Adds cocoapods for libraries.

Adds OCMockito and OCHamcrest libs.
This commit is contained in:
2020-09-05 22:06:51 -07:00
parent f688898d96
commit bab5a55c3b
364 changed files with 17147 additions and 1 deletions

View File

@@ -0,0 +1,35 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
#import "MKTTestLocation.h"
@class MKTInvocationMatcher;
@class MKTOngoingStubbing;
@protocol HCMatcher;
@protocol MKTVerificationMode;
NS_ASSUME_NONNULL_BEGIN
@interface MKTMockingProgress : NSObject
@property (nonatomic, assign, readonly) MKTTestLocation testLocation;
+ (instancetype)sharedProgress;
- (void)reset;
- (void)stubbingStartedAtLocation:(MKTTestLocation)location;
- (void)reportOngoingStubbing:(MKTOngoingStubbing *)ongoingStubbing;
- (MKTOngoingStubbing *)pullOngoingStubbing;
- (void)verificationStarted:(id <MKTVerificationMode>)mode atLocation:(MKTTestLocation)location;
- (id <MKTVerificationMode>)pullVerificationMode;
- (void)setMatcher:(id <HCMatcher>)matcher forArgument:(NSUInteger)index;
- (MKTInvocationMatcher *)pullInvocationMatcher;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,87 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTMockingProgress.h"
#import "MKTInvocationMatcher.h"
#import "MKTOngoingStubbing.h"
#import "MKTVerificationMode.h"
@interface MKTMockingProgress ()
@property (nonatomic, assign, readwrite) MKTTestLocation testLocation;
@property (nonatomic, strong) MKTInvocationMatcher *invocationMatcher;
@property (nonatomic, strong) id <MKTVerificationMode> verificationMode;
@property (nonatomic, strong) MKTOngoingStubbing *ongoingStubbing;
@end
@implementation MKTMockingProgress
+ (instancetype)sharedProgress
{
static id sharedProgress = nil;
if (!sharedProgress)
sharedProgress = [[self alloc] init];
return sharedProgress;
}
- (void)reset
{
self.invocationMatcher = nil;
self.verificationMode = nil;
self.ongoingStubbing = nil;
}
- (void)stubbingStartedAtLocation:(MKTTestLocation)location
{
[self setTestLocation:location];
}
- (void)reportOngoingStubbing:(MKTOngoingStubbing *)ongoingStubbing
{
self.ongoingStubbing = ongoingStubbing;
}
- (MKTOngoingStubbing *)pullOngoingStubbing
{
MKTOngoingStubbing *result = self.ongoingStubbing;
self.ongoingStubbing = nil;
return result;
}
- (void)verificationStarted:(id <MKTVerificationMode>)mode atLocation:(MKTTestLocation)location
{
self.verificationMode = mode;
[self setTestLocation:location];
}
- (id <MKTVerificationMode>)pullVerificationMode
{
id <MKTVerificationMode> result = self.verificationMode;
self.verificationMode = nil;
return result;
}
- (void)setMatcher:(id <HCMatcher>)matcher forArgument:(NSUInteger)index
{
if (!self.invocationMatcher)
self.invocationMatcher = [[MKTInvocationMatcher alloc] init];
[self.invocationMatcher setMatcher:matcher atIndex:index];
}
- (MKTInvocationMatcher *)pullInvocationMatcher
{
MKTInvocationMatcher *result = self.invocationMatcher;
self.invocationMatcher = nil;
return result;
}
- (void)setOngoingStubbing:(MKTOngoingStubbing *)ongoingStubbing
{
@synchronized (self)
{
_ongoingStubbing = ongoingStubbing;
}
}
@end

View File

@@ -0,0 +1,27 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
#import "MKTTestLocation.h"
@class MKTObjectMock;
@class MKTOngoingStubbing;
@protocol MKTVerificationMode;
NS_ASSUME_NONNULL_BEGIN
@interface MKTMockitoCore : NSObject
+ (instancetype)sharedCore;
- (MKTOngoingStubbing *)stubAtLocation:(MKTTestLocation)location;
- (id)verifyMock:(MKTObjectMock *)mock
withMode:(id <MKTVerificationMode>)mode
atLocation:(MKTTestLocation)location;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,51 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTMockitoCore.h"
#import "MKTMockingProgress.h"
#import "MKTVerificationMode.h"
@interface MKTMockitoCore ()
@property (nonatomic, strong, readonly) MKTMockingProgress *mockingProgress;
@end
@implementation MKTMockitoCore
+ (instancetype)sharedCore
{
static id sharedCore = nil;
if (!sharedCore)
sharedCore = [[self alloc] init];
return sharedCore;
}
- (instancetype)init
{
self = [super init];
if (self)
_mockingProgress = [MKTMockingProgress sharedProgress];
return self;
}
- (MKTOngoingStubbing *)stubAtLocation:(MKTTestLocation)location
{
[self.mockingProgress stubbingStartedAtLocation:location];
return [self stub];
}
- (MKTOngoingStubbing *)stub
{
return [self.mockingProgress pullOngoingStubbing];
}
- (id)verifyMock:(MKTObjectMock *)mock
withMode:(id <MKTVerificationMode>)mode
atLocation:(MKTTestLocation)location
{
[self.mockingProgress verificationStarted:mode atLocation:location];
return mock;
}
@end

View File

@@ -0,0 +1,44 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
@protocol HCMatcher;
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Ability to specify OCHamcrest matchers for non-object arguments.
*/
@protocol MKTNonObjectArgumentMatching
/*!
* @abstract Specifies OCHamcrest matcher for a specific argument of a method.
* @discussion For methods arguments that take objects, just pass the matcher directly as a method
* call. But for arguments that take non-objects, pass in a dummy value to satisfy the compiler, but
* call this to override it with the given matcher. Upon verification, the actual argument received
* will be converted to an object before being checked by the matcher.
*
* The argument index is 0-based, so the first argument of a method has index 0.
*
* Examples:
* <pre>[[given([mockFetchedResultsController performFetch:NULL]) withMatcher:anything()] willReturn:\@YES];</pre>
* This stubs <code>performFetch:</code> to return <code>YES</code> for any NSError ** argument.
*
* <pre>[[verify(mockArray) withMatcher:greaterThan(@5]) forArgument:0] removeObjectAtIndex:0];</pre>
* This verifies that <code>removeObjectAtIndex:</code> was called with an index greater than 5.
*/
- (id)withMatcher:(id <HCMatcher>)matcher forArgument:(NSUInteger)index;
/*!
* @abstract Specifies OCHamcrest matcher for the first argument of a method.
* @discussion Equivalent to <code>withMatcher:matcher forArgument:0</code>.
*
* Example:
* <pre>[[verify(mockArray) withMatcher:greaterThan(\@5)] removeObjectAtIndex:0];</pre>
* This verifies that <code>removeObjectAtIndex:</code> was called with an index greater than 5.
*/
- (id)withMatcher:(id <HCMatcher>)matcher;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,29 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef struct
{
__unsafe_unretained id testCase;
const char *fileName;
int lineNumber;
} MKTTestLocation;
static inline MKTTestLocation MKTTestLocationMake(id test, const char *file, int line)
{
MKTTestLocation location;
location.testCase = test;
location.fileName = file;
location.lineNumber = line;
return location;
}
void MKTFailTest(id testCase, const char *fileName, int lineNumber, NSString *description);
void MKTFailTestLocation(MKTTestLocation testLocation, NSString *description);
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,23 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTTestLocation.h"
#import <OCHamcrest/HCTestFailure.h>
#import <OCHamcrest/HCTestFailureReporter.h>
#import <OCHamcrest/HCTestFailureReporterChain.h>
void MKTFailTest(id testCase, const char *fileName, int lineNumber, NSString *description)
{
HCTestFailure *failure = [[HCTestFailure alloc] initWithTestCase:testCase
fileName:[NSString stringWithUTF8String:fileName]
lineNumber:(NSUInteger)lineNumber
reason:description];
HCTestFailureReporter *failureReporter = [HCTestFailureReporterChain reporterChain];
[failureReporter handleFailure:failure];
}
void MKTFailTestLocation(MKTTestLocation testLocation, NSString *description)
{
MKTFailTest(testLocation.testCase, testLocation.fileName, testLocation.lineNumber, description);
}

View File

@@ -0,0 +1,402 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT double OCMockitoVersionNumber;
FOUNDATION_EXPORT const unsigned char OCMockitoVersionString[];
#import <OCMockito/MKTOngoingStubbing.h>
#import <OCMockito/NSInvocation+OCMockito.h>
// Explicitly import transitive headers for complete "umbrella header"
#import <OCMockito/MKTBaseMockObject.h>
#import <OCMockito/MKTClassObjectMock.h>
#import <OCMockito/MKTObjectAndProtocolMock.h>
#import <OCMockito/MKTObjectMock.h>
#import <OCMockito/MKTProtocolMock.h>
@protocol MKTVerificationMode;
NS_ASSUME_NONNULL_BEGIN
FOUNDATION_EXPORT id MKTMock(Class classToMock);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates mock object of given class.
* @param classToMock The class for which to mock instance methods.
* @discussion The mock object will handle all instance methods of <code>classToMock</code>. Methods
* return 0 by default.<br />
* Use <code>given</code> to stub different return values or behaviors.<br />
* Use <code>givenVoid</code> to stub behaviors of void methods.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTMock instead.
*/
static inline id mock(Class classToMock)
{
return MKTMock(classToMock);
}
#endif
FOUNDATION_EXPORT id MKTMockClass(Class classToMock);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates mock class object of given class.
* @param classToMock The class for which to mock class methods.
* @discussion The mock object will handle all class methods of <code>classToMock</code>. Methods
* return 0 by default.<br />
* Use <code>given</code> to stub different return values or behaviors.<br />
* Use <code>givenVoid</code> to stub behaviors of void methods.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTMockClass instead.
*/
static inline id mockClass(Class classToMock)
{
return MKTMockClass(classToMock);
}
#endif
FOUNDATION_EXPORT id MKTMockProtocol(Protocol *protocolToMock);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates mock object of given protocol.
* @param protocolToMock The protocol to mock.
* @discussion The mock object will handle all methods of <code>protocolToMock</code>. Methods
* return 0 by default.<br />
* Use <code>given</code> to stub different return values or behaviors.<br />
* Use <code>givenVoid</code> to stub behaviors of void methods.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTMockProtocol instead.
*/
static inline id mockProtocol(Protocol *protocolToMock)
{
return MKTMockProtocol(protocolToMock);
}
#endif
FOUNDATION_EXPORT id MKTMockProtocolWithoutOptionals(Protocol *protocolToMock);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates mock object of given protocol, but without optional methods.
* @param protocolToMock The protocol to mock.
* @discussion The mock object will handle only required methods of <code>protocolToMock</code>. It
* will <b>not</b> respond to the protocol's optional methods. Methods return 0 by default.<br />
* Use <code>given</code> to stub different return values or behaviors.<br />
* Use <code>givenVoid</code> to stub behaviors of void methods.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTMockProtocolWithoutOptionals instead.
*/
static inline id mockProtocolWithoutOptionals(Protocol *protocolToMock)
{
return MKTMockProtocolWithoutOptionals(protocolToMock);
}
#endif
FOUNDATION_EXPORT id MKTMockObjectAndProtocol(Class classToMock, Protocol *protocolToMock);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates mock object of given class that also implements given protocol.
* @param classToMock The class to mock.
* @param protocolToMock The protocol to mock.
* @discussion The mock object will handle all instance methods of <code>classToMock</code>, along
* with all methods of <code>protocolToMock</code>. Methods return 0 by default.<br />
* Use <code>given</code> to stub different return values or behaviors.<br />
* Use <code>givenVoid</code> to stub behaviors of void methods.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTMockObjectAndProtocol instead.
*/
static inline id mockObjectAndProtocol(Class classToMock, Protocol *protocolToMock)
{
return MKTMockObjectAndProtocol(classToMock, protocolToMock);
}
#endif
FOUNDATION_EXPORT MKTOngoingStubbing *MKTGivenWithLocation(id testCase, const char *fileName, int lineNumber, ...);
#define MKTGiven(methodCall) MKTGivenWithLocation(self, __FILE__, __LINE__, methodCall)
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Stubs a method call.
* @discussion Creates an MKTOngoingStubbing used for any matching method calls. Call
* MKTOngoingStubbing methods to define the stub's return value or behavior.
*
* Method arguments are matched with specified OCHamcrest matchers. Any argument that is not a
* matcher is implicitly wrapped in <code>equalTo</code> to match for equality.
*
* Example:
* <pre>[given([mockObject transform:\@"FOO"]) willReturn:\@"BAR"];</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTGiven instead.
*/
#define given(methodCall) MKTGiven(methodCall)
#endif
FOUNDATION_EXPORT MKTOngoingStubbing *MKTGivenVoidWithLocation(id testCase, const char *fileName, int lineNumber, void(^methodCallWrapper)(void));
#define MKTGivenVoid(methodCall) MKTGivenVoidWithLocation(self, __FILE__, __LINE__, ^{ methodCall; })
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Stubs a call to a <code>void</code> method.
* @discussion Creates an MKTOngoingStubbing used for any matching method calls. Call
* MKTOngoingStubbing methods to define the stub's behavior.
*
* Method arguments are matched with specified OCHamcrest matchers. Any argument that is not a
* matcher is implicitly wrapped in <code>equalTo</code> to match for equality.
*
* Example:
* <pre>[givenVoid([mockObject methodReturningVoid]) willDo:^id(NSInvocation *invocation) { magic(); return nil; }];</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTGiven instead.
*/
#define givenVoid(methodCall) MKTGivenVoid(methodCall)
#endif
#define MKTStubProperty(mock, propertyName, stubbedValue) \
do { \
[MKTGiven([mock propertyName]) willReturn:stubbedValue]; \
[MKTGiven([mock valueForKey:@#propertyName]) willReturn:stubbedValue]; \
[MKTGiven([mock valueForKeyPath:@#propertyName]) willReturn:stubbedValue]; \
} while(0)
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Stubs a property and its related KVO methods to return a given value.
* @discussion
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTStubProperty instead.
*/
#define stubProperty(mock, propertyName, stubbedValue) MKTStubProperty(mock, propertyName, stubbedValue)
#endif
FOUNDATION_EXPORT void MKTStubSingletonWithLocation(id mockClass, SEL aSelector, id testCase, const char *fileName, int lineNumber);
#define MKTStubSingleton(mockClass, methodName) MKTStubSingletonWithLocation(mockClass, @selector(methodName), self, __FILE__, __LINE__)
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Stubs a singleton to the mock class object.
* @discussion
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTStubSingleton instead.
*/
#define stubSingleton(mockClass, methodName) MKTStubSingleton(mockClass, methodName)
#endif
FOUNDATION_EXPORT _Nullable id MKTVerifyWithLocation(id mock, id testCase, const char *fileName, int lineNumber);
#define MKTVerify(mock) MKTVerifyWithLocation(mock, self, __FILE__, __LINE__)
#ifndef MKT_DISABLE_SHORT_SYNTAX
#undef verify
/*!
* @abstract Verifies certain behavior happened once.
* @discussion Equivalent to <code>verifyCount(mock, times(1))</code>.
*
* Method arguments are matched with specified OCHamcrest matchers. Any argument that is
* not a matcher is implicitly wrapped in <code>equalTo</code> to match for equality.
*
* Examples:
* <pre>[verify(mockObject) someMethod:startsWith(\@"foo")];</pre>
* <pre>[verify(mockObject) someMethod:\@"bar"];</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTVerify instead.
*/
#define verify(mock) MKTVerify(mock)
#endif
FOUNDATION_EXPORT id MKTVerifyCountWithLocation(id mock, id <MKTVerificationMode> mode, id testCase, const char *fileName, int lineNumber);
#define MKTVerifyCount(mock, mode) MKTVerifyCountWithLocation(mock, mode, self, __FILE__, __LINE__)
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Verifies certain behavior happened a given number of times.
* @discussion Method arguments are matched with specified OCHamcrest matchers. Any argument that is
* not a matcher is implicitly wrapped in <code>equalTo</code> to match for equality.
* Examples:
* <pre>[verifyCount(mockObject, times(5)) someMethod:\@"was called five times"];</pre>
* <pre>[verifyCount(mockObject, never()) someMethod:\@"was never called"];</pre>
* verifyCount checks that a method was invoked the given number of times, with arguments that
* match given OCHamcrest matchers. If an argument is not a matcher, it is implicitly wrapped in an
* <code>equalTo</code> matcher to check for equality.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTVerifyCount instead.
*/
#define verifyCount(mock, mode) MKTVerifyCount(mock, mode)
#endif
FOUNDATION_EXPORT id <MKTVerificationMode> MKTTimes(NSUInteger wantedNumberOfInvocations);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates <code>verifyCount</code> mode verifying an exact number of invocations.
* @discussion Example:
* <pre>[verifyCount(mockObject, times(2)) someMethod:\@"some arg"];</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTTimes instead.
*/
static inline id <MKTVerificationMode> times(NSUInteger wantedNumberOfInvocations)
{
return MKTTimes(wantedNumberOfInvocations);
}
#endif
FOUNDATION_EXPORT id <MKTVerificationMode> MKTNever(void);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates <code>verifyCount</code> mode verifying that an interaction did not happen.
* @discussion Example:
* <pre>[verifyCount(mockObject, never()) someMethod:\@"some arg"];</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTNever instead.
*/
static inline id <MKTVerificationMode> never(void)
{
return MKTNever();
}
#endif
FOUNDATION_EXPORT id <MKTVerificationMode> MKTAtLeast(NSUInteger minNumberOfInvocations);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates <code>verifyCount</code> mode verifying that an interaction happened at least
* the given number of times.
* @discussion
* Example:
* <pre>[verifyCount(mockObject, atLeast(2)) someMethod:\@"some arg"];</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTAtLeast instead.
*/
static inline id <MKTVerificationMode> atLeast(NSUInteger minNumberOfInvocations)
{
return MKTAtLeast(minNumberOfInvocations);
}
#endif
FOUNDATION_EXPORT id <MKTVerificationMode> MKTAtLeastOnce(void);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates <code>verifyCount</code> mode verifying that an interaction happened at least
* once.
* @discussion Same as <code>atLeast(1)</code>.
*
* Example:
* <pre>[verifyCount(mockObject, atLeastOnce()) someMethod:\@"some arg"];</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTAtLeastOnce instead.
*/
static inline id <MKTVerificationMode> atLeastOnce(void)
{
return MKTAtLeastOnce();
}
#endif
FOUNDATION_EXPORT id <MKTVerificationMode> MKTAtMost(NSUInteger maxNumberOfInvocations);
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates <code>verifyCount</code> mode verifying that an interaction happened at most
* the given number of times.
* @discussion
* Example:
* <pre>[verifyCount(mockObject, atMost(2)) someMethod:\@"some arg"];</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTAtLeast instead.
*/
static inline id <MKTVerificationMode> atMost(NSUInteger maxNumberOfInvocations)
{
return MKTAtMost(maxNumberOfInvocations);
}
#endif
FOUNDATION_EXPORT void MKTDisableMockingWithLocation(id mock, id testCase, const char *fileName, int lineNumber);
#define MKTDisableMocking(mock) MKTDisableMockingWithLocation(mock, self, __FILE__, __LINE__)
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Disables mocking, preventing any more invocations from being handled.
* @discussion There are cases where calling stopMocking() on a mock can release code under test
* that was being retained. If that code under test's dealloc method then references another mock
* that has not yet been stopped, it will create a strong reference to an object that is in the
* process of being deallocated, resulting in an over-release at a later date. A solution to this is
* to call disableMocking() on all mocks before calling stopMocking(). This allows a test to call
* stopMocking on all of its mocks without having to worry about which order to call them.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTDisableMocking instead.
*/
#define disableMocking(mock) MKTDisableMocking(mock)
#endif
FOUNDATION_EXPORT void MKTStopMockingWithLocation(id mock, id testCase, const char *fileName, int lineNumber);
#define MKTStopMocking(mock) MKTStopMockingWithLocation(mock, self, __FILE__, __LINE__)
#ifndef MKT_DISABLE_SHORT_SYNTAX
/*!
* @abstract Stops mocking and releases arguments.
* @discussion Mock objects normally retain all message arguments. This is not a problem for most
* tests, but can sometimes cause retain cycles. In such cases, call stopMocking to tell the mock
* to release its arguments, and to stop accepting messages. See StopMockingTests.m for an example.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define MKT_DISABLE_SHORT_SYNTAX</code> and use the synonym
* MKTStopMocking instead.
*/
#define stopMocking(mock) MKTStopMocking(mock)
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,148 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "OCMockito.h"
#import "MKTAtLeastTimes.h"
#import "MKTAtMostTimes.h"
#import "MKTExactTimes.h"
#import "MKTMockitoCore.h"
static NSString *actualTypeName(id mock)
{
NSString *className = NSStringFromClass([mock class]);
if (!className)
return @"nil";
return [@"type " stringByAppendingString:className];
}
static BOOL reportedInvalidMock(id mock, id testCase, const char *fileName, int lineNumber, NSString *functionName)
{
if ([MKTBaseMockObject isMockObject:mock])
return NO;
NSString *description = [NSString stringWithFormat:
@"Argument passed to %@ should be a mock, but was %@",
functionName, actualTypeName(mock)];
MKTFailTest(testCase, fileName, lineNumber, description);
return YES;
}
static BOOL reportedInvalidClassMock(id classMock, id testCase, const char *fileName, int lineNumber, NSString *functionName)
{
NSString *className = NSStringFromClass([classMock class]);
if ([className isEqualToString:@"MKTClassObjectMock"])
return NO;
NSString *description = [NSString stringWithFormat:
@"Argument passed to %@ should be a class mock, but was %@",
functionName, actualTypeName(classMock)];
MKTFailTest(testCase, fileName, lineNumber, description);
return YES;
}
static BOOL reportedInvalidClassMethod(MKTClassObjectMock *theMock, SEL aSelector, id testCase, const char *fileName, int lineNumber, NSString *functionName)
{
if ([theMock respondsToSelector:aSelector])
return NO;
NSString *description = [NSString stringWithFormat:
@"Method name passed to %@ should be a class method of %@, but was %@",
functionName, theMock.mockedClass, NSStringFromSelector(aSelector)];
MKTFailTest(testCase, fileName, lineNumber, description);
return YES;
}
id MKTMock(Class classToMock)
{
return [[MKTObjectMock alloc] initWithClass:classToMock];
}
id MKTMockClass(Class classToMock)
{
return [[MKTClassObjectMock alloc] initWithClass:classToMock];
}
id MKTMockProtocol(Protocol *protocolToMock)
{
return [[MKTProtocolMock alloc] initWithProtocol:protocolToMock includeOptionalMethods:YES];
}
id MKTMockProtocolWithoutOptionals(Protocol *protocolToMock)
{
return [[MKTProtocolMock alloc] initWithProtocol:protocolToMock includeOptionalMethods:NO];
}
id MKTMockObjectAndProtocol(Class classToMock, Protocol *protocolToMock)
{
return [[MKTObjectAndProtocolMock alloc] initWithClass:classToMock protocol:protocolToMock];
}
MKTOngoingStubbing *MKTGivenWithLocation(id testCase, const char *fileName, int lineNumber, ...)
{
return [[MKTMockitoCore sharedCore] stubAtLocation:MKTTestLocationMake(testCase, fileName, lineNumber)];
}
MKTOngoingStubbing *MKTGivenVoidWithLocation(id testCase, const char *fileName, int lineNumber, void(^methodCallWrapper)(void))
{
methodCallWrapper();
return [[MKTMockitoCore sharedCore] stubAtLocation:MKTTestLocationMake(testCase, fileName, lineNumber)];
}
void MKTStubSingletonWithLocation(id mockClass, SEL aSelector, id testCase, const char *fileName, int lineNumber)
{
if (reportedInvalidClassMock(mockClass, testCase, fileName, lineNumber, @"stubSingleton()"))
return;
MKTClassObjectMock *theMock = (MKTClassObjectMock *)mockClass;
if (reportedInvalidClassMethod(theMock, aSelector, testCase, fileName, lineNumber, @"stubSingleton()"))
return;
[theMock swizzleSingletonAtSelector:aSelector];
}
_Nullable id MKTVerifyWithLocation(id mock, id testCase, const char *fileName, int lineNumber)
{
if (reportedInvalidMock(mock, testCase, fileName, lineNumber, @"verify()"))
return nil;
return MKTVerifyCountWithLocation(mock, MKTTimes(1), testCase, fileName, lineNumber);
}
id MKTVerifyCountWithLocation(id mock, id mode, id testCase, const char *fileName, int lineNumber)
{
if (reportedInvalidMock(mock, testCase, fileName, lineNumber, @"verifyCount()"))
return nil;
return [[MKTMockitoCore sharedCore] verifyMock:mock
withMode:mode
atLocation:MKTTestLocationMake(testCase, fileName, lineNumber)];
}
id <MKTVerificationMode> MKTTimes(NSUInteger wantedNumberOfInvocations)
{
return [[MKTExactTimes alloc] initWithCount:wantedNumberOfInvocations];
}
id <MKTVerificationMode> MKTNever()
{
return MKTTimes(0);
}
id <MKTVerificationMode> MKTAtLeast(NSUInteger minNumberOfInvocations)
{
return [[MKTAtLeastTimes alloc] initWithMinimumCount:minNumberOfInvocations];
}
id <MKTVerificationMode> MKTAtLeastOnce()
{
return MKTAtLeast(1);
}
id <MKTVerificationMode> MKTAtMost(NSUInteger maxNumberOfInvocations)
{
return [[MKTAtMostTimes alloc] initWithMaximumCount:maxNumberOfInvocations];
}
void MKTStopMockingWithLocation(id mock, id testCase, const char *fileName, int lineNumber)
{
if (reportedInvalidMock(mock, testCase, fileName, lineNumber, @"stopMocking()"))
return;
[mock stopMocking];
}

View File

@@ -0,0 +1,29 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Chain-of-responsibility for converting NSInvocation argument to object.
*/
@interface MKTArgumentGetter : NSObject
/*!
* @abstract Initializes a newly allocated argument getter.
* @param handlerType Argument type managed by this getter. Assign with \@encode compiler directive.
* @param successor Successor in chain to handle argument type.
*/
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
/*!
* @abstract Retrieve designated argument of specified type from NSInvocation, or pass to successor.
*/
- (nullable id)retrieveArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,42 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
@interface MKTArgumentGetter (SubclassResponsibility)
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation;
@end
@interface MKTArgumentGetter ()
@property (nonatomic, assign, readonly) char const *handlerType;
@property (nullable, nonatomic, strong, readonly) MKTArgumentGetter *successor;
@end
@implementation MKTArgumentGetter
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor
{
self = [super init];
if (self)
{
_handlerType = handlerType;
_successor = successor;
}
return self;
}
- (BOOL)handlesArgumentType:(char const *)argType
{
return argType[0] == self.handlerType[0];
}
- (nullable id)retrieveArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
if ([self handlesArgumentType:type])
return [self getArgumentAtIndex:idx ofType:type onInvocation:invocation];
return [self.successor retrieveArgumentAtIndex:idx ofType:type onInvocation:invocation];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
@class MKTArgumentGetter;
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Returns chain of argument getters.
*/
FOUNDATION_EXPORT MKTArgumentGetter *MKTArgumentGetterChain(void);
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,52 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetterChain.h"
#import "MKTObjectArgumentGetter.h"
#import "MKTSelectorArgumentGetter.h"
#import "MKTClassArgumentGetter.h"
#import "MKTCharArgumentGetter.h"
#import "MKTBoolArgumentGetter.h"
#import "MKTIntArgumentGetter.h"
#import "MKTShortArgumentGetter.h"
#import "MKTLongArgumentGetter.h"
#import "MKTLongLongArgumentGetter.h"
#import "MKTUnsignedCharArgumentGetter.h"
#import "MKTUnsignedIntArgumentGetter.h"
#import "MKTUnsignedShortArgumentGetter.h"
#import "MKTUnsignedLongArgumentGetter.h"
#import "MKTUnsignedLongLongArgumentGetter.h"
#import "MKTFloatArgumentGetter.h"
#import "MKTDoubleArgumentGetter.h"
#import "MKTPointerArgumentGetter.h"
#import "MKTStructArgumentGetter.h"
MKTArgumentGetter *MKTArgumentGetterChain(void)
{
static MKTArgumentGetter *chain = nil;
if (!chain)
{
MKTArgumentGetter *structGetter = [[MKTStructArgumentGetter alloc] initWithSuccessor:nil];
MKTArgumentGetter *pointerGetter = [[MKTPointerArgumentGetter alloc] initWithSuccessor:structGetter];
MKTArgumentGetter *doubleGetter = [[MKTDoubleArgumentGetter alloc] initWithSuccessor:pointerGetter];
MKTArgumentGetter *floatGetter = [[MKTFloatArgumentGetter alloc] initWithSuccessor:doubleGetter];
MKTArgumentGetter *uLongLongGetter = [[MKTUnsignedLongLongArgumentGetter alloc] initWithSuccessor:floatGetter];
MKTArgumentGetter *uLongGetter = [[MKTUnsignedLongArgumentGetter alloc] initWithSuccessor:uLongLongGetter];
MKTArgumentGetter *uShortGetter = [[MKTUnsignedShortArgumentGetter alloc] initWithSuccessor:uLongGetter];
MKTArgumentGetter *uIntGetter = [[MKTUnsignedIntArgumentGetter alloc] initWithSuccessor:uShortGetter];
MKTArgumentGetter *uCharGetter = [[MKTUnsignedCharArgumentGetter alloc] initWithSuccessor:uIntGetter];
MKTArgumentGetter *longLongGetter = [[MKTLongLongArgumentGetter alloc] initWithSuccessor:uCharGetter];
MKTArgumentGetter *longGetter = [[MKTLongArgumentGetter alloc] initWithSuccessor:longLongGetter];
MKTArgumentGetter *shortGetter = [[MKTShortArgumentGetter alloc] initWithSuccessor:longGetter];
MKTArgumentGetter *intGetter = [[MKTIntArgumentGetter alloc] initWithSuccessor:shortGetter];
MKTArgumentGetter *boolGetter = [[MKTBoolArgumentGetter alloc] initWithSuccessor:intGetter];
MKTArgumentGetter *charGetter = [[MKTCharArgumentGetter alloc] initWithSuccessor:boolGetter];
MKTArgumentGetter *classGetter = [[MKTClassArgumentGetter alloc] initWithSuccessor:charGetter];
MKTArgumentGetter *selectorGetter = [[MKTSelectorArgumentGetter alloc] initWithSuccessor:classGetter];
MKTArgumentGetter *objectGetter = [[MKTObjectArgumentGetter alloc] initWithSuccessor:selectorGetter];
chain = objectGetter;
}
return chain;
}

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTBoolArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTBoolArgumentGetter.h"
@implementation MKTBoolArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(BOOL) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
BOOL arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTCharArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTCharArgumentGetter.h"
@implementation MKTCharArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(char) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
char arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTClassArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTClassArgumentGetter.h"
@implementation MKTClassArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(Class) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
__unsafe_unretained Class arg = nil;
[invocation getArgument:&arg atIndex:idx];
return arg;
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTDoubleArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTDoubleArgumentGetter.h"
@implementation MKTDoubleArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(double) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
double arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTFloatArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTFloatArgumentGetter.h"
@implementation MKTFloatArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(float) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
float arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTIntArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTIntArgumentGetter.h"
@implementation MKTIntArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(int) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
int arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTLongArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTLongArgumentGetter.h"
@implementation MKTLongArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(long) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
long arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,15 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTLongLongArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTLongLongArgumentGetter.h"
@implementation MKTLongLongArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(long long) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
long long arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTObjectArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTObjectArgumentGetter.h"
@implementation MKTObjectArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(id) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
__unsafe_unretained id arg = nil;
[invocation getArgument:&arg atIndex:idx];
return arg ? arg : [NSNull null];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTPointerArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,22 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTPointerArgumentGetter.h"
@implementation MKTPointerArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(void *) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
void *arg;
[invocation getArgument:&arg atIndex:idx];
return [NSValue valueWithPointer:arg];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTSelectorArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTSelectorArgumentGetter.h"
@implementation MKTSelectorArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(SEL) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
SEL arg = nil;
[invocation getArgument:&arg atIndex:idx];
return arg ? NSStringFromSelector(arg) : [NSNull null];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTShortArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTShortArgumentGetter.h"
@implementation MKTShortArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(short) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
short arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTStructArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,28 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTStructArgumentGetter.h"
typedef struct {} MKTDummyStructure;
@implementation MKTStructArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(MKTDummyStructure) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
NSUInteger structSize = 0;
NSGetSizeAndAlignment(type, &structSize, NULL);
void *structMem = calloc(1, structSize);
[invocation getArgument:structMem atIndex:idx];
id arg = [NSData dataWithBytes:structMem length:structSize];
free(structMem);
return arg;
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedCharArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedCharArgumentGetter.h"
@implementation MKTUnsignedCharArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(unsigned char) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
unsigned char arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedIntArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedIntArgumentGetter.h"
@implementation MKTUnsignedIntArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(unsigned int) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
unsigned int arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedLongArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedLongArgumentGetter.h"
@implementation MKTUnsignedLongArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(unsigned long) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
unsigned long arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedLongLongArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedLongLongArgumentGetter.h"
@implementation MKTUnsignedLongLongArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(unsigned long long) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
unsigned long long arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTArgumentGetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedShortArgumentGetter : MKTArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTArgumentGetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedShortArgumentGetter.h"
@implementation MKTUnsignedShortArgumentGetter
- (instancetype)initWithSuccessor:(nullable MKTArgumentGetter *)successor
{
self = [super initWithType:@encode(unsigned short) successor:successor];
return self;
}
- (id)getArgumentAtIndex:(NSInteger)idx ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
unsigned short arg;
[invocation getArgument:&arg atIndex:idx];
return @(arg);
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTBoolReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTBoolReturnSetter.h"
@implementation MKTBoolReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(BOOL) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
BOOL value = [returnValue boolValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTCharReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTCharReturnSetter.h"
@implementation MKTCharReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(char) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
char value = [returnValue charValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTClassReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTClassReturnSetter.h"
@implementation MKTClassReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(Class) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
__unsafe_unretained Class value = returnValue;
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTDoubleReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTDoubleReturnSetter.h"
@implementation MKTDoubleReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(double) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
double value = [returnValue doubleValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTFloatReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTFloatReturnSetter.h"
@implementation MKTFloatReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(float) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
float value = [returnValue floatValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTIntReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTIntReturnSetter.h"
@implementation MKTIntReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(int) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
int value = [returnValue intValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTLongLongReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTLongLongReturnSetter.h"
@implementation MKTLongLongReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(long long) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
long long value = [returnValue longLongValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTLongReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTLongReturnSetter.h"
@implementation MKTLongReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(long) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
long value = [returnValue longValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTObjectReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTObjectReturnSetter.h"
@implementation MKTObjectReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(id) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
__unsafe_unretained id value = returnValue;
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,30 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Chain-of-responsibility for converting objects to NSInvocation return values.
*/
@interface MKTReturnValueSetter : NSObject
/*!
* @abstract Initializes a newly allocated return value setter.
* @param handlerType Return type managed by this setter. Assign with \@encode compiler directive.
* @param successor Successor in chain to handle return type.
*/
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
;
/*!
* @abstract Set NSInvocation return value of specified type, or pass to successor.
*/
- (void)setReturnValue:(nullable id)returnValue ofType:(char const *)type onInvocation:(NSInvocation *)invocation;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,43 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
@interface MKTReturnValueSetter (SubclassResponsibility)
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation;
@end
@interface MKTReturnValueSetter ()
@property (nonatomic, assign, readonly) char const *handlerType;
@property (nullable, nonatomic, strong, readonly) MKTReturnValueSetter *successor;
@end
@implementation MKTReturnValueSetter
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor
{
self = [super init];
if (self)
{
_handlerType = handlerType;
_successor = successor;
}
return self;
}
- (BOOL)handlesReturnType:(char const *)returnType
{
return returnType[0] == self.handlerType[0];
}
- (void)setReturnValue:(nullable id)returnValue ofType:(char const *)type onInvocation:(NSInvocation *)invocation
{
if ([self handlesReturnType:type])
[self setReturnValue:returnValue onInvocation:invocation];
else
[self.successor setReturnValue:returnValue ofType:type onInvocation:invocation];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
@class MKTReturnValueSetter;
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Returns chain of return value handlers.
*/
FOUNDATION_EXPORT MKTReturnValueSetter *MKTReturnValueSetterChain(void);
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,48 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetterChain.h"
#import "MKTObjectReturnSetter.h"
#import "MKTClassReturnSetter.h"
#import "MKTCharReturnSetter.h"
#import "MKTBoolReturnSetter.h"
#import "MKTLongLongReturnSetter.h"
#import "MKTIntReturnSetter.h"
#import "MKTShortReturnSetter.h"
#import "MKTLongReturnSetter.h"
#import "MKTUnsignedCharReturnSetter.h"
#import "MKTUnsignedIntReturnSetter.h"
#import "MKTUnsignedShortReturnSetter.h"
#import "MKTUnsignedLongReturnSetter.h"
#import "MKTUnsignedLongLongReturnSetter.h"
#import "MKTFloatReturnSetter.h"
#import "MKTDoubleReturnSetter.h"
#import "MKTStructReturnSetter.h"
MKTReturnValueSetter *MKTReturnValueSetterChain(void)
{
static MKTReturnValueSetter *chain = nil;
if (!chain)
{
MKTReturnValueSetter *structSetter = [[MKTStructReturnSetter alloc] initWithSuccessor:nil];
MKTReturnValueSetter *doubleSetter = [[MKTDoubleReturnSetter alloc] initWithSuccessor:structSetter];
MKTReturnValueSetter *floatSetter = [[MKTFloatReturnSetter alloc] initWithSuccessor:doubleSetter];
MKTReturnValueSetter *uLongLongSetter = [[MKTUnsignedLongLongReturnSetter alloc] initWithSuccessor:floatSetter];
MKTReturnValueSetter *uLongSetter = [[MKTUnsignedLongReturnSetter alloc] initWithSuccessor:uLongLongSetter];
MKTReturnValueSetter *uShortSetter = [[MKTUnsignedShortReturnSetter alloc] initWithSuccessor:uLongSetter];
MKTReturnValueSetter *uIntSetter = [[MKTUnsignedIntReturnSetter alloc] initWithSuccessor:uShortSetter];
MKTReturnValueSetter *uCharSetter = [[MKTUnsignedCharReturnSetter alloc] initWithSuccessor:uIntSetter];
MKTReturnValueSetter *longLongSetter = [[MKTLongLongReturnSetter alloc] initWithSuccessor:uCharSetter];
MKTReturnValueSetter *longSetter = [[MKTLongReturnSetter alloc] initWithSuccessor:longLongSetter];
MKTReturnValueSetter *shortSetter = [[MKTShortReturnSetter alloc] initWithSuccessor:longSetter];
MKTReturnValueSetter *intSetter = [[MKTIntReturnSetter alloc] initWithSuccessor:shortSetter];
MKTReturnValueSetter *boolSetter = [[MKTBoolReturnSetter alloc] initWithSuccessor:intSetter];
MKTReturnValueSetter *charSetter = [[MKTCharReturnSetter alloc] initWithSuccessor:boolSetter];
MKTReturnValueSetter *classSetter = [[MKTClassReturnSetter alloc] initWithSuccessor:charSetter];
MKTReturnValueSetter *objectSetter = [[MKTObjectReturnSetter alloc] initWithSuccessor:classSetter];
chain = objectSetter;
}
return chain;
}

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTShortReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTShortReturnSetter.h"
@implementation MKTShortReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(short) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
short value = [returnValue shortValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,17 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTStructReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,23 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTStructReturnSetter.h"
@implementation MKTStructReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:"{" successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
NSMethodSignature *methodSignature = [invocation methodSignature];
NSMutableData *value = [NSMutableData dataWithLength:[methodSignature methodReturnLength]];
[returnValue getValue:[value mutableBytes]];
[invocation setReturnValue:[value mutableBytes]];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedCharReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedCharReturnSetter.h"
@implementation MKTUnsignedCharReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(unsigned char) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
unsigned char value = [returnValue unsignedCharValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedIntReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedIntReturnSetter.h"
@implementation MKTUnsignedIntReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(unsigned int) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
unsigned int value = [returnValue unsignedIntValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,17 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedLongLongReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedLongLongReturnSetter.h"
@implementation MKTUnsignedLongLongReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(unsigned long long) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
unsigned long long value = [returnValue unsignedLongLongValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedLongReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedLongReturnSetter.h"
@implementation MKTUnsignedLongReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(unsigned long) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
unsigned long value = [returnValue unsignedLongValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTReturnValueSetter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MKTUnsignedShortReturnSetter : MKTReturnValueSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithType:(char const *)handlerType successor:(nullable MKTReturnValueSetter *)successor NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,21 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTUnsignedShortReturnSetter.h"
@implementation MKTUnsignedShortReturnSetter
- (instancetype)initWithSuccessor:(nullable MKTReturnValueSetter *)successor
{
self = [super initWithType:@encode(unsigned short) successor:successor];
return self;
}
- (void)setReturnValue:(id)returnValue onInvocation:(NSInvocation *)invocation
{
unsigned short value = [returnValue unsignedShortValue];
[invocation setReturnValue:&value];
}
@end

View File

@@ -0,0 +1,19 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MKTCallStackElement : NSObject
@property (nonatomic, copy, readonly) NSString *moduleName;
@property (nonatomic, copy, readonly) NSString *instruction;
- (instancetype)initWithSymbols:(NSString *)element NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,53 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTCallStackElement.h"
static NSRange trimTrailingSpacesFromRange(NSString *string, NSRange range)
{
while ([string characterAtIndex:range.location + range.length - 1] == ' ')
range.length -= 1;
return range;
}
static NSString *extractModuleName(NSString *element)
{
NSRange range = trimTrailingSpacesFromRange(element, NSMakeRange(4, 33));
return [element substringWithRange:range];
}
static BOOL isAddress32Bit(NSString *element)
{
return [element characterAtIndex:50] == ' ';
}
static NSString *extractInstruction(NSString *element)
{
NSUInteger loc = 59;
if (isAddress32Bit(element))
loc -= 8;
NSRange range = NSMakeRange(loc, element.length - loc);
return [element substringWithRange:range];
}
@implementation MKTCallStackElement
- (instancetype)initWithSymbols:(NSString *)element
{
self = [super init];
if (self)
{
_moduleName = extractModuleName(element);
_instruction = extractInstruction(element);
}
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"%@ %@", self.moduleName, self.instruction];
}
@end

View File

@@ -0,0 +1,13 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
@class MKTCallStackElement;
NS_ASSUME_NONNULL_BEGIN
NSArray<MKTCallStackElement *> *MKTFilterCallStack(NSArray<MKTCallStackElement *> *callStackSymbols);
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,34 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTFilterCallStack.h"
#import "MKTCallStackElement.h"
static NSUInteger MKTFirstRelevantCallStackIndex(NSArray<MKTCallStackElement *> *parsedStack)
{
NSUInteger firstIndex = [parsedStack indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
MKTCallStackElement *element = obj;
return [element.instruction hasPrefix:@"-[MKTBaseMockObject forwardInvocation:]"];
}];
return firstIndex + 3;
}
static NSUInteger MKTLastRelevantCallStackIndex(NSArray<MKTCallStackElement *> *parsedStack,
NSUInteger startBackFrom,
NSString *moduleName)
{
NSUInteger lastIndex = startBackFrom;
while (lastIndex > 0 && ![[(parsedStack[lastIndex]) moduleName] isEqualToString:moduleName])
lastIndex -= 1;
return [[(parsedStack[lastIndex]) moduleName] isEqualToString:moduleName] ? lastIndex : startBackFrom;
}
NSArray<MKTCallStackElement *> *MKTFilterCallStack(NSArray<MKTCallStackElement *> *parsedStack)
{
NSUInteger firstIndex = MKTFirstRelevantCallStackIndex(parsedStack);
NSUInteger lastIndex = MKTLastRelevantCallStackIndex(parsedStack, parsedStack.count - 1, @"XCTest");
lastIndex = MKTLastRelevantCallStackIndex(parsedStack, lastIndex, [parsedStack[firstIndex] moduleName]);
return [parsedStack subarrayWithRange:NSMakeRange(firstIndex, lastIndex - firstIndex + 1)];
}

View File

@@ -0,0 +1,23 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
@class MKTLocation;
NS_ASSUME_NONNULL_BEGIN
@interface MKTInvocation : NSObject
@property (nonatomic, strong, readonly) NSInvocation *invocation;
@property (nonatomic, strong, readonly) MKTLocation *location;
@property (nonatomic, assign) BOOL verified;
- (instancetype)initWithInvocation:(NSInvocation *)invocation;
- (instancetype)initWithInvocation:(NSInvocation *)invocation location:(MKTLocation *)location NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,27 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTInvocation.h"
#import "MKTLocation.h"
@implementation MKTInvocation
- (instancetype)initWithInvocation:(NSInvocation *)invocation
{
return [self initWithInvocation:invocation
location:[[MKTLocation alloc] init]];
}
- (instancetype)initWithInvocation:(NSInvocation *)invocation location:(MKTLocation *)location
{
self = [super init];
if (self) {
_invocation = invocation;
_location = location;
}
return self;
}
@end

View File

@@ -0,0 +1,27 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
@protocol HCMatcher;
NS_ASSUME_NONNULL_BEGIN
@interface MKTInvocationMatcher : NSObject
@property (nonatomic, strong, readonly) NSInvocation *expected;
@property (nonatomic, assign, readonly) NSUInteger numberOfArguments;
@property (nonatomic, copy, readonly) NSArray<id <HCMatcher>> *matchers;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (void)setMatcher:(id <HCMatcher>)matcher atIndex:(NSUInteger)index;
- (void)setExpectedInvocation:(NSInvocation *)expectedInvocation;
- (BOOL)matches:(NSInvocation *)actual;
- (void)stopArgumentCapture;
- (void)enumerateMismatchesOf:(NSInvocation *)actual
usingBlock:(void (^)(NSUInteger idx, NSString *description))block;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,149 @@
// 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

View File

@@ -0,0 +1,16 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MKTLocation : NSObject
- (instancetype)init;
- (instancetype)initWithCallStack:(NSArray<NSString *> *)callStack NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,36 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTLocation.h"
#import "MKTFilterCallStack.h"
#import "MKTParseCallStack.h"
@interface MKTLocation ()
@property (nonatomic, strong, readonly) NSArray<NSString *> *callStack; // strong not copy, for speed
@end
@implementation MKTLocation
- (instancetype)init
{
self = [self initWithCallStack:[NSThread callStackSymbols]];
return self;
}
- (instancetype)initWithCallStack:(NSArray<NSString *> *)callStack
{
self = [super init];
if (self)
_callStack = callStack;
return self;
}
- (NSString *)description
{
NSArray<MKTCallStackElement *> *stack = MKTFilterCallStack(MKTParseCallStack(self.callStack));
return [stack componentsJoinedByString:@"\n"];
}
@end

View File

@@ -0,0 +1,24 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
@class MKTInvocation;
@class MKTInvocationMatcher;
@class MKTLocation;
NS_ASSUME_NONNULL_BEGIN
@interface MKTMatchingInvocationsFinder : NSObject
@property (nonatomic, assign, readonly) NSUInteger count;
- (void)findInvocationsInList:(NSArray<MKTInvocation *> *)invocations matching:(MKTInvocationMatcher *)wanted;
- (MKTLocation *)locationOfInvocationAtIndex:(NSUInteger)index;
- (MKTLocation *)locationOfLastInvocation;
- (void)markInvocationsAsVerified;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,50 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTMatchingInvocationsFinder.h"
#import "MKTInvocation.h"
#import "MKTInvocationMatcher.h"
@interface MKTMatchingInvocationsFinder ()
@property (nonatomic, copy) NSArray<MKTInvocation *> *invocations;
@end
@implementation MKTMatchingInvocationsFinder
@dynamic count;
- (void)findInvocationsInList:(NSArray<MKTInvocation *> *)invocations matching:(MKTInvocationMatcher *)wanted
{
self.invocations = [invocations filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(id obj, NSDictionary *bindings) {
MKTInvocation *invocation = obj;
return !invocation.verified && [wanted matches:invocation.invocation];
}]];
}
- (NSUInteger)count
{
return self.invocations.count;
}
- (MKTLocation *)locationOfInvocationAtIndex:(NSUInteger)index
{
MKTInvocation *invocation = self.invocations[index];
return invocation.location;
}
- (MKTLocation *)locationOfLastInvocation
{
MKTInvocation *invocation = self.invocations.lastObject;
return invocation.location;
}
- (void)markInvocationsAsVerified
{
for (MKTInvocation *invocation in self.invocations)
invocation.verified = YES;
}
@end

View File

@@ -0,0 +1,13 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
@class MKTCallStackElement;
NS_ASSUME_NONNULL_BEGIN
NSArray<MKTCallStackElement *> *MKTParseCallStack(NSArray<NSString *> *callStackSymbols);
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,18 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import "MKTParseCallStack.h"
#import "MKTCallStackElement.h"
NSArray<MKTCallStackElement *> *MKTParseCallStack(NSArray<NSString *> *callStackSymbols)
{
NSMutableArray<MKTCallStackElement *> *result = [[NSMutableArray alloc] init];
for (NSString *rawElement in callStackSymbols)
{
MKTCallStackElement *element = [[MKTCallStackElement alloc] initWithSymbols:rawElement];
[result addObject:element];
}
return result;
}

View File

@@ -0,0 +1,24 @@
// OCMockito by Jon Reid, https://qualitycoding.org/
// Copyright 2020 Quality Coding, Inc. See LICENSE.txt
#import <Foundation/Foundation.h>
@class MKTInvocation;
@class MKTInvocationMatcher;
NS_ASSUME_NONNULL_BEGIN
@interface MKTPrinter : NSObject
- (NSString *)printMatcher:(MKTInvocationMatcher *)matcher;
- (NSString *)printInvocation:(MKTInvocation *)invocation;
- (NSString *)printMismatchOf:(MKTInvocation *)invocation
expectation:(MKTInvocationMatcher *)expectation;
@end
FOUNDATION_EXPORT NSString *MKTOrdinal(NSUInteger index);
NS_ASSUME_NONNULL_END

Some files were not shown because too many files have changed in this diff Show More