Files
MonsterCards/iOS/Pods/OCMockito/Source/OCMockito/Invocation/MKTInvocationMatcher.m
Tom Hicks c3031fbc39 Adds cocoapods for libraries.
Adds OCMockito and OCHamcrest libs.
2020-09-05 22:06:51 -07:00

150 lines
4.0 KiB
Objective-C

// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTInvocationMatcher.h"
#import "NSInvocation+OCMockito.h"
#import <OCHamcrest/HCArgumentCaptor.h>
#import <OCHamcrest/HCAssertThat.h>
#import <OCHamcrest/HCIsNil.h>
#import <OCHamcrest/HCWrapInMatcher.h>
@interface MKTUnspecifiedArgumentPlaceholder : NSObject
@end
@implementation MKTUnspecifiedArgumentPlaceholder
+ (instancetype)sharedPlaceholder
{
static MKTUnspecifiedArgumentPlaceholder *instance = nil;
if (!instance)
instance = [[self alloc] init];
return instance;
}
@end
@interface MKTInvocationMatcher ()
@property (nonatomic, strong, readwrite) NSInvocation *expected;
@property (nonatomic, assign, readwrite) NSUInteger numberOfArguments;
@property (nonatomic, strong, readonly) NSMutableArray<id <HCMatcher>> *argumentMatchers;
@end
@implementation MKTInvocationMatcher
@dynamic matchers;
- (instancetype)init
{
self = [super init];
if (self)
_argumentMatchers = [[NSMutableArray alloc] init];
return self;
}
- (NSArray<id <HCMatcher>> *)matchers
{
return self.argumentMatchers;
}
- (void)setMatcher:(id <HCMatcher>)matcher atIndex:(NSUInteger)index
{
if (index < self.argumentMatchers.count)
self.argumentMatchers[index] = matcher;
else
{
[self trueUpArgumentMatchersToCount:index];
[self.argumentMatchers addObject:matcher];
}
}
- (void)trueUpArgumentMatchersToCount:(NSUInteger)desiredCount
{
NSUInteger count = self.argumentMatchers.count;
while (count < desiredCount)
{
[self.argumentMatchers addObject:[self placeholderForUnspecifiedMatcher]];
++count;
}
}
- (void)setExpectedInvocation:(NSInvocation *)expectedInvocation
{
[expectedInvocation mkt_retainArgumentsWithWeakTarget];
self.expected = expectedInvocation;
self.numberOfArguments = [[self.expected methodSignature] numberOfArguments] - 2;
[self trueUpArgumentMatchersToCount:self.numberOfArguments];
[self replacePlaceholdersWithEqualityMatchersForArguments:[self.expected mkt_arguments]];
}
- (void)replacePlaceholdersWithEqualityMatchersForArguments:(NSArray *)expectedArgs
{
for (NSUInteger index = 0; index < self.numberOfArguments; ++index)
{
if (self.argumentMatchers[index] == [self placeholderForUnspecifiedMatcher])
self.argumentMatchers[index] = [self matcherForArgument:expectedArgs[index]];
}
}
- (id)placeholderForUnspecifiedMatcher
{
return [MKTUnspecifiedArgumentPlaceholder sharedPlaceholder];
}
- (id <HCMatcher>)matcherForArgument:(id)arg
{
if (arg == [NSNull null])
return HC_nilValue();
return HCWrapInMatcher(arg);
}
- (BOOL)matches:(NSInvocation *)actual
{
if (self.expected.selector != actual.selector)
return NO;
NSArray *actualArgs = [actual mkt_arguments];
for (NSUInteger index = 0; index < self.numberOfArguments; ++index)
{
if ([self argument:actualArgs[index] doesNotMatch:self.argumentMatchers[index]])
return NO;
}
return YES;
}
- (void)stopArgumentCapture
{
for (id <HCMatcher> matcher in self.argumentMatchers)
if ([matcher isKindOfClass:[HCArgumentCaptor class]])
{
HCArgumentCaptor *captor = (HCArgumentCaptor *)matcher;
captor.captureEnabled = NO;
}
}
- (void)enumerateMismatchesOf:(NSInvocation *)actual
usingBlock:(void (^)(NSUInteger idx, NSString *description))block
{
NSArray *actualArgs = [actual mkt_arguments];
for (NSUInteger index = 0; index < self.numberOfArguments; ++index)
if ([self argument:actualArgs[index] doesNotMatch:self.argumentMatchers[index]])
{
id <HCMatcher> matcher = self.argumentMatchers[index];
id argument = actualArgs[index];
block(index, HCDescribeMismatch(matcher, argument));
}
}
- (BOOL)argument:(id)arg doesNotMatch:(id <HCMatcher>)matcher
{
if (arg == [NSNull null])
arg = nil;
return ![matcher matches:arg];
}
@end