blob: 8296a72002e25b8e19b6b63826a1e7e2bfd97b71 [file] [log] [blame]
Johnny Chenbf6ffa32010-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 Chenff3d01d2010-08-20 21:03:09 +000031import sys
Johnny Chen73258832010-08-05 23:42:46 +000032import unittest2
Johnny Chenbf6ffa32010-07-03 03:41:59 +000033import lldb
34
Johnny Chen00778092010-08-09 22:01:17 +000035#
36# Some commonly used assert messages.
37#
38
39CURRENT_EXECUTABLE_SET = "Current executable set successfully"
40
Johnny Chenff3d01d2010-08-20 21:03:09 +000041RUN_STOPPED = "Process is launched and then stopped successfully"
Johnny Chen00778092010-08-09 22:01:17 +000042
Johnny Chen17941842010-08-09 23:44:24 +000043RUN_COMPLETED = "Process exited successfully"
Johnny Chen00778092010-08-09 22:01:17 +000044
Johnny Chen17941842010-08-09 23:44:24 +000045BREAKPOINT_CREATED = "Breakpoint created successfully"
46
Johnny Chene76896c2010-08-17 21:33:31 +000047BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
48
Johnny Chen17941842010-08-09 23:44:24 +000049BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
Johnny Chen00778092010-08-09 22:01:17 +000050
51STOPPED_DUE_TO_BREAKPOINT = "Process state is stopped due to breakpoint"
52
53STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
54
55VARIABLES_DISPLAYED_CORRECTLY = "Show specified variable(s) correctly"
56
Johnny Chen17941842010-08-09 23:44:24 +000057#
58# And a generic "Command '%s' returns successfully" message generator.
59#
60def CMD_MSG(command):
61 return "Command '%s' returns successfully" % (command)
62
63
Johnny Chen73258832010-08-05 23:42:46 +000064class TestBase(unittest2.TestCase):
Johnny Chenbf6ffa32010-07-03 03:41:59 +000065 """This LLDB abstract base class is meant to be subclassed."""
66
67 # The concrete subclass should override this attribute.
Johnny Chenf02ec122010-07-03 20:41:42 +000068 mydir = None
Johnny Chenbf6ffa32010-07-03 03:41:59 +000069
Johnny Chen6ca006c2010-08-16 21:28:10 +000070 # State pertaining to the inferior process, if any.
71 runStarted = False
72
Johnny Chenbf6ffa32010-07-03 03:41:59 +000073 def setUp(self):
Johnny Chen9289a652010-08-07 01:13:18 +000074 #import traceback
Johnny Chena2124952010-08-05 21:23:45 +000075 #traceback.print_stack()
76
Johnny Chenf02ec122010-07-03 20:41:42 +000077 # Fail fast if 'mydir' attribute is not overridden.
78 if not self.mydir or len(self.mydir) == 0:
79 raise Exception("Subclasses must override the 'mydir' attribute.")
Johnny Chenbf6ffa32010-07-03 03:41:59 +000080 # Save old working directory.
81 self.oldcwd = os.getcwd()
82
83 # Change current working directory if ${LLDB_TEST} is defined.
84 # See also dotest.py which sets up ${LLDB_TEST}.
85 if ("LLDB_TEST" in os.environ):
86 os.chdir(os.path.join(os.environ["LLDB_TEST"], self.mydir));
87
88 # Create the debugger instance if necessary.
89 try:
90 self.dbg = lldb.DBG
Johnny Chenbf6ffa32010-07-03 03:41:59 +000091 except AttributeError:
92 self.dbg = lldb.SBDebugger.Create()
Johnny Chenf02ec122010-07-03 20:41:42 +000093
Johnny Chenbf6ffa32010-07-03 03:41:59 +000094 if not self.dbg.IsValid():
95 raise Exception('Invalid debugger instance')
96
97 # We want our debugger to be synchronous.
98 self.dbg.SetAsync(False)
99
100 # Retrieve the associated command interpreter instance.
101 self.ci = self.dbg.GetCommandInterpreter()
102 if not self.ci:
103 raise Exception('Could not get the command interpreter')
104
105 # And the result object.
106 self.res = lldb.SBCommandReturnObject()
107
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000108 def tearDown(self):
Johnny Chen6ca006c2010-08-16 21:28:10 +0000109 # Finish the inferior process, if it was "run" previously.
110 if self.runStarted:
111 self.ci.HandleCommand("continue", self.res)
112
Johnny Chenbf6ffa32010-07-03 03:41:59 +0000113 del self.dbg
114
115 # Restore old working directory.
116 os.chdir(self.oldcwd)
Johnny Chen27f212d2010-08-19 23:26:59 +0000117
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000118 def runCmd(self, cmd, msg=None, check=True, verbose=False):
Johnny Chen27f212d2010-08-19 23:26:59 +0000119 """
120 Ask the command interpreter to handle the command and then check its
121 return status.
122 """
123 # Fail fast if 'cmd' is not meaningful.
124 if not cmd or len(cmd) == 0:
125 raise Exception("Bad 'cmd' parameter encountered")
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000126
127 if verbose:
Johnny Chenff3d01d2010-08-20 21:03:09 +0000128 print >> sys.stderr, "runCmd:", cmd
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000129
Johnny Chen27f212d2010-08-19 23:26:59 +0000130 self.ci.HandleCommand(cmd, self.res)
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000131
Johnny Chena6480c12010-08-19 23:53:55 +0000132 if cmd.startswith("run"):
Johnny Chen27f212d2010-08-19 23:26:59 +0000133 self.runStarted = True
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000134
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000135 if verbose:
Johnny Chenff3d01d2010-08-20 21:03:09 +0000136 if self.res.Succeeded():
137 print >> sys.stderr, "output:", self.res.GetOutput()
138 else:
139 print >> sys.stderr, self.res.GetError()
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000140
Johnny Chen27f212d2010-08-19 23:26:59 +0000141 if check:
142 self.assertTrue(self.res.Succeeded(),
143 msg if msg else CMD_MSG(cmd))
144
Johnny Chen74f26b82010-08-20 19:17:39 +0000145 def expect(self, cmd, msg=None, startstr=None, substrs=None, verbose=False):
Johnny Chen27f212d2010-08-19 23:26:59 +0000146 """
147 Similar to runCmd; with additional expect style output matching ability.
148
149 Ask the command interpreter to handle the command and then check its
150 return status. The 'msg' parameter specifies an informational assert
151 message. We expect the output from running the command to start with
152 'startstr' and matches the substrings contained in 'substrs'.
153 """
Johnny Chen74f26b82010-08-20 19:17:39 +0000154
155 # First run the command.
Johnny Chen5bbb88f2010-08-20 17:57:32 +0000156 self.runCmd(cmd, verbose = (True if verbose else False))
Johnny Chen27f212d2010-08-19 23:26:59 +0000157
Johnny Chen74f26b82010-08-20 19:17:39 +0000158 # Then compare the output against expected strings.
Johnny Chen27f212d2010-08-19 23:26:59 +0000159 output = self.res.GetOutput()
160 matched = output.startswith(startstr) if startstr else True
Johnny Chenb145bba2010-08-20 18:25:15 +0000161
162 if not matched and startstr and verbose:
Johnny Chenff3d01d2010-08-20 21:03:09 +0000163 print >> sys.stderr, "Startstr not matched:", startstr
Johnny Chenb145bba2010-08-20 18:25:15 +0000164
Johnny Chen27f212d2010-08-19 23:26:59 +0000165 if substrs:
166 for str in substrs:
167 matched = output.find(str) > 0
168 if not matched:
Johnny Chenb145bba2010-08-20 18:25:15 +0000169 if verbose:
Johnny Chenff3d01d2010-08-20 21:03:09 +0000170 print >> sys.stderr, "Substring not matched:", str
Johnny Chen27f212d2010-08-19 23:26:59 +0000171 break
172
Johnny Chen74f26b82010-08-20 19:17:39 +0000173 self.assertTrue(matched, msg if msg else CMD_MSG(cmd))
Johnny Chen27f212d2010-08-19 23:26:59 +0000174