Skip to content

Commit

Permalink
Revert "Removed code that tried to make setup/verify thread-safe."
Browse files Browse the repository at this point in the history
This reverts commit 06d2c33.
  • Loading branch information
erikdoe committed Apr 12, 2016
1 parent 015a8f5 commit bf6f59a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 15 deletions.
29 changes: 18 additions & 11 deletions Source/OCMock/OCMMacroState.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,34 @@

@implementation OCMMacroState

static OCMMacroState *globalState;
static NSString *const OCMGlobalStateKey = @"OCMGlobalStateKey";

#pragma mark Methods to begin/end macros

+ (void)beginStubMacro
{
OCMStubRecorder *recorder = [[[OCMStubRecorder alloc] init] autorelease];
globalState = [[[OCMMacroState alloc] initWithRecorder:recorder] autorelease];
OCMMacroState *macroState = [[OCMMacroState alloc] initWithRecorder:recorder];
[NSThread currentThread].threadDictionary[OCMGlobalStateKey] = macroState;
[macroState release];
}

+ (OCMStubRecorder *)endStubMacro
{
OCMStubRecorder *recorder = (OCMStubRecorder *)[globalState recorder];
globalState = nil;
return recorder;
NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary;
OCMMacroState *globalState = threadDictionary[OCMGlobalStateKey];
OCMStubRecorder *recorder = [(OCMStubRecorder *)[globalState recorder] retain];
[threadDictionary removeObjectForKey:OCMGlobalStateKey];
return [recorder autorelease];
}


+ (void)beginExpectMacro
{
OCMExpectationRecorder *recorder = [[[OCMExpectationRecorder alloc] init] autorelease];
globalState = [[[OCMMacroState alloc] initWithRecorder:recorder] autorelease];
OCMMacroState *macroState = [[OCMMacroState alloc] initWithRecorder:recorder];
[NSThread currentThread].threadDictionary[OCMGlobalStateKey] = macroState;
[macroState release];
}

+ (OCMStubRecorder *)endExpectMacro
Expand All @@ -58,20 +64,22 @@ + (void)beginVerifyMacroAtLocation:(OCMLocation *)aLocation
{
OCMVerifier *recorder = [[[OCMVerifier alloc] init] autorelease];
[recorder setLocation:aLocation];
globalState = [[[OCMMacroState alloc] initWithRecorder:recorder] autorelease];
OCMMacroState *macroState = [[OCMMacroState alloc] initWithRecorder:recorder];
[NSThread currentThread].threadDictionary[OCMGlobalStateKey] = macroState;
[macroState release];
}

+ (void)endVerifyMacro
{
globalState = nil;
[[NSThread currentThread].threadDictionary removeObjectForKey:OCMGlobalStateKey];
}


#pragma mark Accessing global state

+ (OCMMacroState *)globalState
{
return globalState;
return [NSThread currentThread].threadDictionary[OCMGlobalStateKey];
}


Expand All @@ -90,8 +98,7 @@ - (id)initWithRecorder:(OCMRecorder *)aRecorder
- (void)dealloc
{
[recorder release];
if(globalState == self)
globalState = nil;
NSAssert([NSThread currentThread].threadDictionary[OCMGlobalStateKey] != self, @"Unexpected dealloc while set as the global state");
[super dealloc];
}

Expand Down
17 changes: 15 additions & 2 deletions Source/OCMock/OCMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,27 @@
({ \
_OCMSilenceWarnings( \
[OCMMacroState beginStubMacro]; \
OCMStubRecorder *recorder = nil; \
@try{ \
invocation; \
[OCMMacroState endStubMacro]; \
}@finally{ \
recorder = [OCMMacroState endStubMacro]; \
} \
recorder; \
); \
})

#define OCMExpect(invocation) \
({ \
_OCMSilenceWarnings( \
[OCMMacroState beginExpectMacro]; \
OCMStubRecorder *recorder = nil; \
@try{ \
invocation; \
[OCMMacroState endExpectMacro]; \
}@finally{ \
recorder = [OCMMacroState endExpectMacro]; \
} \
recorder; \
); \
})

Expand All @@ -71,8 +81,11 @@
({ \
_OCMSilenceWarnings( \
[OCMMacroState beginVerifyMacroAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]; \
@try{ \
invocation; \
}@finally{ \
[OCMMacroState endVerifyMacro]; \
} \
); \
})

Expand Down
25 changes: 23 additions & 2 deletions Source/OCMock/OCMockObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,19 @@ - (NSString *)description

- (void)addStub:(OCMInvocationStub *)aStub
{
@synchronized(stubs)
{
[stubs addObject:aStub];
}
}

- (void)addExpectation:(OCMInvocationExpectation *)anExpectation
{
@synchronized(expectations)
{
[expectations addObject:anExpectation];
}
}


#pragma mark Public API
Expand Down Expand Up @@ -159,11 +165,14 @@ - (id)verify
- (id)verifyAtLocation:(OCMLocation *)location
{
NSMutableArray *unsatisfiedExpectations = [NSMutableArray array];
@synchronized(expectations)
{
for(OCMInvocationExpectation *e in expectations)
{
if(![e isSatisfied])
[unsatisfiedExpectations addObject:e];
}
}

if([unsatisfiedExpectations count] == 1)
{
Expand All @@ -178,12 +187,18 @@ - (id)verifyAtLocation:(OCMLocation *)location
OCMReportFailure(location, description);
}

if([exceptions count] > 0)
OCMInvocationExpectation *firstException = nil;
@synchronized(exceptions)
{
firstException = [exceptions.firstObject retain];
}
if(firstException)
{
NSString *description = [NSString stringWithFormat:@"%@: %@ (This is a strict mock failure that was ignored when it actually occured.)",
[self description], [[exceptions objectAtIndex:0] description]];
[self description], [firstException description]];
OCMReportFailure(location, description);
}
[firstException release];

return [[[OCMVerifier alloc] initWithMockObject:self] autorelease];
}
Expand All @@ -199,8 +214,11 @@ - (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location
NSTimeInterval step = 0.01;
while(delay > 0)
{
@synchronized(expectations)
{
if([expectations count] == 0)
break;
}
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:MIN(step, delay)]];
delay -= step;
step *= 2;
Expand All @@ -218,11 +236,14 @@ - (void)verifyInvocation:(OCMInvocationMatcher *)matcher

- (void)verifyInvocation:(OCMInvocationMatcher *)matcher atLocation:(OCMLocation *)location
{
@synchronized(invocations)
{
for(NSInvocation *invocation in invocations)
{
if([matcher matchesInvocation:invocation])
return;
}
}
NSString *description = [NSString stringWithFormat:@"%@: Method %@ was not invoked.",
[self description], [matcher description]];

Expand Down
9 changes: 9 additions & 0 deletions Source/OCMock/OCObserverMockObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,22 @@ - (void)setExpectationOrderMatters:(BOOL)flag

- (void)autoRemoveFromCenter:(NSNotificationCenter *)aCenter
{
@synchronized(centers)
{
[centers addObject:aCenter];
}
}


#pragma mark Public API

- (id)expect
{
OCMObserverRecorder *recorder = [[[OCMObserverRecorder alloc] init] autorelease];
@synchronized(recorders)
{
[recorders addObject:recorder];
}
return recorder;
}

Expand All @@ -81,6 +87,8 @@ - (void)verify

- (void)verifyAtLocation:(OCMLocation *)location
{
@synchronized(recorders)
{
if([recorders count] == 1)
{
NSString *description = [NSString stringWithFormat:@"%@: expected notification was not observed: %@",
Expand All @@ -94,6 +102,7 @@ - (void)verifyAtLocation:(OCMLocation *)location
OCMReportFailure(location, description);
}
}
}


#pragma mark Receiving recording requests via macro
Expand Down

0 comments on commit bf6f59a

Please sign in to comment.