Index: test/tools/lldb-mi/TestMiBreakpoint.py =================================================================== --- test/tools/lldb-mi/TestMiBreakpoint.py +++ test/tools/lldb-mi/TestMiBreakpoint.py @@ -18,7 +18,7 @@ self.runCmd("-file-exec-and-symbols %s" % self.myexe) self.expect("\^done") - self.runCmd("-break-insert -f a_MyFunction") + self.runCmd("-break-insert -f b_MyFunction") self.expect("\^done,bkpt={number=\"1\"") self.runCmd("-exec-run") @@ -40,7 +40,7 @@ self.expect("\^done") # Find the line number to break inside main() and set - # pending BP. + # pending BP line = line_number('main.c', '//BP_source') self.runCmd("-break-insert -f main.c:%d" % line) self.expect("\^done,bkpt={number=\"1\"") @@ -70,15 +70,15 @@ self.expect("\^running") self.expect("\*stopped,reason=\"breakpoint-hit\"") - #break on symbol - self.runCmd("-break-insert a_MyFunction") + # Break on symbol + self.runCmd("-break-insert b_MyFunction") self.expect("\^done,bkpt={number=\"2\"") self.runCmd("-exec-continue") self.expect("\^running") self.expect("\*stopped,reason=\"breakpoint-hit\"") - #break on source + # Break on source line = line_number('main.c', '//BP_source') self.runCmd("-break-insert main.c:%d" % line) self.expect("\^done,bkpt={number=\"3\"") @@ -87,7 +87,7 @@ self.expect("\^running") self.expect("\*stopped,reason=\"breakpoint-hit\"") - #run to exit + # Run to exit self.runCmd("-exec-continue") self.expect("\^running") self.expect("\*stopped,reason=\"exited-normally\"") Index: test/tools/lldb-mi/TestMiData.py =================================================================== --- test/tools/lldb-mi/TestMiData.py +++ test/tools/lldb-mi/TestMiData.py @@ -0,0 +1,88 @@ +""" +Test that the lldb-mi driver works with -data-xxx commands +""" + +import lldbmi_testcase +from lldbtest import * +import unittest2 + +class MiDataTestCase(lldbmi_testcase.MiTestCaseBase): + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + def test_lldbmi_data_disassemble(self): + """Test that 'lldb-mi --interpreter' works for -data-disassemble.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test -data-disassemble: try to disassemble some address + self.runCmd("-data-disassemble -s 0x0 -e 0x0 -- 0") + self.expect("\^done,asm_insns=\[") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("-data-list-register-names doesn't work properly") + def test_lldbmi_data_list_register_names(self): + """Test that 'lldb-mi --interpreter' works for -data-list-register-names.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test -data-list-register-names: try to get all registers + self.runCmd("-data-list-register-names") + self.expect("\^done,register-names=\[\".+\",") + + # Test -data-list-register-names: try to get specified registers + self.runCmd("-data-list-register-names 0") + self.expect("\^done,register-names=\[\".+\"\]") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("-data-list-register-values doesn't work properly") + def test_lldbmi_data_list_register_values(self): + """Test that 'lldb-mi --interpreter' works for -data-list-register-values.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test -data-list-register-values: try to get all registers + self.runCmd("-data-list-register-values x") + self.expect("\^done,register-values=\[{number=\"0\",value=\"0x[0-9a-f]+\"") + + # Test -data-list-register-values: try to get specified registers + self.runCmd("-data-list-register-values x 0") + self.expect("\^done,register-values=\[{number=\"0\",value=\"0x[0-9a-f]+\"}\]") + +if __name__ == '__main__': + unittest2.main() Index: test/tools/lldb-mi/TestMiEvaluate.py =================================================================== --- test/tools/lldb-mi/TestMiEvaluate.py +++ test/tools/lldb-mi/TestMiEvaluate.py @@ -18,7 +18,7 @@ self.runCmd("-file-exec-and-symbols %s" % self.myexe) self.expect("\^done") - #run to main + # Run to main self.runCmd("-break-insert -f main") self.expect("\^done,bkpt={number=\"1\"") @@ -26,7 +26,7 @@ self.expect("\^running") self.expect("\*stopped,reason=\"breakpoint-hit\"") - #run to program return (marked BP_source) + # Run to program return (marked BP_source) line = line_number('main.c', '//BP_source') self.runCmd("-break-insert main.c:%d" % line) self.expect("\^done,bkpt={number=\"2\"") @@ -35,55 +35,60 @@ self.expect("\^running") self.expect("\*stopped,reason=\"breakpoint-hit\"") - #print non-existant variable + # Print non-existant variable #self.runCmd("-var-create var1 --thread 1 --frame 0 * undef") #FIXME: shows undef as {...} #self.expect("error") #self.runCmd("-data-evaluate-expression undef") #FIXME: gets value="undef" #self.expect("error") + self.runCmd("-interpreter-exec command \"print undef\"") + self.expect("undeclared identifier") - #print global "g_MyVar" - self.runCmd("-var-create var1 --thread 1 --frame 0 * g_MyVar") #FIXME: shows name=" + # Print global "g_MyVar" + self.runCmd("-var-create var1 --frame 0 * g_MyVar") #FIXME: shows name=" self.expect("value=\"3\",type=\"int\"") #self.runCmd("-var-evaluate-expression var1") #FIXME: gets var1 does not exist self.runCmd("-var-show-attributes var1") self.expect("status=\"editable\"") self.runCmd("-var-delete var1") self.expect("\^done") - self.runCmd("-var-create var1 --thread 1 --frame 0 * g_MyVar") + self.runCmd("-var-create var1 --frame 0 * g_MyVar") self.expect("value=\"3\",type=\"int\"") - #print static "s_MyVar" and modify + # Print static "s_MyVar" and modify self.runCmd("-data-evaluate-expression s_MyVar") self.expect("value=\"30\"") - self.runCmd("-var-create var3 --thread 1 --frame 0 * \"s_MyVar=3\"") + self.runCmd("-var-create var3 --frame 0 * \"s_MyVar=3\"") self.expect("value=\"3\",type=\"int\"") self.runCmd("-data-evaluate-expression \"s_MyVar=30\"") self.expect("value=\"30\"") + self.runCmd("-interpreter-exec command \"p s_MyVar\"") + self.expect("= 30") - #print local "b" and modify + # Print local "b" and modify self.runCmd("-data-evaluate-expression b") self.expect("value=\"20\"") - self.runCmd("-var-create var3 --thread 1 --frame 0 * \"b=3\"") + self.runCmd("-var-create var3 --frame 0 * \"b=3\"") self.expect("value=\"3\",type=\"int\"") self.runCmd("-data-evaluate-expression \"b=20\"") self.expect("value=\"20\"") + self.runCmd("-interpreter-exec command \"print b\"") + self.expect("= 20") - #print "a + b" + # Print "a + b" self.runCmd("-data-evaluate-expression \"a + b\"") self.expect("value=\"30\"") - self.runCmd("-var-create var3 --thread 1 --frame 0 * \"a + b\"") + self.runCmd("-var-create var3 --frame 0 * \"a + b\"") self.expect("value=\"30\",type=\"int\"") + self.runCmd("-interpreter-exec command \"print a + b\"") + self.expect("= 30") - #print "argv[0]" + # Print "argv[0]" self.runCmd("-data-evaluate-expression \"argv[0]\"") self.expect("value=\"0x") - self.runCmd("-var-create var3 --thread 1 --frame 0 * \"argv[0]\"") + self.runCmd("-var-create var3 --frame 0 * \"argv[0]\"") self.expect("numchild=\"1\",value=\"0x.*\",type=\"const char \*\"") + self.runCmd("-interpreter-exec command \"print argv[0]\"") + self.expect("= 0x") - #run to exit - self.runCmd("-exec-continue") - self.expect("\^running") - self.expect("\*stopped,reason=\"exited-normally\"") - if __name__ == '__main__': unittest2.main() Index: test/tools/lldb-mi/TestMiExec.py =================================================================== --- test/tools/lldb-mi/TestMiExec.py +++ test/tools/lldb-mi/TestMiExec.py @@ -0,0 +1,440 @@ +""" +Test that the lldb-mi driver works with -exec-xxx commands +""" + +import lldbmi_testcase +from lldbtest import * +import unittest2 + +class MiExecTestCase(lldbmi_testcase.MiTestCaseBase): + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("-exec-abort isn't implemented") + def test_lldbmi_exec_abort(self): + """Test that 'lldb-mi --interpreter' works for -exec-abort.""" + + self.spawnLldbMi(args = None) + + # Test that -exec-abort fails on invalid process + self.runCmd("-exec-abort") + self.expect("\^error,msg=\"Command 'exec-abort'. Invalid process during debug session\"") + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Set arguments + self.runCmd("-exec-arguments arg1") + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test that arguments were passed + self.runCmd("-data-evaluate-expression argc") + self.expect("\^done,value=\"2\"") + + # Test that program may be aborted + self.runCmd("-exec-abort") + self.expect("\^done") + self.expect("\*stopped,reason=\"exited-normally\"") + + # Test that program can be run again + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test that arguments were passed again + self.runCmd("-data-evaluate-expression argc") + self.expect("\^done,value=\"2\"") + + # Test that program may be aborted again + self.runCmd("-exec-abort") + self.expect("\^done") + self.expect("\*stopped,reason=\"exited-normally\"") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("reviews.llvm.org/D6965: requires this patch") + def test_lldbmi_exec_arguments_set(self): + """Test that 'lldb-mi --interpreter' can pass args using -exec-arguments.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Set arguments + self.runCmd("-exec-arguments --arg1 \"2nd arg\" third_arg fourth=\"4th arg\"") + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Check argc and argv to see if arg passed + self.runCmd("-data-evaluate-expression argc") + self.expect("\^done,value=\"5\"") + #self.runCmd("-data-evaluate-expression argv[1]") + #self.expect("\^done,value=\"--arg1\"") + self.runCmd("-interpreter-exec command \"print argv[1]\"") + self.expect("\"--arg1\"") + #self.runCmd("-data-evaluate-expression argv[2]") + #self.expect("\^done,value=\"2nd arg\"") + self.runCmd("-interpreter-exec command \"print argv[2]\"") + self.expect("\"2nd arg\"") + #self.runCmd("-data-evaluate-expression argv[3]") + #self.expect("\^done,value=\"third_arg\"") + self.runCmd("-interpreter-exec command \"print argv[3]\"") + self.expect("\"third_arg\"") + #self.runCmd("-data-evaluate-expression argv[4]") + #self.expect("\^done,value=\"fourth=\\\\\\\"4th arg\\\\\\\"\"") + self.runCmd("-interpreter-exec command \"print argv[4]\"") + self.expect("\"fourth=\\\\\\\"4th arg\\\\\\\"\"") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("reviews.llvm.org/D6965: requires this patch") + def test_lldbmi_exec_arguments_reset(self): + """Test that 'lldb-mi --interpreter' can reset previously set args using -exec-arguments.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Set arguments + self.runCmd("-exec-arguments foo bar baz") + self.expect("\^done") + self.runCmd("-exec-arguments") + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Check argc to see if arg passed + self.runCmd("-data-evaluate-expression argc") + self.expect("\^done,value=\"1\"") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + def test_lldbmi_exec_next(self): + """Test that 'lldb-mi --interpreter' works for stepping.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Warning: the following is sensative to the lines in the source. + + # Test -exec-next + self.runCmd("-exec-next --thread 1 --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"") + + # Test that --thread is optional + self.runCmd("-exec-next --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"23\"") + + # Test that --frame is optional + self.runCmd("-exec-next --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"25\"") + + # Test that both --thread and --frame are optional + self.runCmd("-exec-next --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"27\"") + + # Test that an invalid --thread is handled + self.runCmd("-exec-next --thread 0") + self.expect("\^error,message=\"error: Thread index 0 is out of range") + self.runCmd("-exec-next --thread 10") + self.expect("\^error,message=\"error: Thread index 10 is out of range") + + # Test that an invalid --frame is handled + # FIXME: no error is returned + self.runCmd("-exec-next --frame 10") + #self.expect("\^error: Frame index 10 is out of range") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + def test_lldbmi_exec_next_instruction(self): + """Test that 'lldb-mi --interpreter' works for instruction stepping.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Warning: the following is sensative to the lines in the + # source and optimizations + + # Test -exec-next-instruction + self.runCmd("-exec-next-instruction --thread 1 --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"20\"") + + # Test that --thread is optional + self.runCmd("-exec-next-instruction --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"20\"") + + # Test that --frame is optional + self.runCmd("-exec-next-instruction --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"20\"") + + # Test that both --thread and --frame are optional + self.runCmd("-exec-next-instruction --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"") + + # Test that an invalid --thread is handled + self.runCmd("-exec-next-instruction --thread 0") + self.expect("\^error,message=\"error: Thread index 0 is out of range") + self.runCmd("-exec-next-instruction --thread 10") + self.expect("\^error,message=\"error: Thread index 10 is out of range") + + # Test that an invalid --frame is handled + # FIXME: no error is returned + self.runCmd("-exec-next-instruction --frame 10") + #self.expect("\^error: Frame index 10 is out of range") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + def test_lldbmi_exec_step(self): + """Test that 'lldb-mi --interpreter' works for stepping into.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to printf call + line = line_number('main.c', '//BP_printf_call') + self.runCmd("-break-insert -f main.c:%d" % line) + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Warning: the following is sensative to the lines in the source + + # Test that -exec-step does not step into printf (which + # has no debug info) + #FIXME: is this supposed to step into printf? + self.runCmd("-exec-step --thread 1 --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"") + + # Test that -exec-step steps into a_MyFunction and back out + # (and that --thread is optional) + self.runCmd("-exec-step --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"a_MyFunction\"") + #FIXME: is this supposed to step into printf? + self.runCmd("-exec-step --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"a_MyFunction\"") + self.runCmd("-exec-step --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"") + self.runCmd("-exec-step --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"23\"") + + # Test that -exec-step steps into b_MyFunction + # (and that --frame is optional) + self.runCmd("-exec-step --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"b_MyFunction\"") + + # Test that -exec-step steps into a_MyFunction from inside + # b_MyFunction (and that both --thread and --frame are optional) + self.runCmd("-exec-step") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"a_MyFunction\"") + + # Test that an invalid --thread is handled + self.runCmd("-exec-step --thread 0") + self.expect("\^error,message=\"error: Thread index 0 is out of range") + self.runCmd("-exec-step --thread 10") + self.expect("\^error,message=\"error: Thread index 10 is out of range") + + # Test that an invalid --frame is handled + # FIXME: no error is returned + self.runCmd("-exec-step --frame 10") + #self.expect("\^error: Frame index 10 is out of range") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin due to calling convention assumptions") + def test_lldbmi_exec_step_instruction(self): + """Test that 'lldb-mi --interpreter' works for instruction stepping into.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Warning: the following is sensative to the lines in the + # source and optimizations + + # Run to a_MyFunction call + line = line_number('main.c', '//BP_a_MyFunction_call') + self.runCmd("-break-insert -f main.c:%d" % line) + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test that -exec-step-instruction steps over non branching + # instruction + self.runCmd("-exec-step-instruction --thread 1 --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"") + + # Test that -exec-step-instruction steps over non branching + # instruction (and that --thread is optional) + self.runCmd("-exec-step-instruction --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*main.c\",line=\"22\"") + + # Test that -exec-step-instruction steps into a_MyFunction + # (and that --frame is optional) + self.runCmd("-exec-step-instruction --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"a_MyFunction\"") + + # Test that -exec-step-instruction steps into a_MyFunction + # (and that both --thread and --frame are optional) + self.runCmd("-exec-step-instruction --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"a_MyFunction\"") + + # Test that an invalid --thread is handled + self.runCmd("-exec-step-instruction --thread 0") + self.expect("\^error,message=\"error: Thread index 0 is out of range") + self.runCmd("-exec-step-instruction --thread 10") + self.expect("\^error,message=\"error: Thread index 10 is out of range") + + # Test that an invalid --frame is handled + # FIXME: no error is returned + self.runCmd("-exec-step-instruction --frame 10") + #self.expect("\^error: Frame index 10 is out of range") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("reviews.llvm.org/D6965: requires this patch") + def test_lldbmi_exec_finish(self): + """Test that 'lldb-mi --interpreter' works for -exec-finish.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Set argument 'l' + self.runCmd("-exec-arguments l") + self.expect("\^done") + + # Set BP at a_MyFunction_call and run to BP + self.runCmd("-break-insert -f a_MyFunction") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test that -exec-finish returns from a_MyFunction + self.runCmd("-exec-finish --thread 1 --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"main\"") + + # Run to BP inside b_MyFunction call + line = line_number('b.c', '//BP_b_MyFunction') + self.runCmd("-break-insert -f b.c:%d" % line) + self.expect("\^done,bkpt={number=\"2\"") + self.runCmd("-exec-continue") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test that -exec-finish hits BP at a_MyFunction call inside + # b_MyFunction (and that --thread is optional) + self.runCmd("-exec-finish --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test that -exec-finish returns from a_MyFunction call inside + # b_MyFunction (and that --frame is optional) + self.runCmd("-exec-finish --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"b_MyFunction\"") + + # Test that -exec-finish returns from b_MyFunction + # (and that both --thread and --frame are optional) + self.runCmd("-exec-finish") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"main\"") + + # Test that an invalid --thread is handled + self.runCmd("-exec-finish --thread 0") + self.expect("\^error,message=\"error: Thread index 0 is out of range") + self.runCmd("-exec-finish --thread 10") + self.expect("\^error,message=\"error: Thread index 10 is out of range") + + # Test that an invalid --frame is handled + # FIXME: no error is returned + #self.runCmd("-exec-finish --frame 10") + #self.expect("\^error: Frame index 10 is out of range") + + # Set BP at printf and run to BP + # FIXME: BP at printf not resolved and never hit! + self.runCmd("-interpreter-exec command \"b printf\"") #FIXME: self.runCmd("-break-insert -f printf") + self.expect("\^done") #FIXME: self.expect("\^done,bkpt={number=\"3\"") + self.runCmd("-exec-continue") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + ## Test that -exec-finish returns from printf + self.runCmd("-exec-finish --thread 1 --frame 0") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".*func=\"main\"") + +if __name__ == '__main__': + unittest2.main() Index: test/tools/lldb-mi/TestMiExit.py =================================================================== --- test/tools/lldb-mi/TestMiExit.py +++ test/tools/lldb-mi/TestMiExit.py @@ -0,0 +1,59 @@ +""" +Test that the lldb-mi driver works properly with "-gdb-exit". +""" + +import lldbmi_testcase +from lldbtest import * +import unittest2 + +class MiExitTestCase(lldbmi_testcase.MiTestCaseBase): + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + def test_lldbmi_gdbexit(self): + """Test that '-gdb-exit' terminates debug session and exits.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test -gdb-exit: try to exit and check that program is finished + self.runCmd("-gdb-exit") + self.expect("\^exit") + import pexpect + self.expect(pexpect.EOF) + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + def test_lldbmi_quit(self): + """Test that 'quit' exits immediately.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test quit: try to exit and check that program is finished + self.runCmd("quit") + import pexpect + self.expect(pexpect.EOF) + +if __name__ == '__main__': + unittest2.main() Index: test/tools/lldb-mi/TestMiInterrupt.py =================================================================== --- test/tools/lldb-mi/TestMiInterrupt.py +++ test/tools/lldb-mi/TestMiInterrupt.py @@ -9,8 +9,8 @@ class MiInterruptTestCase(lldbmi_testcase.MiTestCaseBase): @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") def test_lldbmi_interrupt(self): """Test that 'lldb-mi --interpreter' interrupt and resume a looping app.""" @@ -19,20 +19,20 @@ self.runCmd("-file-exec-and-symbols %s" % self.myexe) self.expect("\^done") - #run to main + # Run to main self.runCmd("-break-insert -f main") self.expect("\^done,bkpt={number=\"1\"") self.runCmd("-exec-run") self.expect("\^running") self.expect("\*stopped,reason=\"breakpoint-hit\"") - #set doloop=1 and run (to loop forever) + # Set doloop=1 and run (to loop forever) self.runCmd("-data-evaluate-expression \"doloop=1\"") self.expect("value=\"1\"") self.runCmd("-exec-continue") self.expect("\^running") - #issue interrupt, set BP in loop (marked BP_loop), and resume + # Issue interrupt, set BP in loop (marked BP_loop), and resume self.runCmd("-exec-interrupt") self.expect("\*stopped,reason=\"signal-received\"") line = line_number('loop.c', '//BP_loop') @@ -42,13 +42,55 @@ self.runCmd("-exec-continue") self.expect("\*stopped,reason=\"breakpoint-hit\"") - #we should have hit BP - #set loop=-1 so we'll exit the loop + # We should have hit BP + # Set loop=-1 so we'll exit the loop self.runCmd("-data-evaluate-expression \"loop=-1\"") self.expect("value=\"-1\"") self.runCmd("-exec-continue") self.expect("\^running") self.expect("\*stopped,reason=\"exited-normally\"") + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("lldb-mi how to send cntl-C to app?") + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_lldbmi_cntlC(self): + """Test that 'lldb-mi --interpreter' cntl-C interrupts app.""" + + self.spawnLldbMi(args = None) + + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Set doloop=1 and run (to loop forever) + self.runCmd("-var-create var2 --thread 1 --frame 0 * \"doloop=1\"") + self.expect("value=\"1\",type=\"int\"") + self.runCmd("-exec-continue") + self.expect("\^running") + + # Issue interrupt, set a bp, and resume + #FIXME: how to runCmd cntl-C? + self.runCmd("-exec-interrupt") # or cntl-c + self.expect("\*stopped,reason=\"signal-received\"") + self.runCmd("-break-insert loop.c:11") + self.expect("\^done,bkpt={number=\"2\"") + self.runCmd("-exec-continue") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # We should be sitting at loop.c:12 + # Set loop=-1 so we'll exit the loop + self.runCmd("-data-evaluate-expression \"loop=-1\"") + self.expect("value=\"-1\"") + self.runCmd("-exec-continue") + self.expect("\^running") + self.expect("\*stopped,reason=\"exited-normally\"") + if __name__ == '__main__': unittest2.main() Index: test/tools/lldb-mi/TestMiLaunch.py =================================================================== --- test/tools/lldb-mi/TestMiLaunch.py +++ test/tools/lldb-mi/TestMiLaunch.py @@ -15,7 +15,7 @@ self.spawnLldbMi(args = None) - #use no path + # Use no path self.runCmd("-file-exec-and-symbols %s" % self.myexe) self.expect("\^done") @@ -30,7 +30,7 @@ self.spawnLldbMi(args = None) - #use full path + # Use full path import os exe = os.path.join(os.getcwd(), self.myexe) self.runCmd("-file-exec-and-symbols %s" % exe) @@ -47,7 +47,7 @@ self.spawnLldbMi(args = None) - #use relative path + # Use relative path exe = "../../" + self.mydir + "/" + self.myexe self.runCmd("-file-exec-and-symbols %s" % exe) self.expect("\^done") @@ -63,7 +63,7 @@ self.spawnLldbMi(args = None) - #use non-existant path + # Use non-existant path exe = "badpath/" + self.myexe self.runCmd("-file-exec-and-symbols %s" % exe) self.expect("\^error") Index: test/tools/lldb-mi/TestMiNotification.py =================================================================== --- test/tools/lldb-mi/TestMiNotification.py +++ test/tools/lldb-mi/TestMiNotification.py @@ -0,0 +1,113 @@ +""" +Test that the lldb-mi driver nofities user properly. +""" + +import lldbmi_testcase +from lldbtest import * +import unittest2 + +class MiNotificationTestCase(lldbmi_testcase.MiTestCaseBase): + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("lldb-mi doesn't print prompt in all cases") + def test_lldbmi_prompt(self): + """Test that 'lldb-mi --interpreter' echos '(gdb)' after commands and events.""" + + self.spawnLldbMi(args = None) + + # Test that lldb-mi is ready after startup + self.expect(self.child_prompt, exactly = True) + + # Test that lldb-mi is ready after -file-exec-and-symbols + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + self.expect(self.child_prompt, exactly = True) + + # Test that lldb-mi is ready after -break-insert + self.runCmd("-break-insert -f b_MyFunction") + self.expect("\^done,bkpt={number=\"1\"") + self.expect(self.child_prompt, exactly = True) + + # Test that lldb-mi is ready after -exec-run + self.runCmd("-exec-run") + self.expect("\*running") + self.expect(self.child_prompt, exactly = True) + + # Test that lldb-mi is ready after BP hit + self.expect("\*stopped,reason=\"breakpoint-hit\"") + self.expect(self.child_prompt, exactly = True) + + # Test that lldb-mi is ready after -exec-continue + self.runCmd("-exec-continue") + self.expect("\^running") + self.expect(self.child_prompt, exactly = True) + + # Test that lldb-mi is ready after program exited + self.expect("\*stopped,reason=\"exited-normally\"") + self.expect(self.child_prompt, exactly = True) + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("reviews.llvm.org/D7273: requires this patch") + def test_lldbmi_stopped_when_stopatentry_local(self): + """Test that 'lldb-mi --interpreter' notifies after it was stopped on entry (local).""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run with stop-at-entry flag + self.runCmd("-interpreter-exec command \"process launch -s\"") + self.expect("\^done") + + # Test that *stopped is printed + self.expect("\*stopped,reason=\"signal-received\",signal=\"17\",thread-id=\"1\",stopped-threads=\"all\"") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("reviews.llvm.org/D7273: requires this patch") + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_lldbmi_stopped_when_stopatentry_remote(self): + """Test that 'lldb-mi --interpreter' notifies after it was stopped on entry (remote).""" + + # Prepare debugserver + import os, sys + lldb_gdbserver_folder = os.path.abspath(os.path.join(os.path.dirname(os.getcwd()), "lldb-gdbserver")) + sys.path.append(lldb_gdbserver_folder) + import lldbgdbserverutils + debugserver_exe = lldbgdbserverutils.get_debugserver_exe() + if not debugserver_exe: + raise Exception("debugserver not found") + hostname = "localhost" + import random + port = 12000 + random.randint(0,3999) # the same as GdbRemoteTestCaseBase.get_next_port + import pexpect + debugserver_child = pexpect.spawn("%s %s:%d" % (debugserver_exe, hostname, port)) + + self.spawnLldbMi(args = None) + + # Connect to debugserver + self.runCmd("-interpreter-exec command \"platform select remote-macosx --sysroot /\"") + self.expect("\^done") + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + self.runCmd("-interpreter-exec command \"process connect connect://%s:%d\"" % (hostname, port)) + self.expect("\^done") + + try: + # Run with stop-at-entry flag + self.runCmd("-interpreter-exec command \"process launch -s\"") + self.expect("\^done") + + # Test that *stopped is printed + self.expect("\*stopped,reason=\"signal-received\",signal=\"17\",thread-id=\"1\",stopped-threads=\"all\"") + + finally: + # Clean up + debugserver_child.terminate(force = True) + +if __name__ == '__main__': + unittest2.main() Index: test/tools/lldb-mi/TestMiProgramArgs.py =================================================================== --- test/tools/lldb-mi/TestMiProgramArgs.py +++ test/tools/lldb-mi/TestMiProgramArgs.py @@ -1,45 +0,0 @@ -""" -Test that the lldb-mi driver can pass arguments to the app. -""" - -import lldbmi_testcase -from lldbtest import * -import unittest2 - -class MiProgramArgsTestCase(lldbmi_testcase.MiTestCaseBase): - - @lldbmi_test - @unittest2.skip("lldb-mi can't pass params to app.") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") - def test_lldbmi_paramargs(self): - """Test that 'lldb-mi --interpreter' can pass arguments to the app.""" - - self.spawnLldbMi(args = None) - - self.runCmd("-file-exec-and-symbols %s" % self.myexe) - self.expect("\^done") - - self.runCmd("settings set target.run-args l") #FIXME: args not passed - #self.runCmd("-exec-arguments l") #FIXME: not recognized and hung lldb-mi - - #run to main - self.runCmd("-break-insert -f main") - self.expect("\^done,bkpt={number=\"1\"") - self.runCmd("-exec-run") - self.expect("\^running") - self.expect("\*stopped,reason=\"breakpoint-hit\"") - - #check argc to see if arg passed - self.runCmd("-data-evaluate-expression argc") - self.expect("value=\"2\"") - - #set BP on code which is only executed if "l" was passed correctly (marked BP_argtest) - line = line_number('main.c', '//BP_argtest') - self.runCmd("-break-insert main.c:%d" % line) - self.expect("\^done,bkpt={number=\"2\"") - self.runCmd("-exec-continue") - self.expect("\^running") - self.expect("\*stopped,reason=\"breakpoint-hit\"") - -if __name__ == '__main__': - unittest2.main() Index: test/tools/lldb-mi/TestMiStack.py =================================================================== --- test/tools/lldb-mi/TestMiStack.py +++ test/tools/lldb-mi/TestMiStack.py @@ -10,6 +10,7 @@ @lldbmi_test @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("-stack-list-locals doesn't work properly") def test_lldbmi_stackargs(self): """Test that 'lldb-mi --interpreter' can shows arguments.""" @@ -27,20 +28,21 @@ self.expect("\*stopped,reason=\"breakpoint-hit\"") # Test arguments - #self.runCmd("-stack-list-arguments 0") #FIXME: --no-values doesn't work - #self.expect("\^done,stack-args=\[frame={level=\"0\",args=\[name=\"argc\",name=\"argv\"\]}") + self.runCmd("-stack-list-arguments 0") #FIXME: --no-values doesn't work + self.expect("\^done,stack-args=\[frame={level=\"0\",args=\[name=\"argc\",name=\"argv\"\]}") self.runCmd("-stack-list-arguments 1") self.expect("\^done,stack-args=\[frame={level=\"0\",args=\[{name=\"argc\",value=\"1\"},{name=\"argv\",value=\".*\"}\]}") @lldbmi_test @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("-stack-list-locals doesn't work properly") def test_lldbmi_locals(self): """Test that 'lldb-mi --interpreter' can shows local variables.""" self.spawnLldbMi(args = None) # Load executable - self.runCmd("-file-exec-and-symbols %s" % (self.myexe)) + self.runCmd("-file-exec-and-symbols %s" % self.myexe) self.expect("\^done") # Run to main @@ -52,10 +54,54 @@ self.expect("\*stopped,reason=\"breakpoint-hit\"") # Test locals - #self.runCmd("-stack-list-locals 0") #FIXME: --no-values doesn't work - #self.expect("\^done,locals=\[name=\"a\",name=\"b\"\]") + self.runCmd("-stack-list-locals 0") #FIXME: --no-values doesn't work + self.expect("\^done,locals=\[name=\"a\",name=\"b\"\]") self.runCmd("-stack-list-locals 1") self.expect("\^done,locals=\[{name=\"a\",value=\"10\"},{name=\"b\",value=\"20\"}\]") + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + def test_lldbmi_stackdepth(self): + """Test that 'lldb-mi --interpreter' can shows depth of the stack.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test stack depth + self.runCmd("-stack-info-depth") + self.expect("\^done,depth=\"[1-9]\"") + + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + def test_lldbmi_stackframes(self): + """Test that 'lldb-mi --interpreter' can lists the frames on the stack.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to main + self.runCmd("-break-insert -f main") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test stack frame: get frame #0 info + self.runCmd("-stack-list-frames 0 0") + self.expect("\^done,stack=\[frame=\{level=\"0\",addr=\".+\",func=\"main\",file=\"main\.c\",fullname=\".*main\.c\",line=\".+\"\}\]") + if __name__ == '__main__': unittest2.main() Index: test/tools/lldb-mi/TestMiSyntax.py =================================================================== --- test/tools/lldb-mi/TestMiSyntax.py +++ test/tools/lldb-mi/TestMiSyntax.py @@ -20,7 +20,7 @@ self.expect("000\^done") # Run to main - self.runCmd("100000001-break-insert -f a_MyFunction") + self.runCmd("100000001-break-insert -f b_MyFunction") self.expect("100000001\^done,bkpt={number=\"1\"") self.runCmd("2-exec-run") self.expect("2\^running") @@ -31,5 +31,35 @@ self.expect("0000000000000000000003\^running") self.expect("\*stopped,reason=\"exited-normally\"") + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @unittest2.skip("lldb-mi doesn't handle special chars properly") + def test_lldbmi_specialchars(self): + """Test that 'lldb-mi --interpreter' handles complicated strings.""" + + self.spawnLldbMi(args = None) + + # Create alias for myexe + complicated_myexe = "C--mpl-x file's`s @#$%^&*()_+-={}[]| name" + if os.path.exists(complicated_myexe): + os.unlink(complicated_myexe) + os.symlink(self.myexe, complicated_myexe) + + try: + # Try to load executable with complicated filename + self.runCmd("-file-exec-and-symbols \"%s\"" % complicated_myexe) + self.expect("\^done") + + # Check that it was loaded correctly + self.runCmd("-break-insert -f a_MyFunction") + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + finally: + # Clean up + os.unlink(complicated_myexe) + if __name__ == '__main__': unittest2.main() Index: test/tools/lldb-mi/a.c =================================================================== --- test/tools/lldb-mi/a.c +++ test/tools/lldb-mi/a.c @@ -3,7 +3,6 @@ int a_MyFunction () { - // Set a breakpoint here. - printf ("a is about to return 10.\n"); + printf ("a is about to return 10.\n"); //BP_a_MyFunction return 10; } Index: test/tools/lldb-mi/b.c =================================================================== --- test/tools/lldb-mi/b.c +++ test/tools/lldb-mi/b.c @@ -1,9 +1,10 @@ #include +extern int a_MyFunction(); int b_MyFunction () { - // Set a breakpoint here. + (void)a_MyFunction(); //BP_b_MyFunction printf ("b is about to return 20.\n"); return 20; } Index: test/tools/lldb-mi/lldbmi_testcase.py =================================================================== --- test/tools/lldb-mi/lldbmi_testcase.py +++ test/tools/lldb-mi/lldbmi_testcase.py @@ -37,5 +37,7 @@ def runCmd(self, cmd): self.child.sendline(cmd) - def expect(self, pattern, *args, **kwargs): - self.child.expect(pattern, *args, **kwargs) + def expect(self, pattern, exactly=False, *args, **kwargs): + if exactly: + return self.child.expect_exact(pattern, *args, **kwargs) + return self.child.expect(pattern, *args, **kwargs) Index: test/tools/lldb-mi/main.c =================================================================== --- test/tools/lldb-mi/main.c +++ test/tools/lldb-mi/main.c @@ -17,10 +17,11 @@ int main (int argc, char const *argv[]) { int a, b; - printf("argc=%d\n", argc); - a = a_MyFunction(); - b = b_MyFunction(); - //BP_localstest + printf("argc=%d\n", argc); //BP_printf_call + //BP_argctest + a = a_MyFunction(); //BP_a_MyFunction_call + b = b_MyFunction(); //BP_b_MyFunction_call + //BP_localstest -- it must be at line #24 (or fix it in main*.micmds) if (doloop) infloop(); if (argc > 1 && *argv[1] == 'l') {