|
| 1 | +# coding=utf8 |
| 2 | +""" |
| 3 | +Test lldb data formatter subsystem. |
| 4 | +""" |
| 5 | + |
| 6 | + |
| 7 | +import lldb |
| 8 | +from lldbsuite.test.decorators import * |
| 9 | +from lldbsuite.test.lldbtest import * |
| 10 | +from lldbsuite.test import lldbutil |
| 11 | + |
| 12 | + |
| 13 | +class StdStringViewDataFormatterTestCase(TestBase): |
| 14 | + def setUp(self): |
| 15 | + # Call super's setUp(). |
| 16 | + TestBase.setUp(self) |
| 17 | + # Find the line number to break at. |
| 18 | + self.line1 = line_number("main.cpp", "// Set break point at this line.") |
| 19 | + self.line2 = line_number( |
| 20 | + "main.cpp", "// Break here to look at bad string view." |
| 21 | + ) |
| 22 | + |
| 23 | + def do_test(self): |
| 24 | + """Test that that file and class static variables display correctly.""" |
| 25 | + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) |
| 26 | + |
| 27 | + lldbutil.run_break_set_by_file_and_line( |
| 28 | + self, "main.cpp", self.line1, num_expected_locations=-1 |
| 29 | + ) |
| 30 | + lldbutil.run_break_set_by_file_and_line( |
| 31 | + self, "main.cpp", self.line2, num_expected_locations=-1 |
| 32 | + ) |
| 33 | + |
| 34 | + self.runCmd("run", RUN_SUCCEEDED) |
| 35 | + |
| 36 | + # The stop reason of the thread should be breakpoint. |
| 37 | + self.expect( |
| 38 | + "thread list", |
| 39 | + STOPPED_DUE_TO_BREAKPOINT, |
| 40 | + substrs=["stopped", "stop reason = breakpoint"], |
| 41 | + ) |
| 42 | + |
| 43 | + # This is the function to remove the custom formats in order to have a |
| 44 | + # clean slate for the next test case. |
| 45 | + def cleanup(): |
| 46 | + self.runCmd("type format clear", check=False) |
| 47 | + self.runCmd("type summary clear", check=False) |
| 48 | + self.runCmd("type filter clear", check=False) |
| 49 | + self.runCmd("type synth clear", check=False) |
| 50 | + |
| 51 | + # Execute the cleanup function during test case tear down. |
| 52 | + self.addTearDownHook(cleanup) |
| 53 | + |
| 54 | + self.expect_var_path("wempty", type="std::wstring_view", summary='L""') |
| 55 | + self.expect_var_path( |
| 56 | + "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"' |
| 57 | + ) |
| 58 | + self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"') |
| 59 | + self.expect_var_path("empty", type="std::string_view", summary='""') |
| 60 | + self.expect_var_path("q_source", type="std::string", summary='"hello world"') |
| 61 | + self.expect_var_path("q", type="std::string_view", summary='"hello world"') |
| 62 | + self.expect_var_path( |
| 63 | + "Q", |
| 64 | + type="std::string_view", |
| 65 | + summary='"quite a long std::strin with lots of info inside it"', |
| 66 | + ) |
| 67 | + self.expect_var_path( |
| 68 | + "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"' |
| 69 | + ) |
| 70 | + self.expect_var_path( |
| 71 | + "IHaveEmbeddedZerosToo", |
| 72 | + type="std::wstring_view", |
| 73 | + summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', |
| 74 | + ) |
| 75 | + self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') |
| 76 | + self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') |
| 77 | + self.expect_var_path( |
| 78 | + "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' |
| 79 | + ) |
| 80 | + self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""') |
| 81 | + self.expect_var_path( |
| 82 | + "oops", type="std::string_view", summary='"Hellooo World\\n"' |
| 83 | + ) |
| 84 | + |
| 85 | + # GetSummary returns None so can't be checked by expect_var_path, so we |
| 86 | + # use the str representation instead |
| 87 | + null_obj = self.frame().GetValueForVariablePath("null_str") |
| 88 | + self.assertEqual(null_obj.GetSummary(), "Summary Unavailable") |
| 89 | + self.assertEqual(str(null_obj), "(std::string_view *) null_str = nullptr") |
| 90 | + |
| 91 | + self.runCmd("n") |
| 92 | + |
| 93 | + TheVeryLongOne = self.frame().FindVariable("TheVeryLongOne") |
| 94 | + summaryOptions = lldb.SBTypeSummaryOptions() |
| 95 | + summaryOptions.SetCapping(lldb.eTypeSummaryUncapped) |
| 96 | + uncappedSummaryStream = lldb.SBStream() |
| 97 | + TheVeryLongOne.GetSummary(uncappedSummaryStream, summaryOptions) |
| 98 | + uncappedSummary = uncappedSummaryStream.GetData() |
| 99 | + self.assertGreater( |
| 100 | + uncappedSummary.find("someText"), |
| 101 | + 0, |
| 102 | + "uncappedSummary does not include the full string", |
| 103 | + ) |
| 104 | + summaryOptions.SetCapping(lldb.eTypeSummaryCapped) |
| 105 | + cappedSummaryStream = lldb.SBStream() |
| 106 | + TheVeryLongOne.GetSummary(cappedSummaryStream, summaryOptions) |
| 107 | + cappedSummary = cappedSummaryStream.GetData() |
| 108 | + self.assertLessEqual( |
| 109 | + cappedSummary.find("someText"), 0, "cappedSummary includes the full string" |
| 110 | + ) |
| 111 | + |
| 112 | + self.expect_expr( |
| 113 | + "s", |
| 114 | + result_type="std::wstring_view", |
| 115 | + result_summary='L"hello world! מזל טוב!"', |
| 116 | + ) |
| 117 | + |
| 118 | + self.expect_var_path("wempty", type="std::wstring_view", summary='L""') |
| 119 | + self.expect_var_path( |
| 120 | + "s", type="std::wstring_view", summary='L"hello world! מזל טוב!"' |
| 121 | + ) |
| 122 | + self.expect_var_path("S", type="std::wstring_view", summary='L"!!!!"') |
| 123 | + self.expect_var_path("empty", type="std::string_view", summary='""') |
| 124 | + self.expect_var_path("q_source", type="std::string", summary='"Hello world"') |
| 125 | + self.expect_var_path("q", type="std::string_view", summary='"Hello world"') |
| 126 | + self.expect_var_path( |
| 127 | + "Q", |
| 128 | + type="std::string_view", |
| 129 | + summary='"quite a long std::strin with lots of info inside it"', |
| 130 | + ) |
| 131 | + self.expect_var_path( |
| 132 | + "IHaveEmbeddedZeros", type="std::string_view", summary='"a\\0b\\0c\\0d"' |
| 133 | + ) |
| 134 | + self.expect_var_path( |
| 135 | + "IHaveEmbeddedZerosToo", |
| 136 | + type="std::wstring_view", |
| 137 | + summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"', |
| 138 | + ) |
| 139 | + self.expect_var_path("u16_string", type="std::u16string_view", summary='u"ß水氶"') |
| 140 | + self.expect_var_path("u16_empty", type="std::u16string_view", summary='u""') |
| 141 | + self.expect_var_path( |
| 142 | + "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"' |
| 143 | + ) |
| 144 | + self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""') |
| 145 | + |
| 146 | + self.runCmd("cont") |
| 147 | + self.expect( |
| 148 | + "thread list", |
| 149 | + STOPPED_DUE_TO_BREAKPOINT, |
| 150 | + substrs=["stopped", "stop reason = breakpoint"], |
| 151 | + ) |
| 152 | + |
| 153 | + broken_obj = self.frame().GetValueForVariablePath("in_str_view") |
| 154 | + self.assertEqual(broken_obj.GetSummary(), "Summary Unavailable") |
| 155 | + |
| 156 | + @expectedFailureAll( |
| 157 | + bugnumber="llvm.org/pr36109", debug_info="gmodules", triple=".*-android" |
| 158 | + ) |
| 159 | + # Inline namespace is randomly ignored as Clang due to broken lookup inside |
| 160 | + # the std namespace. |
| 161 | + @expectedFailureAll(debug_info="gmodules") |
| 162 | + @add_test_categories(["libc++"]) |
| 163 | + def test_libcxx(self): |
| 164 | + self.build(dictionary={"USE_LIBCPP" : 1}) |
| 165 | + self.do_test() |
0 commit comments