1*99451b44SJordan Rupprecht""" 2*99451b44SJordan RupprechtTest lldb data formatter subsystem. 3*99451b44SJordan Rupprecht""" 4*99451b44SJordan Rupprecht 5*99451b44SJordan Rupprechtfrom __future__ import print_function 6*99451b44SJordan Rupprecht 7*99451b44SJordan Rupprecht 8*99451b44SJordan Rupprechtimport lldb 9*99451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 10*99451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 11*99451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 12*99451b44SJordan Rupprecht 13*99451b44SJordan Rupprecht 14*99451b44SJordan Rupprechtclass PythonSynthDataFormatterTestCase(TestBase): 15*99451b44SJordan Rupprecht 16*99451b44SJordan Rupprecht def test_with_run_command(self): 17*99451b44SJordan Rupprecht """Test data formatter commands.""" 18*99451b44SJordan Rupprecht self.build() 19*99451b44SJordan Rupprecht self.data_formatter_commands() 20*99451b44SJordan Rupprecht 21*99451b44SJordan Rupprecht def test_rdar10960550_with_run_command(self): 22*99451b44SJordan Rupprecht """Test data formatter commands.""" 23*99451b44SJordan Rupprecht self.build() 24*99451b44SJordan Rupprecht self.rdar10960550_formatter_commands() 25*99451b44SJordan Rupprecht 26*99451b44SJordan Rupprecht def setUp(self): 27*99451b44SJordan Rupprecht # Call super's setUp(). 28*99451b44SJordan Rupprecht TestBase.setUp(self) 29*99451b44SJordan Rupprecht # Find the line number to break at. 30*99451b44SJordan Rupprecht self.line = line_number('main.cpp', '// Set break point at this line.') 31*99451b44SJordan Rupprecht self.line2 = line_number('main.cpp', 32*99451b44SJordan Rupprecht '// Set cast break point at this line.') 33*99451b44SJordan Rupprecht self.line3 = line_number( 34*99451b44SJordan Rupprecht 'main.cpp', '// Set second cast break point at this line.') 35*99451b44SJordan Rupprecht 36*99451b44SJordan Rupprecht def data_formatter_commands(self): 37*99451b44SJordan Rupprecht """Test using Python synthetic children provider.""" 38*99451b44SJordan Rupprecht 39*99451b44SJordan Rupprecht _, process, thread, _ = lldbutil.run_to_line_breakpoint( 40*99451b44SJordan Rupprecht self, lldb.SBFileSpec("main.cpp"), self.line) 41*99451b44SJordan Rupprecht 42*99451b44SJordan Rupprecht # This is the function to remove the custom formats in order to have a 43*99451b44SJordan Rupprecht # clean slate for the next test case. 44*99451b44SJordan Rupprecht def cleanup(): 45*99451b44SJordan Rupprecht self.runCmd('type format clear', check=False) 46*99451b44SJordan Rupprecht self.runCmd('type summary clear', check=False) 47*99451b44SJordan Rupprecht self.runCmd('type filter clear', check=False) 48*99451b44SJordan Rupprecht self.runCmd('type synth clear', check=False) 49*99451b44SJordan Rupprecht 50*99451b44SJordan Rupprecht # Execute the cleanup function during test case tear down. 51*99451b44SJordan Rupprecht self.addTearDownHook(cleanup) 52*99451b44SJordan Rupprecht 53*99451b44SJordan Rupprecht # print the f00_1 variable without a synth 54*99451b44SJordan Rupprecht self.expect("frame variable f00_1", 55*99451b44SJordan Rupprecht substrs=['a = 1', 56*99451b44SJordan Rupprecht 'b = 2', 57*99451b44SJordan Rupprecht 'r = 34']) 58*99451b44SJordan Rupprecht 59*99451b44SJordan Rupprecht # now set up the synth 60*99451b44SJordan Rupprecht self.runCmd("script from fooSynthProvider import *") 61*99451b44SJordan Rupprecht self.runCmd("type synth add -l fooSynthProvider foo") 62*99451b44SJordan Rupprecht self.runCmd("type synth add -l wrapfooSynthProvider wrapfoo") 63*99451b44SJordan Rupprecht self.expect("type synthetic list foo", substrs=['fooSynthProvider']) 64*99451b44SJordan Rupprecht 65*99451b44SJordan Rupprecht # note that the value of fake_a depends on target byte order 66*99451b44SJordan Rupprecht if process.GetByteOrder() == lldb.eByteOrderLittle: 67*99451b44SJordan Rupprecht fake_a_val = 0x02000000 68*99451b44SJordan Rupprecht else: 69*99451b44SJordan Rupprecht fake_a_val = 0x00000100 70*99451b44SJordan Rupprecht 71*99451b44SJordan Rupprecht # check that we get the two real vars and the fake_a variables 72*99451b44SJordan Rupprecht self.expect( 73*99451b44SJordan Rupprecht "frame variable f00_1", 74*99451b44SJordan Rupprecht substrs=[ 75*99451b44SJordan Rupprecht 'a = 1', 76*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 77*99451b44SJordan Rupprecht 'r = 34', 78*99451b44SJordan Rupprecht ]) 79*99451b44SJordan Rupprecht 80*99451b44SJordan Rupprecht # check that we do not get the extra vars 81*99451b44SJordan Rupprecht self.expect("frame variable f00_1", matching=False, 82*99451b44SJordan Rupprecht substrs=['b = 2']) 83*99451b44SJordan Rupprecht 84*99451b44SJordan Rupprecht # check access to members by name 85*99451b44SJordan Rupprecht self.expect('frame variable f00_1.fake_a', 86*99451b44SJordan Rupprecht substrs=['%d' % fake_a_val]) 87*99451b44SJordan Rupprecht 88*99451b44SJordan Rupprecht # check access to members by index 89*99451b44SJordan Rupprecht self.expect('frame variable f00_1[1]', 90*99451b44SJordan Rupprecht substrs=['%d' % fake_a_val]) 91*99451b44SJordan Rupprecht 92*99451b44SJordan Rupprecht # put synthetic children in summary in several combinations 93*99451b44SJordan Rupprecht self.runCmd( 94*99451b44SJordan Rupprecht "type summary add --summary-string \"fake_a=${svar.fake_a}\" foo") 95*99451b44SJordan Rupprecht self.expect('frame variable f00_1', 96*99451b44SJordan Rupprecht substrs=['fake_a=%d' % fake_a_val]) 97*99451b44SJordan Rupprecht self.runCmd( 98*99451b44SJordan Rupprecht "type summary add --summary-string \"fake_a=${svar[1]}\" foo") 99*99451b44SJordan Rupprecht self.expect('frame variable f00_1', 100*99451b44SJordan Rupprecht substrs=['fake_a=%d' % fake_a_val]) 101*99451b44SJordan Rupprecht 102*99451b44SJordan Rupprecht # clear the summary 103*99451b44SJordan Rupprecht self.runCmd("type summary delete foo") 104*99451b44SJordan Rupprecht 105*99451b44SJordan Rupprecht # check that the caching does not span beyond the stopoint 106*99451b44SJordan Rupprecht self.runCmd("n") 107*99451b44SJordan Rupprecht 108*99451b44SJordan Rupprecht if process.GetByteOrder() == lldb.eByteOrderLittle: 109*99451b44SJordan Rupprecht fake_a_val = 0x02000000 110*99451b44SJordan Rupprecht else: 111*99451b44SJordan Rupprecht fake_a_val = 0x00000200 112*99451b44SJordan Rupprecht 113*99451b44SJordan Rupprecht self.expect( 114*99451b44SJordan Rupprecht "frame variable f00_1", 115*99451b44SJordan Rupprecht substrs=[ 116*99451b44SJordan Rupprecht 'a = 2', 117*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 118*99451b44SJordan Rupprecht 'r = 34', 119*99451b44SJordan Rupprecht ]) 120*99451b44SJordan Rupprecht 121*99451b44SJordan Rupprecht # check that altering the object also alters fake_a 122*99451b44SJordan Rupprecht self.runCmd("expr f00_1.a = 280") 123*99451b44SJordan Rupprecht 124*99451b44SJordan Rupprecht if process.GetByteOrder() == lldb.eByteOrderLittle: 125*99451b44SJordan Rupprecht fake_a_val = 0x02000001 126*99451b44SJordan Rupprecht else: 127*99451b44SJordan Rupprecht fake_a_val = 0x00011800 128*99451b44SJordan Rupprecht 129*99451b44SJordan Rupprecht self.expect( 130*99451b44SJordan Rupprecht "frame variable f00_1", 131*99451b44SJordan Rupprecht substrs=[ 132*99451b44SJordan Rupprecht 'a = 280', 133*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 134*99451b44SJordan Rupprecht 'r = 34', 135*99451b44SJordan Rupprecht ]) 136*99451b44SJordan Rupprecht 137*99451b44SJordan Rupprecht # check that expanding a pointer does the right thing 138*99451b44SJordan Rupprecht if process.GetByteOrder() == lldb.eByteOrderLittle: 139*99451b44SJordan Rupprecht fake_a_val = 0x0d000000 140*99451b44SJordan Rupprecht else: 141*99451b44SJordan Rupprecht fake_a_val = 0x00000c00 142*99451b44SJordan Rupprecht 143*99451b44SJordan Rupprecht self.expect( 144*99451b44SJordan Rupprecht "frame variable --ptr-depth 1 f00_ptr", 145*99451b44SJordan Rupprecht substrs=[ 146*99451b44SJordan Rupprecht 'a = 12', 147*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 148*99451b44SJordan Rupprecht 'r = 45', 149*99451b44SJordan Rupprecht ]) 150*99451b44SJordan Rupprecht self.expect( 151*99451b44SJordan Rupprecht "frame variable --ptr-depth 1 wrapper", 152*99451b44SJordan Rupprecht substrs=[ 153*99451b44SJordan Rupprecht 'a = 12', 154*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 155*99451b44SJordan Rupprecht 'r = 45', 156*99451b44SJordan Rupprecht ]) 157*99451b44SJordan Rupprecht 158*99451b44SJordan Rupprecht # now add a filter.. it should fail 159*99451b44SJordan Rupprecht self.expect("type filter add foo --child b --child j", error=True, 160*99451b44SJordan Rupprecht substrs=['cannot add']) 161*99451b44SJordan Rupprecht 162*99451b44SJordan Rupprecht # we get the synth again.. 163*99451b44SJordan Rupprecht self.expect('frame variable f00_1', matching=False, 164*99451b44SJordan Rupprecht substrs=['b = 1', 165*99451b44SJordan Rupprecht 'j = 17']) 166*99451b44SJordan Rupprecht self.expect( 167*99451b44SJordan Rupprecht "frame variable --ptr-depth 1 f00_ptr", 168*99451b44SJordan Rupprecht substrs=[ 169*99451b44SJordan Rupprecht 'a = 12', 170*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 171*99451b44SJordan Rupprecht 'r = 45', 172*99451b44SJordan Rupprecht ]) 173*99451b44SJordan Rupprecht self.expect( 174*99451b44SJordan Rupprecht "frame variable --ptr-depth 1 wrapper", 175*99451b44SJordan Rupprecht substrs=[ 176*99451b44SJordan Rupprecht 'a = 12', 177*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 178*99451b44SJordan Rupprecht 'r = 45', 179*99451b44SJordan Rupprecht ]) 180*99451b44SJordan Rupprecht 181*99451b44SJordan Rupprecht # Test that the custom dereference operator for `wrapfoo` works through 182*99451b44SJordan Rupprecht # the Python API. The synthetic children provider gets queried at 183*99451b44SJordan Rupprecht # slightly different times in this case. 184*99451b44SJordan Rupprecht wrapper_var = thread.GetSelectedFrame().FindVariable('wrapper') 185*99451b44SJordan Rupprecht foo_var = wrapper_var.Dereference() 186*99451b44SJordan Rupprecht self.assertEqual(foo_var.GetNumChildren(), 3) 187*99451b44SJordan Rupprecht self.assertEqual(foo_var.GetChildAtIndex(0).GetName(), 'a') 188*99451b44SJordan Rupprecht self.assertEqual(foo_var.GetChildAtIndex(1).GetName(), 'fake_a') 189*99451b44SJordan Rupprecht self.assertEqual(foo_var.GetChildAtIndex(2).GetName(), 'r') 190*99451b44SJordan Rupprecht 191*99451b44SJordan Rupprecht # now delete the synth and add the filter 192*99451b44SJordan Rupprecht self.runCmd("type synth delete foo") 193*99451b44SJordan Rupprecht self.runCmd("type synth delete wrapfoo") 194*99451b44SJordan Rupprecht self.runCmd("type filter add foo --child b --child j") 195*99451b44SJordan Rupprecht 196*99451b44SJordan Rupprecht self.expect('frame variable f00_1', 197*99451b44SJordan Rupprecht substrs=['b = 2', 198*99451b44SJordan Rupprecht 'j = 18']) 199*99451b44SJordan Rupprecht self.expect("frame variable --ptr-depth 1 f00_ptr", matching=False, 200*99451b44SJordan Rupprecht substrs=['r = 45', 201*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 202*99451b44SJordan Rupprecht 'a = 12']) 203*99451b44SJordan Rupprecht self.expect("frame variable --ptr-depth 1 wrapper", matching=False, 204*99451b44SJordan Rupprecht substrs=['r = 45', 205*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 206*99451b44SJordan Rupprecht 'a = 12']) 207*99451b44SJordan Rupprecht 208*99451b44SJordan Rupprecht # now add the synth and it should fail 209*99451b44SJordan Rupprecht self.expect("type synth add -l fooSynthProvider foo", error=True, 210*99451b44SJordan Rupprecht substrs=['cannot add']) 211*99451b44SJordan Rupprecht 212*99451b44SJordan Rupprecht # check the listing 213*99451b44SJordan Rupprecht self.expect('type synth list', matching=False, 214*99451b44SJordan Rupprecht substrs=['foo', 215*99451b44SJordan Rupprecht 'Python class fooSynthProvider']) 216*99451b44SJordan Rupprecht self.expect('type filter list', 217*99451b44SJordan Rupprecht substrs=['foo', 218*99451b44SJordan Rupprecht '.b', 219*99451b44SJordan Rupprecht '.j']) 220*99451b44SJordan Rupprecht 221*99451b44SJordan Rupprecht # delete the filter, add the synth 222*99451b44SJordan Rupprecht self.runCmd("type filter delete foo") 223*99451b44SJordan Rupprecht self.runCmd("type synth add -l fooSynthProvider foo") 224*99451b44SJordan Rupprecht 225*99451b44SJordan Rupprecht self.expect('frame variable f00_1', matching=False, 226*99451b44SJordan Rupprecht substrs=['b = 2', 227*99451b44SJordan Rupprecht 'j = 18']) 228*99451b44SJordan Rupprecht self.expect( 229*99451b44SJordan Rupprecht "frame variable --ptr-depth 1 f00_ptr", 230*99451b44SJordan Rupprecht substrs=[ 231*99451b44SJordan Rupprecht 'a = 12', 232*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 233*99451b44SJordan Rupprecht 'r = 45', 234*99451b44SJordan Rupprecht ]) 235*99451b44SJordan Rupprecht self.expect( 236*99451b44SJordan Rupprecht "frame variable --ptr-depth 1 wrapper", 237*99451b44SJordan Rupprecht substrs=[ 238*99451b44SJordan Rupprecht 'a = 12', 239*99451b44SJordan Rupprecht 'fake_a = %d' % fake_a_val, 240*99451b44SJordan Rupprecht 'r = 45', 241*99451b44SJordan Rupprecht ]) 242*99451b44SJordan Rupprecht 243*99451b44SJordan Rupprecht # check the listing 244*99451b44SJordan Rupprecht self.expect('type synth list', 245*99451b44SJordan Rupprecht substrs=['foo', 246*99451b44SJordan Rupprecht 'Python class fooSynthProvider']) 247*99451b44SJordan Rupprecht self.expect('type filter list', matching=False, 248*99451b44SJordan Rupprecht substrs=['foo', 249*99451b44SJordan Rupprecht '.b', 250*99451b44SJordan Rupprecht '.j']) 251*99451b44SJordan Rupprecht 252*99451b44SJordan Rupprecht # delete the synth and check that we get good output 253*99451b44SJordan Rupprecht self.runCmd("type synth delete foo") 254*99451b44SJordan Rupprecht 255*99451b44SJordan Rupprecht self.expect("frame variable f00_1", 256*99451b44SJordan Rupprecht substrs=['a = 280', 257*99451b44SJordan Rupprecht 'b = 2', 258*99451b44SJordan Rupprecht 'j = 18']) 259*99451b44SJordan Rupprecht 260*99451b44SJordan Rupprecht self.expect("frame variable f00_1", matching=False, 261*99451b44SJordan Rupprecht substrs=['fake_a = ']) 262*99451b44SJordan Rupprecht 263*99451b44SJordan Rupprecht def rdar10960550_formatter_commands(self): 264*99451b44SJordan Rupprecht """Test that synthetic children persist stoppoints.""" 265*99451b44SJordan Rupprecht self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) 266*99451b44SJordan Rupprecht 267*99451b44SJordan Rupprecht # The second breakpoint is on a multi-line expression, so the comment 268*99451b44SJordan Rupprecht # can't be on the right line... 269*99451b44SJordan Rupprecht lldbutil.run_break_set_by_file_and_line( 270*99451b44SJordan Rupprecht self, "main.cpp", self.line2, num_expected_locations=1, loc_exact=False) 271*99451b44SJordan Rupprecht lldbutil.run_break_set_by_file_and_line( 272*99451b44SJordan Rupprecht self, "main.cpp", self.line3, num_expected_locations=1, loc_exact=True) 273*99451b44SJordan Rupprecht 274*99451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 275*99451b44SJordan Rupprecht 276*99451b44SJordan Rupprecht # The stop reason of the thread should be breakpoint. 277*99451b44SJordan Rupprecht self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 278*99451b44SJordan Rupprecht substrs=['stopped', 279*99451b44SJordan Rupprecht 'stop reason = breakpoint']) 280*99451b44SJordan Rupprecht 281*99451b44SJordan Rupprecht # This is the function to remove the custom formats in order to have a 282*99451b44SJordan Rupprecht # clean slate for the next test case. 283*99451b44SJordan Rupprecht def cleanup(): 284*99451b44SJordan Rupprecht self.runCmd('type format clear', check=False) 285*99451b44SJordan Rupprecht self.runCmd('type summary clear', check=False) 286*99451b44SJordan Rupprecht self.runCmd('type filter clear', check=False) 287*99451b44SJordan Rupprecht self.runCmd('type synth clear', check=False) 288*99451b44SJordan Rupprecht 289*99451b44SJordan Rupprecht # Execute the cleanup function during test case tear down. 290*99451b44SJordan Rupprecht self.addTearDownHook(cleanup) 291*99451b44SJordan Rupprecht 292*99451b44SJordan Rupprecht self.runCmd("command script import ./ftsp.py --allow-reload") 293*99451b44SJordan Rupprecht self.runCmd("type synth add -l ftsp.ftsp wrapint") 294*99451b44SJordan Rupprecht 295*99451b44SJordan Rupprecht # we need to check that the VO is properly updated so that the same synthetic children are reused 296*99451b44SJordan Rupprecht # but their values change correctly across stop-points - in order to do this, self.runCmd("next") 297*99451b44SJordan Rupprecht # does not work because it forces a wipe of the stack frame - this is why we are using this more contrived 298*99451b44SJordan Rupprecht # mechanism to achieve our goal of preserving test_cast as a VO 299*99451b44SJordan Rupprecht test_cast = self.dbg.GetSelectedTarget().GetProcess( 300*99451b44SJordan Rupprecht ).GetSelectedThread().GetSelectedFrame().FindVariable('test_cast') 301*99451b44SJordan Rupprecht 302*99451b44SJordan Rupprecht str_cast = str(test_cast) 303*99451b44SJordan Rupprecht 304*99451b44SJordan Rupprecht if self.TraceOn(): 305*99451b44SJordan Rupprecht print(str_cast) 306*99451b44SJordan Rupprecht 307*99451b44SJordan Rupprecht self.assertTrue(str_cast.find('A') != -1, 'could not find A in output') 308*99451b44SJordan Rupprecht self.assertTrue(str_cast.find('B') != -1, 'could not find B in output') 309*99451b44SJordan Rupprecht self.assertTrue(str_cast.find('C') != -1, 'could not find C in output') 310*99451b44SJordan Rupprecht self.assertTrue(str_cast.find('D') != -1, 'could not find D in output') 311*99451b44SJordan Rupprecht self.assertTrue( 312*99451b44SJordan Rupprecht str_cast.find("4 = '\\0'") != -1, 313*99451b44SJordan Rupprecht 'could not find item 4 == 0') 314*99451b44SJordan Rupprecht 315*99451b44SJordan Rupprecht self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().StepOver() 316*99451b44SJordan Rupprecht 317*99451b44SJordan Rupprecht str_cast = str(test_cast) 318*99451b44SJordan Rupprecht 319*99451b44SJordan Rupprecht if self.TraceOn(): 320*99451b44SJordan Rupprecht print(str_cast) 321*99451b44SJordan Rupprecht 322*99451b44SJordan Rupprecht # we detect that all the values of the child objects have changed - but the counter-generated item 323*99451b44SJordan Rupprecht # is still fixed at 0 because it is cached - this would fail if update(self): in ftsp returned False 324*99451b44SJordan Rupprecht # or if synthetic children were not being preserved 325*99451b44SJordan Rupprecht self.assertTrue(str_cast.find('Q') != -1, 'could not find Q in output') 326*99451b44SJordan Rupprecht self.assertTrue(str_cast.find('X') != -1, 'could not find X in output') 327*99451b44SJordan Rupprecht self.assertTrue(str_cast.find('T') != -1, 'could not find T in output') 328*99451b44SJordan Rupprecht self.assertTrue(str_cast.find('F') != -1, 'could not find F in output') 329*99451b44SJordan Rupprecht self.assertTrue( 330*99451b44SJordan Rupprecht str_cast.find("4 = '\\0'") != -1, 331*99451b44SJordan Rupprecht 'could not find item 4 == 0') 332