From 01a28ca7f8f0999527ffa2d86f6e77b374ef1ed6 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Wed, 29 Mar 2017 21:01:14 +0000 Subject: [PATCH] Centralize libc++ test skipping logic Summary: This aims to replace the different decorators we've had on each libc++ test with a single solution. Each libc++ will be assigned to the "libc++" category and a single central piece of code will decide whether we are actually able to run libc++ test in the given configuration by enabling or disabling the category (while giving the user the opportunity to override this). I started this effort because I wanted to get libc++ tests running on android, and none of the existing decorators worked for this use case: - skipIfGcc - incorrect, we can build libc++ executables on android with gcc (in fact, after this, we can now do it on linux as well) - lldbutil.skip_if_library_missing - this checks whether libc++.so is loaded in the proces, which fails in case of a statically linked libc++ (this makes copying executables to the remote target easier to manage). To make this work I needed to split out the pseudo_barrier code from the force-included file, as libc++'s atomic does not play well with gcc on linux, and this made every test fail, even though we need the code only in the threading tests. So far, I am only annotating one of the tests with this category. If this does not break anything, I'll proceed to update the rest. Reviewers: jingham, zturner, EricWF Subscribers: srhines, lldb-commits Differential Revision: https://reviews.llvm.org/D30984 llvm-svn: 299028 --- lldb/packages/Python/lldbsuite/test/dotest.py | 25 ++++++++++++++ .../string/TestDataFormatterLibcxxString.py | 33 +++++++++---------- .../postmortem/elf-core/gcore/main.cpp | 2 +- .../postmortem/elf-core/thread_crash/main.cpp | 2 +- .../thread/break_after_join/main.cpp | 2 +- .../thread/concurrent_events/main.cpp | 2 +- .../thread/create_during_step/main.cpp | 2 +- .../thread/exit_during_break/main.cpp | 2 +- .../thread/exit_during_step/main.cpp | 1 + .../thread/multi_break/main.cpp | 2 +- .../functionalities/thread/step_out/main.cpp | 2 +- .../thread/thread_exit/main.cpp | 2 +- .../Python/lldbsuite/test/lldbplatformutil.py | 12 +++---- .../Python/lldbsuite/test/make/Android.rules | 2 +- .../Python/lldbsuite/test/make/Makefile.rules | 28 ++++++++-------- .../lldbsuite/test/make/pseudo_barrier.h | 20 +++++++++++ .../Python/lldbsuite/test/make/test_common.h | 31 ----------------- .../Python/lldbsuite/test/test_categories.py | 1 + 18 files changed, 92 insertions(+), 79 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/make/pseudo_barrier.h diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index a6bb01ea608d..7d739acba952 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -1061,6 +1061,29 @@ def checkCompiler(): configuration.compiler = cmd_output.split('\n')[0] print("'xcrun -find %s' returning %s" % (c, configuration.compiler)) +def canRunLibcxxTests(): + from lldbsuite.test import lldbplatformutil + + platform = lldbplatformutil.getPlatform() + + if lldbplatformutil.target_is_android() or lldbplatformutil.platformIsDarwin(): + return True, "libc++ always present" + + if platform == "linux": + if not os.path.isdir("/usr/include/c++/v1"): + return False, "Unable to find libc++ installation" + return True, "Headers found, let's hope they work" + + return False, "Don't know how to build with libc++ on %s" % platform + +def checkLibcxxSupport(): + result, reason = canRunLibcxxTests() + if result: + return # libc++ supported + if "libc++" in configuration.categoriesList: + return # libc++ category explicitly requested, let it run. + print("Libc++ tests will not be run because: " + reason) + configuration.skipCategories.append("libc++") def run_suite(): # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults @@ -1164,6 +1187,8 @@ def run_suite(): target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] + checkLibcxxSupport() + # Don't do debugserver tests on everything except OS X. configuration.dont_do_debugserver_test = "linux" in target_platform or "freebsd" in target_platform or "windows" in target_platform diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py index b0e84121dded..5b9b14d549e5 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py @@ -23,9 +23,10 @@ class LibcxxStringDataFormatterTestCase(TestBase): TestBase.setUp(self) # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') + ns = 'ndk' if lldbplatformutil.target_is_android() else '' + self.namespace = 'std::__' + ns + '1' - @skipIf(compiler="gcc") - @skipIfWindows # libc++ not ported to Windows yet + @add_test_categories(["libc++"]) def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() @@ -36,9 +37,6 @@ class LibcxxStringDataFormatterTestCase(TestBase): self.runCmd("run", RUN_SUCCEEDED) - lldbutil.skip_if_library_missing( - self, self.target(), lldbutil.PrintableRegex("libc\+\+")) - # The stop reason of the thread should be breakpoint. self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', @@ -58,17 +56,18 @@ class LibcxxStringDataFormatterTestCase(TestBase): # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) + ns = self.namespace self.expect( "frame variable", substrs=[ - '(std::__1::wstring) s = L"hello world! מזל טוב!"', - '(std::__1::wstring) S = L"!!!!"', + '(%s::wstring) s = L"hello world! מזל טוב!"'%ns, + '(%s::wstring) S = L"!!!!"'%ns, '(const wchar_t *) mazeltov = 0x', 'L"מזל טוב"', - '(std::__1::string) q = "hello world"', - '(std::__1::string) Q = "quite a long std::strin with lots of info inside it"', - '(std::__1::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"', - '(std::__1::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"']) + '(%s::string) q = "hello world"'%ns, + '(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns, + '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, + '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns]) self.runCmd("n") @@ -91,11 +90,11 @@ class LibcxxStringDataFormatterTestCase(TestBase): self.expect( "frame variable", substrs=[ - '(std::__1::wstring) s = L"hello world! מזל טוב!"', - '(std::__1::wstring) S = L"!!!!!"', + '(%s::wstring) s = L"hello world! מזל טוב!"'%ns, + '(%s::wstring) S = L"!!!!!"'%ns, '(const wchar_t *) mazeltov = 0x', 'L"מזל טוב"', - '(std::__1::string) q = "hello world"', - '(std::__1::string) Q = "quite a long std::strin with lots of info inside it"', - '(std::__1::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"', - '(std::__1::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"']) + '(%s::string) q = "hello world"'%ns, + '(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns, + '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, + '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns]) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp index 9908faffb6eb..f53ce2f35924 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/gcore/main.cpp @@ -9,7 +9,7 @@ // This test verifies the correct handling of child thread exits. -#include +#include "pseudo_barrier.h" #include #include diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp index 826d9d3fa972..7e09662edb2d 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/main.cpp @@ -9,7 +9,7 @@ // This test verifies the correct handling of child thread exits. -#include +#include "pseudo_barrier.h" #include #include diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp index f9f33fda82bb..f06761936d12 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp @@ -13,7 +13,7 @@ // breakpoint is hit. The test case should be flexible enough to treat that // as success. -#include +#include "pseudo_barrier.h" #include #include diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp index 10b55bff3ba4..540b5148aefa 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp @@ -13,7 +13,7 @@ // the main thread (before any worker threads are spawned) and modify variables // which control the number of threads that are spawned for each action. -#include +#include "pseudo_barrier.h" #include using namespace std; diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp index 70681fd11603..f927e3d9d496 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp @@ -10,7 +10,7 @@ // This test is intended to create a situation in which one thread will be // created while the debugger is stepping in another thread. -#include +#include "pseudo_barrier.h" #include #define do_nothing() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp index a032da835ea6..e41fbebf380d 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp @@ -13,7 +13,7 @@ // breakpoint is hit. The test case should be flexible enough to treat that // as success. -#include +#include "pseudo_barrier.h" #include #include diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp index 45adf28ce813..c7affd2a59ab 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp @@ -10,6 +10,7 @@ // This test is intended to create a situation in which one thread will exit // while the debugger is stepping in another thread. +#include "pseudo_barrier.h" #include #define do_nothing() diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp index c3d695dbc745..d46038109fc2 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp @@ -12,7 +12,7 @@ // the breakpoint in the second thread will be hit while the breakpoint handler // in the first thread is trying to stop all threads. -#include +#include "pseudo_barrier.h" #include pseudo_barrier_t g_barrier; diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp index 31f9a1576b92..ecc0571f2bd3 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp @@ -10,7 +10,7 @@ // This test is intended to create a situation in which two threads are stopped // at a breakpoint and the debugger issues a step-out command. -#include +#include "pseudo_barrier.h" #include pseudo_barrier_t g_barrier; diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp index c57db9f48527..f9508cf6ecca 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp @@ -9,7 +9,7 @@ // This test verifies the correct handling of child thread exits. -#include +#include "pseudo_barrier.h" #include pseudo_barrier_t g_barrier1; diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 0d5254bc0e7a..89ce1d468bd0 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -52,12 +52,12 @@ def _run_adb_command(cmd, device_id): return p.returncode, stdout, stderr -def _target_is_android(): - if not hasattr(_target_is_android, 'result'): +def target_is_android(): + if not hasattr(target_is_android, 'result'): triple = lldb.DBG.GetSelectedPlatform().GetTriple() match = re.match(".*-.*-.*-android", triple) - _target_is_android.result = match is not None - return _target_is_android.result + target_is_android.result = match is not None + return target_is_android.result def android_device_api(): @@ -84,7 +84,7 @@ def android_device_api(): def match_android_device(device_arch, valid_archs=None, valid_api_levels=None): - if not _target_is_android(): + if not target_is_android(): return False if valid_archs is not None and device_arch not in valid_archs: return False @@ -95,7 +95,7 @@ def match_android_device(device_arch, valid_archs=None, valid_api_levels=None): def finalize_build_dictionary(dictionary): - if _target_is_android(): + if target_is_android(): if dictionary is None: dictionary = {} dictionary["OS"] = "Android" diff --git a/lldb/packages/Python/lldbsuite/test/make/Android.rules b/lldb/packages/Python/lldbsuite/test/make/Android.rules index 2ab3b9fde897..634f8660c727 100644 --- a/lldb/packages/Python/lldbsuite/test/make/Android.rules +++ b/lldb/packages/Python/lldbsuite/test/make/Android.rules @@ -72,7 +72,7 @@ ifeq (1,$(USE_LIBCPP)) ARCH_LDFLAGS += \ -L$(NDK_ROOT)/sources/cxx-stl/llvm-libc++/libs/$(STL_ARCH) \ - -l$(NDK_ROOT)/sources/cxx-stl/llvm-libc++/libs/$(STL_ARCH)/libc++.a + $(NDK_ROOT)/sources/cxx-stl/llvm-libc++/libs/$(STL_ARCH)/libc++.a else ARCH_CFLAGS += \ -isystem $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/include \ diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules index 30f3e9c39b07..a7b94ef57380 100644 --- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules @@ -202,7 +202,7 @@ else CFLAGS += $(ARCHFLAG)$(ARCH) $(FRAMEWORK_INCLUDES) $(CFLAGS_EXTRAS) -I$(LLDB_BASE_DIR)include endif -CFLAGS += -include $(THIS_FILE_DIR)test_common.h $(ARCH_CFLAGS) +CFLAGS += -include $(THIS_FILE_DIR)test_common.h -I$(THIS_FILE_DIR) $(ARCH_CFLAGS) # Use this one if you want to build one part of the result without debug information: ifeq "$(OS)" "Darwin" @@ -324,23 +324,21 @@ ifeq (1,$(USE_LIBSTDCPP)) endif ifeq (1,$(USE_LIBCPP)) - # Clang requires an extra flag: -stdlib=libstdc++ - ifneq (,$(findstring clang,$(CC))) - CXXFLAGS += -DLLDB_USING_LIBCPP - ifeq "$(OS)" "Linux" - # This is the default install location on Ubuntu 14.04 - ifneq ($(wildcard /usr/include/c++/v1/.),) - CXXFLAGS += -stdlib=libc++ - LDFLAGS += -stdlib=libc++ - CXXFLAGS += -I/usr/include/c++/v1 - endif - else ifeq "$(OS)" "Android" - # Nothing to do, this is already handled in - # Android.rules. - else + CXXFLAGS += -DLLDB_USING_LIBCPP + ifeq "$(OS)" "Linux" + ifneq (,$(findstring clang,$(CC))) CXXFLAGS += -stdlib=libc++ LDFLAGS += -stdlib=libc++ + else + CXXFLAGS += -isystem /usr/include/c++/v1 + LDFLAGS += -lc++ endif + else ifeq "$(OS)" "Android" + # Nothing to do, this is already handled in + # Android.rules. + else + CXXFLAGS += -stdlib=libc++ + LDFLAGS += -stdlib=libc++ endif endif diff --git a/lldb/packages/Python/lldbsuite/test/make/pseudo_barrier.h b/lldb/packages/Python/lldbsuite/test/make/pseudo_barrier.h new file mode 100644 index 000000000000..592000ddea4d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/make/pseudo_barrier.h @@ -0,0 +1,20 @@ +#include + +// Note that although hogging the CPU while waiting for a variable to change +// would be terrible in production code, it's great for testing since it +// avoids a lot of messy context switching to get multiple threads synchronized. + +typedef std::atomic pseudo_barrier_t; +#define pseudo_barrier_wait(barrier) \ + do \ + { \ + --(barrier); \ + while ((barrier).load() > 0) \ + ; \ + } while (0) + +#define pseudo_barrier_init(barrier, count) \ + do \ + { \ + (barrier) = (count); \ + } while (0) diff --git a/lldb/packages/Python/lldbsuite/test/make/test_common.h b/lldb/packages/Python/lldbsuite/test/make/test_common.h index 3ffece26d04d..529d0952ed3e 100644 --- a/lldb/packages/Python/lldbsuite/test/make/test_common.h +++ b/lldb/packages/Python/lldbsuite/test/make/test_common.h @@ -45,34 +45,3 @@ #define lldb_enable_attach() #endif - -#if defined(__APPLE__) && defined(LLDB_USING_LIBSTDCPP) - -// on Darwin, libstdc++ is missing , so this would cause any test to fail building -// since this header file is being included in every C-family test case, we need to not include it -// on Darwin, most tests use libc++ by default, so this will only affect tests that explicitly require libstdc++ - -#else -#ifdef __cplusplus -#include - -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. - -typedef std::atomic pseudo_barrier_t; -#define pseudo_barrier_wait(barrier) \ - do \ - { \ - --(barrier); \ - while ((barrier).load() > 0) \ - ; \ - } while (0) - -#define pseudo_barrier_init(barrier, count) \ - do \ - { \ - (barrier) = (count); \ - } while (0) -#endif // __cplusplus -#endif // defined(__APPLE__) && defined(LLDB_USING_LIBSTDCPP) diff --git a/lldb/packages/Python/lldbsuite/test/test_categories.py b/lldb/packages/Python/lldbsuite/test/test_categories.py index b505f2da747c..2cadd3f28a43 100644 --- a/lldb/packages/Python/lldbsuite/test/test_categories.py +++ b/lldb/packages/Python/lldbsuite/test/test_categories.py @@ -25,6 +25,7 @@ all_categories = { 'dsym': 'Tests that can be run with DSYM debug information', 'gmodules': 'Tests that can be run with -gmodules debug information', 'expression': 'Tests related to the expression parser', + 'libc++': 'Test for libc++ data formatters', 'objc': 'Tests related to the Objective-C programming language support', 'pyapi': 'Tests related to the Python API', 'basic_process': 'Basic process execution sniff tests.',