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

35
Pods/OCMockito/LICENSE.txt generated Normal file
View File

@@ -0,0 +1,35 @@
OCMockito by Jon Reid, https://qualitycoding.org/
Copyright 2020 Quality Coding, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(MIT License)
-----
TPDWeakProxy:
The MIT License (MIT)
Copyright © 2013 Tetherpad
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

415
Pods/OCMockito/README.md generated Normal file
View File

@@ -0,0 +1,415 @@
![mockito](https://raw.githubusercontent.com/mockito/mockito.github.io/master/img/logo.png)
[![Build Status](https://travis-ci.org/jonreid/OCMockito.svg?branch=master)](https://travis-ci.org/jonreid/OCMockito)
[![Coverage Status](https://coveralls.io/repos/jonreid/OCMockito/badge.svg?branch=master)](https://coveralls.io/r/jonreid/OCMockito?branch=master)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Cocoapods Version](https://cocoapod-badges.herokuapp.com/v/OCMockito/badge.png)](http://cocoapods.org/pods/OCMockito)
[![Twitter Follow](https://img.shields.io/twitter/follow/qcoding.svg?style=social)](https://twitter.com/qcoding)
OCMockito is an Objective-C implementation of Mockito, supporting creation,
verification and stubbing of mock objects.
Key differences from other mocking frameworks:
* Mock objects are always "nice," recording their calls instead of throwing
exceptions about unspecified invocations. This makes tests less fragile.
* No expect-run-verify, making tests more readable. Mock objects record their
calls, then you verify the methods you want.
* Verification failures are reported as unit test failures, identifying specific
lines instead of throwing exceptions. This makes it easier to identify
failures.
Let's verify some behavior!
---------------------------
```obj-c
// mock creation
NSMutableArray *mockArray = mock([NSMutableArray class]);
// using mock object
[mockArray addObject:@"one"];
[mockArray removeAllObjects];
// verification
[verify(mockArray) addObject:@"one"];
[verify(mockArray) removeAllObjects];
```
Once created, the mock will remember all interactions. Then you can selectively
verify whatever interactions you are interested in.
(If Xcode complains about multiple methods with the same name, cast `verify`
to the mocked class.)
How about some stubbing?
------------------------
```obj-c
// mock creation
NSArray *mockArray = mock([NSArray class]);
// stubbing
[given([mockArray objectAtIndex:0]) willReturn:@"first"];
[given([mockArray objectAtIndex:1]) willThrow:[NSException exceptionWithName:@"name"
reason:@"reason"
userInfo:nil]];
// following prints "first"
NSLog(@"%@", [mockArray objectAtIndex:0]);
// follows throws exception
NSLog(@"%@", [mockArray objectAtIndex:1]);
// following prints "(null)" because objectAtIndex:999 was not stubbed
NSLog(@"%@", [mockArray objectAtIndex:999]);
```
How do you mock a class object?
-------------------------------
```obj-c
__strong Class mockStringClass = mockClass([NSString class]);
```
(In the iOS 64-bit runtime, Class objects aren't strong by default. Either make
it explicitly strong as shown above, or use `id` instead.)
How do you mock a protocol?
---------------------------
```obj-c
id <MyDelegate> delegate = mockProtocol(@protocol(MyDelegate));
```
Or, if you don't want it to contain any optional methods:
```obj-c
id <MyDelegate> delegate = mockProtocolWithoutOptionals(@protocol(MyDelegate));
```
How do you mock an object that also implements a protocol?
----------------------------------------------------------
```obj-c
UIViewController <CustomProtocol> *controller =
mockObjectAndProtocol([UIViewController class], @protocol(CustomProtocol));
```
How do you stub methods that return primitives?
-----------------------------------------------
To stub methods that return primitive scalars, box the scalars into NSValues:
```obj-c
[given([mockArray count]) willReturn:@3];
```
How do you stub methods that return structs?
--------------------------------------------
Use `willReturnStruct:objCType:` passing a pointer to your structure and its
type from the Objective-C `@encode()` compiler directive:
```obj-c
SomeStruct aStruct = {...};
[given([mockObject methodReturningStruct]) willReturnStruct:&aStruct
objCType:@encode(SomeStruct)];
```
How do you stub a property so that KVO works?
---------------------------------------------
Use `stubProperty(mock, property, stubbedValue)`. For example, say you have a
mock object named `mockEmployee`. It has a property `firstName`. You want to
stub it to return the value "FIRST-NAME":
```obj-c
stubProperty(mockEmployee, firstName, @"FIRST-NAME");
```
This stubs the `firstName` property, `valueForKey:` and `valueForKeyPath:`.
Argument matchers
-----------------
OCMockito verifies argument values by testing for equality. But when extra
flexibility is required, you can specify
[OCHamcrest](https://github.com/hamcrest/OCHamcrest) matchers.
```obj-c
// mock creation
NSMutableArray *mockArray = mock([NSMutableArray class]);
// using mock object
[mockArray removeObject:@"This is a test"];
// verification
[verify(mockArray) removeObject:startsWith(@"This is")];
```
OCHamcrest matchers can be specified as arguments for both verification and
stubbing.
Typed arguments will issue a warning that the matcher is the wrong type. Just
cast the matcher to `id`.
How do you specify matchers for non-object arguments?
-----------------------------------------------------
To stub a method that takes a non-object argument but specify a matcher, invoke
the method with a dummy argument, then call `-withMatcher:forArgument:`
```obj-c
[[given([mockArray objectAtIndex:0]) withMatcher:anything() forArgument:0]
willReturn:@"foo"];
```
This is particularly useful for ignoring `NSError **` parameters: pass in `NULL`, but override it with an `anything()` matcher.
Use the shortcut `-withMatcher:` to specify a matcher for a single argument:
```obj-c
[[given([mockArray objectAtIndex:0]) withMatcher:anything()]
willReturn:@"foo"];
```
These methods are also available to specify matchers for verification. Just call
them after `verify(…)` but before the invocation you want to verify:
```obj-c
[[verify(mockArray) withMatcher:greaterThan(@5])] removeObjectAtIndex:0];
```
Verifying exact number of invocations / at least x / never
----------------------------------------------------------
```obj-c
// using mock
[mockArray addObject:@"once"];
[mockArray addObject:@"twice"];
[mockArray addObject:@"twice"];
// the following two verifications work exactly the same
[verify(mockArray) addObject:@"once"];
[verifyCount(mockArray, times(1)) addObject:@"once"];
// verify exact number of invocations
[verifyCount(mockArray, times(2)) addObject:@"twice"];
[verifyCount(mockArray, times(3)) addObject:@"three times"];
// verify using never(), which is an alias for times(0)
[verifyCount(mockArray, never()) addObject:@"never happened"];
// verify using atLeast()/atMost()
[verifyCount(mockArray, atLeastOnce()) addObject:@"at least once"];
[verifyCount(mockArray, atLeast(2)) addObject:@"at least twice"];
[verifyCount(mockArray, atMost(5)) addObject:@"at most five times"];
```
Capturing arguments for further assertions
------------------------------------------
OCMockito verifies argument values using OCHamcrest matchers; non-matcher
arguments are implicitly wrapped in the `equalTo` matcher to test for equality.
In some situations though, it's helpful to capture an argument so you can send
it another message.
OCHamcrest provides a special matcher for this purpose: HCArgumentCaptor.
Specify it as an argument, then query it with either the `value` or `allValues`
properties.
For example, you may want to send the captured argument a message to query its
state:
```obj-c
HCArgumentCaptor *argument = [[HCArgumentCaptor alloc] init];
[verify(mockObject) doSomething:(id)argument];
assertThat([argument.value nameAtIndex:0], is(@"Jon"));
```
Capturing arguments is especially handy for block arguments. Capture the
argument, cast it to the block type, then invoke the block directly to simulate
the ways it will be called by production code:
```obj-c
HCArgumentCaptor *argument = [[HCArgumentCaptor alloc] init];
[verify(mockArray) sortUsingComparator:(id)argument];
NSComparator block = argument.value;
assertThat(@(block(@"a", @"z")), is(@(NSOrderedAscending)));
```
Stubbing consecutive calls
--------------------------
```obj-c
[[given([mockObject someMethod:@"some arg"])
willThrow:[NSException exceptionWithName:@"name" reason:@"reason" userInfo:nil]]
willReturn:@"foo"];
// First call: throws exception
[mockObject someMethod:@"some arg"];
// Second call: prints "foo"
NSLog(@"%@", [mockObject someMethod:@"some arg"]);
// Any consecutive call: prints "foo" as well. (Last stubbing wins.)
NSLog(@"%@", [mockObject someMethod:@"some arg"]);
```
Stubbing with blocks
--------------------
We recommend using simple stubbing with `willReturn:` or `willThrow:` only. But
`willDo:` using a block can sometimes be helpful. The block can easily access
invocation arguments by calling `mkt_arguments` from NSInvocation+OCMockito.h.
Whatever the block returns will be used as the stubbed return value.
```obj-c
[given([mockObject someMethod:anything()]) willDo:^id (NSInvocation *invocation){
NSArray *args = [invocation mkt_arguments];
return @([args[0] intValue] * 2);
}];
// Following prints 4
NSLog(@"%@", [mockObject someMethod:@2]);
```
You can stub a void method with a block by using `givenVoid` instead of `given`.
Problems with dealloc
---------------------
Use `stopMocking(…)` if a `-dealloc` of your System Under Test is trying to
message an object that is mocked. It disables message handling on the mock and
frees its retained arguments. This prevents retain cycles and crashes during
test clean-up. See StopMockingTests.m for an example.
How do you mock a singleton?
----------------------------
The short answer is: Don't. Instead of your class deciding who it's going to
talk to, inject those dependencies.
The longer answer is: Well. Legacy code. Call `stubSingleton` on a mock class
object, specifying the name of the factory method.
```obj-c
__strong Class mockUserDefaultsClass = mockClass([NSUserDefaults class]);
NSUserDefaults* mockDefaults = mock([NSUserDefaults class]);
stubSingleton(mockUserDefaultsClass, standardUserDefaults);
[given([NSUserDefaults standardUserDefaults]) willReturn:mockDefaults];
```
Beware! This uses swizzling. You need to make sure the mock class object gets
deallocated so that the swizzling is undone.
In the example above, `mockUserDefaultsClass` will go out scope and be
destroyed. But what if you kept it in the test fixture, as an ivar or a
property? According to XCTest's design, it won't be implicitly destroyed.
You need to explicitly set it to nil in `-tearDown`, or the swizzling will
bleed over to your other tests, compromising their integrity.
If you need more control over when the swizzling is undone, call
`stopMocking(…)` on the mock class.
How do I add OCMockito to my project?
-------------------------------------
The Examples folder shows projects using OCMockito either through CocoaPods or
through the prebuilt frameworks, for iOS and macOS development.
### CocoaPods
If you want to add OCMockito using Cocoapods then add the following dependency
to your Podfile. Most people will want OCMockito in their test targets, and not
include any pods from their main targets:
```ruby
target 'MyTests' do
inherit! :search_paths
use_frameworks!
pod 'OCMockito', '~> 5.0'
end
```
Use the following imports:
@import OCHamcrest;
@import OCMockito;
### Carthage
Add the following to your Cartfile:
```
github "jonreid/OCMockito" ~> 5.0
```
Then drag the the built frameworks (both OCHamcrest and OCMockito) from the
appropriate Carthage/Build directory into your project, but with "Copy items
into destination group's folder" disabled.
### Prebuilt Frameworks
Prebuilt binaries are available on GitHub for
[OCMockito](https://github.com/jonreid/OCMockito/releases/). You will also need
[OCHamcrest](https://github.com/hamcrest/OCHamcrest/releases/).
The binaries are packaged as frameworks:
* __OCMockitoIOS.framework__ for iOS development
* __OCMockito.framework__ for macOS development
OCHamcrest comes in a similar scheme. Drag the appropriate frameworks for both
both OCMockito and OCHamcrest into your project, specifying "Copy items into
destination group's folder". Then specify `-ObjC` in your "Other Linker Flags".
#### iOS Development:
Use the following imports:
@import OCHamcrestIOS;
@import OCMockitoIOS;
#### macOS Development:
Add a "Copy Files" build phase to copy OCMockito.framework and
OCHamcrest.framework to your Products Directory.
Use the following imports:
@import OCHamcrest;
@import OCMockito;
### Build Your Own
If you want to build OCMockito yourself, clone the repo, then
```sh
$ Frameworks/gethamcrest
$ cd Source
$ ./MakeDistribution.sh
```

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

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