From aca76201ad6871d1fc25fe51b0089b5d34caa840 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Thu, 7 Jan 2010 15:28:47 +0000 Subject: [PATCH] Monotone-Parent: a0eed2fa6f0ac118ef5805719586e42b465f61f9 Monotone-Revision: f36c1a3969587db790c18c96805411a8dfe38f00 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2010-01-07T15:28:47 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 8 ++ UnitTests/GNUmakefile | 18 ++++ UnitTests/SOGoTest.h | 79 ++++++++++++++ UnitTests/SOGoTest.m | 237 +++++++++++++++++++++++++++++++++++++++++ UnitTests/sogo-tests.m | 81 ++++++++++++++ 5 files changed, 423 insertions(+) create mode 100644 UnitTests/GNUmakefile create mode 100644 UnitTests/SOGoTest.h create mode 100644 UnitTests/SOGoTest.m create mode 100644 UnitTests/sogo-tests.m diff --git a/ChangeLog b/ChangeLog index 92567f74d..19fe646eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-01-07 Wolfgang Sourdeau + + * UnitTests/SOGoTest.m: base class for our unit test testcases. + Similar to JUnit and family. + + * UnitTests/sogo-tests.m: main executable for our Objective-C test + framework. + 2010-01-06 Wolfgang Sourdeau * UI/WebServerResources/SchedulerUI.js (onViewEventCallback): diff --git a/UnitTests/GNUmakefile b/UnitTests/GNUmakefile new file mode 100644 index 000000000..bdc05f509 --- /dev/null +++ b/UnitTests/GNUmakefile @@ -0,0 +1,18 @@ +# GNUstep makefile + +include ../config.make +include $(GNUSTEP_MAKEFILES)/common.make +include ../Version + +TEST_TOOL = sogo-tests +$(TEST_TOOL)_INSTALL_DIR = $(SOGO_ADMIN_TOOLS) +$(TEST_TOOL)_OBJC_FILES += \ + sogo-tests.m \ + \ + SOGoTest.m + +TOOL_NAME = $(TEST_TOOL) + +-include GNUmakefile.preamble +include $(GNUSTEP_MAKEFILES)/tool.make +-include GNUmakefile.postamble diff --git a/UnitTests/SOGoTest.h b/UnitTests/SOGoTest.h new file mode 100644 index 000000000..5b8ba515d --- /dev/null +++ b/UnitTests/SOGoTest.h @@ -0,0 +1,79 @@ +/* SOGoTest.h - this file is part of SOGo + * + * Copyright (C) 2010 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef SOGOTEST_H +#define SOGOTEST_H + +#import + +@class NSArray; +@class NSMutableArray; + +typedef enum { + SOGoTestFailureSuccess = 0, + SOGoTestFailureFailure = 1, + SOGoTestFailureError = 2, +} SOGoTestFailureCode; + +@interface SOGoTest : NSObject +{ + NSMutableArray *messages; + int testCount; + int failuresCount; + int errorsCount; + BOOL hasFailed; +} + ++ (NSArray *) allTestClasses; + +- (void) setUp; +- (void) tearDown; + +- (void) test: (BOOL) condition + message: (NSString *) message + file: (const char *) file + line: (int) line; + +- (BOOL) run; + +@end + +#define test(c) { \ + [self test: (c) message: @"assertion failure" \ + file: __FILE__ line: __LINE__]; \ + } + +#define testWithMessage(c,m) { \ + [self test: (c) message: (m) \ + file: __FILE__ line: __LINE__]; \ + } + +#define failIf(c) test(!c) + +#define testEquals(a,b) \ + testWithMessage(([a isEqual: b]), \ + ([NSString stringWithFormat: @"objects %@ and %@ differs", a, b])) + +#define testEqualsWithMessage(a,b,m) \ + testWithMessage(([a isEqual: b]), (m)) + +#endif /* SOGOTEST_H */ diff --git a/UnitTests/SOGoTest.m b/UnitTests/SOGoTest.m new file mode 100644 index 000000000..1015633ca --- /dev/null +++ b/UnitTests/SOGoTest.m @@ -0,0 +1,237 @@ +/* SOGoTest.m - this file is part of SOGo + * + * Copyright (C) 2010 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import + +#import "SOGoTest.h" + +static NSString *SOGoTestAssertException = @"SOGoTestAssertException"; + +@implementation SOGoTest + ++ (NSArray *) allTestClasses +{ + NSMutableArray *allTestClasses; + NSArray *allSubClasses; + NSString *class; + int count, max; + + allSubClasses = GSObjCAllSubclassesOfClass (self); + max = [allSubClasses count]; + allTestClasses = [NSMutableArray arrayWithCapacity: max]; + for (count = 0; count < max; count++) + { + class = NSStringFromClass ([allSubClasses objectAtIndex: count]); + if ([class hasPrefix: @"Test"]) + [allTestClasses addObject: class]; + } + + return allTestClasses; +} + +- (id) init +{ + if ((self = [super init])) + { + messages = [NSMutableArray new]; + testCount = 0; + failuresCount = 0; + errorsCount = 0; + hasFailed = NO; + } + + return self; +} + +- (void) dealloc +{ + [messages release]; + [super dealloc]; +} + +- (void) setUp +{ +} + +- (void) tearDown +{ +} + +- (void) test: (BOOL) condition + message: (NSString *) message + file: (const char *) file + line: (int) line +{ + NSDictionary *fileInfo; + + if (!condition) + { + if (file) + fileInfo = [NSDictionary dictionaryWithObject: + [NSString stringWithFormat: @"%s:%d", file, line] + forKey: @"fileInfo"]; + else + fileInfo = nil; + [[NSException exceptionWithName: SOGoTestAssertException + reason: message + userInfo: fileInfo] raise]; + } +} + +- (void) reportException: (NSException *) exception + method: (NSString *) methodName + withCode: (SOGoTestFailureCode) failureCode +{ + static NSString *failurePrefixs[] = { @"", @"FAIL", @"ERROR" }; + NSMutableString *message; + NSString *fileInfo; + + hasFailed = YES; + + message = [NSMutableString stringWithFormat: @"%@: %@", + failurePrefixs[failureCode], methodName]; + fileInfo = [[exception userInfo] objectForKey: @"fileInfo"]; + if (fileInfo) + [message appendFormat: @" (%@)\n", fileInfo]; + else + [message appendString: @"\n"]; + [message appendString: @"----------------------------------------------------------------------\n"]; + + if (failureCode == SOGoTestFailureFailure) + { + [message appendString: [exception reason]]; + failuresCount++; + } + else if (failureCode == SOGoTestFailureError) + { + [message appendFormat: @"an exception occured: %@\n" + @" reason: %@", + [exception name], [exception reason]]; + errorsCount++; + } + [message appendString: @"\n"]; + [messages addObject: message]; +} + +- (void) performTest: (SEL) testMethod +{ + static char failureChars[] = { '.', 'F', 'E' }; + SOGoTestFailureCode failureCode; + + failureCode = SOGoTestFailureSuccess; + NS_DURING + { + [self setUp]; + } + NS_HANDLER + { + failureCode = SOGoTestFailureError; + [self reportException: localException + method: @"setUp" + withCode: failureCode]; + } + NS_ENDHANDLER; + + if (failureCode == SOGoTestFailureSuccess) + { + NS_DURING + { + [self performSelector: testMethod]; + } + NS_HANDLER + { + if ([[localException name] + isEqualToString: SOGoTestAssertException]) + failureCode = SOGoTestFailureFailure; + else + failureCode = SOGoTestFailureError; + [self reportException: localException + method: NSStringFromSelector (testMethod) + withCode: failureCode]; + } + NS_ENDHANDLER; + } + + NS_DURING + { + [self tearDown]; + } + NS_HANDLER + { + failureCode = SOGoTestFailureError; + [self reportException: localException + method: @"tearDown" + withCode: failureCode]; + } + NS_ENDHANDLER; + + testCount++; + fprintf (stderr, "%c", failureChars[failureCode]); +} + +- (void) displayReport +{ + static NSString *separator = @"\n======================================================================\n"; + NSString *reportMessage; + + if ([messages count]) + { + fprintf (stderr, "%s", [separator UTF8String]); + reportMessage = [messages componentsJoinedByString: separator]; + fprintf (stderr, "%s", [reportMessage UTF8String]); + } + fprintf (stderr, + "\n----------------------------------------------------------------------\n" + "Ran %d tests\n\n", testCount); + if (hasFailed) + fprintf (stderr, "FAILED (%d failures, %d errors)\n", + failuresCount, errorsCount); + else + fprintf (stderr, "OK\n"); +} + +- (BOOL) run +{ + NSArray *methods; + NSString *method; + int count, max; + SEL testMethod; + + methods = GSObjCMethodNames (self); + max = [methods count]; + for (count = 0; count < max; count++) + { + method = [methods objectAtIndex: count]; + if ([method hasPrefix: @"test"] + && [method rangeOfString: @":"].location == NSNotFound) + { + testMethod = NSSelectorFromString (method); + [self performTest: testMethod]; + } + } + + [self displayReport]; + + return YES; +} + +@end diff --git a/UnitTests/sogo-tests.m b/UnitTests/sogo-tests.m new file mode 100644 index 000000000..67c5a4e8a --- /dev/null +++ b/UnitTests/sogo-tests.m @@ -0,0 +1,81 @@ +/* sogo-tests.m - this file is part of SOGo + * + * Copyright (C) 2010 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import + +#import "SOGoTest.h" + +@interface SOGoTestRunner : NSObject +@end + +@implementation SOGoTestRunner + ++ (SOGoTestRunner *) testRunner +{ + SOGoTestRunner *testRunner; + + testRunner = [self new]; + [testRunner autorelease]; + + return testRunner; +} + +- (int) run +{ + NSEnumerator *allTestClasses; + NSString *class; + SOGoTest *test; + NSAutoreleasePool *pool; + int rc; + + rc = 0; + pool = [NSAutoreleasePool currentPool]; + + [self retain]; + allTestClasses = [[SOGoTest allTestClasses] objectEnumerator]; + [allTestClasses retain]; + while ((class = [allTestClasses nextObject])) + { + test = [NSClassFromString (class) new]; + if (![test run]) + rc |= -1; + [pool emptyPool]; + } + [allTestClasses autorelease]; + [self autorelease]; + + return rc; +} + +@end + +int main() +{ + NSAutoreleasePool *pool; + int rc; + + pool = [NSAutoreleasePool new]; + rc = [[SOGoTestRunner testRunner] run]; + [pool release]; + + return rc; +}