kiwi-bdd / Kiwi

Simple BDD for iOS
BSD 3-Clause "New" or "Revised" License
4.14k stars 512 forks source link

Stub with string argument doesn't work in iOS 10 #684

Open rermolov opened 8 years ago

rermolov commented 8 years ago

Precondition: Using MobileCoreServices.framework target is real object or mock - doesn't matter

What I do:

[target stub:@selector(methodWithStringArg:) andReturn:mock withArguments:@"=string"];
id result = [target methodWithStringArg:@"=string"];

What I expect: result is mock

What I receive: result is nil

Reason: +[KWGenericMatchEvaluator isGenericMatcher:] detects matcher by looking for a method with signature bool matches(id). Method with this signature is added by MobileCoreServices to NSString (bool -[NSString matches:]) via category, so any string detected as matcher now. It seems that it is already undefined behavior for Kiwi. Method matches: in NSString works fine in most cases, and we can't see the bug. But when string starts with = symbol, it fails (actually, the problem is in method matchesString:, that is called inside matches:): Ex:

(lldb) p (BOOL)[@"abra" matchesString:@"abra"]
(BOOL) $7 = YES
(lldb) p (BOOL)[@"=1" matchesString:@"=1"]
(BOOL) $8 = NO

Proposed solution: Best solution - replace the way of determining generic matchers with something more strict and certain. Slightly worse - add NSString with subclasses to blacklist.

modocache commented 8 years ago

Seems like the "best solution" you describe is the way to go here. Let me know if you'd be willing/able to submit a pull request for it!

rermolov commented 8 years ago

Yep, I can create a PR, but it seems that I need an additional information about generic matchers.

I found 2 classes that implements method with signature - (BOOL)matches:(id)item: KWStringContainsMatcher & KWStringPrefixMatcher.

KWStringContainsMatcher implements KWGenericMatching, but all public methods marked as DEPRECATED. KWStringPrefixMatcher doesn't implement KWGenericMatching, but can be used as generic matcher.

Also, why all methods in KiwiGenericMatchingAdditions.h marked as DEPRECATED, but still in use?

Would it be correct if I will add KWGenericMatching into KWStringPrefixMatcher and replace part of + (BOOL)isGenericMatcher:(id)object with

class_conformsToProtocol(theClass, @protocol(KWGenericMatching))

? Thank you!