123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- //
- // Licensed under the terms in License.txt
- //
- // Copyright 2010 Allen Ding. All rights reserved.
- //
- #import "KWReceiveMatcher.h"
- #import "KWFormatter.h"
- #import "KWInvocationCapturer.h"
- #import "KWMessagePattern.h"
- #import "KWMessageTracker.h"
- #import "KWObjCUtilities.h"
- #import "KWStringUtilities.h"
- #import "KWWorkarounds.h"
- #import "NSObject+KiwiStubAdditions.h"
- static NSString * const MatchVerifierKey = @"MatchVerifierKey";
- static NSString * const CountTypeKey = @"CountTypeKey";
- static NSString * const CountKey = @"CountKey";
- static NSString * const StubValueKey = @"StubValueKey";
- @interface KWReceiveMatcher()
- #pragma mark - Properties
- @property (nonatomic, readwrite, strong) KWMessageTracker *messageTracker;
- @end
- @implementation KWReceiveMatcher
- #pragma mark - Initializing
- - (id)initWithSubject:(id)anObject {
- self = [super initWithSubject:anObject];
- if (self) {
- _willEvaluateMultipleTimes = NO;
- }
-
- return self;
- }
- #pragma mark - Getting Matcher Strings
- + (NSArray *)matcherStrings {
- return @[@"receive:",
- @"receive:withCount:",
- @"receive:withCountAtLeast:",
- @"receive:withCountAtMost:",
- @"receive:andReturn:",
- @"receive:andReturn:withCount:",
- @"receive:andReturn:withCountAtLeast:",
- @"receive:andReturn:withCountAtMost:",
- @"receiveMessagePattern:countType:count:",
- @"receiveMessagePattern:andReturn:countType:count:",
- @"receiveUnspecifiedCountOfMessagePattern:",
- @"receiveUnspecifiedCountOfMessagePattern:andReturn:"];
- }
- #pragma mark - Matching
- - (BOOL)shouldBeEvaluatedAtEndOfExample {
- return YES;
- }
- - (BOOL)evaluate {
- BOOL succeeded = [self.messageTracker succeeded];
- if (!self.willEvaluateMultipleTimes) {
- [self.messageTracker stopTracking];
- }
- return succeeded;
- }
- #pragma mark - Getting Failure Messages
- - (NSString *)failureMessageForShould {
- return [NSString stringWithFormat:@"expected subject to receive -%@ %@, but received it %@",
- [self.messageTracker.messagePattern stringValue],
- [self.messageTracker expectedCountPhrase],
- [self.messageTracker receivedCountPhrase]];
- }
- - (NSString *)failureMessageForShouldNot {
- return [NSString stringWithFormat:@"expected subject not to receive -%@, but received it %@",
- [self.messageTracker.messagePattern stringValue],
- [self.messageTracker receivedCountPhrase]];
- }
- #pragma mark - Configuring Matchers
- - (void)receive:(SEL)aSelector {
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector];
- [self receiveUnspecifiedCountOfMessagePattern:messagePattern];
- }
- - (void)receive:(SEL)aSelector withCount:(NSUInteger)aCount {
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector];
- return [self receiveMessagePattern:messagePattern countType:KWCountTypeExact count:aCount];
- }
- - (void)receive:(SEL)aSelector withCountAtLeast:(NSUInteger)aCount {
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector];
- return [self receiveMessagePattern:messagePattern countType:KWCountTypeAtLeast count:aCount];
- }
- - (void)receive:(SEL)aSelector withCountAtMost:(NSUInteger)aCount {
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector];
- return [self receiveMessagePattern:messagePattern countType:KWCountTypeAtMost count:aCount];
- }
- - (void)receive:(SEL)aSelector andReturn:(id)aValue {
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector];
- [self receiveUnspecifiedCountOfMessagePattern:messagePattern andReturn:aValue];
- }
- - (void)receive:(SEL)aSelector andReturn:(id)aValue withCount:(NSUInteger)aCount {
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector];
- [self receiveMessagePattern:messagePattern andReturn:aValue countType:KWCountTypeExact count:aCount];
- }
- - (void)receive:(SEL)aSelector andReturn:(id)aValue withCountAtLeast:(NSUInteger)aCount {
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector];
- [self receiveMessagePattern:messagePattern andReturn:aValue countType:KWCountTypeAtLeast count:aCount];
- }
- - (void)receive:(SEL)aSelector andReturn:(id)aValue withCountAtMost:(NSUInteger)aCount {
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector];
- [self receiveMessagePattern:messagePattern andReturn:aValue countType:KWCountTypeAtMost count:aCount];
- }
- - (void)receiveUnspecifiedCountOfMessagePattern:(KWMessagePattern *)messagePattern {
- if (self.willEvaluateAgainstNegativeExpectation) {
- [self receiveMessagePattern:messagePattern countType:KWCountTypeAtLeast count:1];
- } else {
- [self receiveMessagePattern:messagePattern countType:KWCountTypeExact count:1];
- }
- }
- - (void)receiveUnspecifiedCountOfMessagePattern:(KWMessagePattern *)messagePattern andReturn:(id)aValue {
- if (self.willEvaluateAgainstNegativeExpectation) {
- [self receiveMessagePattern:messagePattern andReturn:aValue countType:KWCountTypeAtLeast count:1];
- } else {
- [self receiveMessagePattern:messagePattern andReturn:aValue countType:KWCountTypeExact count:1];
- }
- }
- - (void)receiveMessagePattern:(KWMessagePattern *)aMessagePattern countType:(KWCountType)aCountType count:(NSUInteger)aCount {
- #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG
- @try {
- #endif // #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG
- [self.subject stubMessagePattern:aMessagePattern andReturn:nil overrideExisting:NO];
- self.messageTracker = [KWMessageTracker messageTrackerWithSubject:self.subject messagePattern:aMessagePattern countType:aCountType count:aCount];
- #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG
- } @catch(NSException *exception) {
- KWSetExceptionFromAcrossInvocationBoundary(exception);
- }
- #endif // #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG
- }
- - (void)receiveMessagePattern:(KWMessagePattern *)aMessagePattern andReturn:(id)aValue countType:(KWCountType)aCountType count:(NSUInteger)aCount {
- #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG
- @try {
- #endif // #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG
- [self.subject stubMessagePattern:aMessagePattern andReturn:aValue];
- self.messageTracker = [KWMessageTracker messageTrackerWithSubject:self.subject messagePattern:aMessagePattern countType:aCountType count:aCount];
- #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG
- } @catch(NSException *exception) {
- KWSetExceptionFromAcrossInvocationBoundary(exception);
- }
- #endif // #if KW_TARGET_HAS_INVOCATION_EXCEPTION_BUG
- }
- #pragma mark - Capturing Invocations
- + (NSMethodSignature *)invocationCapturer:(KWInvocationCapturer *)anInvocationCapturer methodSignatureForSelector:(SEL)aSelector {
- KWMatchVerifier *verifier = (anInvocationCapturer.userInfo)[MatchVerifierKey];
- if ([verifier.subject respondsToSelector:aSelector])
- return [verifier.subject methodSignatureForSelector:aSelector];
- NSString *encoding = KWEncodingForDefaultMethod();
- return [NSMethodSignature signatureWithObjCTypes:[encoding UTF8String]];
- }
- + (void)invocationCapturer:(KWInvocationCapturer *)anInvocationCapturer didCaptureInvocation:(NSInvocation *)anInvocation {
- NSDictionary *userInfo = anInvocationCapturer.userInfo;
- id verifier = userInfo[MatchVerifierKey];
- KWCountType countType = [userInfo[CountTypeKey] unsignedIntegerValue];
- NSUInteger count = [userInfo[CountKey] unsignedIntegerValue];
- id stubValue = userInfo[StubValueKey];
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternFromInvocation:anInvocation];
- if (stubValue != nil)
- [verifier receiveMessagePattern:messagePattern andReturn:stubValue countType:countType count:count];
- else
- [verifier receiveMessagePattern:messagePattern countType:countType count:count];
- }
- @end
- @implementation KWMatchVerifier(KWReceiveMatcherAdditions)
- #pragma mark - Verifying
- - (void)receive:(SEL)aSelector withArguments:(id)firstArgument, ... {
- va_list argumentList;
- va_start(argumentList, firstArgument);
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector firstArgumentFilter:firstArgument argumentList:argumentList];
- [(id)self receiveUnspecifiedCountOfMessagePattern:messagePattern];
- }
- - (void)receive:(SEL)aSelector withCount:(NSUInteger)aCount arguments:(id)firstArgument, ... {
- va_list argumentList;
- va_start(argumentList, firstArgument);
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector firstArgumentFilter:firstArgument argumentList:argumentList];
- [(id)self receiveMessagePattern:messagePattern countType:KWCountTypeExact count:aCount];
- }
- - (void)receive:(SEL)aSelector withCountAtLeast:(NSUInteger)aCount arguments:(id)firstArgument, ... {
- va_list argumentList;
- va_start(argumentList, firstArgument);
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector firstArgumentFilter:firstArgument argumentList:argumentList];
- [(id)self receiveMessagePattern:messagePattern countType:KWCountTypeAtLeast count:aCount];
- }
- - (void)receive:(SEL)aSelector withCountAtMost:(NSUInteger)aCount arguments:(id)firstArgument, ... {
- va_list argumentList;
- va_start(argumentList, firstArgument);
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector firstArgumentFilter:firstArgument argumentList:argumentList];
- [(id)self receiveMessagePattern:messagePattern countType:KWCountTypeAtMost count:aCount];
- }
- - (void)receive:(SEL)aSelector andReturn:(id)aValue withArguments:(id)firstArgument, ... {
- va_list argumentList;
- va_start(argumentList, firstArgument);
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector firstArgumentFilter:firstArgument argumentList:argumentList];
- [(id)self receiveUnspecifiedCountOfMessagePattern:messagePattern andReturn:aValue];
- }
- - (void)receive:(SEL)aSelector andReturn:(id)aValue withCount:(NSUInteger)aCount arguments:(id)firstArgument, ... {
- va_list argumentList;
- va_start(argumentList, firstArgument);
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector firstArgumentFilter:firstArgument argumentList:argumentList];
- [(id)self receiveMessagePattern:messagePattern andReturn:aValue countType:KWCountTypeExact count:aCount];
- }
- - (void)receive:(SEL)aSelector andReturn:(id)aValue withCountAtLeast:(NSUInteger)aCount arguments:(id)firstArgument, ... {
- va_list argumentList;
- va_start(argumentList, firstArgument);
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector firstArgumentFilter:firstArgument argumentList:argumentList];
- [(id)self receiveMessagePattern:messagePattern andReturn:aValue countType:KWCountTypeAtLeast count:aCount];
- }
- - (void)receive:(SEL)aSelector andReturn:(id)aValue withCountAtMost:(NSUInteger)aCount arguments:(id)firstArgument, ... {
- va_list argumentList;
- va_start(argumentList, firstArgument);
- KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:aSelector firstArgumentFilter:firstArgument argumentList:argumentList];
- [(id)self receiveMessagePattern:messagePattern andReturn:aValue countType:KWCountTypeAtMost count:aCount];
- }
- #pragma mark Invocation Capturing Methods
- - (NSDictionary *)userInfoForReceiveMatcherWithCountType:(KWCountType)aCountType count:(NSUInteger)aCount {
- return @{
- MatchVerifierKey: self,
- CountTypeKey: @(aCountType),
- CountKey: @(aCount)
- };
- }
- - (NSDictionary *)userInfoForReceiveMatcherWithCountType:(KWCountType)aCountType count:(NSUInteger)aCount value:(id)aValue {
- return @{
- MatchVerifierKey: self,
- CountTypeKey: @(aCountType),
- CountKey: @(aCount),
- StubValueKey: aValue
- };
- }
- - (id)receive {
- NSDictionary *userInfo = [self userInfoForReceiveMatcherWithCountType:KWCountTypeExact count:1];
- return [KWInvocationCapturer invocationCapturerWithDelegate:[KWReceiveMatcher class] userInfo:userInfo];
- }
- - (id)receiveWithCount:(NSUInteger)aCount {
- NSDictionary *userInfo = [self userInfoForReceiveMatcherWithCountType:KWCountTypeExact count:aCount];
- return [KWInvocationCapturer invocationCapturerWithDelegate:[KWReceiveMatcher class] userInfo:userInfo];
- }
- - (id)receiveWithCountAtLeast:(NSUInteger)aCount {
- NSDictionary *userInfo = [self userInfoForReceiveMatcherWithCountType:KWCountTypeAtLeast count:aCount];
- return [KWInvocationCapturer invocationCapturerWithDelegate:[KWReceiveMatcher class] userInfo:userInfo];
- }
- - (id)receiveWithCountAtMost:(NSUInteger)aCount {
- NSDictionary *userInfo = [self userInfoForReceiveMatcherWithCountType:KWCountTypeAtMost count:aCount];
- return [KWInvocationCapturer invocationCapturerWithDelegate:[KWReceiveMatcher class] userInfo:userInfo];
- }
- - (id)receiveAndReturn:(id)aValue {
- NSDictionary *userInfo = [self userInfoForReceiveMatcherWithCountType:KWCountTypeExact count:1 value:aValue];
- return [KWInvocationCapturer invocationCapturerWithDelegate:[KWReceiveMatcher class] userInfo:userInfo];
- }
- - (id)receiveAndReturn:(id)aValue withCount:(NSUInteger)aCount {
- NSDictionary *userInfo = [self userInfoForReceiveMatcherWithCountType:KWCountTypeExact count:aCount value:aValue];
- return [KWInvocationCapturer invocationCapturerWithDelegate:[KWReceiveMatcher class] userInfo:userInfo];
- }
- - (id)receiveAndReturn:(id)aValue withCountAtLeast:(NSUInteger)aCount {
- NSDictionary *userInfo = [self userInfoForReceiveMatcherWithCountType:KWCountTypeAtLeast count:aCount value:aValue];
- return [KWInvocationCapturer invocationCapturerWithDelegate:[KWReceiveMatcher class] userInfo:userInfo];
- }
- - (id)receiveAndReturn:(id)aValue withCountAtMost:(NSUInteger)aCount {
- NSDictionary *userInfo = [self userInfoForReceiveMatcherWithCountType:KWCountTypeAtMost count:aCount value:aValue];
- return [KWInvocationCapturer invocationCapturerWithDelegate:[KWReceiveMatcher class] userInfo:userInfo];
- }
- @end
|