Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: third_party/twisted_8_1/twisted/scripts/trial.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.trial.test.test_script -*-
2
3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6
7 import sys, os, random, gc, time, warnings
8
9 from twisted.internet import defer
10 from twisted.application import app
11 from twisted.python import usage, reflect, failure
12 from twisted import plugin
13 from twisted.python.util import spewer
14 from twisted.python.compat import set
15 from twisted.trial import runner, itrial, reporter
16
17
18 # Yea, this is stupid. Leave it for for command-line compatibility for a
19 # while, though.
20 TBFORMAT_MAP = {
21 'plain': 'default',
22 'default': 'default',
23 'emacs': 'brief',
24 'brief': 'brief',
25 'cgitb': 'verbose',
26 'verbose': 'verbose'
27 }
28
29
30 def _parseLocalVariables(line):
31 """Accepts a single line in Emacs local variable declaration format and
32 returns a dict of all the variables {name: value}.
33 Raises ValueError if 'line' is in the wrong format.
34
35 See http://www.gnu.org/software/emacs/manual/html_node/File-Variables.html
36 """
37 paren = '-*-'
38 start = line.find(paren) + len(paren)
39 end = line.rfind(paren)
40 if start == -1 or end == -1:
41 raise ValueError("%r not a valid local variable declaration" % (line,))
42 items = line[start:end].split(';')
43 localVars = {}
44 for item in items:
45 if len(item.strip()) == 0:
46 continue
47 split = item.split(':')
48 if len(split) != 2:
49 raise ValueError("%r contains invalid declaration %r"
50 % (line, item))
51 localVars[split[0].strip()] = split[1].strip()
52 return localVars
53
54
55 def loadLocalVariables(filename):
56 """Accepts a filename and attempts to load the Emacs variable declarations
57 from that file, simulating what Emacs does.
58
59 See http://www.gnu.org/software/emacs/manual/html_node/File-Variables.html
60 """
61 f = file(filename, "r")
62 lines = [f.readline(), f.readline()]
63 f.close()
64 for line in lines:
65 try:
66 return _parseLocalVariables(line)
67 except ValueError:
68 pass
69 return {}
70
71
72 def getTestModules(filename):
73 testCaseVar = loadLocalVariables(filename).get('test-case-name', None)
74 if testCaseVar is None:
75 return []
76 return testCaseVar.split(',')
77
78
79 def isTestFile(filename):
80 """Returns true if 'filename' looks like a file containing unit tests.
81 False otherwise. Doesn't care whether filename exists.
82 """
83 basename = os.path.basename(filename)
84 return (basename.startswith('test_')
85 and os.path.splitext(basename)[1] == ('.py'))
86
87
88 def _zshReporterAction():
89 return "(%s)" % (" ".join([p.longOpt for p in plugin.getPlugins(itrial.IRepo rter)]),)
90
91 class Options(usage.Options, app.ReactorSelectionMixin):
92 synopsis = """%s [options] [[file|package|module|TestCase|testmethod]...]
93 """ % (os.path.basename(sys.argv[0]),)
94
95 optFlags = [["help", "h"],
96 ["rterrors", "e", "realtime errors, print out tracebacks as "
97 "soon as they occur"],
98 ["debug", "b", "Run tests in the Python debugger. Will load "
99 "'.pdbrc' from current directory if it exists."],
100 ["debug-stacktraces", "B", "Report Deferred creation and "
101 "callback stack traces"],
102 ["nopm", None, "don't automatically jump into debugger for "
103 "postmorteming of exceptions"],
104 ["dry-run", 'n', "do everything but run the tests"],
105 ["force-gc", None, "Have Trial run gc.collect() before and "
106 "after each test case."],
107 ["profile", None, "Run tests under the Python profiler"],
108 ["unclean-warnings", None,
109 "Turn dirty reactor errors into warnings"],
110 ["until-failure", "u", "Repeat test until it fails"],
111 ["no-recurse", "N", "Don't recurse into packages"],
112 ['help-reporters', None,
113 "Help on available output plugins (reporters)"]
114 ]
115
116 optParameters = [
117 ["logfile", "l", "test.log", "log file name"],
118 ["random", "z", None,
119 "Run tests in random order using the specified seed"],
120 ['temp-directory', None, '_trial_temp',
121 'Path to use as working directory for tests.'],
122 ['reporter', None, 'verbose',
123 'The reporter to use for this test run. See --help-reporters for '
124 'more info.']]
125
126 zsh_actions = {"tbformat":"(plain emacs cgitb)",
127 "reporter":_zshReporterAction}
128 zsh_actionDescr = {"logfile":"log file name",
129 "random":"random seed"}
130 zsh_extras = ["*:file|module|package|TestCase|testMethod:_files -g '*.py'"]
131
132 fallbackReporter = reporter.TreeReporter
133 extra = None
134 tracer = None
135
136 def __init__(self):
137 self['tests'] = set()
138 usage.Options.__init__(self)
139
140 def opt_coverage(self):
141 """
142 Generate coverage information in the _trial_temp/coverage. Requires
143 Python 2.3.3.
144 """
145 coverdir = 'coverage'
146 print "Setting coverage directory to %s." % (coverdir,)
147 import trace
148
149 # begin monkey patch ---------------------------
150 # Before Python 2.4, this function asserted that 'filename' had
151 # to end with '.py' This is wrong for at least two reasons:
152 # 1. We might be wanting to find executable line nos in a script
153 # 2. The implementation should use os.splitext
154 # This monkey patch is the same function as in the stdlib (v2.3)
155 # but with the assertion removed.
156 def find_executable_linenos(filename):
157 """Return dict where keys are line numbers in the line number
158 table.
159 """
160 #assert filename.endswith('.py') # YOU BASTARDS
161 try:
162 prog = open(filename).read()
163 prog = '\n'.join(prog.splitlines()) + '\n'
164 except IOError, err:
165 sys.stderr.write("Not printing coverage data for %r: %s\n"
166 % (filename, err))
167 sys.stderr.flush()
168 return {}
169 code = compile(prog, filename, "exec")
170 strs = trace.find_strings(filename)
171 return trace.find_lines(code, strs)
172
173 trace.find_executable_linenos = find_executable_linenos
174 # end monkey patch ------------------------------
175
176 self.coverdir = os.path.abspath(os.path.join(self['temp-directory'], cov erdir))
177 self.tracer = trace.Trace(count=1, trace=0)
178 sys.settrace(self.tracer.globaltrace)
179
180 def opt_testmodule(self, filename):
181 "Filename to grep for test cases (-*- test-case-name)"
182 # If the filename passed to this parameter looks like a test module
183 # we just add that to the test suite.
184 #
185 # If not, we inspect it for an Emacs buffer local variable called
186 # 'test-case-name'. If that variable is declared, we try to add its
187 # value to the test suite as a module.
188 #
189 # This parameter allows automated processes (like Buildbot) to pass
190 # a list of files to Trial with the general expectation of "these files,
191 # whatever they are, will get tested"
192 if not os.path.isfile(filename):
193 sys.stderr.write("File %r doesn't exist\n" % (filename,))
194 return
195 filename = os.path.abspath(filename)
196 if isTestFile(filename):
197 self['tests'].add(filename)
198 else:
199 self['tests'].update(getTestModules(filename))
200
201 def opt_spew(self):
202 """Print an insanely verbose log of everything that happens. Useful
203 when debugging freezes or locks in complex code."""
204 sys.settrace(spewer)
205
206
207 def opt_help_reporters(self):
208 synopsis = ("Trial's output can be customized using plugins called "
209 "Reporters. You can\nselect any of the following "
210 "reporters using --reporter=<foo>\n")
211 print synopsis
212 for p in plugin.getPlugins(itrial.IReporter):
213 print ' ', p.longOpt, '\t', p.description
214 print
215 sys.exit(0)
216
217 def opt_disablegc(self):
218 """Disable the garbage collector"""
219 gc.disable()
220
221 def opt_tbformat(self, opt):
222 """Specify the format to display tracebacks with. Valid formats are
223 'plain', 'emacs', and 'cgitb' which uses the nicely verbose stdlib
224 cgitb.text function"""
225 try:
226 self['tbformat'] = TBFORMAT_MAP[opt]
227 except KeyError:
228 raise usage.UsageError(
229 "tbformat must be 'plain', 'emacs', or 'cgitb'.")
230
231 def opt_extra(self, arg):
232 """
233 Add an extra argument. (This is a hack necessary for interfacing with
234 emacs's `gud'.)
235 """
236 if self.extra is None:
237 self.extra = []
238 self.extra.append(arg)
239 opt_x = opt_extra
240
241 def opt_recursionlimit(self, arg):
242 """see sys.setrecursionlimit()"""
243 try:
244 sys.setrecursionlimit(int(arg))
245 except (TypeError, ValueError):
246 raise usage.UsageError(
247 "argument to recursionlimit must be an integer")
248
249 def opt_random(self, option):
250 try:
251 self['random'] = long(option)
252 except ValueError:
253 raise usage.UsageError(
254 "Argument to --random must be a positive integer")
255 else:
256 if self['random'] < 0:
257 raise usage.UsageError(
258 "Argument to --random must be a positive integer")
259 elif self['random'] == 0:
260 self['random'] = long(time.time() * 100)
261
262 def opt_without_module(self, option):
263 """
264 Fake the lack of the specified modules, separated with commas.
265 """
266 for module in option.split(","):
267 if module in sys.modules:
268 warnings.warn("Module '%s' already imported, "
269 "disabling anyway." % (module,),
270 category=RuntimeWarning)
271 sys.modules[module] = None
272
273 def parseArgs(self, *args):
274 self['tests'].update(args)
275 if self.extra is not None:
276 self['tests'].update(self.extra)
277
278 def _loadReporterByName(self, name):
279 for p in plugin.getPlugins(itrial.IReporter):
280 qual = "%s.%s" % (p.module, p.klass)
281 if p.longOpt == name:
282 return reflect.namedAny(qual)
283 raise usage.UsageError("Only pass names of Reporter plugins to "
284 "--reporter. See --help-reporters for "
285 "more info.")
286
287
288 def postOptions(self):
289
290 # Only load reporters now, as opposed to any earlier, to avoid letting
291 # application-defined plugins muck up reactor selecting by importing
292 # t.i.reactor and causing the default to be installed.
293 self['reporter'] = self._loadReporterByName(self['reporter'])
294
295 if 'tbformat' not in self:
296 self['tbformat'] = 'default'
297 if self['nopm']:
298 if not self['debug']:
299 raise usage.UsageError("you must specify --debug when using "
300 "--nopm ")
301 failure.DO_POST_MORTEM = False
302
303
304 def _initialDebugSetup(config):
305 # do this part of debug setup first for easy debugging of import failures
306 if config['debug']:
307 failure.startDebugMode()
308 if config['debug'] or config['debug-stacktraces']:
309 defer.setDebugging(True)
310
311
312 def _getSuite(config):
313 loader = _getLoader(config)
314 recurse = not config['no-recurse']
315 return loader.loadByNames(config['tests'], recurse)
316
317
318 def _getLoader(config):
319 loader = runner.TestLoader()
320 if config['random']:
321 randomer = random.Random()
322 randomer.seed(config['random'])
323 loader.sorter = lambda x : randomer.random()
324 print 'Running tests shuffled with seed %d\n' % config['random']
325 if not config['until-failure']:
326 loader.suiteFactory = runner.DestructiveTestSuite
327 return loader
328
329
330 def _makeRunner(config):
331 mode = None
332 if config['debug']:
333 mode = runner.TrialRunner.DEBUG
334 if config['dry-run']:
335 mode = runner.TrialRunner.DRY_RUN
336 return runner.TrialRunner(config['reporter'],
337 mode=mode,
338 profile=config['profile'],
339 logfile=config['logfile'],
340 tracebackFormat=config['tbformat'],
341 realTimeErrors=config['rterrors'],
342 uncleanWarnings=config['unclean-warnings'],
343 workingDirectory=config['temp-directory'],
344 forceGarbageCollection=config['force-gc'])
345
346
347 def run():
348 if len(sys.argv) == 1:
349 sys.argv.append("--help")
350 config = Options()
351 try:
352 config.parseOptions()
353 except usage.error, ue:
354 raise SystemExit, "%s: %s" % (sys.argv[0], ue)
355 _initialDebugSetup(config)
356 trialRunner = _makeRunner(config)
357 suite = _getSuite(config)
358 if config['until-failure']:
359 test_result = trialRunner.runUntilFailure(suite)
360 else:
361 test_result = trialRunner.run(suite)
362 if config.tracer:
363 sys.settrace(None)
364 results = config.tracer.results()
365 results.write_results(show_missing=1, summary=False,
366 coverdir=config.coverdir)
367 sys.exit(not test_result.wasSuccessful())
368
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/scripts/tkunzip.py ('k') | third_party/twisted_8_1/twisted/scripts/twistd.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698