From 07ee63fa3f707507d332e52626ac109f2e1829f1 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 8 Jul 2025 18:30:16 +0100 Subject: [PATCH 1/4] [lldb][test] Move std::string_view from libcxx to generic directory This just moves the test from `libcxx` to `generic`. There are currently no `std::queue` formatters for libstdc++ so I didn't add a test-case for it. Split out from https://github.com/llvm/llvm-project/pull/146740 --- .../TestDataFormatterLibcxxStringView.py | 0 .../generic/string_view/Makefile | 4 + .../TestDataFormatterStdStringView.py | 165 ++++++++++++++++++ .../{libcxx => generic}/string_view/main.cpp | 0 .../libcxx/string_view/Makefile | 6 - 5 files changed, 169 insertions(+), 6 deletions(-) rename lldb/test/API/functionalities/data-formatter/data-formatter-stl/{libcxx/string_view => generic/string}/TestDataFormatterLibcxxStringView.py (100%) create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/Makefile create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py rename lldb/test/API/functionalities/data-formatter/data-formatter-stl/{libcxx => generic}/string_view/main.cpp (100%) delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/Makefile diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterLibcxxStringView.py similarity index 100% rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterLibcxxStringView.py diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/Makefile new file mode 100644 index 0000000000000..d5f5fec8441b5 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +CXXFLAGS_EXTRAS := -std=c++17 + +include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py new file mode 100644 index 0000000000000..fb934130f663f --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py @@ -0,0 +1,165 @@ +# coding=utf8 +""" +Test lldb data formatter subsystem. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class StdStringViewDataFormatterTestCase(TestBase): + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line1 = line_number("main.cpp", "// Set break point at this line.") + self.line2 = line_number( + "main.cpp", "// Break here to look at bad string view." + ) + + def do_test(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line1, num_expected_locations=-1 + ) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line2, num_expected_locations=-1 + ) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=["stopped", "stop reason = breakpoint"], + ) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + 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.expect_var_path("wempty", type="std::wstring_view", summary='L""') + self.expect_var_path( + "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"' + ) + self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"') + self.expect_var_path("empty", type="std::string_view", summary='""') + self.expect_var_path("q_source", type="std::string", summary='"hello world"') + self.expect_var_path("q", type="std::string_view", summary='"hello world"') + self.expect_var_path( + "Q", + type="std::string_view", + summary='"quite a long std::strin with lots of info inside it"', + ) + self.expect_var_path( + "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"' + ) + self.expect_var_path( + "IHaveEmbeddedZerosToo", + type="std::wstring_view", + summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', + ) + self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') + self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') + self.expect_var_path( + "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' + ) + self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""') + self.expect_var_path( + "oops", type="std::string_view", summary='"Hellooo World\\n"' + ) + + # GetSummary returns None so can't be checked by expect_var_path, so we + # use the str representation instead + null_obj = self.frame().GetValueForVariablePath("null_str") + self.assertEqual(null_obj.GetSummary(), "Summary Unavailable") + self.assertEqual(str(null_obj), "(std::string_view *) null_str = nullptr") + + self.runCmd("n") + + TheVeryLongOne = self.frame().FindVariable("TheVeryLongOne") + summaryOptions = lldb.SBTypeSummaryOptions() + summaryOptions.SetCapping(lldb.eTypeSummaryUncapped) + uncappedSummaryStream = lldb.SBStream() + TheVeryLongOne.GetSummary(uncappedSummaryStream, summaryOptions) + uncappedSummary = uncappedSummaryStream.GetData() + self.assertGreater( + uncappedSummary.find("someText"), + 0, + "uncappedSummary does not include the full string", + ) + summaryOptions.SetCapping(lldb.eTypeSummaryCapped) + cappedSummaryStream = lldb.SBStream() + TheVeryLongOne.GetSummary(cappedSummaryStream, summaryOptions) + cappedSummary = cappedSummaryStream.GetData() + self.assertLessEqual( + cappedSummary.find("someText"), 0, "cappedSummary includes the full string" + ) + + self.expect_expr( + "s", + result_type="std::wstring_view", + result_summary='L"hello world! מזל טוב!"', + ) + + self.expect_var_path("wempty", type="std::wstring_view", summary='L""') + self.expect_var_path( + "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"' + ) + self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"') + self.expect_var_path("empty", type="std::string_view", summary='""') + self.expect_var_path("q_source", type="std::string", summary='"Hello world"') + self.expect_var_path("q", type="std::string_view", summary='"Hello world"') + self.expect_var_path( + "Q", + type="std::string_view", + summary='"quite a long std::strin with lots of info inside it"', + ) + self.expect_var_path( + "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"' + ) + self.expect_var_path( + "IHaveEmbeddedZerosToo", + type="std::wstring_view", + summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', + ) + self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') + self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') + self.expect_var_path( + "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' + ) + self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""') + + self.runCmd("cont") + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=["stopped", "stop reason = breakpoint"], + ) + + broken_obj = self.frame().GetValueForVariablePath("in_str_view") + self.assertEqual(broken_obj.GetSummary(), "Summary Unavailable") + + @expectedFailureAll( + bugnumber="llvm.org/pr36109", debug_info="gmodules", triple=".*-android" + ) + # Inline namespace is randomly ignored as Clang due to broken lookup inside + # the std namespace. + @expectedFailureAll(debug_info="gmodules") + @add_test_categories(["libc++"]) + def test_libcxx(self): + self.build(dictionary={"USE_LIBCPP" : 1}) + self.do_test() diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/main.cpp similarity index 100% rename from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/main.cpp rename to lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/main.cpp diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/Makefile deleted file mode 100644 index c7c91da728d1e..0000000000000 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -CXX_SOURCES := main.cpp - -USE_LIBCPP := 1 - -CXXFLAGS_EXTRAS := -std=c++11 -O0 -include Makefile.rules From 9d42b2f7128c55afee940458983f502176fb7d39 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 9 Jul 2025 11:43:43 +0100 Subject: [PATCH 2/4] fixup! remove redundant file --- .../TestDataFormatterLibcxxStringView.py | 162 ------------------ 1 file changed, 162 deletions(-) delete mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterLibcxxStringView.py diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterLibcxxStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterLibcxxStringView.py deleted file mode 100644 index 3883395f23924..0000000000000 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterLibcxxStringView.py +++ /dev/null @@ -1,162 +0,0 @@ -# coding=utf8 -""" -Test lldb data formatter subsystem. -""" - - -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class LibcxxStringViewDataFormatterTestCase(TestBase): - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line number to break at. - self.line1 = line_number("main.cpp", "// Set break point at this line.") - self.line2 = line_number( - "main.cpp", "// Break here to look at bad string view." - ) - - @add_test_categories(["libc++"]) - @expectedFailureAll( - bugnumber="llvm.org/pr36109", debug_info="gmodules", triple=".*-android" - ) - # Inline namespace is randomly ignored as Clang due to broken lookup inside - # the std namespace. - @expectedFailureAll(debug_info="gmodules") - def test_with_run_command(self): - """Test that that file and class static variables display correctly.""" - self.build() - self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) - - lldbutil.run_break_set_by_file_and_line( - self, "main.cpp", self.line1, num_expected_locations=-1 - ) - lldbutil.run_break_set_by_file_and_line( - self, "main.cpp", self.line2, num_expected_locations=-1 - ) - - self.runCmd("run", RUN_SUCCEEDED) - - # The stop reason of the thread should be breakpoint. - self.expect( - "thread list", - STOPPED_DUE_TO_BREAKPOINT, - substrs=["stopped", "stop reason = breakpoint"], - ) - - # This is the function to remove the custom formats in order to have a - # clean slate for the next test case. - 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.expect_var_path("wempty", type="std::wstring_view", summary='L""') - self.expect_var_path( - "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"' - ) - self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"') - self.expect_var_path("empty", type="std::string_view", summary='""') - self.expect_var_path("q_source", type="std::string", summary='"hello world"') - self.expect_var_path("q", type="std::string_view", summary='"hello world"') - self.expect_var_path( - "Q", - type="std::string_view", - summary='"quite a long std::strin with lots of info inside it"', - ) - self.expect_var_path( - "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"' - ) - self.expect_var_path( - "IHaveEmbeddedZerosToo", - type="std::wstring_view", - summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', - ) - self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') - self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') - self.expect_var_path( - "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' - ) - self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""') - self.expect_var_path( - "oops", type="std::string_view", summary='"Hellooo World\\n"' - ) - - # GetSummary returns None so can't be checked by expect_var_path, so we - # use the str representation instead - null_obj = self.frame().GetValueForVariablePath("null_str") - self.assertEqual(null_obj.GetSummary(), "Summary Unavailable") - self.assertEqual(str(null_obj), "(std::string_view *) null_str = nullptr") - - self.runCmd("n") - - TheVeryLongOne = self.frame().FindVariable("TheVeryLongOne") - summaryOptions = lldb.SBTypeSummaryOptions() - summaryOptions.SetCapping(lldb.eTypeSummaryUncapped) - uncappedSummaryStream = lldb.SBStream() - TheVeryLongOne.GetSummary(uncappedSummaryStream, summaryOptions) - uncappedSummary = uncappedSummaryStream.GetData() - self.assertGreater( - uncappedSummary.find("someText"), - 0, - "uncappedSummary does not include the full string", - ) - summaryOptions.SetCapping(lldb.eTypeSummaryCapped) - cappedSummaryStream = lldb.SBStream() - TheVeryLongOne.GetSummary(cappedSummaryStream, summaryOptions) - cappedSummary = cappedSummaryStream.GetData() - self.assertLessEqual( - cappedSummary.find("someText"), 0, "cappedSummary includes the full string" - ) - - self.expect_expr( - "s", - result_type="std::wstring_view", - result_summary='L"hello world! מזל טוב!"', - ) - - self.expect_var_path("wempty", type="std::wstring_view", summary='L""') - self.expect_var_path( - "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"' - ) - self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"') - self.expect_var_path("empty", type="std::string_view", summary='""') - self.expect_var_path("q_source", type="std::string", summary='"Hello world"') - self.expect_var_path("q", type="std::string_view", summary='"Hello world"') - self.expect_var_path( - "Q", - type="std::string_view", - summary='"quite a long std::strin with lots of info inside it"', - ) - self.expect_var_path( - "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"' - ) - self.expect_var_path( - "IHaveEmbeddedZerosToo", - type="std::wstring_view", - summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', - ) - self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') - self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') - self.expect_var_path( - "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' - ) - self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""') - - self.runCmd("cont") - self.expect( - "thread list", - STOPPED_DUE_TO_BREAKPOINT, - substrs=["stopped", "stop reason = breakpoint"], - ) - - broken_obj = self.frame().GetValueForVariablePath("in_str_view") - self.assertEqual(broken_obj.GetSummary(), "Summary Unavailable") From 3e5a24c00157e55960b275d0ab9cbd05e1e5c3ab Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 9 Jul 2025 11:50:50 +0100 Subject: [PATCH 3/4] fixup! python format --- .../string_view/TestDataFormatterStdStringView.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py index fb934130f663f..b57b95d3ca6d5 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py @@ -72,7 +72,9 @@ def cleanup(): type="std::wstring_view", summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', ) - self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') + self.expect_var_path( + "u16_string", type="std::u16string_view", summary='u"ß水氶"' + ) self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') self.expect_var_path( "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' @@ -136,7 +138,9 @@ def cleanup(): type="std::wstring_view", summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', ) - self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') + self.expect_var_path( + "u16_string", type="std::u16string_view", summary='u"ß水氶"' + ) self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') self.expect_var_path( "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' @@ -161,5 +165,5 @@ def cleanup(): @expectedFailureAll(debug_info="gmodules") @add_test_categories(["libc++"]) def test_libcxx(self): - self.build(dictionary={"USE_LIBCPP" : 1}) + self.build(dictionary={"USE_LIBCPP": 1}) self.do_test() From ab53e65e1f5eb8387af8e890849ab4bef296977a Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 9 Jul 2025 13:02:12 +0100 Subject: [PATCH 4/4] fixup! python format --- .../generic/string_view/TestDataFormatterStdStringView.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py index b57b95d3ca6d5..8c053f0843f9b 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py @@ -72,9 +72,7 @@ def cleanup(): type="std::wstring_view", summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', ) - self.expect_var_path( - "u16_string", type="std::u16string_view", summary='u"ß水氶"' - ) + self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') self.expect_var_path( "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' @@ -138,9 +136,7 @@ def cleanup(): type="std::wstring_view", summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', ) - self.expect_var_path( - "u16_string", type="std::u16string_view", summary='u"ß水氶"' - ) + self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') self.expect_var_path( "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"'