[lldb][test] Combine libstdc++ and libc++ std::variant tests into generic test (#147253)
This combines the libc++ and libstdc++ test cases. The libstdc++ test had an additional test-case for "reference to typedef". So I added those to the generic test. The rest of the tests was the same as libc++. I also moved the test-case for checking invalid variant indexes into a separate libstdcpp test because it relied on the layout of the libstdc++ type. We should probably rewrite it in the "simulator" style. But for now I just moved it. This also removes some redundant checks for libc++ versions and existence of the `variant` header, which at this point should be available anywhere these tests are run. Split out from https://github.com/llvm/llvm-project/pull/146740
This commit is contained in:
parent
e4d00683c3
commit
d9b208b4d3
@ -1,6 +1,4 @@
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
USE_LIBCPP := 1
|
||||
|
||||
CXXFLAGS_EXTRAS := -std=c++17
|
||||
|
||||
include Makefile.rules
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
Test lldb data formatter for LibStdC++ std::variant.
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
import lldb
|
||||
@ -8,18 +8,23 @@ from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class LibStdcxxVariantDataFormatterTestCase(TestBase):
|
||||
@add_test_categories(["libstdcxx"])
|
||||
def test_with_run_command(self):
|
||||
"""Test LibStdC++ std::variant data formatter works correctly."""
|
||||
self.build()
|
||||
class StdVariantDataFormatterTestCase(TestBase):
|
||||
def do_test(self):
|
||||
"""Test that that file and class static variables display correctly."""
|
||||
|
||||
def cleanup():
|
||||
self.runCmd("type format clear", check=False)
|
||||
self.runCmd("type summary clear", check=False)
|
||||
self.runCmd("type filter clear", check=False)
|
||||
self.runCmd("type synth clear", check=False)
|
||||
|
||||
# Execute the cleanup function during test case tear down.
|
||||
self.addTearDownHook(cleanup)
|
||||
|
||||
(self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||
self, "// break here", lldb.SBFileSpec("main.cpp", False)
|
||||
)
|
||||
|
||||
lldbutil.continue_to_breakpoint(self.process, bkpt)
|
||||
|
||||
for name in ["v1", "v1_typedef"]:
|
||||
self.expect(
|
||||
"frame variable " + name,
|
||||
@ -65,32 +70,16 @@ class LibStdcxxVariantDataFormatterTestCase(TestBase):
|
||||
self.expect("frame variable v_valueless", substrs=["v_valueless = No Value"])
|
||||
|
||||
self.expect(
|
||||
"frame variable v_many_types_valueless",
|
||||
substrs=["v_many_types_valueless = No Value"],
|
||||
"frame variable v_300_types_valueless",
|
||||
substrs=["v_300_types_valueless = No Value"],
|
||||
)
|
||||
|
||||
@add_test_categories(["libc++"])
|
||||
def test_libcxx(self):
|
||||
self.build(dictionary={"USE_LIBCPP": 1})
|
||||
self.do_test()
|
||||
|
||||
@add_test_categories(["libstdcxx"])
|
||||
def test_invalid_variant_index(self):
|
||||
"""Test LibStdC++ data formatter for std::variant with invalid index."""
|
||||
self.build()
|
||||
|
||||
(self.target, self.process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||
self, "// break here", lldb.SBFileSpec("main.cpp", False)
|
||||
)
|
||||
|
||||
lldbutil.continue_to_breakpoint(self.process, bkpt)
|
||||
|
||||
self.expect(
|
||||
"frame variable v1",
|
||||
substrs=["v1 = Active Type = int {", "Value = 12", "}"],
|
||||
)
|
||||
|
||||
var_v1 = thread.frames[0].FindVariable("v1")
|
||||
var_v1_raw_obj = var_v1.GetNonSyntheticValue()
|
||||
index_obj = var_v1_raw_obj.GetChildMemberWithName("_M_index")
|
||||
self.assertTrue(index_obj and index_obj.IsValid())
|
||||
|
||||
INVALID_INDEX = "100"
|
||||
index_obj.SetValueFromCString(INVALID_INDEX)
|
||||
|
||||
self.expect("frame variable v1", substrs=["v1 = <Invalid>"])
|
||||
def test_libstdcxx(self):
|
||||
self.build(dictionary={"USE_LIBSTDCPP": 1})
|
||||
self.do_test()
|
@ -10,12 +10,9 @@ struct S {
|
||||
};
|
||||
|
||||
int main() {
|
||||
bool has_variant = true;
|
||||
|
||||
printf("%d\n", has_variant); // break here
|
||||
|
||||
std::variant<int, double, char> v1;
|
||||
std::variant<int, double, char> &v1_ref = v1;
|
||||
|
||||
using V1_typedef = std::variant<int, double, char>;
|
||||
V1_typedef v1_typedef;
|
||||
V1_typedef &v1_typedef_ref = v1_typedef;
|
||||
@ -24,7 +21,7 @@ int main() {
|
||||
std::variant<int, double, char> v3;
|
||||
std::variant<std::variant<int, double, char>> v_v1;
|
||||
std::variant<int, char, S> v_valueless = 5;
|
||||
// The next variant has many types, meaning the type index does not fit in
|
||||
// The next variant has 300 types, meaning the type index does not fit in
|
||||
// a byte and must be `unsigned short` instead of `unsigned char` when
|
||||
// using the unstable libc++ ABI. With stable libc++ ABI, the type index
|
||||
// is always just `unsigned int`.
|
||||
@ -45,11 +42,15 @@ int main() {
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, S>
|
||||
v_many_types_valueless;
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
S>
|
||||
v_300_types_valueless;
|
||||
|
||||
v_valueless = 5;
|
||||
v_many_types_valueless.emplace<0>(10);
|
||||
v_300_types_valueless.emplace<0>(10);
|
||||
|
||||
v1 = 12; // v contains int
|
||||
v1_typedef = v1;
|
||||
@ -83,11 +84,11 @@ int main() {
|
||||
try {
|
||||
// Exception in move-assignment is guaranteed to put std::variant into a
|
||||
// valueless state.
|
||||
v_many_types_valueless = S();
|
||||
v_300_types_valueless = S();
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
printf("%d\n", v_many_types_valueless.valueless_by_exception());
|
||||
printf("%d\n", v_300_types_valueless.valueless_by_exception());
|
||||
|
||||
return 0; // break here
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
"""
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class LibcxxVariantDataFormatterTestCase(TestBase):
|
||||
@add_test_categories(["libc++"])
|
||||
## Clang 7.0 is the oldest Clang that can reliably parse newer libc++ versions
|
||||
## with -std=c++17.
|
||||
@skipIf(
|
||||
oslist=no_match(["macosx"]), compiler="clang", compiler_version=["<", "7.0"]
|
||||
)
|
||||
## We are skipping gcc version less that 5.1 since this test requires -std=c++17
|
||||
@skipIf(compiler="gcc", compiler_version=["<", "5.1"])
|
||||
## std::get is unavailable for std::variant before macOS 10.14
|
||||
@skipIf(macos_version=["<", "10.14"])
|
||||
def test_with_run_command(self):
|
||||
"""Test that that file and class static variables display correctly."""
|
||||
self.build()
|
||||
|
||||
(self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||
self, "// break here", lldb.SBFileSpec("main.cpp", False)
|
||||
)
|
||||
|
||||
self.runCmd("frame variable has_variant")
|
||||
|
||||
output = self.res.GetOutput()
|
||||
|
||||
## The variable has_variant tells us if the test program
|
||||
## detected we have a sufficient libc++ version to support variant
|
||||
## false means we do not and therefore should skip the test
|
||||
if output.find("(bool) has_variant = false") != -1:
|
||||
self.skipTest("std::variant not supported")
|
||||
|
||||
lldbutil.continue_to_breakpoint(self.process, bkpt)
|
||||
|
||||
self.expect(
|
||||
"frame variable v1",
|
||||
substrs=["v1 = Active Type = int {", "Value = 12", "}"],
|
||||
)
|
||||
|
||||
self.expect(
|
||||
"frame variable v1_ref",
|
||||
patterns=["v1_ref = 0x.* Active Type = int : {", "Value = 12", "}"],
|
||||
)
|
||||
|
||||
self.expect(
|
||||
"frame variable v_v1",
|
||||
substrs=[
|
||||
"v_v1 = Active Type = std::variant<int, double, char> {",
|
||||
"Value = Active Type = int {",
|
||||
"Value = 12",
|
||||
"}",
|
||||
"}",
|
||||
],
|
||||
)
|
||||
|
||||
lldbutil.continue_to_breakpoint(self.process, bkpt)
|
||||
|
||||
self.expect(
|
||||
"frame variable v1",
|
||||
substrs=["v1 = Active Type = double {", "Value = 2", "}"],
|
||||
)
|
||||
|
||||
lldbutil.continue_to_breakpoint(self.process, bkpt)
|
||||
|
||||
self.expect(
|
||||
"frame variable v2",
|
||||
substrs=["v2 = Active Type = double {", "Value = 2", "}"],
|
||||
)
|
||||
|
||||
self.expect(
|
||||
"frame variable v3",
|
||||
substrs=["v3 = Active Type = char {", "Value = 'A'", "}"],
|
||||
)
|
||||
|
||||
self.expect("frame variable v_no_value", substrs=["v_no_value = No Value"])
|
||||
|
||||
self.expect(
|
||||
"frame variable v_300_types_no_value",
|
||||
substrs=["v_300_types_no_value = No Value"],
|
||||
)
|
@ -1,95 +0,0 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// If we have libc++ 4.0 or greater we should have <variant>
|
||||
// According to libc++ C++1z status page https://libcxx.llvm.org/cxx1z_status.html
|
||||
#if _LIBCPP_VERSION >= 4000
|
||||
#include <variant>
|
||||
#define HAVE_VARIANT 1
|
||||
#else
|
||||
#define HAVE_VARIANT 0
|
||||
#endif
|
||||
|
||||
struct S {
|
||||
operator int() { throw 42; }
|
||||
} ;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
bool has_variant = HAVE_VARIANT ;
|
||||
|
||||
printf( "%d\n", has_variant ) ; // break here
|
||||
|
||||
#if HAVE_VARIANT == 1
|
||||
std::variant<int, double, char> v1;
|
||||
std::variant<int, double, char> &v1_ref = v1;
|
||||
std::variant<int, double, char> v2;
|
||||
std::variant<int, double, char> v3;
|
||||
std::variant<std::variant<int,double,char>> v_v1 ;
|
||||
std::variant<int, double, char> v_no_value;
|
||||
// The next variant has 300 types, meaning the type index does not fit in
|
||||
// a byte and must be `unsigned short` instead of `unsigned char` when
|
||||
// using the unstable libc++ ABI. With stable libc++ ABI, the type index
|
||||
// is always just `unsigned int`.
|
||||
std::variant<
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int>
|
||||
v_300_types_no_value;
|
||||
|
||||
v1 = 12; // v contains int
|
||||
v_v1 = v1 ;
|
||||
int i = std::get<int>(v1);
|
||||
printf( "%d\n", i ); // break here
|
||||
|
||||
v2 = 2.0 ;
|
||||
double d = std::get<double>(v2) ;
|
||||
printf( "%f\n", d );
|
||||
|
||||
v3 = 'A' ;
|
||||
char c = std::get<char>(v3) ;
|
||||
printf( "%d\n", c );
|
||||
|
||||
// Checking v1 above and here to make sure we done maintain the incorrect
|
||||
// state when we change its value.
|
||||
v1 = 2.0;
|
||||
d = std::get<double>(v1) ;
|
||||
printf( "%f\n", d ); // break here
|
||||
|
||||
try {
|
||||
v_no_value.emplace<0>(S());
|
||||
} catch( ... ) {}
|
||||
|
||||
printf( "%zu\n", v_no_value.index() ) ;
|
||||
|
||||
try {
|
||||
v_300_types_no_value.emplace<0>(S());
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
printf("%zu\n", v_300_types_no_value.index());
|
||||
#endif
|
||||
|
||||
return 0; // break here
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
USE_LIBSTDCPP := 1
|
||||
CXXFLAGS_EXTRAS := -std=c++17
|
||||
USE_LIBSTDCPP := 1
|
||||
|
||||
include Makefile.rules
|
@ -0,0 +1,30 @@
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class InvalidStdVariantDataFormatterTestCase(TestBase):
|
||||
@add_test_categories(["libstdcxx"])
|
||||
def test(self):
|
||||
"""Test STL data formatters for std::variant with invalid index."""
|
||||
self.build()
|
||||
|
||||
(_, _, thread, _) = lldbutil.run_to_source_breakpoint(
|
||||
self, "// break here", lldb.SBFileSpec("main.cpp", False)
|
||||
)
|
||||
|
||||
self.expect(
|
||||
"frame variable v1",
|
||||
substrs=["v1 = Active Type = char {", "Value = 'x'", "}"],
|
||||
)
|
||||
|
||||
var_v1 = thread.frames[0].FindVariable("v1")
|
||||
var_v1_raw_obj = var_v1.GetNonSyntheticValue()
|
||||
index_obj = var_v1_raw_obj.GetChildMemberWithName("_M_index")
|
||||
self.assertTrue(index_obj and index_obj.IsValid())
|
||||
|
||||
INVALID_INDEX = "100"
|
||||
index_obj.SetValueFromCString(INVALID_INDEX)
|
||||
|
||||
self.expect("frame variable v1", substrs=["v1 = <Invalid>"])
|
@ -0,0 +1,11 @@
|
||||
#include <cstdio>
|
||||
#include <variant>
|
||||
|
||||
int main() {
|
||||
std::variant<int, double, char> v1;
|
||||
v1 = 'x';
|
||||
|
||||
std::puts("// break here");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user