Help debugging error_chain! types


#1

I ran into an odd problem in a test case I had written last night. Basically I am trying to return a consistent error in a Future call, Timeout. I recently fixed an issue where the TCP connection establishment wasn’t properly timing out. After fixing it I tried to write a test, code here: https://github.com/bluejekyll/trust-dns/blob/master/server/tests/client_tests.rs#L218

It looked like this:

let response = client.query(&name, DNSClass::IN, RecordType::A);
assert!(response.is_err());

match response.unwrap_err().kind() {
         &ClientErrorKind::Timeout => (),
         e @ _ => assert!(false, format!("something else: {}", e)),
}

For some reason this fails, and I don’t know why. I expect the match statement to match this as the Timeout variant. The assert!(...) is printing what I expect:

  thread 'test_timeout_query_tcp' panicked at 'something else: ClientError: request timed out', tests/client_tests.rs:230

Which is the associated display string. This only errors on the new TCPConnection timeout code:

The conversion that I expected to happen is proved by the output from the request timed out, which only occurs once in the codebase. If this were Java, I would be thinking there was an odd ClassLoader issue going on, but I don’t think anything is similar here. To be clear, this match does work properly when the query itself times out, i.e. with UDP or the Mock connection I use in tests. It’s only on this early return due to TCP connection timeout failure where there is an issue with this match. This is not a blocking issue, just something that is confusing me greatly at the moment.

The question I have, is how do I go about debugging this issue? Why isn’t the match doing what I expect?

Here is a test that validates the correct conversion:

#[test]
fn test_conversion() {
    let io_error = io::Error::new(io::ErrorKind::TimedOut, format!("mock timeout"));

    let error = Error::from(&io_error);

    match error.kind() {
        &ErrorKind::Timeout => (),
        _ => panic!("incorrect type: {}", error),
    }
}

which succeeds…


Solution:

First question: how to debug this, use {:?} for printing the enum variant. The Debug error_chain! implementation includes the enum name in it’s output.

Second question: why wasn’t this matching. Turns out I implemented a Clone on my error type to make it easier to extract the error from a Future impl. This clone just blindly wrapped the error in a Msg and always returned that. Thus, the type changed, but the message remained the same. :footprints: :gun: