Nimble: Crash using Nimble 5.0.0 & OCMock 3.3.1

Created on 14 Dec 2016  Â·  18Comments  Â·  Source: Quick/Nimble

Migrating https://github.com/erikdoe/ocmock/issues/319 here. I couldn't quite figure it out, but it seems like Nimble was failing to print a description of an OCClassMockObject.

bug

All 18 comments

Maybe we should have a special handling for NSProxy?

description of NSObjectProtocol, which will be the counterpart of Swift's CustomStringConvertible is implemented on NSProxy. On the other hand, debugDescription of NSObjectProtocol, which may mean CustomDebugStringConvertible in Swift is an optional property and will not be implemented on NSProxy.

Yeah, we should be careful in trying to call methods on NSProxy unnecessarily.

On Dec 14, 2016, 12:44 AM -0800, Syo Ikeda notifications@github.com, wrote:
>

Maybe we should have a special handling for NSProxy?

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub (https://github.com/Quick/Nimble/issues/377#issuecomment-266976315), or mute the thread (https://github.com/notifications/unsubscribe-auth/AAEMCLCzIsd4PqKdt66NrVFiyeGRethRks5rH6x6gaJpZM4LMiDg).

Hello everyone, this still appears to be open, and unfortunately many of our unit tests are broken on the latest releases of Quick / Nimble. Has there been any further movement on this issue?

As @ikesyo pointed out, this seems like something that could be fixed by modifying Nimble's stringify function to handle NSProxy. I think adding an if let value = value as? NSProxy { ... } statement to handle this case should do the trick.

@joeljfischer, would you be willing to submit a pull request for that case? Since you have a test suite that demonstrates the problem, I think you'd be able to quickly iterate on the solution.

Sure, I'll try to take a look today.

I spent some time on this, and I repeatedly got the error until I turned off optimization on the Nimble project and rebuilt, then everything seems to work correctly. Any ideas on why that might be? Swift's debugging capabilities still kind of suck so it's hard to tell exactly what's going on.

Awesome, thanks for working on this! A few questions that could help me figure out what's going wrong here:

  • You mention an error -- are you referring to the crash this issue is in reference to?
  • Do you mean that, without any modifications, turning off optimizations when building Nimble caused the crash to stop occurring? Or, if you made some modifications, could you post the diff here?
  1. Yes, I was referring to the crash referenced in this issue.
  2. That's correct. With no modifications, by turning off optimizations (so that I could debug more easily) the crash disappeared.

Hmm, that's definitely interesting. My understanding is that program behavior should never change due to optimization level, just the speed at which the program executes. Changes in behavior seem like a bug in the compiler or runtime.

Still, since finding a workaround here is probably the first step to diagnosing any compiler bugs anyway, let's start there. If it were me, I'd switch back to an optimized build and try to find a workaround that prevents the crash from happening. I still think the NSProxy theory is a strong one, so I'd add the if statement I mention a few comments above and see what happens.

I did attempt that first and it did not seem to help, but with the optimized build I wasn't able to step through to actually see what was happening. No breakpoints I set into the stringify function would actually fire, and the error would always fire on the return stringify(unboxed) line, which didn't help since it was likely failing in the unwrapped stringify method.

Yeah, I suppose a debugger won't work because it's optimized. I'd probably switch to print-based debugging at this point (a tool of the pros).

Do you have a small sample project that can reproduce it? I did some native NSProxy implementations that didn't seem to cause any problems. I guess next time I get a chance I'll try with OCMock.

I wasn't able to get a small sample project that will reproduce it, but I pushed a branch of the primary project that has been showing the issue: https://github.com/smartdevicelink/sdl_ios/tree/hotfix/nimble_fix_tests

You'd just have to pull in the libraries with carthage and run the tests.

Using print statements, this is what I'm seeing.

I changed the relevant Nimble code to:

public func stringify<T>(_ value: T) -> String {
    print("Stringify: \(value)")

    if let value = value as? TestOutputStringConvertible {
        print("TestOutputStringConvertible")
        return value.testDescription
    }

    if let value = value as? CustomDebugStringConvertible {
        print("CustomDebugStringConvertible")
        return value.debugDescription
    }

    print("None of those, describing...")
    return String(describing: value)
}

/// -SeeAlso: `stringify<T>(value: T)`
public func stringify<T>(_ value: T?) -> String {
    print("Stringify? \(value)")
    if let unboxed = value {
        return stringify(unboxed)
    }
    return "nil"
}

and this is the output

Stringify? Optional(<SDLConfiguration: 0x7ff562635390>)
Stringify: <SDLConfiguration: 0x7ff562635390>
CustomDebugStringConvertible
Stringify? Optional(<SDLConfiguration: 0x7ff562635390>)
Stringify: <SDLConfiguration: 0x7ff562635390>
CustomDebugStringConvertible
Stringify? Optional(OCProtocolMockObject)
Stringify: OCProtocolMockObject
Could not cast value of type 'OCProtocolMockObject' (0x1164fc108) to 'Swift.CustomDebugStringConvertible' (0x1164390e8).

It's very interesting that it's saying it can't convert to a CustomDebugStringConvertible yet the print statement within that if let isn't firing. That makes me think something weird is going on on the cast in the if let itself.

Interesting, it seems like the Swift compiler chooses to convert the instance to it's corresponding class. It might seem that Swift accidentally interprets the pointer as a class.

I'm starting to break out into a cold sweat with the announcement that Xcode 8.3 will drop Swift 2.3 support. Once that happens, I won't have functioning tests. Any further ideas on a possible fix? I'll take another look soon.

Just wanted to note that now that Xcode 8.3 is out, we've had to disable all of our tests using OCMock. I'm not sure if there's any further thoughts on working around this bug, or if we're going to have to rethink how we do those tests.

Closing this due to inactivity.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ikesyo picture ikesyo  Â·  4Comments

kdawgwilk picture kdawgwilk  Â·  4Comments

iby picture iby  Â·  3Comments

aaroncrespo picture aaroncrespo  Â·  10Comments

ikesyo picture ikesyo  Â·  3Comments