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