forked from OSchip/llvm-project
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
This commit is contained in:
parent
32093a1c28
commit
01a28ca7f8
|
@ -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
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
// This test verifies the correct handling of child thread exits.
|
||||
|
||||
#include <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <thread>
|
||||
#include <csignal>
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
// This test verifies the correct handling of child thread exits.
|
||||
|
||||
#include <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <thread>
|
||||
#include <csignal>
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// breakpoint is hit. The test case should be flexible enough to treat that
|
||||
// as success.
|
||||
|
||||
#include <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
|
|
|
@ -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 <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
|
|
|
@ -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 <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <thread>
|
||||
|
||||
#define do_nothing()
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// breakpoint is hit. The test case should be flexible enough to treat that
|
||||
// as success.
|
||||
|
||||
#include <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
|
|
|
@ -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 <thread>
|
||||
|
||||
#define do_nothing()
|
||||
|
|
|
@ -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 <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <thread>
|
||||
|
||||
pseudo_barrier_t g_barrier;
|
||||
|
|
|
@ -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 <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <thread>
|
||||
|
||||
pseudo_barrier_t g_barrier;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
// This test verifies the correct handling of child thread exits.
|
||||
|
||||
#include <atomic>
|
||||
#include "pseudo_barrier.h"
|
||||
#include <thread>
|
||||
|
||||
pseudo_barrier_t g_barrier1;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#include <atomic>
|
||||
|
||||
// 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<int> 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)
|
|
@ -45,34 +45,3 @@
|
|||
#define lldb_enable_attach()
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(LLDB_USING_LIBSTDCPP)
|
||||
|
||||
// on Darwin, libstdc++ is missing <atomic>, 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 <atomic>
|
||||
|
||||
// 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<int> 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)
|
||||
|
|
|
@ -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.',
|
||||
|
|
Loading…
Reference in New Issue