199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest lldb Python commands. 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprecht 699451b44SJordan Rupprechtimport sys 799451b44SJordan Rupprechtimport lldb 899451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 999451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 1099451b44SJordan Rupprecht 1199451b44SJordan Rupprecht 1299451b44SJordan Rupprechtclass CmdPythonTestCase(TestBase): 1399451b44SJordan Rupprecht NO_DEBUG_INFO_TESTCASE = True 1499451b44SJordan Rupprecht 1599451b44SJordan Rupprecht def test(self): 1699451b44SJordan Rupprecht self.build() 1799451b44SJordan Rupprecht self.pycmd_tests() 1899451b44SJordan Rupprecht 1999451b44SJordan Rupprecht def pycmd_tests(self): 2099451b44SJordan Rupprecht self.runCmd("command source py_import") 2199451b44SJordan Rupprecht 224eb694e3SJim Ingham # Test that we did indeed add these commands as user commands: 234eb694e3SJim Ingham interp = self.dbg.GetCommandInterpreter() 2400b2c33cSJim Ingham self.assertTrue(interp.UserCommandExists("foobar"), "foobar exists") 2500b2c33cSJim Ingham self.assertFalse(interp.CommandExists("foobar"), "It is not a builtin.") 264eb694e3SJim Ingham 2799451b44SJordan Rupprecht # Test a bunch of different kinds of python callables with 2899451b44SJordan Rupprecht # both 4 and 5 positional arguments. 2999451b44SJordan Rupprecht self.expect("foobar", substrs=["All good"]) 3099451b44SJordan Rupprecht self.expect("foobar4", substrs=["All good"]) 3199451b44SJordan Rupprecht self.expect("vfoobar", substrs=["All good"]) 3299451b44SJordan Rupprecht self.expect("v5foobar", substrs=["All good"]) 3399451b44SJordan Rupprecht self.expect("sfoobar", substrs=["All good"]) 3499451b44SJordan Rupprecht self.expect("cfoobar", substrs=["All good"]) 3599451b44SJordan Rupprecht self.expect("ifoobar", substrs=["All good"]) 3699451b44SJordan Rupprecht self.expect("sfoobar4", substrs=["All good"]) 3799451b44SJordan Rupprecht self.expect("cfoobar4", substrs=["All good"]) 3899451b44SJordan Rupprecht self.expect("ifoobar4", substrs=["All good"]) 3999451b44SJordan Rupprecht self.expect("ofoobar", substrs=["All good"]) 4099451b44SJordan Rupprecht self.expect("ofoobar4", substrs=["All good"]) 4199451b44SJordan Rupprecht 4299451b44SJordan Rupprecht # Verify command that specifies eCommandRequiresTarget returns failure 4399451b44SJordan Rupprecht # without a target. 442238dcc3SJonas Devlieghere self.expect("targetname", substrs=["a.out"], matching=False, error=True) 4599451b44SJordan Rupprecht 4699451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 472238dcc3SJonas Devlieghere self.expect("file " + exe, patterns=["Current executable set to .*a.out"]) 4899451b44SJordan Rupprecht 492238dcc3SJonas Devlieghere self.expect("targetname", substrs=["a.out"], matching=True, error=False) 5099451b44SJordan Rupprecht 5199451b44SJordan Rupprecht # This is the function to remove the custom commands in order to have a 5299451b44SJordan Rupprecht # clean slate for the next test case. 5399451b44SJordan Rupprecht def cleanup(): 542238dcc3SJonas Devlieghere self.runCmd("command script delete welcome", check=False) 552238dcc3SJonas Devlieghere self.runCmd("command script delete targetname", check=False) 562238dcc3SJonas Devlieghere self.runCmd("command script delete longwait", check=False) 572238dcc3SJonas Devlieghere self.runCmd("command script delete mysto", check=False) 582238dcc3SJonas Devlieghere self.runCmd("command script delete tell_sync", check=False) 592238dcc3SJonas Devlieghere self.runCmd("command script delete tell_async", check=False) 602238dcc3SJonas Devlieghere self.runCmd("command script delete tell_curr", check=False) 612238dcc3SJonas Devlieghere self.runCmd("command script delete bug11569", check=False) 622238dcc3SJonas Devlieghere self.runCmd("command script delete takes_exe_ctx", check=False) 632238dcc3SJonas Devlieghere self.runCmd("command script delete decorated", check=False) 6499451b44SJordan Rupprecht 6599451b44SJordan Rupprecht # Execute the cleanup function during test case tear down. 6699451b44SJordan Rupprecht self.addTearDownHook(cleanup) 6799451b44SJordan Rupprecht 6899451b44SJordan Rupprecht # Interact with debugger in synchronous mode 6999451b44SJordan Rupprecht self.setAsync(False) 7099451b44SJordan Rupprecht 7199451b44SJordan Rupprecht # We don't want to display the stdout if not in TraceOn() mode. 7299451b44SJordan Rupprecht if not self.TraceOn(): 7399451b44SJordan Rupprecht self.HideStdout() 7499451b44SJordan Rupprecht 752238dcc3SJonas Devlieghere self.expect("welcome Enrico", substrs=["Hello Enrico, welcome to LLDB"]) 7699451b44SJordan Rupprecht 772238dcc3SJonas Devlieghere self.expect( 782238dcc3SJonas Devlieghere "help welcome", 792238dcc3SJonas Devlieghere substrs=[ 802238dcc3SJonas Devlieghere "Just a docstring for welcome_impl", 812238dcc3SJonas Devlieghere "A command that says hello to LLDB users", 822238dcc3SJonas Devlieghere ], 832238dcc3SJonas Devlieghere ) 8499451b44SJordan Rupprecht 8599451b44SJordan Rupprecht decorated_commands = ["decorated" + str(n) for n in range(1, 5)] 8699451b44SJordan Rupprecht for name in decorated_commands: 8799451b44SJordan Rupprecht self.expect(name, substrs=["hello from " + name]) 882238dcc3SJonas Devlieghere self.expect( 892238dcc3SJonas Devlieghere "help " + name, substrs=["Python command defined by @lldb.command"] 902238dcc3SJonas Devlieghere ) 9199451b44SJordan Rupprecht 922238dcc3SJonas Devlieghere self.expect( 932238dcc3SJonas Devlieghere "help", 942238dcc3SJonas Devlieghere substrs=["For more information run"] + decorated_commands + ["welcome"], 952238dcc3SJonas Devlieghere ) 9699451b44SJordan Rupprecht 972238dcc3SJonas Devlieghere self.expect( 982238dcc3SJonas Devlieghere "help -a", 992238dcc3SJonas Devlieghere substrs=["For more information run"] + decorated_commands + ["welcome"], 1002238dcc3SJonas Devlieghere ) 10199451b44SJordan Rupprecht 1022238dcc3SJonas Devlieghere self.expect("help -u", matching=False, substrs=["For more information run"]) 10399451b44SJordan Rupprecht 10499451b44SJordan Rupprecht self.runCmd("command script delete welcome") 10599451b44SJordan Rupprecht 1062238dcc3SJonas Devlieghere self.expect( 1072238dcc3SJonas Devlieghere "welcome Enrico", 1082238dcc3SJonas Devlieghere matching=False, 1092238dcc3SJonas Devlieghere error=True, 1102238dcc3SJonas Devlieghere substrs=["Hello Enrico, welcome to LLDB"], 1112238dcc3SJonas Devlieghere ) 11299451b44SJordan Rupprecht 1132238dcc3SJonas Devlieghere self.expect( 1142238dcc3SJonas Devlieghere "targetname fail", error=True, substrs=["a test for error in command"] 1152238dcc3SJonas Devlieghere ) 11699451b44SJordan Rupprecht 1172238dcc3SJonas Devlieghere self.expect( 1182238dcc3SJonas Devlieghere "command script list", substrs=["targetname", "For more information run"] 1192238dcc3SJonas Devlieghere ) 12099451b44SJordan Rupprecht 1212238dcc3SJonas Devlieghere self.expect( 1222238dcc3SJonas Devlieghere "help targetname", 1232238dcc3SJonas Devlieghere substrs=["Expects", "'raw'", "input", "help", "raw-input"], 1242238dcc3SJonas Devlieghere ) 12599451b44SJordan Rupprecht 1262238dcc3SJonas Devlieghere self.expect("longwait", substrs=["Done; if you saw the delays I am doing OK"]) 12799451b44SJordan Rupprecht 128dd01d9aaSMuhammad Omair Javaid self.runCmd("break set -f main.cpp -l 48") 12999451b44SJordan Rupprecht self.runCmd("run") 13099451b44SJordan Rupprecht self.runCmd("mysto 3") 1312238dcc3SJonas Devlieghere self.expect( 1322238dcc3SJonas Devlieghere "frame variable array", 1332238dcc3SJonas Devlieghere substrs=["[0] = 79630", "[1] = 388785018", "[2] = 0"], 1342238dcc3SJonas Devlieghere ) 13599451b44SJordan Rupprecht self.runCmd("mysto 3") 1362238dcc3SJonas Devlieghere self.expect( 1372238dcc3SJonas Devlieghere "frame variable array", 1382238dcc3SJonas Devlieghere substrs=["[0] = 79630", "[4] = 388785018", "[5] = 0"], 1392238dcc3SJonas Devlieghere ) 14099451b44SJordan Rupprecht 14199451b44SJordan Rupprecht # we cannot use the stepover command to check for async execution mode since LLDB 14299451b44SJordan Rupprecht # seems to get confused when events start to queue up 1432238dcc3SJonas Devlieghere self.expect("tell_sync", substrs=["running sync"]) 1442238dcc3SJonas Devlieghere self.expect("tell_async", substrs=["running async"]) 1452238dcc3SJonas Devlieghere self.expect("tell_curr", substrs=["I am running sync"]) 14699451b44SJordan Rupprecht 14799451b44SJordan Rupprecht # check that the execution context is passed in to commands that ask for it 14899451b44SJordan Rupprecht self.expect("takes_exe_ctx", substrs=["a.out"]) 14999451b44SJordan Rupprecht 15099451b44SJordan Rupprecht # Test that a python command can redefine itself 15199451b44SJordan Rupprecht self.expect('command script add -f foobar welcome -h "just some help"') 15299451b44SJordan Rupprecht 15399451b44SJordan Rupprecht self.runCmd("command script clear") 15499451b44SJordan Rupprecht 15599451b44SJordan Rupprecht # Test that re-defining an existing command works 1562238dcc3SJonas Devlieghere self.runCmd("command script add my_command --class welcome.WelcomeCommand") 1572238dcc3SJonas Devlieghere self.expect("my_command Blah", substrs=["Hello Blah, welcome to LLDB"]) 15899451b44SJordan Rupprecht 15999451b44SJordan Rupprecht self.runCmd( 1602238dcc3SJonas Devlieghere "command script add my_command -o --class welcome.TargetnameCommand" 1612238dcc3SJonas Devlieghere ) 1622238dcc3SJonas Devlieghere self.expect("my_command", substrs=["a.out"]) 16399451b44SJordan Rupprecht 164cf0be7b4SFelipe de Azevedo Piovezan # Test that without --overwrite we are not allowed to redefine the command. 165cf0be7b4SFelipe de Azevedo Piovezan self.expect( 166cf0be7b4SFelipe de Azevedo Piovezan "command script add my_command --class welcome.TargetnameCommand", 167cf0be7b4SFelipe de Azevedo Piovezan substrs=[ 168cf0be7b4SFelipe de Azevedo Piovezan ( 169cf0be7b4SFelipe de Azevedo Piovezan 'user command "my_command" already exists and force replace was' 170cf0be7b4SFelipe de Azevedo Piovezan " not set by --overwrite or 'settings set" 171cf0be7b4SFelipe de Azevedo Piovezan " interpreter.require-overwrite false'" 172cf0be7b4SFelipe de Azevedo Piovezan ), 173cf0be7b4SFelipe de Azevedo Piovezan ], 174cf0be7b4SFelipe de Azevedo Piovezan error=True, 175cf0be7b4SFelipe de Azevedo Piovezan ) 176cf0be7b4SFelipe de Azevedo Piovezan 17799451b44SJordan Rupprecht self.runCmd("command script clear") 17899451b44SJordan Rupprecht 1792238dcc3SJonas Devlieghere self.expect( 1802238dcc3SJonas Devlieghere "command script list", matching=False, substrs=["targetname", "longwait"] 1812238dcc3SJonas Devlieghere ) 18299451b44SJordan Rupprecht 1832238dcc3SJonas Devlieghere self.expect( 1842238dcc3SJonas Devlieghere "command script add -f foobar frame", 1852238dcc3SJonas Devlieghere error=True, 1862238dcc3SJonas Devlieghere substrs=["cannot add command"], 1872238dcc3SJonas Devlieghere ) 18899451b44SJordan Rupprecht 18999451b44SJordan Rupprecht # http://llvm.org/bugs/show_bug.cgi?id=11569 19099451b44SJordan Rupprecht # LLDBSwigPythonCallCommand crashes when a command script returns an 19199451b44SJordan Rupprecht # object 1922238dcc3SJonas Devlieghere self.runCmd("command script add -f bug11569 bug11569") 19399451b44SJordan Rupprecht # This should not crash. 1942238dcc3SJonas Devlieghere self.runCmd("bug11569", check=False) 1957406d236SPavel Labath 1969093f3c3SJim Ingham # Make sure that a reference to a non-existent class raises an error: 1979093f3c3SJim Ingham bad_class_name = "LLDBNoSuchModule.LLDBNoSuchClass" 1982238dcc3SJonas Devlieghere self.expect( 1992238dcc3SJonas Devlieghere "command script add wont-work --class {0}".format(bad_class_name), 2002238dcc3SJonas Devlieghere error=True, 2012238dcc3SJonas Devlieghere substrs=[bad_class_name], 2022238dcc3SJonas Devlieghere ) 2039093f3c3SJim Ingham 2047406d236SPavel Labath def test_persistence(self): 2050a07c966SPavel Labath """ 2060a07c966SPavel Labath Ensure that function arguments meaningfully persist (and do not crash!) 2070a07c966SPavel Labath even after the function terminates. 2080a07c966SPavel Labath """ 2097406d236SPavel Labath self.runCmd("command script import persistence.py") 2107406d236SPavel Labath self.runCmd("command script add -f persistence.save_debugger save_debugger") 2117406d236SPavel Labath self.expect("save_debugger", substrs=[str(self.dbg)]) 2120a07c966SPavel Labath 2130a07c966SPavel Labath # After the command completes, the debugger object should still be 2140a07c966SPavel Labath # valid. 2157406d236SPavel Labath self.expect("script str(persistence.debugger_copy)", substrs=[str(self.dbg)]) 2160a07c966SPavel Labath # The result object will be replaced by an empty result object (in the 2170a07c966SPavel Labath # "Started" state). 2180a07c966SPavel Labath self.expect("script str(persistence.result_copy)", substrs=["Started"]) 219*5784bf85Sjimingham 220*5784bf85Sjimingham def test_interactive(self): 221*5784bf85Sjimingham """ 222*5784bf85Sjimingham Test that we can add multiple lines interactively. 223*5784bf85Sjimingham """ 224*5784bf85Sjimingham interp = self.dbg.GetCommandInterpreter() 225*5784bf85Sjimingham cmd_file = self.getSourcePath("cmd_file.lldb") 226*5784bf85Sjimingham result = lldb.SBCommandReturnObject() 227*5784bf85Sjimingham interp.HandleCommand(f"command source {cmd_file}", result) 228*5784bf85Sjimingham self.assertCommandReturn(result, "Sourcing the command should cause no errors.") 229*5784bf85Sjimingham self.assertTrue(interp.UserCommandExists("my_cmd"), "Command defined.") 230*5784bf85Sjimingham interp.HandleCommand("my_cmd", result) 231*5784bf85Sjimingham self.assertCommandReturn(result, "Running the command succeeds") 232*5784bf85Sjimingham self.assertIn("My Command Result", result.GetOutput(), "Command was correct") 233