1# coding=utf8 2""" 3Test lldb data formatter subsystem. 4""" 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class LibcxxStringDataFormatterTestCase(TestBase): 14 def setUp(self): 15 # Call super's setUp(). 16 TestBase.setUp(self) 17 # Find the line number to break at. 18 self.main_spec = lldb.SBFileSpec("main.cpp") 19 self.namespace = "std" 20 21 @add_test_categories(["libc++"]) 22 @expectedFailureAll( 23 bugnumber="llvm.org/pr36109", debug_info="gmodules", triple=".*-android" 24 ) 25 # Inline namespace is randomly ignored as Clang due to broken lookup inside 26 # the std namespace. 27 @expectedFailureAll(debug_info="gmodules") 28 def test_with_run_command(self): 29 """Test that that file and class static variables display correctly.""" 30 self.build() 31 32 (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 33 self, "Set break point at this line.", self.main_spec 34 ) 35 frame = thread.frames[0] 36 37 # This is the function to remove the custom formats in order to have a 38 # clean slate for the next test case. 39 def cleanup(): 40 self.runCmd("type format clear", check=False) 41 self.runCmd("type summary clear", check=False) 42 self.runCmd("type filter clear", check=False) 43 self.runCmd("type synth clear", check=False) 44 self.runCmd("settings set target.max-children-count 256", check=False) 45 46 is_64_bit = self.process().GetAddressByteSize() == 8 47 48 # Execute the cleanup function during test case tear down. 49 self.addTearDownHook(cleanup) 50 51 ns = self.namespace 52 53 self.expect( 54 "frame variable", 55 substrs=[ 56 '(%s::wstring) wempty = L""' % ns, 57 '(%s::wstring) s = L"hello world! מזל טוב!"' % ns, 58 '(%s::wstring) S = L"!!!!"' % ns, 59 "(const wchar_t *) mazeltov = 0x", 60 'L"מזל טוב"', 61 '(%s::string) empty = ""' % ns, 62 '(%s::string) q = "hello world"' % ns, 63 '(%s::string) Q = "quite a long std::strin with lots of info inside it"' 64 % ns, 65 '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"' % ns, 66 '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"' 67 % ns, 68 '(%s::u16string) u16_string = u"ß水氶"' % ns, 69 # FIXME: This should have a 'u' prefix. 70 '(%s::u16string) u16_empty = ""' % ns, 71 '(%s::u32string) u32_string = U""' % ns, 72 # FIXME: This should have a 'U' prefix. 73 '(%s::u32string) u32_empty = ""' % ns, 74 "(%s::string *) null_str = nullptr" % ns, 75 ], 76 ) 77 78 thread.StepOver() 79 80 TheVeryLongOne = frame.FindVariable("TheVeryLongOne") 81 summaryOptions = lldb.SBTypeSummaryOptions() 82 summaryOptions.SetCapping(lldb.eTypeSummaryUncapped) 83 uncappedSummaryStream = lldb.SBStream() 84 TheVeryLongOne.GetSummary(uncappedSummaryStream, summaryOptions) 85 uncappedSummary = uncappedSummaryStream.GetData() 86 self.assertGreater( 87 uncappedSummary.find("someText"), 88 0, 89 "uncappedSummary does not include the full string", 90 ) 91 summaryOptions.SetCapping(lldb.eTypeSummaryCapped) 92 cappedSummaryStream = lldb.SBStream() 93 TheVeryLongOne.GetSummary(cappedSummaryStream, summaryOptions) 94 cappedSummary = cappedSummaryStream.GetData() 95 self.assertLessEqual( 96 cappedSummary.find("someText"), 0, "cappedSummary includes the full string" 97 ) 98 99 self.expect_expr( 100 "s", result_type=ns + "::wstring", result_summary='L"hello world! מזל טוב!"' 101 ) 102 103 self.expect_expr( 104 "q", result_type=ns + "::string", result_summary='"hello world"' 105 ) 106 107 self.expect_expr( 108 "Q", 109 result_type=ns + "::string", 110 result_summary='"quite a long std::strin with lots of info inside it"', 111 ) 112 113 self.expect( 114 "frame variable", 115 substrs=[ 116 '(%s::wstring) S = L"!!!!!"' % ns, 117 "(const wchar_t *) mazeltov = 0x", 118 'L"מזל טוב"', 119 '(%s::string) q = "hello world"' % ns, 120 '(%s::string) Q = "quite a long std::strin with lots of info inside it"' 121 % ns, 122 '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"' % ns, 123 '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"' 124 % ns, 125 '(%s::u16string) u16_string = u"ß水氶"' % ns, 126 '(%s::u32string) u32_string = U""' % ns, 127 '(%s::u32string) u32_empty = ""' % ns, 128 "(%s::string *) null_str = nullptr" % ns, 129 ], 130 ) 131 132 # The test assumes that std::string is in its cap-size-data layout. 133 is_alternate_layout = ( 134 "arm" in self.getArchitecture() 135 ) and self.platformIsDarwin() 136 if is_64_bit and not is_alternate_layout: 137 self.expect( 138 "frame variable garbage1", substrs=["garbage1 = Summary Unavailable"] 139 ) 140 self.expect( 141 "frame variable garbage2", substrs=[r'garbage2 = "\xfa\xfa\xfa\xfa"'] 142 ) 143 self.expect("frame variable garbage3", substrs=[r'garbage3 = "\xf0\xf0"']) 144 self.expect( 145 "frame variable garbage4", substrs=["garbage4 = Summary Unavailable"] 146 ) 147 self.expect( 148 "frame variable garbage5", substrs=["garbage5 = Summary Unavailable"] 149 ) 150 151 # Finally, make sure that if the string is not readable, we give an error: 152 bkpt_2 = target.BreakpointCreateBySourceRegex( 153 "Break here to look at bad string", self.main_spec 154 ) 155 self.assertEqual(bkpt_2.GetNumLocations(), 1, "Got one location") 156 threads = lldbutil.continue_to_breakpoint(process, bkpt_2) 157 self.assertEqual(len(threads), 1, "Stopped at second breakpoint") 158 frame = threads[0].frames[0] 159 var = frame.FindVariable("in_str") 160 self.assertTrue(var.GetError().Success(), "Made variable") 161 summary = var.GetSummary() 162 self.assertEqual(summary, "Summary Unavailable", "No summary for bad value") 163