aboutsummaryrefslogtreecommitdiff
path: root/DebugUtils
diff options
context:
space:
mode:
authorGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-10-22 19:16:19 +0000
committerGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-10-22 19:16:19 +0000
commit11938e47355bfbf3b81f1ff5b15f1222b83d4f47 (patch)
tree3794c78559472e4b2efe5eabc0e094d7c14a9743 /DebugUtils
parent90eba8f973c0b77f36dc7084163ff0d43675a1a8 (diff)
- GTM_INLINE will make sure a function gets inlined, and provides a consistent
way for all GTM code to do it. - Added GTMDebugThreadValidation to allow you to enforce the fact that your code must run in the main thread in DEBUG builds. - Updated some internals of the iPhone unittesting so it doesn't double print the test descriptions, file names, or lines numbers of a test failure line. Also includes the test names in the error output. - Changed the xcconfigs so that know it's easier to set different settings at the different levels and not accidentally overwrite settings set at lower levels in the "settings collapse". Also tightened up warnings significantly. - Changed how gtm_unitTestExposedBindingsTestValues works. If you have an implementation of gtm_unitTestExposedBindingsTestValues in your own code you will need to update to the new way of calling. See implementations in GTMNSObject+BindingUnitTesting.m for details. - Added support for grabbing the build number for a particular OS in GTMSystemVersion and easily comparing it to known build numbers, and switched some types from in GTMSystemVersion from "int" to SInt32 to make 64 bit work better. - Added support for SnowLeopard (10A96). We build cleanly with the 10.6 SDKs and all radar checks were updated accordingly. Build All script was also updated to build on SnowLeopard if you have the SDK available. - Turned off building ppc64 GTM because the SnowLeopard SDK currently doesn't have ppc64 support, so SenTestCase isn't defined. This makes it impossible to build the ppc64 10.5 config on SnowLeopard. We have left the setting in the xcconfig for those of you who need it, but have disabled it in the GTM project settings. - Turned on stack smashing protection on the debug builds for all Leopard and above. - Added ability to easily do leak checking by defining the GTM_ENABLE_LEAKS environment variable. It isn't on by default because several of Apple's frameworks leak. You can work around these false positives by using the GTM_LEAKS_SYMBOLS_TO_IGNORE environment variable. Also if you turn on leaks make sure to turn off zombies by defining the GTM_DISABLE_ZOMBIES variable, otherwise every memory allocation you do will look like a leak.
Diffstat (limited to 'DebugUtils')
-rw-r--r--DebugUtils/GTMDebugThreadValidation.h55
-rw-r--r--DebugUtils/GTMDebugThreadValidation.m38
-rw-r--r--DebugUtils/GTMDebugThreadValidationTest.m110
-rw-r--r--DebugUtils/GTMMethodCheck.m2
-rw-r--r--DebugUtils/GTMMethodCheckTest.m4
5 files changed, 207 insertions, 2 deletions
diff --git a/DebugUtils/GTMDebugThreadValidation.h b/DebugUtils/GTMDebugThreadValidation.h
new file mode 100644
index 0000000..0636159
--- /dev/null
+++ b/DebugUtils/GTMDebugThreadValidation.h
@@ -0,0 +1,55 @@
+//
+// GTMDebugThreadValidation.h
+//
+// Copyright 2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#if DEBUG
+#import "GTMDefines.h"
+#import <Foundation/Foundation.h>
+
+// GTMAssertRunningOnMainThread will allow you to verify that you are
+// currently running on the main thread. This can be useful for checking
+// under DEBUG to make sure that code that requires being run on the main thread
+// is doing so. Use the GTMAssertRunningOnMainThread macro, don't use
+// the _GTMAssertRunningOnMainThread or _GTMIsRunningOnMainThread
+// helper functions.
+
+// On Leopard and above we can just use NSThread functionality.
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+BOOL _GTMIsRunningOnMainThread(void);
+#else // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+#import <Foundation/Foundation.h>
+GTM_INLINE BOOL _GTMIsRunningOnMainThread(void) {
+ return [NSThread isMainThread];
+}
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+
+GTM_INLINE void _GTMAssertRunningOnMainThread(const char *func,
+ const char *file,
+ int lineNum) {
+ _GTMDevAssert(_GTMIsRunningOnMainThread(),
+ @"%s not being run on main thread (%s - %d)",
+ func, file, lineNum);
+}
+
+#define GTMAssertRunningOnMainThread() \
+ (_GTMAssertRunningOnMainThread(__func__, __FILE__, __LINE__))
+
+#else // DEBUG
+
+#define GTMAssertRunningOnMainThread() do { } while (0)
+
+#endif // DEBUG
diff --git a/DebugUtils/GTMDebugThreadValidation.m b/DebugUtils/GTMDebugThreadValidation.m
new file mode 100644
index 0000000..5889cd8
--- /dev/null
+++ b/DebugUtils/GTMDebugThreadValidation.m
@@ -0,0 +1,38 @@
+//
+// GTMDebugThreadValidation.m
+//
+// Copyright 2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+
+#if DEBUG && MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+
+#import "GTMDebugThreadValidation.h"
+
+static NSThread *gGTMMainThread = nil;
+
+static __attribute__((constructor)) void _GTMInitThread(void) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ gGTMMainThread = [NSThread currentThread];
+ [gGTMMainThread retain];
+ [pool release];
+}
+
+
+BOOL _GTMIsRunningOnMainThread(void) {
+ return [[NSThread currentThread] isEqual:gGTMMainThread];
+}
+
+#endif // DEBUG && MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
diff --git a/DebugUtils/GTMDebugThreadValidationTest.m b/DebugUtils/GTMDebugThreadValidationTest.m
new file mode 100644
index 0000000..66bd51b
--- /dev/null
+++ b/DebugUtils/GTMDebugThreadValidationTest.m
@@ -0,0 +1,110 @@
+//
+// GTMDebugThreadValidationTest.m
+// Copyright 2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#import "GTMSenTestCase.h"
+#import "GTMDebugThreadValidation.h"
+
+// GTMDebugThreadValidation only happens on debug builds
+#if DEBUG
+
+@interface GTMDebugThreadValidationTest : GTMTestCase
+@end
+
+// A cheap flag for knowing when our thread has run
+
+static volatile BOOL gGTMDebugThreadValidationTestDone = NO;
+
+// This is an assertion handler that just records that an assertion has fired.
+@interface GTMDebugThreadValidationCheckAssertionHandler : NSAssertionHandler {
+ @private
+ BOOL handledAssertion_;
+}
+- (void)handleFailureInMethod:(SEL)selector
+ object:(id)object
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line
+ description:(NSString *)format,...;
+
+- (void)handleFailureInFunction:(NSString *)functionName
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line
+ description:(NSString *)format,...;
+- (BOOL)didHandleAssertion;
+@end
+
+@implementation GTMDebugThreadValidationTest
+- (void)testOnMainThread {
+ STAssertNoThrow(GTMAssertRunningOnMainThread(), nil);
+}
+
+- (void)threadFunc:(NSMutableString *)result {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ // We'll insert our own assertion handler that will get called on the assert
+ // so that we don't have to worry about the log, and exception being thrown.
+ GTMDebugThreadValidationCheckAssertionHandler *handler =
+ [[[GTMDebugThreadValidationCheckAssertionHandler alloc] init] autorelease];
+ NSMutableDictionary *threadDictionary
+ = [[NSThread currentThread] threadDictionary];
+ [threadDictionary setObject:handler forKey:@"NSAssertionHandler"];
+ GTMAssertRunningOnMainThread();
+ if ([handler didHandleAssertion]) {
+ [result setString:@"ASSERTED"];
+ }
+ [threadDictionary removeObjectForKey:@"NSAssertionHandler"];
+ gGTMDebugThreadValidationTestDone = YES;
+ [pool release];
+}
+
+- (void)testOnOtherThread {
+ NSMutableString *result = [NSMutableString string];
+ gGTMDebugThreadValidationTestDone = NO;
+ [NSThread detachNewThreadSelector:@selector(threadFunc:)
+ toTarget:self
+ withObject:result];
+ NSRunLoop *loop = [NSRunLoop currentRunLoop];
+
+ while (!gGTMDebugThreadValidationTestDone) {
+ NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0.01];
+ [loop runUntilDate:date];
+ }
+ STAssertEqualStrings(result, @"ASSERTED", @"GTMAssertRunningOnMainThread did "
+ @"not assert while running on another thread");
+}
+@end
+
+@implementation GTMDebugThreadValidationCheckAssertionHandler
+
+- (void)handleFailureInMethod:(SEL)selector
+ object:(id)object
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line
+ description:(NSString *)format,... {
+ handledAssertion_ = YES;
+}
+
+- (void)handleFailureInFunction:(NSString *)functionName
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line
+ description:(NSString *)format,... {
+ handledAssertion_ = YES;
+}
+
+- (BOOL)didHandleAssertion {
+ return handledAssertion_;
+}
+@end
+#endif // DEBUG
diff --git a/DebugUtils/GTMMethodCheck.m b/DebugUtils/GTMMethodCheck.m
index ef3ee4a..2f88dc3 100644
--- a/DebugUtils/GTMMethodCheck.m
+++ b/DebugUtils/GTMMethodCheck.m
@@ -76,6 +76,7 @@ void GTMMethodCheckMethodChecker(void) {
// Run through all the classes looking for class methods that are
// prefixed with xxGMMethodCheckMethod. If it finds one, it calls it.
// See GTMMethodCheck.h to see what it does.
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int numClasses = 0;
int newNumClasses = objc_getClassList(NULL, 0);
int i;
@@ -156,6 +157,7 @@ void GTMMethodCheckMethodChecker(void) {
if (classes) {
free(classes);
}
+ [pool release];
}
#endif // DEBUG
diff --git a/DebugUtils/GTMMethodCheckTest.m b/DebugUtils/GTMMethodCheckTest.m
index 7b9fa0c..974dfaf 100644
--- a/DebugUtils/GTMMethodCheckTest.m
+++ b/DebugUtils/GTMMethodCheckTest.m
@@ -25,8 +25,8 @@ static BOOL gTestCheckVar = NO;
@end
@implementation GTMMethodCheckTest
-GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestMethod); // COV_NF_LINE
-GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestClassMethod); // COV_NF_LINE
+GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestMethod);
+GTM_METHOD_CHECK(GTMMethodCheckTest, GTMMethodCheckTestClassMethod);
- (void)GTMMethodCheckTestMethod {
}