diff options
Diffstat (limited to 'DebugUtils')
-rw-r--r-- | DebugUtils/GTMDebugThreadValidation.h | 55 | ||||
-rw-r--r-- | DebugUtils/GTMDebugThreadValidation.m | 38 | ||||
-rw-r--r-- | DebugUtils/GTMDebugThreadValidationTest.m | 110 | ||||
-rw-r--r-- | DebugUtils/GTMMethodCheck.m | 2 | ||||
-rw-r--r-- | DebugUtils/GTMMethodCheckTest.m | 4 |
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 { } |