Add an OCUnit API compatibility shim and update the Mac OS X test bundle to use XCTest.

This allows us to leave existing test cases entirely unmodified while
switching the project over to XCTest. Unfortunately, this also means
that we lose test support on legacy platforms (i.e. iOS <= 5.x) that do
not support XCTest.

Given that Apple actively discourages legacy support, it doesn't seem
worth blocking compatibility with newer Xcode releases while we try to
find a mechanism to support both OCUnit *and* XCTest.

This commit does not update the iOS targets, and the test runnability
is broken pending those changes.

Issue: PLCR-548
This commit is contained in:
Landon Fuller 2015-02-19 11:30:58 -07:00
Родитель 634a6a2a63
Коммит 7abc6e83b7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 28BBCFC35B80A3C4
40 изменённых файлов: 140 добавлений и 2619 удалений

Просмотреть файл

@ -438,13 +438,6 @@
05CD318F0EE93A90000FDE88 /* CrashReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 05CD31890EE93A90000FDE88 /* CrashReporter.h */; };
05CD31900EE93A90000FDE88 /* CrashReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD318A0EE93A90000FDE88 /* CrashReporter.m */; };
05CD32110EE93AF9000FDE88 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; };
05CD328E0EE93F7C000FDE88 /* GTMSenTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD328D0EE93F7C000FDE88 /* GTMSenTestCase.m */; };
05CD32B20EE940B8000FDE88 /* GTMIPhoneUnitTestDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD32B00EE940B8000FDE88 /* GTMIPhoneUnitTestDelegate.m */; };
05CD32B30EE940B8000FDE88 /* GTMIPhoneUnitTestMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD32B10EE940B8000FDE88 /* GTMIPhoneUnitTestMain.m */; };
05CD32F00EE94148000FDE88 /* GTMSenTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD328D0EE93F7C000FDE88 /* GTMSenTestCase.m */; };
05CD332C0EE94464000FDE88 /* GTMSenTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD328D0EE93F7C000FDE88 /* GTMSenTestCase.m */; };
05CD332D0EE94464000FDE88 /* GTMIPhoneUnitTestDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD32B00EE940B8000FDE88 /* GTMIPhoneUnitTestDelegate.m */; };
05CD332E0EE94464000FDE88 /* GTMIPhoneUnitTestMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 05CD32B10EE940B8000FDE88 /* GTMIPhoneUnitTestMain.m */; };
05CD339C0EE948EB000FDE88 /* PLCrashSignalHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 05CD339A0EE948EB000FDE88 /* PLCrashSignalHandler.h */; };
05CD339D0EE948EB000FDE88 /* PLCrashSignalHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 05CD339B0EE948EB000FDE88 /* PLCrashSignalHandler.mm */; settings = {COMPILER_FLAGS = "-fno-objc-exceptions"; }; };
05CD339E0EE948EB000FDE88 /* PLCrashSignalHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 05CD339A0EE948EB000FDE88 /* PLCrashSignalHandler.h */; };
@ -1154,6 +1147,7 @@
05507A3E178364E8009D5168 /* unwind_test_x86_64_frame.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unwind_test_x86_64_frame.S; sourceTree = "<group>"; };
05507A4E1784DA8A009D5168 /* unwind_test_x86_64_unusual.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unwind_test_x86_64_unusual.S; sourceTree = "<group>"; };
05507A521784DEE4009D5168 /* unwind_test_x86_frame.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unwind_test_x86_frame.S; sourceTree = "<group>"; };
05614E111A965A6100D62442 /* SenTestCompat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SenTestCompat.h; sourceTree = "<group>"; };
05654F760EFA5B54004283F5 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
05659DEA17455DD400D2EE21 /* PLCrashAsyncDwarfEncoding.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = PLCrashAsyncDwarfEncoding.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
05659DED17455DED00D2EE21 /* PLCrashAsyncDwarfEncoding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = PLCrashAsyncDwarfEncoding.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
@ -1234,15 +1228,10 @@
05CD31630EE93905000FDE88 /* libCrashReporter-iphonesimulator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libCrashReporter-iphonesimulator.a"; sourceTree = BUILT_PRODUCTS_DIR; };
05CD31890EE93A90000FDE88 /* CrashReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrashReporter.h; sourceTree = "<group>"; };
05CD318A0EE93A90000FDE88 /* CrashReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CrashReporter.m; sourceTree = "<group>"; };
05CD32690EE93DC3000FDE88 /* Tests-MacOSX.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Tests-MacOSX.octest"; sourceTree = BUILT_PRODUCTS_DIR; };
05CD32690EE93DC3000FDE88 /* Tests-MacOSX.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Tests-MacOSX.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
05CD326A0EE93DC3000FDE88 /* Tests-MacOSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-MacOSX-Info.plist"; sourceTree = "<group>"; };
05CD328B0EE93F5E000FDE88 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDefines.h; sourceTree = "<group>"; };
05CD328C0EE93F7C000FDE88 /* GTMSenTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMSenTestCase.h; path = UnitTesting/GTMSenTestCase.h; sourceTree = "<group>"; };
05CD328D0EE93F7C000FDE88 /* GTMSenTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTMSenTestCase.m; path = UnitTesting/GTMSenTestCase.m; sourceTree = "<group>"; };
05CD32A90EE94062000FDE88 /* Tests-iOS-Simulator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tests-iOS-Simulator.app"; sourceTree = BUILT_PRODUCTS_DIR; };
05CD32AF0EE94086000FDE88 /* Tests-iPhone-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Tests-iPhone-Info.plist"; sourceTree = "<group>"; };
05CD32B00EE940B8000FDE88 /* GTMIPhoneUnitTestDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTMIPhoneUnitTestDelegate.m; path = UnitTesting/GTMIPhoneUnitTestDelegate.m; sourceTree = "<group>"; };
05CD32B10EE940B8000FDE88 /* GTMIPhoneUnitTestMain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTMIPhoneUnitTestMain.m; path = UnitTesting/GTMIPhoneUnitTestMain.m; sourceTree = "<group>"; };
05CD33240EE94439000FDE88 /* Tests-iOS-Device.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tests-iOS-Device.app"; sourceTree = BUILT_PRODUCTS_DIR; };
05CD33520EE9457D000FDE88 /* CrashReporter.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = CrashReporter.exp; sourceTree = "<group>"; };
05CD339A0EE948EB000FDE88 /* PLCrashSignalHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLCrashSignalHandler.h; sourceTree = "<group>"; };
@ -1324,8 +1313,6 @@
05F4150C0EF9DD9B008050CF /* PLCrashReportBinaryImageInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLCrashReportBinaryImageInfo.m; sourceTree = "<group>"; };
05F415510EF9E078008050CF /* PLCrashReportExceptionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLCrashReportExceptionInfo.h; sourceTree = "<group>"; };
05F415520EF9E078008050CF /* PLCrashReportExceptionInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLCrashReportExceptionInfo.m; sourceTree = "<group>"; };
05F76DCF162DBF8300A668C7 /* GTMObjC2Runtime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GTMObjC2Runtime.h; path = Foundation/GTMObjC2Runtime.h; sourceTree = "<group>"; };
05F76DD0162DC2BC00A668C7 /* GTMGarbageCollection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GTMGarbageCollection.h; path = Foundation/GTMGarbageCollection.h; sourceTree = "<group>"; };
05F76DD2162F213E00A668C7 /* PLCrashAsyncMachOImage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = PLCrashAsyncMachOImage.c; sourceTree = "<group>"; };
05F76DD7162F215800A668C7 /* PLCrashAsyncMachOImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLCrashAsyncMachOImage.h; sourceTree = "<group>"; };
05F76DD9162F238E00A668C7 /* PLCrashAsyncMachOImageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLCrashAsyncMachOImageTests.m; sourceTree = "<group>"; };
@ -1461,7 +1448,7 @@
8DC2EF5B0486A6940098B216 /* CrashReporter.framework */,
05CD31520EE936A9000FDE88 /* libCrashReporter-iphoneos.a */,
05CD31630EE93905000FDE88 /* libCrashReporter-iphonesimulator.a */,
05CD32690EE93DC3000FDE88 /* Tests-MacOSX.octest */,
05CD32690EE93DC3000FDE88 /* Tests-MacOSX.xctest */,
05CD32A90EE94062000FDE88 /* Tests-iOS-Simulator.app */,
05CD33240EE94439000FDE88 /* Tests-iOS-Device.app */,
05F40CE70EF7AB80008050CF /* DemoCrash.app */,
@ -1895,28 +1882,6 @@
name = "Host and Process Info";
sourceTree = "<group>";
};
05CD32750EE93E5A000FDE88 /* Tools */ = {
isa = PBXGroup;
children = (
05CD32890EE93F44000FDE88 /* google-toolbox-for-mac-trunk-r582 */,
);
path = Tools;
sourceTree = "<group>";
};
05CD32890EE93F44000FDE88 /* google-toolbox-for-mac-trunk-r582 */ = {
isa = PBXGroup;
children = (
05F76DD0162DC2BC00A668C7 /* GTMGarbageCollection.h */,
05F76DCF162DBF8300A668C7 /* GTMObjC2Runtime.h */,
05CD328C0EE93F7C000FDE88 /* GTMSenTestCase.h */,
05CD328D0EE93F7C000FDE88 /* GTMSenTestCase.m */,
05CD328B0EE93F5E000FDE88 /* GTMDefines.h */,
05CD32B10EE940B8000FDE88 /* GTMIPhoneUnitTestMain.m */,
05CD32B00EE940B8000FDE88 /* GTMIPhoneUnitTestDelegate.m */,
);
path = "google-toolbox-for-mac-trunk-r582";
sourceTree = "<group>";
};
05D8FE4916ACAA44000ED70C /* Allocator */ = {
isa = PBXGroup;
children = (
@ -2091,7 +2056,6 @@
089C1665FE841158C02AAC07 /* Resources */,
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
034768DFFF38A50411DB9C8B /* Products */,
05CD32750EE93E5A000FDE88 /* Tools */,
059670E30EEFADA6008A0601 /* Dependencies */,
);
name = CrashReporter;
@ -2165,8 +2129,9 @@
32C88DFF0371C24200C91783 /* Other Sources */ = {
isa = PBXGroup;
children = (
05614E111A965A6100D62442 /* SenTestCompat.h */,
);
name = "Other Sources";
path = "Other Sources";
sourceTree = "<group>";
};
FCE4576E42A51370AD81A734 /* Stack Frame Unwind */ = {
@ -2549,8 +2514,8 @@
);
name = "Tests-MacOSX";
productName = "Tests-MacOSX";
productReference = 05CD32690EE93DC3000FDE88 /* Tests-MacOSX.octest */;
productType = "com.apple.product-type.bundle.ocunit-test";
productReference = 05CD32690EE93DC3000FDE88 /* Tests-MacOSX.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
05CD32A80EE94062000FDE88 /* Tests-iOS-Simulator */ = {
isa = PBXNativeTarget;
@ -3009,7 +2974,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
05CD328E0EE93F7C000FDE88 /* GTMSenTestCase.m in Sources */,
05CD33A30EE94931000FDE88 /* PLCrashSignalHandlerTests.m in Sources */,
059666E30EEDDFCC008A0601 /* PLCrashFrameWalkerTests.m in Sources */,
0596702E0EEF6B51008A0601 /* PLCrashLogWriterTests.m in Sources */,
@ -3113,9 +3077,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
05CD32F00EE94148000FDE88 /* GTMSenTestCase.m in Sources */,
05CD32B20EE940B8000FDE88 /* GTMIPhoneUnitTestDelegate.m in Sources */,
05CD32B30EE940B8000FDE88 /* GTMIPhoneUnitTestMain.m in Sources */,
05CD33A40EE94931000FDE88 /* PLCrashSignalHandlerTests.m in Sources */,
059666E50EEDDFCC008A0601 /* PLCrashFrameWalkerTests.m in Sources */,
0596702F0EEF6B51008A0601 /* PLCrashLogWriterTests.m in Sources */,
@ -3218,9 +3179,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
05CD332C0EE94464000FDE88 /* GTMSenTestCase.m in Sources */,
05CD332D0EE94464000FDE88 /* GTMIPhoneUnitTestDelegate.m in Sources */,
05CD332E0EE94464000FDE88 /* GTMIPhoneUnitTestMain.m in Sources */,
05CD33A50EE94931000FDE88 /* PLCrashSignalHandlerTests.m in Sources */,
059666E40EEDDFCC008A0601 /* PLCrashFrameWalkerTests.m in Sources */,
059670300EEF6B51008A0601 /* PLCrashLogWriterTests.m in Sources */,
@ -3955,20 +3913,13 @@
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
EFFECTIVE_PLATFORM_NAME = "-MacOSX";
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
INFOPLIST_FILE = "Resources/Tests-MacOSX-Info.plist";
INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles";
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks $(DEVELOPER_DIR)/Library/Frameworks";
OTHER_LDFLAGS = (
"-framework",
Cocoa,
"-framework",
SenTestingKit,
);
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks";
PRODUCT_NAME = "Tests-MacOSX";
SDKROOT = macosx;
SKIP_INSTALL = YES;
@ -3976,7 +3927,7 @@
"$(inherited)",
"$(OTHER_WARNING_NO_ADDRESS)",
);
WRAPPER_EXTENSION = octest;
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
@ -3989,18 +3940,11 @@
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
EFFECTIVE_PLATFORM_NAME = "-MacOSX";
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_MODEL_TUNING = G5;
INFOPLIST_FILE = "Resources/Tests-MacOSX-Info.plist";
INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles";
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks $(DEVELOPER_DIR)/Library/Frameworks";
OTHER_LDFLAGS = (
"-framework",
Cocoa,
"-framework",
SenTestingKit,
);
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks";
PRODUCT_NAME = "Tests-MacOSX";
SDKROOT = macosx;
SKIP_INSTALL = YES;
@ -4008,7 +3952,7 @@
"$(inherited)",
"$(OTHER_WARNING_NO_ADDRESS)",
);
WRAPPER_EXTENSION = octest;
WRAPPER_EXTENSION = xctest;
ZERO_LINK = NO;
};
name = Release;
@ -4351,7 +4295,7 @@
1DEB91B208733DA50010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = "1.2.1";
CURRENT_PROJECT_VERSION = 1.2.1;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@ -4380,7 +4324,7 @@
1DEB91B308733DA50010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = "1.2.1";
CURRENT_PROJECT_VERSION = 1.2.1;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;

Просмотреть файл

@ -0,0 +1,95 @@
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2015 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Minimal compatibility shims to support existing tests written against the SenTestCase (aka OCUnit) API. This
* allows us to support Apple's new XCTest framework without polluting existing test cases with spurious changes.
*
* The APIs are nearly identical, and can be aliased directly.
*/
#import <XCTest/XCTest.h>
@compatibility_alias SenTestCase XCTestCase;
@compatibility_alias SenTestSuite XCTestSuite;
#define STAssertNil(a1, description, ...) XCTAssertNil(a1, description, ##__VA_ARGS__)
#define STAssertNotNil(a1, description, ...) XCTAssertNotNil(a1, description, ##__VA_ARGS__)
#define STAssertTrue(expression, description, ...) XCTAssertTrue(expression, description, ##__VA_ARGS__)
#define STAssertFalse(expression, description, ...) XCTAssertFalse(expression, description, ##__VA_ARGS__)
#define STAssertEqualObjects(a1, a2, description, ...) XCTAssertEqualObjects(a1, a2, description, ##__VA_ARGS__)
#define STAssertEquals(a1, a2, description, ...) XCTAssertEqual(a1, a2, description, ##__VA_ARGS__)
#define STAssertEqualsWithAccuracy(left, right, accuracy, description, ...) XCTAssertEqualsWithAccuracy(left, right, accuracy, description, ##__VA_ARGS__)
#define STAssertThrows(expression, description, ...) XCTAssertThrows(expression, description, ##__VA_ARGS__)
#define STAssertThrowsSpecific(expression, specificException, description, ...) XCTAssertThrowsSpecific(expression, specificException, description, ##__VA_ARGS__)
#define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) XCTAssertThrowsSpecificNamed(expr, specificException, aName, description, ##__VA_ARGS__)
#define STAssertNoThrow(expression, description, ...) XCTAssertNoThrow(expression, description, ##__VA_ARGS__)
#define STAssertNoThrowSpecific(expression, specificException, description, ...) XCTAssertNoThrowSpecific(expression, specificException, description, ##__VA_ARGS__)
#define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) XCTAssertNoThrowSpecificNamed(expr, specificException, aName, description, ##__VA_ARGS__)
#define STFail(description, ...) XCTFail(description, ##__VA_ARGS__)
#define STAssertTrueNoThrow(expression, description, ...) XCTAssertTrueNoThrow(expression, description, ##__VA_ARGS__)
#define STAssertFalseNoThrow(expression, description, ...) XCTAssertFalseNoThrow(expression, description, ##__VA_ARGS__)
/* The following assertions re-implement extensions that were provided by Google's GTM library, which were used throughout the PLCrashReporter tests */
#define STAssertNotEquals(a1, a2, description, ...) XCTAssertNotEqual(a1, a2, description, ##__VA_ARGS__)
#define STAssertEqualStrings(a1, a2, description, ...) XCTAssertEqualObjects(a1, a2, description, ##__VA_ARGS__)
#define STAssertLessThan(a1, a2, description, ...) XCTAssertLessThan(a1, a2, description, ##__VA_ARGS__)
#define STAssertGreaterThan(a1, a2, description, ...) XCTAssertGreaterThan(a1, a2, description, ##__VA_ARGS__)
#define STAssertEqualCStrings(a1, a2, description, ...) do { \
if (strcmp(a1, a2) != 0) { \
NSString *msg = [NSString stringWithFormat: description, ##__VA_ARGS__]; \
XCTFail(@"%s == %s: %@", "" #a1, "" #a2, msg); \
} \
} while(0)
#define STAssertNotEqualCStrings(a1, a2, description, ...) do { \
if (strcmp(a1, a2) == 0) { \
NSString *msg = [NSString stringWithFormat: description, ##__VA_ARGS__]; \
XCTFail(@"%s != %s: %@", "" #a1, "" #a2, msg); \
} \
} while(0)
#define STAssertNotNULL(a1, description, ...) do { \
const void *expressionValue = a1; \
if (expressionValue == NULL) { \
NSString *msg = [NSString stringWithFormat: description, ##__VA_ARGS__]; \
XCTFail(@"%s != NULL: %@", "" #a1, msg); \
} \
} while(0)
#define STAssertNULL(a1, description, ...) do { \
const void *expressionValue = a1; \
if (expressionValue != NULL) { \
NSString *msg = [NSString stringWithFormat: description, ##__VA_ARGS__]; \
XCTFail(@"%s == NULL: %@", "" #a1, msg); \
} \
} while(0)

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncAllocator.h"
@interface PLCrashAsyncAllocatorTests : SenTestCase {

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncImageList.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncLinkedList.hpp"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncMObject.h"
@interface PLCrashAsyncMObjectTests : SenTestCase {

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncMachExceptionInfo.h"
#import "PLCrashFeatureConfig.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncMachOImage.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import <dlfcn.h>
#import <mach-o/dyld.h>

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import <dlfcn.h>
#import <mach-o/dyld.h>

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncSignalInfo.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import <dlfcn.h>
#import <mach-o/dyld.h>

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsync.h"
#import <fcntl.h>

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncThread.h"
#import "PLCrashTestThread.h"

Просмотреть файл

@ -25,7 +25,7 @@
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashFrameCompactUnwind.h"
#import "PLCrashFeatureConfig.h"

Просмотреть файл

@ -25,7 +25,7 @@
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashFrameDWARFUnwind.h"
#import "PLCrashFeatureConfig.h"

Просмотреть файл

@ -27,7 +27,7 @@
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashFrameStackUnwind.h"
struct stack_frame {

Просмотреть файл

@ -28,7 +28,7 @@
#import <pthread.h>
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashFrameWalker.h"
#import "PLCrashTestThread.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashSysctl.h"
#import "PLCrashHostInfo.h"

Просмотреть файл

@ -26,14 +26,14 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsync.h"
#import "PLCrashLogWriterEncoding.h"
#import "protobuf-c.h"
#import "PLCrashLogWriterEncodingTests.pb-c.h"
@interface PLCrashLogWriterEncodingTests : GTMTestCase {
@interface PLCrashLogWriterEncodingTests : SenTestCase {
@private
plcrash_async_file_t _file;
NSString *_filePath;

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashLogWriter.h"
#import "PLCrashFrameWalker.h"

Просмотреть файл

@ -30,7 +30,7 @@
#if PLCRASH_FEATURE_MACH_EXCEPTIONS
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashMachExceptionPortSet.h"
@interface PLCrashMachExceptionPortSetTests : SenTestCase {

Просмотреть файл

@ -30,7 +30,7 @@
#if PLCRASH_FEATURE_MACH_EXCEPTIONS
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashMachExceptionPort.h"
#import "PLCrashAsync.h"

Просмотреть файл

@ -30,7 +30,7 @@
#if PLCRASH_FEATURE_MACH_EXCEPTIONS
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashMachExceptionServer.h"
#import "PLCrashMachExceptionPort.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashSysctl.h"
#import "PLCrashProcessInfo.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashReport.h"
#import "PLCrashReporter.h"
#import "PLCrashFrameWalker.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashReporterNSError.h"
@interface PLCrashReporterNSErrorTests : SenTestCase @end

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashReport.h"
#import "PLCrashReporter.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashSignalHandler.h"
#import "PLCrashProcessInfo.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashSysctl.h"

Просмотреть файл

@ -27,7 +27,7 @@
*/
#import <Foundation/Foundation.h>
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
@interface PLCrashTestCase : SenTestCase {
}

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashAsyncThread.h"
#import "PLCrashTestThread.h"

Просмотреть файл

@ -26,7 +26,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "GTMSenTestCase.h"
#import "SenTestCompat.h"
#import "PLCrashSignalHandler.h"
#import "PLCrashProcessInfo.h"

Просмотреть файл

@ -1,72 +0,0 @@
//
// GTMGarbageCollection.h
//
// Copyright 2007-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import <Foundation/Foundation.h>
#import "GTMDefines.h"
// This allows us to easily move our code from GC to non GC.
// They are no-ops unless we are require Leopard or above.
// See
// http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/index.html
// and
// http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html#//apple_ref/doc/uid/TP40006687-SW1
// for details.
#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) && !GTM_IPHONE_SDK
// General use would be to call this through GTMCFAutorelease
// but there may be a reason the you want to make something collectable
// but not autoreleased, especially in pure GC code where you don't
// want to bother with the nop autorelease. Done as a define instead of an
// inline so that tools like Clang's scan-build don't report code as leaking.
#define GTMNSMakeCollectable(cf) ((id)NSMakeCollectable(cf))
// GTMNSMakeUncollectable is for global maps, etc. that we don't
// want released ever. You should still retain these in non-gc code.
GTM_INLINE void GTMNSMakeUncollectable(id object) {
[[NSGarbageCollector defaultCollector] disableCollectorForPointer:object];
}
// Hopefully no code really needs this, but GTMIsGarbageCollectionEnabled is
// a common way to check at runtime if GC is on.
// There are some places where GC doesn't work w/ things w/in Apple's
// frameworks, so this is here so GTM unittests and detect it, and not run
// individual tests to work around bugs in Apple's frameworks.
GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
return ([NSGarbageCollector defaultCollector] != nil);
}
#else
#define GTMNSMakeCollectable(cf) ((id)(cf))
GTM_INLINE void GTMNSMakeUncollectable(id object) {
}
GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
return NO;
}
#endif
// GTMCFAutorelease makes a CF object collectable in GC mode, or adds it
// to the autorelease pool in non-GC mode. Either way it is taken care
// of. Done as a define instead of an inline so that tools like Clang's
// scan-build don't report code as leaking.
#define GTMCFAutorelease(cf) ([GTMNSMakeCollectable(cf) autorelease])

Просмотреть файл

@ -1,113 +0,0 @@
//
// GTMObjC2Runtime.h
//
// Copyright 2007-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import <objc/objc-api.h>
#import <objc/objc-auto.h>
#import "GTMDefines.h"
// These functions exist for code that we want to compile on both the < 10.5
// sdks and on the >= 10.5 sdks without warnings. It basically reimplements
// certain parts of the objc2 runtime in terms of the objc1 runtime. It is not
// a complete implementation as I've only implemented the routines I know we
// use. Feel free to add more as necessary.
// These functions are not documented because they conform to the documentation
// for the ObjC2 Runtime.
#if OBJC_API_VERSION >= 2 // Only have optional and req'd keywords in ObjC2.
#define AT_OPTIONAL @optional
#define AT_REQUIRED @required
#else
#define AT_OPTIONAL
#define AT_REQUIRED
#endif
// The file objc-runtime.h was moved to runtime.h and in Leopard, objc-runtime.h
// was just a wrapper around runtime.h. For the iPhone SDK, this objc-runtime.h
// is removed in the iPhoneOS2.0 SDK.
//
// The |Object| class was removed in the iPhone2.0 SDK too.
#if GTM_IPHONE_SDK
#import <objc/message.h>
#import <objc/runtime.h>
#else
#import <objc/objc-runtime.h>
#import <objc/Object.h>
#endif
#import <libkern/OSAtomic.h>
#if GTM_MACOS_SDK && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
#import "objc/Protocol.h"
OBJC_EXPORT Class object_getClass(id obj);
OBJC_EXPORT const char *class_getName(Class cls);
OBJC_EXPORT BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
OBJC_EXPORT BOOL class_respondsToSelector(Class cls, SEL sel);
OBJC_EXPORT Class class_getSuperclass(Class cls);
OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount);
OBJC_EXPORT SEL method_getName(Method m);
OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2);
OBJC_EXPORT IMP method_getImplementation(Method method);
OBJC_EXPORT IMP method_setImplementation(Method method, IMP imp);
OBJC_EXPORT struct objc_method_description protocol_getMethodDescription(Protocol *p,
SEL aSel,
BOOL isRequiredMethod,
BOOL isInstanceMethod);
OBJC_EXPORT BOOL sel_isEqual(SEL lhs, SEL rhs);
// If building for 10.4 but using the 10.5 SDK, don't include these.
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
// atomics
// On Leopard these are GC aware
// Intentionally did not include the non-barrier versions, because I couldn't
// come up with a case personally where you wouldn't want to use the
// barrier versions.
GTM_INLINE bool OSAtomicCompareAndSwapPtrBarrier(void *predicate,
void *replacement,
void * volatile *theValue) {
#if defined(__LP64__) && __LP64__
return OSAtomicCompareAndSwap64Barrier((int64_t)predicate,
(int64_t)replacement,
(int64_t *)theValue);
#else // defined(__LP64__) && __LP64__
return OSAtomicCompareAndSwap32Barrier((int32_t)predicate,
(int32_t)replacement,
(int32_t *)theValue);
#endif // defined(__LP64__) && __LP64__
}
#endif // MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
#endif // GTM_MACOS_SDK && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
#if GTM_MACOS_SDK && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
GTM_INLINE BOOL objc_atomicCompareAndSwapGlobalBarrier(id predicate,
id replacement,
volatile id *objectLocation) {
return OSAtomicCompareAndSwapPtrBarrier(predicate,
replacement,
(void * volatile *)objectLocation);
}
GTM_INLINE BOOL objc_atomicCompareAndSwapInstanceVariableBarrier(id predicate,
id replacement,
volatile id *objectLocation) {
return OSAtomicCompareAndSwapPtrBarrier(predicate,
replacement,
(void * volatile *)objectLocation);
}
#endif // GTM_MACOS_SDK && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)

Просмотреть файл

@ -1,444 +0,0 @@
//
// GTMDefines.h
//
// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// ============================================================================
#include <AvailabilityMacros.h>
#include <TargetConditionals.h>
#ifdef __OBJC__
#include <Foundation/NSObjCRuntime.h>
#endif // __OBJC__
#if TARGET_OS_IPHONE
#include <Availability.h>
#endif // TARGET_OS_IPHONE
// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs
#ifndef MAC_OS_X_VERSION_10_5
#define MAC_OS_X_VERSION_10_5 1050
#endif
#ifndef MAC_OS_X_VERSION_10_6
#define MAC_OS_X_VERSION_10_6 1060
#endif
#ifndef MAC_OS_X_VERSION_10_7
#define MAC_OS_X_VERSION_10_7 1070
#endif
// Not all __IPHONE_X macros defined in past SDKs
#ifndef __IPHONE_3_0
#define __IPHONE_3_0 30000
#endif
#ifndef __IPHONE_3_1
#define __IPHONE_3_1 30100
#endif
#ifndef __IPHONE_3_2
#define __IPHONE_3_2 30200
#endif
#ifndef __IPHONE_4_0
#define __IPHONE_4_0 40000
#endif
#ifndef __IPHONE_4_3
#define __IPHONE_4_3 40300
#endif
#ifndef __IPHONE_5_0
#define __IPHONE_5_0 50000
#endif
// ----------------------------------------------------------------------------
// CPP symbols that can be overridden in a prefix to control how the toolbox
// is compiled.
// ----------------------------------------------------------------------------
// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
// when a validation fails. If you implement your own validators, you may want
// to control their internals using the same macros for consistency.
#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
#define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
#endif
// Give ourselves a consistent way to do inlines. Apple's macros even use
// a few different actual definitions, so we're based off of the foundation
// one.
#if !defined(GTM_INLINE)
#if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__)
#define GTM_INLINE static __inline__ __attribute__((always_inline))
#else
#define GTM_INLINE static __inline__
#endif
#endif
// Give ourselves a consistent way of doing externs that links up nicely
// when mixing objc and objc++
#if !defined (GTM_EXTERN)
#if defined __cplusplus
#define GTM_EXTERN extern "C"
#define GTM_EXTERN_C_BEGIN extern "C" {
#define GTM_EXTERN_C_END }
#else
#define GTM_EXTERN extern
#define GTM_EXTERN_C_BEGIN
#define GTM_EXTERN_C_END
#endif
#endif
// Give ourselves a consistent way of exporting things if we have visibility
// set to hidden.
#if !defined (GTM_EXPORT)
#define GTM_EXPORT __attribute__((visibility("default")))
#endif
// Give ourselves a consistent way of declaring something as unused. This
// doesn't use __unused because that is only supported in gcc 4.2 and greater.
#if !defined (GTM_UNUSED)
#define GTM_UNUSED(x) ((void)(x))
#endif
// _GTMDevLog & _GTMDevAssert
//
// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
// developer level errors. This implementation simply macros to NSLog/NSAssert.
// It is not intended to be a general logging/reporting system.
//
// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
// for a little more background on the usage of these macros.
//
// _GTMDevLog log some error/problem in debug builds
// _GTMDevAssert assert if conditon isn't met w/in a method/function
// in all builds.
//
// To replace this system, just provide different macro definitions in your
// prefix header. Remember, any implementation you provide *must* be thread
// safe since this could be called by anything in what ever situtation it has
// been placed in.
//
// We only define the simple macros if nothing else has defined this.
#ifndef _GTMDevLog
#ifdef DEBUG
#define _GTMDevLog(...) NSLog(__VA_ARGS__)
#else
#define _GTMDevLog(...) do { } while (0)
#endif
#endif // _GTMDevLog
#ifndef _GTMDevAssert
// we directly invoke the NSAssert handler so we can pass on the varargs
// (NSAssert doesn't have a macro we can use that takes varargs)
#if !defined(NS_BLOCK_ASSERTIONS)
#define _GTMDevAssert(condition, ...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
file:[NSString stringWithUTF8String:__FILE__] \
lineNumber:__LINE__ \
description:__VA_ARGS__]; \
} \
} while(0)
#else // !defined(NS_BLOCK_ASSERTIONS)
#define _GTMDevAssert(condition, ...) do { } while (0)
#endif // !defined(NS_BLOCK_ASSERTIONS)
#endif // _GTMDevAssert
// _GTMCompileAssert
// _GTMCompileAssert is an assert that is meant to fire at compile time if you
// want to check things at compile instead of runtime. For example if you
// want to check that a wchar is 4 bytes instead of 2 you would use
// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
// Note that the second "arg" is not in quotes, and must be a valid processor
// symbol in it's own right (no spaces, punctuation etc).
// Wrapping this in an #ifndef allows external groups to define their own
// compile time assert scheme.
#ifndef _GTMCompileAssert
// We got this technique from here:
// http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
#define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
#define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
#define _GTMCompileAssert(test, msg) \
typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
#endif // _GTMCompileAssert
// ----------------------------------------------------------------------------
// CPP symbols defined based on the project settings so the GTM code has
// simple things to test against w/o scattering the knowledge of project
// setting through all the code.
// ----------------------------------------------------------------------------
// Provide a single constant CPP symbol that all of GTM uses for ifdefing
// iPhone code.
#if TARGET_OS_IPHONE // iPhone SDK
// For iPhone specific stuff
#define GTM_IPHONE_SDK 1
#if TARGET_IPHONE_SIMULATOR
#define GTM_IPHONE_SIMULATOR 1
#else
#define GTM_IPHONE_DEVICE 1
#endif // TARGET_IPHONE_SIMULATOR
// By default, GTM has provided it's own unittesting support, define this
// to use the support provided by Xcode, especially for the Xcode4 support
// for unittesting.
#ifndef GTM_IPHONE_USE_SENTEST
#define GTM_IPHONE_USE_SENTEST 0
#endif
#else
// For MacOS specific stuff
#define GTM_MACOS_SDK 1
#endif
// Some of our own availability macros
#if GTM_MACOS_SDK
#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE
#define GTM_AVAILABLE_ONLY_ON_MACOS
#else
#define GTM_AVAILABLE_ONLY_ON_IPHONE
#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE
#endif
// Provide a symbol to include/exclude extra code for GC support. (This mainly
// just controls the inclusion of finalize methods).
#ifndef GTM_SUPPORT_GC
#if GTM_IPHONE_SDK
// iPhone never needs GC
#define GTM_SUPPORT_GC 0
#else
// We can't find a symbol to tell if GC is supported/required, so best we
// do on Mac targets is include it if we're on 10.5 or later.
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define GTM_SUPPORT_GC 0
#else
#define GTM_SUPPORT_GC 1
#endif
#endif
#endif
// To simplify support for 64bit (and Leopard in general), we provide the type
// defines for non Leopard SDKs
#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
// NSInteger/NSUInteger and Max/Mins
#ifndef NSINTEGER_DEFINED
#if __LP64__ || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
#define NSIntegerMax LONG_MAX
#define NSIntegerMin LONG_MIN
#define NSUIntegerMax ULONG_MAX
#define NSINTEGER_DEFINED 1
#endif // NSINTEGER_DEFINED
// CGFloat
#ifndef CGFLOAT_DEFINED
#if defined(__LP64__) && __LP64__
// This really is an untested path (64bit on Tiger?)
typedef double CGFloat;
#define CGFLOAT_MIN DBL_MIN
#define CGFLOAT_MAX DBL_MAX
#define CGFLOAT_IS_DOUBLE 1
#else /* !defined(__LP64__) || !__LP64__ */
typedef float CGFloat;
#define CGFLOAT_MIN FLT_MIN
#define CGFLOAT_MAX FLT_MAX
#define CGFLOAT_IS_DOUBLE 0
#endif /* !defined(__LP64__) || !__LP64__ */
#define CGFLOAT_DEFINED 1
#endif // CGFLOAT_DEFINED
#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
// Some support for advanced clang static analysis functionality
// See http://clang-analyzer.llvm.org/annotations.html
#ifndef __has_feature // Optional.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
#ifndef NS_RETURNS_RETAINED
#if __has_feature(attribute_ns_returns_retained)
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
#else
#define NS_RETURNS_RETAINED
#endif
#endif
#ifndef NS_RETURNS_NOT_RETAINED
#if __has_feature(attribute_ns_returns_not_retained)
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
#else
#define NS_RETURNS_NOT_RETAINED
#endif
#endif
#ifndef CF_RETURNS_RETAINED
#if __has_feature(attribute_cf_returns_retained)
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
#else
#define CF_RETURNS_RETAINED
#endif
#endif
#ifndef CF_RETURNS_NOT_RETAINED
#if __has_feature(attribute_cf_returns_not_retained)
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
#else
#define CF_RETURNS_NOT_RETAINED
#endif
#endif
#ifndef NS_CONSUMED
#if __has_feature(attribute_ns_consumed)
#define NS_CONSUMED __attribute__((ns_consumed))
#else
#define NS_CONSUMED
#endif
#endif
#ifndef CF_CONSUMED
#if __has_feature(attribute_cf_consumed)
#define CF_CONSUMED __attribute__((cf_consumed))
#else
#define CF_CONSUMED
#endif
#endif
#ifndef NS_CONSUMES_SELF
#if __has_feature(attribute_ns_consumes_self)
#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
#else
#define NS_CONSUMES_SELF
#endif
#endif
// Defined on 10.6 and above.
#ifndef NS_FORMAT_ARGUMENT
#define NS_FORMAT_ARGUMENT(A)
#endif
// Defined on 10.6 and above.
#ifndef NS_FORMAT_FUNCTION
#define NS_FORMAT_FUNCTION(F,A)
#endif
// Defined on 10.6 and above.
#ifndef CF_FORMAT_ARGUMENT
#define CF_FORMAT_ARGUMENT(A)
#endif
// Defined on 10.6 and above.
#ifndef CF_FORMAT_FUNCTION
#define CF_FORMAT_FUNCTION(F,A)
#endif
#ifndef GTM_NONNULL
#define GTM_NONNULL(x) __attribute__((nonnull(x)))
#endif
// Invalidates the initializer from which it's called.
#ifndef GTMInvalidateInitializer
#if __has_feature(objc_arc)
#define GTMInvalidateInitializer() \
do { \
[self class]; /* Avoid warning of dead store to |self|. */ \
_GTMDevAssert(NO, @"Invalid initializer."); \
return nil; \
} while (0)
#else
#define GTMInvalidateInitializer() \
do { \
[self release]; \
_GTMDevAssert(NO, @"Invalid initializer."); \
return nil; \
} while (0)
#endif
#endif
#ifdef __OBJC__
// Declared here so that it can easily be used for logging tracking if
// necessary. See GTMUnitTestDevLog.h for details.
@class NSString;
GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2);
// Macro to allow you to create NSStrings out of other macros.
// #define FOO foo
// NSString *fooString = GTM_NSSTRINGIFY(FOO);
#if !defined (GTM_NSSTRINGIFY)
#define GTM_NSSTRINGIFY_INNER(x) @#x
#define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x)
#endif
// Macro to allow fast enumeration when building for 10.5 or later, and
// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration
// does keys, so pick the right thing, nothing is done on the FastEnumeration
// side to be sure you're getting what you wanted.
#ifndef GTM_FOREACH_OBJECT
#if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
for (element in enumeration)
#define GTM_FOREACH_OBJECT(element, collection) \
for (element in collection)
#define GTM_FOREACH_KEY(element, collection) \
for (element in collection)
#else
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
for (NSEnumerator *_ ## element ## _enum = enumeration; \
(element = [_ ## element ## _enum nextObject]) != nil; )
#define GTM_FOREACH_OBJECT(element, collection) \
GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator])
#define GTM_FOREACH_KEY(element, collection) \
GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator])
#endif
#endif
// ============================================================================
// To simplify support for both Leopard and Snow Leopard we declare
// the Snow Leopard protocols that we need here.
#if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
#define GTM_10_6_PROTOCOLS_DEFINED 1
@protocol NSConnectionDelegate
@end
@protocol NSAnimationDelegate
@end
@protocol NSImageDelegate
@end
@protocol NSTabViewDelegate
@end
#endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
// GTM_SEL_STRING is for specifying selector (usually property) names to KVC
// or KVO methods.
// In debug it will generate warnings for undeclared selectors if
// -Wunknown-selector is turned on.
// In release it will have no runtime overhead.
#ifndef GTM_SEL_STRING
#ifdef DEBUG
#define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName))
#else
#define GTM_SEL_STRING(selName) @#selName
#endif // DEBUG
#endif // GTM_SEL_STRING
#endif // __OBJC__

Просмотреть файл

@ -1,240 +0,0 @@
//
// GTMIPhoneUnitTestDelegate.m
//
// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import "GTMIPhoneUnitTestDelegate.h"
#import "GTMDefines.h"
#if !GTM_IPHONE_SDK
#error GTMIPhoneUnitTestDelegate for iPhone only
#endif
#import <objc/runtime.h>
#import <stdio.h>
#import <UIKit/UIKit.h>
#import "GTMSenTestCase.h"
@interface UIApplication (GTMIPhoneUnitTestDelegate)
// SPI that we need to exit cleanly with a value.
- (void)_terminateWithStatus:(int)status;
@end
@interface GTMIPhoneUnitTestDelegate ()
// We have cases where we are created in UIApplicationMain, but then the
// user accidentally/intentionally replaces us as a delegate in their xib file
// which means that we never get the applicationDidFinishLaunching: message.
// We can register for the notification, but when the applications delegate
// is reset, it releases us, and we get dealloced. Therefore we have retainer
// which is responsible for retaining us until we get the notification.
// We do it through this slightly roundabout route (instead of just an extra
// retain in the init) so that clang doesn't complain about a leak.
// We also check to make sure we aren't called twice with the
// applicationDidFinishLaunchingCalled flag.
@property (readwrite, retain, nonatomic) GTMIPhoneUnitTestDelegate *retainer;
- (void)runTestsAndExit:(UIApplication *)application;
@end
@implementation GTMIPhoneUnitTestDelegate
@synthesize retainer = retainer_;
- (id)init {
if ((self = [super init])) {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(applicationDidFinishLaunching:)
name:UIApplicationDidFinishLaunchingNotification
object:[UIApplication sharedApplication]];
[self setRetainer:self];
}
return self;
}
// Run through all the registered classes and run test methods on any
// that are subclasses of SenTestCase. Terminate the application upon
// test completion.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// We could get called twice once from our notification registration, and
// once if we actually still are the delegate of the application after
// it has finished launching. So we'll just return if we've been called once.
if (applicationDidFinishLaunchingCalled_) return;
applicationDidFinishLaunchingCalled_ = YES;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self
name:UIApplicationDidFinishLaunchingNotification
object:[UIApplication sharedApplication]];
// To permit UI-based tests, run the tests and exit app in a delayed selector
// call. This ensures tests are run outside of applicationDidFinishLaunching:.
[self performSelector:@selector(runTestsAndExit:)
withObject:application
afterDelay:0];
}
// Run through all tests and then exit application if required.
- (void)runTestsAndExit:(UIApplication *)application {
[self runTests];
if (!getenv("GTM_DISABLE_TERMINATION")) {
// To help using xcodebuild, make the exit status 0/1 to signal the tests
// success/failure.
int exitStatus = (([self totalFailures] == 0U) ? 0 : 1);
// Alternative to exit(status); so it cleanly terminates the UIApplication
// and classes that depend on this signal to exit cleanly.
if ([application respondsToSelector:@selector(_terminateWithStatus:)]) {
[application performSelector:@selector(_terminateWithStatus:)
withObject:(id)(uintptr_t)exitStatus];
} else {
exit(exitStatus);
}
}
// Release ourself now that we're done. If we really are the application
// delegate, it will have retained us, so we'll stick around if necessary.
[self setRetainer:nil];
}
static int ClassSort(const void *a, const void *b) {
Class *classA = (Class *)a;
Class *classB = (Class *)b;
const char *nameA = class_getName(*classA);
const char *nameB = class_getName(*classB);
return strcmp(nameA, nameB);
}
// Run through all the registered classes and run test methods on any
// that are subclasses of SenTestCase. Print results and run time to
// the default output.
- (void)runTests {
int count = objc_getClassList(NULL, 0);
NSMutableData *classData
= [NSMutableData dataWithLength:sizeof(Class) * count];
Class *classes = (Class*)[classData mutableBytes];
_GTMDevAssert(classes, @"Couldn't allocate class list");
objc_getClassList(classes, count);
// Follow SenTest's lead and sort the classes. (This may only be a change
// in the iOS 5 runtime, but make sure it is always sorted just incase)
mergesort(classes, count, sizeof(Class), ClassSort);
totalFailures_ = 0;
totalSuccesses_ = 0;
NSString *suiteName = [[NSBundle mainBundle] bundlePath];
NSDate *suiteStartDate = [NSDate date];
NSString *suiteStartString
= [NSString stringWithFormat:@"Test Suite '%@' started at %@\n",
suiteName, suiteStartDate];
fputs([suiteStartString UTF8String], stderr);
fflush(stderr);
for (int i = 0; i < count; ++i) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Class currClass = classes[i];
if (class_respondsToSelector(currClass, @selector(conformsToProtocol:)) &&
[currClass conformsToProtocol:@protocol(SenTestCase)]) {
NSArray *invocations = [currClass testInvocations];
if ([invocations count]) {
NSDate *fixtureStartDate = [NSDate date];
NSString *fixtureName = NSStringFromClass(currClass);
NSString *fixtureStartString
= [NSString stringWithFormat:@"Test Suite '%@' started at %@\n",
fixtureName, fixtureStartDate];
int fixtureSuccesses = 0;
int fixtureFailures = 0;
fputs([fixtureStartString UTF8String], stderr);
fflush(stderr);
NSInvocation *invocation;
GTM_FOREACH_OBJECT(invocation, invocations) {
GTMTestCase *testCase
= [[currClass alloc] initWithInvocation:invocation];
BOOL failed = NO;
NSDate *caseStartDate = [NSDate date];
NSString *selectorName = NSStringFromSelector([invocation selector]);
NSString *caseStartString
= [NSString stringWithFormat:@"Test Case '-[%@ %@]' started.\n",
fixtureName, selectorName];
fputs([caseStartString UTF8String], stderr);
fflush(stderr);
@try {
[testCase performTest];
} @catch (NSException *exception) {
failed = YES;
}
if (failed) {
fixtureFailures += 1;
} else {
fixtureSuccesses += 1;
}
NSTimeInterval caseEndTime
= [[NSDate date] timeIntervalSinceDate:caseStartDate];
NSString *caseEndString
= [NSString stringWithFormat:@"Test Case '-[%@ %@]' %@ (%0.3f "
"seconds).\n",
fixtureName, selectorName,
failed ? @"failed" : @"passed",
caseEndTime];
fputs([caseEndString UTF8String], stderr);
fflush(stderr);
[testCase release];
}
NSDate *fixtureEndDate = [NSDate date];
NSTimeInterval fixtureEndTime
= [fixtureEndDate timeIntervalSinceDate:fixtureStartDate];
NSString *fixtureEndString
= [NSString stringWithFormat:@"Test Suite '%@' finished at %@.\n"
"Executed %d tests, with %d failures (%d "
"unexpected) in %0.3f (%0.3f) seconds\n\n",
fixtureName, fixtureEndDate,
fixtureSuccesses + fixtureFailures,
fixtureFailures, fixtureFailures,
fixtureEndTime, fixtureEndTime];
fputs([fixtureEndString UTF8String], stderr);
fflush(stderr);
totalSuccesses_ += fixtureSuccesses;
totalFailures_ += fixtureFailures;
}
}
[pool release];
}
NSDate *suiteEndDate = [NSDate date];
NSTimeInterval suiteEndTime
= [suiteEndDate timeIntervalSinceDate:suiteStartDate];
NSString *suiteEndString
= [NSString stringWithFormat:@"Test Suite '%@' finished at %@.\n"
"Executed %lu tests, with %lu failures (%lu "
"unexpected) in %0.3f (%0.3f) seconds\n\n",
suiteName, suiteEndDate,
(unsigned long)(totalSuccesses_ + totalFailures_),
(unsigned long)totalFailures_, (unsigned long)totalFailures_,
suiteEndTime, suiteEndTime];
fputs([suiteEndString UTF8String], stderr);
fflush(stderr);
}
- (NSUInteger)totalSuccesses {
return totalSuccesses_;
}
- (NSUInteger)totalFailures {
return totalFailures_;
}
@end

Просмотреть файл

@ -1,39 +0,0 @@
//
// GTMIPhoneUnitTestMain.m
//
// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import "GTMDefines.h"
#if !GTM_IPHONE_SDK
#error GTMIPhoneUnitTestMain for iPhone only
#endif
#import <UIKit/UIKit.h>
// Creates an application that runs all tests from classes extending
// SenTestCase, outputs results and test run time, and terminates right
// afterwards.
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
#if GTM_IPHONE_USE_SENTEST
// Is using SenTest, just create a dummy app that can be used as the
// TEST_HOST.
int retVal = UIApplicationMain(argc, argv, nil, nil);
#else
int retVal = UIApplicationMain(argc, argv, nil, @"GTMIPhoneUnitTestDelegate");
#endif
[pool release];
return retVal;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,500 +0,0 @@
//
// GTMSenTestCase.m
//
// Copyright 2007-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import "GTMSenTestCase.h"
#import <unistd.h>
#if GTM_IPHONE_SIMULATOR
#import <objc/message.h>
#endif
#import "GTMObjC2Runtime.h"
#import "GTMUnitTestDevLog.h"
#if !GTM_IPHONE_SDK
#import "GTMGarbageCollection.h"
#endif // !GTM_IPHONE_SDK
#if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
#import <stdarg.h>
@interface NSException (GTMSenTestPrivateAdditions)
+ (NSException *)failureInFile:(NSString *)filename
atLine:(int)lineNumber
reason:(NSString *)reason;
@end
@implementation NSException (GTMSenTestPrivateAdditions)
+ (NSException *)failureInFile:(NSString *)filename
atLine:(int)lineNumber
reason:(NSString *)reason {
NSDictionary *userInfo =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger:lineNumber], SenTestLineNumberKey,
filename, SenTestFilenameKey,
nil];
return [self exceptionWithName:SenTestFailureException
reason:reason
userInfo:userInfo];
}
@end
@implementation NSException (GTMSenTestAdditions)
+ (NSException *)failureInFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
NSString *testDescription = @"";
if (formatString) {
va_list vl;
va_start(vl, formatString);
testDescription =
[[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
va_end(vl);
}
NSString *reason = testDescription;
return [self failureInFile:filename atLine:lineNumber reason:reason];
}
+ (NSException *)failureInCondition:(NSString *)condition
isTrue:(BOOL)isTrue
inFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
NSString *testDescription = @"";
if (formatString) {
va_list vl;
va_start(vl, formatString);
testDescription =
[[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
va_end(vl);
}
NSString *reason = [NSString stringWithFormat:@"'%@' should be %s. %@",
condition, isTrue ? "false" : "true", testDescription];
return [self failureInFile:filename atLine:lineNumber reason:reason];
}
+ (NSException *)failureInEqualityBetweenObject:(id)left
andObject:(id)right
inFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
NSString *testDescription = @"";
if (formatString) {
va_list vl;
va_start(vl, formatString);
testDescription =
[[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
va_end(vl);
}
NSString *reason =
[NSString stringWithFormat:@"'%@' should be equal to '%@'. %@",
[left description], [right description], testDescription];
return [self failureInFile:filename atLine:lineNumber reason:reason];
}
+ (NSException *)failureInEqualityBetweenValue:(NSValue *)left
andValue:(NSValue *)right
withAccuracy:(NSValue *)accuracy
inFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
NSString *testDescription = @"";
if (formatString) {
va_list vl;
va_start(vl, formatString);
testDescription =
[[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
va_end(vl);
}
NSString *reason;
if (accuracy) {
reason =
[NSString stringWithFormat:@"'%@' should be equal to '%@'. %@",
left, right, testDescription];
} else {
reason =
[NSString stringWithFormat:@"'%@' should be equal to '%@' +/-'%@'. %@",
left, right, accuracy, testDescription];
}
return [self failureInFile:filename atLine:lineNumber reason:reason];
}
+ (NSException *)failureInRaise:(NSString *)expression
inFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
NSString *testDescription = @"";
if (formatString) {
va_list vl;
va_start(vl, formatString);
testDescription =
[[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
va_end(vl);
}
NSString *reason = [NSString stringWithFormat:@"'%@' should raise. %@",
expression, testDescription];
return [self failureInFile:filename atLine:lineNumber reason:reason];
}
+ (NSException *)failureInRaise:(NSString *)expression
exception:(NSException *)exception
inFile:(NSString *)filename
atLine:(int)lineNumber
withDescription:(NSString *)formatString, ... {
NSString *testDescription = @"";
if (formatString) {
va_list vl;
va_start(vl, formatString);
testDescription =
[[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
va_end(vl);
}
NSString *reason;
if ([[exception name] isEqualToString:SenTestFailureException]) {
// it's our exception, assume it has the right description on it.
reason = [exception reason];
} else {
// not one of our exception, use the exceptions reason and our description
reason = [NSString stringWithFormat:@"'%@' raised '%@'. %@",
expression, [exception reason], testDescription];
}
return [self failureInFile:filename atLine:lineNumber reason:reason];
}
@end
NSString *STComposeString(NSString *formatString, ...) {
NSString *reason = @"";
if (formatString) {
va_list vl;
va_start(vl, formatString);
reason =
[[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
va_end(vl);
}
return reason;
}
NSString *const SenTestFailureException = @"SenTestFailureException";
NSString *const SenTestFilenameKey = @"SenTestFilenameKey";
NSString *const SenTestLineNumberKey = @"SenTestLineNumberKey";
@interface SenTestCase (SenTestCasePrivate)
// our method of logging errors
+ (void)printException:(NSException *)exception fromTestName:(NSString *)name;
@end
@implementation SenTestCase
+ (id)testCaseWithInvocation:(NSInvocation *)anInvocation {
return [[[self alloc] initWithInvocation:anInvocation] autorelease];
}
- (id)initWithInvocation:(NSInvocation *)anInvocation {
if ((self = [super init])) {
invocation_ = [anInvocation retain];
}
return self;
}
- (void)dealloc {
[invocation_ release];
[super dealloc];
}
- (void)failWithException:(NSException*)exception {
[exception raise];
}
- (void)setUp {
}
- (void)performTest {
@try {
[self invokeTest];
} @catch (NSException *exception) {
[[self class] printException:exception
fromTestName:NSStringFromSelector([self selector])];
[exception raise];
}
}
- (NSInvocation *)invocation {
return invocation_;
}
- (SEL)selector {
return [invocation_ selector];
}
+ (void)printException:(NSException *)exception fromTestName:(NSString *)name {
NSDictionary *userInfo = [exception userInfo];
NSString *filename = [userInfo objectForKey:SenTestFilenameKey];
NSNumber *lineNumber = [userInfo objectForKey:SenTestLineNumberKey];
NSString *className = NSStringFromClass([self class]);
if ([filename length] == 0) {
filename = @"Unknown.m";
}
fprintf(stderr, "%s:%ld: error: -[%s %s] : %s\n",
[filename UTF8String],
(long)[lineNumber integerValue],
[className UTF8String],
[name UTF8String],
[[exception reason] UTF8String]);
fflush(stderr);
}
- (void)invokeTest {
NSException *e = nil;
@try {
// Wrap things in autorelease pools because they may
// have an STMacro in their dealloc which may get called
// when the pool is cleaned up
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// We don't log exceptions here, instead we let the person that called
// this log the exception. This ensures they are only logged once but the
// outer layers get the exceptions to report counts, etc.
@try {
[self setUp];
@try {
NSInvocation *invocation = [self invocation];
#if GTM_IPHONE_SIMULATOR
// We don't call [invocation invokeWithTarget:self]; because of
// Radar 8081169: NSInvalidArgumentException can't be caught
// It turns out that on iOS4 (and 3.2) exceptions thrown inside an
// [invocation invoke] on the simulator cannot be caught.
// http://openradar.appspot.com/8081169
objc_msgSend(self, [invocation selector]);
#else
[invocation invokeWithTarget:self];
#endif
} @catch (NSException *exception) {
e = [exception retain];
}
[self tearDown];
} @catch (NSException *exception) {
e = [exception retain];
}
[pool release];
} @catch (NSException *exception) {
e = [exception retain];
}
if (e) {
[e autorelease];
[e raise];
}
}
- (void)tearDown {
}
- (NSString *)description {
// This matches the description OCUnit would return to you
return [NSString stringWithFormat:@"-[%@ %@]", [self class],
NSStringFromSelector([self selector])];
}
// Used for sorting methods below
static NSInteger MethodSort(id a, id b, void *context) {
NSInvocation *invocationA = a;
NSInvocation *invocationB = b;
const char *nameA = sel_getName([invocationA selector]);
const char *nameB = sel_getName([invocationB selector]);
return strcmp(nameA, nameB);
}
+ (NSArray *)testInvocations {
NSMutableArray *invocations = nil;
// Need to walk all the way up the parent classes collecting methods (in case
// a test is a subclass of another test).
Class senTestCaseClass = [SenTestCase class];
for (Class currentClass = self;
currentClass && (currentClass != senTestCaseClass);
currentClass = class_getSuperclass(currentClass)) {
unsigned int methodCount;
Method *methods = class_copyMethodList(currentClass, &methodCount);
if (methods) {
// This handles disposing of methods for us even if an exception should fly.
[NSData dataWithBytesNoCopy:methods
length:sizeof(Method) * methodCount];
if (!invocations) {
invocations = [NSMutableArray arrayWithCapacity:methodCount];
}
for (size_t i = 0; i < methodCount; ++i) {
Method currMethod = methods[i];
SEL sel = method_getName(currMethod);
char *returnType = NULL;
const char *name = sel_getName(sel);
// If it starts with test, takes 2 args (target and sel) and returns
// void run it.
if (strstr(name, "test") == name) {
returnType = method_copyReturnType(currMethod);
if (returnType) {
// This handles disposing of returnType for us even if an
// exception should fly. Length +1 for the terminator, not that
// the length really matters here, as we never reference inside
// the data block.
[NSData dataWithBytesNoCopy:returnType
length:strlen(returnType) + 1];
}
}
// TODO: If a test class is a subclass of another, and they reuse the
// same selector name (ie-subclass overrides it), this current loop
// and test here will cause cause it to get invoked twice. To fix this
// the selector would have to be checked against all the ones already
// added, so it only gets done once.
if (returnType // True if name starts with "test"
&& strcmp(returnType, @encode(void)) == 0
&& method_getNumberOfArguments(currMethod) == 2) {
NSMethodSignature *sig = [self instanceMethodSignatureForSelector:sel];
NSInvocation *invocation
= [NSInvocation invocationWithMethodSignature:sig];
[invocation setSelector:sel];
[invocations addObject:invocation];
}
}
}
}
// Match SenTestKit and run everything in alphbetical order.
[invocations sortUsingFunction:MethodSort context:nil];
return invocations;
}
@end
#endif // GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
@implementation GTMTestCase : SenTestCase
- (void)invokeTest {
NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];
Class devLogClass = NSClassFromString(@"GTMUnitTestDevLog");
if (devLogClass) {
[devLogClass performSelector:@selector(enableTracking)];
[devLogClass performSelector:@selector(verifyNoMoreLogsExpected)];
}
[super invokeTest];
if (devLogClass) {
[devLogClass performSelector:@selector(verifyNoMoreLogsExpected)];
[devLogClass performSelector:@selector(disableTracking)];
}
[localPool drain];
}
+ (BOOL)isAbstractTestCase {
NSString *name = NSStringFromClass(self);
return [name rangeOfString:@"AbstractTest"].location != NSNotFound;
}
+ (NSArray *)testInvocations {
NSArray *invocations = nil;
if (![self isAbstractTestCase]) {
invocations = [super testInvocations];
}
return invocations;
}
@end
// Leak detection
#if !GTM_IPHONE_DEVICE && !GTM_SUPPRESS_RUN_LEAKS_HOOK
// Don't want to get leaks on the iPhone Device as the device doesn't
// have 'leaks'. The simulator does though.
// COV_NF_START
// We don't have leak checking on by default, so this won't be hit.
static void _GTMRunLeaks(void) {
// This is an atexit handler. It runs leaks for us to check if we are
// leaking anything in our tests.
const char* cExclusionsEnv = getenv("GTM_LEAKS_SYMBOLS_TO_IGNORE");
NSMutableString *exclusions = [NSMutableString string];
if (cExclusionsEnv) {
NSString *exclusionsEnv = [NSString stringWithUTF8String:cExclusionsEnv];
NSArray *exclusionsArray = [exclusionsEnv componentsSeparatedByString:@","];
NSString *exclusion;
NSCharacterSet *wcSet = [NSCharacterSet whitespaceCharacterSet];
GTM_FOREACH_OBJECT(exclusion, exclusionsArray) {
exclusion = [exclusion stringByTrimmingCharactersInSet:wcSet];
[exclusions appendFormat:@"-exclude \"%@\" ", exclusion];
}
}
// Clearing out DYLD_ROOT_PATH because iPhone Simulator framework libraries
// are different from regular OS X libraries and leaks will fail to run
// because of missing symbols. Also capturing the output of leaks and then
// pipe rather than a direct pipe, because otherwise if leaks failed,
// the system() call will still be successful. Bug:
// http://code.google.com/p/google-toolbox-for-mac/issues/detail?id=56
NSString *string
= [NSString stringWithFormat:
@"LeakOut=`DYLD_ROOT_PATH='' /usr/bin/leaks %@%d` &&"
@"echo \"$LeakOut\"|/usr/bin/sed -e 's/Leak: /Leaks:0: warning: Leak /'",
exclusions, getpid()];
int ret = system([string UTF8String]);
if (ret) {
fprintf(stderr,
"%s:%d: Error: Unable to run leaks. 'system' returned: %d\n",
__FILE__, __LINE__, ret);
fflush(stderr);
}
}
// COV_NF_END
static __attribute__((constructor)) void _GTMInstallLeaks(void) {
BOOL checkLeaks = YES;
#if !GTM_IPHONE_SDK
checkLeaks = GTMIsGarbageCollectionEnabled() ? NO : YES;
#endif // !GTM_IPHONE_SDK
if (checkLeaks) {
checkLeaks = getenv("GTM_ENABLE_LEAKS") ? YES : NO;
if (checkLeaks) {
// COV_NF_START
// We don't have leak checking on by default, so this won't be hit.
fprintf(stderr, "Leak Checking Enabled\n");
fflush(stderr);
int ret = atexit(&_GTMRunLeaks);
// To avoid unused variable warning when _GTMDevAssert is stripped.
(void)ret;
_GTMDevAssert(ret == 0,
@"Unable to install _GTMRunLeaks as an atexit handler (%d)",
errno);
// COV_NF_END
}
}
}
#endif // !GTM_IPHONE_DEVICE && !GTM_SUPPRESS_RUN_LEAKS_HOOK