├── llvm-jit-objc ├── src │ ├── dummy.cpp │ ├── lib │ │ ├── DebugUtils.cpp │ │ ├── CMakeLists.txt │ │ ├── ObjCResolver.cpp │ │ ├── ObjCRuntimeHelpers.cpp │ │ ├── SwiftRuntimeSetup.cpp │ │ ├── ObjCType.cpp │ │ ├── ObjCEnabledMemoryManager.cpp │ │ └── ObjCRuntime.cpp │ ├── CMakeLists.txt │ └── include │ │ ├── llvm-jit-objc │ │ ├── SwiftRuntimeSetup.h │ │ ├── ObjCRuntimeHelpers.h │ │ ├── ObjCResolver.h │ │ ├── DebugUtils.h │ │ ├── ObjCEnabledMemoryManager.h │ │ └── ObjCRuntime.h │ │ └── CMakeLists.txt ├── tests │ ├── TestHelpers.h │ ├── CustomXCTestRunnerBinding.h │ ├── CustomXCTestRunnerBinding.cpp │ ├── CMakeLists.txt │ ├── TestHelpers.cpp │ ├── XCTestObjCTest.cpp │ ├── XCTestSwiftTest.cpp │ └── SandboxTest.cpp ├── LLVM.toolchain.macos.cmake ├── LLVM.cmake └── CMakeLists.txt ├── .gitignore ├── CustomXCTestRunner ├── .gitignore ├── CustomXCTestRunnerObjC │ ├── CustomXCTestRunnerObjC.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── project.pbxproj │ └── CustomXCTestRunnerObjC │ │ └── main.m ├── CustomXCTestRunner.h ├── Makefile ├── CMakeLists.txt └── CustomXCTestRunner.m ├── fixtures ├── xctest_objc_001_minimal_xctestcase_run │ └── xctest_objc_001_minimal_xctestcase_run.m ├── 002_calling_class_method │ └── 002_calling_class_method.m ├── 001_minimal_test │ └── 001_minimal_test.m ├── 004_calling_a_super_method_on_class │ └── 004_calling_a_super_method_on_class.m ├── 003_calling_a_super_method_on_instance │ └── 003_calling_a_super_method_on_instance.m ├── 005_ivars_of_class_and_superclass │ └── 005_ivars_of_class_and_superclass.m ├── 007_category_basic │ └── 007_category_basic.m ├── 006_properties_of_class_and_superclass │ └── 006_properties_of_class_and_superclass.m ├── Makefile └── xctest_swift_001_minimal_xctestcase_run │ ├── MinimalSwiftXCTestCase.swift │ └── Makefile ├── CMakeLists.txt ├── Makefile ├── googletest ├── CMakeLists.txt ├── src │ ├── gtest_main.cc │ ├── gtest-all.cc │ ├── gtest-typed-test.cc │ └── gtest-test-part.cc └── include │ └── gtest │ ├── internal │ ├── custom │ │ ├── gtest.h │ │ ├── gtest-printers.h │ │ └── gtest-port.h │ ├── gtest-port-arch.h │ ├── gtest-string.h │ ├── gtest-linked_ptr.h │ ├── gtest-filepath.h │ ├── gtest-param-util-generated.h.pump │ ├── gtest-type-util.h.pump │ └── gtest-tuple.h.pump │ ├── gtest_prod.h │ ├── gtest-test-part.h │ ├── gtest-message.h │ ├── gtest-spi.h │ └── gtest-typed-test.h └── README.md /llvm-jit-objc/src/dummy.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/lib/DebugUtils.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/build/** 2 | **/Build/** 3 | **/BuildXcode/** 4 | **/cmake-build-debug/** 5 | *.o 6 | *.bc 7 | *.ll 8 | -------------------------------------------------------------------------------- /CustomXCTestRunner/.gitignore: -------------------------------------------------------------------------------- 1 | **/Build/** 2 | **/xcuserdata/** 3 | *.xcworkspacedata 4 | *.bc 5 | *.dylib 6 | 7 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(llvm-jit-objc SHARED dummy.cpp) 3 | 4 | target_link_libraries(llvm-jit-objc ${LLVM_DEPENDENCIES}) 5 | 6 | add_subdirectory(include) 7 | add_subdirectory(lib) 8 | 9 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/include/llvm-jit-objc/SwiftRuntimeSetup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class SwiftRuntimeSetup { 4 | public: 5 | static void loadFoundation(); 6 | static void loadXCTest(); 7 | static void loadSwiftLibraries(); 8 | 9 | }; 10 | -------------------------------------------------------------------------------- /llvm-jit-objc/tests/TestHelpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | std::unique_ptr loadModuleAtPath(const std::string &path, 7 | llvm::LLVMContext &llvmContext); 8 | -------------------------------------------------------------------------------- /fixtures/xctest_objc_001_minimal_xctestcase_run/xctest_objc_001_minimal_xctestcase_run.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface TestCase : XCTestCase 4 | @end 5 | 6 | @implementation TestCase 7 | - (void)testHello { 8 | XCTAssertTrue(YES); 9 | } 10 | @end 11 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/include/llvm-jit-objc/ObjCRuntimeHelpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace objc { 6 | bool objc_classIsRegistered(Class cls); 7 | void objc_dumpClass(Class clz); 8 | void objc_dumpClasses(); 9 | } // namespace objc 10 | -------------------------------------------------------------------------------- /llvm-jit-objc/tests/CustomXCTestRunnerBinding.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Stanislav Pankevich on 2019-09-29. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class CustomXCTestRunnerBinding { 10 | public: 11 | static std::string getCustomXCTestRunnerPath(); 12 | }; 13 | -------------------------------------------------------------------------------- /fixtures/002_calling_class_method/002_calling_class_method.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FirstClass : NSObject 4 | + (int)hello; 5 | @end 6 | 7 | @implementation FirstClass 8 | + (int)hello { 9 | return 1234; 10 | } 11 | @end 12 | 13 | int run() { 14 | int result = [FirstClass hello]; 15 | 16 | return result; 17 | } 18 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/include/llvm-jit-objc/ObjCResolver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class ObjCResolver : public llvm::JITSymbolResolver { 6 | public: 7 | ObjCResolver() {} 8 | llvm::JITSymbol findSymbol(const std::string &Name); 9 | llvm::JITSymbol findSymbolInLogicalDylib(const std::string &Name); 10 | }; 11 | -------------------------------------------------------------------------------- /CustomXCTestRunner/CustomXCTestRunnerObjC/CustomXCTestRunnerObjC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /fixtures/001_minimal_test/001_minimal_test.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FirstClass : NSObject 4 | - (int)hello; 5 | @end 6 | 7 | @implementation FirstClass 8 | - (int)hello { 9 | return 1234; 10 | } 11 | @end 12 | 13 | int run() { 14 | FirstClass *fc = [[FirstClass alloc] init]; 15 | 16 | int result = [fc hello]; 17 | 18 | return result; 19 | } 20 | -------------------------------------------------------------------------------- /llvm-jit-objc/tests/CustomXCTestRunnerBinding.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Stanislav Pankevich on 2019-09-29. 3 | // 4 | 5 | #include "CustomXCTestRunnerBinding.h" 6 | 7 | #include 8 | 9 | std::string CustomXCTestRunnerBinding::getCustomXCTestRunnerPath() { 10 | // Value is provided by CMake. See CMakeLists.txt. 11 | std::string customXCTestRunnerPath = "@CUSTOM_XCTEST_RUNNER_BINARY_PATH@"; 12 | 13 | assert(std::ifstream(customXCTestRunnerPath.c_str()).good()); 14 | 15 | return customXCTestRunnerPath; 16 | } 17 | -------------------------------------------------------------------------------- /CustomXCTestRunner/CustomXCTestRunner.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomXCTestRunner.h 3 | // CustomXCTestRunner (Objective-C) 4 | // 5 | // Created by Stanislaw Pankevich on 30/03/18 6 | // Copyright © 2018 Lowlevelbits.org. All rights reserved. 7 | // 8 | 9 | #ifndef CustomXCTestRunner_h 10 | #define CustomXCTestRunner_h 11 | 12 | extern int CustomXCTestRunnerRunAll(void); 13 | extern int CustomXCTestRunnerRunOne(const char *const testName); 14 | extern void CustomXCTestRunnerPrintAllTests(char *output); 15 | 16 | #endif /* CustomXCTestRunner_h */ 17 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | 3 | project(llvm-jit-objc C CXX) 4 | 5 | add_compile_options($<$:-std=c++11>) 6 | 7 | # https://cmake.org/Wiki/CMake_RPATH_handling#Always_full_RPATH 8 | SET(CMAKE_SKIP_BUILD_RPATH FALSE) 9 | SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 10 | SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" "${LLVM_LIB_PATH}") 11 | SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 12 | 13 | add_subdirectory(CustomXCTestRunner) 14 | add_subdirectory(googletest) 15 | add_subdirectory(llvm-jit-objc) 16 | -------------------------------------------------------------------------------- /fixtures/004_calling_a_super_method_on_class/004_calling_a_super_method_on_class.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ClassA : NSObject 4 | + (int)hello; 5 | @end 6 | 7 | @implementation ClassA 8 | + (int)hello { 9 | return 100; 10 | } 11 | @end 12 | 13 | @interface ClassB : ClassA 14 | + (int)hello; 15 | @end 16 | 17 | @implementation ClassB 18 | + (int)hello { 19 | int superHello = [super hello]; 20 | return superHello + 11; 21 | } 22 | @end 23 | 24 | int run() { 25 | int result = [ClassB hello]; 26 | return result; 27 | } 28 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/include/llvm-jit-objc/DebugUtils.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | std::string to_hex16(T val) { 6 | constexpr int HEX_DIGIT_BITS = 4; // One hex digit = 4 bits. 7 | constexpr int HEX_BASE_CHARS = 2; // For the "0x". 8 | 9 | std::stringstream sformatter; 10 | sformatter << std::hex 11 | << std::internal 12 | << std::showbase 13 | << std::setfill('0') 14 | << std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS) 15 | << (uintptr_t)val; 16 | 17 | return sformatter.str(); 18 | } 19 | -------------------------------------------------------------------------------- /fixtures/003_calling_a_super_method_on_instance/003_calling_a_super_method_on_instance.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ClassA : NSObject 4 | - (int)hello; 5 | @end 6 | 7 | @implementation ClassA 8 | - (int)hello { 9 | return 100; 10 | } 11 | @end 12 | 13 | @interface ClassB : ClassA 14 | - (int)hello; 15 | @end 16 | 17 | @implementation ClassB 18 | - (int)hello { 19 | int superHello = [super hello]; 20 | return superHello + 11; 21 | } 22 | @end 23 | 24 | int run() { 25 | ClassB *classB = [[ClassB alloc] init]; 26 | int result = [classB hello]; 27 | return result; 28 | } 29 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | target_include_directories(llvm-jit-objc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 3 | 4 | set(headers 5 | "${CMAKE_CURRENT_LIST_DIR}/llvm-jit-objc/ObjCResolver.h" 6 | "${CMAKE_CURRENT_LIST_DIR}/llvm-jit-objc/ObjCRuntime.h" 7 | "${CMAKE_CURRENT_LIST_DIR}/llvm-jit-objc/ObjCRuntimeHelpers.h" 8 | "${CMAKE_CURRENT_LIST_DIR}/llvm-jit-objc/ObjCEnabledMemoryManager.h" 9 | "${CMAKE_CURRENT_LIST_DIR}/llvm-jit-objc/ObjCType.h" 10 | "${CMAKE_CURRENT_LIST_DIR}/llvm-jit-objc/SwiftRuntimeSetup.h" 11 | "${CMAKE_CURRENT_LIST_DIR}/llvm-jit-objc/DebugUtils.h" 12 | ) 13 | target_sources(llvm-jit-objc PRIVATE ${headers}) 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += --warn-undefined-variables 2 | 3 | BUILD_DIR_XCODE?=$(PWD)/BuildXcode 4 | 5 | # Self-Documented Makefile 6 | # http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html 7 | .PHONY: help 8 | help: ## Show this help message. 9 | @grep -E '^[a-zA-Z_\.-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 10 | 11 | ## Xcode 12 | 13 | xcode.build: ## Build Xcode project with CMake. 14 | mkdir -p $(BUILD_DIR_XCODE) 15 | 16 | # rm -rfv $(BUILD_DIR_XCODE)/CMakeCache.txt 17 | cd $(BUILD_DIR_XCODE) && cmake ../ -G Xcode 18 | 19 | xcode.open: ## Open Xcode project 20 | open BuildXcode/llvm-jit-objc.xcodeproj 21 | 22 | clean: ## Delete Xcode CMake build cache. 23 | rm -rfv $(BUILD_DIR_XCODE) 24 | -------------------------------------------------------------------------------- /googletest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | message(STATUS "googletest> Creating google-test target...") 2 | 3 | file(GLOB_RECURSE google_test_headers ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 4 | 5 | set(google_test_sources src/gtest-all.cc src/gtest_main.cc) 6 | 7 | add_library(google-test STATIC ${google_test_sources} ${google_test_headers}) 8 | 9 | target_include_directories(google-test PUBLIC "include") 10 | target_include_directories(google-test PRIVATE ".") 11 | 12 | # compile flags 13 | get_target_property(default_compile_flags google-test COMPILE_FLAGS) 14 | if(NOT default_compile_flags) 15 | set(default_compile_flags "") 16 | endif() 17 | set(googletest_compileflags ${default_compile_flags} ${LLVM_CXX_FLAGS}) 18 | set_target_properties(google-test 19 | PROPERTIES COMPILE_FLAGS 20 | "${googletest_compileflags}" 21 | ) 22 | -------------------------------------------------------------------------------- /llvm-jit-objc/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(sources 2 | ObjCTest.cpp 3 | SandboxTest.cpp 4 | XCTestObjCTest.cpp 5 | XCTestSwiftTest.cpp 6 | TestHelpers.cpp 7 | TestHelpers.h 8 | ${CMAKE_CURRENT_BINARY_DIR}/CustomXCTestRunnerBinding.cpp 9 | ) 10 | 11 | add_executable(llvm-jit-objc-tests ${sources} ${headers}) 12 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 13 | 14 | add_dependencies(llvm-jit-objc-tests CustomXCTestRunner) 15 | target_link_libraries(llvm-jit-objc-tests llvm-jit-objc google-test) 16 | include_directories("${CMAKE_SOURCE_DIR}/googletest/include") 17 | 18 | target_link_libraries(llvm-jit-objc-tests ${LLVM_DEPENDENCIES}) 19 | 20 | configure_file ( 21 | ${CMAKE_CURRENT_LIST_DIR}/CustomXCTestRunnerBinding.cpp 22 | ${CMAKE_CURRENT_BINARY_DIR}/CustomXCTestRunnerBinding.cpp 23 | @ONLY 24 | ) 25 | -------------------------------------------------------------------------------- /CustomXCTestRunner/Makefile: -------------------------------------------------------------------------------- 1 | CC=/opt/llvm-6.0.0/bin/clang 2 | # CC=/opt/llvm-5.0.0/bin/clang 3 | SYSROOT=-isysroot $(shell xcrun --sdk macosx --show-sdk-path) 4 | 5 | MACOS_FRAMEWORKS_DIR=/Applications/Xcode-9.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks 6 | # XCTEST_PATH=$(MACOS_FRAMEWORKS_DIR)/XCTest.framework/XCTest 7 | XCTEST_FLAGS=-F$(MACOS_FRAMEWORKS_DIR) -framework XCTest 8 | 9 | CCFLAGS=$(SYSROOT) 10 | 11 | compile: compile.dylib compile.bc 12 | 13 | compile.dylib: 14 | $(CC) \ 15 | $(CCFLAGS) \ 16 | $(XCTEST_FLAGS) \ 17 | -fobjc-arc -shared -undefined dynamic_lookup \ 18 | -o CustomXCTestRunner.dylib \ 19 | CustomXCTestRunner.m 20 | 21 | compile.bc: 22 | $(CC) $(CCFLAGS) \ 23 | -F$(MACOS_FRAMEWORKS_DIR) \ 24 | -fobjc-arc \ 25 | -emit-llvm \ 26 | CustomXCTestRunner.m \ 27 | -c \ 28 | -o CustomXCTestRunner.bc 29 | 30 | -------------------------------------------------------------------------------- /fixtures/005_ivars_of_class_and_superclass/005_ivars_of_class_and_superclass.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ClassA : NSObject 4 | - (int)hello; 5 | @end 6 | 7 | @implementation ClassA { 8 | int _ivar1; 9 | int _ivar2; 10 | } 11 | - (id)init { 12 | self = [super init]; 13 | _ivar1 = 1000; 14 | _ivar2 = 100; 15 | return self; 16 | } 17 | - (int)hello { 18 | return _ivar1 + _ivar2; 19 | } 20 | @end 21 | 22 | @interface ClassB : ClassA 23 | - (int)hello; 24 | @end 25 | 26 | @implementation ClassB { 27 | int _ivar1; 28 | int _ivar2; 29 | } 30 | - (id)init { 31 | self = [super init]; 32 | _ivar1 = 10; 33 | _ivar2 = 1; 34 | return self; 35 | } 36 | - (int)hello { 37 | int superHello = [super hello]; 38 | return superHello + _ivar1 + _ivar2; 39 | } 40 | @end 41 | 42 | int run() { 43 | ClassB *clB = [[ClassB alloc] init]; 44 | int result = [clB hello]; 45 | return result; 46 | } 47 | -------------------------------------------------------------------------------- /llvm-jit-objc/tests/TestHelpers.cpp: -------------------------------------------------------------------------------- 1 | #include "TestHelpers.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace llvm; 8 | 9 | std::unique_ptr loadModuleAtPath(const std::string &path, 10 | llvm::LLVMContext &llvmContext) { 11 | 12 | auto BufferOrError = llvm::MemoryBuffer::getFile(path); 13 | if (!BufferOrError) { 14 | errs() << "ModuleLoader> Can't load module " << path << '\n'; 15 | return nullptr; 16 | } 17 | errs() << "ModuleLoader> module " << path << '\n'; 18 | 19 | auto llvmModule = llvm::parseBitcodeFile(BufferOrError->get()->getMemBufferRef(), 20 | llvmContext); 21 | 22 | if (!llvmModule) { 23 | errs() << "ModuleLoader> Can't load module " << path << '\n'; 24 | return nullptr; 25 | } 26 | 27 | return std::move(llvmModule.get()); 28 | } 29 | -------------------------------------------------------------------------------- /fixtures/007_category_basic/007_category_basic.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ClassWithCategory : NSObject 4 | @property (nonatomic, assign) int prop; 5 | @end 6 | 7 | @implementation ClassWithCategory 8 | - (id)init { 9 | self = [super init]; 10 | self.prop = 1000; 11 | return self; 12 | } 13 | @end 14 | 15 | @interface ClassWithCategory (CategoryThatReadsProperty) 16 | + (int)classMethodOnACategory; 17 | - (int)readProperty; 18 | @end 19 | 20 | @implementation ClassWithCategory (CategoryThatReadsProperty) 21 | + (int)classMethodOnACategory { 22 | return 1234; 23 | } 24 | - (int)readProperty { 25 | int propertyValue = [self prop]; 26 | return propertyValue; 27 | } 28 | @end 29 | 30 | int run() { 31 | ClassWithCategory *obj = [[ClassWithCategory alloc] init]; 32 | int instanceMethodResult = [obj readProperty]; 33 | int classMethodResult = [ClassWithCategory classMethodOnACategory]; 34 | return instanceMethodResult + classMethodResult; 35 | } 36 | -------------------------------------------------------------------------------- /fixtures/006_properties_of_class_and_superclass/006_properties_of_class_and_superclass.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ClassA : NSObject 4 | @property (nonatomic, assign) int prop1; 5 | @property (nonatomic, assign) int prop2; 6 | - (int)hello; 7 | @end 8 | 9 | @implementation ClassA 10 | - (id)init { 11 | self = [super init]; 12 | self.prop1 = 1000; 13 | self.prop2 = 100; 14 | return self; 15 | } 16 | - (int)hello { 17 | return self.prop1 + self.prop2; 18 | } 19 | @end 20 | 21 | @interface ClassB : ClassA 22 | @property (nonatomic, assign) int prop3; 23 | @property (nonatomic, assign) int prop4; 24 | - (int)hello; 25 | @end 26 | 27 | @implementation ClassB 28 | - (id)init { 29 | self = [super init]; 30 | self.prop3 = 10; 31 | self.prop4 = 1; 32 | return self; 33 | } 34 | - (int)hello { 35 | int superHello = [super hello]; 36 | return superHello + self.prop3 + self.prop4; 37 | } 38 | @end 39 | 40 | int run() { 41 | ClassB *clB = [[ClassB alloc] init]; 42 | int result = [clB hello]; 43 | return result; 44 | } 45 | -------------------------------------------------------------------------------- /CustomXCTestRunner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(CustomXCTestRunner SHARED CustomXCTestRunner.m) 2 | 3 | set(SYSROOT_VALUE "") 4 | execute_process( 5 | COMMAND xcrun --sdk macosx --show-sdk-path 6 | OUTPUT_VARIABLE SYSROOT_VALUE 7 | OUTPUT_STRIP_TRAILING_WHITESPACE 8 | ) 9 | 10 | set(MACOS_FRAMEWORKS_DIR "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks") 11 | 12 | set(XCTEST_FLAGS -F${MACOS_FRAMEWORKS_DIR} -framework XCTest) 13 | 14 | target_compile_options(CustomXCTestRunner 15 | PRIVATE 16 | -fobjc-arc 17 | -isysroot ${SYSROOT_VALUE} 18 | ${XCTEST_FLAGS} 19 | ) 20 | 21 | target_link_options(CustomXCTestRunner 22 | PRIVATE 23 | -shared -undefined dynamic_lookup 24 | ) 25 | 26 | set_target_properties(CustomXCTestRunner 27 | PROPERTIES 28 | LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" 29 | LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib" 30 | LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib" 31 | ) 32 | 33 | set(CUSTOM_XCTEST_RUNNER_BINARY_PATH 34 | ${CMAKE_BINARY_DIR}/lib/libCustomXCTestRunner.dylib 35 | PARENT_SCOPE 36 | ) 37 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/include/llvm-jit-objc/ObjCEnabledMemoryManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ObjCRuntime.h" 4 | 5 | #include 6 | #include 7 | 8 | class ObjCEnabledMemoryManager: public llvm::SectionMemoryManager { 9 | 10 | private: 11 | struct ObjectSectionEntry { 12 | uint8_t *pointer; 13 | uintptr_t size; 14 | llvm::StringRef section; 15 | 16 | ObjectSectionEntry(uint8_t *pointer, 17 | uintptr_t size, 18 | llvm::StringRef section) 19 | : pointer(pointer), size(size), section(section) {} 20 | }; 21 | 22 | std::vector objcSections; 23 | mull::objc::Runtime runtime; 24 | 25 | void registerObjC(); 26 | 27 | public: 28 | ObjCEnabledMemoryManager(); 29 | 30 | uint8_t *allocateDataSection(uintptr_t Size, 31 | unsigned Alignment, 32 | unsigned SectionID, 33 | llvm::StringRef SectionName, 34 | bool isReadOnly) override; 35 | 36 | bool finalizeMemory(std::string *ErrMsg = nullptr) override; 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(sources 2 | "${CMAKE_CURRENT_LIST_DIR}/ObjCResolver.cpp" 3 | "${CMAKE_CURRENT_LIST_DIR}/ObjCRuntime.cpp" 4 | "${CMAKE_CURRENT_LIST_DIR}/ObjCRuntimeHelpers.cpp" 5 | "${CMAKE_CURRENT_LIST_DIR}/ObjCEnabledMemoryManager.cpp" 6 | "${CMAKE_CURRENT_LIST_DIR}/ObjCType.cpp" 7 | "${CMAKE_CURRENT_LIST_DIR}/SwiftRuntimeSetup.cpp" 8 | "${CMAKE_CURRENT_LIST_DIR}/DebugUtils.cpp" 9 | ) 10 | 11 | target_sources(llvm-jit-objc PRIVATE ${sources}) 12 | 13 | # # The following is needed to make CMake to generate a folder structure in Xcode 14 | # # that corresponds to a physical folder structure. 15 | # get_target_property(HERE_TARGET_SOURCES llvm-jit-objc SOURCES) 16 | # foreach(source_file ${HERE_TARGET_SOURCES}) 17 | # if (source_file MATCHES "(.*)\.h$") 18 | # file(RELATIVE_PATH relative_source_file ${CMAKE_CURRENT_SOURCE_DIR} ${source_file}) 19 | # get_filename_component(relative_path ${relative_source_file} DIRECTORY) 20 | # source_group("${relative_path}" FILES ${source_file}) 21 | # else() 22 | # get_filename_component(relative_path ${source_file} DIRECTORY) 23 | # source_group("${relative_path}" FILES ${source_file}) 24 | # endif() 25 | # endforeach() 26 | -------------------------------------------------------------------------------- /CustomXCTestRunner/CustomXCTestRunnerObjC/CustomXCTestRunnerObjC/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CustomXCTestRunnerObjC 4 | // 5 | // Created by Stanislav Pankevich on 30.03.18. 6 | // Copyright © 2018 Stanislav Pankevich. All rights reserved. 7 | // 8 | 9 | #import "CustomXCTestRunner.h" 10 | 11 | #import 12 | #import 13 | 14 | @interface TestCase1 : XCTestCase 15 | - (void)testHelloWorld1; 16 | @end 17 | 18 | @implementation TestCase1 19 | - (void)testHelloWorld1 { 20 | XCTAssert(YES); 21 | } 22 | @end 23 | 24 | @interface TestCase2 : XCTestCase 25 | - (void)testHelloWorld2; 26 | @end 27 | 28 | @implementation TestCase2 29 | - (void)testHelloWorld2 { 30 | XCTAssert(YES); 31 | } 32 | @end 33 | 34 | int main(int argc, const char * argv[]) { 35 | int testRunResult = 0; 36 | @autoreleasepool { 37 | NSLog(@"Hello, World!"); 38 | 39 | testRunResult = CustomXCTestRunnerRunAll(); 40 | testRunResult = CustomXCTestRunnerRunAll(); 41 | 42 | char tests[1024]; 43 | CustomXCTestRunnerPrintAllTests(tests); 44 | 45 | printf("tests: %s\n", tests); 46 | CustomXCTestRunnerRunOne("TestCase1.testHelloWorld1"); 47 | 48 | } 49 | return testRunResult; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /llvm-jit-objc/LLVM.toolchain.macos.cmake: -------------------------------------------------------------------------------- 1 | # Make sure to delete CMake's CMakeCache.txt file or even the whole build folder. 2 | # Before bootstrapping this file as a CMake toolchain. 3 | # "CMake ignores toolchain file. How do get debug/error output?" 4 | # http://stackoverflow.com/a/8303317/598057 5 | 6 | MESSAGE(STATUS "Using LLVM.toolchain.macos.cmake") 7 | 8 | # brew install llvm 9 | set(LLVM_ROOT "/opt/llvm-6.0.0" CACHE PATH "Root of LLVM install.") 10 | 11 | # A bit of a sanity check: 12 | if (NOT EXISTS ${LLVM_ROOT}/include/llvm) 13 | message(SEND_ERROR "LLVM_ROOT (${LLVM_ROOT}) is not a valid LLVM install") 14 | endif() 15 | 16 | ## Changing the compilers will not work in Xcode which always forces Apple Clang, 17 | ## It will always yield something like this: 18 | ## -- The C compiler identification is AppleClang 8.0.0.8000042 19 | ## -- The CXX compiler identification is AppleClang 8.0.0.8000042 20 | ## Without looking at the variables below. Only Ninja will work. 21 | # set(CMAKE_C_COMPILER ${LLVM_ROOT}/bin/clang) 22 | # set(CMAKE_CXX_COMPILER ${LLVM_ROOT}/bin/clang++) 23 | # set(CMAKE_ASM_COMPILER ${LLVM_ROOT}/bin/llvm-as) 24 | 25 | # brew install zlib 26 | set(LLVM_TOOLCHAIN_ZLIB_PATH "/usr/local/opt/zlib/lib") 27 | 28 | set(CMAKE_MACOSX_RPATH ON) 29 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/lib/ObjCResolver.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm-jit-objc/ObjCResolver.h" 2 | 3 | #include "llvm-jit-objc/ObjCType.h" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | using namespace llvm; 12 | using namespace mull::objc; 13 | 14 | extern "C" int objc_printf( const char * format, ... ) { 15 | errs() << "**** objc_printf ****" << "\n"; 16 | 17 | va_list arguments; 18 | va_start(arguments, format); 19 | int res = vprintf(format, arguments); 20 | va_end(arguments); 21 | 22 | return res; 23 | } 24 | 25 | JITSymbol ObjCResolver::findSymbol(const std::string &Name) { 26 | //errs() << "ObjCResolver::findSymbol> " << Name << "\n"; 27 | if (Name == "_printf") { 28 | return 29 | JITSymbol((uint64_t)objc_printf, 30 | JITSymbolFlags::Exported); 31 | } 32 | 33 | if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name)) { 34 | return JITSymbol(SymAddr, JITSymbolFlags::Exported); 35 | } 36 | 37 | return JITSymbol(nullptr); 38 | } 39 | 40 | JITSymbol 41 | ObjCResolver::findSymbolInLogicalDylib(const std::string &Name) { 42 | //errs() << "ObjCResolver::findSymbolInLogicalDylib> " << Name << "\n"; 43 | 44 | return JITSymbol(nullptr); 45 | } 46 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/include/llvm-jit-objc/ObjCRuntime.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "ObjCType.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace llvm; 15 | 16 | #pragma mark - 17 | 18 | namespace mull { namespace objc { 19 | 20 | class Runtime { 21 | std::queue classesToRegister; 22 | 23 | std::vector classRefs; 24 | std::vector metaclassRefs; 25 | 26 | std::set runtimeClasses; 27 | std::vector> oldAndNewClassesMap; 28 | 29 | Class registerOneClass(class64_t **classrefPtr, Class superclass); 30 | void parsePropertyAttributes(const char *const attributesStr, 31 | char *const stringStorage, 32 | objc_property_attribute_t *attributes, 33 | size_t *count); 34 | 35 | public: 36 | ~Runtime(); 37 | 38 | void registerSelectors(void *selRefsSectionPtr, 39 | uintptr_t selRefsSectionSize); 40 | 41 | void addClassesFromSection(void *sectionPtr, 42 | uintptr_t sectionSize); 43 | void addClassesFromClassRefsSection(void *sectionPtr, 44 | uintptr_t sectionSize); 45 | void addClassesFromSuperclassRefsSection(void *sectionPtr, 46 | uintptr_t sectionSize); 47 | void addCategoriesFromSection(void *sectionPtr, 48 | uintptr_t sectionSize); 49 | 50 | void registerClasses(); 51 | }; 52 | 53 | } } 54 | -------------------------------------------------------------------------------- /googletest/src/gtest_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | 32 | #include "gtest/gtest.h" 33 | 34 | GTEST_API_ int main(int argc, char **argv) { 35 | printf("Running main() from gtest_main.cc\n"); 36 | testing::InitGoogleTest(&argc, argv); 37 | return RUN_ALL_TESTS(); 38 | } 39 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/lib/ObjCRuntimeHelpers.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm-jit-objc/ObjCRuntimeHelpers.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | using namespace llvm; 8 | 9 | namespace objc { 10 | 11 | void objc_dumpClasses() { 12 | int numRegisteredClasses = objc_getClassList(NULL, 0); 13 | assert(numRegisteredClasses > 0); 14 | 15 | Class *classes = (Class *)malloc(sizeof(Class) * numRegisteredClasses); 16 | 17 | numRegisteredClasses = objc_getClassList(classes, numRegisteredClasses); 18 | 19 | for (int i = 0; i < numRegisteredClasses; i++) { 20 | errs() << "registered class: " << class_getName(classes[i]) << "\n"; 21 | } 22 | 23 | free(classes); 24 | } 25 | 26 | bool objc_classIsRegistered(Class cls) { 27 | int numRegisteredClasses = objc_getClassList(NULL, 0); 28 | assert(numRegisteredClasses > 0); 29 | 30 | Class *classes = (Class *)malloc(sizeof(Class) * numRegisteredClasses); 31 | 32 | numRegisteredClasses = objc_getClassList(classes, numRegisteredClasses); 33 | 34 | for (int i = 0; i < numRegisteredClasses; i++) { 35 | if (classes[i] == cls) { 36 | free(classes); 37 | return true; 38 | } 39 | } 40 | 41 | free(classes); 42 | return false; 43 | } 44 | 45 | void objc_dumpClass(Class clz) { 46 | printf("class_dumpMethods() dumping class: %p, is meta class: %d\n", (void *)clz, class_isMetaClass(clz)); 47 | 48 | unsigned int methodCount = 0; 49 | Method *methods = class_copyMethodList(clz, &methodCount); 50 | 51 | printf("Found %d methods on '%s'\n", methodCount, class_getName(clz)); 52 | 53 | for (unsigned int i = 0; i < methodCount; i++) { 54 | Method method = methods[i]; 55 | 56 | printf("\t'%s' has method named '%s' of encoding '%s' %p\n", 57 | class_getName(clz), 58 | sel_getName(method_getName(method)), 59 | method_getTypeEncoding(method), 60 | (void *)method); 61 | } 62 | 63 | free(methods); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /fixtures/Makefile: -------------------------------------------------------------------------------- 1 | # Self-Documented Makefile 2 | # http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html 3 | .PHONY: help 4 | help: ## Show this help message. 5 | @grep -E '^[0-9a-zA-Z_\.-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' 6 | 7 | CC=/opt/llvm-6.0.0/bin/clang 8 | # CC=/opt/llvm-6.0.0/bin/clang 9 | SYSROOT=-isysroot $(shell xcrun --sdk macosx --show-sdk-path) 10 | 11 | MACOS_FRAMEWORKS_DIR=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks 12 | # XCTEST_PATH=$(MACOS_FRAMEWORKS_DIR)/XCTest.framework/XCTest 13 | # XCTEST_FLAGS=-framework XCTest 14 | 15 | CCFLAGS=$(SYSROOT) -F$(MACOS_FRAMEWORKS_DIR) 16 | 17 | OUTPUT_PATH=$(PWD)/bitcode 18 | 19 | FIXTURES_IN=001_minimal_test \ 20 | 002_calling_class_method \ 21 | 003_calling_a_super_method_on_instance \ 22 | 004_calling_a_super_method_on_class \ 23 | 005_ivars_of_class_and_superclass \ 24 | 006_properties_of_class_and_superclass \ 25 | 007_category_basic \ 26 | xctest_objc_001_minimal_xctestcase_run 27 | 28 | FIXTURES_OUT_BC=$(FIXTURES_IN:%=$(OUTPUT_PATH)/%.bc) 29 | FIXTURES_OUT_LL=$(FIXTURES_IN:%=$(OUTPUT_PATH)/%.ll) 30 | FIXTURES_OUT_O=$(FIXTURES_IN:%=$(OUTPUT_PATH)/%.o) 31 | 32 | all: $(FIXTURES_OUT_BC) # $(FIXTURES_OUT_LL) $(FIXTURES_OUT_O) ## Build all fixtures. 33 | 34 | $(OUTPUT_PATH)/%.bc: | $(OUTPUT_PATH) 35 | cd $(OUTPUT_PATH) && \ 36 | $(CC) $(CCFLAGS) -fobjc-arc -emit-llvm $(PWD)/$*/$*.m -c -o $@ 37 | 38 | $(OUTPUT_PATH)/%.ll: | $(OUTPUT_PATH) 39 | cd $(OUTPUT_PATH) && \ 40 | $(CC) $(CCFLAGS) -fobjc-arc -emit-llvm -S $(PWD)/$*/$*.m -c -o $@ 41 | 42 | $(OUTPUT_PATH)/%.o: | $(OUTPUT_PATH) 43 | cd $(OUTPUT_PATH) && \ 44 | $(CC) $(CCFLAGS) -fobjc-arc $(PWD)/$*/$*.m -c -o $@ 45 | 46 | $(OUTPUT_PATH): 47 | mkdir -p $(OUTPUT_PATH) 48 | 49 | clean: ## Cleans the build folder. 50 | rm -rfv $(OUTPUT_PATH) 51 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/custom/gtest.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Injection point for custom user configurations. 31 | // The following macros can be defined: 32 | // 33 | // GTEST_OS_STACK_TRACE_GETTER_ - The name of an implementation of 34 | // OsStackTraceGetterInterface. 35 | // 36 | // ** Custom implementation starts here ** 37 | 38 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 39 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 40 | 41 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 42 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/custom/gtest-printers.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // This file provides an injection point for custom printers in a local 31 | // installation of gTest. 32 | // It will be included from gtest-printers.h and the overrides in this file 33 | // will be visible to everyone. 34 | // See documentation at gtest/gtest-printers.h for details on how to define a 35 | // custom printer. 36 | // 37 | // ** Custom implementation starts here ** 38 | 39 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 40 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 41 | 42 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Attempt to run Objective-C and Swift code with LLVM JIT 2 | 3 | This is a highly experimental proof of concept which was supposed to serve as 4 | an Objective-C/Swift backend for Mull mutation testing tool. We have never 5 | finished this project because we mostly focused on C/C++ since then. 6 | 7 | See these articles for a background: 8 | 9 | - [LLVM JIT, Objective-C and Swift on macOS: knowledge dump](https://stanislaw.github.io/2018/09/03/llvm-jit-objc-and-swift-knowledge-dump.html) 10 | - [Mutation testing for Swift with Mull: how it could work. Looking for contributors.](https://stanislaw.github.io/2018/09/03/mull-and-swift-how-it-almost-works.html) 11 | 12 | **Note:** Please keep in mind, that the code covers only very basics of running 13 | Objective-C with LLVM JIT. The code is quite raw and you can quickly hit some 14 | weird crashes or unexpected behavior once you start adding some new 15 | functionality and test cases. See also this Twitter thread where the engineer 16 | from Apple says that this project's implementation is based on a very unstable 17 | API: https://twitter.com/gparker/status/1036671921616609280. 18 | 19 | ## Setup 20 | 21 | ### Preconditions 22 | 23 | You need to have a binary version of LLVM 6 installed on your machine in 24 | `/opt/llvm-6.0.0` folder. 25 | 26 | The binary distribution of LLVM 6 can be found on 27 | [LLVM Download Page](http://releases.llvm.org/download.html) page. 28 | 29 | ### Cloning the repository 30 | 31 | Please clone the repository to the `/opt/llvm-jit-objc`. Putting everything 32 | to the `/opt` was an old convention that allowed faster prototyping. This 33 | should be changed in the future but for now many things are hardcoded to the 34 | `/opt/llvm-jit-objc` folder. 35 | 36 | ### Generating fixtures 37 | 38 | Generation of the fixtures is not (yet) part of CMake project so you have to 39 | create them manually: 40 | 41 | ```bash 42 | cd fixtures && make all 43 | cd fixtures/xctest_swift_001_minimal_xctestcase_run/ && make compile 44 | ``` 45 | 46 | ### Creating a project 47 | 48 | The project works on macOS only. 49 | 50 | To run with Xcode, clone the repository and run: 51 | 52 | ``` 53 | make xcode.build 54 | make xcode.open 55 | ``` 56 | 57 | Otherwise the project is a normal CMake project so opening it with any 58 | CMake-aware IDE like CLion should work out of the box. 59 | -------------------------------------------------------------------------------- /googletest/src/gtest-all.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | // Google C++ Testing Framework (Google Test) 33 | // 34 | // Sometimes it's desirable to build Google Test by compiling a single file. 35 | // This file serves this purpose. 36 | 37 | // This line ensures that gtest.h can be compiled on its own, even 38 | // when it's fused. 39 | #include "gtest/gtest.h" 40 | 41 | // The following lines pull in the real gtest *.cc files. 42 | #include "src/gtest.cc" 43 | #include "src/gtest-death-test.cc" 44 | #include "src/gtest-filepath.cc" 45 | #include "src/gtest-port.cc" 46 | #include "src/gtest-printers.cc" 47 | #include "src/gtest-test-part.cc" 48 | #include "src/gtest-typed-test.cc" 49 | -------------------------------------------------------------------------------- /googletest/include/gtest/gtest_prod.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Google C++ Testing Framework definitions useful in production code. 33 | 34 | #ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 35 | #define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 36 | 37 | // When you need to test the private or protected members of a class, 38 | // use the FRIEND_TEST macro to declare your tests as friends of the 39 | // class. For example: 40 | // 41 | // class MyClass { 42 | // private: 43 | // void MyMethod(); 44 | // FRIEND_TEST(MyClassTest, MyMethod); 45 | // }; 46 | // 47 | // class MyClassTest : public testing::Test { 48 | // // ... 49 | // }; 50 | // 51 | // TEST_F(MyClassTest, MyMethod) { 52 | // // Can call MyClass::MyMethod() here. 53 | // } 54 | 55 | #define FRIEND_TEST(test_case_name, test_name)\ 56 | friend class test_case_name##_##test_name##_Test 57 | 58 | #endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 59 | -------------------------------------------------------------------------------- /fixtures/xctest_swift_001_minimal_xctestcase_run/MinimalSwiftXCTestCase.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | // The recursive version of binary search. 4 | public func binarySearch(_ a: [T], key: T, range: Range) -> Int? { 5 | if range.lowerBound >= range.upperBound { 6 | return nil 7 | } else { 8 | let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 9 | if a[midIndex] > key { 10 | return binarySearch(a, key: key, range: range.lowerBound ..< midIndex) 11 | } else if a[midIndex] < key { 12 | return binarySearch(a, key: key, range: midIndex + 1 ..< range.upperBound) 13 | } else { 14 | return midIndex 15 | } 16 | } 17 | } 18 | 19 | /** 20 | The iterative version of binary search. 21 | 22 | Notice how similar these functions are. The difference is that this one 23 | uses a while loop, while the other calls itself recursively. 24 | **/ 25 | 26 | public func binarySearch(_ a: [T], key: T) -> Int? { 27 | var lowerBound = 0 28 | var upperBound = a.count 29 | while lowerBound < upperBound { 30 | let midIndex = lowerBound + (upperBound - lowerBound) / 2 31 | if a[midIndex] == key { 32 | return midIndex 33 | } else if a[midIndex] < key { 34 | lowerBound = midIndex + 1 35 | } else { 36 | upperBound = midIndex 37 | } 38 | } 39 | return nil 40 | } 41 | 42 | @objc(BinarySearchTest) 43 | class BinarySearchTest: XCTestCase { 44 | var searchList = [Int]() 45 | 46 | override func setUp() { 47 | super.setUp() 48 | for number in 1...500 { 49 | searchList.append(number) 50 | } 51 | } 52 | 53 | func testEmptyArray() { 54 | let array = [Int]() 55 | let index = binarySearch(array, key: 123) 56 | XCTAssertNil(index) 57 | } 58 | 59 | func testBinarySearch() { 60 | for i in 1...100 { 61 | var array = [Int]() 62 | for number in 1...i { 63 | array.append(number) 64 | } 65 | let randomIndex = Int(arc4random_uniform(UInt32(i))) 66 | let testValue = array[randomIndex] 67 | 68 | let index = binarySearch(array, key: testValue) 69 | XCTAssertNotNil(index) 70 | XCTAssertEqual(index!, randomIndex) 71 | XCTAssertEqual(array[index!], testValue) 72 | } 73 | } 74 | 75 | func testLowerBound() { 76 | let index = binarySearch(searchList, key: 1) 77 | XCTAssertNotNil(index) 78 | XCTAssertEqual(index!, 0) 79 | XCTAssertEqual(searchList[index!], 1) 80 | } 81 | 82 | func testUpperBound() { 83 | let index = binarySearch(searchList, key: 500) 84 | XCTAssertNotNil(index) 85 | XCTAssertEqual(index!, 499) 86 | XCTAssertEqual(searchList[index!], 500) 87 | } 88 | 89 | func testOutOfLowerBound() { 90 | let index = binarySearch(searchList, key: 0) 91 | XCTAssertNil(index) 92 | } 93 | 94 | func testOutOfUpperBound() { 95 | let index = binarySearch(searchList, key: 501) 96 | XCTAssertNil(index) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /llvm-jit-objc/LLVM.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | 3 | if (NOT LLVM_ROOT) 4 | message(FATAL_ERROR "LLVM_ROOT variable is not defined!") 5 | endif() 6 | 7 | set(LLVM_CONFIG_PATH "${LLVM_ROOT}/bin/llvm-config") 8 | 9 | # Getting LLVM CXX flags using llvm-config 10 | function(llvm_get_cxx_flags OUT_CXX_FLAGS) 11 | set(config_command ${LLVM_CONFIG_PATH} 12 | "--cxxflags" 13 | ) 14 | execute_process( 15 | COMMAND ${config_command} 16 | RESULT_VARIABLE HAD_ERROR 17 | OUTPUT_VARIABLE config_output 18 | OUTPUT_STRIP_TRAILING_WHITESPACE 19 | ) 20 | 21 | if(NOT HAD_ERROR) 22 | # Remove -O3 or any other -O? flags 23 | string(REGEX REPLACE "-O." "" config_output "${config_output}") 24 | # Remove DNDEBUG to not disable assertions. 25 | string(REPLACE "-DNDEBUG" "" config_output "${config_output}") 26 | set(llvm_cxx_flags ${config_output}) 27 | else() 28 | string(REPLACE ";" " " config_command_str "${config_command}") 29 | endif() 30 | 31 | set(${OUT_CXX_FLAGS} ${llvm_cxx_flags} PARENT_SCOPE) 32 | endfunction() 33 | 34 | # Getting LLVM linker flags using llvm-config 35 | function(llvm_get_link_flags OUT_LINK_FLAGS) 36 | set(config_command ${LLVM_CONFIG_PATH} 37 | "--ldflags" 38 | ) 39 | execute_process( 40 | COMMAND ${config_command} 41 | RESULT_VARIABLE HAD_ERROR 42 | OUTPUT_VARIABLE config_output 43 | ) 44 | if(NOT HAD_ERROR) 45 | string(REGEX REPLACE "[\r\n(\r\n)]+" "" config_output ${config_output}) 46 | set(llvm_link_flags ${config_output}) 47 | else() 48 | string(REPLACE ";" " " config_command_str "${config_command}") 49 | message(STATUS "${config_command_str}") 50 | message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") 51 | endif() 52 | 53 | set(${OUT_LINK_FLAGS} ${llvm_link_flags} PARENT_SCOPE) 54 | endfunction() 55 | 56 | # Getting LLVM lib directory using llvm-config. 57 | function(llvm_get_lib_dir OUT_LIB_DIR) 58 | set(config_command ${LLVM_CONFIG_PATH} 59 | "--libdir" 60 | ) 61 | execute_process( 62 | COMMAND ${config_command} 63 | RESULT_VARIABLE HAD_ERROR 64 | OUTPUT_VARIABLE config_output 65 | ) 66 | 67 | if(NOT HAD_ERROR) 68 | string(REGEX REPLACE "[\r\n(\r\n)]+" "" config_output ${config_output}) 69 | set(llvm_lib_dir ${config_output}) 70 | else() 71 | string(REPLACE ";" " " config_command_str "${config_command}") 72 | message(STATUS "${config_command_str}") 73 | message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") 74 | endif() 75 | 76 | set(${OUT_LIB_DIR} ${llvm_lib_dir} PARENT_SCOPE) 77 | endfunction() 78 | 79 | # Getting LLVM libraries 80 | function(llvm_get_libs OUT_LIBS components) 81 | set(config_command ${LLVM_CONFIG_PATH} 82 | "--libs" 83 | ${components} 84 | ) 85 | execute_process( 86 | COMMAND ${config_command} 87 | RESULT_VARIABLE HAD_ERROR 88 | OUTPUT_VARIABLE config_output 89 | ) 90 | if(NOT HAD_ERROR) 91 | string(REGEX REPLACE "[ \t\r\n(\r\n)]+" ";" config_output ${config_output}) 92 | set(llvm_libs "${config_output}") 93 | else() 94 | string(REPLACE ";" " " config_command_str "${config_command}") 95 | endif() 96 | set(${OUT_LIBS} ${llvm_libs} PARENT_SCOPE) 97 | endfunction() 98 | -------------------------------------------------------------------------------- /fixtures/xctest_swift_001_minimal_xctestcase_run/Makefile: -------------------------------------------------------------------------------- 1 | # Self-Documented Makefile 2 | # http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html 3 | .PHONY: help 4 | help: ## Show this help message. 5 | @grep -E '^[0-9a-zA-Z_\.-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' 6 | 7 | SWIFTCC=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift 8 | # CC=/opt/llvm-5.0.0/bin/clang 9 | SYSROOT=$(shell xcrun --sdk macosx --show-sdk-path) 10 | 11 | MACOS_FRAMEWORKS_DIR=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks 12 | # XCTEST_PATH=$(MACOS_FRAMEWORKS_DIR)/XCTest.framework/XCTest 13 | # XCTEST_FLAGS=-framework XCTest 14 | 15 | CCFLAGS=$(SYSROOT) -F$(MACOS_FRAMEWORKS_DIR) 16 | 17 | OUTPUT_PATH=$(realpath $(PWD)/../bitcode) 18 | 19 | FIXTURES_OUT_BC=$(FIXTURES_IN:%=$(OUTPUT_PATH)/%.bc) 20 | FIXTURES_OUT_LL=$(FIXTURES_IN:%=$(OUTPUT_PATH)/%.ll) 21 | FIXTURES_OUT_O=$(FIXTURES_IN:%=$(OUTPUT_PATH)/%.o) 22 | 23 | compile: ## Compile MinimalSwiftXCTestCase.swift 24 | mkdir -p $(OUTPUT_PATH) 25 | $(SWIFTCC) \ 26 | -frontend \ 27 | -sdk $(SYSROOT) \ 28 | -emit-bc \ 29 | -enable-objc-interop \ 30 | -Onone \ 31 | -swift-version 4 \ 32 | -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks \ 33 | -F/opt/SwiftTestCase/Build/Products/Release \ 34 | -target x86_64-apple-macosx10.13 \ 35 | -o $(OUTPUT_PATH)/swift_001_minimal_xctestcase_run.bc \ 36 | MinimalSwiftXCTestCase.swift 37 | 38 | $(SWIFTCC) \ 39 | -frontend \ 40 | -sdk $(SYSROOT) \ 41 | -emit-ir \ 42 | -enable-objc-interop \ 43 | -Onone \ 44 | -g \ 45 | -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks \ 46 | -F/opt/SwiftTestCase/Build/Products/Release \ 47 | -target x86_64-apple-macosx10.13 \ 48 | -o $(OUTPUT_PATH)/swift_001_minimal_xctestcase_run.ll \ 49 | MinimalSwiftXCTestCase.swift 50 | 51 | $(SWIFTCC) \ 52 | -frontend \ 53 | -sdk $(SYSROOT) \ 54 | -emit-object \ 55 | -sdk $(SYSROOT) \ 56 | -g \ 57 | -Onone \ 58 | -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks \ 59 | -F/opt/SwiftTestCase/Build/Products/Release \ 60 | -target x86_64-apple-macosx10.13 \ 61 | -o $(OUTPUT_PATH)/swift_001_minimal_xctestcase_run.Onone.o \ 62 | MinimalSwiftXCTestCase.swift 63 | 64 | $(SWIFTCC) \ 65 | -frontend \ 66 | -sdk $(SYSROOT) \ 67 | -emit-object \ 68 | -O \ 69 | -g \ 70 | -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks \ 71 | -F/opt/SwiftTestCase/Build/Products/Release \ 72 | -target x86_64-apple-macosx10.13 \ 73 | -o $(OUTPUT_PATH)/swift_001_minimal_xctestcase_run.o \ 74 | MinimalSwiftXCTestCase.swift 75 | 76 | clean: ## Cleans the build folder. 77 | rm -rfv $(OUTPUT_PATH) 78 | 79 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/lib/SwiftRuntimeSetup.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm-jit-objc/SwiftRuntimeSetup.h" 2 | 3 | #include 4 | #include 5 | 6 | using namespace llvm; 7 | 8 | namespace SwiftDyLibPath { 9 | static const char *const Core = "libswiftCore.dylib"; 10 | static const char *const Darwin = "libswiftDarwin.dylib"; 11 | static const char *const ObjectiveC = "libswiftObjectiveC.dylib"; 12 | static const char *const Dispatch = "libswiftDispatch.dylib"; 13 | static const char *const CoreFoundation = "libswiftCoreFoundation.dylib"; 14 | 15 | static const char *const IOKit = "libswiftIOKit.dylib"; 16 | static const char *const CoreGraphics = "libswiftCoreGraphics.dylib"; 17 | static const char *const Foundation = "libswiftFoundation.dylib"; 18 | static const char *const CoreData = "libswiftCoreData.dylib"; 19 | 20 | static const char *const XPC = "libswiftXPC.dylib"; 21 | static const char *const os = "libswiftos.dylib"; 22 | static const char *const Metal = "libswiftMetal.dylib"; 23 | 24 | static const char *const CoreImage = "libswiftCoreImage.dylib"; 25 | static const char *const QuartzCore = "libswiftQuartzCore.dylib"; 26 | static const char *const AppKit = "libswiftAppKit.dylib"; 27 | 28 | static const char *const XCTest = "libswiftXCTest.dylib"; 29 | static const char *const SwiftOnoneSupport = "libswiftSwiftOnoneSupport.dylib"; 30 | } 31 | 32 | const char *const SwiftLibrariesPath = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx"; 33 | 34 | const char *const SwiftLibraries[] = { 35 | SwiftDyLibPath::Core, 36 | SwiftDyLibPath::Darwin, 37 | SwiftDyLibPath::ObjectiveC, 38 | SwiftDyLibPath::Dispatch, 39 | SwiftDyLibPath::CoreFoundation, 40 | SwiftDyLibPath::IOKit, 41 | SwiftDyLibPath::CoreGraphics, 42 | SwiftDyLibPath::Foundation, 43 | SwiftDyLibPath::CoreData, 44 | 45 | SwiftDyLibPath::XPC, 46 | SwiftDyLibPath::os, 47 | SwiftDyLibPath::Metal, 48 | SwiftDyLibPath::CoreImage, 49 | SwiftDyLibPath::QuartzCore, 50 | SwiftDyLibPath::AppKit, 51 | 52 | SwiftDyLibPath::XCTest, 53 | SwiftDyLibPath::SwiftOnoneSupport, 54 | }; 55 | 56 | void SwiftRuntimeSetup::loadFoundation() { 57 | assert(!sys::DynamicLibrary::LoadLibraryPermanently( 58 | "/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation" 59 | )); 60 | } 61 | 62 | void SwiftRuntimeSetup::loadXCTest() { 63 | assert(!sys::DynamicLibrary::LoadLibraryPermanently( 64 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/XCTest.framework/XCTest" 65 | )); 66 | } 67 | 68 | void SwiftRuntimeSetup::loadSwiftLibraries() { 69 | char fullLibraryPath[255]; 70 | std::string errorMessage; 71 | 72 | for (const char *const library: SwiftLibraries) { 73 | snprintf(fullLibraryPath, sizeof(fullLibraryPath), "%s/%s", SwiftLibrariesPath, library); 74 | 75 | if (sys::DynamicLibrary::LoadLibraryPermanently(fullLibraryPath, 76 | &errorMessage)) { 77 | errs() << errorMessage << "\n"; 78 | exit(1); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /llvm-jit-objc/tests/XCTestObjCTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "llvm-jit-objc/ObjCResolver.h" 3 | #include "llvm-jit-objc/ObjCRuntime.h" 4 | #include "llvm-jit-objc/SwiftRuntimeSetup.h" 5 | 6 | #include "TestHelpers.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | using namespace llvm; 19 | using namespace llvm::orc; 20 | 21 | static const char *const FixturesPath = "/opt/CustomXCTestRunner"; 22 | 23 | static 24 | llvm::orc::RTDyldObjectLinkingLayer::MemoryManagerGetter getMemoryManager() { 25 | llvm::orc::RTDyldObjectLinkingLayer::MemoryManagerGetter GetMemMgr = 26 | []() { 27 | return std::make_shared(); 28 | }; 29 | return GetMemMgr; 30 | } 31 | 32 | TEST(XCTest_ObjC, Test_001_Minimal) { 33 | // These lines are needed for TargetMachine TM to be created correctly. 34 | llvm::InitializeNativeTarget(); 35 | llvm::InitializeNativeTargetAsmPrinter(); 36 | llvm::InitializeNativeTargetAsmParser(); 37 | 38 | llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); 39 | 40 | SwiftRuntimeSetup::loadFoundation(); 41 | SwiftRuntimeSetup::loadXCTest(); 42 | 43 | // assert(!sys::DynamicLibrary::LoadLibraryPermanently( 44 | // "/opt/CustomXCTestRunner/CustomXCTestRunner.dylib" 45 | // )); 46 | 47 | llvm::LLVMContext llvmContext; 48 | 49 | char fixturePath[255]; 50 | snprintf(fixturePath, sizeof(fixturePath), "%s/%s", FixturesPath, "CustomXCTestRunner.bc"); 51 | auto objcModule = loadModuleAtPath(fixturePath, llvmContext); 52 | 53 | RTDyldObjectLinkingLayer objectLayer(getMemoryManager()); 54 | 55 | std::unique_ptr TM( 56 | EngineBuilder().selectTarget(llvm::Triple(), 57 | "", 58 | "", 59 | SmallVector()) 60 | ); 61 | 62 | assert(TM.get()); 63 | 64 | SimpleCompiler compiler(*TM); 65 | 66 | std::shared_ptr objcResolver = std::make_shared(); 67 | 68 | RTDyldObjectLinkingLayer::ObjectPtr objcCompiledModule = 69 | std::make_shared>(compiler(*objcModule)); 70 | assert(objcCompiledModule); 71 | assert(objcCompiledModule->getBinary()); 72 | assert(objcCompiledModule->getBinary()->isMachO()); 73 | std::vector objcSet; 74 | auto objcHandle = objectLayer.addObject(objcCompiledModule, objcResolver).get(); 75 | assert(objcHandle->get()); 76 | 77 | Error err = objectLayer.emitAndFinalize(objcHandle); 78 | 79 | // void *runnerPtr = sys::DynamicLibrary::SearchForAddressOfSymbol("CustomXCTestRunnerRunAll"); 80 | // auto runnerFPtr = ((int (*)(void))runnerPtr); 81 | // if (runnerFPtr == nullptr) { 82 | // errs() << "Could not find CustomXCTestRunner function: CustomXCTestRunnerRunAll()" << "\n"; 83 | // exit(1); 84 | // } 85 | // int result = runnerFPtr(); 86 | // ASSERT_EQ(result, 0); 87 | } 88 | -------------------------------------------------------------------------------- /llvm-jit-objc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5.1) 2 | 3 | include(LLVM.toolchain.macos.cmake) 4 | include(LLVM.cmake) 5 | 6 | # This enables assertions for Release builds. 7 | # https://stackoverflow.com/questions/22140520/how-to-enable-assert-in-cmake-release-mode 8 | string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") 9 | 10 | # Setting THREADS_PREFER_PTHREAD_FLAG and finding package Threads resolves: 11 | # /usr/bin/ld: ../../gtest-1.7.0/libgtest.a(gtest-all.cc.o): undefined reference to symbol 'pthread_key_delete@@GLIBC_2.2.5' 12 | # /lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line 13 | # https://stackoverflow.com/questions/25617839/undefined-reference-to-symbol-pthread-key-deleteglibc-2-2-5 14 | set(THREADS_PREFER_PTHREAD_FLAG ON) 15 | find_package(Threads REQUIRED) 16 | 17 | add_compile_options($<$:-std=c++11>) 18 | 19 | if (NOT LLVM_ROOT) 20 | message(FATAL_ERROR "This CMakeLists.txt file expects cmake to be called with a 21 | CMake toolchain file which provides LLVM_ROOT:\n \ 22 | -DCMAKE_TOOLCHAIN_FILE=path_to_your_toolchain") 23 | endif() 24 | 25 | ## LLVM CXX flags 26 | llvm_get_cxx_flags(LLVM_CXX_FLAGS) 27 | 28 | ## LLVM lib directory 29 | llvm_get_lib_dir(LLVM_LIB_PATH) 30 | 31 | ## LLVM linker flags. 32 | llvm_get_link_flags(LLVM_LINK_FLAGS) 33 | # Without -undefined,dynamic_lookup flags there is a problem with order in which 34 | # the libraries are linked and that causes missing symbols. 35 | # https://github.com/eliben/llvm-clang-samples/pull/11 36 | set(LLVM_LINK_FLAGS "${LLVM_LINK_FLAGS} -Wl,-undefined,dynamic_lookup") 37 | 38 | # LLVM libraries 39 | set(llvm_components 40 | "asmparser" 41 | "orcjit" 42 | "support" 43 | "x86") 44 | llvm_get_libs(LLVMJITLAB_DEPENDENCY_LLVM_LIBRARIES "${llvm_components}") 45 | 46 | # https://cmake.org/Wiki/CMake_RPATH_handling#Always_full_RPATH 47 | SET(CMAKE_SKIP_BUILD_RPATH FALSE) 48 | SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 49 | SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" "${LLVM_LIB_PATH}") 50 | SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 51 | 52 | set(LLVMJITLAB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 53 | set(LLVMJITLAB_INCLUDE_DIR ${LLVMJITLAB_SOURCE_DIR}/include) 54 | 55 | include_directories(${LLVM_ROOT}/include) 56 | 57 | ## LLVM's dependencies. 58 | find_library(LLVMJITLAB_DEPENDENCY_LIBZ z HINTS ${LLVM_TOOLCHAIN_LIBZ_PATH}) 59 | find_library(LLVMJITLAB_DEPENDENCY_NCURSES ncurses) 60 | ## Mull's own dependencies: 61 | find_library(LLVMJITLAB_DEPENDENCY_SQLITE sqlite3 HINTS ${LLVMJITLAB_TOOLCHAIN_SQLITE_PATH}) 62 | 63 | include_directories(${LLVMJITLAB_INCLUDE_DIR}) 64 | 65 | ## LLVM 66 | set(LLVM_DEPENDENCIES 67 | ${LLVMJITLAB_DEPENDENCY_LLVM_LIBRARIES} 68 | 69 | ${LLVMJITLAB_DEPENDENCY_LIBZ} 70 | ${LLVMJITLAB_DEPENDENCY_NCURSES} 71 | ) 72 | 73 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS}") 74 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LLVM_LINK_FLAGS}") 75 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LLVM_LINK_FLAGS}") 76 | # # Link flags 77 | # get_target_property(default_link_flags llvm-jit-objc LINK_FLAGS) 78 | # if(NOT ${default_link_flags}) 79 | # set(default_link_flags "") 80 | # endif() 81 | # set(link_flags 82 | # "${default_link_flags} " 83 | # ) 84 | # set_target_properties(llvm-jit-objc PROPERTIES LINK_FLAGS "${link_flags}") 85 | 86 | add_subdirectory(src) 87 | add_subdirectory(tests) 88 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/custom/gtest-port.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Injection point for custom user configurations. 31 | // The following macros can be defined: 32 | // 33 | // Flag related macros: 34 | // GTEST_FLAG(flag_name) 35 | // GTEST_USE_OWN_FLAGFILE_FLAG_ - Define to 0 when the system provides its 36 | // own flagfile flag parsing. 37 | // GTEST_DECLARE_bool_(name) 38 | // GTEST_DECLARE_int32_(name) 39 | // GTEST_DECLARE_string_(name) 40 | // GTEST_DEFINE_bool_(name, default_val, doc) 41 | // GTEST_DEFINE_int32_(name, default_val, doc) 42 | // GTEST_DEFINE_string_(name, default_val, doc) 43 | // 44 | // Test filtering: 45 | // GTEST_TEST_FILTER_ENV_VAR_ - The name of an environment variable that 46 | // will be used if --GTEST_FLAG(test_filter) 47 | // is not provided. 48 | // 49 | // Logging: 50 | // GTEST_LOG_(severity) 51 | // GTEST_CHECK_(condition) 52 | // Functions LogToStderr() and FlushInfoLog() have to be provided too. 53 | // 54 | // Threading: 55 | // GTEST_HAS_NOTIFICATION_ - Enabled if Notification is already provided. 56 | // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - Enabled if Mutex and ThreadLocal are 57 | // already provided. 58 | // Must also provide GTEST_DECLARE_STATIC_MUTEX_(mutex) and 59 | // GTEST_DEFINE_STATIC_MUTEX_(mutex) 60 | // 61 | // GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) 62 | // GTEST_LOCK_EXCLUDED_(locks) 63 | // 64 | // Exporting API symbols: 65 | // GTEST_API_ - Specifier for exported symbols. 66 | // 67 | // ** Custom implementation starts here ** 68 | 69 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 70 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 71 | 72 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 73 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/lib/ObjCType.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm-jit-objc/ObjCType.h" 2 | 3 | #include "llvm-jit-objc/ObjCRuntimeHelpers.h" 4 | #include "llvm-jit-objc/DebugUtils.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace llvm; 14 | using namespace objc; 15 | 16 | namespace mull { namespace objc { 17 | 18 | std::string method64_t::getDebugDescription(int level) const { 19 | std::ostringstream os; 20 | std::string padding = std::string(level * 4, ' '); 21 | 22 | os << padding << "[method64_t]\n"; 23 | os << padding << "\t" << "name: " << sel_getName(name) << "\n"; 24 | os << padding << "\t" << "types: " << (const char *)types << "\n"; 25 | os << padding << "\t" << "imp: " << (const void * const *)&imp << " / " << (const void *)imp << " / " << to_hex16(imp) << "\n"; 26 | 27 | return os.str(); 28 | } 29 | 30 | std::string method_list64_t::getDebugDescription(int level) const { 31 | std::ostringstream os; 32 | std::string padding = std::string(level * 4, ' '); 33 | 34 | if (count > 100 || entsize == 0) { 35 | os << padding << "[error]" << "\n"; 36 | return os.str(); 37 | } 38 | 39 | os << padding << "[method_list64_t]\n"; 40 | os << padding << "entsize: " << entsize << "\n"; 41 | os << padding << "count: " << count << "\n"; 42 | for (uint32_t i = 0; i < count; i++) { 43 | const method64_t *method = getFirstMethodPointer() + i; 44 | os << method->getDebugDescription(level + 1); 45 | } 46 | 47 | return os.str(); 48 | } 49 | 50 | std::string class_ro64_t::getDebugDescription(int level) const { 51 | std::ostringstream os; 52 | std::string padding = std::string(level * 4, ' '); 53 | 54 | os << padding << "[class_ro64_t] (metaclass: " << (isMetaClass() ? "yes" : "no") << ")\n"; 55 | os << padding << "name: " << getName() << "\n"; 56 | os << padding << "baseMethods: " << (void *)baseMethods << "\n"; 57 | if (method_list64_t *methodListPointer = getMethodListPtr()) { 58 | os << methodListPointer->getDebugDescription(level + 1); 59 | } 60 | 61 | return os.str(); 62 | } 63 | 64 | std::string class64_t::getDebugDescription(Description level) const { 65 | std::ostringstream os; 66 | std::string padding = std::string(level * 4, ' '); 67 | 68 | os << padding << "[class64_t]" << "\n"; 69 | os << padding << "this: " << (void *)this << " / " << to_hex16(this) << "\n"; 70 | os << padding << "isa: " << (void *)isa << "\n"; 71 | if (level == Clazz) { 72 | os << getIsaPointer()->getDebugDescription(IsaOrSuperclass); 73 | } 74 | os << padding << "superclass: " << (void *const *)&superclass << "/" << (void *)superclass << "\n"; 75 | if (level == Clazz) { 76 | Class superClz = (Class)getSuperclassPointer(); 77 | if (objc_classIsRegistered(superClz)) { 78 | os << padding << "\t(registered) " << object_getClassName((id)superClz) << "\n"; 79 | } else { 80 | class64_t *superclassPointer = getSuperclassPointer(); 81 | os << superclassPointer->getDebugDescription(IsaOrSuperclass); 82 | } 83 | } 84 | os << padding << "cache: " << (void *const *)&cache << "/" << (void *)cache << "\n"; 85 | 86 | os << padding << "vtable: " << (void *const *)&vtable << "/" << (void *)vtable << "\n"; 87 | 88 | os << padding << "data: " << (void *const *)&data << "/" << (void *)data << "\n"; 89 | 90 | auto dataPtr = getDataPointer(); 91 | os << dataPtr->getDebugDescription(level + 1); 92 | 93 | return os.str(); 94 | } 95 | 96 | } } 97 | 98 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/lib/ObjCEnabledMemoryManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | using namespace llvm; 6 | 7 | ObjCEnabledMemoryManager::ObjCEnabledMemoryManager() 8 | : runtime(mull::objc::Runtime()) {} 9 | 10 | uint8_t * 11 | ObjCEnabledMemoryManager::allocateDataSection(uintptr_t Size, 12 | unsigned Alignment, 13 | unsigned SectionID, 14 | llvm::StringRef SectionName, 15 | bool isReadOnly) { 16 | uint8_t *pointer = SectionMemoryManager::allocateDataSection(Size, 17 | Alignment, 18 | SectionID, 19 | SectionName, 20 | isReadOnly); 21 | 22 | int numRegisteredClasses = objc_getClassList(NULL, 0); 23 | assert(numRegisteredClasses > 0); 24 | //errs() << "OBJC CREATED CLASSES constr: " << numRegisteredClasses << "\n"; 25 | 26 | if (SectionName.find("objc") != llvm::StringRef::npos) { 27 | errs() << "MullMemoryManager::allocateDataSection(objc) -- " 28 | << SectionName << " " 29 | << "pointer: " << pointer << " " 30 | << "size: " << Size 31 | << "\n"; 32 | 33 | ObjectSectionEntry entry(pointer, Size, SectionName); 34 | 35 | objcSections.push_back(entry); 36 | } 37 | 38 | return pointer; 39 | } 40 | 41 | bool ObjCEnabledMemoryManager::finalizeMemory(std::string *ErrMsg) { 42 | registerObjC(); 43 | 44 | int numRegisteredClasses = objc_getClassList(NULL, 0); 45 | assert(numRegisteredClasses > 0); 46 | 47 | Class *buffer = (Class *)malloc(sizeof(Class) * numRegisteredClasses); 48 | objc_getClassList(buffer, numRegisteredClasses); 49 | 50 | errs() << "OBJC CREATED CLASSES finalizeMemory: " << numRegisteredClasses << "\n"; 51 | for (int i = 0; i < numRegisteredClasses; i++) { 52 | // errs() << "created class: " << class_getName(buffer[i]) << "\n"; 53 | } 54 | 55 | bool success = SectionMemoryManager::finalizeMemory(ErrMsg); 56 | 57 | return success; 58 | } 59 | 60 | void ObjCEnabledMemoryManager::registerObjC() { 61 | errs() << "MullMemoryManager::registerObjC()" << "\n"; 62 | 63 | for (ObjectSectionEntry &entry: objcSections) { 64 | errs() << entry.section << "\n"; 65 | 66 | if (entry.section.find("__objc_selrefs") != StringRef::npos) { 67 | runtime.registerSelectors(entry.pointer, entry.size); 68 | } 69 | } 70 | 71 | for (ObjectSectionEntry &entry: objcSections) { 72 | if (entry.section.find("__objc_classlist") != StringRef::npos) { 73 | runtime.addClassesFromSection(entry.pointer, entry.size); 74 | } 75 | } 76 | 77 | runtime.registerClasses(); 78 | 79 | for (ObjectSectionEntry &entry: objcSections) { 80 | if (entry.section.find("__objc_classrefs") != StringRef::npos) { 81 | runtime.addClassesFromClassRefsSection(entry.pointer, entry.size); 82 | } 83 | } 84 | 85 | for (ObjectSectionEntry &entry: objcSections) { 86 | if (entry.section.find("__objc_superrefs") != StringRef::npos) { 87 | runtime.addClassesFromSuperclassRefsSection(entry.pointer, entry.size); 88 | } 89 | } 90 | 91 | for (ObjectSectionEntry &entry: objcSections) { 92 | if (entry.section.find("__objc_catlist") != StringRef::npos) { 93 | runtime.addCategoriesFromSection(entry.pointer, entry.size); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/gtest-port-arch.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // The Google C++ Testing Framework (Google Test) 31 | // 32 | // This header file defines the GTEST_OS_* macro. 33 | // It is separate from gtest-port.h so that custom/gtest-port.h can include it. 34 | 35 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 36 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 37 | 38 | // Determines the platform on which Google Test is compiled. 39 | #ifdef __CYGWIN__ 40 | # define GTEST_OS_CYGWIN 1 41 | #elif defined __SYMBIAN32__ 42 | # define GTEST_OS_SYMBIAN 1 43 | #elif defined _WIN32 44 | # define GTEST_OS_WINDOWS 1 45 | # ifdef _WIN32_WCE 46 | # define GTEST_OS_WINDOWS_MOBILE 1 47 | # elif defined(__MINGW__) || defined(__MINGW32__) 48 | # define GTEST_OS_WINDOWS_MINGW 1 49 | # elif defined(WINAPI_FAMILY) 50 | # include 51 | # if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 52 | # define GTEST_OS_WINDOWS_DESKTOP 1 53 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) 54 | # define GTEST_OS_WINDOWS_PHONE 1 55 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 56 | # define GTEST_OS_WINDOWS_RT 1 57 | # else 58 | // WINAPI_FAMILY defined but no known partition matched. 59 | // Default to desktop. 60 | # define GTEST_OS_WINDOWS_DESKTOP 1 61 | # endif 62 | # else 63 | # define GTEST_OS_WINDOWS_DESKTOP 1 64 | # endif // _WIN32_WCE 65 | #elif defined __APPLE__ 66 | # define GTEST_OS_MAC 1 67 | # if TARGET_OS_IPHONE 68 | # define GTEST_OS_IOS 1 69 | # endif 70 | #elif defined __FreeBSD__ 71 | # define GTEST_OS_FREEBSD 1 72 | #elif defined __linux__ 73 | # define GTEST_OS_LINUX 1 74 | # if defined __ANDROID__ 75 | # define GTEST_OS_LINUX_ANDROID 1 76 | # endif 77 | #elif defined __MVS__ 78 | # define GTEST_OS_ZOS 1 79 | #elif defined(__sun) && defined(__SVR4) 80 | # define GTEST_OS_SOLARIS 1 81 | #elif defined(_AIX) 82 | # define GTEST_OS_AIX 1 83 | #elif defined(__hpux) 84 | # define GTEST_OS_HPUX 1 85 | #elif defined __native_client__ 86 | # define GTEST_OS_NACL 1 87 | #elif defined __OpenBSD__ 88 | # define GTEST_OS_OPENBSD 1 89 | #elif defined __QNX__ 90 | # define GTEST_OS_QNX 1 91 | #endif // __CYGWIN__ 92 | 93 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 94 | -------------------------------------------------------------------------------- /llvm-jit-objc/tests/XCTestSwiftTest.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm-jit-objc/ObjCEnabledMemoryManager.h" 2 | #include "llvm-jit-objc/ObjCResolver.h" 3 | #include "llvm-jit-objc/ObjCRuntime.h" 4 | #include "llvm-jit-objc/ObjCRuntimeHelpers.h" 5 | #include "llvm-jit-objc/SwiftRuntimeSetup.h" 6 | 7 | #include "CustomXCTestRunnerBinding.h" 8 | #include "TestHelpers.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace llvm; 24 | using namespace llvm::orc; 25 | 26 | static const char *const FixturesPath = "/opt/llvm-jit-objc/fixtures/bitcode"; 27 | 28 | static 29 | llvm::orc::RTDyldObjectLinkingLayer::MemoryManagerGetter getMemoryManager() { 30 | llvm::orc::RTDyldObjectLinkingLayer::MemoryManagerGetter GetMemMgr = 31 | []() { 32 | return std::make_shared(); 33 | }; 34 | return GetMemMgr; 35 | } 36 | 37 | TEST(XCTest_Swift, Test_001_Minimal) { 38 | // These lines are needed for TargetMachine TM to be created correctly. 39 | llvm::InitializeNativeTarget(); 40 | llvm::InitializeNativeTargetAsmPrinter(); 41 | llvm::InitializeNativeTargetAsmParser(); 42 | 43 | llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); 44 | 45 | SwiftRuntimeSetup::loadFoundation(); 46 | SwiftRuntimeSetup::loadXCTest(); 47 | SwiftRuntimeSetup::loadSwiftLibraries(); 48 | 49 | 50 | assert(!sys::DynamicLibrary::LoadLibraryPermanently( 51 | CustomXCTestRunnerBinding::getCustomXCTestRunnerPath().c_str() 52 | )); 53 | 54 | llvm::LLVMContext llvmContext; 55 | 56 | char fixturePath[255]; 57 | snprintf(fixturePath, sizeof(fixturePath), "%s/%s", FixturesPath, "swift_001_minimal_xctestcase_run.bc"); 58 | 59 | auto objcModule = loadModuleAtPath(fixturePath, llvmContext); 60 | 61 | RTDyldObjectLinkingLayer objectLayer(getMemoryManager()); 62 | 63 | std::unique_ptr TM( 64 | EngineBuilder().selectTarget(llvm::Triple(), 65 | "", 66 | "", 67 | SmallVector()) 68 | ); 69 | 70 | assert(TM.get()); 71 | 72 | SimpleCompiler compiler(*TM); 73 | 74 | std::shared_ptr objcResolver = std::make_shared(); 75 | 76 | RTDyldObjectLinkingLayer::ObjectPtr objcCompiledModule = 77 | std::make_shared>(compiler(*objcModule)); 78 | assert(objcCompiledModule); 79 | assert(objcCompiledModule->getBinary()); 80 | assert(objcCompiledModule->getBinary()->isMachO()); 81 | std::vector objcSet; 82 | auto objcHandle = objectLayer.addObject(objcCompiledModule, objcResolver).get(); 83 | assert(objcHandle->get()); 84 | 85 | Error err = objectLayer.emitAndFinalize(objcHandle); 86 | 87 | id runtimeClass = (id)objc_getRequiredClass("BinarySearchTest"); 88 | id allocatedInstance = objc_msgSend(runtimeClass, sel_registerName("alloc")); 89 | id initializedInstance = objc_msgSend(allocatedInstance, sel_registerName("init")); 90 | assert((id)object_getClass(initializedInstance) == runtimeClass); 91 | 92 | Ivar iv = class_getInstanceVariable((Class)runtimeClass, "searchList"); 93 | assert(iv); 94 | id ivv = object_getIvar(initializedInstance, iv); 95 | assert(iv); 96 | 97 | const char *clzName = object_getClassName(ivv); 98 | assert(strcmp((char *)clzName, "Swift.__EmptyArrayStorage") == 0); 99 | 100 | void *runnerPtr = sys::DynamicLibrary::SearchForAddressOfSymbol("CustomXCTestRunnerRunAll"); 101 | auto runnerFPtr = ((int (*)(void))runnerPtr); 102 | if (runnerFPtr == nullptr) { 103 | errs() << "Could not find CustomXCTestRunner function: CustomXCTestRunnerRunAll()" << "\n"; 104 | exit(1); 105 | } 106 | int result = runnerFPtr(); 107 | ASSERT_EQ(result, 0); 108 | } 109 | -------------------------------------------------------------------------------- /googletest/src/gtest-typed-test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Google Inc. 2 | // All Rights Reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | #include "gtest/gtest-typed-test.h" 33 | #include "gtest/gtest.h" 34 | 35 | namespace testing { 36 | namespace internal { 37 | 38 | #if GTEST_HAS_TYPED_TEST_P 39 | 40 | // Skips to the first non-space char in str. Returns an empty string if str 41 | // contains only whitespace characters. 42 | static const char* SkipSpaces(const char* str) { 43 | while (IsSpace(*str)) 44 | str++; 45 | return str; 46 | } 47 | 48 | static std::vector SplitIntoTestNames(const char* src) { 49 | std::vector name_vec; 50 | src = SkipSpaces(src); 51 | for (; src != NULL; src = SkipComma(src)) { 52 | name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src))); 53 | } 54 | return name_vec; 55 | } 56 | 57 | // Verifies that registered_tests match the test names in 58 | // registered_tests_; returns registered_tests if successful, or 59 | // aborts the program otherwise. 60 | const char* TypedTestCasePState::VerifyRegisteredTestNames( 61 | const char* file, int line, const char* registered_tests) { 62 | typedef RegisteredTestsMap::const_iterator RegisteredTestIter; 63 | registered_ = true; 64 | 65 | std::vector name_vec = SplitIntoTestNames(registered_tests); 66 | 67 | Message errors; 68 | 69 | std::set tests; 70 | for (std::vector::const_iterator name_it = name_vec.begin(); 71 | name_it != name_vec.end(); ++name_it) { 72 | const std::string& name = *name_it; 73 | if (tests.count(name) != 0) { 74 | errors << "Test " << name << " is listed more than once.\n"; 75 | continue; 76 | } 77 | 78 | bool found = false; 79 | for (RegisteredTestIter it = registered_tests_.begin(); 80 | it != registered_tests_.end(); 81 | ++it) { 82 | if (name == it->first) { 83 | found = true; 84 | break; 85 | } 86 | } 87 | 88 | if (found) { 89 | tests.insert(name); 90 | } else { 91 | errors << "No test named " << name 92 | << " can be found in this test case.\n"; 93 | } 94 | } 95 | 96 | for (RegisteredTestIter it = registered_tests_.begin(); 97 | it != registered_tests_.end(); 98 | ++it) { 99 | if (tests.count(it->first) == 0) { 100 | errors << "You forgot to list test " << it->first << ".\n"; 101 | } 102 | } 103 | 104 | const std::string& errors_str = errors.GetString(); 105 | if (errors_str != "") { 106 | fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), 107 | errors_str.c_str()); 108 | fflush(stderr); 109 | posix::Abort(); 110 | } 111 | 112 | return registered_tests; 113 | } 114 | 115 | #endif // GTEST_HAS_TYPED_TEST_P 116 | 117 | } // namespace internal 118 | } // namespace testing 119 | -------------------------------------------------------------------------------- /googletest/src/gtest-test-part.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | 34 | #include "gtest/gtest-test-part.h" 35 | 36 | // Indicates that this translation unit is part of Google Test's 37 | // implementation. It must come before gtest-internal-inl.h is 38 | // included, or there will be a compiler error. This trick exists to 39 | // prevent the accidental inclusion of gtest-internal-inl.h in the 40 | // user's code. 41 | #define GTEST_IMPLEMENTATION_ 1 42 | #include "src/gtest-internal-inl.h" 43 | #undef GTEST_IMPLEMENTATION_ 44 | 45 | namespace testing { 46 | 47 | using internal::GetUnitTestImpl; 48 | 49 | // Gets the summary of the failure message by omitting the stack trace 50 | // in it. 51 | std::string TestPartResult::ExtractSummary(const char* message) { 52 | const char* const stack_trace = strstr(message, internal::kStackTraceMarker); 53 | return stack_trace == NULL ? message : 54 | std::string(message, stack_trace); 55 | } 56 | 57 | // Prints a TestPartResult object. 58 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { 59 | return os 60 | << result.file_name() << ":" << result.line_number() << ": " 61 | << (result.type() == TestPartResult::kSuccess ? "Success" : 62 | result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : 63 | "Non-fatal failure") << ":\n" 64 | << result.message() << std::endl; 65 | } 66 | 67 | // Appends a TestPartResult to the array. 68 | void TestPartResultArray::Append(const TestPartResult& result) { 69 | array_.push_back(result); 70 | } 71 | 72 | // Returns the TestPartResult at the given index (0-based). 73 | const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { 74 | if (index < 0 || index >= size()) { 75 | printf("\nInvalid index (%d) into TestPartResultArray.\n", index); 76 | internal::posix::Abort(); 77 | } 78 | 79 | return array_[index]; 80 | } 81 | 82 | // Returns the number of TestPartResult objects in the array. 83 | int TestPartResultArray::size() const { 84 | return static_cast(array_.size()); 85 | } 86 | 87 | namespace internal { 88 | 89 | HasNewFatalFailureHelper::HasNewFatalFailureHelper() 90 | : has_new_fatal_failure_(false), 91 | original_reporter_(GetUnitTestImpl()-> 92 | GetTestPartResultReporterForCurrentThread()) { 93 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); 94 | } 95 | 96 | HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { 97 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( 98 | original_reporter_); 99 | } 100 | 101 | void HasNewFatalFailureHelper::ReportTestPartResult( 102 | const TestPartResult& result) { 103 | if (result.fatally_failed()) 104 | has_new_fatal_failure_ = true; 105 | original_reporter_->ReportTestPartResult(result); 106 | } 107 | 108 | } // namespace internal 109 | 110 | } // namespace testing 111 | -------------------------------------------------------------------------------- /llvm-jit-objc/tests/SandboxTest.cpp: -------------------------------------------------------------------------------- 1 | //#include "ObjCEnabledMemoryManager.h" 2 | 3 | #include "llvm-jit-objc/ObjCEnabledMemoryManager.h" 4 | #include "llvm-jit-objc/ObjCResolver.h" 5 | #include "llvm-jit-objc/ObjCRuntime.h" 6 | #include "llvm-jit-objc/ObjCRuntimeHelpers.h" 7 | #include "llvm-jit-objc/SwiftRuntimeSetup.h" 8 | 9 | #include "TestHelpers.h" 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | using namespace llvm; 31 | using namespace llvm::orc; 32 | 33 | static 34 | llvm::orc::RTDyldObjectLinkingLayer::MemoryManagerGetter getMemoryManager() { 35 | llvm::orc::RTDyldObjectLinkingLayer::MemoryManagerGetter GetMemMgr = 36 | []() { 37 | return std::make_shared(); 38 | }; 39 | return GetMemMgr; 40 | } 41 | 42 | #include 43 | 44 | std::vector loadBitcodeFileListFromPath(std::string path) { 45 | std::vector bitcodePaths; 46 | 47 | std::ifstream ifs(path); 48 | 49 | for (std::string path; getline(ifs, path); ) { 50 | if (path.at(0) == '#') { 51 | continue; 52 | } 53 | 54 | bitcodePaths.push_back(path); 55 | } 56 | 57 | assert(bitcodePaths.size() > 0); 58 | 59 | return bitcodePaths; 60 | } 61 | 62 | static void createDummyFunction(StringRef Name, llvm::Module &M) { 63 | auto &Context = M.getContext(); 64 | Function *F = cast(M.getOrInsertFunction( 65 | Name, FunctionType::get(Type::getVoidTy(Context), false))); 66 | BasicBlock *BB = BasicBlock::Create(Context, "entry", F); 67 | new UnreachableInst(Context, BB); 68 | } 69 | 70 | TEST(DISABLED_Sandbox, Test) { 71 | // These lines are needed for TargetMachine TM to be created correctly. 72 | llvm::InitializeNativeTarget(); 73 | llvm::InitializeNativeTargetAsmPrinter(); 74 | llvm::InitializeNativeTargetAsmParser(); 75 | 76 | llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); 77 | 78 | SwiftRuntimeSetup::loadSwiftLibraries(); 79 | 80 | llvm::LLVMContext llvmContext; 81 | 82 | RTDyldObjectLinkingLayer objectLayer(getMemoryManager()); 83 | 84 | std::unique_ptr TM( 85 | EngineBuilder().selectTarget(llvm::Triple(), 86 | "", 87 | "", 88 | SmallVector()) 89 | ); 90 | 91 | TM->setOptLevel(CodeGenOpt::Level::None); 92 | 93 | assert(TM.get()); 94 | SimpleCompiler compiler(*TM); 95 | 96 | std::shared_ptr objcResolver = std::make_shared(); 97 | 98 | std::vector bitcodeFilePaths = loadBitcodeFileListFromPath("/opt/bitcode-targets/swift-protobuf-bitcode/bitcode.list.yml"); 99 | 100 | auto resolver = llvm::orc::createLambdaResolver( 101 | [&](std::string name) { 102 | if (JITSymbol js = objectLayer.findSymbol(name, false)) { 103 | return js; 104 | } 105 | 106 | if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(name)) { 107 | return JITSymbol(SymAddr, JITSymbolFlags::Exported); 108 | } 109 | 110 | return JITSymbol(nullptr); 111 | }, 112 | [&](std::string name) { 113 | return JITSymbol(nullptr); 114 | } 115 | ); 116 | 117 | std::vector handles; 118 | for (std::string &bitcodeFilePath: bitcodeFilePaths) { 119 | errs() << "loading bitcode path: " << bitcodeFilePath << "\n"; 120 | auto bitcodeModule = loadModuleAtPath(bitcodeFilePath, llvmContext); 121 | 122 | createDummyFunction("dummy", *bitcodeModule); 123 | 124 | RTDyldObjectLinkingLayer::ObjectPtr compiledModule = 125 | std::make_shared>(compiler(*bitcodeModule)); 126 | assert(compiledModule); 127 | assert(compiledModule->getBinary()); 128 | assert(compiledModule->getBinary()->isMachO()); 129 | 130 | llvm::orc::RTDyldObjectLinkingLayer::ObjHandleT handle = objectLayer.addObject(compiledModule, resolver).get(); 131 | handles.push_back(handle); 132 | // Error err = objectLayer.emitAndFinalize(handle); 133 | // 134 | // std::string cacheName("/tmp/_Sandbox.o"); 135 | // std::error_code EC; 136 | // raw_fd_ostream outfile(cacheName, EC, sys::fs::F_None); 137 | // outfile.write(compiledModule->getBinary()->getMemoryBufferRef().getBufferStart(), 138 | // compiledModule->getBinary()->getMemoryBufferRef().getBufferSize()); 139 | // outfile.close(); 140 | } 141 | 142 | for (uint32_t i = 0; i < handles.size(); i++) { 143 | auto &handle = handles.at(i); 144 | errs() << "Resolving handle: " << handle->get() << " / " << i << "\n"; 145 | 146 | auto symb = (*handle)->getSymbol("_dummy", false); 147 | assert(symb.getAddress().get() > 0); 148 | // Error err = objectLayer.emitAndFinalize(handle); 149 | // //assert(!err); 150 | } 151 | 152 | std::string functionName = "_CustomXCTestRunnerRunAll"; 153 | JITSymbol symbol = objectLayer.findSymbol(functionName, false); 154 | 155 | void *fpointer = 156 | reinterpret_cast(static_cast(symbol.getAddress().get())); 157 | 158 | if (fpointer == nullptr) { 159 | errs() << "CustomTestRunner> Can't find pointer to function: " 160 | << functionName << "\n"; 161 | exit(1); 162 | } 163 | 164 | auto runnerFunction = ((int (*)(void))(intptr_t)fpointer); 165 | 166 | int result = runnerFunction(); 167 | EXPECT_EQ(result, 0); 168 | 169 | // void *runnerPtr = sys::DynamicLibrary::SearchForAddressOfSymbol("CustomXCTestRunnerRunAll"); 170 | // auto runnerFPtr = ((int (*)(void))runnerPtr); 171 | // if (runnerFPtr == nullptr) { 172 | // errs() << "Could not find CustomXCTestRunner function: CustomXCTestRunnerRunAll()" << "\n"; 173 | // exit(1); 174 | // } 175 | // int result = runnerFPtr(); 176 | // ASSERT_EQ(result, 0); 177 | } 178 | 179 | -------------------------------------------------------------------------------- /googletest/include/gtest/gtest-test-part.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | 33 | #ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 34 | #define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 35 | 36 | #include 37 | #include 38 | #include "gtest/internal/gtest-internal.h" 39 | #include "gtest/internal/gtest-string.h" 40 | 41 | namespace testing { 42 | 43 | // A copyable object representing the result of a test part (i.e. an 44 | // assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). 45 | // 46 | // Don't inherit from TestPartResult as its destructor is not virtual. 47 | class GTEST_API_ TestPartResult { 48 | public: 49 | // The possible outcomes of a test part (i.e. an assertion or an 50 | // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). 51 | enum Type { 52 | kSuccess, // Succeeded. 53 | kNonFatalFailure, // Failed but the test can continue. 54 | kFatalFailure // Failed and the test should be terminated. 55 | }; 56 | 57 | // C'tor. TestPartResult does NOT have a default constructor. 58 | // Always use this constructor (with parameters) to create a 59 | // TestPartResult object. 60 | TestPartResult(Type a_type, 61 | const char* a_file_name, 62 | int a_line_number, 63 | const char* a_message) 64 | : type_(a_type), 65 | file_name_(a_file_name == NULL ? "" : a_file_name), 66 | line_number_(a_line_number), 67 | summary_(ExtractSummary(a_message)), 68 | message_(a_message) { 69 | } 70 | 71 | // Gets the outcome of the test part. 72 | Type type() const { return type_; } 73 | 74 | // Gets the name of the source file where the test part took place, or 75 | // NULL if it's unknown. 76 | const char* file_name() const { 77 | return file_name_.empty() ? NULL : file_name_.c_str(); 78 | } 79 | 80 | // Gets the line in the source file where the test part took place, 81 | // or -1 if it's unknown. 82 | int line_number() const { return line_number_; } 83 | 84 | // Gets the summary of the failure message. 85 | const char* summary() const { return summary_.c_str(); } 86 | 87 | // Gets the message associated with the test part. 88 | const char* message() const { return message_.c_str(); } 89 | 90 | // Returns true iff the test part passed. 91 | bool passed() const { return type_ == kSuccess; } 92 | 93 | // Returns true iff the test part failed. 94 | bool failed() const { return type_ != kSuccess; } 95 | 96 | // Returns true iff the test part non-fatally failed. 97 | bool nonfatally_failed() const { return type_ == kNonFatalFailure; } 98 | 99 | // Returns true iff the test part fatally failed. 100 | bool fatally_failed() const { return type_ == kFatalFailure; } 101 | 102 | private: 103 | Type type_; 104 | 105 | // Gets the summary of the failure message by omitting the stack 106 | // trace in it. 107 | static std::string ExtractSummary(const char* message); 108 | 109 | // The name of the source file where the test part took place, or 110 | // "" if the source file is unknown. 111 | std::string file_name_; 112 | // The line in the source file where the test part took place, or -1 113 | // if the line number is unknown. 114 | int line_number_; 115 | std::string summary_; // The test failure summary. 116 | std::string message_; // The test failure message. 117 | }; 118 | 119 | // Prints a TestPartResult object. 120 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result); 121 | 122 | // An array of TestPartResult objects. 123 | // 124 | // Don't inherit from TestPartResultArray as its destructor is not 125 | // virtual. 126 | class GTEST_API_ TestPartResultArray { 127 | public: 128 | TestPartResultArray() {} 129 | 130 | // Appends the given TestPartResult to the array. 131 | void Append(const TestPartResult& result); 132 | 133 | // Returns the TestPartResult at the given index (0-based). 134 | const TestPartResult& GetTestPartResult(int index) const; 135 | 136 | // Returns the number of TestPartResult objects in the array. 137 | int size() const; 138 | 139 | private: 140 | std::vector array_; 141 | 142 | GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); 143 | }; 144 | 145 | // This interface knows how to report a test part result. 146 | class TestPartResultReporterInterface { 147 | public: 148 | virtual ~TestPartResultReporterInterface() {} 149 | 150 | virtual void ReportTestPartResult(const TestPartResult& result) = 0; 151 | }; 152 | 153 | namespace internal { 154 | 155 | // This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a 156 | // statement generates new fatal failures. To do so it registers itself as the 157 | // current test part result reporter. Besides checking if fatal failures were 158 | // reported, it only delegates the reporting to the former result reporter. 159 | // The original result reporter is restored in the destructor. 160 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 161 | class GTEST_API_ HasNewFatalFailureHelper 162 | : public TestPartResultReporterInterface { 163 | public: 164 | HasNewFatalFailureHelper(); 165 | virtual ~HasNewFatalFailureHelper(); 166 | virtual void ReportTestPartResult(const TestPartResult& result); 167 | bool has_new_fatal_failure() const { return has_new_fatal_failure_; } 168 | private: 169 | bool has_new_fatal_failure_; 170 | TestPartResultReporterInterface* original_reporter_; 171 | 172 | GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); 173 | }; 174 | 175 | } // namespace internal 176 | 177 | } // namespace testing 178 | 179 | #endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 180 | -------------------------------------------------------------------------------- /CustomXCTestRunner/CustomXCTestRunner.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomXCTestRunner.h 3 | // CustomXCTestRunner (Objective-C) 4 | // 5 | // Created by Stanislaw Pankevich on 30/03/18. 6 | // Copyright © 2016 Lowlevelbits.org. All rights reserved. 7 | // 8 | 9 | #import "CustomXCTestRunner.h" 10 | 11 | #import 12 | #import 13 | 14 | #import 15 | 16 | static NSString *getTestName(NSString *fullTestName) { 17 | NSString *searchedString = fullTestName; 18 | NSRange searchedRange = NSMakeRange(0, [searchedString length]); 19 | 20 | NSString *pattern = @"^-\\[[A-Za-z0-9_]+ ([A-Za-z0-9_]+)\\]$"; 21 | NSError *error = nil; 22 | 23 | NSRegularExpression* regex = 24 | [NSRegularExpression regularExpressionWithPattern:pattern 25 | options:0 26 | error:&error]; 27 | 28 | NSArray *matches = [regex matchesInString:searchedString 29 | options:0 30 | range:searchedRange]; 31 | 32 | if (matches.count == 0) { 33 | return nil; 34 | } 35 | 36 | for (NSTextCheckingResult* match in matches) { 37 | // NSString *matchText = [searchedString substringWithRange:[match range]]; 38 | NSRange group1 = [match rangeAtIndex:1]; 39 | return [searchedString substringWithRange:group1]; 40 | } 41 | return nil; 42 | } 43 | 44 | @interface CustomXCTestObserver : NSObject 45 | @property (assign, nonatomic) NSUInteger testsFailed; 46 | @end 47 | 48 | @implementation CustomXCTestObserver 49 | 50 | - (instancetype)init { 51 | self = [super init]; 52 | 53 | self.testsFailed = 0; 54 | 55 | return self; 56 | } 57 | 58 | //- (void)testBundleWillStart:(NSBundle *)testBundle { 59 | // NSLog(@"testBundleWillStart: %@", testBundle); 60 | //} 61 | // 62 | //- (void)testBundleDidFinish:(NSBundle *)testBundle { 63 | // NSLog(@"testBundleDidFinish: %@", testBundle); 64 | //} 65 | // 66 | //- (void)testSuiteWillStart:(XCTestSuite *)testSuite { 67 | // NSLog(@"testSuiteWillStart: %@", testSuite); 68 | //} 69 | // 70 | //- (void)testCaseWillStart:(XCTestCase *)testCase { 71 | // NSLog(@"testCaseWillStart: %@", testCase); 72 | //} 73 | // 74 | //- (void)testSuiteDidFinish:(XCTestSuite *)testSuite { 75 | // NSLog(@"testSuiteDidFinish: %@", testSuite); 76 | //} 77 | // 78 | //- (void)testSuite:(XCTestSuite *)testSuite didFailWithDescription:(NSString *)description inFile:(NSString *)filePath atLine:(NSUInteger)lineNumber { 79 | // NSLog(@"testSuite:didFailWithDescription:inFile:atLine: %@ %@ %@ %tu", 80 | // testSuite, description, filePath, lineNumber); 81 | //} 82 | // 83 | - (void)testCase:(XCTestCase *)testCase didFailWithDescription:(NSString *)description inFile:(NSString *)filePath atLine:(NSUInteger)lineNumber { 84 | //NSLog(@"testCase:didFailWithDescription:inFile:atLine: %@ %@ %@ %tu", 85 | // testCase, description, filePath, lineNumber); 86 | self.testsFailed++; 87 | } 88 | 89 | //- (void)testCaseDidFinish:(XCTestCase *)testCase { 90 | // NSLog(@"testCaseWillFinish: %@", testCase); 91 | //} 92 | 93 | @end 94 | 95 | static void ObjCEnumerateRuntimeClasses(void(^callback)(Class)) { 96 | int numClasses; 97 | numClasses = objc_getClassList(NULL, 0); 98 | 99 | if (numClasses == 0) { 100 | return; 101 | } 102 | 103 | Class * classes = (Class *)malloc(sizeof(Class) * numClasses); 104 | numClasses = objc_getClassList(classes, numClasses); 105 | 106 | for (int i = 0; i < numClasses; i++) { 107 | Class runtimeClass = classes[i]; 108 | 109 | callback(runtimeClass); 110 | } 111 | 112 | free(classes); 113 | } 114 | 115 | int CustomXCTestRunnerRunAll(void) { 116 | int exitResult = 0; 117 | 118 | @autoreleasepool { 119 | CustomXCTestObserver *testObserver = [CustomXCTestObserver new]; 120 | Class xcTestCaseClass = NSClassFromString(@"XCTestCase"); 121 | NSCAssert(xcTestCaseClass, nil); 122 | 123 | XCTestSuite *customXCTestRunnerSuite = 124 | [[XCTestSuite alloc] initWithName:@"CustomXCTestRunner Suite"]; 125 | 126 | ObjCEnumerateRuntimeClasses(^(__unsafe_unretained Class runtimeClass) { 127 | if (class_getSuperclass(runtimeClass) != xcTestCaseClass) { 128 | return; 129 | } 130 | 131 | XCTestSuite *suite = [XCTestSuite testSuiteForTestCaseClass:runtimeClass]; 132 | 133 | [customXCTestRunnerSuite addTest:suite]; 134 | }); 135 | 136 | XCTestObservationCenter *center = [XCTestObservationCenter sharedTestObservationCenter]; 137 | [center addTestObserver:testObserver]; 138 | 139 | [customXCTestRunnerSuite runTest]; 140 | 141 | if (testObserver.testsFailed > 0) { 142 | exitResult = 1; 143 | } 144 | } 145 | 146 | return exitResult; 147 | } 148 | 149 | int CustomXCTestRunnerRunOne(const char *const testName) { 150 | int exitResult = 0; 151 | 152 | @autoreleasepool { 153 | CustomXCTestObserver *testObserver = [CustomXCTestObserver new]; 154 | 155 | NSString *testNameString = [NSString stringWithUTF8String:testName]; 156 | NSArray *testPair = [testNameString componentsSeparatedByString:@"."]; 157 | 158 | if (testPair.count != 2) { 159 | return -1; 160 | } 161 | 162 | NSString *classString = testPair[0]; 163 | NSString *testString = testPair[1]; 164 | 165 | XCTestSuite *customXCTestRunnerSuite = 166 | [[XCTestSuite alloc] initWithName:@"CustomXCTestRunner Suite"]; 167 | 168 | XCTestSuite *suite = [XCTestSuite testSuiteForTestCaseWithName:classString]; 169 | XCTest *foundTest = nil; 170 | for (XCTest *test in suite.tests) { 171 | NSString *testName = getTestName(test.name); 172 | 173 | if ([testName isEqualToString:testString]) { 174 | foundTest = test; 175 | } 176 | } 177 | 178 | if (foundTest == nil) { 179 | return -1; 180 | } 181 | 182 | [customXCTestRunnerSuite addTest:foundTest]; 183 | 184 | XCTestObservationCenter *center = [XCTestObservationCenter sharedTestObservationCenter]; 185 | [center addTestObserver:testObserver]; 186 | 187 | [customXCTestRunnerSuite runTest]; 188 | 189 | if (testObserver.testsFailed > 0) { 190 | exitResult = 1; 191 | } 192 | 193 | return exitResult; 194 | } 195 | } 196 | 197 | void CustomXCTestRunnerPrintAllTests(char *output) { 198 | // printf("Running CustomXCTestRunnerPrintAllTests\n"); 199 | Class xcTestCaseClass = NSClassFromString(@"XCTestCase"); 200 | NSCAssert(xcTestCaseClass, nil); 201 | 202 | NSMutableArray *tests = [NSMutableArray new]; 203 | ObjCEnumerateRuntimeClasses(^(__unsafe_unretained Class runtimeClass) { 204 | if (class_getSuperclass(runtimeClass) != xcTestCaseClass) { 205 | return; 206 | } 207 | 208 | XCTestSuite *suite = [XCTestSuite testSuiteForTestCaseClass:runtimeClass]; 209 | 210 | for (XCTest *xcTest in suite.tests) { 211 | NSString *testName = getTestName(xcTest.name); 212 | if (testName == nil) { 213 | continue; 214 | } 215 | 216 | NSString *test = [NSString stringWithFormat:@"%@.%@", xcTest.className, testName]; 217 | 218 | [tests addObject:test]; 219 | } 220 | }); 221 | 222 | NSString *allTestsString = [tests componentsJoinedByString:@","]; 223 | sprintf(output, "%s", allTestsString.UTF8String); 224 | } 225 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/gtest-string.h: -------------------------------------------------------------------------------- 1 | // Copyright 2005, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | // 34 | // This header file declares the String class and functions used internally by 35 | // Google Test. They are subject to change without notice. They should not used 36 | // by code external to Google Test. 37 | // 38 | // This header file is #included by . 39 | // It should not be #included by other files. 40 | 41 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 42 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 43 | 44 | #ifdef __BORLANDC__ 45 | // string.h is not guaranteed to provide strcpy on C++ Builder. 46 | # include 47 | #endif 48 | 49 | #include 50 | #include 51 | 52 | #include "gtest/internal/gtest-port.h" 53 | 54 | namespace testing { 55 | namespace internal { 56 | 57 | // String - an abstract class holding static string utilities. 58 | class GTEST_API_ String { 59 | public: 60 | // Static utility methods 61 | 62 | // Clones a 0-terminated C string, allocating memory using new. The 63 | // caller is responsible for deleting the return value using 64 | // delete[]. Returns the cloned string, or NULL if the input is 65 | // NULL. 66 | // 67 | // This is different from strdup() in string.h, which allocates 68 | // memory using malloc(). 69 | static const char* CloneCString(const char* c_str); 70 | 71 | #if GTEST_OS_WINDOWS_MOBILE 72 | // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be 73 | // able to pass strings to Win32 APIs on CE we need to convert them 74 | // to 'Unicode', UTF-16. 75 | 76 | // Creates a UTF-16 wide string from the given ANSI string, allocating 77 | // memory using new. The caller is responsible for deleting the return 78 | // value using delete[]. Returns the wide string, or NULL if the 79 | // input is NULL. 80 | // 81 | // The wide string is created using the ANSI codepage (CP_ACP) to 82 | // match the behaviour of the ANSI versions of Win32 calls and the 83 | // C runtime. 84 | static LPCWSTR AnsiToUtf16(const char* c_str); 85 | 86 | // Creates an ANSI string from the given wide string, allocating 87 | // memory using new. The caller is responsible for deleting the return 88 | // value using delete[]. Returns the ANSI string, or NULL if the 89 | // input is NULL. 90 | // 91 | // The returned string is created using the ANSI codepage (CP_ACP) to 92 | // match the behaviour of the ANSI versions of Win32 calls and the 93 | // C runtime. 94 | static const char* Utf16ToAnsi(LPCWSTR utf16_str); 95 | #endif 96 | 97 | // Compares two C strings. Returns true iff they have the same content. 98 | // 99 | // Unlike strcmp(), this function can handle NULL argument(s). A 100 | // NULL C string is considered different to any non-NULL C string, 101 | // including the empty string. 102 | static bool CStringEquals(const char* lhs, const char* rhs); 103 | 104 | // Converts a wide C string to a String using the UTF-8 encoding. 105 | // NULL will be converted to "(null)". If an error occurred during 106 | // the conversion, "(failed to convert from wide string)" is 107 | // returned. 108 | static std::string ShowWideCString(const wchar_t* wide_c_str); 109 | 110 | // Compares two wide C strings. Returns true iff they have the same 111 | // content. 112 | // 113 | // Unlike wcscmp(), this function can handle NULL argument(s). A 114 | // NULL C string is considered different to any non-NULL C string, 115 | // including the empty string. 116 | static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); 117 | 118 | // Compares two C strings, ignoring case. Returns true iff they 119 | // have the same content. 120 | // 121 | // Unlike strcasecmp(), this function can handle NULL argument(s). 122 | // A NULL C string is considered different to any non-NULL C string, 123 | // including the empty string. 124 | static bool CaseInsensitiveCStringEquals(const char* lhs, 125 | const char* rhs); 126 | 127 | // Compares two wide C strings, ignoring case. Returns true iff they 128 | // have the same content. 129 | // 130 | // Unlike wcscasecmp(), this function can handle NULL argument(s). 131 | // A NULL C string is considered different to any non-NULL wide C string, 132 | // including the empty string. 133 | // NB: The implementations on different platforms slightly differ. 134 | // On windows, this method uses _wcsicmp which compares according to LC_CTYPE 135 | // environment variable. On GNU platform this method uses wcscasecmp 136 | // which compares according to LC_CTYPE category of the current locale. 137 | // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the 138 | // current locale. 139 | static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, 140 | const wchar_t* rhs); 141 | 142 | // Returns true iff the given string ends with the given suffix, ignoring 143 | // case. Any string is considered to end with an empty suffix. 144 | static bool EndsWithCaseInsensitive( 145 | const std::string& str, const std::string& suffix); 146 | 147 | // Formats an int value as "%02d". 148 | static std::string FormatIntWidth2(int value); // "%02d" for width == 2 149 | 150 | // Formats an int value as "%X". 151 | static std::string FormatHexInt(int value); 152 | 153 | // Formats a byte as "%02X". 154 | static std::string FormatByte(unsigned char value); 155 | 156 | private: 157 | String(); // Not meant to be instantiated. 158 | }; // class String 159 | 160 | // Gets the content of the stringstream's buffer as an std::string. Each '\0' 161 | // character in the buffer is replaced with "\\0". 162 | GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); 163 | 164 | } // namespace internal 165 | } // namespace testing 166 | 167 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 168 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/gtest-linked_ptr.h: -------------------------------------------------------------------------------- 1 | // Copyright 2003 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Authors: Dan Egnor (egnor@google.com) 31 | // 32 | // A "smart" pointer type with reference tracking. Every pointer to a 33 | // particular object is kept on a circular linked list. When the last pointer 34 | // to an object is destroyed or reassigned, the object is deleted. 35 | // 36 | // Used properly, this deletes the object when the last reference goes away. 37 | // There are several caveats: 38 | // - Like all reference counting schemes, cycles lead to leaks. 39 | // - Each smart pointer is actually two pointers (8 bytes instead of 4). 40 | // - Every time a pointer is assigned, the entire list of pointers to that 41 | // object is traversed. This class is therefore NOT SUITABLE when there 42 | // will often be more than two or three pointers to a particular object. 43 | // - References are only tracked as long as linked_ptr<> objects are copied. 44 | // If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS 45 | // will happen (double deletion). 46 | // 47 | // A good use of this class is storing object references in STL containers. 48 | // You can safely put linked_ptr<> in a vector<>. 49 | // Other uses may not be as good. 50 | // 51 | // Note: If you use an incomplete type with linked_ptr<>, the class 52 | // *containing* linked_ptr<> must have a constructor and destructor (even 53 | // if they do nothing!). 54 | // 55 | // Bill Gibbons suggested we use something like this. 56 | // 57 | // Thread Safety: 58 | // Unlike other linked_ptr implementations, in this implementation 59 | // a linked_ptr object is thread-safe in the sense that: 60 | // - it's safe to copy linked_ptr objects concurrently, 61 | // - it's safe to copy *from* a linked_ptr and read its underlying 62 | // raw pointer (e.g. via get()) concurrently, and 63 | // - it's safe to write to two linked_ptrs that point to the same 64 | // shared object concurrently. 65 | // TODO(wan@google.com): rename this to safe_linked_ptr to avoid 66 | // confusion with normal linked_ptr. 67 | 68 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 69 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 70 | 71 | #include 72 | #include 73 | 74 | #include "gtest/internal/gtest-port.h" 75 | 76 | namespace testing { 77 | namespace internal { 78 | 79 | // Protects copying of all linked_ptr objects. 80 | GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); 81 | 82 | // This is used internally by all instances of linked_ptr<>. It needs to be 83 | // a non-template class because different types of linked_ptr<> can refer to 84 | // the same object (linked_ptr(obj) vs linked_ptr(obj)). 85 | // So, it needs to be possible for different types of linked_ptr to participate 86 | // in the same circular linked list, so we need a single class type here. 87 | // 88 | // DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. 89 | class linked_ptr_internal { 90 | public: 91 | // Create a new circle that includes only this instance. 92 | void join_new() { 93 | next_ = this; 94 | } 95 | 96 | // Many linked_ptr operations may change p.link_ for some linked_ptr 97 | // variable p in the same circle as this object. Therefore we need 98 | // to prevent two such operations from occurring concurrently. 99 | // 100 | // Note that different types of linked_ptr objects can coexist in a 101 | // circle (e.g. linked_ptr, linked_ptr, and 102 | // linked_ptr). Therefore we must use a single mutex to 103 | // protect all linked_ptr objects. This can create serious 104 | // contention in production code, but is acceptable in a testing 105 | // framework. 106 | 107 | // Join an existing circle. 108 | void join(linked_ptr_internal const* ptr) 109 | GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { 110 | MutexLock lock(&g_linked_ptr_mutex); 111 | 112 | linked_ptr_internal const* p = ptr; 113 | while (p->next_ != ptr) { 114 | assert(p->next_ != this && 115 | "Trying to join() a linked ring we are already in. " 116 | "Is GMock thread safety enabled?"); 117 | p = p->next_; 118 | } 119 | p->next_ = this; 120 | next_ = ptr; 121 | } 122 | 123 | // Leave whatever circle we're part of. Returns true if we were the 124 | // last member of the circle. Once this is done, you can join() another. 125 | bool depart() 126 | GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { 127 | MutexLock lock(&g_linked_ptr_mutex); 128 | 129 | if (next_ == this) return true; 130 | linked_ptr_internal const* p = next_; 131 | while (p->next_ != this) { 132 | assert(p->next_ != next_ && 133 | "Trying to depart() a linked ring we are not in. " 134 | "Is GMock thread safety enabled?"); 135 | p = p->next_; 136 | } 137 | p->next_ = next_; 138 | return false; 139 | } 140 | 141 | private: 142 | mutable linked_ptr_internal const* next_; 143 | }; 144 | 145 | template 146 | class linked_ptr { 147 | public: 148 | typedef T element_type; 149 | 150 | // Take over ownership of a raw pointer. This should happen as soon as 151 | // possible after the object is created. 152 | explicit linked_ptr(T* ptr = NULL) { capture(ptr); } 153 | ~linked_ptr() { depart(); } 154 | 155 | // Copy an existing linked_ptr<>, adding ourselves to the list of references. 156 | template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } 157 | linked_ptr(linked_ptr const& ptr) { // NOLINT 158 | assert(&ptr != this); 159 | copy(&ptr); 160 | } 161 | 162 | // Assignment releases the old value and acquires the new. 163 | template linked_ptr& operator=(linked_ptr const& ptr) { 164 | depart(); 165 | copy(&ptr); 166 | return *this; 167 | } 168 | 169 | linked_ptr& operator=(linked_ptr const& ptr) { 170 | if (&ptr != this) { 171 | depart(); 172 | copy(&ptr); 173 | } 174 | return *this; 175 | } 176 | 177 | // Smart pointer members. 178 | void reset(T* ptr = NULL) { 179 | depart(); 180 | capture(ptr); 181 | } 182 | T* get() const { return value_; } 183 | T* operator->() const { return value_; } 184 | T& operator*() const { return *value_; } 185 | 186 | bool operator==(T* p) const { return value_ == p; } 187 | bool operator!=(T* p) const { return value_ != p; } 188 | template 189 | bool operator==(linked_ptr const& ptr) const { 190 | return value_ == ptr.get(); 191 | } 192 | template 193 | bool operator!=(linked_ptr const& ptr) const { 194 | return value_ != ptr.get(); 195 | } 196 | 197 | private: 198 | template 199 | friend class linked_ptr; 200 | 201 | T* value_; 202 | linked_ptr_internal link_; 203 | 204 | void depart() { 205 | if (link_.depart()) delete value_; 206 | } 207 | 208 | void capture(T* ptr) { 209 | value_ = ptr; 210 | link_.join_new(); 211 | } 212 | 213 | template void copy(linked_ptr const* ptr) { 214 | value_ = ptr->get(); 215 | if (value_) 216 | link_.join(&ptr->link_); 217 | else 218 | link_.join_new(); 219 | } 220 | }; 221 | 222 | template inline 223 | bool operator==(T* ptr, const linked_ptr& x) { 224 | return ptr == x.get(); 225 | } 226 | 227 | template inline 228 | bool operator!=(T* ptr, const linked_ptr& x) { 229 | return ptr != x.get(); 230 | } 231 | 232 | // A function to convert T* into linked_ptr 233 | // Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation 234 | // for linked_ptr >(new FooBarBaz(arg)) 235 | template 236 | linked_ptr make_linked_ptr(T* ptr) { 237 | return linked_ptr(ptr); 238 | } 239 | 240 | } // namespace internal 241 | } // namespace testing 242 | 243 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 244 | -------------------------------------------------------------------------------- /googletest/include/gtest/gtest-message.h: -------------------------------------------------------------------------------- 1 | // Copyright 2005, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | // 34 | // This header file defines the Message class. 35 | // 36 | // IMPORTANT NOTE: Due to limitation of the C++ language, we have to 37 | // leave some internal implementation details in this header file. 38 | // They are clearly marked by comments like this: 39 | // 40 | // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 41 | // 42 | // Such code is NOT meant to be used by a user directly, and is subject 43 | // to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user 44 | // program! 45 | 46 | #ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 47 | #define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 48 | 49 | #include 50 | 51 | #include "gtest/internal/gtest-port.h" 52 | 53 | // Ensures that there is at least one operator<< in the global namespace. 54 | // See Message& operator<<(...) below for why. 55 | void operator<<(const testing::internal::Secret&, int); 56 | 57 | namespace testing { 58 | 59 | // The Message class works like an ostream repeater. 60 | // 61 | // Typical usage: 62 | // 63 | // 1. You stream a bunch of values to a Message object. 64 | // It will remember the text in a stringstream. 65 | // 2. Then you stream the Message object to an ostream. 66 | // This causes the text in the Message to be streamed 67 | // to the ostream. 68 | // 69 | // For example; 70 | // 71 | // testing::Message foo; 72 | // foo << 1 << " != " << 2; 73 | // std::cout << foo; 74 | // 75 | // will print "1 != 2". 76 | // 77 | // Message is not intended to be inherited from. In particular, its 78 | // destructor is not virtual. 79 | // 80 | // Note that stringstream behaves differently in gcc and in MSVC. You 81 | // can stream a NULL char pointer to it in the former, but not in the 82 | // latter (it causes an access violation if you do). The Message 83 | // class hides this difference by treating a NULL char pointer as 84 | // "(null)". 85 | class GTEST_API_ Message { 86 | private: 87 | // The type of basic IO manipulators (endl, ends, and flush) for 88 | // narrow streams. 89 | typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); 90 | 91 | public: 92 | // Constructs an empty Message. 93 | Message(); 94 | 95 | // Copy constructor. 96 | Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT 97 | *ss_ << msg.GetString(); 98 | } 99 | 100 | // Constructs a Message from a C-string. 101 | explicit Message(const char* str) : ss_(new ::std::stringstream) { 102 | *ss_ << str; 103 | } 104 | 105 | #if GTEST_OS_SYMBIAN 106 | // Streams a value (either a pointer or not) to this object. 107 | template 108 | inline Message& operator <<(const T& value) { 109 | StreamHelper(typename internal::is_pointer::type(), value); 110 | return *this; 111 | } 112 | #else 113 | // Streams a non-pointer value to this object. 114 | template 115 | inline Message& operator <<(const T& val) { 116 | // Some libraries overload << for STL containers. These 117 | // overloads are defined in the global namespace instead of ::std. 118 | // 119 | // C++'s symbol lookup rule (i.e. Koenig lookup) says that these 120 | // overloads are visible in either the std namespace or the global 121 | // namespace, but not other namespaces, including the testing 122 | // namespace which Google Test's Message class is in. 123 | // 124 | // To allow STL containers (and other types that has a << operator 125 | // defined in the global namespace) to be used in Google Test 126 | // assertions, testing::Message must access the custom << operator 127 | // from the global namespace. With this using declaration, 128 | // overloads of << defined in the global namespace and those 129 | // visible via Koenig lookup are both exposed in this function. 130 | using ::operator <<; 131 | *ss_ << val; 132 | return *this; 133 | } 134 | 135 | // Streams a pointer value to this object. 136 | // 137 | // This function is an overload of the previous one. When you 138 | // stream a pointer to a Message, this definition will be used as it 139 | // is more specialized. (The C++ Standard, section 140 | // [temp.func.order].) If you stream a non-pointer, then the 141 | // previous definition will be used. 142 | // 143 | // The reason for this overload is that streaming a NULL pointer to 144 | // ostream is undefined behavior. Depending on the compiler, you 145 | // may get "0", "(nil)", "(null)", or an access violation. To 146 | // ensure consistent result across compilers, we always treat NULL 147 | // as "(null)". 148 | template 149 | inline Message& operator <<(T* const& pointer) { // NOLINT 150 | if (pointer == NULL) { 151 | *ss_ << "(null)"; 152 | } else { 153 | *ss_ << pointer; 154 | } 155 | return *this; 156 | } 157 | #endif // GTEST_OS_SYMBIAN 158 | 159 | // Since the basic IO manipulators are overloaded for both narrow 160 | // and wide streams, we have to provide this specialized definition 161 | // of operator <<, even though its body is the same as the 162 | // templatized version above. Without this definition, streaming 163 | // endl or other basic IO manipulators to Message will confuse the 164 | // compiler. 165 | Message& operator <<(BasicNarrowIoManip val) { 166 | *ss_ << val; 167 | return *this; 168 | } 169 | 170 | // Instead of 1/0, we want to see true/false for bool values. 171 | Message& operator <<(bool b) { 172 | return *this << (b ? "true" : "false"); 173 | } 174 | 175 | // These two overloads allow streaming a wide C string to a Message 176 | // using the UTF-8 encoding. 177 | Message& operator <<(const wchar_t* wide_c_str); 178 | Message& operator <<(wchar_t* wide_c_str); 179 | 180 | #if GTEST_HAS_STD_WSTRING 181 | // Converts the given wide string to a narrow string using the UTF-8 182 | // encoding, and streams the result to this Message object. 183 | Message& operator <<(const ::std::wstring& wstr); 184 | #endif // GTEST_HAS_STD_WSTRING 185 | 186 | #if GTEST_HAS_GLOBAL_WSTRING 187 | // Converts the given wide string to a narrow string using the UTF-8 188 | // encoding, and streams the result to this Message object. 189 | Message& operator <<(const ::wstring& wstr); 190 | #endif // GTEST_HAS_GLOBAL_WSTRING 191 | 192 | // Gets the text streamed to this object so far as an std::string. 193 | // Each '\0' character in the buffer is replaced with "\\0". 194 | // 195 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 196 | std::string GetString() const; 197 | 198 | private: 199 | 200 | #if GTEST_OS_SYMBIAN 201 | // These are needed as the Nokia Symbian Compiler cannot decide between 202 | // const T& and const T* in a function template. The Nokia compiler _can_ 203 | // decide between class template specializations for T and T*, so a 204 | // tr1::type_traits-like is_pointer works, and we can overload on that. 205 | template 206 | inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { 207 | if (pointer == NULL) { 208 | *ss_ << "(null)"; 209 | } else { 210 | *ss_ << pointer; 211 | } 212 | } 213 | template 214 | inline void StreamHelper(internal::false_type /*is_pointer*/, 215 | const T& value) { 216 | // See the comments in Message& operator <<(const T&) above for why 217 | // we need this using statement. 218 | using ::operator <<; 219 | *ss_ << value; 220 | } 221 | #endif // GTEST_OS_SYMBIAN 222 | 223 | // We'll hold the text streamed to this object here. 224 | const internal::scoped_ptr< ::std::stringstream> ss_; 225 | 226 | // We declare (but don't implement) this to prevent the compiler 227 | // from implementing the assignment operator. 228 | void operator=(const Message&); 229 | }; 230 | 231 | // Streams a Message to an ostream. 232 | inline std::ostream& operator <<(std::ostream& os, const Message& sb) { 233 | return os << sb.GetString(); 234 | } 235 | 236 | namespace internal { 237 | 238 | // Converts a streamable value to an std::string. A NULL pointer is 239 | // converted to "(null)". When the input value is a ::string, 240 | // ::std::string, ::wstring, or ::std::wstring object, each NUL 241 | // character in it is replaced with "\\0". 242 | template 243 | std::string StreamableToString(const T& streamable) { 244 | return (Message() << streamable).GetString(); 245 | } 246 | 247 | } // namespace internal 248 | } // namespace testing 249 | 250 | #endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 251 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/gtest-filepath.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: keith.ray@gmail.com (Keith Ray) 31 | // 32 | // Google Test filepath utilities 33 | // 34 | // This header file declares classes and functions used internally by 35 | // Google Test. They are subject to change without notice. 36 | // 37 | // This file is #included in . 38 | // Do not include this header file separately! 39 | 40 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 41 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 42 | 43 | #include "gtest/internal/gtest-string.h" 44 | 45 | namespace testing { 46 | namespace internal { 47 | 48 | // FilePath - a class for file and directory pathname manipulation which 49 | // handles platform-specific conventions (like the pathname separator). 50 | // Used for helper functions for naming files in a directory for xml output. 51 | // Except for Set methods, all methods are const or static, which provides an 52 | // "immutable value object" -- useful for peace of mind. 53 | // A FilePath with a value ending in a path separator ("like/this/") represents 54 | // a directory, otherwise it is assumed to represent a file. In either case, 55 | // it may or may not represent an actual file or directory in the file system. 56 | // Names are NOT checked for syntax correctness -- no checking for illegal 57 | // characters, malformed paths, etc. 58 | 59 | class GTEST_API_ FilePath { 60 | public: 61 | FilePath() : pathname_("") { } 62 | FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } 63 | 64 | explicit FilePath(const std::string& pathname) : pathname_(pathname) { 65 | Normalize(); 66 | } 67 | 68 | FilePath& operator=(const FilePath& rhs) { 69 | Set(rhs); 70 | return *this; 71 | } 72 | 73 | void Set(const FilePath& rhs) { 74 | pathname_ = rhs.pathname_; 75 | } 76 | 77 | const std::string& string() const { return pathname_; } 78 | const char* c_str() const { return pathname_.c_str(); } 79 | 80 | // Returns the current working directory, or "" if unsuccessful. 81 | static FilePath GetCurrentDir(); 82 | 83 | // Given directory = "dir", base_name = "test", number = 0, 84 | // extension = "xml", returns "dir/test.xml". If number is greater 85 | // than zero (e.g., 12), returns "dir/test_12.xml". 86 | // On Windows platform, uses \ as the separator rather than /. 87 | static FilePath MakeFileName(const FilePath& directory, 88 | const FilePath& base_name, 89 | int number, 90 | const char* extension); 91 | 92 | // Given directory = "dir", relative_path = "test.xml", 93 | // returns "dir/test.xml". 94 | // On Windows, uses \ as the separator rather than /. 95 | static FilePath ConcatPaths(const FilePath& directory, 96 | const FilePath& relative_path); 97 | 98 | // Returns a pathname for a file that does not currently exist. The pathname 99 | // will be directory/base_name.extension or 100 | // directory/base_name_.extension if directory/base_name.extension 101 | // already exists. The number will be incremented until a pathname is found 102 | // that does not already exist. 103 | // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 104 | // There could be a race condition if two or more processes are calling this 105 | // function at the same time -- they could both pick the same filename. 106 | static FilePath GenerateUniqueFileName(const FilePath& directory, 107 | const FilePath& base_name, 108 | const char* extension); 109 | 110 | // Returns true iff the path is "". 111 | bool IsEmpty() const { return pathname_.empty(); } 112 | 113 | // If input name has a trailing separator character, removes it and returns 114 | // the name, otherwise return the name string unmodified. 115 | // On Windows platform, uses \ as the separator, other platforms use /. 116 | FilePath RemoveTrailingPathSeparator() const; 117 | 118 | // Returns a copy of the FilePath with the directory part removed. 119 | // Example: FilePath("path/to/file").RemoveDirectoryName() returns 120 | // FilePath("file"). If there is no directory part ("just_a_file"), it returns 121 | // the FilePath unmodified. If there is no file part ("just_a_dir/") it 122 | // returns an empty FilePath (""). 123 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 124 | FilePath RemoveDirectoryName() const; 125 | 126 | // RemoveFileName returns the directory path with the filename removed. 127 | // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 128 | // If the FilePath is "a_file" or "/a_file", RemoveFileName returns 129 | // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 130 | // not have a file, like "just/a/dir/", it returns the FilePath unmodified. 131 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 132 | FilePath RemoveFileName() const; 133 | 134 | // Returns a copy of the FilePath with the case-insensitive extension removed. 135 | // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 136 | // FilePath("dir/file"). If a case-insensitive extension is not 137 | // found, returns a copy of the original FilePath. 138 | FilePath RemoveExtension(const char* extension) const; 139 | 140 | // Creates directories so that path exists. Returns true if successful or if 141 | // the directories already exist; returns false if unable to create 142 | // directories for any reason. Will also return false if the FilePath does 143 | // not represent a directory (that is, it doesn't end with a path separator). 144 | bool CreateDirectoriesRecursively() const; 145 | 146 | // Create the directory so that path exists. Returns true if successful or 147 | // if the directory already exists; returns false if unable to create the 148 | // directory for any reason, including if the parent directory does not 149 | // exist. Not named "CreateDirectory" because that's a macro on Windows. 150 | bool CreateFolder() const; 151 | 152 | // Returns true if FilePath describes something in the file-system, 153 | // either a file, directory, or whatever, and that something exists. 154 | bool FileOrDirectoryExists() const; 155 | 156 | // Returns true if pathname describes a directory in the file-system 157 | // that exists. 158 | bool DirectoryExists() const; 159 | 160 | // Returns true if FilePath ends with a path separator, which indicates that 161 | // it is intended to represent a directory. Returns false otherwise. 162 | // This does NOT check that a directory (or file) actually exists. 163 | bool IsDirectory() const; 164 | 165 | // Returns true if pathname describes a root directory. (Windows has one 166 | // root directory per disk drive.) 167 | bool IsRootDirectory() const; 168 | 169 | // Returns true if pathname describes an absolute path. 170 | bool IsAbsolutePath() const; 171 | 172 | private: 173 | // Replaces multiple consecutive separators with a single separator. 174 | // For example, "bar///foo" becomes "bar/foo". Does not eliminate other 175 | // redundancies that might be in a pathname involving "." or "..". 176 | // 177 | // A pathname with multiple consecutive separators may occur either through 178 | // user error or as a result of some scripts or APIs that generate a pathname 179 | // with a trailing separator. On other platforms the same API or script 180 | // may NOT generate a pathname with a trailing "/". Then elsewhere that 181 | // pathname may have another "/" and pathname components added to it, 182 | // without checking for the separator already being there. 183 | // The script language and operating system may allow paths like "foo//bar" 184 | // but some of the functions in FilePath will not handle that correctly. In 185 | // particular, RemoveTrailingPathSeparator() only removes one separator, and 186 | // it is called in CreateDirectoriesRecursively() assuming that it will change 187 | // a pathname from directory syntax (trailing separator) to filename syntax. 188 | // 189 | // On Windows this method also replaces the alternate path separator '/' with 190 | // the primary path separator '\\', so that for example "bar\\/\\foo" becomes 191 | // "bar\\foo". 192 | 193 | void Normalize(); 194 | 195 | // Returns a pointer to the last occurence of a valid path separator in 196 | // the FilePath. On Windows, for example, both '/' and '\' are valid path 197 | // separators. Returns NULL if no path separator was found. 198 | const char* FindLastPathSeparator() const; 199 | 200 | std::string pathname_; 201 | }; // class FilePath 202 | 203 | } // namespace internal 204 | } // namespace testing 205 | 206 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 207 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/gtest-param-util-generated.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $var n = 50 $$ Maximum length of Values arguments we want to support. 3 | $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support. 4 | // Copyright 2008 Google Inc. 5 | // All Rights Reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are 9 | // met: 10 | // 11 | // * Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // * Redistributions in binary form must reproduce the above 14 | // copyright notice, this list of conditions and the following disclaimer 15 | // in the documentation and/or other materials provided with the 16 | // distribution. 17 | // * Neither the name of Google Inc. nor the names of its 18 | // contributors may be used to endorse or promote products derived from 19 | // this software without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | // Author: vladl@google.com (Vlad Losev) 34 | 35 | // Type and function utilities for implementing parameterized tests. 36 | // This file is generated by a SCRIPT. DO NOT EDIT BY HAND! 37 | // 38 | // Currently Google Test supports at most $n arguments in Values, 39 | // and at most $maxtuple arguments in Combine. Please contact 40 | // googletestframework@googlegroups.com if you need more. 41 | // Please note that the number of arguments to Combine is limited 42 | // by the maximum arity of the implementation of tuple which is 43 | // currently set at $maxtuple. 44 | 45 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 46 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 47 | 48 | // scripts/fuse_gtest.py depends on gtest's own header being #included 49 | // *unconditionally*. Therefore these #includes cannot be moved 50 | // inside #if GTEST_HAS_PARAM_TEST. 51 | #include "gtest/internal/gtest-param-util.h" 52 | #include "gtest/internal/gtest-port.h" 53 | 54 | #if GTEST_HAS_PARAM_TEST 55 | 56 | namespace testing { 57 | 58 | // Forward declarations of ValuesIn(), which is implemented in 59 | // include/gtest/gtest-param-test.h. 60 | template 61 | internal::ParamGenerator< 62 | typename ::testing::internal::IteratorTraits::value_type> 63 | ValuesIn(ForwardIterator begin, ForwardIterator end); 64 | 65 | template 66 | internal::ParamGenerator ValuesIn(const T (&array)[N]); 67 | 68 | template 69 | internal::ParamGenerator ValuesIn( 70 | const Container& container); 71 | 72 | namespace internal { 73 | 74 | // Used in the Values() function to provide polymorphic capabilities. 75 | $range i 1..n 76 | $for i [[ 77 | $range j 1..i 78 | 79 | template <$for j, [[typename T$j]]> 80 | class ValueArray$i { 81 | public: 82 | $if i==1 [[explicit ]]ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {} 83 | 84 | template 85 | operator ParamGenerator() const { 86 | const T array[] = {$for j, [[static_cast(v$(j)_)]]}; 87 | return ValuesIn(array); 88 | } 89 | 90 | private: 91 | // No implementation - assignment is unsupported. 92 | void operator=(const ValueArray$i& other); 93 | 94 | $for j [[ 95 | 96 | const T$j v$(j)_; 97 | ]] 98 | 99 | }; 100 | 101 | ]] 102 | 103 | # if GTEST_HAS_COMBINE 104 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 105 | // 106 | // Generates values from the Cartesian product of values produced 107 | // by the argument generators. 108 | // 109 | $range i 2..maxtuple 110 | $for i [[ 111 | $range j 1..i 112 | $range k 2..i 113 | 114 | template <$for j, [[typename T$j]]> 115 | class CartesianProductGenerator$i 116 | : public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > { 117 | public: 118 | typedef ::testing::tuple<$for j, [[T$j]]> ParamType; 119 | 120 | CartesianProductGenerator$i($for j, [[const ParamGenerator& g$j]]) 121 | : $for j, [[g$(j)_(g$j)]] {} 122 | virtual ~CartesianProductGenerator$i() {} 123 | 124 | virtual ParamIteratorInterface* Begin() const { 125 | return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]); 126 | } 127 | virtual ParamIteratorInterface* End() const { 128 | return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]); 129 | } 130 | 131 | private: 132 | class Iterator : public ParamIteratorInterface { 133 | public: 134 | Iterator(const ParamGeneratorInterface* base, $for j, [[ 135 | 136 | const ParamGenerator& g$j, 137 | const typename ParamGenerator::iterator& current$(j)]]) 138 | : base_(base), 139 | $for j, [[ 140 | 141 | begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j) 142 | ]] { 143 | ComputeCurrentValue(); 144 | } 145 | virtual ~Iterator() {} 146 | 147 | virtual const ParamGeneratorInterface* BaseGenerator() const { 148 | return base_; 149 | } 150 | // Advance should not be called on beyond-of-range iterators 151 | // so no component iterators must be beyond end of range, either. 152 | virtual void Advance() { 153 | assert(!AtEnd()); 154 | ++current$(i)_; 155 | 156 | $for k [[ 157 | if (current$(i+2-k)_ == end$(i+2-k)_) { 158 | current$(i+2-k)_ = begin$(i+2-k)_; 159 | ++current$(i+2-k-1)_; 160 | } 161 | 162 | ]] 163 | ComputeCurrentValue(); 164 | } 165 | virtual ParamIteratorInterface* Clone() const { 166 | return new Iterator(*this); 167 | } 168 | virtual const ParamType* Current() const { return ¤t_value_; } 169 | virtual bool Equals(const ParamIteratorInterface& other) const { 170 | // Having the same base generator guarantees that the other 171 | // iterator is of the same type and we can downcast. 172 | GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) 173 | << "The program attempted to compare iterators " 174 | << "from different generators." << std::endl; 175 | const Iterator* typed_other = 176 | CheckedDowncastToActualType(&other); 177 | // We must report iterators equal if they both point beyond their 178 | // respective ranges. That can happen in a variety of fashions, 179 | // so we have to consult AtEnd(). 180 | return (AtEnd() && typed_other->AtEnd()) || 181 | ($for j && [[ 182 | 183 | current$(j)_ == typed_other->current$(j)_ 184 | ]]); 185 | } 186 | 187 | private: 188 | Iterator(const Iterator& other) 189 | : base_(other.base_), $for j, [[ 190 | 191 | begin$(j)_(other.begin$(j)_), 192 | end$(j)_(other.end$(j)_), 193 | current$(j)_(other.current$(j)_) 194 | ]] { 195 | ComputeCurrentValue(); 196 | } 197 | 198 | void ComputeCurrentValue() { 199 | if (!AtEnd()) 200 | current_value_ = ParamType($for j, [[*current$(j)_]]); 201 | } 202 | bool AtEnd() const { 203 | // We must report iterator past the end of the range when either of the 204 | // component iterators has reached the end of its range. 205 | return 206 | $for j || [[ 207 | 208 | current$(j)_ == end$(j)_ 209 | ]]; 210 | } 211 | 212 | // No implementation - assignment is unsupported. 213 | void operator=(const Iterator& other); 214 | 215 | const ParamGeneratorInterface* const base_; 216 | // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. 217 | // current[i]_ is the actual traversing iterator. 218 | $for j [[ 219 | 220 | const typename ParamGenerator::iterator begin$(j)_; 221 | const typename ParamGenerator::iterator end$(j)_; 222 | typename ParamGenerator::iterator current$(j)_; 223 | ]] 224 | 225 | ParamType current_value_; 226 | }; // class CartesianProductGenerator$i::Iterator 227 | 228 | // No implementation - assignment is unsupported. 229 | void operator=(const CartesianProductGenerator$i& other); 230 | 231 | 232 | $for j [[ 233 | const ParamGenerator g$(j)_; 234 | 235 | ]] 236 | }; // class CartesianProductGenerator$i 237 | 238 | 239 | ]] 240 | 241 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 242 | // 243 | // Helper classes providing Combine() with polymorphic features. They allow 244 | // casting CartesianProductGeneratorN to ParamGenerator if T is 245 | // convertible to U. 246 | // 247 | $range i 2..maxtuple 248 | $for i [[ 249 | $range j 1..i 250 | 251 | template <$for j, [[class Generator$j]]> 252 | class CartesianProductHolder$i { 253 | public: 254 | CartesianProductHolder$i($for j, [[const Generator$j& g$j]]) 255 | : $for j, [[g$(j)_(g$j)]] {} 256 | template <$for j, [[typename T$j]]> 257 | operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const { 258 | return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >( 259 | new CartesianProductGenerator$i<$for j, [[T$j]]>( 260 | $for j,[[ 261 | 262 | static_cast >(g$(j)_) 263 | ]])); 264 | } 265 | 266 | private: 267 | // No implementation - assignment is unsupported. 268 | void operator=(const CartesianProductHolder$i& other); 269 | 270 | 271 | $for j [[ 272 | const Generator$j g$(j)_; 273 | 274 | ]] 275 | }; // class CartesianProductHolder$i 276 | 277 | ]] 278 | 279 | # endif // GTEST_HAS_COMBINE 280 | 281 | } // namespace internal 282 | } // namespace testing 283 | 284 | #endif // GTEST_HAS_PARAM_TEST 285 | 286 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 287 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/gtest-type-util.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $var n = 50 $$ Maximum length of type lists we want to support. 3 | // Copyright 2008 Google Inc. 4 | // All Rights Reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are 8 | // met: 9 | // 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above 13 | // copyright notice, this list of conditions and the following disclaimer 14 | // in the documentation and/or other materials provided with the 15 | // distribution. 16 | // * Neither the name of Google Inc. nor the names of its 17 | // contributors may be used to endorse or promote products derived from 18 | // this software without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | // 32 | // Author: wan@google.com (Zhanyong Wan) 33 | 34 | // Type utilities needed for implementing typed and type-parameterized 35 | // tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! 36 | // 37 | // Currently we support at most $n types in a list, and at most $n 38 | // type-parameterized tests in one type-parameterized test case. 39 | // Please contact googletestframework@googlegroups.com if you need 40 | // more. 41 | 42 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 43 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 44 | 45 | #include "gtest/internal/gtest-port.h" 46 | 47 | // #ifdef __GNUC__ is too general here. It is possible to use gcc without using 48 | // libstdc++ (which is where cxxabi.h comes from). 49 | # if GTEST_HAS_CXXABI_H_ 50 | # include 51 | # elif defined(__HP_aCC) 52 | # include 53 | # endif // GTEST_HASH_CXXABI_H_ 54 | 55 | namespace testing { 56 | namespace internal { 57 | 58 | // GetTypeName() returns a human-readable name of type T. 59 | // NB: This function is also used in Google Mock, so don't move it inside of 60 | // the typed-test-only section below. 61 | template 62 | std::string GetTypeName() { 63 | # if GTEST_HAS_RTTI 64 | 65 | const char* const name = typeid(T).name(); 66 | # if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) 67 | int status = 0; 68 | // gcc's implementation of typeid(T).name() mangles the type name, 69 | // so we have to demangle it. 70 | # if GTEST_HAS_CXXABI_H_ 71 | using abi::__cxa_demangle; 72 | # endif // GTEST_HAS_CXXABI_H_ 73 | char* const readable_name = __cxa_demangle(name, 0, 0, &status); 74 | const std::string name_str(status == 0 ? readable_name : name); 75 | free(readable_name); 76 | return name_str; 77 | # else 78 | return name; 79 | # endif // GTEST_HAS_CXXABI_H_ || __HP_aCC 80 | 81 | # else 82 | 83 | return ""; 84 | 85 | # endif // GTEST_HAS_RTTI 86 | } 87 | 88 | #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P 89 | 90 | // AssertyTypeEq::type is defined iff T1 and T2 are the same 91 | // type. This can be used as a compile-time assertion to ensure that 92 | // two types are equal. 93 | 94 | template 95 | struct AssertTypeEq; 96 | 97 | template 98 | struct AssertTypeEq { 99 | typedef bool type; 100 | }; 101 | 102 | // A unique type used as the default value for the arguments of class 103 | // template Types. This allows us to simulate variadic templates 104 | // (e.g. Types, Type, and etc), which C++ doesn't 105 | // support directly. 106 | struct None {}; 107 | 108 | // The following family of struct and struct templates are used to 109 | // represent type lists. In particular, TypesN 110 | // represents a type list with N types (T1, T2, ..., and TN) in it. 111 | // Except for Types0, every struct in the family has two member types: 112 | // Head for the first type in the list, and Tail for the rest of the 113 | // list. 114 | 115 | // The empty type list. 116 | struct Types0 {}; 117 | 118 | // Type lists of length 1, 2, 3, and so on. 119 | 120 | template 121 | struct Types1 { 122 | typedef T1 Head; 123 | typedef Types0 Tail; 124 | }; 125 | 126 | $range i 2..n 127 | 128 | $for i [[ 129 | $range j 1..i 130 | $range k 2..i 131 | template <$for j, [[typename T$j]]> 132 | struct Types$i { 133 | typedef T1 Head; 134 | typedef Types$(i-1)<$for k, [[T$k]]> Tail; 135 | }; 136 | 137 | 138 | ]] 139 | 140 | } // namespace internal 141 | 142 | // We don't want to require the users to write TypesN<...> directly, 143 | // as that would require them to count the length. Types<...> is much 144 | // easier to write, but generates horrible messages when there is a 145 | // compiler error, as gcc insists on printing out each template 146 | // argument, even if it has the default value (this means Types 147 | // will appear as Types in the compiler 148 | // errors). 149 | // 150 | // Our solution is to combine the best part of the two approaches: a 151 | // user would write Types, and Google Test will translate 152 | // that to TypesN internally to make error messages 153 | // readable. The translation is done by the 'type' member of the 154 | // Types template. 155 | 156 | $range i 1..n 157 | template <$for i, [[typename T$i = internal::None]]> 158 | struct Types { 159 | typedef internal::Types$n<$for i, [[T$i]]> type; 160 | }; 161 | 162 | template <> 163 | struct Types<$for i, [[internal::None]]> { 164 | typedef internal::Types0 type; 165 | }; 166 | 167 | $range i 1..n-1 168 | $for i [[ 169 | $range j 1..i 170 | $range k i+1..n 171 | template <$for j, [[typename T$j]]> 172 | struct Types<$for j, [[T$j]]$for k[[, internal::None]]> { 173 | typedef internal::Types$i<$for j, [[T$j]]> type; 174 | }; 175 | 176 | ]] 177 | 178 | namespace internal { 179 | 180 | # define GTEST_TEMPLATE_ template class 181 | 182 | // The template "selector" struct TemplateSel is used to 183 | // represent Tmpl, which must be a class template with one type 184 | // parameter, as a type. TemplateSel::Bind::type is defined 185 | // as the type Tmpl. This allows us to actually instantiate the 186 | // template "selected" by TemplateSel. 187 | // 188 | // This trick is necessary for simulating typedef for class templates, 189 | // which C++ doesn't support directly. 190 | template 191 | struct TemplateSel { 192 | template 193 | struct Bind { 194 | typedef Tmpl type; 195 | }; 196 | }; 197 | 198 | # define GTEST_BIND_(TmplSel, T) \ 199 | TmplSel::template Bind::type 200 | 201 | // A unique struct template used as the default value for the 202 | // arguments of class template Templates. This allows us to simulate 203 | // variadic templates (e.g. Templates, Templates, 204 | // and etc), which C++ doesn't support directly. 205 | template 206 | struct NoneT {}; 207 | 208 | // The following family of struct and struct templates are used to 209 | // represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except 211 | // for Templates0, every struct in the family has two member types: 212 | // Head for the selector of the first template in the list, and Tail 213 | // for the rest of the list. 214 | 215 | // The empty template list. 216 | struct Templates0 {}; 217 | 218 | // Template lists of length 1, 2, 3, and so on. 219 | 220 | template 221 | struct Templates1 { 222 | typedef TemplateSel Head; 223 | typedef Templates0 Tail; 224 | }; 225 | 226 | $range i 2..n 227 | 228 | $for i [[ 229 | $range j 1..i 230 | $range k 2..i 231 | template <$for j, [[GTEST_TEMPLATE_ T$j]]> 232 | struct Templates$i { 233 | typedef TemplateSel Head; 234 | typedef Templates$(i-1)<$for k, [[T$k]]> Tail; 235 | }; 236 | 237 | 238 | ]] 239 | 240 | // We don't want to require the users to write TemplatesN<...> directly, 241 | // as that would require them to count the length. Templates<...> is much 242 | // easier to write, but generates horrible messages when there is a 243 | // compiler error, as gcc insists on printing out each template 244 | // argument, even if it has the default value (this means Templates 245 | // will appear as Templates in the compiler 246 | // errors). 247 | // 248 | // Our solution is to combine the best part of the two approaches: a 249 | // user would write Templates, and Google Test will translate 250 | // that to TemplatesN internally to make error messages 251 | // readable. The translation is done by the 'type' member of the 252 | // Templates template. 253 | 254 | $range i 1..n 255 | template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]> 256 | struct Templates { 257 | typedef Templates$n<$for i, [[T$i]]> type; 258 | }; 259 | 260 | template <> 261 | struct Templates<$for i, [[NoneT]]> { 262 | typedef Templates0 type; 263 | }; 264 | 265 | $range i 1..n-1 266 | $for i [[ 267 | $range j 1..i 268 | $range k i+1..n 269 | template <$for j, [[GTEST_TEMPLATE_ T$j]]> 270 | struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> { 271 | typedef Templates$i<$for j, [[T$j]]> type; 272 | }; 273 | 274 | ]] 275 | 276 | // The TypeList template makes it possible to use either a single type 277 | // or a Types<...> list in TYPED_TEST_CASE() and 278 | // INSTANTIATE_TYPED_TEST_CASE_P(). 279 | 280 | template 281 | struct TypeList { 282 | typedef Types1 type; 283 | }; 284 | 285 | 286 | $range i 1..n 287 | template <$for i, [[typename T$i]]> 288 | struct TypeList > { 289 | typedef typename Types<$for i, [[T$i]]>::type type; 290 | }; 291 | 292 | #endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P 293 | 294 | } // namespace internal 295 | } // namespace testing 296 | 297 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 298 | -------------------------------------------------------------------------------- /googletest/include/gtest/gtest-spi.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Utilities for testing Google Test itself and code that uses Google Test 33 | // (e.g. frameworks built on top of Google Test). 34 | 35 | #ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 36 | #define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 37 | 38 | #include "gtest/gtest.h" 39 | 40 | namespace testing { 41 | 42 | // This helper class can be used to mock out Google Test failure reporting 43 | // so that we can test Google Test or code that builds on Google Test. 44 | // 45 | // An object of this class appends a TestPartResult object to the 46 | // TestPartResultArray object given in the constructor whenever a Google Test 47 | // failure is reported. It can either intercept only failures that are 48 | // generated in the same thread that created this object or it can intercept 49 | // all generated failures. The scope of this mock object can be controlled with 50 | // the second argument to the two arguments constructor. 51 | class GTEST_API_ ScopedFakeTestPartResultReporter 52 | : public TestPartResultReporterInterface { 53 | public: 54 | // The two possible mocking modes of this object. 55 | enum InterceptMode { 56 | INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. 57 | INTERCEPT_ALL_THREADS // Intercepts all failures. 58 | }; 59 | 60 | // The c'tor sets this object as the test part result reporter used 61 | // by Google Test. The 'result' parameter specifies where to report the 62 | // results. This reporter will only catch failures generated in the current 63 | // thread. DEPRECATED 64 | explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); 65 | 66 | // Same as above, but you can choose the interception scope of this object. 67 | ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, 68 | TestPartResultArray* result); 69 | 70 | // The d'tor restores the previous test part result reporter. 71 | virtual ~ScopedFakeTestPartResultReporter(); 72 | 73 | // Appends the TestPartResult object to the TestPartResultArray 74 | // received in the constructor. 75 | // 76 | // This method is from the TestPartResultReporterInterface 77 | // interface. 78 | virtual void ReportTestPartResult(const TestPartResult& result); 79 | private: 80 | void Init(); 81 | 82 | const InterceptMode intercept_mode_; 83 | TestPartResultReporterInterface* old_reporter_; 84 | TestPartResultArray* const result_; 85 | 86 | GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); 87 | }; 88 | 89 | namespace internal { 90 | 91 | // A helper class for implementing EXPECT_FATAL_FAILURE() and 92 | // EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given 93 | // TestPartResultArray contains exactly one failure that has the given 94 | // type and contains the given substring. If that's not the case, a 95 | // non-fatal failure will be generated. 96 | class GTEST_API_ SingleFailureChecker { 97 | public: 98 | // The constructor remembers the arguments. 99 | SingleFailureChecker(const TestPartResultArray* results, 100 | TestPartResult::Type type, 101 | const string& substr); 102 | ~SingleFailureChecker(); 103 | private: 104 | const TestPartResultArray* const results_; 105 | const TestPartResult::Type type_; 106 | const string substr_; 107 | 108 | GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); 109 | }; 110 | 111 | } // namespace internal 112 | 113 | } // namespace testing 114 | 115 | // A set of macros for testing Google Test assertions or code that's expected 116 | // to generate Google Test fatal failures. It verifies that the given 117 | // statement will cause exactly one fatal Google Test failure with 'substr' 118 | // being part of the failure message. 119 | // 120 | // There are two different versions of this macro. EXPECT_FATAL_FAILURE only 121 | // affects and considers failures generated in the current thread and 122 | // EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. 123 | // 124 | // The verification of the assertion is done correctly even when the statement 125 | // throws an exception or aborts the current function. 126 | // 127 | // Known restrictions: 128 | // - 'statement' cannot reference local non-static variables or 129 | // non-static members of the current object. 130 | // - 'statement' cannot return a value. 131 | // - You cannot stream a failure message to this macro. 132 | // 133 | // Note that even though the implementations of the following two 134 | // macros are much alike, we cannot refactor them to use a common 135 | // helper macro, due to some peculiarity in how the preprocessor 136 | // works. The AcceptsMacroThatExpandsToUnprotectedComma test in 137 | // gtest_unittest.cc will fail to compile if we do that. 138 | #define EXPECT_FATAL_FAILURE(statement, substr) \ 139 | do { \ 140 | class GTestExpectFatalFailureHelper {\ 141 | public:\ 142 | static void Execute() { statement; }\ 143 | };\ 144 | ::testing::TestPartResultArray gtest_failures;\ 145 | ::testing::internal::SingleFailureChecker gtest_checker(\ 146 | >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ 147 | {\ 148 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 149 | ::testing::ScopedFakeTestPartResultReporter:: \ 150 | INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ 151 | GTestExpectFatalFailureHelper::Execute();\ 152 | }\ 153 | } while (::testing::internal::AlwaysFalse()) 154 | 155 | #define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ 156 | do { \ 157 | class GTestExpectFatalFailureHelper {\ 158 | public:\ 159 | static void Execute() { statement; }\ 160 | };\ 161 | ::testing::TestPartResultArray gtest_failures;\ 162 | ::testing::internal::SingleFailureChecker gtest_checker(\ 163 | >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ 164 | {\ 165 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 166 | ::testing::ScopedFakeTestPartResultReporter:: \ 167 | INTERCEPT_ALL_THREADS, >est_failures);\ 168 | GTestExpectFatalFailureHelper::Execute();\ 169 | }\ 170 | } while (::testing::internal::AlwaysFalse()) 171 | 172 | // A macro for testing Google Test assertions or code that's expected to 173 | // generate Google Test non-fatal failures. It asserts that the given 174 | // statement will cause exactly one non-fatal Google Test failure with 'substr' 175 | // being part of the failure message. 176 | // 177 | // There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only 178 | // affects and considers failures generated in the current thread and 179 | // EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. 180 | // 181 | // 'statement' is allowed to reference local variables and members of 182 | // the current object. 183 | // 184 | // The verification of the assertion is done correctly even when the statement 185 | // throws an exception or aborts the current function. 186 | // 187 | // Known restrictions: 188 | // - You cannot stream a failure message to this macro. 189 | // 190 | // Note that even though the implementations of the following two 191 | // macros are much alike, we cannot refactor them to use a common 192 | // helper macro, due to some peculiarity in how the preprocessor 193 | // works. If we do that, the code won't compile when the user gives 194 | // EXPECT_NONFATAL_FAILURE() a statement that contains a macro that 195 | // expands to code containing an unprotected comma. The 196 | // AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc 197 | // catches that. 198 | // 199 | // For the same reason, we have to write 200 | // if (::testing::internal::AlwaysTrue()) { statement; } 201 | // instead of 202 | // GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) 203 | // to avoid an MSVC warning on unreachable code. 204 | #define EXPECT_NONFATAL_FAILURE(statement, substr) \ 205 | do {\ 206 | ::testing::TestPartResultArray gtest_failures;\ 207 | ::testing::internal::SingleFailureChecker gtest_checker(\ 208 | >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ 209 | (substr));\ 210 | {\ 211 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 212 | ::testing::ScopedFakeTestPartResultReporter:: \ 213 | INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ 214 | if (::testing::internal::AlwaysTrue()) { statement; }\ 215 | }\ 216 | } while (::testing::internal::AlwaysFalse()) 217 | 218 | #define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ 219 | do {\ 220 | ::testing::TestPartResultArray gtest_failures;\ 221 | ::testing::internal::SingleFailureChecker gtest_checker(\ 222 | >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ 223 | (substr));\ 224 | {\ 225 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 226 | ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ 227 | >est_failures);\ 228 | if (::testing::internal::AlwaysTrue()) { statement; }\ 229 | }\ 230 | } while (::testing::internal::AlwaysFalse()) 231 | 232 | #endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 233 | -------------------------------------------------------------------------------- /googletest/include/gtest/internal/gtest-tuple.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $var n = 10 $$ Maximum number of tuple fields we want to support. 3 | $$ This meta comment fixes auto-indentation in Emacs. }} 4 | // Copyright 2009 Google Inc. 5 | // All Rights Reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are 9 | // met: 10 | // 11 | // * Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // * Redistributions in binary form must reproduce the above 14 | // copyright notice, this list of conditions and the following disclaimer 15 | // in the documentation and/or other materials provided with the 16 | // distribution. 17 | // * Neither the name of Google Inc. nor the names of its 18 | // contributors may be used to endorse or promote products derived from 19 | // this software without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | // Author: wan@google.com (Zhanyong Wan) 34 | 35 | // Implements a subset of TR1 tuple needed by Google Test and Google Mock. 36 | 37 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ 38 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ 39 | 40 | #include // For ::std::pair. 41 | 42 | // The compiler used in Symbian has a bug that prevents us from declaring the 43 | // tuple template as a friend (it complains that tuple is redefined). This 44 | // hack bypasses the bug by declaring the members that should otherwise be 45 | // private as public. 46 | // Sun Studio versions < 12 also have the above bug. 47 | #if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) 48 | # define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: 49 | #else 50 | # define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ 51 | template friend class tuple; \ 52 | private: 53 | #endif 54 | 55 | // Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict 56 | // with our own definitions. Therefore using our own tuple does not work on 57 | // those compilers. 58 | #if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */ 59 | # error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \ 60 | GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers." 61 | #endif 62 | 63 | 64 | $range i 0..n-1 65 | $range j 0..n 66 | $range k 1..n 67 | // GTEST_n_TUPLE_(T) is the type of an n-tuple. 68 | #define GTEST_0_TUPLE_(T) tuple<> 69 | 70 | $for k [[ 71 | $range m 0..k-1 72 | $range m2 k..n-1 73 | #define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]> 74 | 75 | ]] 76 | 77 | // GTEST_n_TYPENAMES_(T) declares a list of n typenames. 78 | 79 | $for j [[ 80 | $range m 0..j-1 81 | #define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]] 82 | 83 | 84 | ]] 85 | 86 | // In theory, defining stuff in the ::std namespace is undefined 87 | // behavior. We can do this as we are playing the role of a standard 88 | // library vendor. 89 | namespace std { 90 | namespace tr1 { 91 | 92 | template <$for i, [[typename T$i = void]]> 93 | class tuple; 94 | 95 | // Anything in namespace gtest_internal is Google Test's INTERNAL 96 | // IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. 97 | namespace gtest_internal { 98 | 99 | // ByRef::type is T if T is a reference; otherwise it's const T&. 100 | template 101 | struct ByRef { typedef const T& type; }; // NOLINT 102 | template 103 | struct ByRef { typedef T& type; }; // NOLINT 104 | 105 | // A handy wrapper for ByRef. 106 | #define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type 107 | 108 | // AddRef::type is T if T is a reference; otherwise it's T&. This 109 | // is the same as tr1::add_reference::type. 110 | template 111 | struct AddRef { typedef T& type; }; // NOLINT 112 | template 113 | struct AddRef { typedef T& type; }; // NOLINT 114 | 115 | // A handy wrapper for AddRef. 116 | #define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type 117 | 118 | // A helper for implementing get(). 119 | template class Get; 120 | 121 | // A helper for implementing tuple_element. kIndexValid is true 122 | // iff k < the number of fields in tuple type T. 123 | template 124 | struct TupleElement; 125 | 126 | 127 | $for i [[ 128 | template 129 | struct TupleElement { 130 | typedef T$i type; 131 | }; 132 | 133 | 134 | ]] 135 | } // namespace gtest_internal 136 | 137 | template <> 138 | class tuple<> { 139 | public: 140 | tuple() {} 141 | tuple(const tuple& /* t */) {} 142 | tuple& operator=(const tuple& /* t */) { return *this; } 143 | }; 144 | 145 | 146 | $for k [[ 147 | $range m 0..k-1 148 | template 149 | class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] { 150 | public: 151 | template friend class gtest_internal::Get; 152 | 153 | tuple() : $for m, [[f$(m)_()]] {} 154 | 155 | explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]] 156 | $for m, [[f$(m)_(f$m)]] {} 157 | 158 | tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} 159 | 160 | template 161 | tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} 162 | 163 | $if k == 2 [[ 164 | template 165 | tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} 166 | 167 | ]] 168 | 169 | tuple& operator=(const tuple& t) { return CopyFrom(t); } 170 | 171 | template 172 | tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) { 173 | return CopyFrom(t); 174 | } 175 | 176 | $if k == 2 [[ 177 | template 178 | tuple& operator=(const ::std::pair& p) { 179 | f0_ = p.first; 180 | f1_ = p.second; 181 | return *this; 182 | } 183 | 184 | ]] 185 | 186 | GTEST_DECLARE_TUPLE_AS_FRIEND_ 187 | 188 | template 189 | tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) { 190 | 191 | $for m [[ 192 | f$(m)_ = t.f$(m)_; 193 | 194 | ]] 195 | return *this; 196 | } 197 | 198 | 199 | $for m [[ 200 | T$m f$(m)_; 201 | 202 | ]] 203 | }; 204 | 205 | 206 | ]] 207 | // 6.1.3.2 Tuple creation functions. 208 | 209 | // Known limitations: we don't support passing an 210 | // std::tr1::reference_wrapper to make_tuple(). And we don't 211 | // implement tie(). 212 | 213 | inline tuple<> make_tuple() { return tuple<>(); } 214 | 215 | $for k [[ 216 | $range m 0..k-1 217 | 218 | template 219 | inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) { 220 | return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]); 221 | } 222 | 223 | ]] 224 | 225 | // 6.1.3.3 Tuple helper classes. 226 | 227 | template struct tuple_size; 228 | 229 | 230 | $for j [[ 231 | template 232 | struct tuple_size { 233 | static const int value = $j; 234 | }; 235 | 236 | 237 | ]] 238 | template 239 | struct tuple_element { 240 | typedef typename gtest_internal::TupleElement< 241 | k < (tuple_size::value), k, Tuple>::type type; 242 | }; 243 | 244 | #define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type 245 | 246 | // 6.1.3.4 Element access. 247 | 248 | namespace gtest_internal { 249 | 250 | 251 | $for i [[ 252 | template <> 253 | class Get<$i> { 254 | public: 255 | template 256 | static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) 257 | Field(Tuple& t) { return t.f$(i)_; } // NOLINT 258 | 259 | template 260 | static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) 261 | ConstField(const Tuple& t) { return t.f$(i)_; } 262 | }; 263 | 264 | 265 | ]] 266 | } // namespace gtest_internal 267 | 268 | template 269 | GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) 270 | get(GTEST_$(n)_TUPLE_(T)& t) { 271 | return gtest_internal::Get::Field(t); 272 | } 273 | 274 | template 275 | GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) 276 | get(const GTEST_$(n)_TUPLE_(T)& t) { 277 | return gtest_internal::Get::ConstField(t); 278 | } 279 | 280 | // 6.1.3.5 Relational operators 281 | 282 | // We only implement == and !=, as we don't have a need for the rest yet. 283 | 284 | namespace gtest_internal { 285 | 286 | // SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the 287 | // first k fields of t1 equals the first k fields of t2. 288 | // SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if 289 | // k1 != k2. 290 | template 291 | struct SameSizeTuplePrefixComparator; 292 | 293 | template <> 294 | struct SameSizeTuplePrefixComparator<0, 0> { 295 | template 296 | static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { 297 | return true; 298 | } 299 | }; 300 | 301 | template 302 | struct SameSizeTuplePrefixComparator { 303 | template 304 | static bool Eq(const Tuple1& t1, const Tuple2& t2) { 305 | return SameSizeTuplePrefixComparator::Eq(t1, t2) && 306 | ::std::tr1::get(t1) == ::std::tr1::get(t2); 307 | } 308 | }; 309 | 310 | } // namespace gtest_internal 311 | 312 | template 313 | inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t, 314 | const GTEST_$(n)_TUPLE_(U)& u) { 315 | return gtest_internal::SameSizeTuplePrefixComparator< 316 | tuple_size::value, 317 | tuple_size::value>::Eq(t, u); 318 | } 319 | 320 | template 321 | inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t, 322 | const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); } 323 | 324 | // 6.1.4 Pairs. 325 | // Unimplemented. 326 | 327 | } // namespace tr1 328 | } // namespace std 329 | 330 | 331 | $for j [[ 332 | #undef GTEST_$(j)_TUPLE_ 333 | 334 | ]] 335 | 336 | 337 | $for j [[ 338 | #undef GTEST_$(j)_TYPENAMES_ 339 | 340 | ]] 341 | 342 | #undef GTEST_DECLARE_TUPLE_AS_FRIEND_ 343 | #undef GTEST_BY_REF_ 344 | #undef GTEST_ADD_REF_ 345 | #undef GTEST_TUPLE_ELEMENT_ 346 | 347 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ 348 | -------------------------------------------------------------------------------- /llvm-jit-objc/src/lib/ObjCRuntime.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm-jit-objc/ObjCRuntime.h" 2 | 3 | #include "llvm-jit-objc/DebugUtils.h" 4 | #include "llvm-jit-objc/ObjCRuntimeHelpers.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | extern "C" Class objc_readClassPair(Class bits, const struct objc_image_info *info); 12 | 13 | using namespace objc; 14 | 15 | namespace mull { namespace objc { 16 | 17 | mull::objc::Runtime::~Runtime() { 18 | for (const Class &clz: runtimeClasses) { 19 | errs() << "disposing class: " << class_getName(clz) << "\n"; 20 | //assert(objc_classIsRegistered(clz)); 21 | 22 | objc_disposeClassPair(clz); 23 | 24 | assert(objc_classIsRegistered(clz) == false); 25 | } 26 | } 27 | 28 | void mull::objc::Runtime::registerSelectors(void *selRefsSectionPtr, 29 | uintptr_t selRefsSectionSize) { 30 | uint8_t *sectionStart = (uint8_t *)selRefsSectionPtr; 31 | 32 | for (uint8_t *cursor = sectionStart; 33 | cursor < (sectionStart + selRefsSectionSize); 34 | cursor = cursor + sizeof(SEL)) { 35 | SEL *selector = (SEL *)cursor; 36 | 37 | // TODO: memory padded/aligned by JIT. 38 | if (*selector == NULL) { 39 | continue; 40 | } 41 | const char *name = sel_getName(*selector); 42 | errs() << "Trying to register selector: " << *selector << "/" << name << "\n"; 43 | *selector = sel_registerName(name); 44 | } 45 | } 46 | 47 | void mull::objc::Runtime::addClassesFromSection(void *sectionPtr, 48 | uintptr_t sectionSize) { 49 | errs() << "mull::objc::Runtime> adding section for later registration: " 50 | << sectionPtr << ", " << sectionSize << "\n"; 51 | 52 | class64_t **classes = (class64_t **)sectionPtr; 53 | 54 | uint32_t count = sectionSize / 8; 55 | // 16 is "8 + alignment" (don't know yet what alignment is for). 56 | for (uintptr_t i = 0; i < count / 2; i += 1) { 57 | class64_t **clzPointerRef = &classes[i]; 58 | class64_t *clzPointer = *clzPointerRef; 59 | 60 | errs() << "mull::objc::Runtime> adding class for registration: " 61 | << clzPointer->getDataPointer()->getName() << "\n"; 62 | 63 | classesToRegister.push(clzPointerRef); 64 | } 65 | } 66 | 67 | void mull::objc::Runtime::addClassesFromClassRefsSection(void *sectionPtr, 68 | uintptr_t sectionSize) { 69 | errs() << "Runtime> addClassesFromClassRefsSection" << "\n"; 70 | 71 | Class *classrefs = (Class *)sectionPtr; 72 | uint32_t count = sectionSize / 8; 73 | 74 | for (uint32_t i = 0; i < count / 2; i++) { 75 | Class *classrefPtr = (&classrefs[i]); 76 | const char *className = object_getClassName((id)*classrefPtr); 77 | assert(className); 78 | errs() << "Considering " << className << "\n"; 79 | 80 | Class newClz = objc_getRequiredClass(className); 81 | assert(class_isMetaClass(newClz) == false); 82 | errs() << "\tclass has address: " << (void *)newClz << "\n"; 83 | 84 | if (*classrefPtr != newClz) { 85 | *classrefPtr = objc_getRequiredClass(className); 86 | } 87 | } 88 | } 89 | 90 | void mull::objc::Runtime::addClassesFromSuperclassRefsSection(void *sectionPtr, 91 | uintptr_t sectionSize) { 92 | errs() << "Runtime> addClassesFromSuperclassRefsSection" << "\n"; 93 | 94 | Class *classrefs = (Class *)sectionPtr; 95 | uint32_t count = sectionSize / 8; 96 | 97 | for (uint32_t i = 0; i < count / 2; i++) { 98 | int refType = 0; // 0 - unknown, 1 - class, 2 - metaclass 99 | 100 | Class *classrefPtr = (&classrefs[i]); 101 | Class classref = *classrefPtr; 102 | 103 | class64_t *ref = NULL; 104 | for (auto &clref: classRefs) { 105 | if ((void *)clref == (void *)classref) { 106 | errs() << "Ref is class" << "\n"; 107 | refType = 1; 108 | ref = clref; 109 | 110 | assert(ref); 111 | 112 | break; 113 | } 114 | } 115 | 116 | if (refType == 0) { 117 | for (auto &metaclref: metaclassRefs) { 118 | if ((void *)metaclref == (void *)classref) { 119 | errs() << "Ref is metaclass" << "\n"; 120 | refType = 2; 121 | ref = metaclref; 122 | break; 123 | } 124 | } 125 | } 126 | 127 | assert(refType != 0); 128 | const char *className; 129 | if (ref == NULL) { 130 | className = object_getClassName((id)classref); 131 | 132 | errs() << "Class is already registered (not by us) - " << className << "\n"; 133 | } else { 134 | className = ref->getDataPointer()->getName(); 135 | } 136 | here_objc_class *objcClass = (here_objc_class *)classref; 137 | if (refType == 1 && runtimeClasses.count(classref) > 0) { 138 | className = objcClass->data()->ro->name; 139 | } 140 | else if (refType == 2) { 141 | Class classForMetaClass = objc_getClass(object_getClassName((id)classref)); 142 | assert(classForMetaClass); 143 | className = objcClass->data()->ro->name; 144 | } 145 | assert(className); 146 | 147 | errs() << "Considering " << className << "\n"; 148 | Class newClz = objc_getClass(className); 149 | 150 | assert(refType != 0); 151 | if (refType == 2) { 152 | newClz = objc_getMetaClass(className); 153 | assert(newClz); 154 | assert(class_isMetaClass(newClz)); 155 | } 156 | 157 | if (*classrefPtr != newClz) { 158 | *classrefPtr = newClz; 159 | } 160 | } 161 | } 162 | 163 | void mull::objc::Runtime::addCategoriesFromSection(void *sectionPtr, 164 | uintptr_t sectionSize) { 165 | errs() << "Runtime> addCategoriesFromSection" << "\n"; 166 | 167 | category_t **categories = (category_t **)sectionPtr; 168 | uint32_t count = sectionSize / 8; 169 | 170 | for (uint32_t i = 0; i < count / 2; i++) { 171 | category_t *category = categories[i]; 172 | Class clz = (Class)category->cls; 173 | Class metaClz = objc_getMetaClass(class_getName(clz)); 174 | 175 | /* Instance methods */ 176 | const method_list64_t *clzMethodListPtr = (const method_list64_t *)category->instanceMethods; 177 | if (clzMethodListPtr) { 178 | const method64_t *methods = (const method64_t *)clzMethodListPtr->getFirstMethodPointer(); 179 | 180 | for (uint32_t i = 0; i < clzMethodListPtr->count; i++) { 181 | const method64_t *methodPtr = &methods[i]; 182 | 183 | IMP imp = (IMP)methodPtr->imp; 184 | 185 | BOOL success = class_addMethod(clz, 186 | sel_registerName(sel_getName(methodPtr->name)), 187 | (IMP)imp, 188 | (const char *)methodPtr->types); 189 | assert(success); 190 | } 191 | } 192 | 193 | /* Class methods */ 194 | const method_list64_t *metaclassMethodListPtr = (const method_list64_t *)category->classMethods; 195 | if (metaclassMethodListPtr) { 196 | const method64_t *methods = (const method64_t *)metaclassMethodListPtr->getFirstMethodPointer(); 197 | 198 | for (uint32_t i = 0; i < clzMethodListPtr->count; i++) { 199 | const method64_t *methodPtr = &methods[i]; 200 | 201 | IMP imp = (IMP)methodPtr->imp; 202 | 203 | BOOL success = class_addMethod(metaClz, 204 | sel_registerName(sel_getName(methodPtr->name)), 205 | (IMP)imp, 206 | (const char *)methodPtr->types); 207 | assert(success); 208 | } 209 | } 210 | } 211 | } 212 | 213 | #pragma mark - Private 214 | 215 | void mull::objc::Runtime::registerClasses() { 216 | while (classesToRegister.empty() == false) { 217 | class64_t **classrefPtr = classesToRegister.front(); 218 | class64_t *classref = *classrefPtr; 219 | classesToRegister.pop(); 220 | 221 | errs() << "registerClasses() " << classref->getDataPointer()->getName() << "\n"; 222 | 223 | class64_t *superClz64 = classref->getSuperclassPointer(); 224 | Class superClz = (Class)superClz64; 225 | if (objc_classIsRegistered(superClz) == false) { 226 | const char *superclzName = superClz64->getDataPointer()->getName(); 227 | if (Class registeredSuperClz = objc_getClass(superclzName)) { 228 | errs() << "registerClasses() " << "superclass is registered" << "\n"; 229 | superClz = registeredSuperClz; 230 | } else { 231 | errs() << "registerClasses() " << "superclass is not registered" << "\n"; 232 | 233 | classesToRegister.push(classrefPtr); 234 | continue; 235 | } 236 | } 237 | 238 | errs() << "registerClasses() " 239 | << "superclass is registered for class: " << classref->getDataPointer()->getName() 240 | << "\n"; 241 | //errs() << classref->getDebugDescription() << "\n"; 242 | 243 | assert(superClz); 244 | 245 | errs() << classref->getDebugDescription() << "\n"; 246 | 247 | Class runtimeClass = registerOneClass(classrefPtr, superClz); 248 | assert(objc_classIsRegistered(runtimeClass)); 249 | 250 | runtimeClasses.insert(runtimeClass); 251 | 252 | oldAndNewClassesMap.push_back(std::pair(classrefPtr, runtimeClass)); 253 | } 254 | 255 | assert(classesToRegister.empty()); 256 | } 257 | 258 | Class mull::objc::Runtime::registerOneClass(class64_t **classrefPtr, 259 | Class superclass) { 260 | 261 | class64_t *classref = *classrefPtr; 262 | class64_t *metaclassRef = classref->getIsaPointer(); 263 | 264 | assert(strlen(classref->getDataPointer()->name) > 0); 265 | printf("registerOneClass: %s \n", classref->getDataPointer()->name); 266 | printf("\t" "source ptr: 0x%016" PRIxPTR "\n", (uintptr_t)classref); 267 | printf("0x%016" PRIXPTR "\n", (uintptr_t) classref); 268 | 269 | classRefs.push_back(classref); 270 | metaclassRefs.push_back(metaclassRef); 271 | 272 | if (objc_getClass(classref->getDataPointer()->name) != nullptr) { 273 | errs() << "JIT Error: Objective-C class is already registered: " 274 | << classref->getDataPointer()->name << "\n"; 275 | exit(1); 276 | } 277 | assert(objc_classIsRegistered((Class)classref) == false); 278 | 279 | Class runtimeClass = objc_readClassPair((Class)classref, NULL); 280 | assert(runtimeClass); 281 | 282 | // The following might be wrong: 283 | // The class is registered by objc_readClassPair but we still hack on its 284 | // `flags` below and call objc_registerClassPair to make sure we can dispose 285 | // it with objc_disposeClassPair when JIT deallocates. 286 | assert(objc_classIsRegistered((Class)runtimeClass)); 287 | 288 | here_objc_class *runtimeClassInternal = (here_objc_class *)runtimeClass; 289 | here_objc_class *runtimeMetaclassInternal = (here_objc_class *)runtimeClassInternal->ISA(); 290 | 291 | #define RW_CONSTRUCTING (1<<26) 292 | here_class_rw_t *sourceClassData = runtimeClassInternal->data(); 293 | here_class_rw_t *sourceMetaclassData = (here_class_rw_t *)runtimeMetaclassInternal->data(); 294 | sourceClassData->flags |= RW_CONSTRUCTING; 295 | sourceMetaclassData->flags |= RW_CONSTRUCTING; 296 | objc_registerClassPair(runtimeClass); 297 | 298 | return runtimeClass; 299 | } 300 | 301 | } } 302 | -------------------------------------------------------------------------------- /googletest/include/gtest/gtest-typed-test.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Google Inc. 2 | // All Rights Reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | #ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ 33 | #define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ 34 | 35 | // This header implements typed tests and type-parameterized tests. 36 | 37 | // Typed (aka type-driven) tests repeat the same test for types in a 38 | // list. You must know which types you want to test with when writing 39 | // typed tests. Here's how you do it: 40 | 41 | #if 0 42 | 43 | // First, define a fixture class template. It should be parameterized 44 | // by a type. Remember to derive it from testing::Test. 45 | template 46 | class FooTest : public testing::Test { 47 | public: 48 | ... 49 | typedef std::list List; 50 | static T shared_; 51 | T value_; 52 | }; 53 | 54 | // Next, associate a list of types with the test case, which will be 55 | // repeated for each type in the list. The typedef is necessary for 56 | // the macro to parse correctly. 57 | typedef testing::Types MyTypes; 58 | TYPED_TEST_CASE(FooTest, MyTypes); 59 | 60 | // If the type list contains only one type, you can write that type 61 | // directly without Types<...>: 62 | // TYPED_TEST_CASE(FooTest, int); 63 | 64 | // Then, use TYPED_TEST() instead of TEST_F() to define as many typed 65 | // tests for this test case as you want. 66 | TYPED_TEST(FooTest, DoesBlah) { 67 | // Inside a test, refer to TypeParam to get the type parameter. 68 | // Since we are inside a derived class template, C++ requires use to 69 | // visit the members of FooTest via 'this'. 70 | TypeParam n = this->value_; 71 | 72 | // To visit static members of the fixture, add the TestFixture:: 73 | // prefix. 74 | n += TestFixture::shared_; 75 | 76 | // To refer to typedefs in the fixture, add the "typename 77 | // TestFixture::" prefix. 78 | typename TestFixture::List values; 79 | values.push_back(n); 80 | ... 81 | } 82 | 83 | TYPED_TEST(FooTest, HasPropertyA) { ... } 84 | 85 | #endif // 0 86 | 87 | // Type-parameterized tests are abstract test patterns parameterized 88 | // by a type. Compared with typed tests, type-parameterized tests 89 | // allow you to define the test pattern without knowing what the type 90 | // parameters are. The defined pattern can be instantiated with 91 | // different types any number of times, in any number of translation 92 | // units. 93 | // 94 | // If you are designing an interface or concept, you can define a 95 | // suite of type-parameterized tests to verify properties that any 96 | // valid implementation of the interface/concept should have. Then, 97 | // each implementation can easily instantiate the test suite to verify 98 | // that it conforms to the requirements, without having to write 99 | // similar tests repeatedly. Here's an example: 100 | 101 | #if 0 102 | 103 | // First, define a fixture class template. It should be parameterized 104 | // by a type. Remember to derive it from testing::Test. 105 | template 106 | class FooTest : public testing::Test { 107 | ... 108 | }; 109 | 110 | // Next, declare that you will define a type-parameterized test case 111 | // (the _P suffix is for "parameterized" or "pattern", whichever you 112 | // prefer): 113 | TYPED_TEST_CASE_P(FooTest); 114 | 115 | // Then, use TYPED_TEST_P() to define as many type-parameterized tests 116 | // for this type-parameterized test case as you want. 117 | TYPED_TEST_P(FooTest, DoesBlah) { 118 | // Inside a test, refer to TypeParam to get the type parameter. 119 | TypeParam n = 0; 120 | ... 121 | } 122 | 123 | TYPED_TEST_P(FooTest, HasPropertyA) { ... } 124 | 125 | // Now the tricky part: you need to register all test patterns before 126 | // you can instantiate them. The first argument of the macro is the 127 | // test case name; the rest are the names of the tests in this test 128 | // case. 129 | REGISTER_TYPED_TEST_CASE_P(FooTest, 130 | DoesBlah, HasPropertyA); 131 | 132 | // Finally, you are free to instantiate the pattern with the types you 133 | // want. If you put the above code in a header file, you can #include 134 | // it in multiple C++ source files and instantiate it multiple times. 135 | // 136 | // To distinguish different instances of the pattern, the first 137 | // argument to the INSTANTIATE_* macro is a prefix that will be added 138 | // to the actual test case name. Remember to pick unique prefixes for 139 | // different instances. 140 | typedef testing::Types MyTypes; 141 | INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); 142 | 143 | // If the type list contains only one type, you can write that type 144 | // directly without Types<...>: 145 | // INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); 146 | 147 | #endif // 0 148 | 149 | #include "gtest/internal/gtest-port.h" 150 | #include "gtest/internal/gtest-type-util.h" 151 | 152 | // Implements typed tests. 153 | 154 | #if GTEST_HAS_TYPED_TEST 155 | 156 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 157 | // 158 | // Expands to the name of the typedef for the type parameters of the 159 | // given test case. 160 | # define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ 161 | 162 | // The 'Types' template argument below must have spaces around it 163 | // since some compilers may choke on '>>' when passing a template 164 | // instance (e.g. Types) 165 | # define TYPED_TEST_CASE(CaseName, Types) \ 166 | typedef ::testing::internal::TypeList< Types >::type \ 167 | GTEST_TYPE_PARAMS_(CaseName) 168 | 169 | # define TYPED_TEST(CaseName, TestName) \ 170 | template \ 171 | class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ 172 | : public CaseName { \ 173 | private: \ 174 | typedef CaseName TestFixture; \ 175 | typedef gtest_TypeParam_ TypeParam; \ 176 | virtual void TestBody(); \ 177 | }; \ 178 | bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ 179 | ::testing::internal::TypeParameterizedTest< \ 180 | CaseName, \ 181 | ::testing::internal::TemplateSel< \ 182 | GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ 183 | GTEST_TYPE_PARAMS_(CaseName)>::Register(\ 184 | "", ::testing::internal::CodeLocation(__FILE__, __LINE__), \ 185 | #CaseName, #TestName, 0); \ 186 | template \ 187 | void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() 188 | 189 | #endif // GTEST_HAS_TYPED_TEST 190 | 191 | // Implements type-parameterized tests. 192 | 193 | #if GTEST_HAS_TYPED_TEST_P 194 | 195 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 196 | // 197 | // Expands to the namespace name that the type-parameterized tests for 198 | // the given type-parameterized test case are defined in. The exact 199 | // name of the namespace is subject to change without notice. 200 | # define GTEST_CASE_NAMESPACE_(TestCaseName) \ 201 | gtest_case_##TestCaseName##_ 202 | 203 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 204 | // 205 | // Expands to the name of the variable used to remember the names of 206 | // the defined tests in the given test case. 207 | # define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ 208 | gtest_typed_test_case_p_state_##TestCaseName##_ 209 | 210 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. 211 | // 212 | // Expands to the name of the variable used to remember the names of 213 | // the registered tests in the given test case. 214 | # define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ 215 | gtest_registered_test_names_##TestCaseName##_ 216 | 217 | // The variables defined in the type-parameterized test macros are 218 | // static as typically these macros are used in a .h file that can be 219 | // #included in multiple translation units linked together. 220 | # define TYPED_TEST_CASE_P(CaseName) \ 221 | static ::testing::internal::TypedTestCasePState \ 222 | GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) 223 | 224 | # define TYPED_TEST_P(CaseName, TestName) \ 225 | namespace GTEST_CASE_NAMESPACE_(CaseName) { \ 226 | template \ 227 | class TestName : public CaseName { \ 228 | private: \ 229 | typedef CaseName TestFixture; \ 230 | typedef gtest_TypeParam_ TypeParam; \ 231 | virtual void TestBody(); \ 232 | }; \ 233 | static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ 234 | GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ 235 | __FILE__, __LINE__, #CaseName, #TestName); \ 236 | } \ 237 | template \ 238 | void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() 239 | 240 | # define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ 241 | namespace GTEST_CASE_NAMESPACE_(CaseName) { \ 242 | typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ 243 | } \ 244 | static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) \ 245 | GTEST_ATTRIBUTE_UNUSED_ = \ 246 | GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ 247 | __FILE__, __LINE__, #__VA_ARGS__) 248 | 249 | // The 'Types' template argument below must have spaces around it 250 | // since some compilers may choke on '>>' when passing a template 251 | // instance (e.g. Types) 252 | # define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ 253 | bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ 254 | ::testing::internal::TypeParameterizedTestCase::type>::Register(\ 257 | #Prefix, \ 258 | ::testing::internal::CodeLocation(__FILE__, __LINE__), \ 259 | >EST_TYPED_TEST_CASE_P_STATE_(CaseName), \ 260 | #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) 261 | 262 | #endif // GTEST_HAS_TYPED_TEST_P 263 | 264 | #endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ 265 | -------------------------------------------------------------------------------- /CustomXCTestRunner/CustomXCTestRunnerObjC/CustomXCTestRunnerObjC.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 86DCB3A1206E6FDE0019B127 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DCB3A0206E6FDE0019B127 /* main.m */; }; 11 | 86DCB3A9206E6FED0019B127 /* CustomXCTestRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DCB3A7206E6FED0019B127 /* CustomXCTestRunner.m */; }; 12 | 86DCB3AC206E70290019B127 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 86DCB3AB206E70290019B127 /* XCTest.framework */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | 86DCB39B206E6FDD0019B127 /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = usr/share/man/man1; 20 | dstSubfolderSpec = 10; 21 | files = ( 22 | ); 23 | runOnlyForDeploymentPostprocessing = 1; 24 | }; 25 | /* End PBXCopyFilesBuildPhase section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 86DCB39D206E6FDD0019B127 /* CustomXCTestRunnerObjC */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CustomXCTestRunnerObjC; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 86DCB3A0206E6FDE0019B127 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 30 | 86DCB3A7206E6FED0019B127 /* CustomXCTestRunner.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; name = CustomXCTestRunner.m; path = ../CustomXCTestRunner.m; sourceTree = ""; }; 31 | 86DCB3A8206E6FED0019B127 /* CustomXCTestRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomXCTestRunner.h; path = ../CustomXCTestRunner.h; sourceTree = ""; }; 32 | 86DCB3AB206E70290019B127 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/MacOSX.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | 86DCB39A206E6FDD0019B127 /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | 86DCB3AC206E70290019B127 /* XCTest.framework in Frameworks */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 86DCB394206E6FDD0019B127 = { 48 | isa = PBXGroup; 49 | children = ( 50 | 86DCB3A8206E6FED0019B127 /* CustomXCTestRunner.h */, 51 | 86DCB3A7206E6FED0019B127 /* CustomXCTestRunner.m */, 52 | 86DCB39F206E6FDE0019B127 /* CustomXCTestRunnerObjC */, 53 | 86DCB39E206E6FDD0019B127 /* Products */, 54 | 86DCB3AA206E70290019B127 /* Frameworks */, 55 | ); 56 | sourceTree = ""; 57 | }; 58 | 86DCB39E206E6FDD0019B127 /* Products */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 86DCB39D206E6FDD0019B127 /* CustomXCTestRunnerObjC */, 62 | ); 63 | name = Products; 64 | sourceTree = ""; 65 | }; 66 | 86DCB39F206E6FDE0019B127 /* CustomXCTestRunnerObjC */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 86DCB3A0206E6FDE0019B127 /* main.m */, 70 | ); 71 | path = CustomXCTestRunnerObjC; 72 | sourceTree = ""; 73 | }; 74 | 86DCB3AA206E70290019B127 /* Frameworks */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 86DCB3AB206E70290019B127 /* XCTest.framework */, 78 | ); 79 | name = Frameworks; 80 | sourceTree = ""; 81 | }; 82 | /* End PBXGroup section */ 83 | 84 | /* Begin PBXNativeTarget section */ 85 | 86DCB39C206E6FDD0019B127 /* CustomXCTestRunnerObjC */ = { 86 | isa = PBXNativeTarget; 87 | buildConfigurationList = 86DCB3A4206E6FDE0019B127 /* Build configuration list for PBXNativeTarget "CustomXCTestRunnerObjC" */; 88 | buildPhases = ( 89 | 86DCB399206E6FDD0019B127 /* Sources */, 90 | 86DCB39A206E6FDD0019B127 /* Frameworks */, 91 | 86DCB39B206E6FDD0019B127 /* CopyFiles */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = CustomXCTestRunnerObjC; 98 | productName = CustomXCTestRunnerObjC; 99 | productReference = 86DCB39D206E6FDD0019B127 /* CustomXCTestRunnerObjC */; 100 | productType = "com.apple.product-type.tool"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | 86DCB395206E6FDD0019B127 /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastUpgradeCheck = 0920; 109 | ORGANIZATIONNAME = "Stanislav Pankevich"; 110 | TargetAttributes = { 111 | 86DCB39C206E6FDD0019B127 = { 112 | CreatedOnToolsVersion = 9.2; 113 | ProvisioningStyle = Automatic; 114 | }; 115 | }; 116 | }; 117 | buildConfigurationList = 86DCB398206E6FDD0019B127 /* Build configuration list for PBXProject "CustomXCTestRunnerObjC" */; 118 | compatibilityVersion = "Xcode 8.0"; 119 | developmentRegion = en; 120 | hasScannedForEncodings = 0; 121 | knownRegions = ( 122 | en, 123 | ); 124 | mainGroup = 86DCB394206E6FDD0019B127; 125 | productRefGroup = 86DCB39E206E6FDD0019B127 /* Products */; 126 | projectDirPath = ""; 127 | projectRoot = ""; 128 | targets = ( 129 | 86DCB39C206E6FDD0019B127 /* CustomXCTestRunnerObjC */, 130 | ); 131 | }; 132 | /* End PBXProject section */ 133 | 134 | /* Begin PBXSourcesBuildPhase section */ 135 | 86DCB399206E6FDD0019B127 /* Sources */ = { 136 | isa = PBXSourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | 86DCB3A1206E6FDE0019B127 /* main.m in Sources */, 140 | 86DCB3A9206E6FED0019B127 /* CustomXCTestRunner.m in Sources */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXSourcesBuildPhase section */ 145 | 146 | /* Begin XCBuildConfiguration section */ 147 | 86DCB3A2206E6FDE0019B127 /* Debug */ = { 148 | isa = XCBuildConfiguration; 149 | buildSettings = { 150 | ALWAYS_SEARCH_USER_PATHS = NO; 151 | CLANG_ANALYZER_NONNULL = YES; 152 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 153 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 154 | CLANG_CXX_LIBRARY = "libc++"; 155 | CLANG_ENABLE_MODULES = YES; 156 | CLANG_ENABLE_OBJC_ARC = YES; 157 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 158 | CLANG_WARN_BOOL_CONVERSION = YES; 159 | CLANG_WARN_COMMA = YES; 160 | CLANG_WARN_CONSTANT_CONVERSION = YES; 161 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 162 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 163 | CLANG_WARN_EMPTY_BODY = YES; 164 | CLANG_WARN_ENUM_CONVERSION = YES; 165 | CLANG_WARN_INFINITE_RECURSION = YES; 166 | CLANG_WARN_INT_CONVERSION = YES; 167 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 168 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 169 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 170 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 171 | CLANG_WARN_STRICT_PROTOTYPES = YES; 172 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 173 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 174 | CLANG_WARN_UNREACHABLE_CODE = YES; 175 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 176 | CODE_SIGN_IDENTITY = "Mac Developer"; 177 | COPY_PHASE_STRIP = NO; 178 | DEBUG_INFORMATION_FORMAT = dwarf; 179 | ENABLE_STRICT_OBJC_MSGSEND = YES; 180 | ENABLE_TESTABILITY = YES; 181 | GCC_C_LANGUAGE_STANDARD = gnu11; 182 | GCC_DYNAMIC_NO_PIC = NO; 183 | GCC_NO_COMMON_BLOCKS = YES; 184 | GCC_OPTIMIZATION_LEVEL = 0; 185 | GCC_PREPROCESSOR_DEFINITIONS = ( 186 | "DEBUG=1", 187 | "$(inherited)", 188 | ); 189 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 190 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 191 | GCC_WARN_UNDECLARED_SELECTOR = YES; 192 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 193 | GCC_WARN_UNUSED_FUNCTION = YES; 194 | GCC_WARN_UNUSED_VARIABLE = YES; 195 | MACOSX_DEPLOYMENT_TARGET = 10.13; 196 | MTL_ENABLE_DEBUG_INFO = YES; 197 | ONLY_ACTIVE_ARCH = YES; 198 | SDKROOT = macosx; 199 | }; 200 | name = Debug; 201 | }; 202 | 86DCB3A3206E6FDE0019B127 /* Release */ = { 203 | isa = XCBuildConfiguration; 204 | buildSettings = { 205 | ALWAYS_SEARCH_USER_PATHS = NO; 206 | CLANG_ANALYZER_NONNULL = YES; 207 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 208 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 209 | CLANG_CXX_LIBRARY = "libc++"; 210 | CLANG_ENABLE_MODULES = YES; 211 | CLANG_ENABLE_OBJC_ARC = YES; 212 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 213 | CLANG_WARN_BOOL_CONVERSION = YES; 214 | CLANG_WARN_COMMA = YES; 215 | CLANG_WARN_CONSTANT_CONVERSION = YES; 216 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 217 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 218 | CLANG_WARN_EMPTY_BODY = YES; 219 | CLANG_WARN_ENUM_CONVERSION = YES; 220 | CLANG_WARN_INFINITE_RECURSION = YES; 221 | CLANG_WARN_INT_CONVERSION = YES; 222 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 223 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 224 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 225 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 226 | CLANG_WARN_STRICT_PROTOTYPES = YES; 227 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 228 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 229 | CLANG_WARN_UNREACHABLE_CODE = YES; 230 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 231 | CODE_SIGN_IDENTITY = "Mac Developer"; 232 | COPY_PHASE_STRIP = NO; 233 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 234 | ENABLE_NS_ASSERTIONS = NO; 235 | ENABLE_STRICT_OBJC_MSGSEND = YES; 236 | GCC_C_LANGUAGE_STANDARD = gnu11; 237 | GCC_NO_COMMON_BLOCKS = YES; 238 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 239 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 240 | GCC_WARN_UNDECLARED_SELECTOR = YES; 241 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 242 | GCC_WARN_UNUSED_FUNCTION = YES; 243 | GCC_WARN_UNUSED_VARIABLE = YES; 244 | MACOSX_DEPLOYMENT_TARGET = 10.13; 245 | MTL_ENABLE_DEBUG_INFO = NO; 246 | SDKROOT = macosx; 247 | }; 248 | name = Release; 249 | }; 250 | 86DCB3A5206E6FDE0019B127 /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | CODE_SIGN_STYLE = Automatic; 254 | DEVELOPMENT_TEAM = 399ZF6384C; 255 | FRAMEWORK_SEARCH_PATHS = "/Applications/Xcode-9.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks"; 256 | LD_RUNPATH_SEARCH_PATHS = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/; 257 | PRODUCT_NAME = "$(TARGET_NAME)"; 258 | }; 259 | name = Debug; 260 | }; 261 | 86DCB3A6206E6FDE0019B127 /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | CODE_SIGN_STYLE = Automatic; 265 | DEVELOPMENT_TEAM = 399ZF6384C; 266 | FRAMEWORK_SEARCH_PATHS = "/Applications/Xcode-9.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks"; 267 | LD_RUNPATH_SEARCH_PATHS = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/; 268 | PRODUCT_NAME = "$(TARGET_NAME)"; 269 | }; 270 | name = Release; 271 | }; 272 | /* End XCBuildConfiguration section */ 273 | 274 | /* Begin XCConfigurationList section */ 275 | 86DCB398206E6FDD0019B127 /* Build configuration list for PBXProject "CustomXCTestRunnerObjC" */ = { 276 | isa = XCConfigurationList; 277 | buildConfigurations = ( 278 | 86DCB3A2206E6FDE0019B127 /* Debug */, 279 | 86DCB3A3206E6FDE0019B127 /* Release */, 280 | ); 281 | defaultConfigurationIsVisible = 0; 282 | defaultConfigurationName = Release; 283 | }; 284 | 86DCB3A4206E6FDE0019B127 /* Build configuration list for PBXNativeTarget "CustomXCTestRunnerObjC" */ = { 285 | isa = XCConfigurationList; 286 | buildConfigurations = ( 287 | 86DCB3A5206E6FDE0019B127 /* Debug */, 288 | 86DCB3A6206E6FDE0019B127 /* Release */, 289 | ); 290 | defaultConfigurationIsVisible = 0; 291 | defaultConfigurationName = Release; 292 | }; 293 | /* End XCConfigurationList section */ 294 | }; 295 | rootObject = 86DCB395206E6FDD0019B127 /* Project object */; 296 | } 297 | --------------------------------------------------------------------------------