Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -321,3 +321,5 @@ if (LIBUNWIND_INCLUDE_DOCS) add_subdirectory(docs) endif() + +add_subdirectory(test) Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -0,0 +1,35 @@ +include(AddLLVM) # for add_lit_testsuite +macro(pythonize_bool var) + if (${var}) + set(${var} True) + else() + set(${var} False) + endif() +endmacro() + +if (NOT DEFINED LIBCXX_ENABLE_SHARED) + set(LIBCXX_ENABLE_SHARED ON) +endif() + +pythonize_bool(LIBUNWIND_BUILD_32_BITS) +pythonize_bool(LIBCXX_ENABLE_SHARED) +pythonize_bool(LIBUNWIND_ENABLE_SHARED) +pythonize_bool(LIBUNWIND_ENABLE_THREADS) +pythonize_bool(LIBUNWIND_ENABLE_EXCEPTIONS) +pythonize_bool(LIBUNWIND_USE_LLVM_UNWINDER) +pythonize_bool(LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY) +set(LIBUNWIND_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING + "TargetInfo to use when setting up test environment.") +set(LIBUNWIND_EXECUTOR "None" CACHE STRING + "Executor to use when running tests.") + +set(AUTO_GEN_COMMENT "## Autogenerated by libunwind configuration.\n# Do not edit!") +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + @ONLY) + +add_lit_testsuite(check-unwind "Running libunwind tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${LIBUNWIND_TEST_DEPS} + ) Index: test/libunwind/test/config.py =================================================================== --- test/libunwind/test/config.py +++ test/libunwind/test/config.py @@ -0,0 +1,70 @@ +#===----------------------------------------------------------------------===## +# +# The LLVM Compiler Infrastructure +# +# This file is dual licensed under the MIT and the University of Illinois Open +# Source Licenses. See LICENSE.TXT for details. +# +#===----------------------------------------------------------------------===## +import os +import sys + +from libcxx.test.config import Configuration as LibcxxConfiguration + + +class Configuration(LibcxxConfiguration): + # pylint: disable=redefined-outer-name + def __init__(self, lit_config, config): + super(Configuration, self).__init__(lit_config, config) + self.libunwind_src_root = None + self.libunwind_obj_root = None + self.abi_library_path = None + self.libcxx_src_root = None + + def configure_src_root(self): + self.libunwind_src_root = self.get_lit_conf( + 'libunwind_src_root', + os.path.dirname(self.config.test_source_root)) + self.libcxx_src_root = self.get_lit_conf( + 'libcxx_src_root', + os.path.join(self.libunwind_src_root, '/../libcxx')) + + def configure_obj_root(self): + self.libunwind_obj_root = self.get_lit_conf('libunwind_obj_root') + super(Configuration, self).configure_obj_root() + + def has_cpp_feature(self, feature, required_value): + return int(self.cxx.dumpMacros().get('__cpp_' + feature, 0)) >= required_value + + def configure_features(self): + super(Configuration, self).configure_features() + if not self.get_lit_bool('enable_exceptions', True): + self.config.available_features.add('libcxxabi-no-exceptions') + + def configure_compile_flags(self): + self.cxx.compile_flags += ['-DLIBUNWIND_NO_TIMER'] + if self.get_lit_bool('enable_exceptions', True): + self.cxx.compile_flags += ['-funwind-tables'] + else: + self.cxx.compile_flags += ['-fno-exceptions', '-DLIBUNWIND_HAS_NO_EXCEPTIONS'] + if not self.get_lit_bool('enable_threads', True): + self.cxx.compile_flags += ['-D_LIBUNWIND_HAS_NO_THREADS'] + self.config.available_features.add('libunwind-no-threads') + super(Configuration, self).configure_compile_flags() + + def configure_compile_flags_header_includes(self): + self.configure_config_site_header() + + libunwind_headers = self.get_lit_conf( + 'libunwind_headers', + os.path.join(self.libunwind_src_root, 'include')) + if not os.path.isdir(libunwind_headers): + self.lit_config.fatal("libunwind_headers='%s' is not a directory." + % libunwind_headers) + self.cxx.compile_flags += ['-I' + libunwind_headers] + + def configure_compile_flags_exceptions(self): + pass + + def configure_compile_flags_rtti(self): + pass Index: test/libunwind_02.pass.cpp =================================================================== --- test/libunwind_02.pass.cpp +++ test/libunwind_02.pass.cpp @@ -6,6 +6,7 @@ #define NUM_FRAMES_UPPER_BOUND 100 _Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) { + (void)context; int *i = (int *)cnt; ++*i; if (*i > NUM_FRAMES_UPPER_BOUND) { Index: test/lit.cfg =================================================================== --- test/lit.cfg +++ test/lit.cfg @@ -0,0 +1,67 @@ +# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79: + +# Configuration file for the 'lit' test runner. + + +import os +import site + +site.addsitedir(os.path.dirname(__file__)) + + +# Tell pylint that we know config and lit_config exist somewhere. +if 'PYLINT_IMPORT' in os.environ: + config = object() + lit_config = object() + +# name: The name of this test suite. +config.name = 'libunwind' + +# suffixes: A list of file extensions to treat as test files. +config.suffixes = ['.cpp', '.s'] + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) + +# Infer the libcxx_test_source_root for configuration import. +# If libcxx_source_root isn't specified in the config, assume that the libcxx +# and libunwind source directories are sibling directories. +libcxx_src_root = getattr(config, 'libcxx_src_root', None) +if not libcxx_src_root: + libcxx_src_root = os.path.join(config.test_source_root, '../../libcxx') +libcxx_test_src_root = os.path.join(libcxx_src_root, 'utils') +if os.path.isfile(os.path.join(libcxx_test_src_root, 'libcxx', '__init__.py')): + site.addsitedir(libcxx_test_src_root) +else: + lit_config.fatal('Could not find libcxx test directory for test imports' + ' in: %s' % libcxx_test_src_root) + +# Infer the test_exec_root from the libcxx_object root. +obj_root = getattr(config, 'libunwind_obj_root', None) + +# Check that the test exec root is known. +if obj_root is None: + import libcxx.test.config + libcxx.test.config.loadSiteConfig( + lit_config, config, 'libunwind_site_config', 'LIBCXXABI_SITE_CONFIG') + obj_root = getattr(config, 'libunwind_obj_root', None) + if obj_root is None: + import tempfile + obj_root = tempfile.mkdtemp(prefix='libunwind-testsuite-') + lit_config.warning('Creating temporary directory for object root: %s' % + obj_root) + +config.test_exec_root = os.path.join(obj_root, 'test') + +cfg_variant = getattr(config, 'configuration_variant', 'libunwind') +if cfg_variant: + lit_config.note('Using configuration variant: %s' % cfg_variant) + +# Load the Configuration class from the module name .test.config. +config_module_name = '.'.join([cfg_variant, 'test', 'config']) +config_module = __import__(config_module_name, fromlist=['Configuration']) + +configuration = config_module.Configuration(lit_config, config) +configuration.configure() +configuration.print_config_info() +config.test_format = configuration.get_test_format() Index: test/lit.site.cfg.in =================================================================== --- test/lit.site.cfg.in +++ test/lit.site.cfg.in @@ -0,0 +1,25 @@ +@AUTO_GEN_COMMENT@ +config.cxx_under_test = "@LIBUNWIND_COMPILER@" +config.project_obj_root = "@CMAKE_BINARY_DIR@" +config.libunwind_src_root = "@LIBUNWIND_SOURCE_DIR@" +config.libunwind_obj_root = "@LIBUNWIND_BINARY_DIR@" +config.abi_library_path = "@LIBUNWIND_LIBRARY_DIR@" +config.libcxx_src_root = "@LIBUNWIND_LIBCXX_PATH@" +config.libunwind_headers = "@LIBUNWIND_SOURCE_DIR@/include" +config.cxx_library_root = "@LIBUNWIND_LIBCXX_LIBRARY_PATH@" +config.llvm_unwinder = "@LIBUNWIND_USE_LLVM_UNWINDER@" +config.enable_threads = "@LIBUNWIND_ENABLE_THREADS@" +config.use_sanitizer = "@LLVM_USE_SANITIZER@" +config.enable_32bit = "@LIBUNWIND_BUILD_32_BITS@" +config.target_info = "@LIBUNWIND_TARGET_INFO@" +config.executor = "@LIBUNWIND_EXECUTOR@" +config.libunwind_shared = "@LIBUNWIND_ENABLE_SHARED@" +config.enable_shared = "@LIBCXX_ENABLE_SHARED@" +config.enable_exceptions = "@LIBUNWIND_ENABLE_EXCEPTIONS@" +config.host_triple = "@LLVM_HOST_TRIPLE@" +config.target_triple = "@TARGET_TRIPLE@" +config.use_target = len("@LIBUNWIND_TARGET_TRIPLE@") > 0 +config.cxx_ext_threads = "@LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY@" + +# Let the main config do the real work. +lit_config.load_config(config, "@LIBUNWIND_SOURCE_DIR@/test/lit.cfg")