blob: e4727be484fd2b988dddcaae8a4ae443943116cc [file] [log] [blame]
Johnny Chena1affab2010-07-03 03:41:59 +00001"""
2LLDB module which provides the abstract base class of lldb test case.
3
4The concrete subclass can override lldbtest.TesBase in order to inherit the
5common behavior for unitest.TestCase.setUp/tearDown implemented in this file.
6
7The subclass should override the attribute mydir in order for the python runtime
8to locate the individual test cases when running as part of a large test suite
9or when running each test case as a separate python invocation.
10
11./dotest.py provides a test driver which sets up the environment to run the
12entire test suite. Users who want to run a test case on its own can specify the
13LLDB_TEST and PYTHONPATH environment variables, for example:
14
15$ export LLDB_TEST=$PWD
16$ export PYTHONPATH=/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:$LLDB_TEST
17$ echo $LLDB_TEST
18/Volumes/data/lldb/svn/trunk/test
19$ echo $PYTHONPATH
20/Volumes/data/lldb/svn/trunk/build/Debug/LLDB.framework/Resources/Python:/Volumes/data/lldb/svn/trunk/test
21$ python function_types/TestFunctionTypes.py
22.
23----------------------------------------------------------------------
24Ran 1 test in 0.363s
25
26OK
27$
28"""
29
30import os
Johnny Chen75e28f92010-08-05 23:42:46 +000031import unittest2
Johnny Chena1affab2010-07-03 03:41:59 +000032import lldb
33
Johnny Chen96f08d52010-08-09 22:01:17 +000034#
35# Some commonly used assert messages.
36#
37
38CURRENT_EXECUTABLE_SET = "Current executable set successfully"
39
Johnny Chend85dae52010-08-09 23:44:24 +000040RUN_STOPPED = "Process is stopped successfully"
Johnny Chen96f08d52010-08-09 22:01:17 +000041
Johnny Chend85dae52010-08-09 23:44:24 +000042RUN_COMPLETED = "Process exited successfully"
Johnny Chen96f08d52010-08-09 22:01:17 +000043
Johnny Chend85dae52010-08-09 23:44:24 +000044BREAKPOINT_CREATED = "Breakpoint created successfully"
45
Johnny Chen9b92c6e2010-08-17 21:33:31 +000046BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
47
Johnny Chend85dae52010-08-09 23:44:24 +000048BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen96f08d52010-08-09 22:01:17 +000049
50STOPPED_DUE_TO_BREAKPOINT = "Process state is stopped due to breakpoint"
51
52STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
53
54VARIABLES_DISPLAYED_CORRECTLY = "Show specified variable(s) correctly"
55
Johnny Chend85dae52010-08-09 23:44:24 +000056#
57# And a generic "Command '%s' returns successfully" message generator.
58#
59def CMD_MSG(command):
60 return "Command '%s' returns successfully" % (command)
61
62
Johnny Chen75e28f92010-08-05 23:42:46 +000063class TestBase(unittest2.TestCase):
Johnny Chena1affab2010-07-03 03:41:59 +000064 """This LLDB abstract base class is meant to be subclassed."""
65
66 # The concrete subclass should override this attribute.
Johnny Chenf8c723b2010-07-03 20:41:42 +000067 mydir = None
Johnny Chena1affab2010-07-03 03:41:59 +000068
Johnny Chenffde4fc2010-08-16 21:28:10 +000069 # State pertaining to the inferior process, if any.
70 runStarted = False
71
Johnny Chena1affab2010-07-03 03:41:59 +000072 def setUp(self):
Johnny Chen6ead27f2010-08-07 01:13:18 +000073 #import traceback
Johnny Chen88f83042010-08-05 21:23:45 +000074 #traceback.print_stack()
75
Johnny Chenf8c723b2010-07-03 20:41:42 +000076 # Fail fast if 'mydir' attribute is not overridden.
77 if not self.mydir or len(self.mydir) == 0:
78 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chena1affab2010-07-03 03:41:59 +000079 # Save old working directory.
80 self.oldcwd = os.getcwd()
81
82 # Change current working directory if ${LLDB_TEST} is defined.
83 # See also dotest.py which sets up ${LLDB_TEST}.
84 if ("LLDB_TEST" in os.environ):
85 os.chdir(os.path.join(os.environ["LLDB_TEST"], self.mydir));
86
87 # Create the debugger instance if necessary.
88 try:
89 self.dbg = lldb.DBG
Johnny Chena1affab2010-07-03 03:41:59 +000090 except AttributeError:
91 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf8c723b2010-07-03 20:41:42 +000092
Johnny Chena1affab2010-07-03 03:41:59 +000093 if not self.dbg.IsValid():
94 raise Exception('Invalid debugger instance')
95
96 # We want our debugger to be synchronous.
97 self.dbg.SetAsync(False)
98
99 # Retrieve the associated command interpreter instance.
100 self.ci = self.dbg.GetCommandInterpreter()
101 if not self.ci:
102 raise Exception('Could not get the command interpreter')
103
104 # And the result object.
105 self.res = lldb.SBCommandReturnObject()
106
Johnny Chena1affab2010-07-03 03:41:59 +0000107 def tearDown(self):
Johnny Chenffde4fc2010-08-16 21:28:10 +0000108 # Finish the inferior process, if it was "run" previously.
109 if self.runStarted:
110 self.ci.HandleCommand("continue", self.res)
111
Johnny Chena1affab2010-07-03 03:41:59 +0000112 del self.dbg
113
114 # Restore old working directory.
115 os.chdir(self.oldcwd)
Johnny Chen8df95eb2010-08-19 23:26:59 +0000116
117 def runCmd(self, cmd, msg=None, check=True):
118 """
119 Ask the command interpreter to handle the command and then check its
120 return status.
121 """
122 # Fail fast if 'cmd' is not meaningful.
123 if not cmd or len(cmd) == 0:
124 raise Exception("Bad 'cmd' parameter encountered")
125 self.ci.HandleCommand(cmd, self.res)
126 if cmd == "run":
127 self.runStarted = True
128 if check:
129 self.assertTrue(self.res.Succeeded(),
130 msg if msg else CMD_MSG(cmd))
131
132 def expect(self, cmd, msg, startstr=None, substrs=None):
133 """
134 Similar to runCmd; with additional expect style output matching ability.
135
136 Ask the command interpreter to handle the command and then check its
137 return status. The 'msg' parameter specifies an informational assert
138 message. We expect the output from running the command to start with
139 'startstr' and matches the substrings contained in 'substrs'.
140 """
141 # Fail fast if 'msg' is not meaningful.
142 if not msg or len(msg) == 0:
143 raise Exception("Bad 'msg' parameter encountered")
144 self.runCmd(cmd)
145
146 output = self.res.GetOutput()
147 matched = output.startswith(startstr) if startstr else True
148 if substrs:
149 for str in substrs:
150 matched = output.find(str) > 0
151 if not matched:
152 break
153
154 self.assertTrue(matched, msg)
155