Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: third_party/ocmock/OCMock/OCMFunctions.m

Issue 2624143003: Update OCMock to 3.1.5 (Closed)
Patch Set: Patches in more commits Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2014-2015 Erik Doernenburg and contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may
5 * not use these files except in compliance with the License. You may obtain
6 * a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17 #import <objc/runtime.h>
18 #import "OCMFunctions.h"
19 #import "OCMLocation.h"
20 #import "OCClassMockObject.h"
21 #import "OCPartialMockObject.h"
22
23
24 #pragma mark Known private API
25
26 @interface NSException(OCMKnownExceptionMethods)
27 + (NSException *)failureInFile:(NSString *)file atLine:(int)line withDescription :(NSString *)formatString, ...;
28 @end
29
30 @interface NSObject(OCMKnownTestCaseMethods)
31 - (void)recordFailureWithDescription:(NSString *)description inFile:(NSString *) file atLine:(NSUInteger)line expected:(BOOL)expected;
32 - (void)failWithException:(NSException *)exception;
33 @end
34
35
36 #pragma mark Functions related to ObjC type system
37
38 BOOL OCMIsObjectType(const char *objCType)
39 {
40 objCType = OCMTypeWithoutQualifiers(objCType);
41
42 if(strcmp(objCType, @encode(id)) == 0 || strcmp(objCType, @encode(Class)) == 0)
43 return YES;
44
45 // if the returnType is a typedef to an object, it has the form ^{OriginClas s=#}
46 NSString *regexString = @"^\\^\\{(.*)=#.*\\}";
47 NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPatte rn:regexString options:0 error:NULL];
48 NSString *type = [NSString stringWithCString:objCType encoding:NSASCIIString Encoding];
49 if([regex numberOfMatchesInString:type options:0 range:NSMakeRange(0, type.l ength)] > 0)
50 return YES;
51
52 // if the return type is a block we treat it like an object
53 // TODO: if the runtime were to encode the block's argument and/or return ty pes, this test would not be sufficient
54 if(strcmp(objCType, @encode(void(^)())) == 0)
55 return YES;
56
57 return NO;
58 }
59
60
61 const char *OCMTypeWithoutQualifiers(const char *objCType)
62 {
63 while(strchr("rnNoORV", objCType[0]) != NULL)
64 objCType += 1;
65 return objCType;
66 }
67
68
69 /*
70 * Sometimes an external type is an opaque struct (which will have an @encode of "{structName}"
71 * or "{structName=}") but the actual method return type, or property type, will know the contents
72 * of the struct (so will have an objcType of say "{structName=iiSS}". This fun ction will determine
73 * those are equal provided they have the same structure name, otherwise everyth ing else will be
74 * compared textually. This can happen particularly for pointers to such struct ures, which still
75 * encode what is being pointed to.
76 *
77 * For some types some runtime functions throw exceptions, which is why we wrap this in an
78 * exception handler just below.
79 */
80 static BOOL OCMEqualTypesAllowingOpaqueStructsInternal(const char *type1, const char *type2)
81 {
82 type1 = OCMTypeWithoutQualifiers(type1);
83 type2 = OCMTypeWithoutQualifiers(type2);
84
85 switch (type1[0])
86 {
87 case '{':
88 case '(':
89 {
90 if (type2[0] != type1[0])
91 return NO;
92 char endChar = type1[0] == '{'? '}' : ')';
93
94 const char *type1End = strchr(type1, endChar);
95 const char *type2End = strchr(type2, endChar);
96 const char *type1Equals = strchr(type1, '=');
97 const char *type2Equals = strchr(type2, '=');
98
99 /* Opaque types either don't have an equals sign (just the name and the end brace), or
100 * empty content after the equals sign.
101 * We want that to compare the same as a type of the same name but w ith the content.
102 */
103 BOOL type1Opaque = (type1Equals == NULL || (type1End < type1Equals) || type1Equals[1] == endChar);
104 BOOL type2Opaque = (type2Equals == NULL || (type2End < type2Equals) || type2Equals[1] == endChar);
105 const char *type1NameEnd = (type1Equals == NULL || (type1End < type1 Equals)) ? type1End : type1Equals;
106 const char *type2NameEnd = (type2Equals == NULL || (type2End < type2 Equals)) ? type2End : type2Equals;
107 intptr_t type1NameLen = type1NameEnd - type1;
108 intptr_t type2NameLen = type2NameEnd - type2;
109
110 /* If the names are not equal, return NO */
111 if (type1NameLen != type2NameLen || strncmp(type1, type2, type1NameL en))
112 return NO;
113
114 /* If the same name, and at least one is opaque, that is close enoug h. */
115 if (type1Opaque || type2Opaque)
116 return YES;
117
118 /* Otherwise, compare all the elements. Use NSGetSizeAndAlignment t o walk through the struct elements. */
119 type1 = type1Equals + 1;
120 type2 = type2Equals + 1;
121 while (type1[0] != endChar && type1[0] != '\0')
122 {
123 if (!OCMEqualTypesAllowingOpaqueStructs(type1, type2))
124 return NO;
125 type1 = NSGetSizeAndAlignment(type1, NULL, NULL);
126 type2 = NSGetSizeAndAlignment(type2, NULL, NULL);
127 }
128 return YES;
129 }
130 case '^':
131 /* for a pointer, make sure the other is a pointer, then recursively compare the rest */
132 if (type2[0] != type1[0])
133 return NO;
134 return OCMEqualTypesAllowingOpaqueStructs(type1 + 1, type2 + 1);
135
136 case '?':
137 return type2[0] == '?';
138
139 case '\0':
140 return type2[0] == '\0';
141
142 default:
143 {
144 // Move the type pointers past the current types, then compare that region
145 const char *afterType1 = NSGetSizeAndAlignment(type1, NULL, NULL);
146 const char *afterType2 = NSGetSizeAndAlignment(type2, NULL, NULL);
147 intptr_t type1Len = afterType1 - type1;
148 intptr_t type2Len = afterType2 - type2;
149
150 return (type1Len == type2Len && (strncmp(type1, type2, type1Len) == 0));
151 }
152 }
153 }
154
155 BOOL OCMEqualTypesAllowingOpaqueStructs(const char *type1, const char *type2)
156 {
157 @try
158 {
159 return OCMEqualTypesAllowingOpaqueStructsInternal(type1, type2);
160 }
161 @catch (NSException *e)
162 {
163 /* Probably a bitfield or something that NSGetSizeAndAlignment chokes on , oh well */
164 return NO;
165 }
166 }
167
168
169 #pragma mark Creating classes
170
171 Class OCMCreateSubclass(Class class, void *ref)
172 {
173 const char *className = [[NSString stringWithFormat:@"%@-%p-%u", NSStringFro mClass(class), ref, arc4random()] UTF8String];
174 Class subclass = objc_allocateClassPair(class, className, 0);
175 objc_registerClassPair(subclass);
176 return subclass;
177 }
178
179
180 #pragma mark Directly manipulating the isa pointer (look away)
181
182 void OCMSetIsa(id object, Class class)
183 {
184 *((Class *)object) = class;
185 }
186
187 Class OCMGetIsa(id object)
188 {
189 return *((Class *)object);
190 }
191
192
193 #pragma mark Alias for renaming real methods
194
195 static NSString *const OCMRealMethodAliasPrefix = @"ocmock_replaced_";
196 static const char *const OCMRealMethodAliasPrefixCString = "ocmock_replaced_";
197
198 BOOL OCMIsAliasSelector(SEL selector)
199 {
200 return [NSStringFromSelector(selector) hasPrefix:OCMRealMethodAliasPrefix];
201 }
202
203 SEL OCMAliasForOriginalSelector(SEL selector)
204 {
205 char aliasName[2048];
206 const char *originalName = sel_getName(selector);
207 strlcpy(aliasName, OCMRealMethodAliasPrefixCString, sizeof(aliasName));
208 strlcat(aliasName, originalName, sizeof(aliasName));
209 return sel_registerName(aliasName);
210 }
211
212 SEL OCMOriginalSelectorForAlias(SEL selector)
213 {
214 if(!OCMIsAliasSelector(selector))
215 [NSException raise:NSInvalidArgumentException format:@"Not an alias sele ctor; found %@", NSStringFromSelector(selector)];
216 NSString *string = NSStringFromSelector(selector);
217 return NSSelectorFromString([string substringFromIndex:[OCMRealMethodAliasPr efix length]]);
218 }
219
220
221 #pragma mark Wrappers around associative references
222
223 static NSString *const OCMClassMethodMockObjectKey = @"OCMClassMethodMockObjectK ey";
224
225 void OCMSetAssociatedMockForClass(OCClassMockObject *mock, Class aClass)
226 {
227 if((mock != nil) && (objc_getAssociatedObject(aClass, OCMClassMethodMockObje ctKey) != nil))
228 [NSException raise:NSInternalInconsistencyException format:@"Another moc k is already associated with class %@", NSStringFromClass(aClass)];
229 objc_setAssociatedObject(aClass, OCMClassMethodMockObjectKey, mock, OBJC_ASS OCIATION_ASSIGN);
230 }
231
232 OCClassMockObject *OCMGetAssociatedMockForClass(Class aClass, BOOL includeSuperc lasses)
233 {
234 OCClassMockObject *mock = nil;
235 do
236 {
237 mock = objc_getAssociatedObject(aClass, OCMClassMethodMockObjectKey);
238 aClass = class_getSuperclass(aClass);
239 }
240 while((mock == nil) && (aClass != nil) && includeSuperclasses);
241 return mock;
242 }
243
244 static NSString *const OCMPartialMockObjectKey = @"OCMPartialMockObjectKey";
245
246 void OCMSetAssociatedMockForObject(OCClassMockObject *mock, id anObject)
247 {
248 if((mock != nil) && (objc_getAssociatedObject(anObject, OCMPartialMockObject Key) != nil))
249 [NSException raise:NSInternalInconsistencyException format:@"Another moc k is already associated with object %@", anObject];
250 objc_setAssociatedObject(anObject, OCMPartialMockObjectKey, mock, OBJC_ASSOC IATION_ASSIGN);
251 }
252
253 OCPartialMockObject *OCMGetAssociatedMockForObject(id anObject)
254 {
255 return objc_getAssociatedObject(anObject, OCMPartialMockObjectKey);
256 }
257
258
259 #pragma mark Functions related to IDE error reporting
260
261 void OCMReportFailure(OCMLocation *loc, NSString *description)
262 {
263 id testCase = [loc testCase];
264 if((testCase != nil) && [testCase respondsToSelector:@selector(recordFailure WithDescription:inFile:atLine:expected:)])
265 {
266 [testCase recordFailureWithDescription:description inFile:[loc file] atL ine:[loc line] expected:NO];
267 }
268 else if((testCase != nil) && [testCase respondsToSelector:@selector(failWith Exception:)])
269 {
270 NSException *exception = nil;
271 if([NSException instancesRespondToSelector:@selector(failureInFile:atLin e:withDescription:)])
272 {
273 exception = [NSException failureInFile:[loc file] atLine:(int)[loc l ine] withDescription:description];
274 }
275 else
276 {
277 NSString *reason = [NSString stringWithFormat:@"%@:%lu %@", [loc fil e], (unsigned long)[loc line], description];
278 exception = [NSException exceptionWithName:@"OCMockTestFailure" reas on:reason userInfo:nil];
279 }
280 [testCase failWithException:exception];
281 }
282 else if(loc != nil)
283 {
284 NSLog(@"%@:%lu %@", [loc file], (unsigned long)[loc line], description);
285 NSString *reason = [NSString stringWithFormat:@"%@:%lu %@", [loc file], (unsigned long)[loc line], description];
286 [[NSException exceptionWithName:@"OCMockTestFailure" reason:reason userI nfo:nil] raise];
287
288 }
289 else
290 {
291 NSLog(@"%@", description);
292 [[NSException exceptionWithName:@"OCMockTestFailure" reason:description userInfo:nil] raise];
293 }
294
295 }
OLDNEW
« no previous file with comments | « third_party/ocmock/OCMock/OCMFunctions.h ('k') | third_party/ocmock/OCMock/OCMIndirectReturnValueProvider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698