Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async versions of each of the verify modes. #35

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions Source/OCMockito.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@
638F68DA150FC21A0081DEE6 /* MKTClassObjectMock.m in Sources */ = {isa = PBXBuildFile; fileRef = 638F68D6150FC21A0081DEE6 /* MKTClassObjectMock.m */; };
638F68DD150FC3210081DEE6 /* MKTClassObjectMockTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 638F68DC150FC3210081DEE6 /* MKTClassObjectMockTest.m */; };
638F68DE150FC3210081DEE6 /* MKTClassObjectMockTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 638F68DC150FC3210081DEE6 /* MKTClassObjectMockTest.m */; };
6525714317D14C2300577580 /* MKTExactTimesTest.m in Resources */ = {isa = PBXBuildFile; fileRef = 6525714217D14C2300577580 /* MKTExactTimesTest.m */; };
6525714417D1510100577580 /* MKTExactTimesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6525714217D14C2300577580 /* MKTExactTimesTest.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -223,6 +225,7 @@
638F68D5150FC21A0081DEE6 /* MKTClassObjectMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKTClassObjectMock.h; sourceTree = "<group>"; };
638F68D6150FC21A0081DEE6 /* MKTClassObjectMock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKTClassObjectMock.m; sourceTree = "<group>"; };
638F68DC150FC3210081DEE6 /* MKTClassObjectMockTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKTClassObjectMockTest.m; sourceTree = "<group>"; };
6525714217D14C2300577580 /* MKTExactTimesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKTExactTimesTest.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -351,22 +354,23 @@
08BDD5C31350C59C00E5A443 /* Tests */ = {
isa = PBXGroup;
children = (
085CE8F1172A0D43004D070D /* BlockMatchingTest.m */,
361533CB153F283800BB982B /* MKTAtLeastTimesTest.m */,
6525714217D14C2300577580 /* MKTExactTimesTest.m */,
638F68DC150FC3210081DEE6 /* MKTClassObjectMockTest.m */,
089A8C2213552DE7003E7D27 /* MKTObjectMockTest.m */,
08E9DC271516739A00BD7FB4 /* MKTObjectAndProtocolMockTest.m */,
085A8BC6150718E30018EC66 /* MKTProtocolMockTest.m */,
08F189FC135A6D1300F76379 /* MKTInvocationMatcherTest.m */,
08F189E21359661E00F76379 /* MKTMockingProgressTest.m */,
085CE8F1172A0D43004D070D /* BlockMatchingTest.m */,
08E9DC271516739A00BD7FB4 /* MKTObjectAndProtocolMockTest.m */,
089A8C2213552DE7003E7D27 /* MKTObjectMockTest.m */,
085A8BC6150718E30018EC66 /* MKTProtocolMockTest.m */,
08FD4B1E1509A6C40004E1FA /* MockTestCase.h */,
08FD4B1F1509A6C40004E1FA /* MockTestCase.m */,
089A8C3113555D0C003E7D27 /* StubObjectTest.m */,
08FD4B251509B8740004E1FA /* StubProtocolTest.m */,
08E9DC1B15163D4600BD7FB4 /* VerifyClassObjectTest.m */,
08FD4B221509A93B0004E1FA /* VerifyProtocolTest.m */,
085D2FB11351080400EBBE91 /* VerifyObjectTest.m */,
08E9DC2D1516777100BD7FB4 /* VerifyObjectAndProtocolTest.m */,
085D2FB11351080400EBBE91 /* VerifyObjectTest.m */,
08FD4B221509A93B0004E1FA /* VerifyProtocolTest.m */,
);
path = Tests;
sourceTree = "<group>";
Expand Down Expand Up @@ -551,6 +555,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6525714317D14C2300577580 /* MKTExactTimesTest.m in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -708,6 +713,7 @@
08E9DC2E1516777200BD7FB4 /* VerifyObjectAndProtocolTest.m in Sources */,
361533CC153F283800BB982B /* MKTAtLeastTimesTest.m in Sources */,
085CE8F5172A1BCA004D070D /* BlockMatchingTest.m in Sources */,
6525714417D1510100577580 /* MKTExactTimesTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
4 changes: 2 additions & 2 deletions Source/OCMockito/MKTAtLeastTimes.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

@interface MKTAtLeastTimes : NSObject <MKTVerificationMode>

+ (id)timesWithMinimumCount:(NSUInteger)minimumExpectedNumberOfInvocations;
- (id)initWithMinimumCount:(NSUInteger)minimumExpectedNumberOfInvocations;
+ (id)timesWithMinimumCount:(NSUInteger)minimumExpectedNumberOfInvocations eventually:(BOOL)eventually;
- (id)initWithMinimumCount:(NSUInteger)minimumExpectedNumberOfInvocations eventually:(BOOL)eventually;

@end
44 changes: 35 additions & 9 deletions Source/OCMockito/MKTAtLeastTimes.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "MKTAtLeastTimes.h"

#import "OCMockito.h"
#import "MKTInvocationContainer.h"
#import "MKTInvocationMatcher.h"
#import "MKTVerificationData.h"
Expand All @@ -16,36 +17,61 @@
@implementation MKTAtLeastTimes
{
NSUInteger _minimumExpectedCount;
BOOL _eventually;
}

+ (id)timesWithMinimumCount:(NSUInteger)minimumExpectedNumberOfInvocations
+ (id)timesWithMinimumCount:(NSUInteger)minimumExpectedNumberOfInvocations eventually:(BOOL)eventually
{
return [[self alloc] initWithMinimumCount:minimumExpectedNumberOfInvocations];
return [[self alloc] initWithMinimumCount:minimumExpectedNumberOfInvocations eventually:eventually];
}

- (id)initWithMinimumCount:(NSUInteger)minimumExpectedNumberOfInvocations
- (id)initWithMinimumCount:(NSUInteger)minimumExpectedNumberOfInvocations eventually:(BOOL)eventually
{
self = [super init];
if (self)
{
_minimumExpectedCount = minimumExpectedNumberOfInvocations;
_eventually = eventually;
}
return self;
}

- (NSUInteger)matchingCountWithData:(MKTVerificationData *)data
{
NSUInteger matchingCount = 0;
for (NSInvocation *invocation in [[data invocations] registeredInvocations])
{
if ([[data wanted] matches:invocation])
++matchingCount;
}

return matchingCount;
}

#pragma mark MKTVerificationMode

- (void)verifyData:(MKTVerificationData *)data
{
if (_minimumExpectedCount == 0)
return; // this always succeeds
NSUInteger matchingCount = 0;
for (NSInvocation *invocation in [[data invocations] registeredInvocations])

NSUInteger matchingCount;
if (_eventually)
{
if ([[data wanted] matches:invocation])
++matchingCount;
NSDate *expiryDate = [NSDate dateWithTimeIntervalSinceNow:MKT_eventuallyDefaultTimeout()];
while (1)
{
matchingCount = [self matchingCountWithData:data];
if (matchingCount >= _minimumExpectedCount || [(NSDate *)[NSDate date] compare:expiryDate] == NSOrderedDescending)
break;
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
}
else
{
matchingCount = [self matchingCountWithData:data];
}

if (matchingCount < _minimumExpectedCount)
{
NSString *plural = (_minimumExpectedCount == 1) ? @"" : @"s";
Expand Down
4 changes: 2 additions & 2 deletions Source/OCMockito/MKTExactTimes.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

@interface MKTExactTimes : NSObject <MKTVerificationMode>

+ (id)timesWithCount:(NSUInteger)expectedNumberOfInvocations;
- (id)initWithCount:(NSUInteger)expectedNumberOfInvocations;
+ (id)timesWithCount:(NSUInteger)expectedNumberOfInvocations eventually:(BOOL)eventually;
- (id)initWithCount:(NSUInteger)expectedNumberOfInvocations eventually:(BOOL)eventually;

@end
52 changes: 39 additions & 13 deletions Source/OCMockito/MKTExactTimes.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "MKTExactTimes.h"

#import "OCMockito.h"
#import "MKTInvocationContainer.h"
#import "MKTInvocationMatcher.h"
#import "MKTTestLocation.h"
Expand All @@ -25,39 +26,64 @@ - (void)failWithException:(NSException *)exception;

@implementation MKTExactTimes
{
NSUInteger expectedCount;
NSUInteger _expectedCount;
BOOL _eventually;
}

+ (id)timesWithCount:(NSUInteger)expectedNumberOfInvocations
+ (id)timesWithCount:(NSUInteger)expectedNumberOfInvocations eventually:(BOOL)eventually
{
return [[self alloc] initWithCount:expectedNumberOfInvocations];
return [[self alloc] initWithCount:expectedNumberOfInvocations eventually:eventually];
}

- (id)initWithCount:(NSUInteger)expectedNumberOfInvocations
- (id)initWithCount:(NSUInteger)expectedNumberOfInvocations eventually:(BOOL)eventually
{
self = [super init];
if (self)
expectedCount = expectedNumberOfInvocations;
{
_expectedCount = expectedNumberOfInvocations;
_eventually = eventually;
}
return self;
}


#pragma mark MKTVerificationMode

- (void)verifyData:(MKTVerificationData *)data
- (NSUInteger)matchingCountWithData:(MKTVerificationData *)data
{
NSUInteger matchingCount = 0;
for (NSInvocation *invocation in [[data invocations] registeredInvocations])
{
if ([[data wanted] matches:invocation])
++matchingCount;
}

if (matchingCount != expectedCount)

return matchingCount;
}

#pragma mark MKTVerificationMode

- (void)verifyData:(MKTVerificationData *)data
{
NSUInteger matchingCount;
if (_eventually)
{
NSDate *expiryDate = [NSDate dateWithTimeIntervalSinceNow:MKT_eventuallyDefaultTimeout()];
while (1)
{
matchingCount = [self matchingCountWithData:data];
if (matchingCount > _expectedCount || [(NSDate *)[NSDate date] compare:expiryDate] == NSOrderedDescending)
break;
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
}
else
{
matchingCount = [self matchingCountWithData:data];
}

if (matchingCount != _expectedCount)
{
NSString *plural = (expectedCount == 1) ? @"" : @"s";
NSString *plural = (_expectedCount == 1) ? @"" : @"s";
NSString *description = [NSString stringWithFormat:@"Expected %u matching invocation%@, but received %u",
(unsigned)expectedCount, plural, (unsigned)matchingCount];
(unsigned)_expectedCount, plural, (unsigned)matchingCount];
MKTFailTestLocation([data testLocation], description);
}
}
Expand Down
1 change: 1 addition & 0 deletions Source/OCMockito/MKTVerificationMode.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import <Foundation/Foundation.h>

@class MKTVerificationData;
@class MKTVerificationModeResult;


@protocol MKTVerificationMode <NSObject>
Expand Down
82 changes: 82 additions & 0 deletions Source/OCMockito/OCMockito.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ OBJC_EXPORT id MKTVerifyCountWithLocation(id mock, id mode, id testCase, const c


OBJC_EXPORT id MKTTimes(NSUInteger wantedNumberOfInvocations);
OBJC_EXPORT id MKTEventuallyTimes(NSUInteger wantedNumberOfInvocations);

/**
Verifies exact number of invocations.
Expand All @@ -160,8 +161,24 @@ OBJC_EXPORT id MKTTimes(NSUInteger wantedNumberOfInvocations);
#define times(wantedNumberOfInvocations) MKTTimes(wantedNumberOfInvocations)
#endif

/**
Verifies exact number of invocations now, or at some time in the near future.

Example:
@code
[verifyCount(mockObject, eventuallyTimes(2)) someMethod:@"some arg"];
@endcode

(In the event of a name clash, don't \#define @c MOCKITO_SHORTHAND and use the synonym
@c MKTEventuallyTimes instead.)
*/
#ifdef MOCKITO_SHORTHAND
#define eventuallyTimes(wantedNumberOfInvocations) MKTEventuallyTimes(wantedNumberOfInvocations)
#endif


OBJC_EXPORT id MKTNever(void);
OBJC_EXPORT id MKTEventuallyNever(void);

/**
Verifies that interaction did not happen.
Expand All @@ -178,8 +195,24 @@ OBJC_EXPORT id MKTNever(void);
#define never() MKTNever()
#endif

/**
Verifies that interaction did not happen now, or at some time in the near future.

Example:
@code
[verifyCount(mockObject, eventuallyNever()) someMethod:@"some arg"];
@endcode

(In the event of a name clash, don't \#define @c MOCKITO_SHORTHAND and use the synonym
@c MKTEventuallyNever instead.)
*/
#ifdef MOCKITO_SHORTHAND
#define eventuallyNever() MKTEventuallyNever()
#endif


OBJC_EXPORT id MKTAtLeast(NSUInteger minimumWantedNumberOfInvocations);
OBJC_EXPORT id MKTEventuallyAtLeast(NSUInteger minimumWantedNumberOfInvocations);

/**
Verifies minimum number of invocations.
Expand All @@ -199,8 +232,27 @@ OBJC_EXPORT id MKTAtLeast(NSUInteger minimumWantedNumberOfInvocations);
#define atLeast(minimumWantedNumberOfInvocations) MKTAtLeast(minimumWantedNumberOfInvocations)
#endif

/**
Verifies minimum number of invocations now, or at some time in the near future.

The verification will succeed if the specified invocation happened the number of times
specified or more.

Example:
@code
[verifyCount(mockObject, eventuallyAtLeast(2)) someMethod:@"some arg"];
@endcode

(In the event of a name clash, don't \#define @c MOCKITO_SHORTHAND and use the synonym
@c MKTEventuallyAtLeast instead.)
*/
#ifdef MOCKITO_SHORTHAND
#define eventuallyAtLeast(minimumWantedNumberOfInvocations) MKTEventuallyAtLeast(minimumWantedNumberOfInvocations)
#endif


OBJC_EXPORT id MKTAtLeastOnce(void);
OBJC_EXPORT id MKTEventuallyAtLeastOnce(void);

/**
Verifies that interaction happened once or more.
Expand All @@ -216,3 +268,33 @@ OBJC_EXPORT id MKTAtLeastOnce(void);
#ifdef MOCKITO_SHORTHAND
#define atLeastOnce() MKTAtLeastOnce()
#endif

/**
Verifies that interaction happened once or more now, or at some time in the near future.

Example:
@code
[verifyCount(mockObject, atLeastOnce()) someMethod:@"some arg"];
@endcode

(In the event of a name clash, don't \#define @c MOCKITO_SHORTHAND and use the synonym
@c MKTEventuallyAtLeastOnce instead.)
*/
#ifdef MOCKITO_SHORTHAND
#define eventuallyAtLeastOnce() MKTEventuallyAtLeastOnce()
#endif


/**
Retrieves the default timeout used by @c eventuallyTimes, @c eventuallyNever,
@c eventuallyAtLeast and @c eventuallyAtLeastOnce.

The default value is 1 second.
*/
OBJC_EXPORT NSTimeInterval MKT_eventuallyDefaultTimeout(void);

/**
Sets the default timeout used by @c eventuallyTimes, @c eventuallyNever,
@c eventuallyAtLeast and @c eventuallyAtLeastOnce.
*/
OBJC_EXPORT void MKT_setEventuallyDefaultTimeout(NSTimeInterval defaultTimeout);
Loading