├── Resources ├── English.lproj │ └── InfoPlist.strings ├── PLBlockIMP-iOS-Tests-Info.plist ├── PLBlockIMP-iOSimulator-Tests-Info.plist ├── Tests-MacOSX-Info.plist ├── Info.plist └── MainWindow.xib ├── Tools ├── README.txt └── google-toolbox-for-mac-1-5-1 │ ├── UnitTesting │ ├── GTMIPhoneUnitTestMain.m │ ├── GTMIPhoneUnitTestDelegate.h │ ├── GTMIPhoneUnitTestDelegate.m │ ├── GTMSenTestCase.m │ └── GTMSenTestCase.h │ ├── ReleaseNotes.txt │ ├── GTMDefines.h │ └── COPYING ├── LICENSE ├── Source ├── PLBlockIMP.h ├── blockimp.h ├── ARM │ ├── blockimp_arm.tramp │ ├── blockimp_arm_stret.tramp │ └── blockimp_arm64.tramp ├── x86_64 │ ├── blockimp_x86_64.tramp │ └── blockimp_x86_64_stret.tramp ├── x86_32 │ ├── blockimp_x86_32.tramp │ └── blockimp_x86_32_stret.tramp ├── trampoline_table.h ├── blockimp.c ├── blockimp_private.h ├── blockimp_tests.m └── trampoline_table.c ├── README.md └── Other Sources └── gentramp.sh /Resources/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Tools/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains externally maintained build and 2 | testing tools. 3 | 4 | google-toolbox-for-mac-1-5-1: 5 | Apache License 2.0. 6 | 7 | Provides iPhone unit testing. 8 | Downloaded from http://code.google.com/p/google-toolbox-for-mac/ 9 | 10 | Modified as follows: 11 | - Patch GTM to remove use of private -[UIApplication terminate] API. 12 | - Patch GTM to not use the deprecated -[NSString stringWithCString:] 13 | - Remove all sources except for the iPhone unit test harness. 14 | -------------------------------------------------------------------------------- /Resources/PLBlockIMP-iOS-Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.yourcompany.PLBlockIMPiOSTests 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | NSMainNibFile 20 | MainWindow 21 | 22 | 23 | -------------------------------------------------------------------------------- /Resources/PLBlockIMP-iOSimulator-Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.yourcompany.PLBlockIMPiOSTests 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | NSMainNibFile 20 | MainWindow 21 | 22 | 23 | -------------------------------------------------------------------------------- /Resources/Tests-MacOSX-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.yourcompany.${PRODUCT_NAME:rfc1034Identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Author: Landon Fuller 2 | 3 | Copyright 2010-2011 Plausible Labs Cooperative, Inc. 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, 7 | to any person obtaining a copy of this software and associated documentation 8 | files (the "Software"), to deal in the Software without restriction, 9 | including without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to permit 11 | persons to whom the Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /Tools/google-toolbox-for-mac-1-5-1/UnitTesting/GTMIPhoneUnitTestMain.m: -------------------------------------------------------------------------------- 1 | // 2 | // GTMIPhoneUnitTestMain.m 3 | // 4 | // Copyright 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 "GTMDefines.h" 20 | #if !GTM_IPHONE_SDK 21 | #error GTMIPhoneUnitTestMain for iPhone only 22 | #endif 23 | #import 24 | 25 | // Creates an application that runs all tests from classes extending 26 | // SenTestCase, outputs results and test run time, and terminates right 27 | // afterwards. 28 | int main(int argc, char *argv[]) { 29 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 30 | int retVal = UIApplicationMain(argc, argv, nil, @"GTMIPhoneUnitTestDelegate"); 31 | [pool release]; 32 | return retVal; 33 | } 34 | -------------------------------------------------------------------------------- /Source/PLBlockIMP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #pragma once 28 | #include "blockimp.h" -------------------------------------------------------------------------------- /Tools/google-toolbox-for-mac-1-5-1/UnitTesting/GTMIPhoneUnitTestDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // GTMIPhoneUnitTestDelegate.h 3 | // 4 | // Copyright 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 20 | 21 | // Application delegate that runs all test methods in registered classes 22 | // extending SenTestCase. The application is terminated afterwards. 23 | // You can also run the tests directly from your application by invoking 24 | // gtm_runTests and clean up, restore data, etc. before the application 25 | // terminates. 26 | @interface GTMIPhoneUnitTestDelegate : NSObject 27 | // Runs through all the registered classes and runs test methods on any 28 | // that are subclasses of SenTestCase. Prints results and run time to 29 | // the default output. 30 | - (BOOL)runTests; 31 | @end 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PLBlockIMP 2 | ----------- 3 | 4 | 5 | PLBlockIMP provides an open-source implementation of [imp_implementationWithBlock()](http://www.friday.com/bbum/2011/03/17/ios-4-3-imp_implementationwithblock/), using 6 | vm_remap()-based trampolines as described in [Implementing imp_implementationWithBlock](http://landonf.bikemonkey.org/code/objc/imp_implementationWithBlock.20110413.html). 7 | 8 | PLBlockIMP will generate a lightweight, high-performance function pointer trampoline that may be used to register a block as an Objective-C method implementation. Mac OS X 10.6+ and 9 | iOS 4.0+ are supported. 10 | 11 | Additionally, PLBlockIMP contains a generic trampoline allocator and set of generator scripts that may be used to implement custom trampoline pages on Mac OS X and iOS. 12 | 13 | PLBlockIMP is released under the MIT license. 14 | 15 | Sample Use 16 | ----------- 17 | 18 | Use a block to add a new method to NSObject (based on Mike Ash's MABlockClosure example): 19 | 20 | int captured = 42; 21 | id block = ^(id self) { NSLog(@"captured is %d", captured); }; 22 | block = [block copy]; 23 | class_addMethod([NSObject class], @selector(my_printCaptured), pl_imp_implementationWithBlock(block), "v@:"); 24 | 25 | Additionally, pl_imp_getBlock() may be used to fetch the block associated with an IMP trampoline, and pl_imp_removeBlock() to discard a trampoline 26 | and its associated block reference. 27 | -------------------------------------------------------------------------------- /Source/blockimp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | extern IMP pl_imp_implementationWithBlock(void *block); 30 | extern void *pl_imp_getBlock(IMP anImp); 31 | extern BOOL pl_imp_removeBlock(IMP anImp); -------------------------------------------------------------------------------- /Source/ARM/blockimp_arm.tramp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # Copyright (c) 2010-2011, Plausible Labs Cooperative, Inc. 5 | # All Rights Reserved. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # ``Software''), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | # DEALINGS IN THE SOFTWARE. 26 | # ----------------------------------------------------------------------- 27 | 28 | # Supported architectures 29 | check_architecture () { 30 | case "$1" in 31 | armv6) 32 | return 1 33 | ;; 34 | armv7) 35 | return 1 36 | ;; 37 | armv7s) 38 | return 1 39 | ;; 40 | *) 41 | return 0 42 | ;; 43 | esac 44 | } 45 | 46 | # Page size 47 | PAGE_SIZE="4096" 48 | 49 | # The name of this page 50 | PAGE_NAME=pl_blockimp_table_page 51 | 52 | # Prefix to be placed at the start of the trampoline page 53 | trampoline_prefix () { 54 | asm << 'EOF' 55 | _block_tramp_dispatch: 56 | # trampoline address+8 is in r12 -- calculate our config page address 57 | sub r12, #0x8 58 | sub r12, #0x1000 59 | 60 | # Set the 'self' argument as the second argument 61 | mov r1, r0 62 | 63 | # Load the block pointer as the first argument 64 | ldr r0, [r12] 65 | 66 | # Jump to the block pointer 67 | ldr pc, [r0, #0xc] 68 | EOF 69 | } 70 | 71 | # Generate a single trampoline 72 | trampoline () { 73 | asm << 'EOF' 74 | # Save pc+8, then jump to the shared prefix implementation 75 | mov r12, pc 76 | b _block_tramp_dispatch; 77 | EOF 78 | } -------------------------------------------------------------------------------- /Source/ARM/blockimp_arm_stret.tramp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # Copyright (c) 2010-2011, Plausible Labs Cooperative, Inc. 5 | # All Rights Reserved. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # ``Software''), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | # DEALINGS IN THE SOFTWARE. 26 | # ----------------------------------------------------------------------- 27 | 28 | # Supported architectures 29 | check_architecture () { 30 | case "$1" in 31 | armv6) 32 | return 1 33 | ;; 34 | armv7) 35 | return 1 36 | ;; 37 | armv7s) 38 | return 1 39 | ;; 40 | *) 41 | return 0 42 | ;; 43 | esac 44 | } 45 | 46 | # Page size 47 | PAGE_SIZE="4096" 48 | 49 | # The name of this page 50 | PAGE_NAME=pl_blockimp_table_stret_page 51 | 52 | # Prefix to be placed at the start of the trampoline page 53 | trampoline_prefix () { 54 | asm << 'EOF' 55 | _block_tramp_dispatch: 56 | # trampoline address+8 is in r12 -- calculate our config page address 57 | sub r12, #0x8 58 | sub r12, #0x1000 59 | 60 | # Set the 'self' argument as the third argument 61 | mov r2, r1 62 | 63 | # Load the block pointer as the second argument 64 | ldr r1, [r12] 65 | 66 | # Jump to the block pointer 67 | ldr pc, [r1, #0xc] 68 | EOF 69 | } 70 | 71 | # Generate a single trampoline 72 | trampoline () { 73 | asm << 'EOF' 74 | # Save pc+8, then jump to the shared prefix implementation 75 | mov r12, pc 76 | b _block_tramp_dispatch; 77 | EOF 78 | } -------------------------------------------------------------------------------- /Source/ARM/blockimp_arm64.tramp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # Copyright (c) 2010-2013, Plausible Labs Cooperative, Inc. 5 | # All Rights Reserved. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # ``Software''), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | # DEALINGS IN THE SOFTWARE. 26 | # ----------------------------------------------------------------------- 27 | 28 | # Supported architectures 29 | check_architecture () { 30 | case $1 in 31 | arm64) 32 | return 1 33 | ;; 34 | *) 35 | return 0 36 | ;; 37 | esac 38 | } 39 | 40 | # Page size 41 | PAGE_SIZE="16384" 42 | 43 | # The name of this page 44 | PAGE_NAME=pl_blockimp_table_page 45 | 46 | # Prefix to be placed at the start of the trampoline page 47 | trampoline_prefix () { 48 | asm << 'EOF' 49 | _block_tramp_dispatch: 50 | # trampoline address+8 is in lr -- calculate our config page address 51 | sub x12, lr, #0x8 52 | sub x12, x12, #0x4000 53 | 54 | # restore the link register 55 | mov lr, x13 56 | 57 | # Set the 'self' argument as the second argument 58 | mov x1, x0 59 | 60 | # Load the block pointer as the first argument 61 | ldr x0, [x12] 62 | 63 | # Jump to the block pointer 64 | ldr x13, [x0, #0x10] 65 | br x13 66 | EOF 67 | } 68 | 69 | # Generate a single trampoline 70 | trampoline () { 71 | asm << 'EOF' 72 | # Save lr, then jump to the shared prefix implementation 73 | mov x13, lr 74 | bl _block_tramp_dispatch; 75 | // pad out to 16 bytes (the size of our config entries) 76 | nop 77 | nop 78 | EOF 79 | } -------------------------------------------------------------------------------- /Source/x86_64/blockimp_x86_64.tramp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # Copyright (c) 2010-2011, Plausible Labs Cooperative, Inc. 5 | # All Rights Reserved. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # ``Software''), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | # DEALINGS IN THE SOFTWARE. 26 | # ----------------------------------------------------------------------- 27 | 28 | # Supported architectures 29 | check_architecture () { 30 | case $1 in 31 | x86_64) 32 | return 1 33 | ;; 34 | *) 35 | return 0 36 | ;; 37 | esac 38 | } 39 | 40 | # Page size 41 | PAGE_SIZE="4096" 42 | 43 | # The name of this page 44 | PAGE_NAME=pl_blockimp_table_page 45 | 46 | # Prefix to be placed at the start of the trampoline page 47 | trampoline_prefix () { 48 | asm << 'EOF' 49 | _block_tramp_dispatch: 50 | pop %r11 51 | and $0xfffffffffffffff8, %r11 // truncate to the trampoline start (each is 8 bytes) 52 | sub $0x1000, %r11 // load the config location 53 | 54 | // Move 'self' to the second parameter, overwriting IMP 55 | movq %rdi, %rsi 56 | 57 | // Load the block reference from the config page, and move to the first parameter 58 | movq (%r11), %rdi 59 | 60 | // Jump to the block fptr 61 | jmp *0x10(%rdi) 62 | .align 4 // align the trampolines at 16 bytes (required for config page lookup and sizing) 63 | EOF 64 | } 65 | 66 | # Generate a single trampoline 67 | trampoline () { 68 | asm << 'EOF' 69 | // Call into the dispatcher, placing our return address on the stack. 70 | call _block_tramp_dispatch # 5 bytes 71 | .align 4 // align the trampolines at 16 bytes (required for config page lookup and sizing) 72 | EOF 73 | } -------------------------------------------------------------------------------- /Source/x86_32/blockimp_x86_32.tramp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # Copyright (c) 2010-2011, Plausible Labs Cooperative, Inc. 5 | # All Rights Reserved. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # ``Software''), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | # DEALINGS IN THE SOFTWARE. 26 | # ----------------------------------------------------------------------- 27 | 28 | # Supported architectures 29 | check_architecture () { 30 | case $1 in 31 | i386) 32 | return 1 33 | ;; 34 | *) 35 | return 0 36 | ;; 37 | esac 38 | } 39 | 40 | # Page size 41 | PAGE_SIZE="4096" 42 | 43 | # The name of this page 44 | PAGE_NAME=pl_blockimp_table_page 45 | 46 | # Prefix to be placed at the start of the trampoline page 47 | trampoline_prefix () { 48 | asm << 'EOF' 49 | _block_tramp_dispatch: 50 | pop %eax 51 | andl $0xfffffff8, %eax // truncate to the trampoline start (each is 8 bytes) 52 | subl $0x1000, %eax // load the config location 53 | 54 | // Move 'self' to the second parameter, overwriting IMP 55 | movl 0x4(%esp), %ecx 56 | movl %ecx, 0x8(%esp) 57 | 58 | // Load the block reference from the config page, insert as the first parameter 59 | movl (%eax), %eax 60 | movl %eax, 0x4(%esp) 61 | 62 | // Jump to the block fptr 63 | jmp *0xc(%eax) 64 | 65 | .align 3 // align the trampolines at 8 bytes 66 | 67 | EOF 68 | } 69 | 70 | # Generate a single trampoline 71 | trampoline () { 72 | asm << 'EOF' 73 | 74 | # Call into the dispatcher, placing our return address on the stack. 75 | calll _block_tramp_dispatch # 5 bytes 76 | .align 3 // align the trampolines at 8 bytes 77 | EOF 78 | } -------------------------------------------------------------------------------- /Source/x86_32/blockimp_x86_32_stret.tramp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # Copyright (c) 2010-2011, Plausible Labs Cooperative, Inc. 5 | # All Rights Reserved. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # ``Software''), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | # DEALINGS IN THE SOFTWARE. 26 | # ----------------------------------------------------------------------- 27 | 28 | # Supported architectures 29 | check_architecture () { 30 | case $1 in 31 | i386) 32 | return 1 33 | ;; 34 | *) 35 | return 0 36 | ;; 37 | esac 38 | } 39 | 40 | # Page size 41 | PAGE_SIZE="4096" 42 | 43 | # The name of this page 44 | PAGE_NAME=pl_blockimp_table_stret_page 45 | 46 | # Prefix to be placed at the start of the trampoline page 47 | trampoline_prefix () { 48 | asm << 'EOF' 49 | _block_tramp_dispatch: 50 | pop %eax 51 | andl $0xfffffff8, %eax // truncate to the trampoline start (each is 8 bytes) 52 | subl $0x1000, %eax // load the config location 53 | 54 | // Move 'self' to the third parameter, overwriting IMP 55 | movl 0x8(%esp), %ecx 56 | movl %ecx, 0xc(%esp) 57 | 58 | // Load the block reference from the config page, insert as the second parameter 59 | movl (%eax), %eax 60 | movl %eax, 0x8(%esp) 61 | 62 | // Jump to the block fptr 63 | jmp *0xc(%eax) 64 | 65 | .align 3 // align the trampolines at 8 bytes 66 | EOF 67 | } 68 | 69 | # Generate a single trampoline 70 | trampoline () { 71 | asm << 'EOF' 72 | 73 | # Call into the dispatcher, placing our return address on the stack. 74 | calll _block_tramp_dispatch # 5 bytes 75 | .align 3 // align the trampolines at 8 bytes 76 | 77 | EOF 78 | } -------------------------------------------------------------------------------- /Source/x86_64/blockimp_x86_64_stret.tramp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # Copyright (c) 2010-2011, Plausible Labs Cooperative, Inc. 5 | # All Rights Reserved. 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # ``Software''), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included 16 | # in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | # DEALINGS IN THE SOFTWARE. 26 | # ----------------------------------------------------------------------- 27 | 28 | # Supported architectures 29 | check_architecture () { 30 | case $1 in 31 | x86_64) 32 | return 1 33 | ;; 34 | *) 35 | return 0 36 | ;; 37 | esac 38 | } 39 | 40 | # Page size 41 | PAGE_SIZE="4096" 42 | 43 | # The name of this page 44 | PAGE_NAME=pl_blockimp_table_stret_page 45 | 46 | # Prefix to be placed at the start of the trampoline page 47 | trampoline_prefix () { 48 | asm << 'EOF' 49 | _block_tramp_dispatch: 50 | pop %r11 51 | and $0xfffffffffffffff8, %r11 // truncate to the trampoline start (each is 8 bytes) 52 | sub $0x1000, %r11 // load the config location 53 | 54 | // Move 'self' to the third parameter, overwriting IMP 55 | movq %rsi, %rdx 56 | 57 | // Load the block reference from the config page, and move to the second parameter 58 | movq (%r11), %rsi 59 | 60 | // Jump to the block fptr 61 | jmp *0x10(%rsi) 62 | .align 4 // align the trampolines at 16 bytes (required for config page lookup and sizing) 63 | EOF 64 | } 65 | 66 | # Generate a single trampoline 67 | trampoline () { 68 | asm << 'EOF' 69 | // Call into the dispatcher, placing our return address on the stack. 70 | call _block_tramp_dispatch # 5 bytes 71 | .align 4 // align the trampolines at 16 bytes (required for config page lookup and sizing) 72 | EOF 73 | } -------------------------------------------------------------------------------- /Source/trampoline_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #ifdef PL_BLOCKIMP_PRIVATE 30 | 31 | #include 32 | #include 33 | 34 | typedef struct pl_trampoline_table pl_trampoline_table; 35 | typedef struct pl_trampoline pl_trampoline; 36 | 37 | /* 38 | * Trampoline table configuration 39 | */ 40 | typedef struct pl_trampoline_table_config { 41 | /* The trampoline size */ 42 | uint32_t trampoline_size; 43 | 44 | /* The page offset at which the trampolines are located. */ 45 | uint32_t page_offset; 46 | 47 | /* The number of trampolines allocated per page. */ 48 | uint32_t trampoline_count; 49 | 50 | /** The template code page. */ 51 | void *template_page; 52 | } pl_trampoline_table_config; 53 | 54 | /* 55 | * A double-linked list of trampoline table entries. 56 | */ 57 | struct pl_trampoline_table { 58 | /* Table configuration */ 59 | pl_trampoline_table_config *config; 60 | 61 | /* Contigious writable and executable pages */ 62 | vm_address_t data_page; 63 | vm_address_t trampoline_page; 64 | 65 | /* free list tracking */ 66 | uint16_t free_count; 67 | pl_trampoline *free_list; 68 | pl_trampoline *free_list_pool; 69 | 70 | pl_trampoline_table *prev; 71 | pl_trampoline_table *next; 72 | }; 73 | 74 | /* 75 | * A linked list of trampoline table entries. 76 | */ 77 | struct pl_trampoline { 78 | /* The actual trampoline. */ 79 | void *(*trampoline)(); 80 | 81 | /** The table in which the entry is allocated. */ 82 | pl_trampoline_table *table; 83 | 84 | /* Next entry in the trampoline list. */ 85 | pl_trampoline *next; 86 | }; 87 | 88 | pl_trampoline *pl_trampoline_alloc (pl_trampoline_table_config *config, pthread_mutex_t *lock, pl_trampoline_table **table_head); 89 | void pl_trampoline_free (pthread_mutex_t *lock, pl_trampoline_table **table_head, pl_trampoline *tramp); 90 | void *pl_trampoline_data_ptr (void *code_ptr); 91 | 92 | #endif /* PL_BLOCKIMP_PRIVATE */ -------------------------------------------------------------------------------- /Source/blockimp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "blockimp.h" 28 | #include "blockimp_private.h" 29 | 30 | #include "trampoline_table.h" 31 | 32 | #include 33 | #include 34 | 35 | /* The ARM64 ABI does not require (or support) the _stret objc_msgSend variant */ 36 | #ifdef __arm64__ 37 | #define STRET_TABLE_REQUIRED 0 38 | #define STRET_TABLE_CONFIG pl_blockimp_table_page_config 39 | #define STRET_TABLE blockimp_table 40 | #else 41 | #define STRET_TABLE_REQUIRED 1 42 | #define STRET_TABLE_CONFIG pl_blockimp_table_page_config 43 | #define STRET_TABLE blockimp_table_stret 44 | #endif 45 | 46 | #pragma mark Trampolines 47 | 48 | /* Global lock for our mutable state. Must be held when accessing the trampoline tables. */ 49 | static pthread_mutex_t blockimp_lock = PTHREAD_MUTEX_INITIALIZER; 50 | 51 | /* Trampoline tables for objc_msgSend() dispatch. */ 52 | static pl_trampoline_table *blockimp_table = NULL; 53 | 54 | #if STRET_TABLE_REQUIRED 55 | /* Trampoline tables for objc_msgSend_stret() dispatch. */ 56 | static pl_trampoline_table *blockimp_table_stret = NULL; 57 | #endif /* STRET_TABLE_REQUIRED */ 58 | 59 | /** 60 | * 61 | */ 62 | IMP pl_imp_implementationWithBlock (void *block) { 63 | #if SUPPORT_APPLE_FALLBACK 64 | /* Prefer Apple's implementation */ 65 | if (&imp_implementationWithBlock != NULL) 66 | return imp_implementationWithBlock(block); 67 | #endif 68 | 69 | /* Allocate the appropriate trampoline type. */ 70 | pl_trampoline *tramp; 71 | struct Block_layout *bl = block; 72 | if (bl->flags & BLOCK_USE_STRET) { 73 | tramp = pl_trampoline_alloc(&STRET_TABLE_CONFIG, &blockimp_lock, &STRET_TABLE); 74 | } else { 75 | tramp = pl_trampoline_alloc(&pl_blockimp_table_page_config, &blockimp_lock, &blockimp_table); 76 | } 77 | 78 | /* Configure the trampoline */ 79 | void **config = pl_trampoline_data_ptr(tramp->trampoline); 80 | config[0] = Block_copy(block); 81 | config[1] = tramp; 82 | 83 | /* Return the function pointer. */ 84 | return (IMP) tramp->trampoline; 85 | } 86 | 87 | /** 88 | * 89 | */ 90 | void *pl_imp_getBlock(IMP anImp) { 91 | #if SUPPORT_APPLE_FALLBACK 92 | /* Prefer Apple's implementation */ 93 | if (&imp_getBlock != NULL) { 94 | return imp_getBlock(anImp); 95 | } 96 | #endif 97 | 98 | /* Fetch the config data and return the block reference. */ 99 | void **config = pl_trampoline_data_ptr(anImp); 100 | return config[0]; 101 | } 102 | 103 | /** 104 | * 105 | */ 106 | BOOL pl_imp_removeBlock(IMP anImp) { 107 | #if SUPPORT_APPLE_FALLBACK 108 | /* Prefer Apple's implementation */ 109 | if (&imp_removeBlock != NULL) 110 | return imp_removeBlock(anImp); 111 | #endif 112 | 113 | /* Fetch the config data */ 114 | void **config = pl_trampoline_data_ptr(anImp); 115 | struct Block_layout *bl = config[0]; 116 | pl_trampoline *tramp = config[1]; 117 | 118 | /* Drop the trampoline allocation */ 119 | if (bl->flags & BLOCK_USE_STRET) { 120 | pl_trampoline_free(&blockimp_lock, &STRET_TABLE, tramp); 121 | } else { 122 | pl_trampoline_free(&blockimp_lock, &blockimp_table, tramp); 123 | } 124 | 125 | /* Release the block */ 126 | Block_release(config[0]); 127 | 128 | // TODO - what does this return value mean? 129 | return YES; 130 | } -------------------------------------------------------------------------------- /Source/blockimp_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Private Block ABI Structures 3 | * Originally acquired frm PLBlocks and compiler_rt 4 | * 5 | * Copyright 2008 - 2009 Apple, Inc. 6 | * Copyright 2009 - 2011 Plausible Labs Cooperative, Inc. 7 | * 8 | * Permission is hereby granted, free of charge, 9 | * to any person obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without restriction, 11 | * including without limitation the rights to use, copy, modify, merge, publish, 12 | * distribute, sublicense, and/or sell copies of the Software, and to permit 13 | * persons to whom the Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | * 27 | */ 28 | 29 | #pragma once 30 | 31 | #if defined(__i386__) 32 | # include "blockimp_x86_32.h" 33 | # include "blockimp_x86_32_stret.h" 34 | #elif defined(__x86_64__) 35 | # include "blockimp_x86_64.h" 36 | # include "blockimp_x86_64_stret.h" 37 | #elif defined(__arm__) 38 | # include "blockimp_arm.h" 39 | # include "blockimp_arm_stret.h" 40 | #elif defined(__arm64__) 41 | # include "blockimp_arm64.h" 42 | #else 43 | # error Unknown Architecture 44 | #endif 45 | 46 | #pragma mark Fallback Support 47 | 48 | // if 1, we attempt to use Apple's official implementations 49 | #define SUPPORT_APPLE_FALLBACK 0 50 | #if SUPPORT_APPLE_FALLBACK 51 | extern IMP imp_implementationWithBlock(void *block) WEAK_IMPORT_ATTRIBUTE; 52 | extern void *imp_getBlock(IMP anImp) WEAK_IMPORT_ATTRIBUTE; 53 | extern BOOL imp_removeBlock(IMP anImp) WEAK_IMPORT_ATTRIBUTE; 54 | #endif 55 | 56 | /* 57 | * Block Flags 58 | */ 59 | typedef enum { 60 | /** 16-bit block reference count. */ 61 | BLOCK_REFCOUNT_MASK = (0xffff), 62 | 63 | BLOCK_NEEDS_FREE = (1 << 24), 64 | BLOCK_HAS_COPY_DISPOSE = (1 << 25), 65 | 66 | /** Helpers have C++ code. */ 67 | BLOCK_HAS_CTOR = (1 << 26), 68 | 69 | BLOCK_IS_GC = (1 << 27), 70 | BLOCK_IS_GLOBAL = (1 << 28), 71 | 72 | /** Block returns its aggregate value in memory (ie, the block has a structure return type). */ 73 | BLOCK_USE_STRET = (1 << 29), 74 | } block_flags_t; 75 | 76 | 77 | /* 78 | * Block field flags. 79 | */ 80 | typedef enum { 81 | // see function implementation for a more complete description of these fields and combinations 82 | BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ... 83 | BLOCK_FIELD_IS_BLOCK = 7, // a block variable 84 | BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable 85 | BLOCK_FIELD_IS_WEAK = 16, // declared __weak, only used in byref copy helpers 86 | BLOCK_BYREF_CALLER = 128, // called from __block (byref) copy/dispose support routines. 87 | } block_field_flags_t; 88 | 89 | /* 90 | * Block description. 91 | * 92 | * Block descriptions are shared across all instances of a block, and 93 | * provide basic information on the block size, as well as pointers 94 | * to any helper functions necessary to copy or dispose of the block. 95 | */ 96 | struct Block_descriptor { 97 | /** Reserved value */ 98 | unsigned long int reserved; 99 | 100 | /** Total size of the described block, including imported variables. */ 101 | unsigned long int size; 102 | 103 | /** Optional block copy helper. May be NULL. */ 104 | void (*copy)(void *dst, void *src); 105 | 106 | /** Optional block dispose helper. May be NULL. */ 107 | void (*dispose)(void *); 108 | }; 109 | 110 | 111 | /* 112 | * Block instance. 113 | * 114 | * The block layout defines the per-block instance state, which includes 115 | * a reference to the shared block descriptor. 116 | * 117 | * The block's imported variables are allocated following the block 118 | * descriptor member. 119 | */ 120 | struct Block_layout { 121 | /** Pointer to the block's Objective-C class. */ 122 | void *isa; 123 | 124 | /** Block flags. */ 125 | int flags; 126 | 127 | /** Reserved value. */ 128 | int reserved; 129 | 130 | /** Block invocation function. */ 131 | void (*invoke)(void *, ...); 132 | 133 | /** Shared block descriptor. */ 134 | struct Block_descriptor *descriptor; 135 | 136 | // imported variables 137 | }; -------------------------------------------------------------------------------- /Source/blockimp_tests.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #import "GTMSenTestCase.h" 28 | #import "blockimp.h" 29 | 30 | @interface BlockIMPTests : SenTestCase @end 31 | 32 | /** 33 | * BlockIMP Tests 34 | */ 35 | @implementation BlockIMPTests 36 | 37 | /** 38 | * Test basic IMP allocation and execution. 39 | */ 40 | - (void) testAllocateIMP { 41 | /* A test block */ 42 | __block BOOL didRun = NO; 43 | void (^Block)(id self) = ^(id blockself) { 44 | didRun = YES; 45 | 46 | STAssertEqualObjects(blockself, self, @"Incorrect 'self' pointer"); 47 | }; 48 | 49 | /* Create the IMP */ 50 | IMP imp = pl_imp_implementationWithBlock(Block); 51 | STAssertTrue(imp != NULL, @"Returned NULL IMP"); 52 | 53 | /* Verify the IMP is valid. */ 54 | void (*ptr)(id self, SEL _cmd) = (void *) imp; 55 | ptr(self, @selector(testAllocateIMP)); 56 | STAssertTrue(didRun, @"Block was not run"); 57 | 58 | /* Clean up */ 59 | pl_imp_removeBlock(imp); 60 | } 61 | 62 | /** 63 | * Test basic stret IMP allocation and execution. 64 | */ 65 | - (void) testAllocateStretIMP { 66 | /* A test block */ 67 | __block BOOL didRun = NO; 68 | NSRange (^Block)(id self) = ^NSRange (id blockself) { 69 | didRun = YES; 70 | 71 | STAssertEqualObjects(blockself, self, @"Incorrect 'self' pointer"); 72 | return NSMakeRange(42, 1); 73 | }; 74 | 75 | /* Create the IMP */ 76 | IMP imp = pl_imp_implementationWithBlock(Block); 77 | STAssertTrue(imp != NULL, @"Returned NULL IMP"); 78 | 79 | /* Verify the IMP is valid. */ 80 | NSRange (*ptr)(id self, SEL _cmd) = (void *) imp; 81 | NSRange result = ptr(self, @selector(testAllocateStretIMP)); 82 | 83 | STAssertTrue(didRun, @"Block was not run"); 84 | STAssertEquals(result.location, (NSUInteger)42, @"Incorrect location"); 85 | STAssertEquals(result.length, (NSUInteger)1, @"Incorrect length"); 86 | 87 | /* Clean up */ 88 | pl_imp_removeBlock(imp); 89 | } 90 | 91 | /** 92 | * Test fetching of the Block ptr from the IMP pointer. 93 | */ 94 | - (void) testGetBlock { 95 | /* A test block */ 96 | void (^Block)(id self) = [[^(id blockself) { 97 | STAssertEqualObjects(blockself, self, @"Incorrect 'self' pointer"); 98 | } copy] autorelease]; 99 | 100 | /* Create the IMP */ 101 | IMP imp = pl_imp_implementationWithBlock(Block); 102 | STAssertTrue(imp != NULL, @"Returned NULL IMP"); 103 | 104 | /* Try to fetch the underlying block */ 105 | void *b = pl_imp_getBlock(imp); 106 | STAssertEquals(b, (void *) Block, @"Did not fetch block"); 107 | 108 | /* Clean up */ 109 | pl_imp_removeBlock(imp); 110 | } 111 | 112 | /** 113 | * Exercise block allocation 114 | */ 115 | - (void) testAllocationExcercise { 116 | /* A test block */ 117 | __block int callCount = 0; 118 | void (^Block)(id self) = [[^(id blockself) { 119 | callCount++; 120 | STAssertEqualObjects(blockself, self, @"Incorrect 'self' pointer"); 121 | } copy] autorelease]; 122 | 123 | /* Use a count larger than what a single page (on any architecture) can likely hold */ 124 | int count=PAGE_SIZE*2; 125 | 126 | /* Generate the IMPs */ 127 | IMP *imps = malloc(sizeof(IMP) * count); 128 | for (int i = 0; i < count; i++) { 129 | imps[i] = pl_imp_implementationWithBlock(Block); 130 | } 131 | 132 | /* Call the IMPs */ 133 | for (int i = 0; i < count; i++) { 134 | void (*ptr)(id self, SEL _cmd) = (void *) imps[i]; 135 | ptr(self, @selector(testAllocationExcercise)); 136 | } 137 | 138 | /* Clean up the IMPs. We do this in reverse to exercise table reordering. */ 139 | for (int i = count-1; i+1 >= 1; i--) { 140 | pl_imp_removeBlock(imps[i]); 141 | } 142 | free(imps); 143 | 144 | /* Verify the result */ 145 | STAssertEquals(callCount, count, @"Call count does not match expected count; not all IMPs were called"); 146 | } 147 | 148 | @end 149 | -------------------------------------------------------------------------------- /Tools/google-toolbox-for-mac-1-5-1/ReleaseNotes.txt: -------------------------------------------------------------------------------- 1 | Google Toolbox for Mac Release Notes 2 | 3 | Project site: http://code.google.com/p/google-toolbox-for-mac/ 4 | Discussion group: http://groups.google.com/group/google-toolbox-for-mac 5 | 6 | Release 1.5.1 7 | Changes since 1.5.0 8 | 16-June-2008 9 | 10 | - Fixed building tiger gcov w/ a directory path that contains a space. 11 | 12 | 13 | Release 1.5.0 14 | Changes since 1.0.0 15 | 13-June-2008 16 | 17 | - Updated the project to Xcode 3. This is the only supported Xcode version 18 | for the project. The code can build against the Tiger or Leopard SDKs, and 19 | developers can pull individual files into a Xcode 2.x project and things 20 | should work just fine. 21 | 22 | - Fixed up the prefix header of the project and prefix handing in the Unittest 23 | Xcode Config. (thanks schafdog) 24 | 25 | - Fixed error in handling default compression for NSData+zlib 26 | 27 | - Changed name on API in NSString+XML and added another api to make this a 28 | litte more clear. (thanks Kent) 29 | 30 | - GTMRegex 31 | - Found and fixed a bug in the enumerators that was causing them to 32 | incorrectly walk a string when using '^' in an expression. 33 | - Added helpers for substring tests and unittests for the new apis. 34 | - Added initializer that takes an outError to allow the collection of any 35 | pattern parsing error message (in case the pattern came from a user and 36 | complete error information is needed to message the user). 37 | 38 | - Added GTMScriptRunner for spawning scripts. 39 | 40 | - Added GTMNSFileManager+Path for two small helpers. 41 | 42 | - Added GTMNSWorkspace+ScreenSaver 43 | 44 | - Added GTMNSString+Data 45 | 46 | - added a common header (GTMDefines) for any common defines so the conditionals 47 | are all in one place 48 | 49 | - Support for things compiling against the iPhone SDK 50 | - Everything in the GTMiPhone project works in the iPhone 51 | - Added iPhone xcconfig files 52 | - Added iPhone unittests (See below) 53 | 54 | - More work on the UI unittests 55 | - support pretty much any part of a UI 56 | - support for CALayers 57 | - full support for the iPhone 58 | - the iPhone uses the same macro set at OCUnit, but has its own runtime 59 | for running tests. 60 | - extended capabilities of UIUnitTesting to be more flexible and give better 61 | error reporting for states. 62 | 63 | - Renamed the actual framework to "GoogleToolboxForMac.framework" (it should 64 | have matched the project on code.google.com from the start) 65 | 66 | - added a Debug-gcov target that will product debug bits w/ code coverage 67 | support to check unittests, etc. 68 | 69 | - GTMDebugSelectorValidation to provide something to include in class impls 70 | to get validation of object/selector pair(s) being implemented so you don't 71 | have to wait for a runtime invocation failures. (especially useful for 72 | things that take a success and failure selector so one doesn't always get 73 | called) 74 | 75 | - added _GTMDevLog (really in GTMDefines) that are a set of macros that can be 76 | used for logging. This allows any project to redefine them to direct logging 77 | into its runtime needs. 78 | 79 | - Moved GTMGeometryUtils into Foundation from AppKit 80 | 81 | - Removed several HI* calls from GTMGeometryUtils as Carbon UI in general is 82 | deprecated. 83 | 84 | - Xcode configs 85 | - changed the layout to make it a little easier to tell how to use them. 86 | - added Leopard or later configs 87 | 88 | - Unittest coverage greatly increased 89 | 90 | - Added RunMacOSUnitTests shell script. We run this script for starting up our 91 | unittests because it turns on a variety of "enhancements" (such as zombies, 92 | scribbling etc) to encourage our unittests to fail for us. It also will run 93 | the unittests using the _debug frameworks if you have them. 94 | 95 | https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=19915 96 | 97 | - Remove NSColor+Theme and NSWorkspace+Theme as they are no longer needed for 98 | testing things for unittests, instead GTMUnitTestingUtilities.m(Lines 64-79) 99 | force the user settable things to ensure tests are consistent. 100 | 101 | - Added GTMBase64. 102 | 103 | - Added GTMHTTPFetcher and GTMProgressMonitorInputStream. 104 | 105 | - Moved the data files for unittests into subdirectories call TestData to 106 | help make it a little easier to find files w/in the main directories. 107 | 108 | - GTMDelegatingTableColumn get an overhaul to match the 10.5 sdk so it's closer 109 | to a dropin for previous sdks. 110 | 111 | - Added a lot of functionality to NSAppleEventDescriptor and NSAppleScript 112 | allowing you to easily call labeled and positional handlers in an AppleScript, 113 | get/set properties and get NSAppleEventDescriptors for most basic datatypes. 114 | 115 | - Added GTMFourCharCode for wrapping FourCharCodes in an ObjC object. Mainly for 116 | use by the NSAppleEventDescriptor code, and also useful for storing them 117 | in ObjC collection classes. 118 | 119 | - Added GTMStackTrace. 120 | 121 | - Added NSString+URLArguments and NSDictionary+URLArguments 122 | 123 | - Added GTMHTTPServer as a simple server but mainly for use in unittesting. 124 | 125 | - Added _GTMCompileAssert for doing compile time assertions to GTMDefines.h 126 | 127 | - Added GTMUnitTestDevLog and GTMTestCase for logging and tracking logs while 128 | running unittests to verify what is being logged is what you expect. All 129 | unittests should now inherit from GTMTestCase instead of SenTestCase to take 130 | advantage of the new log tracking. See GTMUnitTestDevLog.h for details. 131 | 132 | - Extracted GTMIPhoneUnitTestDelegate from GTMIPhoneUnitTestMain.m to its own 133 | file. Tests can now be run from another application. 134 | 135 | 136 | Release 1.0.0 137 | 14-January-2008 138 | 139 | - Initial public release. Includes some simple utils, xcode configs, and 140 | some support for doing unit tests of graphical things. 141 | -------------------------------------------------------------------------------- /Tools/google-toolbox-for-mac-1-5-1/UnitTesting/GTMIPhoneUnitTestDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // GTMIPhoneUnitTestDelegate.m 3 | // 4 | // Copyright 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 "GTMIPhoneUnitTestDelegate.h" 20 | 21 | #import "GTMDefines.h" 22 | #if !GTM_IPHONE_SDK 23 | #error GTMIPhoneUnitTestDelegate for iPhone only 24 | #endif 25 | #import 26 | #import 27 | #import 28 | #import "GTMSenTestCase.h" 29 | 30 | // Used for sorting methods below 31 | static int MethodSort(const void *a, const void *b) { 32 | const char *nameA = sel_getName(method_getName(*(Method*)a)); 33 | const char *nameB = sel_getName(method_getName(*(Method*)b)); 34 | return strcmp(nameA, nameB); 35 | } 36 | 37 | @implementation GTMIPhoneUnitTestDelegate 38 | 39 | // Return YES if class is subclass (1 or more generations) of SenTestCase 40 | - (BOOL)isTestFixture:(Class)aClass { 41 | BOOL iscase = NO; 42 | Class testCaseClass = [SenTestCase class]; 43 | Class superclass; 44 | for (superclass = aClass; 45 | !iscase && superclass; 46 | superclass = class_getSuperclass(superclass)) { 47 | iscase = superclass == testCaseClass ? YES : NO; 48 | } 49 | return iscase; 50 | } 51 | 52 | // Run through all the registered classes and run test methods on any 53 | // that are subclasses of SenTestCase. Terminate the application upon 54 | // test completion. 55 | - (void)applicationDidFinishLaunching:(UIApplication *)application { 56 | if (![self runTests]) 57 | exit(EXIT_FAILURE); 58 | exit(EXIT_SUCCESS); 59 | } 60 | 61 | // Run through all the registered classes and run test methods on any 62 | // that are subclasses of SenTestCase. Print results and run time to 63 | // the default output. 64 | - (BOOL)runTests { 65 | int count = objc_getClassList(NULL, 0); 66 | Class *classes = (Class*)malloc(sizeof(Class) * count); 67 | _GTMDevAssert(classes, @"Couldn't allocate class list"); 68 | objc_getClassList(classes, count); 69 | int suiteSuccesses = 0; 70 | int suiteFailures = 0; 71 | int suiteTotal = 0; 72 | NSString *suiteName = [[NSBundle mainBundle] bundlePath]; 73 | NSDate *suiteStartDate = [NSDate date]; 74 | NSString *suiteStartString = [NSString stringWithFormat:@"Test Suite '%@' started at %@\n", 75 | suiteName, suiteStartDate]; 76 | fputs([suiteStartString UTF8String], stderr); 77 | fflush(stderr); 78 | for (int i = 0; i < count; ++i) { 79 | Class currClass = classes[i]; 80 | if ([self isTestFixture:currClass]) { 81 | NSDate *fixtureStartDate = [NSDate date]; 82 | NSString *fixtureName = NSStringFromClass(currClass); 83 | NSString *fixtureStartString = [NSString stringWithFormat:@"Test Suite '%@' started at %@\n", 84 | fixtureName, fixtureStartDate]; 85 | int fixtureSuccesses = 0; 86 | int fixtureFailures = 0; 87 | int fixtureTotal = 0; 88 | fputs([fixtureStartString UTF8String], stderr); 89 | fflush(stderr); 90 | id testcase = [[currClass alloc] init]; 91 | _GTMDevAssert(testcase, @"Unable to instantiate Test Suite: '%@'\n", 92 | fixtureName); 93 | unsigned int methodCount; 94 | Method *methods = class_copyMethodList(currClass, &methodCount); 95 | // Sort our methods so they are called in Alphabetical order just 96 | // because we can. 97 | qsort(methods, methodCount, sizeof(Method), MethodSort); 98 | for (size_t j = 0; j < methodCount; ++j) { 99 | Method currMethod = methods[j]; 100 | SEL sel = method_getName(currMethod); 101 | const char *name = sel_getName(sel); 102 | // If it starts with test, run it. 103 | if (strstr(name, "test") == name) { 104 | fixtureTotal += 1; 105 | BOOL failed = NO; 106 | NSDate *caseStartDate = [NSDate date]; 107 | @try { 108 | [testcase performTest:sel]; 109 | } @catch (NSException *exception) { 110 | failed = YES; 111 | } 112 | if (failed) { 113 | fixtureFailures += 1; 114 | } else { 115 | fixtureSuccesses += 1; 116 | } 117 | NSTimeInterval caseEndTime = [[NSDate date] timeIntervalSinceDate:caseStartDate]; 118 | NSString *caseEndString = [NSString stringWithFormat:@"Test Case '-[%@ %s]' %s (%0.3f seconds).\n", 119 | fixtureName, name, 120 | failed ? "failed" : "passed", caseEndTime]; 121 | fputs([caseEndString UTF8String], stderr); 122 | fflush(stderr); 123 | } 124 | } 125 | if (methods) { 126 | free(methods); 127 | } 128 | [testcase release]; 129 | NSDate *fixtureEndDate = [NSDate date]; 130 | NSTimeInterval fixtureEndTime = [fixtureEndDate timeIntervalSinceDate:fixtureStartDate]; 131 | NSString *fixtureEndString = [NSString stringWithFormat:@"Test Suite '%@' finished at %@.\n" 132 | "Executed %d tests, with %d failures (%d unexpected) in %0.3f (%0.3f) seconds\n", 133 | fixtureName, fixtureEndDate, fixtureTotal, 134 | fixtureFailures, fixtureFailures, 135 | fixtureEndTime, fixtureEndTime]; 136 | 137 | fputs([fixtureEndString UTF8String], stderr); 138 | fflush(stderr); 139 | suiteTotal += fixtureTotal; 140 | suiteSuccesses += fixtureSuccesses; 141 | suiteFailures += fixtureFailures; 142 | } 143 | } 144 | NSDate *suiteEndDate = [NSDate date]; 145 | NSTimeInterval suiteEndTime = [suiteEndDate timeIntervalSinceDate:suiteStartDate]; 146 | NSString *suiteEndString = [NSString stringWithFormat:@"Test Suite '%@' finished at %@.\n" 147 | "Executed %d tests, with %d failures (%d unexpected) in %0.3f (%0.3f) seconds\n", 148 | suiteName, suiteEndDate, suiteTotal, 149 | suiteFailures, suiteFailures, 150 | suiteEndTime, suiteEndTime]; 151 | fputs([suiteEndString UTF8String], stderr); 152 | fflush(stderr); 153 | 154 | if (suiteFailures > 0) 155 | return NO; 156 | 157 | return YES; 158 | } 159 | 160 | @end 161 | -------------------------------------------------------------------------------- /Tools/google-toolbox-for-mac-1-5-1/GTMDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // GTMDefines.h 3 | // 4 | // Copyright 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 | // ============================================================================ 20 | 21 | // ---------------------------------------------------------------------------- 22 | // CPP symbols that can be overridden in a prefix to control how the toolbox 23 | // is compiled. 24 | // ---------------------------------------------------------------------------- 25 | 26 | 27 | // GTMHTTPFetcher will support logging by default but only hook its input 28 | // stream support for logging when requested. You can control the inclusion of 29 | // the code by providing your own definitions for these w/in a prefix header. 30 | // 31 | #ifndef GTM_HTTPFETCHER_ENABLE_LOGGING 32 | # define GTM_HTTPFETCHER_ENABLE_LOGGING 1 33 | #endif // GTM_HTTPFETCHER_ENABLE_LOGGING 34 | #ifndef GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING 35 | # define GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING 0 36 | #endif // GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING 37 | 38 | 39 | // _GTMDevLog & _GTMDevAssert 40 | // 41 | // _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for 42 | // developer level errors. This implementation simply macros to NSLog/NSAssert. 43 | // It is not intended to be a general logging/reporting system. 44 | // 45 | // Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert 46 | // for a little more background on the usage of these macros. 47 | // 48 | // _GTMDevLog log some error/problem in debug builds 49 | // _GTMDevAssert assert if conditon isn't met w/in a method/function 50 | // in all builds. 51 | // 52 | // To replace this system, just provide different macro definitions in your 53 | // prefix header. Remember, any implementation you provide *must* be thread 54 | // safe since this could be called by anything in what ever situtation it has 55 | // been placed in. 56 | // 57 | 58 | // We only define the simple macros if nothing else has defined this. 59 | #ifndef _GTMDevLog 60 | 61 | #ifdef DEBUG 62 | #define _GTMDevLog(...) NSLog(__VA_ARGS__) 63 | #else 64 | #define _GTMDevLog(...) do { } while (0) 65 | #endif 66 | 67 | #endif // _GTMDevLog 68 | 69 | // Declared here so that it can easily be used for logging tracking if 70 | // necessary. See GTMUnitTestDevLog.h for details. 71 | @class NSString; 72 | extern void _GTMUnittestDevLog(NSString *format, ...); 73 | 74 | #ifndef _GTMDevAssert 75 | // we directly invoke the NSAssert handler so we can pass on the varargs 76 | // (NSAssert doesn't have a macro we can use that takes varargs) 77 | #if !defined(NS_BLOCK_ASSERTIONS) 78 | #define _GTMDevAssert(condition, ...) \ 79 | do { \ 80 | if (!(condition)) { \ 81 | [[NSAssertionHandler currentHandler] \ 82 | handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ 83 | file:[NSString stringWithUTF8String:__FILE__] \ 84 | lineNumber:__LINE__ \ 85 | description:__VA_ARGS__]; \ 86 | } \ 87 | } while(0) 88 | #else // !defined(NS_BLOCK_ASSERTIONS) 89 | #define _GTMDevAssert(condition, ...) do { } while (0) 90 | #endif // !defined(NS_BLOCK_ASSERTIONS) 91 | 92 | #endif // _GTMDevAssert 93 | 94 | // _GTMCompileAssert 95 | // _GTMCompileAssert is an assert that is meant to fire at compile time if you 96 | // want to check things at compile instead of runtime. For example if you 97 | // want to check that a wchar is 4 bytes instead of 2 you would use 98 | // _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X) 99 | // Note that the second "arg" is not in quotes, and must be a valid processor 100 | // symbol in it's own right (no spaces, punctuation etc). 101 | 102 | // Wrapping this in an #ifndef allows external groups to define their own 103 | // compile time assert scheme. 104 | #ifndef _GTMCompileAssert 105 | // We got this technique from here: 106 | // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html 107 | 108 | #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg 109 | #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg) 110 | #define _GTMCompileAssert(test, msg) \ 111 | typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] 112 | #endif // _GTMCompileAssert 113 | 114 | // ============================================================================ 115 | 116 | // ---------------------------------------------------------------------------- 117 | // CPP symbols defined based on the project settings so the GTM code has 118 | // simple things to test against w/o scattering the knowledge of project 119 | // setting through all the code. 120 | // ---------------------------------------------------------------------------- 121 | 122 | // Provide a single constant CPP symbol that all of GTM uses for ifdefing 123 | // iPhone code. 124 | #include 125 | #if TARGET_OS_IPHONE // iPhone SDK 126 | // For iPhone specific stuff 127 | #define GTM_IPHONE_SDK 1 128 | #else 129 | // For MacOS specific stuff 130 | #define GTM_MACOS_SDK 1 131 | #endif 132 | 133 | // To simplify support for 64bit (and Leopard in general), we provide the type 134 | // defines for non Leopard SDKs 135 | #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 136 | // NSInteger/NSUInteger and Max/Mins 137 | #ifndef NSINTEGER_DEFINED 138 | #if __LP64__ || NS_BUILD_32_LIKE_64 139 | typedef long NSInteger; 140 | typedef unsigned long NSUInteger; 141 | #else 142 | typedef int NSInteger; 143 | typedef unsigned int NSUInteger; 144 | #endif 145 | #define NSIntegerMax LONG_MAX 146 | #define NSIntegerMin LONG_MIN 147 | #define NSUIntegerMax ULONG_MAX 148 | #define NSINTEGER_DEFINED 1 149 | #endif // NSINTEGER_DEFINED 150 | // CGFloat 151 | #ifndef CGFLOAT_DEFINED 152 | #if defined(__LP64__) && __LP64__ 153 | // This really is an untested path (64bit on Tiger?) 154 | typedef double CGFloat; 155 | #define CGFLOAT_MIN DBL_MIN 156 | #define CGFLOAT_MAX DBL_MAX 157 | #define CGFLOAT_IS_DOUBLE 1 158 | #else /* !defined(__LP64__) || !__LP64__ */ 159 | typedef float CGFloat; 160 | #define CGFLOAT_MIN FLT_MIN 161 | #define CGFLOAT_MAX FLT_MAX 162 | #define CGFLOAT_IS_DOUBLE 0 163 | #endif /* !defined(__LP64__) || !__LP64__ */ 164 | #define CGFLOAT_DEFINED 1 165 | #endif // CGFLOAT_DEFINED 166 | #endif // MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 167 | -------------------------------------------------------------------------------- /Other Sources/gentramp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ----------------------------------------------------------------------- 4 | # gentramp.sh - Copyright (c) 2010-2011, Plausible Labs Cooperative, Inc. 5 | # 6 | # Trampoline Page Generator 7 | # Author: Landon Fuller 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining 10 | # a copy of this software and associated documentation files (the 11 | # ``Software''), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included 18 | # in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 | # DEALINGS IN THE SOFTWARE. 28 | # ----------------------------------------------------------------------- 29 | 30 | PROGNAME="$0" 31 | 32 | INPUT_FILE_PATH="$1" 33 | CURRENT_ARCH="$2" 34 | PLATFORM_NAME="$3" 35 | OUTPUT_FILE_PREFIX="$4" 36 | OUTPUT_DIR="$5" 37 | 38 | if [ -z "${INPUT_FILE_PATH}" ] || [ -z "${CURRENT_ARCH}" ] || [ -z "${PLATFORM_NAME}" ] || [ -z "${OUTPUT_FILE_PREFIX}" ] || [ -z "${OUTPUT_DIR}" ]; then 39 | echo "USAGE: $PROGNAME " 40 | echo " For example, '$PROGNAME blockimp_arm.tramp armv7 iphoneos bli_arm build' would read 'blockimp_arm.tramp'" 41 | echo " and generate the following files in 'build':" 42 | echo " - bli_arm_config.c" 43 | echo " - bli_arm.s" 44 | echo " - bli_arm.h" 45 | 46 | exit 1 47 | fi 48 | 49 | SRC_C_OUTPUT="${OUTPUT_DIR}/${OUTPUT_FILE_PREFIX}_config.c" 50 | SRC_OUTPUT="${OUTPUT_DIR}/${OUTPUT_FILE_PREFIX}.s" 51 | HEADER_OUTPUT="${OUTPUT_DIR}/${OUTPUT_FILE_PREFIX}.h" 52 | 53 | # Default implementation 54 | trampoline_prefix () { 55 | return 0 56 | } 57 | 58 | # Import the trampoline definition 59 | . "${INPUT_FILE_PATH}" 60 | 61 | check_required () { 62 | local name=$1 63 | eval "local var=\${$1}" 64 | 65 | if [ -z "${var}" ]; then 66 | echo "Required variable ${name} not defined." 67 | exit 1 68 | fi 69 | } 70 | 71 | check_required PAGE_SIZE 72 | check_required PAGE_NAME 73 | 74 | # Write a header line 75 | header () { 76 | echo "$1" >> "${HEADER_OUTPUT}" 77 | } 78 | 79 | # Write a C source line 80 | src () { 81 | echo "$1" >> "${SRC_C_OUTPUT}" 82 | } 83 | 84 | # Flush the assembler output buffer to disk 85 | ASM_BUFFER="" 86 | asm_flush () { 87 | echo "${ASM_BUFFER}" >> "${SRC_OUTPUT}" 88 | asm_discard 89 | } 90 | 91 | # Write the assembler buffer to disk, but don't discard the contents 92 | asm_write () { 93 | echo "${ASM_BUFFER}" >> "${SRC_OUTPUT}" 94 | } 95 | 96 | # Discard the current assembler output buffer 97 | asm_discard () { 98 | ASM_BUFFER='' 99 | return 0; 100 | } 101 | 102 | # Append data to the assembler output buffer 103 | asm () { 104 | local line="" 105 | while read -r line; do 106 | ASM_BUFFER+=$line 107 | ASM_BUFFER+="\n" 108 | done 109 | } 110 | 111 | # Compute the assembled size of the current assembler buffer 112 | compute_asm_size () { 113 | # Create the temporary assembler file 114 | local output=".globl _byte_count_start\n" 115 | output+="_byte_count_start:\n" 116 | output+="${ASM_BUFFER}" 117 | output+=".globl _byte_count_end\n" 118 | output+="_byte_count_end:\n" 119 | 120 | # Apple's ARM64 as(1) handling is a thin shim to clang's arm64 integrated 121 | # assembler, which does not support documented as(1) behavior. We work 122 | # around clang's file extension assumptions via an explicit -x option; 123 | # see rdar://15162294 for more details. 124 | if [ "${CURRENT_ARCH}" == "arm64" ]; then 125 | local asm_args_extra="-x assembler" 126 | else 127 | local asm_args_extra="" 128 | fi 129 | 130 | local tempfile=`mktemp /tmp/as_bytecount.XXXXXXXX` 131 | echo "${output}" | xcrun --sdk "${PLATFORM_NAME}" as -arch "${CURRENT_ARCH}" $asm_args_extra -o "${tempfile}" - 132 | if [ $? != 0 ]; then 133 | echo "Assembling the trampoline failed" 134 | exit 1 135 | fi 136 | 137 | local byte_size=`xcrun --sdk "${PLATFORM_NAME}" nm -t d -P "${tempfile}" | grep ^_byte_count_end | awk '{print $3}'` 138 | rm -f "${tempfile}" 139 | 140 | echo $byte_size 141 | } 142 | 143 | 144 | # Write out the page header 145 | write_page_decl () { 146 | # Calculate the required alignment 147 | local align=`perl -l -e "print log(${PAGE_SIZE})/log(2)"` 148 | asm << EOF 149 | # GENERATED CODE - DO NOT EDIT" 150 | # This file was generated by $PROGNAME on `date` 151 | 152 | # Write out the trampoline table, aligned to the page boundary 153 | .text 154 | .align ${align} 155 | .globl _${PAGE_NAME} 156 | _${PAGE_NAME}: 157 | EOF 158 | } 159 | 160 | main () { 161 | echo '' > "${SRC_OUTPUT}" 162 | echo '' > "${SRC_C_OUTPUT}" 163 | echo '' > "${HEADER_OUTPUT}" 164 | 165 | # Write out the trampoline header file 166 | header "extern void *${PAGE_NAME};" 167 | header "extern struct pl_trampoline_table_config ${PAGE_NAME}_config;" 168 | 169 | # Don't generate tables for an unsupported arch 170 | check_architecture "${CURRENT_ARCH}" 171 | if [ "$?" != "1" ]; then 172 | return 173 | fi 174 | 175 | # Determine the trampoline prefix size 176 | trampoline_prefix 177 | local prefix_size=$(compute_asm_size) 178 | asm_discard 179 | 180 | # Compute the size of the remaining code page. 181 | local page_avail=`expr $PAGE_SIZE - $prefix_size` 182 | 183 | # Determine the trampoline size 184 | trampoline 185 | local tramp_size=$(compute_asm_size) 186 | asm_discard 187 | if [ "${tramp_size}" = 0 ]; then 188 | echo "Error occured calculating trampoline size; received size of 0" 189 | exit 1 190 | fi 191 | 192 | # Compute the number of of available trampolines. 193 | local trampoline_count=`expr $page_avail / $tramp_size` 194 | echo "Prefix size: ${prefix_size}" 195 | echo "Trampoline size: ${tramp_size}" 196 | echo "Trampolines per page: ${trampoline_count}" 197 | 198 | # Write out the page declaration 199 | write_page_decl 200 | asm_flush 201 | 202 | # Write out the prefix 203 | trampoline_prefix 204 | asm_flush 205 | 206 | # Write out the trampolines 207 | trampoline 208 | local i=0 209 | while [ $i -lt ${trampoline_count} ]; do 210 | asm_write 211 | local i=`expr $i + 1` 212 | done 213 | asm_discard 214 | 215 | # Write out the table configuration 216 | local config_src=`cat << EOF 217 | #define PL_BLOCKIMP_PRIVATE 1 218 | #include 219 | 220 | extern void *${PAGE_NAME}; 221 | pl_trampoline_table_config ${PAGE_NAME}_config = { 222 | .trampoline_size = ${tramp_size}, 223 | .page_offset = ${prefix_size}, 224 | .trampoline_count = ${trampoline_count}, 225 | .template_page = &${PAGE_NAME} 226 | }; 227 | EOF` 228 | src "${config_src}" 229 | } 230 | 231 | main -------------------------------------------------------------------------------- /Tools/google-toolbox-for-mac-1-5-1/UnitTesting/GTMSenTestCase.m: -------------------------------------------------------------------------------- 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 | 21 | #if GTM_IPHONE_SDK 22 | 23 | #import 24 | 25 | @implementation NSException (GTMSenTestAdditions) 26 | 27 | + (NSException *)failureInFile:(NSString *)filename 28 | atLine:(int)lineNumber 29 | withDescription:(NSString *)formatString, ... { 30 | va_list vl; 31 | va_start(vl, formatString); 32 | NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; 33 | va_end(vl); 34 | reason = [NSString stringWithFormat:@"%@:%d: error: %@", filename, lineNumber, reason]; 35 | return [NSException exceptionWithName:SenTestFailureException 36 | reason:reason 37 | userInfo:nil]; 38 | } 39 | 40 | + (NSException *)failureInCondition:(NSString *)condition 41 | isTrue:(BOOL)isTrue 42 | inFile:(NSString *)filename 43 | atLine:(int)lineNumber 44 | withDescription:(NSString *)formatString, ... { 45 | va_list vl; 46 | va_start(vl, formatString); 47 | NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; 48 | va_end(vl); 49 | reason = [NSString stringWithFormat:@"condition '%@' is %s : %@", 50 | condition, isTrue ? "TRUE" : "FALSE", reason]; 51 | return [self failureInFile:filename atLine:lineNumber withDescription:reason]; 52 | } 53 | 54 | + (NSException *)failureInEqualityBetweenObject:(id)left 55 | andObject:(id)right 56 | inFile:(NSString *)filename 57 | atLine:(int)lineNumber 58 | withDescription:(NSString *)formatString, ... { 59 | va_list vl; 60 | va_start(vl, formatString); 61 | NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; 62 | va_end(vl); 63 | reason = [NSString stringWithFormat:@"%@ != %@ : %@", 64 | left, right, reason]; 65 | return [self failureInFile:filename atLine:lineNumber withDescription:reason]; 66 | } 67 | 68 | + (NSException *)failureInEqualityBetweenValue:(NSValue *)left 69 | andValue:(NSValue *)right 70 | withAccuracy:(NSValue *)accuracy 71 | inFile:(NSString *)filename 72 | atLine:(int)lineNumber 73 | withDescription:(NSString *)formatString, ... { 74 | va_list vl; 75 | va_start(vl, formatString); 76 | NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; 77 | va_end(vl); 78 | reason = [NSString stringWithFormat:@"%@ != %@ with accuracy %@ : %@", 79 | left, right, accuracy, reason]; 80 | return [self failureInFile:filename atLine:lineNumber withDescription:reason]; 81 | } 82 | 83 | + (NSException *)failureInRaise:(NSString *)expression 84 | inFile:(NSString *)filename 85 | atLine:(int)lineNumber 86 | withDescription:(NSString *)formatString, ... { 87 | va_list vl; 88 | va_start(vl, formatString); 89 | NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; 90 | va_end(vl); 91 | reason = [NSString stringWithFormat:@"failure in raise %@ : %@", 92 | expression, reason]; 93 | return [self failureInFile:filename atLine:lineNumber withDescription:reason]; 94 | } 95 | 96 | + (NSException *)failureInRaise:(NSString *)expression 97 | exception:(NSException *)exception 98 | inFile:(NSString *)filename 99 | atLine:(int)lineNumber 100 | withDescription:(NSString *)formatString, ... { 101 | va_list vl; 102 | va_start(vl, formatString); 103 | NSString *reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; 104 | va_end(vl); 105 | reason = [NSString stringWithFormat:@"failure in raise %@ (%@) : %@", 106 | expression, exception, reason]; 107 | return [self failureInFile:filename atLine:lineNumber withDescription:reason]; 108 | } 109 | 110 | @end 111 | 112 | @implementation NSObject (GTMSenTestAdditions) 113 | - (void)failWithException:(NSException*)exception { 114 | [exception raise]; 115 | } 116 | 117 | @end 118 | 119 | NSString *STComposeString(NSString *formatString, ...) { 120 | NSString *reason = @""; 121 | if (formatString) { 122 | va_list vl; 123 | va_start(vl, formatString); 124 | reason = [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; 125 | va_end(vl); 126 | } 127 | return reason; 128 | } 129 | 130 | NSString * const SenTestFailureException = @"SenTestFailureException"; 131 | 132 | @interface SenTestCase (SenTestCasePrivate) 133 | // our method of logging errors 134 | - (void)printError:(NSString *)error; 135 | @end 136 | 137 | @implementation SenTestCase 138 | - (void)setUp { 139 | } 140 | 141 | - (void)performTest:(SEL)sel { 142 | currentSelector_ = sel; 143 | @try { 144 | [self invokeTest]; 145 | } @catch (NSException *exception) { 146 | [self printError:[exception reason]]; 147 | [exception raise]; 148 | } 149 | } 150 | 151 | - (void)printError:(NSString *)error { 152 | if ([error rangeOfString:@"error:"].location == NSNotFound) { 153 | fprintf(stderr, "error: %s\n", [error UTF8String]); 154 | } else { 155 | fprintf(stderr, "%s\n", [error UTF8String]); 156 | } 157 | fflush(stderr); 158 | } 159 | 160 | - (void)invokeTest { 161 | NSException *e = nil; 162 | @try { 163 | // Wrap things in autorelease pools because they may 164 | // have an STMacro in their dealloc which may get called 165 | // when the pool is cleaned up 166 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 167 | @try { 168 | [self setUp]; 169 | @try { 170 | [self performSelector:currentSelector_]; 171 | } @catch (NSException *exception) { 172 | e = [exception retain]; 173 | [self printError:[exception reason]]; 174 | } 175 | [self tearDown]; 176 | } @catch (NSException *exception) { 177 | e = [exception retain]; 178 | [self printError:[exception reason]]; 179 | } 180 | [pool release]; 181 | } @catch (NSException *exception) { 182 | e = [exception retain]; 183 | [self printError:[exception reason]]; 184 | } 185 | if (e) { 186 | [e autorelease]; 187 | [e raise]; 188 | } 189 | } 190 | 191 | - (void)tearDown { 192 | } 193 | @end 194 | 195 | #endif 196 | 197 | @implementation GTMTestCase : SenTestCase 198 | - (void) invokeTest { 199 | Class devLogClass = NSClassFromString(@"GTMUnitTestDevLog"); 200 | if (devLogClass) { 201 | [devLogClass performSelector:@selector(enableTracking)]; 202 | [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)]; 203 | 204 | } 205 | [super invokeTest]; 206 | if (devLogClass) { 207 | [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)]; 208 | [devLogClass performSelector:@selector(disableTracking)]; 209 | } 210 | } 211 | @end 212 | -------------------------------------------------------------------------------- /Source/trampoline_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright 2010-2011 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without restriction, 10 | * including without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to permit 12 | * persons to whom the Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | 28 | #include "trampoline_table.h" 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | /* 36 | * Allocate, register, and return a new trampoline table. The trampoline lock must be held by the caller. 37 | * 38 | * @param source_page The source page that will be remapped. 39 | */ 40 | static pl_trampoline_table *pl_trampoline_table_alloc (pl_trampoline_table_config *config) { 41 | pl_trampoline_table *table = NULL; 42 | 43 | /* Loop until we can allocate two contigious pages */ 44 | while (table == NULL) { 45 | vm_address_t data_page = 0x0; 46 | kern_return_t kt; 47 | 48 | /* Try to allocate two pages */ 49 | kt = vm_allocate (mach_task_self(), &data_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE); 50 | if (kt != KERN_SUCCESS) { 51 | fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); 52 | break; 53 | } 54 | 55 | /* Now drop the second half of the allocation to make room for the trampoline table */ 56 | vm_address_t trampoline_page = data_page+PAGE_SIZE; 57 | kt = vm_deallocate (mach_task_self(), trampoline_page, PAGE_SIZE); 58 | if (kt != KERN_SUCCESS) { 59 | fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); 60 | break; 61 | } 62 | 63 | /* Remap the trampoline table to directly follow the config page */ 64 | vm_prot_t cur_prot; 65 | vm_prot_t max_prot; 66 | 67 | kt = vm_remap (mach_task_self(), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self(), (vm_address_t) config->template_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE); 68 | 69 | /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */ 70 | if (kt != KERN_SUCCESS) { 71 | /* Log unexpected failures */ 72 | if (kt != KERN_NO_SPACE) { 73 | fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); 74 | } 75 | 76 | vm_deallocate (mach_task_self(), data_page, PAGE_SIZE); 77 | continue; 78 | } 79 | 80 | /* We have valid trampoline and config pages */ 81 | table = calloc (1, sizeof(pl_trampoline_table)); 82 | table->free_count = config->trampoline_count; 83 | table->data_page = data_page; 84 | table->trampoline_page = trampoline_page; 85 | table->config = config; 86 | 87 | /* Create and initialize the free list */ 88 | table->free_list_pool = calloc(config->trampoline_count, sizeof(pl_trampoline)); 89 | 90 | uint16_t i; 91 | for (i = 0; i < table->free_count; i++) { 92 | pl_trampoline *entry = &table->free_list_pool[i]; 93 | entry->table = table; 94 | entry->trampoline = (void *) (table->trampoline_page + (i * config->trampoline_size) + config->page_offset); 95 | 96 | if (i < table->free_count - 1) 97 | entry->next = &table->free_list_pool[i+1]; 98 | } 99 | 100 | table->free_list = table->free_list_pool; 101 | } 102 | 103 | return table; 104 | } 105 | 106 | /** 107 | * Allocate a new trampoline. Returns NULL on error. 108 | * 109 | * @param config The table configuration. This value is owned by the caller, and must survive for the lifetime of the table. 110 | * @param lock The lock to acquire when modifying shared mutable state. 111 | * @param root_table The table from which the entry should be allocated. 112 | */ 113 | pl_trampoline *pl_trampoline_alloc (pl_trampoline_table_config *config, pthread_mutex_t *lock, pl_trampoline_table **table_head) { 114 | pthread_mutex_lock(lock); 115 | 116 | /* Check for an active trampoline table with available entries. */ 117 | pl_trampoline_table *table = *table_head; 118 | if (table == NULL || table->free_list == NULL) { 119 | table = pl_trampoline_table_alloc (config); 120 | if (table == NULL) { 121 | return NULL; 122 | } 123 | 124 | /* Insert the new table at the top of the list */ 125 | table->next = *table_head; 126 | if (table->next != NULL) 127 | table->next->prev = table; 128 | 129 | *table_head = table; 130 | } 131 | 132 | /* Claim the free entry */ 133 | pl_trampoline *entry = (*table_head)->free_list; 134 | (*table_head)->free_list = entry->next; 135 | (*table_head)->free_count--; 136 | entry->next = NULL; 137 | 138 | pthread_mutex_unlock(lock); 139 | 140 | return entry; 141 | } 142 | 143 | /** 144 | * Given a trampoline's code pointer, return its associated data pointer. 145 | */ 146 | void *pl_trampoline_data_ptr (void *code_ptr) { 147 | return (uint8_t *) code_ptr - PAGE_SIZE; 148 | } 149 | 150 | /** 151 | * Deallocate a trampoline and return it to the free list. 152 | * 153 | * @param lock The lock to acquire when modifying shared mutable state. 154 | * @param root_table The root table from which the entry should be deallocated. 155 | * @param tramp The trampoline to deallocate. 156 | */ 157 | void pl_trampoline_free (pthread_mutex_t *lock, pl_trampoline_table **table_head, pl_trampoline *tramp) { 158 | pthread_mutex_lock(lock); 159 | 160 | /* Fetch the table references */ 161 | pl_trampoline_table *table = tramp->table; 162 | 163 | /* Return the entry to the free list */ 164 | tramp->next = table->free_list; 165 | table->free_list = tramp; 166 | table->free_count++; 167 | 168 | /* If all trampolines within this table are free, and at least one other table exists, deallocate 169 | * the table */ 170 | if (table->free_count == table->config->trampoline_count && *table_head != table) { 171 | /* Remove from the list */ 172 | if (table->prev != NULL) 173 | table->prev->next = table->next; 174 | 175 | if (table->next != NULL) 176 | table->next->prev = table->prev; 177 | 178 | /* Deallocate pages */ 179 | kern_return_t kt; 180 | kt = vm_deallocate (mach_task_self(), table->data_page, PAGE_SIZE); 181 | if (kt != KERN_SUCCESS) 182 | fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); 183 | 184 | kt = vm_deallocate (mach_task_self(), table->trampoline_page, PAGE_SIZE); 185 | if (kt != KERN_SUCCESS) 186 | fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); 187 | 188 | /* Deallocate free list */ 189 | free (table->free_list_pool); 190 | free (table); 191 | } else if (*table_head != table) { 192 | /* Otherwise, bump this table to the top of the list */ 193 | table->prev = NULL; 194 | table->next = *table_head; 195 | if (*table_head != NULL) 196 | (*table_head)->prev = table; 197 | 198 | *table_head = table; 199 | } 200 | 201 | pthread_mutex_unlock (lock); 202 | } 203 | -------------------------------------------------------------------------------- /Tools/google-toolbox-for-mac-1-5-1/COPYING: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2007 Google Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /Resources/MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1056 5 | 10J869 6 | 851 7 | 1038.35 8 | 461.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 141 12 | 13 | 14 | YES 15 | 16 | 17 | YES 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | YES 22 | 23 | YES 24 | 25 | 26 | YES 27 | 28 | 29 | 30 | YES 31 | 32 | IBFilesOwner 33 | IBIPadFramework 34 | 35 | 36 | IBFirstResponder 37 | IBIPadFramework 38 | 39 | 40 | IBIPadFramework 41 | 42 | 43 | 44 | 1316 45 | 46 | {768, 1024} 47 | 48 | 1 49 | MSAxIDEAA 50 | 51 | NO 52 | NO 53 | 54 | 2 55 | 56 | IBIPadFramework 57 | YES 58 | 59 | 60 | 61 | 62 | YES 63 | 64 | 65 | delegate 66 | 67 | 68 | 69 | 5 70 | 71 | 72 | 73 | 74 | YES 75 | 76 | 0 77 | 78 | 79 | 80 | 81 | 82 | 2 83 | 84 | 85 | 86 | 87 | -1 88 | 89 | 90 | File's Owner 91 | 92 | 93 | 4 94 | 95 | 96 | App Delegate 97 | 98 | 99 | -2 100 | 101 | 102 | 103 | 104 | 105 | 106 | YES 107 | 108 | YES 109 | -1.CustomClassName 110 | -2.CustomClassName 111 | 2.IBAttributePlaceholdersKey 112 | 2.IBEditorWindowLastContentRect 113 | 2.IBPluginDependency 114 | 2.UIWindow.visibleAtLaunch 115 | 4.CustomClassName 116 | 4.IBPluginDependency 117 | 118 | 119 | YES 120 | UIApplication 121 | UIResponder 122 | 123 | YES 124 | 125 | 126 | YES 127 | 128 | 129 | {{515, 132}, {768, 1024}} 130 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 131 | 132 | GTMIPhoneUnitTestDelegate 133 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 134 | 135 | 136 | 137 | YES 138 | 139 | 140 | YES 141 | 142 | 143 | 144 | 145 | YES 146 | 147 | 148 | YES 149 | 150 | 151 | 152 | 5 153 | 154 | 155 | 156 | YES 157 | 158 | GTMIPhoneUnitTestDelegate 159 | NSObject 160 | 161 | IBProjectSource 162 | Tools/google-toolbox-for-mac-1-5-1/UnitTesting/GTMIPhoneUnitTestDelegate.h 163 | 164 | 165 | 166 | NSObject 167 | 168 | IBProjectSource 169 | Tools/google-toolbox-for-mac-1-5-1/UnitTesting/GTMSenTestCase.h 170 | 171 | 172 | 173 | 174 | YES 175 | 176 | NSObject 177 | 178 | IBFrameworkSource 179 | AppKit.framework/Headers/NSAccessibility.h 180 | 181 | 182 | 183 | NSObject 184 | 185 | IBFrameworkSource 186 | AppKit.framework/Headers/NSApplication.h 187 | 188 | 189 | 190 | NSObject 191 | 192 | IBFrameworkSource 193 | AppKit.framework/Headers/NSApplicationScripting.h 194 | 195 | 196 | 197 | NSObject 198 | 199 | IBFrameworkSource 200 | AppKit.framework/Headers/NSColorPanel.h 201 | 202 | 203 | 204 | NSObject 205 | 206 | IBFrameworkSource 207 | AppKit.framework/Headers/NSControl.h 208 | 209 | 210 | 211 | NSObject 212 | 213 | IBFrameworkSource 214 | AppKit.framework/Headers/NSDictionaryController.h 215 | 216 | 217 | 218 | NSObject 219 | 220 | IBFrameworkSource 221 | AppKit.framework/Headers/NSDragging.h 222 | 223 | 224 | 225 | NSObject 226 | 227 | IBFrameworkSource 228 | AppKit.framework/Headers/NSFontManager.h 229 | 230 | 231 | 232 | NSObject 233 | 234 | IBFrameworkSource 235 | AppKit.framework/Headers/NSFontPanel.h 236 | 237 | 238 | 239 | NSObject 240 | 241 | IBFrameworkSource 242 | AppKit.framework/Headers/NSKeyValueBinding.h 243 | 244 | 245 | 246 | NSObject 247 | 248 | IBFrameworkSource 249 | AppKit.framework/Headers/NSMenu.h 250 | 251 | 252 | 253 | NSObject 254 | 255 | IBFrameworkSource 256 | AppKit.framework/Headers/NSNibLoading.h 257 | 258 | 259 | 260 | NSObject 261 | 262 | IBFrameworkSource 263 | AppKit.framework/Headers/NSOutlineView.h 264 | 265 | 266 | 267 | NSObject 268 | 269 | IBFrameworkSource 270 | AppKit.framework/Headers/NSPasteboard.h 271 | 272 | 273 | 274 | NSObject 275 | 276 | IBFrameworkSource 277 | AppKit.framework/Headers/NSSavePanel.h 278 | 279 | 280 | 281 | NSObject 282 | 283 | IBFrameworkSource 284 | AppKit.framework/Headers/NSTableView.h 285 | 286 | 287 | 288 | NSObject 289 | 290 | IBFrameworkSource 291 | AppKit.framework/Headers/NSToolbarItem.h 292 | 293 | 294 | 295 | NSObject 296 | 297 | IBFrameworkSource 298 | AppKit.framework/Headers/NSView.h 299 | 300 | 301 | 302 | NSObject 303 | 304 | IBFrameworkSource 305 | Foundation.framework/Headers/NSArchiver.h 306 | 307 | 308 | 309 | NSObject 310 | 311 | IBFrameworkSource 312 | Foundation.framework/Headers/NSClassDescription.h 313 | 314 | 315 | 316 | NSObject 317 | 318 | IBFrameworkSource 319 | Foundation.framework/Headers/NSError.h 320 | 321 | 322 | 323 | NSObject 324 | 325 | IBFrameworkSource 326 | Foundation.framework/Headers/NSFileManager.h 327 | 328 | 329 | 330 | NSObject 331 | 332 | IBFrameworkSource 333 | Foundation.framework/Headers/NSKeyValueCoding.h 334 | 335 | 336 | 337 | NSObject 338 | 339 | IBFrameworkSource 340 | Foundation.framework/Headers/NSKeyValueObserving.h 341 | 342 | 343 | 344 | NSObject 345 | 346 | IBFrameworkSource 347 | Foundation.framework/Headers/NSKeyedArchiver.h 348 | 349 | 350 | 351 | NSObject 352 | 353 | IBFrameworkSource 354 | Foundation.framework/Headers/NSObject.h 355 | 356 | 357 | 358 | NSObject 359 | 360 | IBFrameworkSource 361 | Foundation.framework/Headers/NSObjectScripting.h 362 | 363 | 364 | 365 | NSObject 366 | 367 | IBFrameworkSource 368 | Foundation.framework/Headers/NSPortCoder.h 369 | 370 | 371 | 372 | NSObject 373 | 374 | IBFrameworkSource 375 | Foundation.framework/Headers/NSRunLoop.h 376 | 377 | 378 | 379 | NSObject 380 | 381 | IBFrameworkSource 382 | Foundation.framework/Headers/NSScriptClassDescription.h 383 | 384 | 385 | 386 | NSObject 387 | 388 | IBFrameworkSource 389 | Foundation.framework/Headers/NSScriptKeyValueCoding.h 390 | 391 | 392 | 393 | NSObject 394 | 395 | IBFrameworkSource 396 | Foundation.framework/Headers/NSScriptObjectSpecifiers.h 397 | 398 | 399 | 400 | NSObject 401 | 402 | IBFrameworkSource 403 | Foundation.framework/Headers/NSScriptWhoseTests.h 404 | 405 | 406 | 407 | NSObject 408 | 409 | IBFrameworkSource 410 | Foundation.framework/Headers/NSThread.h 411 | 412 | 413 | 414 | NSObject 415 | 416 | IBFrameworkSource 417 | Foundation.framework/Headers/NSURL.h 418 | 419 | 420 | 421 | NSObject 422 | 423 | IBFrameworkSource 424 | Foundation.framework/Headers/NSURLConnection.h 425 | 426 | 427 | 428 | NSObject 429 | 430 | IBFrameworkSource 431 | Foundation.framework/Headers/NSURLDownload.h 432 | 433 | 434 | 435 | 436 | 0 437 | IBIPadFramework 438 | 439 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 440 | 441 | 442 | 443 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 444 | 445 | 446 | YES 447 | 448 | 3 449 | 141 450 | 451 | 452 | -------------------------------------------------------------------------------- /Tools/google-toolbox-for-mac-1-5-1/UnitTesting/GTMSenTestCase.h: -------------------------------------------------------------------------------- 1 | // 2 | // GTMSenTestCase.h 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 | // Portions of this file fall under the following license, marked with 20 | // SENTE_BEGIN - SENTE_END 21 | // 22 | // Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. 23 | // 24 | // Use of this source code is governed by the following license: 25 | // 26 | // Redistribution and use in source and binary forms, with or without modification, 27 | // are permitted provided that the following conditions are met: 28 | // 29 | // (1) Redistributions of source code must retain the above copyright notice, 30 | // this list of conditions and the following disclaimer. 31 | // 32 | // (2) Redistributions in binary form must reproduce the above copyright notice, 33 | // this list of conditions and the following disclaimer in the documentation 34 | // and/or other materials provided with the distribution. 35 | // 36 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 37 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 38 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 39 | // IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 41 | // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 43 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 44 | // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 | // 46 | // Note: this license is equivalent to the FreeBSD license. 47 | // 48 | // This notice may not be removed from this file. 49 | 50 | // Some extra test case macros that would have been convenient for SenTestingKit 51 | // to provide. I didn't stick GTM in front of the Macro names, so that they would 52 | // be easy to remember. 53 | 54 | #import "GTMDefines.h" 55 | 56 | #if (!GTM_IPHONE_SDK) 57 | #import 58 | #else 59 | #import 60 | NSString *STComposeString(NSString *, ...); 61 | #endif 62 | 63 | // Generates a failure when a1 != noErr 64 | // Args: 65 | // a1: should be either an OSErr or an OSStatus 66 | // description: A format string as in the printf() function. Can be nil or 67 | // an empty string but must be present. 68 | // ...: A variable number of arguments to the format string. Can be absent. 69 | #define STAssertNoErr(a1, description, ...) \ 70 | do { \ 71 | @try {\ 72 | OSStatus a1value = (a1); \ 73 | if (a1value != noErr) { \ 74 | NSString *_expression = [NSString stringWithFormat:@"Expected noErr, got %ld for (%s)", a1value, #a1]; \ 75 | if (description) { \ 76 | _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ 77 | } \ 78 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 79 | atLine:__LINE__ \ 80 | withDescription:_expression]]; \ 81 | } \ 82 | }\ 83 | @catch (id anException) {\ 84 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \ 85 | exception:anException \ 86 | inFile:[NSString stringWithUTF8String:__FILE__] \ 87 | atLine:__LINE__ \ 88 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 89 | }\ 90 | } while(0) 91 | 92 | // Generates a failure when a1 != a2 93 | // Args: 94 | // a1: received value. Should be either an OSErr or an OSStatus 95 | // a2: expected value. Should be either an OSErr or an OSStatus 96 | // description: A format string as in the printf() function. Can be nil or 97 | // an empty string but must be present. 98 | // ...: A variable number of arguments to the format string. Can be absent. 99 | #define STAssertErr(a1, a2, description, ...) \ 100 | do { \ 101 | @try {\ 102 | OSStatus a1value = (a1); \ 103 | OSStatus a2value = (a2); \ 104 | if (a1value != a2value) { \ 105 | NSString *_expression = [NSString stringWithFormat:@"Expected %s(%ld) but got %ld for (%s)", #a2, a2value, a1value, #a1]; \ 106 | if (description) { \ 107 | _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ 108 | } \ 109 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 110 | atLine:__LINE__ \ 111 | withDescription:_expression]]; \ 112 | } \ 113 | }\ 114 | @catch (id anException) {\ 115 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \ 116 | exception:anException \ 117 | inFile:[NSString stringWithUTF8String:__FILE__] \ 118 | atLine:__LINE__ \ 119 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 120 | }\ 121 | } while(0) 122 | 123 | 124 | // Generates a failure when a1 is NULL 125 | // Args: 126 | // a1: should be a pointer (use STAssertNotNil for an object) 127 | // description: A format string as in the printf() function. Can be nil or 128 | // an empty string but must be present. 129 | // ...: A variable number of arguments to the format string. Can be absent. 130 | #define STAssertNotNULL(a1, description, ...) \ 131 | do { \ 132 | @try {\ 133 | const void* a1value = (a1); \ 134 | if (a1value == NULL) { \ 135 | NSString *_expression = [NSString stringWithFormat:@"(%s) != NULL", #a1]; \ 136 | if (description) { \ 137 | _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ 138 | } \ 139 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 140 | atLine:__LINE__ \ 141 | withDescription:_expression]]; \ 142 | } \ 143 | }\ 144 | @catch (id anException) {\ 145 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != NULL fails", #a1] \ 146 | exception:anException \ 147 | inFile:[NSString stringWithUTF8String:__FILE__] \ 148 | atLine:__LINE__ \ 149 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 150 | }\ 151 | } while(0) 152 | 153 | // Generates a failure when a1 is not NULL 154 | // Args: 155 | // a1: should be a pointer (use STAssertNil for an object) 156 | // description: A format string as in the printf() function. Can be nil or 157 | // an empty string but must be present. 158 | // ...: A variable number of arguments to the format string. Can be absent. 159 | #define STAssertNULL(a1, description, ...) \ 160 | do { \ 161 | @try {\ 162 | const void* a1value = (a1); \ 163 | if (a1value != NULL) { \ 164 | NSString *_expression = [NSString stringWithFormat:@"(%s) == NULL", #a1]; \ 165 | if (description) { \ 166 | _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ 167 | } \ 168 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 169 | atLine:__LINE__ \ 170 | withDescription:_expression]]; \ 171 | } \ 172 | }\ 173 | @catch (id anException) {\ 174 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == NULL fails", #a1] \ 175 | exception:anException \ 176 | inFile:[NSString stringWithUTF8String:__FILE__] \ 177 | atLine:__LINE__ \ 178 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 179 | }\ 180 | } while(0) 181 | 182 | // Generates a failure when a1 is unequal to a2. This test is for C scalars, 183 | // structs and unions. 184 | // Args: 185 | // a1: argument 1 186 | // a2: argument 2 187 | // description: A format string as in the printf() function. Can be nil or 188 | // an empty string but must be present. 189 | // ...: A variable number of arguments to the format string. Can be absent. 190 | #define STAssertNotEquals(a1, a2, description, ...) \ 191 | do { \ 192 | @try {\ 193 | if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ 194 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 195 | atLine:__LINE__ \ 196 | withDescription:[@"Type mismatch -- " stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ 197 | } else { \ 198 | __typeof__(a1) a1value = (a1); \ 199 | __typeof__(a2) a2value = (a2); \ 200 | NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ 201 | NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ 202 | if ([a1encoded isEqualToValue:a2encoded]) { \ 203 | NSString *_expression = [NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2]; \ 204 | if (description) { \ 205 | _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ 206 | } \ 207 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 208 | atLine:__LINE__ \ 209 | withDescription:_expression]]; \ 210 | } \ 211 | } \ 212 | } \ 213 | @catch (id anException) {\ 214 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ 215 | exception:anException \ 216 | inFile:[NSString stringWithUTF8String:__FILE__] \ 217 | atLine:__LINE__ \ 218 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 219 | }\ 220 | } while(0) 221 | 222 | // Generates a failure when a1 is equal to a2. This test is for objects. 223 | // Args: 224 | // a1: argument 1. object. 225 | // a2: argument 2. object. 226 | // description: A format string as in the printf() function. Can be nil or 227 | // an empty string but must be present. 228 | // ...: A variable number of arguments to the format string. Can be absent. 229 | #define STAssertNotEqualObjects(a1, a2, desc, ...) \ 230 | do { \ 231 | @try {\ 232 | id a1value = (a1); \ 233 | id a2value = (a2); \ 234 | if ( (@encode(__typeof__(a1value)) == @encode(id)) && \ 235 | (@encode(__typeof__(a2value)) == @encode(id)) && \ 236 | ![(id)a1value isEqual:(id)a2value] ) continue; \ 237 | NSString *_expression = [NSString stringWithFormat:@"%s('%@') != %s('%@')", #a1, [a1 description], #a2, [a2 description]]; \ 238 | if (desc) { \ 239 | _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(desc, ##__VA_ARGS__)]; \ 240 | } \ 241 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 242 | atLine:__LINE__ \ 243 | withDescription:_expression]]; \ 244 | }\ 245 | @catch (id anException) {\ 246 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ 247 | exception:anException \ 248 | inFile:[NSString stringWithUTF8String:__FILE__] \ 249 | atLine:__LINE__ \ 250 | withDescription:STComposeString(desc, ##__VA_ARGS__)]]; \ 251 | }\ 252 | } while(0) 253 | 254 | // Generates a failure when a1 is not 'op' to a2. This test is for C scalars. 255 | // Args: 256 | // a1: argument 1 257 | // a2: argument 2 258 | // op: operation 259 | // description: A format string as in the printf() function. Can be nil or 260 | // an empty string but must be present. 261 | // ...: A variable number of arguments to the format string. Can be absent. 262 | #define STAssertOperation(a1, a2, op, description, ...) \ 263 | do { \ 264 | @try {\ 265 | if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ 266 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 267 | atLine:__LINE__ \ 268 | withDescription:[@"Type mismatch -- " stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ 269 | } else { \ 270 | __typeof__(a1) a1value = (a1); \ 271 | __typeof__(a2) a2value = (a2); \ 272 | if (!(a1value op a2value)) { \ 273 | double a1DoubleValue = a1value; \ 274 | double a2DoubleValue = a2value; \ 275 | NSString *_expression = [NSString stringWithFormat:@"%s (%lg) %s %s (%lg)", #a1, a1DoubleValue, #op, #a2, a2DoubleValue]; \ 276 | if (description) { \ 277 | _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ 278 | } \ 279 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 280 | atLine:__LINE__ \ 281 | withDescription:_expression]]; \ 282 | } \ 283 | } \ 284 | } \ 285 | @catch (id anException) {\ 286 | [self failWithException:[NSException \ 287 | failureInRaise:[NSString stringWithFormat:@"(%s) %s (%s)", #a1, #op, #a2] \ 288 | exception:anException \ 289 | inFile:[NSString stringWithUTF8String:__FILE__] \ 290 | atLine:__LINE__ \ 291 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 292 | }\ 293 | } while(0) 294 | 295 | // Generates a failure when a1 is not > a2. This test is for C scalars. 296 | // Args: 297 | // a1: argument 1 298 | // a2: argument 2 299 | // op: operation 300 | // description: A format string as in the printf() function. Can be nil or 301 | // an empty string but must be present. 302 | // ...: A variable number of arguments to the format string. Can be absent. 303 | #define STAssertGreaterThan(a1, a2, description, ...) \ 304 | STAssertOperation(a1, a2, >, description, ##__VA_ARGS__) 305 | 306 | // Generates a failure when a1 is not >= a2. This test is for C scalars. 307 | // Args: 308 | // a1: argument 1 309 | // a2: argument 2 310 | // op: operation 311 | // description: A format string as in the printf() function. Can be nil or 312 | // an empty string but must be present. 313 | // ...: A variable number of arguments to the format string. Can be absent. 314 | #define STAssertGreaterThanOrEqual(a1, a2, description, ...) \ 315 | STAssertOperation(a1, a2, >=, description, ##__VA_ARGS__) 316 | 317 | // Generates a failure when a1 is not < a2. This test is for C scalars. 318 | // Args: 319 | // a1: argument 1 320 | // a2: argument 2 321 | // op: operation 322 | // description: A format string as in the printf() function. Can be nil or 323 | // an empty string but must be present. 324 | // ...: A variable number of arguments to the format string. Can be absent. 325 | #define STAssertLessThan(a1, a2, description, ...) \ 326 | STAssertOperation(a1, a2, <, description, ##__VA_ARGS__) 327 | 328 | // Generates a failure when a1 is not <= a2. This test is for C scalars. 329 | // Args: 330 | // a1: argument 1 331 | // a2: argument 2 332 | // op: operation 333 | // description: A format string as in the printf() function. Can be nil or 334 | // an empty string but must be present. 335 | // ...: A variable number of arguments to the format string. Can be absent. 336 | #define STAssertLessThanOrEqual(a1, a2, description, ...) \ 337 | STAssertOperation(a1, a2, <=, description, ##__VA_ARGS__) 338 | 339 | // Generates a failure when string a1 is not equal to string a2. This call 340 | // differs from STAssertEqualObjects in that strings that are different in 341 | // composition (precomposed vs decomposed) will compare equal if their final 342 | // representation is equal. 343 | // ex O + umlaut decomposed is the same as O + umlaut composed. 344 | // Args: 345 | // a1: string 1 346 | // a2: string 2 347 | // description: A format string as in the printf() function. Can be nil or 348 | // an empty string but must be present. 349 | // ...: A variable number of arguments to the format string. Can be absent. 350 | #define STAssertEqualStrings(a1, a2, description, ...) \ 351 | do { \ 352 | @try {\ 353 | id a1value = (a1); \ 354 | id a2value = (a2); \ 355 | if (a1value == a2value) continue; \ 356 | if ([a1value isKindOfClass:[NSString class]] && \ 357 | [a2value isKindOfClass:[NSString class]] && \ 358 | [a1value compare:a2value options:0] == NSOrderedSame) continue; \ 359 | [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ 360 | andObject: a2value \ 361 | inFile: [NSString stringWithUTF8String:__FILE__] \ 362 | atLine: __LINE__ \ 363 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 364 | }\ 365 | @catch (id anException) {\ 366 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ 367 | exception:anException \ 368 | inFile:[NSString stringWithUTF8String:__FILE__] \ 369 | atLine:__LINE__ \ 370 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 371 | }\ 372 | } while(0) 373 | 374 | // Generates a failure when string a1 is equal to string a2. This call 375 | // differs from STAssertEqualObjects in that strings that are different in 376 | // composition (precomposed vs decomposed) will compare equal if their final 377 | // representation is equal. 378 | // ex O + umlaut decomposed is the same as O + umlaut composed. 379 | // Args: 380 | // a1: string 1 381 | // a2: string 2 382 | // description: A format string as in the printf() function. Can be nil or 383 | // an empty string but must be present. 384 | // ...: A variable number of arguments to the format string. Can be absent. 385 | #define STAssertNotEqualStrings(a1, a2, description, ...) \ 386 | do { \ 387 | @try {\ 388 | id a1value = (a1); \ 389 | id a2value = (a2); \ 390 | if ([a1value isKindOfClass:[NSString class]] && \ 391 | [a2value isKindOfClass:[NSString class]] && \ 392 | [a1value compare:a2value options:0] != NSOrderedSame) continue; \ 393 | [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ 394 | andObject: a2value \ 395 | inFile: [NSString stringWithUTF8String:__FILE__] \ 396 | atLine: __LINE__ \ 397 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 398 | }\ 399 | @catch (id anException) {\ 400 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ 401 | exception:anException \ 402 | inFile:[NSString stringWithUTF8String:__FILE__] \ 403 | atLine:__LINE__ \ 404 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 405 | }\ 406 | } while(0) 407 | 408 | // Generates a failure when c-string a1 is not equal to c-string a2. 409 | // Args: 410 | // a1: string 1 411 | // a2: string 2 412 | // description: A format string as in the printf() function. Can be nil or 413 | // an empty string but must be present. 414 | // ...: A variable number of arguments to the format string. Can be absent. 415 | #define STAssertEqualCStrings(a1, a2, description, ...) \ 416 | do { \ 417 | @try {\ 418 | const char* a1value = (a1); \ 419 | const char* a2value = (a2); \ 420 | if (a1value == a2value) continue; \ 421 | if (strcmp(a1value, a2value) == 0) continue; \ 422 | [self failWithException:[NSException failureInEqualityBetweenObject: [NSString stringWithUTF8String:a1value] \ 423 | andObject: [NSString stringWithUTF8String:a2value] \ 424 | inFile: [NSString stringWithUTF8String:__FILE__] \ 425 | atLine: __LINE__ \ 426 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 427 | }\ 428 | @catch (id anException) {\ 429 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ 430 | exception:anException \ 431 | inFile:[NSString stringWithUTF8String:__FILE__] \ 432 | atLine:__LINE__ \ 433 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 434 | }\ 435 | } while(0) 436 | 437 | // Generates a failure when c-string a1 is equal to c-string a2. 438 | // Args: 439 | // a1: string 1 440 | // a2: string 2 441 | // description: A format string as in the printf() function. Can be nil or 442 | // an empty string but must be present. 443 | // ...: A variable number of arguments to the format string. Can be absent. 444 | #define STAssertNotEqualCStrings(a1, a2, description, ...) \ 445 | do { \ 446 | @try {\ 447 | const char* a1value = (a1); \ 448 | const char* a2value = (a2); \ 449 | if (strcmp(a1value, a2value) != 0) continue; \ 450 | [self failWithException:[NSException failureInEqualityBetweenObject: [NSString stringWithUTF8String:a1value] \ 451 | andObject: [NSString stringWithUTF8String:a2value] \ 452 | inFile: [NSString stringWithUTF8String:__FILE__] \ 453 | atLine: __LINE__ \ 454 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 455 | }\ 456 | @catch (id anException) {\ 457 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ 458 | exception:anException \ 459 | inFile:[NSString stringWithUTF8String:__FILE__] \ 460 | atLine:__LINE__ \ 461 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 462 | }\ 463 | } while(0) 464 | 465 | #if GTM_IPHONE_SDK 466 | 467 | // SENTE_BEGIN 468 | /*" Generates a failure when !{ [a1 isEqualTo:a2] } is false 469 | (or one is nil and the other is not). 470 | _{a1 The object on the left.} 471 | _{a2 The object on the right.} 472 | _{description A format string as in the printf() function. Can be nil or 473 | an empty string but must be present.} 474 | _{... A variable number of arguments to the format string. Can be absent.} 475 | "*/ 476 | #define STAssertEqualObjects(a1, a2, description, ...) \ 477 | do { \ 478 | @try {\ 479 | id a1value = (a1); \ 480 | id a2value = (a2); \ 481 | if (a1value == a2value) continue; \ 482 | if ( (@encode(__typeof__(a1value)) == @encode(id)) && \ 483 | (@encode(__typeof__(a2value)) == @encode(id)) && \ 484 | [(id)a1value isEqual: (id)a2value] ) continue; \ 485 | [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ 486 | andObject: a2value \ 487 | inFile: [NSString stringWithUTF8String:__FILE__] \ 488 | atLine: __LINE__ \ 489 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 490 | }\ 491 | @catch (id anException) {\ 492 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ 493 | exception:anException \ 494 | inFile:[NSString stringWithUTF8String:__FILE__] \ 495 | atLine:__LINE__ \ 496 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 497 | }\ 498 | } while(0) 499 | 500 | 501 | /*" Generates a failure when a1 is not equal to a2. This test is for 502 | C scalars, structs and unions. 503 | _{a1 The argument on the left.} 504 | _{a2 The argument on the right.} 505 | _{description A format string as in the printf() function. Can be nil or 506 | an empty string but must be present.} 507 | _{... A variable number of arguments to the format string. Can be absent.} 508 | "*/ 509 | #define STAssertEquals(a1, a2, description, ...) \ 510 | do { \ 511 | @try {\ 512 | if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ 513 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 514 | atLine:__LINE__ \ 515 | withDescription:[@"Type mismatch -- " stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ 516 | } else { \ 517 | __typeof__(a1) a1value = (a1); \ 518 | __typeof__(a2) a2value = (a2); \ 519 | NSValue *a1encoded = [NSValue value:&a1value withObjCType: @encode(__typeof__(a1))]; \ 520 | NSValue *a2encoded = [NSValue value:&a2value withObjCType: @encode(__typeof__(a2))]; \ 521 | if (![a1encoded isEqualToValue:a2encoded]) { \ 522 | [self failWithException:[NSException failureInEqualityBetweenValue: a1encoded \ 523 | andValue: a2encoded \ 524 | withAccuracy: nil \ 525 | inFile: [NSString stringWithUTF8String:__FILE__] \ 526 | atLine: __LINE__ \ 527 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 528 | } \ 529 | } \ 530 | } \ 531 | @catch (id anException) {\ 532 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ 533 | exception:anException \ 534 | inFile:[NSString stringWithUTF8String:__FILE__] \ 535 | atLine:__LINE__ \ 536 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 537 | }\ 538 | } while(0) 539 | 540 | #define STAbsoluteDifference(left,right) (MAX(left,right)-MIN(left,right)) 541 | 542 | 543 | /*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false. 544 | This test is for scalars such as floats and doubles where small differences 545 | could make these items not exactly equal, but also works for all scalars. 546 | _{a1 The scalar on the left.} 547 | _{a2 The scalar on the right.} 548 | _{accuracy The maximum difference between a1 and a2 for these values to be 549 | considered equal.} 550 | _{description A format string as in the printf() function. Can be nil or 551 | an empty string but must be present.} 552 | _{... A variable number of arguments to the format string. Can be absent.} 553 | "*/ 554 | 555 | #define STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...) \ 556 | do { \ 557 | @try {\ 558 | if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ 559 | [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ 560 | atLine:__LINE__ \ 561 | withDescription:[@"Type mismatch -- " stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ 562 | } else { \ 563 | __typeof__(a1) a1value = (a1); \ 564 | __typeof__(a2) a2value = (a2); \ 565 | __typeof__(accuracy) accuracyvalue = (accuracy); \ 566 | if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \ 567 | NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ 568 | NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ 569 | NSValue *accuracyencoded = [NSValue value:&accuracyvalue withObjCType:@encode(__typeof__(accuracy))]; \ 570 | [self failWithException:[NSException failureInEqualityBetweenValue: a1encoded \ 571 | andValue: a2encoded \ 572 | withAccuracy: accuracyencoded \ 573 | inFile: [NSString stringWithUTF8String:__FILE__] \ 574 | atLine: __LINE__ \ 575 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 576 | } \ 577 | } \ 578 | } \ 579 | @catch (id anException) {\ 580 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ 581 | exception:anException \ 582 | inFile:[NSString stringWithUTF8String:__FILE__] \ 583 | atLine:__LINE__ \ 584 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 585 | }\ 586 | } while(0) 587 | 588 | 589 | 590 | /*" Generates a failure unconditionally. 591 | _{description A format string as in the printf() function. Can be nil or 592 | an empty string but must be present.} 593 | _{... A variable number of arguments to the format string. Can be absent.} 594 | "*/ 595 | #define STFail(description, ...) \ 596 | [self failWithException:[NSException failureInFile: [NSString stringWithUTF8String:__FILE__] \ 597 | atLine: __LINE__ \ 598 | withDescription: STComposeString(description, ##__VA_ARGS__)]] 599 | 600 | 601 | 602 | /*" Generates a failure when a1 is not nil. 603 | _{a1 An object.} 604 | _{description A format string as in the printf() function. Can be nil or 605 | an empty string but must be present.} 606 | _{... A variable number of arguments to the format string. Can be absent.} 607 | "*/ 608 | #define STAssertNil(a1, description, ...) \ 609 | do { \ 610 | @try {\ 611 | id a1value = (a1); \ 612 | if (a1value != nil) { \ 613 | NSString *_a1 = [NSString stringWithUTF8String: #a1]; \ 614 | NSString *_expression = [NSString stringWithFormat:@"((%@) == nil)", _a1]; \ 615 | [self failWithException:[NSException failureInCondition: _expression \ 616 | isTrue: NO \ 617 | inFile: [NSString stringWithUTF8String:__FILE__] \ 618 | atLine: __LINE__ \ 619 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 620 | } \ 621 | }\ 622 | @catch (id anException) {\ 623 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == nil fails", #a1] \ 624 | exception:anException \ 625 | inFile:[NSString stringWithUTF8String:__FILE__] \ 626 | atLine:__LINE__ \ 627 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 628 | }\ 629 | } while(0) 630 | 631 | 632 | /*" Generates a failure when a1 is nil. 633 | _{a1 An object.} 634 | _{description A format string as in the printf() function. Can be nil or 635 | an empty string but must be present.} 636 | _{... A variable number of arguments to the format string. Can be absent.} 637 | "*/ 638 | #define STAssertNotNil(a1, description, ...) \ 639 | do { \ 640 | @try {\ 641 | id a1value = (a1); \ 642 | if (a1value == nil) { \ 643 | NSString *_a1 = [NSString stringWithUTF8String: #a1]; \ 644 | NSString *_expression = [NSString stringWithFormat:@"((%@) != nil)", _a1]; \ 645 | [self failWithException:[NSException failureInCondition: _expression \ 646 | isTrue: NO \ 647 | inFile: [NSString stringWithUTF8String:__FILE__] \ 648 | atLine: __LINE__ \ 649 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 650 | } \ 651 | }\ 652 | @catch (id anException) {\ 653 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != nil fails", #a1] \ 654 | exception:anException \ 655 | inFile:[NSString stringWithUTF8String:__FILE__] \ 656 | atLine:__LINE__ \ 657 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 658 | }\ 659 | } while(0) 660 | 661 | 662 | /*" Generates a failure when expression evaluates to false. 663 | _{expr The expression that is tested.} 664 | _{description A format string as in the printf() function. Can be nil or 665 | an empty string but must be present.} 666 | _{... A variable number of arguments to the format string. Can be absent.} 667 | "*/ 668 | #define STAssertTrue(expr, description, ...) \ 669 | do { \ 670 | BOOL _evaluatedExpression = (expr);\ 671 | if (!_evaluatedExpression) {\ 672 | NSString *_expression = [NSString stringWithUTF8String: #expr];\ 673 | [self failWithException:[NSException failureInCondition: _expression \ 674 | isTrue: NO \ 675 | inFile: [NSString stringWithUTF8String:__FILE__] \ 676 | atLine: __LINE__ \ 677 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 678 | } \ 679 | } while (0) 680 | 681 | 682 | /*" Generates a failure when expression evaluates to false and in addition will 683 | generate error messages if an exception is encountered. 684 | _{expr The expression that is tested.} 685 | _{description A format string as in the printf() function. Can be nil or 686 | an empty string but must be present.} 687 | _{... A variable number of arguments to the format string. Can be absent.} 688 | "*/ 689 | #define STAssertTrueNoThrow(expr, description, ...) \ 690 | do { \ 691 | @try {\ 692 | BOOL _evaluatedExpression = (expr);\ 693 | if (!_evaluatedExpression) {\ 694 | NSString *_expression = [NSString stringWithUTF8String: #expr];\ 695 | [self failWithException:[NSException failureInCondition: _expression \ 696 | isTrue: NO \ 697 | inFile: [NSString stringWithUTF8String:__FILE__] \ 698 | atLine: __LINE__ \ 699 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 700 | } \ 701 | } \ 702 | @catch (id anException) {\ 703 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) ", #expr] \ 704 | exception:anException \ 705 | inFile:[NSString stringWithUTF8String:__FILE__] \ 706 | atLine:__LINE__ \ 707 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 708 | }\ 709 | } while (0) 710 | 711 | 712 | /*" Generates a failure when the expression evaluates to true. 713 | _{expr The expression that is tested.} 714 | _{description A format string as in the printf() function. Can be nil or 715 | an empty string but must be present.} 716 | _{... A variable number of arguments to the format string. Can be absent.} 717 | "*/ 718 | #define STAssertFalse(expr, description, ...) \ 719 | do { \ 720 | BOOL _evaluatedExpression = (expr);\ 721 | if (_evaluatedExpression) {\ 722 | NSString *_expression = [NSString stringWithUTF8String: #expr];\ 723 | [self failWithException:[NSException failureInCondition: _expression \ 724 | isTrue: YES \ 725 | inFile: [NSString stringWithUTF8String:__FILE__] \ 726 | atLine: __LINE__ \ 727 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 728 | } \ 729 | } while (0) 730 | 731 | 732 | /*" Generates a failure when the expression evaluates to true and in addition 733 | will generate error messages if an exception is encountered. 734 | _{expr The expression that is tested.} 735 | _{description A format string as in the printf() function. Can be nil or 736 | an empty string but must be present.} 737 | _{... A variable number of arguments to the format string. Can be absent.} 738 | "*/ 739 | #define STAssertFalseNoThrow(expr, description, ...) \ 740 | do { \ 741 | @try {\ 742 | BOOL _evaluatedExpression = (expr);\ 743 | if (_evaluatedExpression) {\ 744 | NSString *_expression = [NSString stringWithUTF8String: #expr];\ 745 | [self failWithException:[NSException failureInCondition: _expression \ 746 | isTrue: YES \ 747 | inFile: [NSString stringWithUTF8String:__FILE__] \ 748 | atLine: __LINE__ \ 749 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 750 | } \ 751 | } \ 752 | @catch (id anException) {\ 753 | [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"!(%s) ", #expr] \ 754 | exception:anException \ 755 | inFile:[NSString stringWithUTF8String:__FILE__] \ 756 | atLine:__LINE__ \ 757 | withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ 758 | }\ 759 | } while (0) 760 | 761 | 762 | /*" Generates a failure when expression does not throw an exception. 763 | _{expression The expression that is evaluated.} 764 | _{description A format string as in the printf() function. Can be nil or 765 | an empty string but must be present.} 766 | _{... A variable number of arguments to the format string. Can be absent. 767 | "*/ 768 | #define STAssertThrows(expr, description, ...) \ 769 | do { \ 770 | @try { \ 771 | (expr);\ 772 | } \ 773 | @catch (id anException) { \ 774 | continue; \ 775 | }\ 776 | [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 777 | exception: nil \ 778 | inFile: [NSString stringWithUTF8String:__FILE__] \ 779 | atLine: __LINE__ \ 780 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 781 | } while (0) 782 | 783 | 784 | /*" Generates a failure when expression does not throw an exception of a 785 | specific class. 786 | _{expression The expression that is evaluated.} 787 | _{specificException The specified class of the exception.} 788 | _{description A format string as in the printf() function. Can be nil or 789 | an empty string but must be present.} 790 | _{... A variable number of arguments to the format string. Can be absent.} 791 | "*/ 792 | #define STAssertThrowsSpecific(expr, specificException, description, ...) \ 793 | do { \ 794 | @try { \ 795 | (expr);\ 796 | } \ 797 | @catch (specificException *anException) { \ 798 | continue; \ 799 | }\ 800 | @catch (id anException) {\ 801 | NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ 802 | [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 803 | exception: anException \ 804 | inFile: [NSString stringWithUTF8String:__FILE__] \ 805 | atLine: __LINE__ \ 806 | withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ 807 | continue; \ 808 | }\ 809 | NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ 810 | [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 811 | exception: nil \ 812 | inFile: [NSString stringWithUTF8String:__FILE__] \ 813 | atLine: __LINE__ \ 814 | withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ 815 | } while (0) 816 | 817 | 818 | /*" Generates a failure when expression does not throw an exception of a 819 | specific class with a specific name. Useful for those frameworks like 820 | AppKit or Foundation that throw generic NSException w/specific names 821 | (NSInvalidArgumentException, etc). 822 | _{expression The expression that is evaluated.} 823 | _{specificException The specified class of the exception.} 824 | _{aName The name of the specified exception.} 825 | _{description A format string as in the printf() function. Can be nil or 826 | an empty string but must be present.} 827 | _{... A variable number of arguments to the format string. Can be absent.} 828 | 829 | "*/ 830 | #define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) \ 831 | do { \ 832 | @try { \ 833 | (expr);\ 834 | } \ 835 | @catch (specificException *anException) { \ 836 | if ([aName isEqualToString: [anException name]]) continue; \ 837 | NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description);\ 838 | [self failWithException: \ 839 | [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 840 | exception: anException \ 841 | inFile: [NSString stringWithUTF8String:__FILE__] \ 842 | atLine: __LINE__ \ 843 | withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ 844 | continue; \ 845 | }\ 846 | @catch (id anException) {\ 847 | NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ 848 | [self failWithException: \ 849 | [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 850 | exception: anException \ 851 | inFile: [NSString stringWithUTF8String:__FILE__] \ 852 | atLine: __LINE__ \ 853 | withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ 854 | continue; \ 855 | }\ 856 | NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ 857 | [self failWithException: \ 858 | [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 859 | exception: nil \ 860 | inFile: [NSString stringWithUTF8String:__FILE__] \ 861 | atLine: __LINE__ \ 862 | withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ 863 | } while (0) 864 | 865 | 866 | /*" Generates a failure when expression does throw an exception. 867 | _{expression The expression that is evaluated.} 868 | _{description A format string as in the printf() function. Can be nil or 869 | an empty string but must be present.} 870 | _{... A variable number of arguments to the format string. Can be absent.} 871 | "*/ 872 | #define STAssertNoThrow(expr, description, ...) \ 873 | do { \ 874 | @try { \ 875 | (expr);\ 876 | } \ 877 | @catch (id anException) { \ 878 | [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 879 | exception: anException \ 880 | inFile: [NSString stringWithUTF8String:__FILE__] \ 881 | atLine: __LINE__ \ 882 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 883 | }\ 884 | } while (0) 885 | 886 | 887 | /*" Generates a failure when expression does throw an exception of the specitied 888 | class. Any other exception is okay (i.e. does not generate a failure). 889 | _{expression The expression that is evaluated.} 890 | _{specificException The specified class of the exception.} 891 | _{description A format string as in the printf() function. Can be nil or 892 | an empty string but must be present.} 893 | _{... A variable number of arguments to the format string. Can be absent.} 894 | "*/ 895 | #define STAssertNoThrowSpecific(expr, specificException, description, ...) \ 896 | do { \ 897 | @try { \ 898 | (expr);\ 899 | } \ 900 | @catch (specificException *anException) { \ 901 | [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 902 | exception: anException \ 903 | inFile: [NSString stringWithUTF8String:__FILE__] \ 904 | atLine: __LINE__ \ 905 | withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ 906 | }\ 907 | @catch (id anythingElse) {\ 908 | ; \ 909 | }\ 910 | } while (0) 911 | 912 | 913 | /*" Generates a failure when expression does throw an exception of a 914 | specific class with a specific name. Useful for those frameworks like 915 | AppKit or Foundation that throw generic NSException w/specific names 916 | (NSInvalidArgumentException, etc). 917 | _{expression The expression that is evaluated.} 918 | _{specificException The specified class of the exception.} 919 | _{aName The name of the specified exception.} 920 | _{description A format string as in the printf() function. Can be nil or 921 | an empty string but must be present.} 922 | _{... A variable number of arguments to the format string. Can be absent.} 923 | 924 | "*/ 925 | #define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) \ 926 | do { \ 927 | @try { \ 928 | (expr);\ 929 | } \ 930 | @catch (specificException *anException) { \ 931 | if ([aName isEqualToString: [anException name]]) { \ 932 | NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description);\ 933 | [self failWithException: \ 934 | [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ 935 | exception: anException \ 936 | inFile: [NSString stringWithUTF8String:__FILE__] \ 937 | atLine: __LINE__ \ 938 | withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ 939 | } \ 940 | continue; \ 941 | }\ 942 | @catch (id anythingElse) {\ 943 | ; \ 944 | }\ 945 | } while (0) 946 | 947 | 948 | 949 | @interface NSException (GTMSenTestAdditions) 950 | + (NSException *)failureInFile:(NSString *)filename 951 | atLine:(int)lineNumber 952 | withDescription:(NSString *)formatString, ...; 953 | + (NSException *)failureInCondition:(NSString *)condition 954 | isTrue:(BOOL)isTrue 955 | inFile:(NSString *)filename 956 | atLine:(int)lineNumber 957 | withDescription:(NSString *)formatString, ...; 958 | + (NSException *)failureInEqualityBetweenObject:(id)left 959 | andObject:(id)right 960 | inFile:(NSString *)filename 961 | atLine:(int)lineNumber 962 | withDescription:(NSString *)formatString, ...; 963 | + (NSException *)failureInEqualityBetweenValue:(NSValue *)left 964 | andValue:(NSValue *)right 965 | withAccuracy:(NSValue *)accuracy 966 | inFile:(NSString *)filename 967 | atLine:(int) ineNumber 968 | withDescription:(NSString *)formatString, ...; 969 | + (NSException *)failureInRaise:(NSString *)expression 970 | inFile:(NSString *)filename 971 | atLine:(int)lineNumber 972 | withDescription:(NSString *)formatString, ...; 973 | + (NSException *)failureInRaise:(NSString *)expression 974 | exception:(NSException *)exception 975 | inFile:(NSString *)filename 976 | atLine:(int)lineNumber 977 | withDescription:(NSString *)formatString, ...; 978 | @end 979 | 980 | // SENTE_END 981 | 982 | @interface NSObject (GTMSenTestAdditions) 983 | - (void)failWithException:(NSException*)exception; 984 | @end 985 | 986 | @interface SenTestCase : NSObject { 987 | SEL currentSelector_; 988 | } 989 | 990 | - (void)setUp; 991 | - (void)invokeTest; 992 | - (void)tearDown; 993 | - (void)performTest:(SEL)sel; 994 | @end 995 | 996 | CF_EXPORT NSString * const SenTestFailureException; 997 | 998 | #endif // GTM_IPHONE_SDK 999 | 1000 | // All unittest cases in GTM should inherit from GTMTestCase. It makes sure 1001 | // to set up our logging system correctly to verify logging calls. 1002 | // See GTMUnitTestDevLog.h for details 1003 | @interface GTMTestCase : SenTestCase 1004 | @end 1005 | --------------------------------------------------------------------------------