diff options
Diffstat (limited to 'lldb')
| -rwxr-xr-x | lldb/test/dotest.py | 42 | ||||
| -rw-r--r-- | lldb/test/lldbtest.py | 35 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/Makefile | 5 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/TestMiBreakpoint.py | 234 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/TestMiEvaluate.py | 162 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/TestMiInterrupt.py | 115 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/TestMiLaunch.py | 229 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/TestMiProgramArgs.py | 101 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/a.c | 9 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/b.c | 9 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/loop.c | 14 | ||||
| -rw-r--r-- | lldb/test/tools/lldb-mi/main.c | 31 |
12 files changed, 985 insertions, 1 deletions
diff --git a/lldb/test/dotest.py b/lldb/test/dotest.py index aa5ff714d32..0dd9652a93b 100755 --- a/lldb/test/dotest.py +++ b/lldb/test/dotest.py @@ -116,6 +116,12 @@ dont_do_python_api_test = False # By default, both command line and Python API tests are performed. just_do_python_api_test = False +# By default, lldb-mi tests are performed if lldb-mi can be found. +# Use @lldbmi_test decorator, defined in lldbtest.py, to mark a test as +# a lldb-mi test. +dont_do_lldbmi_test = False +just_do_lldbmi_test = False + # By default, benchmarks tests are not run. just_do_benchmarks_test = False @@ -429,6 +435,8 @@ def parseOptionsAndInitTestdirs(): global dont_do_python_api_test global just_do_python_api_test + global dont_do_lldbmi_test + global just_do_lldbmi_test global just_do_benchmarks_test global dont_do_dsym_test global dont_do_dwarf_test @@ -504,6 +512,8 @@ def parseOptionsAndInitTestdirs(): group.add_argument('-f', metavar='filterspec', action='append', help='Specify a filter, which consists of the test class name, a dot, followed by the test method, to only admit such test into the test suite') # FIXME: Example? X('-g', 'If specified, the filterspec by -f is not exclusive, i.e., if a test module does not match the filterspec (testclass.testmethod), the whole module is still admitted to the test suite') X('-l', "Don't skip long running tests") + X('-m', "Don't do lldb-mi tests") + X('+m', "Just do lldb-mi tests. Do not specify along with '+m'", dest='plus_m') group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite') group.add_argument('-X', metavar='directory', help="Exclude a directory from consideration for test discovery. -X types => if 'types' appear in the pathname components of a potential testfile, it will be ignored") group.add_argument('-G', '--category', metavar='category', action='append', dest='categoriesList', help=textwrap.dedent('''Specify categories of test cases of interest. Can be specified more than once.''')) @@ -676,6 +686,15 @@ def parseOptionsAndInitTestdirs(): if args.l: skip_long_running_test = False + if args.m: + dont_do_lldbmi_test = True + + if args.plus_m: + if dont_do_lldbmi_test: + print "Warning: -m and +m can't both be specified! Using only -m" + else: + just_do_lldbmi_test = True + if args.framework: lldbFrameworkPath = args.framework @@ -763,6 +782,10 @@ def parseOptionsAndInitTestdirs(): if dont_do_python_api_test and just_do_python_api_test: usage(parser) + # Do not specify both '-m' and '+m' at the same time. + if dont_do_lldbmi_test and just_do_lldbmi_test: + usage(parser) + if args.lldb_platform_name: lldb_platform_name = args.lldb_platform_name if args.lldb_platform_url: @@ -917,6 +940,7 @@ def setupSysPath(): # We'll try to locate the appropriate executable right here. lldbExec = None + lldbMiExec = None if lldbExecutablePath: if is_exe(lldbExecutablePath): lldbExec = lldbExecutablePath @@ -984,6 +1008,20 @@ def setupSysPath(): os.environ["LLDB_EXEC"] = lldbExec #print "The 'lldb' from PATH env variable", lldbExec + # Assume lldb-mi is in same place as lldb + # If not found, disable the lldb-mi tests + global dont_do_lldbmi_test + if is_exe(lldbExec + "-mi"): + lldbMiExec = lldbExec + "-mi" + if not lldbMiExec: + dont_do_lldbmi_test = True + if just_do_lldbmi_test: + print "The 'lldb-mi' executable cannot be located. The lldb-mi tests can not be run as a result." + else: + print "The 'lldb-mi' executable cannot be located. Some of the tests may not be run as a result." + else: + os.environ["LLDBMI_EXEC"] = lldbMiExec + # Skip printing svn/git information when running in parsable (lit-test compatibility) mode if not svn_silent and not parsable: if os.path.isdir(os.path.join(base, '.svn')) and which("svn") is not None: @@ -1314,6 +1352,8 @@ lldb.lldbtest_remote_shell_template = lldbtest_remote_shell_template # Put all these test decorators in the lldb namespace. lldb.dont_do_python_api_test = dont_do_python_api_test lldb.just_do_python_api_test = just_do_python_api_test +lldb.dont_do_lldbmi_test = dont_do_lldbmi_test +lldb.just_do_lldbmi_test = just_do_lldbmi_test lldb.just_do_benchmarks_test = just_do_benchmarks_test lldb.dont_do_dsym_test = dont_do_dsym_test lldb.dont_do_dwarf_test = dont_do_dwarf_test @@ -1750,4 +1790,4 @@ if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ): subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())]) # Exiting. -exitTestSuite(failed)
\ No newline at end of file +exitTestSuite(failed) diff --git a/lldb/test/lldbtest.py b/lldb/test/lldbtest.py index 9abc4b54c44..c926db499e7 100644 --- a/lldb/test/lldbtest.py +++ b/lldb/test/lldbtest.py @@ -334,6 +334,23 @@ def python_api_test(func): wrapper.__python_api_test__ = True return wrapper +def lldbmi_test(func): + """Decorate the item as a lldb-mi only test.""" + if isinstance(func, type) and issubclass(func, unittest2.TestCase): + raise Exception("@lldbmi_test can only be used to decorate a test method") + @wraps(func) + def wrapper(self, *args, **kwargs): + try: + if lldb.dont_do_lldbmi_test: + self.skipTest("lldb-mi tests") + except AttributeError: + pass + return func(self, *args, **kwargs) + + # Mark this function as such to separate them from lldb command line tests. + wrapper.__lldbmi_test__ = True + return wrapper + def benchmarks_test(func): """Decorate the item as a benchmarks test.""" if isinstance(func, type) and issubclass(func, unittest2.TestCase): @@ -773,6 +790,11 @@ class Base(unittest2.TestCase): self.lldbExec = os.environ["LLDB_EXEC"] else: self.lldbExec = None + if "LLDBMI_EXEC" in os.environ: + self.lldbMiExec = os.environ["LLDBMI_EXEC"] + else: + self.lldbMiExec = None + self.dont_do_lldbmi_test = True if "LLDB_HERE" in os.environ: self.lldbHere = os.environ["LLDB_HERE"] else: @@ -805,6 +827,19 @@ class Base(unittest2.TestCase): except AttributeError: pass + # lldb-mi only test is decorated with @lldbmi_test, + # which also sets the "__lldbmi_test__" attribute of the + # function object to True. + try: + if lldb.just_do_lldbmi_test: + testMethod = getattr(self, self._testMethodName) + if getattr(testMethod, "__lldbmi_test__", False): + pass + else: + self.skipTest("non lldb-mi test") + except AttributeError: + pass + # Benchmarks test is decorated with @benchmarks_test, # which also sets the "__benchmarks_test__" attribute of the # function object to True. diff --git a/lldb/test/tools/lldb-mi/Makefile b/lldb/test/tools/lldb-mi/Makefile new file mode 100644 index 00000000000..a85f73eab35 --- /dev/null +++ b/lldb/test/tools/lldb-mi/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c a.c b.c loop.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/tools/lldb-mi/TestMiBreakpoint.py b/lldb/test/tools/lldb-mi/TestMiBreakpoint.py new file mode 100644 index 00000000000..a45ec5a14a9 --- /dev/null +++ b/lldb/test/tools/lldb-mi/TestMiBreakpoint.py @@ -0,0 +1,234 @@ +""" +Test that the lldb-mi driver understands an MI breakpoint command. +""" + +import os +import unittest2 +import lldb +from lldbtest import * + +class MiBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + myexe = "a.out" + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + try: + os.remove("child_send.txt") + os.remove("child_read.txt") + os.remove(cls.myexe) + except: + pass + + @lldbmi_test + def test_lldbmi_pendbreakonsym(self): + """Test that 'lldb-mi --interpreter' works for pending symbol breakpoints.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + child.send("-file-exec-and-symbols " + self.myexe) + child.sendline('') + child.expect("\^done") + + child.send("-break-insert -f a_MyFunction") + child.sendline('') + child.expect("\^done,bkpt={number=\"1\"") + + child.send("-exec-run") + child.sendline('') # FIXME: lldb-mi hangs here, so the extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"exited-normally\"") + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + self.expect(from_child, exe=False, + substrs = ["breakpoint-hit"]) + + @lldbmi_test + def test_lldbmi_pendbreakonsrc(self): + """Test that 'lldb-mi --interpreter' works for pending source breakpoints.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + child.send("-file-exec-and-symbols " + self.myexe) + child.sendline('') + child.expect("\^done") + + child.send("-break-insert -f main.c:22") + child.sendline('') + child.expect("\^done,bkpt={number=\"1\"") + + child.send("-exec-run") + child.sendline('') # FIXME: lldb-mi hangs here, so the extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"exited-normally\"") + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + self.expect(from_child, exe=False, + substrs = ["breakpoint-hit"]) + + @lldbmi_test + def test_lldbmi_breakpoints(self): + """Test that 'lldb-mi --interpreter' works for breakpoints.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + child.send("-file-exec-and-symbols " + self.myexe) + child.sendline('') + child.expect("\^done") + + child.send("-break-insert -f main") + child.sendline('') + child.expect("\^done,bkpt={number=\"1\"") + + child.send("-exec-run") + child.sendline('') # FIXME: lldb-mi hangs here, so the extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + #break on symbol + child.send("-break-insert a_MyFunction") + child.sendline('') + child.expect("\^done,bkpt={number=\"2\"") + + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + #break on source + child.send("-break-insert main.c:29") + child.sendline('') + child.expect("\^done,bkpt={number=\"3\"") + + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + #run to exit + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"exited-normally\"") + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + self.expect(from_child, exe=False, + substrs = ["breakpoint-hit"]) + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/tools/lldb-mi/TestMiEvaluate.py b/lldb/test/tools/lldb-mi/TestMiEvaluate.py new file mode 100644 index 00000000000..87b2da080f9 --- /dev/null +++ b/lldb/test/tools/lldb-mi/TestMiEvaluate.py @@ -0,0 +1,162 @@ +""" +Test that the lldb-mi driver can evaluate expressions. +""" + +import os +import unittest2 +import lldb +from lldbtest import * + +class MiEvaluateTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + myexe = "a.out" + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + try: + os.remove("child_send.txt") + os.remove("child_read.txt") + os.remove(cls.myexe) + except: + pass + + @lldbmi_test + def test_lldbmi_eval(self): + """Test that 'lldb-mi --interpreter' works for evaluating.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + child.send("-file-exec-and-symbols " + self.myexe) + child.sendline('') + child.expect("\^done") + + #run to main + child.send("-break-insert -f main") + child.sendline('') + child.expect("\^done,bkpt={number=\"1\"") + + child.send("-exec-run") + child.sendline('') #FIXME: hangs here; extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + #run to program return + child.send("-break-insert main.c:30") #BP_source + child.sendline('') + child.expect("\^done,bkpt={number=\"2\"") + + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + #print non-existant variable + #child.send("-var-create var1 --thread 1 --frame 0 * undef") + #child.sendline('') #FIXME: shows undef as {...} + #child.expect("error") + #child.send("-data-evaluate-expression undef") + #child.sendline('') #FIXME: gets value="undef" + #child.expect("error") + + #print global "g_MyVar" + child.send("-var-create var1 --thread 1 --frame 0 * g_MyVar") + child.sendline('') #FIXME: shows name=<unnamedvariable>" + child.expect("value=\"3\",type=\"int\"") + #child.send("-var-evaluate-expression var1") + #child.sendline('') #FIXME: gets var1 does not exist + child.send("-var-show-attributes var1") + child.sendline('') + child.expect("status=\"editable\"") + child.send("-var-delete var1") + child.sendline('') + child.expect("\^done") + child.send("-var-create var1 --thread 1 --frame 0 * g_MyVar") + child.sendline('') + child.expect("value=\"3\",type=\"int\"") + + #print static "s_MyVar" and modify + child.send("-data-evaluate-expression s_MyVar") + child.sendline('') + child.expect("value=\"30\"") + child.send("-var-create var3 --thread 1 --frame 0 * \"s_MyVar=3\"") + child.sendline('') + child.expect("value=\"3\",type=\"int\"") + child.send("-data-evaluate-expression \"s_MyVar=30\"") + child.sendline('') + child.expect("value=\"30\"") + + #print local "b" and modify + child.send("-data-evaluate-expression b") + child.sendline('') + child.expect("value=\"20\"") + child.send("-var-create var3 --thread 1 --frame 0 * \"b=3\"") + child.sendline('') + child.expect("value=\"3\",type=\"int\"") + child.send("-data-evaluate-expression \"b=20\"") + child.sendline('') + child.expect("value=\"20\"") + + #print "a + b" + child.send("-data-evaluate-expression \"a + b\"") + child.sendline('') + child.expect("value=\"30\"") + child.send("-var-create var3 --thread 1 --frame 0 * \"a + b\"") + child.sendline('') + child.expect("value=\"30\",type=\"int\"") + + #print "argv[0]" + child.send("-data-evaluate-expression \"argv[0]\"") + child.sendline('') + child.expect("value=\"0x") + child.send("-var-create var3 --thread 1 --frame 0 * \"argv[0]\"") + child.sendline('') + child.expect("numchild=\"1\",value=\"0x.*\",type=\"const char \*\"") + + #run to exit + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"exited-normally\"") + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/tools/lldb-mi/TestMiInterrupt.py b/lldb/test/tools/lldb-mi/TestMiInterrupt.py new file mode 100644 index 00000000000..e86111a393b --- /dev/null +++ b/lldb/test/tools/lldb-mi/TestMiInterrupt.py @@ -0,0 +1,115 @@ +""" +Test that the lldb-mi driver can interrupt and resume a looping app. +""" + +import os +import unittest2 +import lldb +from lldbtest import * + +class MiInterruptTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + myexe = "a.out" + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + try: + os.remove("child_send.txt") + os.remove("child_read.txt") + os.remove(cls.myexe) + except: + pass + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @lldbmi_test + def test_lldbmi_interrupt(self): + """Test that 'lldb-mi --interpreter' interrupt and resume a looping app.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + child.send("-file-exec-and-symbols " + self.myexe) + child.sendline('') + child.expect("\^done") + + #run to main + child.send("-break-insert -f main") + child.sendline('') + child.expect("\^done,bkpt={number=\"1\"") + child.send("-exec-run") + child.sendline('') #FIXME: hangs here; extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + #set doloop=1 and run (to loop forever) + child.send("-data-evaluate-expression \"doloop=1\"") + child.sendline('') + child.expect("value=\"1\"") + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + + #issue interrupt, set a bp, and resume + child.send("-exec-interrupt") + child.sendline('') + child.expect("\*stopped,reason=\"signal-received\"") + child.send("-break-insert loop.c:11") + child.sendline('') + child.expect("\^done,bkpt={number=\"2\"") + #child.send("-exec-resume") + #child.sendline('') #FIXME: command not recognized + child.send("-exec-continue") + child.sendline('') + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + #we should be sitting at loop.c:12 + #set loop=-1 so we'll exit the loop + child.send("-data-evaluate-expression \"loop=-1\"") + child.sendline('') + child.expect("value=\"-1\"") + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"exited-normally\"") + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/tools/lldb-mi/TestMiLaunch.py b/lldb/test/tools/lldb-mi/TestMiLaunch.py new file mode 100644 index 00000000000..90470b074d6 --- /dev/null +++ b/lldb/test/tools/lldb-mi/TestMiLaunch.py @@ -0,0 +1,229 @@ +""" +Test various ways the lldb-mi driver can launch a program. +""" + +import os +import unittest2 +import lldb +from lldbtest import * + +class MiLaunchTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + myexe = "a.out" + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + try: + os.remove("child_send.txt") + os.remove("child_read.txt") + os.remove(cls.myexe) + except: + pass + + @lldbmi_test + def test_lldbmi_exe(self): + """Test that 'lldb-mi --interpreter' works for -file-exec-and-symbols exe.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + #use no path + child.send("-file-exec-and-symbols " + self.myexe) + child.sendline('') + child.expect("\^done") + + child.send("-exec-run") + child.sendline('') # FIXME: lldb-mi hangs here, so the extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"exited-normally\"") + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + @lldbmi_test + def test_lldbmi_abspathexe(self): + """Test that 'lldb-mi --interpreter' works for -file-exec-and-symbols fullpath/exe.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + #use full path + exe = os.path.join(os.getcwd(), "a.out") + child.send("-file-exec-and-symbols " + exe) + child.sendline('') + child.expect("\^done") + + child.send("-exec-run") + child.sendline('') # FIXME: lldb-mi hangs here, so the extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"exited-normally\"") + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + @lldbmi_test + def test_lldbmi_relpathexe(self): + """Test that 'lldb-mi --interpreter' works for -file-exec-and-symbols relpath/exe.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + #use relative path + exe = "../../" + self.mydir + "/" + self.myexe + child.send("-file-exec-and-symbols " + exe) + child.sendline('') + child.expect("\^done") + + child.send("-exec-run") + child.sendline('') # FIXME: lldb-mi hangs here, so the extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"exited-normally\"") + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + @unittest2.skip("lldb-mi badpath hang") + @lldbmi_test + def test_lldbmi_badpathexe(self): + """Test that 'lldb-mi --interpreter' works for -file-exec-and-symbols badpath/exe.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + #use relative path + exe = "badpath/" + self.myexe + #print ("-file-exec-and-symbols " + exe) + child.send("-file-exec-and-symbols " + exe) + child.sendline('') #FIXME: non-existant directory caused hang + child.expect("\^error") + + child.expect_exact(prompt) + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/tools/lldb-mi/TestMiProgramArgs.py b/lldb/test/tools/lldb-mi/TestMiProgramArgs.py new file mode 100644 index 00000000000..49274299c81 --- /dev/null +++ b/lldb/test/tools/lldb-mi/TestMiProgramArgs.py @@ -0,0 +1,101 @@ +""" +Test that the lldb-mi driver can pass arguments to the app. +""" + +import os +import unittest2 +import lldb +from lldbtest import * + +class MiProgramArgsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + myexe = "a.out" + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + try: + os.remove("child_send.txt") + os.remove("child_read.txt") + os.remove(cls.myexe) + except: + pass + + @unittest2.skip("lldb-mi can't pass params to app.") + @lldbmi_test + def test_lldbmi_paramargs(self): + """Test that 'lldb-mi --interpreter' can pass arguments to the app.""" + import pexpect + self.buildDefault() + + # The default lldb-mi prompt (seriously?!). + prompt = "(gdb)" + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec)) + child = self.child + child.setecho(True) + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + child.send("-file-exec-and-symbols " + self.myexe) + child.sendline('') + child.expect("\^done") + + #child.send("-exec-arguments l") + #child.sendline('') #FIXME: not recognized and hung lldb-mi + child.send("settings set target.run-args l") + child.sendline('') #FIXME: args not passed + + #run to main + child.send("-break-insert -f main") + child.sendline('') + child.expect("\^done,bkpt={number=\"1\"") + child.send("-exec-run") + child.sendline('') #FIXME: hangs here; extra return below is needed + child.send("") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + #check argc to see if arg passed + child.send("-data-evaluate-expression argc") + child.sendline('') + child.expect("value=\"2\"") + + #set BP on code which is only executed if "l" was passed correctly + child.send("-break-insert main.c:27") #BP_argtest + child.sendline('') + child.expect("\^done,bkpt={number=\"2\"") + child.send("-exec-continue") + child.sendline('') + child.expect("\^running") + child.expect("\*stopped,reason=\"breakpoint-hit\"") + + child.send("quit") + child.sendline('') + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/tools/lldb-mi/a.c b/lldb/test/tools/lldb-mi/a.c new file mode 100644 index 00000000000..870e4a6ab16 --- /dev/null +++ b/lldb/test/tools/lldb-mi/a.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int +a_MyFunction () +{ + // Set a breakpoint here. + printf ("a is about to return 10.\n"); + return 10; +} diff --git a/lldb/test/tools/lldb-mi/b.c b/lldb/test/tools/lldb-mi/b.c new file mode 100644 index 00000000000..02b78e7bd85 --- /dev/null +++ b/lldb/test/tools/lldb-mi/b.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int +b_MyFunction () +{ + // Set a breakpoint here. + printf ("b is about to return 20.\n"); + return 20; +} diff --git a/lldb/test/tools/lldb-mi/loop.c b/lldb/test/tools/lldb-mi/loop.c new file mode 100644 index 00000000000..c868fdb9316 --- /dev/null +++ b/lldb/test/tools/lldb-mi/loop.c @@ -0,0 +1,14 @@ +#include <unistd.h> +int +infloop () +{ + int loop = 1; + while (loop > 0) { + if (loop > 10) { + sleep(1); + loop = 1; + } + loop++; // Set break point at this line. + } + return loop; +} diff --git a/lldb/test/tools/lldb-mi/main.c b/lldb/test/tools/lldb-mi/main.c new file mode 100644 index 00000000000..3e16f089104 --- /dev/null +++ b/lldb/test/tools/lldb-mi/main.c @@ -0,0 +1,31 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +extern int a_MyFunction(); +extern int b_MyFunction(); +extern int infloop(); +int doloop; +int g_MyVar = 3; +static int s_MyVar = 4; +int main (int argc, char const *argv[]) +{ + int a, b; + printf("argc=%d\n", argc); + a = a_MyFunction(); + b = b_MyFunction(); + if (doloop) + infloop(); + if (argc > 1 && *argv[1] == 'l') { + a++; + printf("a=%d, argv[1]=%s\n", a, argv[1]); //BP_argtest + } + s_MyVar = a + b; + return a + b - s_MyVar; //BP_source +} |

