Update mojo sdk to rev 1dc8a9a5db73d3718d99917fadf31f5fb2ebad4f
[chromium-blink-merge.git] / third_party / ocmock / OCMock / OCMockObject.m
blob6f2daf00628fff51cafafab7db4adeacb9b26a87
1 //---------------------------------------------------------------------------------------
2 //  $Id$
3 //  Copyright (c) 2004-2009 by Mulle Kybernetik. See License file for details.
4 //---------------------------------------------------------------------------------------
6 #import <OCMock/OCMockObject.h>
7 #import "OCClassMockObject.h"
8 #import "OCProtocolMockObject.h"
9 #import "OCPartialMockObject.h"
10 #import "OCObserverMockObject.h"
11 #import <OCMock/OCMockRecorder.h>
12 #import "NSInvocation+OCMAdditions.h"
14 @interface OCMockObject(Private)
15 + (id)_makeNice:(OCMockObject *)mock;
16 - (NSString *)_recorderDescriptions:(BOOL)onlyExpectations;
17 @end
19 #pragma mark  -
22 @implementation OCMockObject
24 #pragma mark  Class initialisation
26 + (void)initialize
28         if([[NSInvocation class] instanceMethodSignatureForSelector:@selector(getArgumentAtIndexAsObject:)] == NULL)
29                 [NSException raise:NSInternalInconsistencyException format:@"** Expected method not present; the method getArgumentAtIndexAsObject: is not implemented by NSInvocation. If you see this exception it is likely that you are using the static library version of OCMock and your project is not configured correctly to load categories from static libraries. Did you forget to add the -force_load linker flag?"];
33 #pragma mark  Factory methods
35 + (id)mockForClass:(Class)aClass
37         return [[[OCClassMockObject alloc] initWithClass:aClass] autorelease];
40 + (id)mockForProtocol:(Protocol *)aProtocol
42         return [[[OCProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease];
45 + (id)partialMockForObject:(NSObject *)anObject
47         return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease];
51 + (id)niceMockForClass:(Class)aClass
53         return [self _makeNice:[self mockForClass:aClass]];
56 + (id)niceMockForProtocol:(Protocol *)aProtocol
58         return [self _makeNice:[self mockForProtocol:aProtocol]];
62 + (id)_makeNice:(OCMockObject *)mock
64         mock->isNice = YES;
65         return mock;
69 + (id)observerMock
71         return [[[OCObserverMockObject alloc] init] autorelease];
76 #pragma mark  Initialisers, description, accessors, etc.
78 - (id)init
80         // no [super init], we're inheriting from NSProxy
81         expectationOrderMatters = NO;
82         recorders = [[NSMutableArray alloc] init];
83         expectations = [[NSMutableArray alloc] init];
84         rejections = [[NSMutableArray alloc] init];
85         exceptions = [[NSMutableArray alloc] init];
86         return self;
89 - (void)dealloc
91         [recorders release];
92         [expectations release];
93         [rejections     release];
94         [exceptions release];
95         [super dealloc];
98 - (NSString *)description
100         return @"OCMockObject";
104 - (void)setExpectationOrderMatters:(BOOL)flag
106     expectationOrderMatters = flag;
110 #pragma mark  Public API
112 - (id)stub
114         OCMockRecorder *recorder = [self getNewRecorder];
115         [recorders addObject:recorder];
116         return recorder;
120 - (id)expect
122         OCMockRecorder *recorder = [self stub];
123         [expectations addObject:recorder];
124         return recorder;
128 - (id)reject
130         OCMockRecorder *recorder = [self stub];
131         [rejections addObject:recorder];
132         return recorder;
136 - (void)verify
138         if([expectations count] == 1)
139         {
140                 [NSException raise:NSInternalInconsistencyException format:@"%@: expected method was not invoked: %@", 
141                         [self description], [[expectations objectAtIndex:0] description]];
142         }
143         if([expectations count] > 0)
144         {
145                 [NSException raise:NSInternalInconsistencyException format:@"%@ : %ld expected methods were not invoked: %@", 
146                         [self description], (unsigned long)[expectations count], [self _recorderDescriptions:YES]];
147         }
148         if([exceptions count] > 0)
149         {
150                 [[exceptions objectAtIndex:0] raise];
151         }
156 #pragma mark  Handling invocations
158 - (void)forwardInvocation:(NSInvocation *)anInvocation
160         if([self handleInvocation:anInvocation] == NO)
161                 [self handleUnRecordedInvocation:anInvocation];
164 - (BOOL)handleInvocation:(NSInvocation *)anInvocation
166         OCMockRecorder *recorder = nil;
167         unsigned int                       i;
168         
169         for(i = 0; i < [recorders count]; i++)
170         {
171                 recorder = [recorders objectAtIndex:i];
172                 if([recorder matchesInvocation:anInvocation])
173                         break;
174         }
175         
176         if(i == [recorders count])
177                 return NO;
178         
179         if([rejections containsObject:recorder]) 
180         {
181                 NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException reason:
182                                                                   [NSString stringWithFormat:@"%@: explicitly disallowed method invoked: %@", [self description], 
183                                                                    [anInvocation invocationDescription]] userInfo:nil];
184                 [exceptions addObject:exception];
185                 [exception raise];
186         }
188         if([expectations containsObject:recorder])
189         {
190                 if(expectationOrderMatters && ([expectations objectAtIndex:0] != recorder))
191                 {
192                         [NSException raise:NSInternalInconsistencyException     format:@"%@: unexpected method invoked: %@\n\texpected:\t%@",  
193                          [self description], [recorder description], [[expectations objectAtIndex:0] description]];
194                         
195                 }
196                 [[recorder retain] autorelease];
197                 [expectations removeObject:recorder];
198                 [recorders removeObjectAtIndex:i];
199         }
200         [[recorder invocationHandlers] makeObjectsPerformSelector:@selector(handleInvocation:) withObject:anInvocation];
201         
202         return YES;
205 - (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation
207         if(isNice == NO)
208         {
209                 NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException reason:
210                                                                   [NSString stringWithFormat:@"%@: unexpected method invoked: %@ %@",  [self description], 
211                                                                    [anInvocation invocationDescription], [self _recorderDescriptions:NO]] userInfo:nil];
212                 [exceptions addObject:exception];
213                 [exception raise];
214         }
218 #pragma mark  Helper methods
220 - (id)getNewRecorder
222         return [[[OCMockRecorder alloc] initWithSignatureResolver:self] autorelease];
226 - (NSString *)_recorderDescriptions:(BOOL)onlyExpectations
228         NSMutableString *outputString = [NSMutableString string];
229         
230         OCMockRecorder *currentObject;
231         NSEnumerator *recorderEnumerator = [recorders objectEnumerator];
232         while((currentObject = [recorderEnumerator nextObject]) != nil)
233         {
234                 NSString *prefix;
235                 
236                 if(onlyExpectations)
237                 {
238                         if(![expectations containsObject:currentObject])
239                                 continue;
240                         prefix = @" ";
241                 }
242                 else
243                 {
244                         if ([expectations containsObject:currentObject])
245                                 prefix = @"expected: ";
246                         else
247                                 prefix = @"stubbed: ";
248                 }
249                 [outputString appendFormat:@"\n\t%@\t%@", prefix, [currentObject description]];
250         }
251         
252         return outputString;
256 @end