1""" 2Test lldb data formatter subsystem. 3""" 4 5 6import lldb 7from lldbsuite.test.lldbtest import * 8import lldbsuite.test.lldbutil as lldbutil 9 10 11class SynthDataFormatterTestCase(TestBase): 12 def setUp(self): 13 # Call super's setUp(). 14 TestBase.setUp(self) 15 # Find the line number to break at. 16 self.line = line_number("main.cpp", "// Set break point at this line.") 17 18 def test_with_run_command(self): 19 """Test that that file and class static variables display correctly.""" 20 self.build() 21 self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) 22 23 lldbutil.run_break_set_by_file_and_line( 24 self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True 25 ) 26 27 self.runCmd("run", RUN_SUCCEEDED) 28 29 # The stop reason of the thread should be breakpoint. 30 self.expect( 31 "thread list", 32 STOPPED_DUE_TO_BREAKPOINT, 33 substrs=["stopped", "stop reason = breakpoint"], 34 ) 35 36 # This is the function to remove the custom formats in order to have a 37 # clean slate for the next test case. 38 def cleanup(): 39 self.runCmd("type format clear", check=False) 40 self.runCmd("type summary clear", check=False) 41 self.runCmd("type filter clear", check=False) 42 43 # Execute the cleanup function during test case tear down. 44 self.addTearDownHook(cleanup) 45 46 # Pick some values and check that the basics work 47 self.runCmd("type filter add BagOfInts --child x --child z") 48 self.expect("frame variable int_bag", substrs=["x = 6", "z = 8"]) 49 50 # Check we can still access the missing child by summary 51 self.runCmd('type summary add BagOfInts --summary-string "y=${var.y}"') 52 self.expect("frame variable int_bag", substrs=["y=7"]) 53 54 # Even if we have synth children, the summary prevails 55 self.expect( 56 "frame variable int_bag", matching=False, substrs=["x = 6", "z = 8"] 57 ) 58 59 # if we skip synth and summary show y 60 self.expect( 61 "frame variable int_bag --synthetic-type false --no-summary-depth=1", 62 substrs=["x = 6", "y = 7", "z = 8"], 63 ) 64 65 # if we ask for raw output same happens 66 self.expect( 67 "frame variable int_bag --raw-output", substrs=["x = 6", "y = 7", "z = 8"] 68 ) 69 70 # Summary+Synth must work together 71 self.runCmd('type summary add BagOfInts --summary-string "x=${var.x}" -e') 72 self.expect("frame variable int_bag", substrs=["x=6", "x = 6", "z = 8"]) 73 74 # Same output, but using Python 75 self.runCmd( 76 "type summary add BagOfInts --python-script \"return 'x=%s' % valobj.GetChildMemberWithName('x').GetValue()\" -e" 77 ) 78 self.expect("frame variable int_bag", substrs=["x=6", "x = 6", "z = 8"]) 79 80 # If I skip summaries, still give me the artificial children 81 self.expect( 82 "frame variable int_bag --no-summary-depth=1", substrs=["x = 6", "z = 8"] 83 ) 84 85 # Delete synth and check that the view reflects it immediately 86 self.runCmd("type filter delete BagOfInts") 87 self.expect("frame variable int_bag", substrs=["x = 6", "y = 7", "z = 8"]) 88 89 # Add the synth again and check that it's honored deeper in the 90 # hierarchy 91 self.runCmd("type filter add BagOfInts --child x --child z") 92 self.expect( 93 "frame variable bag_bag", 94 substrs=[ 95 "x = x=69 {", 96 "x = 69", 97 "z = 71", 98 "y = x=66 {", 99 "x = 66", 100 "z = 68", 101 ], 102 ) 103 self.expect( 104 "frame variable bag_bag", matching=False, substrs=["y = 70", "y = 67"] 105 ) 106 107 # Check that a synth can expand nested stuff 108 self.runCmd("type filter add BagOfBags --child x.y --child y.z") 109 self.expect("frame variable bag_bag", substrs=["x.y = 70", "y.z = 68"]) 110 111 # ...even if we get -> and . wrong 112 self.runCmd('type filter add BagOfBags --child x.y --child "y->z"') 113 self.expect("frame variable bag_bag", substrs=["x.y = 70", "y->z = 68"]) 114 115 # ...even bitfields 116 self.runCmd('type filter add BagOfBags --child x.y --child "y->z[1-2]"') 117 self.expect( 118 "frame variable bag_bag --show-types", 119 substrs=["x.y = 70", "(int:2) y->z[1-2] = 2"], 120 ) 121 122 # ...even if we format the bitfields 123 self.runCmd('type filter add BagOfBags --child x.y --child "y->y[0-0]"') 124 self.runCmd('type format add "int:1" -f bool') 125 self.expect( 126 "frame variable bag_bag --show-types", 127 substrs=["x.y = 70", "(int:1) y->y[0-0] = true"], 128 ) 129 130 # ...even if we use one-liner summaries 131 self.runCmd("type summary add -c BagOfBags") 132 self.expect( 133 "frame variable bag_bag", 134 substrs=["(BagOfBags) bag_bag = (x.y = 70, y->y[0-0] = true)"], 135 ) 136 137 self.runCmd("type summary delete BagOfBags") 138 139 # now check we are dynamic (and arrays work) 140 self.runCmd( 141 "type filter add Plenty --child bitfield --child array[0] --child array[2]" 142 ) 143 self.expect( 144 "frame variable plenty_of_stuff", 145 substrs=["bitfield = 1", "array[0] = 5", "array[2] = 3"], 146 ) 147 148 self.runCmd("n") 149 self.expect( 150 "frame variable plenty_of_stuff", 151 substrs=["bitfield = 17", "array[0] = 5", "array[2] = 3"], 152 ) 153 154 # skip synthetic children 155 self.expect( 156 "frame variable plenty_of_stuff --synthetic-type no", 157 substrs=["some_values = 0x", "array = 0x", "array_size = 5"], 158 ) 159 160 # check flat printing with synthetic children 161 self.expect( 162 "frame variable plenty_of_stuff --flat", 163 substrs=[ 164 "plenty_of_stuff.bitfield = 17", 165 "*(plenty_of_stuff.array) = 5", 166 "*(plenty_of_stuff.array) = 3", 167 ], 168 ) 169 170 # check that we do not lose location information for our children 171 self.expect( 172 "frame variable plenty_of_stuff --location", 173 substrs=["0x", ": bitfield = 17"], 174 ) 175 176 # check we work across pointer boundaries 177 self.expect( 178 "frame variable plenty_of_stuff.some_values --ptr-depth=1", 179 substrs=["(BagOfInts *) plenty_of_stuff.some_values", "x = 5", "z = 7"], 180 ) 181 182 # but not if we don't want to 183 self.runCmd("type filter add BagOfInts --child x --child z -p") 184 self.expect( 185 "frame variable plenty_of_stuff.some_values --ptr-depth=1", 186 substrs=[ 187 "(BagOfInts *) plenty_of_stuff.some_values", 188 "x = 5", 189 "y = 6", 190 "z = 7", 191 ], 192 ) 193 194 # check we're dynamic even if nested 195 self.runCmd("type filter add BagOfBags --child x.z") 196 self.expect("frame variable bag_bag", substrs=["x.z = 71"]) 197 198 self.runCmd("n") 199 self.expect("frame variable bag_bag", substrs=["x.z = 12"]) 200 201 self.runCmd('type summary add -e -s "I am always empty but have" EmptyStruct') 202 self.expect("frame variable es", substrs=["I am always empty but have {}"]) 203 self.runCmd('type summary add -e -h -s "I am really empty" EmptyStruct') 204 self.expect("frame variable es", substrs=["I am really empty"]) 205 self.expect( 206 "frame variable es", substrs=["I am really empty {}"], matching=False 207 ) 208