PageRenderTime 63ms CodeModel.GetById 2ms app.highlight 56ms RepoModel.GetById 2ms app.codeStats 0ms

/thirdparty/breakpad/common/mac/testing/GTMSenTestCase.m

http://github.com/tomahawk-player/tomahawk
Objective C | 366 lines | 279 code | 49 blank | 38 comment | 21 complexity | 17d553568e6f19f9586574109d29e26e MD5 | raw file
  1//
  2//  GTMSenTestCase.m
  3//
  4//  Copyright 2007-2008 Google Inc.
  5//
  6//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7//  use this file except in compliance with the License.  You may obtain a copy
  8//  of the License at
  9//
 10//  http://www.apache.org/licenses/LICENSE-2.0
 11//
 12//  Unless required by applicable law or agreed to in writing, software
 13//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 14//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 15//  License for the specific language governing permissions and limitations under
 16//  the License.
 17//
 18
 19#import "GTMSenTestCase.h"
 20#import <unistd.h>
 21
 22#if !GTM_IPHONE_SDK
 23#import "GTMGarbageCollection.h"
 24#endif  // !GTM_IPHONE_SDK
 25
 26#if GTM_IPHONE_SDK
 27#import <stdarg.h>
 28
 29@interface NSException (GTMSenTestPrivateAdditions)
 30+ (NSException *)failureInFile:(NSString *)filename
 31                        atLine:(int)lineNumber
 32                        reason:(NSString *)reason;
 33@end
 34
 35@implementation NSException (GTMSenTestPrivateAdditions)
 36+ (NSException *)failureInFile:(NSString *)filename
 37                        atLine:(int)lineNumber
 38                        reason:(NSString *)reason {
 39  NSDictionary *userInfo =
 40    [NSDictionary dictionaryWithObjectsAndKeys:
 41     [NSNumber numberWithInteger:lineNumber], SenTestLineNumberKey,
 42     filename, SenTestFilenameKey,
 43     nil];
 44
 45  return [self exceptionWithName:SenTestFailureException
 46                          reason:reason
 47                        userInfo:userInfo];
 48}
 49@end
 50
 51@implementation NSException (GTMSenTestAdditions)
 52
 53+ (NSException *)failureInFile:(NSString *)filename
 54                        atLine:(int)lineNumber
 55               withDescription:(NSString *)formatString, ... {
 56
 57  NSString *testDescription = @"";
 58  if (formatString) {
 59    va_list vl;
 60    va_start(vl, formatString);
 61    testDescription =
 62      [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
 63    va_end(vl);
 64  }
 65
 66  NSString *reason = testDescription;
 67
 68  return [self failureInFile:filename atLine:lineNumber reason:reason];
 69}
 70
 71+ (NSException *)failureInCondition:(NSString *)condition
 72                             isTrue:(BOOL)isTrue
 73                             inFile:(NSString *)filename
 74                             atLine:(int)lineNumber
 75                    withDescription:(NSString *)formatString, ... {
 76
 77  NSString *testDescription = @"";
 78  if (formatString) {
 79    va_list vl;
 80    va_start(vl, formatString);
 81    testDescription =
 82      [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
 83    va_end(vl);
 84  }
 85
 86  NSString *reason = [NSString stringWithFormat:@"'%@' should be %s. %@",
 87                      condition, isTrue ? "TRUE" : "FALSE", testDescription];
 88
 89  return [self failureInFile:filename atLine:lineNumber reason:reason];
 90}
 91
 92+ (NSException *)failureInEqualityBetweenObject:(id)left
 93                                      andObject:(id)right
 94                                         inFile:(NSString *)filename
 95                                         atLine:(int)lineNumber
 96                                withDescription:(NSString *)formatString, ... {
 97
 98  NSString *testDescription = @"";
 99  if (formatString) {
100    va_list vl;
101    va_start(vl, formatString);
102    testDescription =
103      [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
104    va_end(vl);
105  }
106
107  NSString *reason =
108    [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@",
109     [left description], [right description], testDescription];
110
111  return [self failureInFile:filename atLine:lineNumber reason:reason];
112}
113
114+ (NSException *)failureInEqualityBetweenValue:(NSValue *)left
115                                      andValue:(NSValue *)right
116                                  withAccuracy:(NSValue *)accuracy
117                                        inFile:(NSString *)filename
118                                        atLine:(int)lineNumber
119                               withDescription:(NSString *)formatString, ... {
120
121  NSString *testDescription = @"";
122  if (formatString) {
123    va_list vl;
124    va_start(vl, formatString);
125    testDescription =
126      [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
127    va_end(vl);
128  }
129
130  NSString *reason;
131  if (accuracy) {
132    reason =
133      [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@",
134       left, right, testDescription];
135  } else {
136    reason =
137      [NSString stringWithFormat:@"'%@' should be equal to '%@' +/-'%@'. %@",
138       left, right, accuracy, testDescription];
139  }
140
141  return [self failureInFile:filename atLine:lineNumber reason:reason];
142}
143
144+ (NSException *)failureInRaise:(NSString *)expression
145                         inFile:(NSString *)filename
146                         atLine:(int)lineNumber
147                withDescription:(NSString *)formatString, ... {
148
149  NSString *testDescription = @"";
150  if (formatString) {
151    va_list vl;
152    va_start(vl, formatString);
153    testDescription =
154      [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
155    va_end(vl);
156  }
157
158  NSString *reason = [NSString stringWithFormat:@"'%@' should raise. %@",
159                      expression, testDescription];
160
161  return [self failureInFile:filename atLine:lineNumber reason:reason];
162}
163
164+ (NSException *)failureInRaise:(NSString *)expression
165                      exception:(NSException *)exception
166                         inFile:(NSString *)filename
167                         atLine:(int)lineNumber
168                withDescription:(NSString *)formatString, ... {
169
170  NSString *testDescription = @"";
171  if (formatString) {
172    va_list vl;
173    va_start(vl, formatString);
174    testDescription =
175      [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
176    va_end(vl);
177  }
178
179  NSString *reason;
180  if ([[exception name] isEqualToString:SenTestFailureException]) {
181    // it's our exception, assume it has the right description on it.
182    reason = [exception reason];
183  } else {
184    // not one of our exception, use the exceptions reason and our description
185    reason = [NSString stringWithFormat:@"'%@' raised '%@'. %@",
186              expression, [exception reason], testDescription];
187  }
188
189  return [self failureInFile:filename atLine:lineNumber reason:reason];
190}
191
192@end
193
194NSString *STComposeString(NSString *formatString, ...) {
195  NSString *reason = @"";
196  if (formatString) {
197    va_list vl;
198    va_start(vl, formatString);
199    reason =
200      [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
201    va_end(vl);
202  }
203  return reason;
204}
205
206NSString *const SenTestFailureException = @"SenTestFailureException";
207NSString *const SenTestFilenameKey = @"SenTestFilenameKey";
208NSString *const SenTestLineNumberKey = @"SenTestLineNumberKey";
209
210@interface SenTestCase (SenTestCasePrivate)
211// our method of logging errors
212+ (void)printException:(NSException *)exception fromTestName:(NSString *)name;
213@end
214
215@implementation SenTestCase
216- (void)failWithException:(NSException*)exception {
217  [exception raise];
218}
219
220- (void)setUp {
221}
222
223- (void)performTest:(SEL)sel {
224  currentSelector_ = sel;
225  @try {
226    [self invokeTest];
227  } @catch (NSException *exception) {
228    [[self class] printException:exception
229                    fromTestName:NSStringFromSelector(sel)];
230    [exception raise];
231  }
232}
233
234+ (void)printException:(NSException *)exception fromTestName:(NSString *)name {
235  NSDictionary *userInfo = [exception userInfo];
236  NSString *filename = [userInfo objectForKey:SenTestFilenameKey];
237  NSNumber *lineNumber = [userInfo objectForKey:SenTestLineNumberKey];
238  NSString *className = NSStringFromClass([self class]);
239  if ([filename length] == 0) {
240    filename = @"Unknown.m";
241  }
242  fprintf(stderr, "%s:%ld: error: -[%s %s] : %s\n",
243          [filename UTF8String],
244          (long)[lineNumber integerValue],
245          [className UTF8String],
246          [name UTF8String],
247          [[exception reason] UTF8String]);
248  fflush(stderr);
249}
250
251- (void)invokeTest {
252  NSException *e = nil;
253  @try {
254    // Wrap things in autorelease pools because they may
255    // have an STMacro in their dealloc which may get called
256    // when the pool is cleaned up
257    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
258    // We don't log exceptions here, instead we let the person that called
259    // this log the exception.  This ensures they are only logged once but the
260    // outer layers get the exceptions to report counts, etc.
261    @try {
262      [self setUp];
263      @try {
264        [self performSelector:currentSelector_];
265      } @catch (NSException *exception) {
266        e = [exception retain];
267      }
268      [self tearDown];
269    } @catch (NSException *exception) {
270      e = [exception retain];
271    }
272    [pool release];
273  } @catch (NSException *exception) {
274    e = [exception retain];
275  }
276  if (e) {
277    [e autorelease];
278    [e raise];
279  }
280}
281
282- (void)tearDown {
283}
284
285- (NSString *)description {
286  // This matches the description OCUnit would return to you
287  return [NSString stringWithFormat:@"-[%@ %@]", [self class], 
288          NSStringFromSelector(currentSelector_)];
289}
290@end
291
292#endif  // GTM_IPHONE_SDK
293
294@implementation GTMTestCase : SenTestCase
295- (void)invokeTest {
296  Class devLogClass = NSClassFromString(@"GTMUnitTestDevLog");
297  if (devLogClass) {
298    [devLogClass performSelector:@selector(enableTracking)];
299    [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)];
300
301  }
302  [super invokeTest];
303  if (devLogClass) {
304    [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)];
305    [devLogClass performSelector:@selector(disableTracking)];
306  }
307}
308@end
309
310// Leak detection
311#if !GTM_IPHONE_DEVICE
312// Don't want to get leaks on the iPhone Device as the device doesn't
313// have 'leaks'. The simulator does though.
314
315// COV_NF_START
316// We don't have leak checking on by default, so this won't be hit.
317static void _GTMRunLeaks(void) {
318  // This is an atexit handler. It runs leaks for us to check if we are 
319  // leaking anything in our tests. 
320  const char* cExclusionsEnv = getenv("GTM_LEAKS_SYMBOLS_TO_IGNORE");
321  NSMutableString *exclusions = [NSMutableString string];
322  if (cExclusionsEnv) {
323    NSString *exclusionsEnv = [NSString stringWithUTF8String:cExclusionsEnv];
324    NSArray *exclusionsArray = [exclusionsEnv componentsSeparatedByString:@","];
325    NSString *exclusion;
326    NSCharacterSet *wcSet = [NSCharacterSet whitespaceCharacterSet];
327    GTM_FOREACH_OBJECT(exclusion, exclusionsArray) {
328      exclusion = [exclusion stringByTrimmingCharactersInSet:wcSet];
329      [exclusions appendFormat:@"-exclude \"%@\" ", exclusion];
330    }
331  }
332  NSString *string 
333    = [NSString stringWithFormat:@"/usr/bin/leaks %@%d"
334       @"| /usr/bin/sed -e 's/Leak: /Leaks:0: warning: Leak /'", 
335       exclusions, getpid()];
336  int ret = system([string UTF8String]);
337  if (ret) {
338    fprintf(stderr, "%s:%d: Error: Unable to run leaks. 'system' returned: %d", 
339            __FILE__, __LINE__, ret);
340    fflush(stderr);
341  }
342}
343// COV_NF_END
344
345static __attribute__((constructor)) void _GTMInstallLeaks(void) {
346  BOOL checkLeaks = YES;
347#if !GTM_IPHONE_SDK
348  checkLeaks = GTMIsGarbageCollectionEnabled() ? NO : YES;
349#endif  // !GTM_IPHONE_SDK
350  if (checkLeaks) {
351    checkLeaks = getenv("GTM_ENABLE_LEAKS") ? YES : NO;
352    if (checkLeaks) {
353      // COV_NF_START
354      // We don't have leak checking on by default, so this won't be hit.
355      fprintf(stderr, "Leak Checking Enabled\n");
356      fflush(stderr);
357      int ret = atexit(&_GTMRunLeaks);
358      _GTMDevAssert(ret == 0, 
359                    @"Unable to install _GTMRunLeaks as an atexit handler (%d)", 
360                    errno);
361      // COV_NF_END
362    }  
363  }
364}
365
366#endif   // !GTM_IPHONE_DEVICE