Created
July 27, 2010 14:57
-
-
Save lukeredpath/492336 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| - (BOOL)calledWithCorrectParameters:(NSInvocation *)invocation | |
| { | |
| NSMethodSignature *methodSignature = [invocation methodSignature]; | |
| BOOL parametersAreCorrect = YES; | |
| for (int i = 2; i < [methodSignature numberOfArguments]; i++) { | |
| const char *argType = [methodSignature getArgumentTypeAtIndex:i]; | |
| if (*argType == *@encode(id)) { | |
| id receivedArg; | |
| id expectedArg; | |
| [invocation getArgument:&receivedArg atIndex:i]; | |
| [expectedInvocation getArgument:&expectedArg atIndex:i]; | |
| parametersAreCorrect = [receivedArg isEqual:expectedArg]; | |
| } | |
| else if(*argType == *@encode(int)) | |
| { | |
| int receivedArg; | |
| int expectedArg; | |
| [invocation getArgument:&receivedArg atIndex:i]; | |
| [expectedInvocation getArgument:&expectedArg atIndex:i]; | |
| parametersAreCorrect = (receivedArg == expectedArg); | |
| } | |
| else | |
| { | |
| NSLog(@"Unknown argType %c", *argType); | |
| parametersAreCorrect = NO; | |
| } | |
| } | |
| return parametersAreCorrect; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @implementation LRInvocationComparitor | |
| + (id)comparitorForInvocation:(NSInvocation *)invocation; | |
| { | |
| return [[[self alloc] initWithInvocation:invocation] autorelease]; | |
| } | |
| - (id)initWithInvocation:(NSInvocation *)anInvocation; | |
| { | |
| if (self = [super init]) { | |
| expectedInvocation = [anInvocation retain]; | |
| [expectedInvocation retainArguments]; | |
| } | |
| return self; | |
| } | |
| - (void)dealloc | |
| { | |
| [expectedInvocation release]; | |
| [super dealloc]; | |
| } | |
| - (BOOL)matchesParameters:(NSInvocation *)invocation; | |
| { | |
| NSMethodSignature *methodSignature = [expectedInvocation methodSignature]; | |
| BOOL matchesParameters = YES; | |
| for (int i = 2; i < [methodSignature numberOfArguments]; i++) { | |
| const char *argType = [methodSignature getArgumentTypeAtIndex:i]; | |
| void *receivedArg; | |
| void *expectedArg; | |
| [invocation getArgument:&receivedArg atIndex:i]; | |
| [expectedInvocation getArgument:&expectedArg atIndex:i]; | |
| if (*argType == *@encode(id)) { | |
| matchesParameters = [(id)receivedArg isEqual:(id)expectedArg]; | |
| } | |
| else | |
| { | |
| matchesParameters = (receivedArg == expectedArg); | |
| } | |
| } | |
| return matchesParameters; | |
| } | |
| @end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @implementation LRInvocationComparitorTest | |
| - (void)setUp; | |
| { | |
| testObject = [[InvocationTesterObject alloc] init]; | |
| capture = [[InvocationCapturer alloc] init]; | |
| } | |
| - (void)testCanCompareObjectMethodParameters | |
| { | |
| NSInvocation *expected = [[capture takesAnObject:@"foo"] invocation]; | |
| LRInvocationComparitor *comparitor = [LRInvocationComparitor comparitorForInvocation:expected]; | |
| assertThatBool([comparitor matchesParameters:[[capture takesAnObject:@"foo"] invocation]], | |
| equalToBool(YES)); | |
| assertThatBool([comparitor matchesParameters:[[capture takesAnObject:@"bar"] invocation]], | |
| equalToBool(NO)); | |
| } | |
| - (void)testCanCompareIntegerParameters | |
| { | |
| NSInvocation *expected = [[capture takesAnInt:10] invocation]; | |
| LRInvocationComparitor *comparitor = [LRInvocationComparitor comparitorForInvocation:expected]; | |
| assertThatBool([comparitor matchesParameters:[[capture takesAnInt:10] invocation]], | |
| equalToBool(YES)); | |
| assertThatBool([comparitor matchesParameters:[[capture takesAnInt:20] invocation]], | |
| equalToBool(NO)); | |
| } | |
| - (void)testCanCompareFloatParameters | |
| { | |
| NSInvocation *expected = [[capture takesAFloat:3.14] invocation]; | |
| LRInvocationComparitor *comparitor = [LRInvocationComparitor comparitorForInvocation:expected]; | |
| assertThatBool([comparitor matchesParameters:[[capture takesAFloat:3.14] invocation]], | |
| equalToBool(YES)); | |
| assertThatBool([comparitor matchesParameters:[[capture takesAFloat:10.45] invocation]], | |
| equalToBool(NO)); | |
| } | |
| @end |
Author
Author
Top file shows a potential solution.
Don't you need to reserve some memory for receivedArg and expectedArg?
As described in the discussion example here - http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/Reference/Reference.html#//apple_ref/occ/instm/NSInvocation/getArgument:atIndex:
Although I'm probably missing something...
Author
That doesn't seem to be an issue; it works as is.
Do you know whether it is actually allocating memory somehow? Otherwise, there's a good chance this will stop working at an inconvenient moment ;-)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You should be able to set expectations with parameter constraints that are objects or non-objects. The above code supports object types and integers but isn't going to scale very well; I don't particularly want to do a massive if statement over the different arg types and even if I could refactor it into something polymorphic it still seems like there should be a more generic way of handling this. Any ideas? I'm well aware of the limits in my C and Obj-C runtime knowledge.