- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / ocmock / OCMock / OCMockObject.m
1 //---------------------------------------------------------------------------------------
2 //  $Id$
3 //  Copyright (c) 2004-2009 by Mulle Kybernetik. See License file for details.
4 //---------------------------------------------------------------------------------------
5
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"
13
14 @interface OCMockObject(Private)
15 + (id)_makeNice:(OCMockObject *)mock;
16 - (NSString *)_recorderDescriptions:(BOOL)onlyExpectations;
17 @end
18
19 #pragma mark  -
20
21
22 @implementation OCMockObject
23
24 #pragma mark  Class initialisation
25
26 + (void)initialize
27 {
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?"];
30 }
31
32
33 #pragma mark  Factory methods
34
35 + (id)mockForClass:(Class)aClass
36 {
37         return [[[OCClassMockObject alloc] initWithClass:aClass] autorelease];
38 }
39
40 + (id)mockForProtocol:(Protocol *)aProtocol
41 {
42         return [[[OCProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease];
43 }
44
45 + (id)partialMockForObject:(NSObject *)anObject
46 {
47         return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease];
48 }
49
50
51 + (id)niceMockForClass:(Class)aClass
52 {
53         return [self _makeNice:[self mockForClass:aClass]];
54 }
55
56 + (id)niceMockForProtocol:(Protocol *)aProtocol
57 {
58         return [self _makeNice:[self mockForProtocol:aProtocol]];
59 }
60
61
62 + (id)_makeNice:(OCMockObject *)mock
63 {
64         mock->isNice = YES;
65         return mock;
66 }
67
68
69 + (id)observerMock
70 {
71         return [[[OCObserverMockObject alloc] init] autorelease];
72 }
73
74
75
76 #pragma mark  Initialisers, description, accessors, etc.
77
78 - (id)init
79 {
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;
87 }
88
89 - (void)dealloc
90 {
91         [recorders release];
92         [expectations release];
93         [rejections     release];
94         [exceptions release];
95         [super dealloc];
96 }
97
98 - (NSString *)description
99 {
100         return @"OCMockObject";
101 }
102
103
104 - (void)setExpectationOrderMatters:(BOOL)flag
105 {
106     expectationOrderMatters = flag;
107 }
108
109
110 #pragma mark  Public API
111
112 - (id)stub
113 {
114         OCMockRecorder *recorder = [self getNewRecorder];
115         [recorders addObject:recorder];
116         return recorder;
117 }
118
119
120 - (id)expect
121 {
122         OCMockRecorder *recorder = [self stub];
123         [expectations addObject:recorder];
124         return recorder;
125 }
126
127
128 - (id)reject
129 {
130         OCMockRecorder *recorder = [self stub];
131         [rejections addObject:recorder];
132         return recorder;
133 }
134
135
136 - (void)verify
137 {
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         }
152 }
153
154
155
156 #pragma mark  Handling invocations
157
158 - (void)forwardInvocation:(NSInvocation *)anInvocation
159 {
160         if([self handleInvocation:anInvocation] == NO)
161                 [self handleUnRecordedInvocation:anInvocation];
162 }
163
164 - (BOOL)handleInvocation:(NSInvocation *)anInvocation
165 {
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         }
187
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;
203 }
204
205 - (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation
206 {
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         }
215 }
216
217
218 #pragma mark  Helper methods
219
220 - (id)getNewRecorder
221 {
222         return [[[OCMockRecorder alloc] initWithSignatureResolver:self] autorelease];
223 }
224
225
226 - (NSString *)_recorderDescriptions:(BOOL)onlyExpectations
227 {
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;
253 }
254
255
256 @end