blob: 3edc980f28d581fe46a44b7089dbf6525e03440b [file] [log] [blame]
Johnny Chen9707bb62010-06-25 21:14:08 +00001#!/usr/bin/env python
2
3"""
4A simple testing framework for lldb using python's unit testing framework.
5
6Tests for lldb are written as python scripts which take advantage of the script
7bridging provided by LLDB.framework to interact with lldb core.
8
9A specific naming pattern is followed by the .py script to be recognized as
10a module which implements a test scenario, namely, Test*.py.
11
12To specify the directories where "Test*.py" python test scripts are located,
13you need to pass in a list of directory names. By default, the current
14working directory is searched if nothing is specified on the command line.
15"""
16
17import os
18import sys
Johnny Chen16b97472010-06-29 23:17:15 +000019import time
Johnny Chen75e28f92010-08-05 23:42:46 +000020import unittest2
Johnny Chen9707bb62010-06-25 21:14:08 +000021
Johnny Chen877c7e42010-08-07 00:16:07 +000022class _WritelnDecorator(object):
23 """Used to decorate file-like objects with a handy 'writeln' method"""
24 def __init__(self,stream):
25 self.stream = stream
26
27 def __getattr__(self, attr):
28 if attr in ('stream', '__getstate__'):
29 raise AttributeError(attr)
30 return getattr(self.stream,attr)
31
32 def writeln(self, arg=None):
33 if arg:
34 self.write(arg)
35 self.write('\n') # text-mode streams translate to \r\n if needed
36
Johnny Chen9707bb62010-06-25 21:14:08 +000037#
38# Global variables:
39#
40
41# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000042suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000043
44# Default verbosity is 0.
45verbose = 0
46
47# By default, search from the current working directory.
48testdirs = [ os.getcwd() ]
49
Johnny Chen877c7e42010-08-07 00:16:07 +000050# Separator string.
51separator = '-' * 70
52
53# Decorated sys.stdout.
54out = _WritelnDecorator(sys.stdout)
55
Johnny Chen9707bb62010-06-25 21:14:08 +000056
57def usage():
58 print """
59Usage: dotest.py [option] [args]
60where options:
61-h : print this help message and exit (also --help)
62-v : do verbose mode of unittest framework
63
64and:
65args : specify a list of directory names to search for python Test*.py scripts
66 if empty, search from the curret working directory, instead
Johnny Chen58f93922010-06-29 23:10:39 +000067
68Running of this script also sets up the LLDB_TEST environment variable so that
69individual test cases can locate their supporting files correctly.
Johnny Chen9707bb62010-06-25 21:14:08 +000070"""
71
72
73def setupSysPath():
74 """Add LLDB.framework/Resources/Python to the search paths for modules."""
75
76 # Get the directory containing the current script.
Johnny Chena1affab2010-07-03 03:41:59 +000077 scriptPath = sys.path[0]
78 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +000079 print "This script expects to reside in lldb's test directory."
80 sys.exit(-1)
81
Johnny Chena1affab2010-07-03 03:41:59 +000082 os.environ["LLDB_TEST"] = scriptPath
Johnny Chen58f93922010-06-29 23:10:39 +000083
Johnny Chena1affab2010-07-03 03:41:59 +000084 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen9707bb62010-06-25 21:14:08 +000085 dbgPath = os.path.join(base, 'build', 'Debug', 'LLDB.framework',
86 'Resources', 'Python')
87 relPath = os.path.join(base, 'build', 'Release', 'LLDB.framework',
88 'Resources', 'Python')
89
90 lldbPath = None
91 if os.path.isfile(os.path.join(dbgPath, 'lldb.py')):
92 lldbPath = dbgPath
93 elif os.path.isfile(os.path.join(relPath, 'lldb.py')):
94 lldbPath = relPath
95
96 if not lldbPath:
97 print 'This script requires lldb.py to be in either ' + dbgPath,
98 print ' or' + relPath
99 sys.exit(-1)
100
101 sys.path.append(lldbPath)
Johnny Chena1affab2010-07-03 03:41:59 +0000102 sys.path.append(scriptPath)
Johnny Chen9707bb62010-06-25 21:14:08 +0000103
104
105def initTestdirs():
106 """Initialize the list of directories containing our unittest scripts.
107
108 '-h/--help as the first option prints out usage info and exit the program.
109 """
110
111 global verbose
112 global testdirs
113
114 if len(sys.argv) == 1:
115 pass
116 elif sys.argv[1].find('-h') != -1:
117 # Print usage info and exit.
118 usage()
119 sys.exit(0)
120 else:
121 # Process possible verbose flag.
122 index = 1
123 if sys.argv[1].find('-v') != -1:
124 verbose = 2
125 index += 1
126
127 # Gather all the dirs passed on the command line.
128 if len(sys.argv) > index:
129 testdirs = map(os.path.abspath, sys.argv[index:])
130
Johnny Chen9707bb62010-06-25 21:14:08 +0000131
132def visit(prefix, dir, names):
133 """Visitor function for os.path.walk(path, visit, arg)."""
134
135 global suite
136
137 for name in names:
138 if os.path.isdir(os.path.join(dir, name)):
139 continue
140
141 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
142 # We found a pattern match for our test case. Add it to the suite.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000143 if not sys.path.count(dir):
144 sys.path.append(dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000145 base = os.path.splitext(name)[0]
Johnny Chen75e28f92010-08-05 23:42:46 +0000146 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000147
148
149#
150# Start the actions by first setting up the module search path for lldb,
151# followed by initializing the test directories, and then walking the directory
152# trees, while collecting the tests into our test suite.
153#
154setupSysPath()
155initTestdirs()
156for testdir in testdirs:
157 os.path.walk(testdir, visit, 'Test')
158
159# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chen877c7e42010-08-07 00:16:07 +0000160out.writeln(separator)
161out.writeln("Collected %d test%s" % (suite.countTestCases(),
162 suite.countTestCases() != 1 and "s" or ""))
163out.writeln()
Johnny Chen1bfbd412010-06-29 19:44:16 +0000164
165# For the time being, let's bracket the test runner within the
166# lldb.SBDebugger.Initialize()/Terminate() pair.
167import lldb
168lldb.SBDebugger.Initialize()
169
Johnny Chen909e5a62010-07-01 22:52:57 +0000170# Create a singleton SBDebugger in the lldb namespace.
171lldb.DBG = lldb.SBDebugger.Create()
172
173# Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
174# is defined. Use ${LLDB_LOG} to specify the log file.
175ci = lldb.DBG.GetCommandInterpreter()
176res = lldb.SBCommandReturnObject()
177if ("LLDB_LOG" in os.environ):
178 ci.HandleCommand(
179 "log enable -f " + os.environ["LLDB_LOG"] + " lldb default", res)
Johnny Chen797674b2010-07-02 20:35:23 +0000180 if not res.Succeeded():
181 raise Exception('log enable failed (check your LLDB_LOG env variable...')
Johnny Chen909e5a62010-07-01 22:52:57 +0000182
Johnny Chen7987ac92010-08-09 20:40:52 +0000183# Install the control-c handler.
184unittest2.signals.installHandler()
185
186# Invoke the default TextTestRunner to run the test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +0000187unittest2.TextTestRunner(verbosity=verbose).run(suite)
Johnny Chen1bfbd412010-06-29 19:44:16 +0000188
Johnny Chen16b97472010-06-29 23:17:15 +0000189# Add some delay before calling SBDebugger.Terminate().
190time.sleep(1)
Johnny Chen1bfbd412010-06-29 19:44:16 +0000191lldb.SBDebugger.Terminate()