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

Side by Side Diff: tools/test.py

Issue 14348002: Remove SCons related files (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fixed os.path.join occurrences that depended on old imports Created 7 years, 8 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
« no previous file with comments | « test/test262/testcfg.py ('k') | tools/test-wrapper-gypbuild.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
3 # Copyright 2012 the V8 project authors. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following
12 # disclaimer in the documentation and/or other materials provided
13 # with the distribution.
14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived
16 # from this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
31 import imp
32 import optparse
33 import os
34 from os.path import join, dirname, abspath, basename, isdir, exists
35 import platform
36 import re
37 import signal
38 import subprocess
39 import sys
40 import tempfile
41 import time
42 import threading
43 import utils
44 from Queue import Queue, Empty
45
46
47 VERBOSE = False
48
49
50 # ---------------------------------------------
51 # --- P r o g r e s s I n d i c a t o r s ---
52 # ---------------------------------------------
53
54
55 class ProgressIndicator(object):
56
57 def __init__(self, cases):
58 self.cases = cases
59 self.queue = Queue(len(cases))
60 for case in cases:
61 self.queue.put_nowait(case)
62 self.succeeded = 0
63 self.remaining = len(cases)
64 self.total = len(cases)
65 self.failed = [ ]
66 self.crashed = 0
67 self.terminate = False
68 self.lock = threading.Lock()
69
70 def PrintFailureHeader(self, test):
71 if test.IsNegative():
72 negative_marker = '[negative] '
73 else:
74 negative_marker = ''
75 print "=== %(label)s %(negative)s===" % {
76 'label': test.GetLabel(),
77 'negative': negative_marker
78 }
79 print "Path: %s" % "/".join(test.path)
80
81 def Run(self, tasks):
82 self.Starting()
83 threads = []
84 # Spawn N-1 threads and then use this thread as the last one.
85 # That way -j1 avoids threading altogether which is a nice fallback
86 # in case of threading problems.
87 for i in xrange(tasks - 1):
88 thread = threading.Thread(target=self.RunSingle, args=[])
89 threads.append(thread)
90 thread.start()
91 try:
92 self.RunSingle()
93 # Wait for the remaining threads
94 for thread in threads:
95 # Use a timeout so that signals (ctrl-c) will be processed.
96 thread.join(timeout=10000000)
97 except Exception, e:
98 # If there's an exception we schedule an interruption for any
99 # remaining threads.
100 self.terminate = True
101 # ...and then reraise the exception to bail out
102 raise
103 self.Done()
104 return not self.failed
105
106 def RunSingle(self):
107 while not self.terminate:
108 try:
109 test = self.queue.get_nowait()
110 except Empty:
111 return
112 case = test.case
113 self.lock.acquire()
114 self.AboutToRun(case)
115 self.lock.release()
116 try:
117 start = time.time()
118 output = case.Run()
119 case.duration = (time.time() - start)
120 except BreakNowException:
121 self.terminate = True
122 except IOError, e:
123 assert self.terminate
124 return
125 if self.terminate:
126 return
127 self.lock.acquire()
128 if output.UnexpectedOutput():
129 self.failed.append(output)
130 if output.HasCrashed():
131 self.crashed += 1
132 else:
133 self.succeeded += 1
134 self.remaining -= 1
135 self.HasRun(output)
136 self.lock.release()
137
138
139 def EscapeCommand(command):
140 parts = []
141 for part in command:
142 if ' ' in part:
143 # Escape spaces and double quotes. We may need to escape more characters
144 # for this to work properly.
145 parts.append('"%s"' % part.replace('"', '\\"'))
146 else:
147 parts.append(part)
148 return " ".join(parts)
149
150
151 class SimpleProgressIndicator(ProgressIndicator):
152
153 def Starting(self):
154 print 'Running %i tests' % len(self.cases)
155
156 def Done(self):
157 print
158 for failed in self.failed:
159 self.PrintFailureHeader(failed.test)
160 if failed.output.stderr:
161 print "--- stderr ---"
162 print failed.output.stderr.strip()
163 if failed.output.stdout:
164 print "--- stdout ---"
165 print failed.output.stdout.strip()
166 print "Command: %s" % EscapeCommand(failed.command)
167 if failed.HasCrashed():
168 print "--- CRASHED ---"
169 if failed.HasTimedOut():
170 print "--- TIMEOUT ---"
171 if len(self.failed) == 0:
172 print "==="
173 print "=== All tests succeeded"
174 print "==="
175 else:
176 print
177 print "==="
178 print "=== %i tests failed" % len(self.failed)
179 if self.crashed > 0:
180 print "=== %i tests CRASHED" % self.crashed
181 print "==="
182
183
184 class VerboseProgressIndicator(SimpleProgressIndicator):
185
186 def AboutToRun(self, case):
187 print 'Starting %s...' % case.GetLabel()
188 sys.stdout.flush()
189
190 def HasRun(self, output):
191 if output.UnexpectedOutput():
192 if output.HasCrashed():
193 outcome = 'CRASH'
194 else:
195 outcome = 'FAIL'
196 else:
197 outcome = 'pass'
198 print 'Done running %s: %s' % (output.test.GetLabel(), outcome)
199
200
201 class DotsProgressIndicator(SimpleProgressIndicator):
202
203 def AboutToRun(self, case):
204 pass
205
206 def HasRun(self, output):
207 total = self.succeeded + len(self.failed)
208 if (total > 1) and (total % 50 == 1):
209 sys.stdout.write('\n')
210 if output.UnexpectedOutput():
211 if output.HasCrashed():
212 sys.stdout.write('C')
213 sys.stdout.flush()
214 elif output.HasTimedOut():
215 sys.stdout.write('T')
216 sys.stdout.flush()
217 else:
218 sys.stdout.write('F')
219 sys.stdout.flush()
220 else:
221 sys.stdout.write('.')
222 sys.stdout.flush()
223
224
225 class CompactProgressIndicator(ProgressIndicator):
226
227 def __init__(self, cases, templates):
228 super(CompactProgressIndicator, self).__init__(cases)
229 self.templates = templates
230 self.last_status_length = 0
231 self.start_time = time.time()
232
233 def Starting(self):
234 pass
235
236 def Done(self):
237 self.PrintProgress('Done')
238
239 def AboutToRun(self, case):
240 self.PrintProgress(case.GetLabel())
241
242 def HasRun(self, output):
243 if output.UnexpectedOutput():
244 self.ClearLine(self.last_status_length)
245 self.PrintFailureHeader(output.test)
246 stdout = output.output.stdout.strip()
247 if len(stdout):
248 print self.templates['stdout'] % stdout
249 stderr = output.output.stderr.strip()
250 if len(stderr):
251 print self.templates['stderr'] % stderr
252 print "Command: %s" % EscapeCommand(output.command)
253 if output.HasCrashed():
254 print "--- CRASHED ---"
255 if output.HasTimedOut():
256 print "--- TIMEOUT ---"
257
258 def Truncate(self, str, length):
259 if length and (len(str) > (length - 3)):
260 return str[:(length-3)] + "..."
261 else:
262 return str
263
264 def PrintProgress(self, name):
265 self.ClearLine(self.last_status_length)
266 elapsed = time.time() - self.start_time
267 status = self.templates['status_line'] % {
268 'passed': self.succeeded,
269 'remaining': (((self.total - self.remaining) * 100) // self.total),
270 'failed': len(self.failed),
271 'test': name,
272 'mins': int(elapsed) / 60,
273 'secs': int(elapsed) % 60
274 }
275 status = self.Truncate(status, 78)
276 self.last_status_length = len(status)
277 print status,
278 sys.stdout.flush()
279
280
281 class ColorProgressIndicator(CompactProgressIndicator):
282
283 def __init__(self, cases):
284 templates = {
285 'status_line': "[%(mins)02i:%(secs)02i|\033[34m%%%(remaining) 4d\033[0m|\0 33[32m+%(passed) 4d\033[0m|\033[31m-%(failed) 4d\033[0m]: %(test)s",
286 'stdout': "\033[1m%s\033[0m",
287 'stderr': "\033[31m%s\033[0m",
288 }
289 super(ColorProgressIndicator, self).__init__(cases, templates)
290
291 def ClearLine(self, last_line_length):
292 print "\033[1K\r",
293
294
295 class MonochromeProgressIndicator(CompactProgressIndicator):
296
297 def __init__(self, cases):
298 templates = {
299 'status_line': "[%(mins)02i:%(secs)02i|%%%(remaining) 4d|+%(passed) 4d|-%( failed) 4d]: %(test)s",
300 'stdout': '%s',
301 'stderr': '%s',
302 }
303 super(MonochromeProgressIndicator, self).__init__(cases, templates)
304
305 def ClearLine(self, last_line_length):
306 print ("\r" + (" " * last_line_length) + "\r"),
307
308
309 PROGRESS_INDICATORS = {
310 'verbose': VerboseProgressIndicator,
311 'dots': DotsProgressIndicator,
312 'color': ColorProgressIndicator,
313 'mono': MonochromeProgressIndicator
314 }
315
316
317 # -------------------------
318 # --- F r a m e w o r k ---
319 # -------------------------
320
321 class BreakNowException(Exception):
322 def __init__(self, value):
323 self.value = value
324 def __str__(self):
325 return repr(self.value)
326
327
328 class CommandOutput(object):
329
330 def __init__(self, exit_code, timed_out, stdout, stderr):
331 self.exit_code = exit_code
332 self.timed_out = timed_out
333 self.stdout = stdout
334 self.stderr = stderr
335 self.failed = None
336
337
338 class TestCase(object):
339
340 def __init__(self, context, path, mode):
341 self.path = path
342 self.context = context
343 self.duration = None
344 self.mode = mode
345
346 def IsNegative(self):
347 return False
348
349 def TestsIsolates(self):
350 return False
351
352 def CompareTime(self, other):
353 return cmp(other.duration, self.duration)
354
355 def DidFail(self, output):
356 if output.failed is None:
357 output.failed = self.IsFailureOutput(output)
358 return output.failed
359
360 def IsFailureOutput(self, output):
361 return output.exit_code != 0
362
363 def GetSource(self):
364 return "(no source available)"
365
366 def RunCommand(self, command):
367 full_command = self.context.processor(command)
368 output = Execute(full_command,
369 self.context,
370 self.context.GetTimeout(self, self.mode))
371 self.Cleanup()
372 return TestOutput(self,
373 full_command,
374 output,
375 self.context.store_unexpected_output)
376
377 def BeforeRun(self):
378 pass
379
380 def AfterRun(self, result):
381 pass
382
383 def GetCustomFlags(self, mode):
384 return None
385
386 def Run(self):
387 self.BeforeRun()
388 result = None
389 try:
390 result = self.RunCommand(self.GetCommand())
391 except:
392 self.terminate = True
393 raise BreakNowException("User pressed CTRL+C or IO went wrong")
394 finally:
395 self.AfterRun(result)
396 return result
397
398 def Cleanup(self):
399 return
400
401
402 class TestOutput(object):
403
404 def __init__(self, test, command, output, store_unexpected_output):
405 self.test = test
406 self.command = command
407 self.output = output
408 self.store_unexpected_output = store_unexpected_output
409
410 def UnexpectedOutput(self):
411 if self.HasCrashed():
412 outcome = CRASH
413 elif self.HasTimedOut():
414 outcome = TIMEOUT
415 elif self.HasFailed():
416 outcome = FAIL
417 else:
418 outcome = PASS
419 return not outcome in self.test.outcomes
420
421 def HasPreciousOutput(self):
422 return self.UnexpectedOutput() and self.store_unexpected_output
423
424 def HasCrashed(self):
425 if utils.IsWindows():
426 return 0x80000000 & self.output.exit_code and not (0x3FFFFF00 & self.outpu t.exit_code)
427 else:
428 # Timed out tests will have exit_code -signal.SIGTERM.
429 if self.output.timed_out:
430 return False
431 return self.output.exit_code < 0 and \
432 self.output.exit_code != -signal.SIGABRT
433
434 def HasTimedOut(self):
435 return self.output.timed_out
436
437 def HasFailed(self):
438 execution_failed = self.test.DidFail(self.output)
439 if self.test.IsNegative():
440 return not execution_failed
441 else:
442 return execution_failed
443
444
445 def KillProcessWithID(pid):
446 if utils.IsWindows():
447 os.popen('taskkill /T /F /PID %d' % pid)
448 else:
449 os.kill(pid, signal.SIGTERM)
450
451
452 MAX_SLEEP_TIME = 0.1
453 INITIAL_SLEEP_TIME = 0.0001
454 SLEEP_TIME_FACTOR = 1.25
455
456 SEM_INVALID_VALUE = -1
457 SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h
458
459 def Win32SetErrorMode(mode):
460 prev_error_mode = SEM_INVALID_VALUE
461 try:
462 import ctypes
463 prev_error_mode = ctypes.windll.kernel32.SetErrorMode(mode)
464 except ImportError:
465 pass
466 return prev_error_mode
467
468 def RunProcess(context, timeout, args, **rest):
469 if context.verbose: print "#", " ".join(args)
470 popen_args = args
471 prev_error_mode = SEM_INVALID_VALUE
472 if utils.IsWindows():
473 popen_args = subprocess.list2cmdline(args)
474 if context.suppress_dialogs:
475 # Try to change the error mode to avoid dialogs on fatal errors. Don't
476 # touch any existing error mode flags by merging the existing error mode.
477 # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx.
478 error_mode = SEM_NOGPFAULTERRORBOX
479 prev_error_mode = Win32SetErrorMode(error_mode)
480 Win32SetErrorMode(error_mode | prev_error_mode)
481 process = subprocess.Popen(
482 shell = utils.IsWindows(),
483 args = popen_args,
484 **rest
485 )
486 if utils.IsWindows() and context.suppress_dialogs and prev_error_mode != SEM_I NVALID_VALUE:
487 Win32SetErrorMode(prev_error_mode)
488 # Compute the end time - if the process crosses this limit we
489 # consider it timed out.
490 if timeout is None: end_time = None
491 else: end_time = time.time() + timeout
492 timed_out = False
493 # Repeatedly check the exit code from the process in a
494 # loop and keep track of whether or not it times out.
495 exit_code = None
496 sleep_time = INITIAL_SLEEP_TIME
497 while exit_code is None:
498 if (not end_time is None) and (time.time() >= end_time):
499 # Kill the process and wait for it to exit.
500 KillProcessWithID(process.pid)
501 exit_code = process.wait()
502 timed_out = True
503 else:
504 exit_code = process.poll()
505 time.sleep(sleep_time)
506 sleep_time = sleep_time * SLEEP_TIME_FACTOR
507 if sleep_time > MAX_SLEEP_TIME:
508 sleep_time = MAX_SLEEP_TIME
509 return (process, exit_code, timed_out)
510
511
512 def PrintError(str):
513 sys.stderr.write(str)
514 sys.stderr.write('\n')
515
516
517 def CheckedUnlink(name):
518 # On Windows, when run with -jN in parallel processes,
519 # OS often fails to unlink the temp file. Not sure why.
520 # Need to retry.
521 # Idea from https://bugs.webkit.org/attachment.cgi?id=75982&action=prettypatch
522 retry_count = 0
523 while retry_count < 30:
524 try:
525 os.unlink(name)
526 return
527 except OSError, e:
528 retry_count += 1
529 time.sleep(retry_count * 0.1)
530 PrintError("os.unlink() " + str(e))
531
532 def Execute(args, context, timeout=None):
533 (fd_out, outname) = tempfile.mkstemp()
534 (fd_err, errname) = tempfile.mkstemp()
535 (process, exit_code, timed_out) = RunProcess(
536 context,
537 timeout,
538 args = args,
539 stdout = fd_out,
540 stderr = fd_err,
541 )
542 os.close(fd_out)
543 os.close(fd_err)
544 output = file(outname).read()
545 errors = file(errname).read()
546 CheckedUnlink(outname)
547 CheckedUnlink(errname)
548 return CommandOutput(exit_code, timed_out, output, errors)
549
550
551 def ExecuteNoCapture(args, context, timeout=None):
552 (process, exit_code, timed_out) = RunProcess(
553 context,
554 timeout,
555 args = args,
556 )
557 return CommandOutput(exit_code, False, "", "")
558
559
560 def CarCdr(path):
561 if len(path) == 0:
562 return (None, [ ])
563 else:
564 return (path[0], path[1:])
565
566
567 # Use this to run several variants of the tests, e.g.:
568 # VARIANT_FLAGS = [[], ['--always_compact', '--noflush_code']]
569 VARIANT_FLAGS = [[],
570 ['--stress-opt', '--always-opt'],
571 ['--nocrankshaft']]
572
573
574 class TestConfiguration(object):
575
576 def __init__(self, context, root):
577 self.context = context
578 self.root = root
579
580 def Contains(self, path, file):
581 if len(path) > len(file):
582 return False
583 for i in xrange(len(path)):
584 if not path[i].match(file[i]):
585 return False
586 return True
587
588 def GetTestStatus(self, sections, defs):
589 pass
590
591 def VariantFlags(self):
592 return VARIANT_FLAGS
593
594
595
596
597 class TestSuite(object):
598
599 def __init__(self, name):
600 self.name = name
601
602 def GetName(self):
603 return self.name
604
605
606 class TestRepository(TestSuite):
607
608 def __init__(self, path):
609 normalized_path = abspath(path)
610 super(TestRepository, self).__init__(basename(normalized_path))
611 self.path = normalized_path
612 self.is_loaded = False
613 self.config = None
614
615 def GetConfiguration(self, context):
616 if self.is_loaded:
617 return self.config
618 self.is_loaded = True
619 file = None
620 try:
621 (file, pathname, description) = imp.find_module('testcfg', [ self.path ])
622 module = imp.load_module('testcfg', file, pathname, description)
623 self.config = module.GetConfiguration(context, self.path)
624 finally:
625 if file:
626 file.close()
627 return self.config
628
629 def GetBuildRequirements(self, path, context):
630 return self.GetConfiguration(context).GetBuildRequirements()
631
632 def DownloadData(self, context):
633 config = self.GetConfiguration(context)
634 if 'DownloadData' in dir(config):
635 config.DownloadData()
636
637 def AddTestsToList(self, result, current_path, path, context, mode):
638 config = self.GetConfiguration(context)
639 for v in config.VariantFlags():
640 tests = config.ListTests(current_path, path, mode, v)
641 for t in tests: t.variant_flags = v
642 result += tests
643
644 def GetTestStatus(self, context, sections, defs):
645 self.GetConfiguration(context).GetTestStatus(sections, defs)
646
647
648 class LiteralTestSuite(TestSuite):
649
650 def __init__(self, tests):
651 super(LiteralTestSuite, self).__init__('root')
652 self.tests = tests
653
654 def GetBuildRequirements(self, path, context):
655 (name, rest) = CarCdr(path)
656 result = [ ]
657 for test in self.tests:
658 if not name or name.match(test.GetName()):
659 result += test.GetBuildRequirements(rest, context)
660 return result
661
662 def DownloadData(self, path, context):
663 (name, rest) = CarCdr(path)
664 for test in self.tests:
665 if not name or name.match(test.GetName()):
666 test.DownloadData(context)
667
668 def ListTests(self, current_path, path, context, mode, variant_flags):
669 (name, rest) = CarCdr(path)
670 result = [ ]
671 for test in self.tests:
672 test_name = test.GetName()
673 if not name or name.match(test_name):
674 full_path = current_path + [test_name]
675 test.AddTestsToList(result, full_path, path, context, mode)
676 return result
677
678 def GetTestStatus(self, context, sections, defs):
679 for test in self.tests:
680 test.GetTestStatus(context, sections, defs)
681
682
683 SUFFIX = {
684 'debug' : '_g',
685 'release' : '' }
686 FLAGS = {
687 'debug' : ['--nobreak-on-abort', '--nodead-code-elimination',
688 '--nofold-constants', '--enable-slow-asserts',
689 '--debug-code', '--verify-heap'],
690 'release' : ['--nobreak-on-abort', '--nodead-code-elimination',
691 '--nofold-constants']}
692 TIMEOUT_SCALEFACTOR = {
693 'debug' : 4,
694 'release' : 1 }
695
696
697 class Context(object):
698
699 def __init__(self, workspace, buildspace, verbose, vm, timeout, processor, sup press_dialogs, store_unexpected_output):
700 self.workspace = workspace
701 self.buildspace = buildspace
702 self.verbose = verbose
703 self.vm_root = vm
704 self.timeout = timeout
705 self.processor = processor
706 self.suppress_dialogs = suppress_dialogs
707 self.store_unexpected_output = store_unexpected_output
708
709 def GetVm(self, mode):
710 name = self.vm_root + SUFFIX[mode]
711 if utils.IsWindows() and not name.endswith('.exe'):
712 name = name + '.exe'
713 return name
714
715 def GetVmCommand(self, testcase, mode):
716 return [self.GetVm(mode)] + self.GetVmFlags(testcase, mode)
717
718 def GetVmFlags(self, testcase, mode):
719 flags = testcase.GetCustomFlags(mode)
720 if flags is None:
721 flags = FLAGS[mode]
722 return testcase.variant_flags + flags
723
724 def GetTimeout(self, testcase, mode):
725 result = self.timeout * TIMEOUT_SCALEFACTOR[mode]
726 if '--stress-opt' in self.GetVmFlags(testcase, mode):
727 return result * 4
728 else:
729 return result
730
731 def RunTestCases(cases_to_run, progress, tasks):
732 progress = PROGRESS_INDICATORS[progress](cases_to_run)
733 result = 0
734 try:
735 result = progress.Run(tasks)
736 except Exception, e:
737 print "\n", e
738 return result
739
740
741 def BuildRequirements(context, requirements, mode, scons_flags):
742 command_line = (['scons', '-Y', context.workspace, 'mode=' + ",".join(mode)]
743 + requirements
744 + scons_flags)
745 output = ExecuteNoCapture(command_line, context)
746 return output.exit_code == 0
747
748
749 # -------------------------------------------
750 # --- T e s t C o n f i g u r a t i o n ---
751 # -------------------------------------------
752
753
754 SKIP = 'skip'
755 FAIL = 'fail'
756 PASS = 'pass'
757 OKAY = 'okay'
758 TIMEOUT = 'timeout'
759 CRASH = 'crash'
760 SLOW = 'slow'
761
762
763 class Expression(object):
764 pass
765
766
767 class Constant(Expression):
768
769 def __init__(self, value):
770 self.value = value
771
772 def Evaluate(self, env, defs):
773 return self.value
774
775
776 class Variable(Expression):
777
778 def __init__(self, name):
779 self.name = name
780
781 def GetOutcomes(self, env, defs):
782 if self.name in env: return ListSet([env[self.name]])
783 else: return Nothing()
784
785 def Evaluate(self, env, defs):
786 return env[self.name]
787
788
789 class Outcome(Expression):
790
791 def __init__(self, name):
792 self.name = name
793
794 def GetOutcomes(self, env, defs):
795 if self.name in defs:
796 return defs[self.name].GetOutcomes(env, defs)
797 else:
798 return ListSet([self.name])
799
800
801 class Set(object):
802 pass
803
804
805 class ListSet(Set):
806
807 def __init__(self, elms):
808 self.elms = elms
809
810 def __str__(self):
811 return "ListSet%s" % str(self.elms)
812
813 def Intersect(self, that):
814 if not isinstance(that, ListSet):
815 return that.Intersect(self)
816 return ListSet([ x for x in self.elms if x in that.elms ])
817
818 def Union(self, that):
819 if not isinstance(that, ListSet):
820 return that.Union(self)
821 return ListSet(self.elms + [ x for x in that.elms if x not in self.elms ])
822
823 def IsEmpty(self):
824 return len(self.elms) == 0
825
826
827 class Everything(Set):
828
829 def Intersect(self, that):
830 return that
831
832 def Union(self, that):
833 return self
834
835 def IsEmpty(self):
836 return False
837
838
839 class Nothing(Set):
840
841 def Intersect(self, that):
842 return self
843
844 def Union(self, that):
845 return that
846
847 def IsEmpty(self):
848 return True
849
850
851 class Operation(Expression):
852
853 def __init__(self, left, op, right):
854 self.left = left
855 self.op = op
856 self.right = right
857
858 def Evaluate(self, env, defs):
859 if self.op == '||' or self.op == ',':
860 return self.left.Evaluate(env, defs) or self.right.Evaluate(env, defs)
861 elif self.op == 'if':
862 return False
863 elif self.op == '==':
864 inter = self.left.GetOutcomes(env, defs).Intersect(self.right.GetOutcomes( env, defs))
865 return not inter.IsEmpty()
866 elif self.op == '!=':
867 inter = self.left.GetOutcomes(env, defs).Intersect(self.right.GetOutcomes( env, defs))
868 return inter.IsEmpty()
869 else:
870 assert self.op == '&&'
871 return self.left.Evaluate(env, defs) and self.right.Evaluate(env, defs)
872
873 def GetOutcomes(self, env, defs):
874 if self.op == '||' or self.op == ',':
875 return self.left.GetOutcomes(env, defs).Union(self.right.GetOutcomes(env, defs))
876 elif self.op == 'if':
877 if self.right.Evaluate(env, defs): return self.left.GetOutcomes(env, defs)
878 else: return Nothing()
879 else:
880 assert self.op == '&&'
881 return self.left.GetOutcomes(env, defs).Intersect(self.right.GetOutcomes(e nv, defs))
882
883
884 def IsAlpha(str):
885 for char in str:
886 if not (char.isalpha() or char.isdigit() or char == '_'):
887 return False
888 return True
889
890
891 class Tokenizer(object):
892 """A simple string tokenizer that chops expressions into variables,
893 parens and operators"""
894
895 def __init__(self, expr):
896 self.index = 0
897 self.expr = expr
898 self.length = len(expr)
899 self.tokens = None
900
901 def Current(self, length = 1):
902 if not self.HasMore(length): return ""
903 return self.expr[self.index:self.index+length]
904
905 def HasMore(self, length = 1):
906 return self.index < self.length + (length - 1)
907
908 def Advance(self, count = 1):
909 self.index = self.index + count
910
911 def AddToken(self, token):
912 self.tokens.append(token)
913
914 def SkipSpaces(self):
915 while self.HasMore() and self.Current().isspace():
916 self.Advance()
917
918 def Tokenize(self):
919 self.tokens = [ ]
920 while self.HasMore():
921 self.SkipSpaces()
922 if not self.HasMore():
923 return None
924 if self.Current() == '(':
925 self.AddToken('(')
926 self.Advance()
927 elif self.Current() == ')':
928 self.AddToken(')')
929 self.Advance()
930 elif self.Current() == '$':
931 self.AddToken('$')
932 self.Advance()
933 elif self.Current() == ',':
934 self.AddToken(',')
935 self.Advance()
936 elif IsAlpha(self.Current()):
937 buf = ""
938 while self.HasMore() and IsAlpha(self.Current()):
939 buf += self.Current()
940 self.Advance()
941 self.AddToken(buf)
942 elif self.Current(2) == '&&':
943 self.AddToken('&&')
944 self.Advance(2)
945 elif self.Current(2) == '||':
946 self.AddToken('||')
947 self.Advance(2)
948 elif self.Current(2) == '==':
949 self.AddToken('==')
950 self.Advance(2)
951 elif self.Current(2) == '!=':
952 self.AddToken('!=')
953 self.Advance(2)
954 else:
955 return None
956 return self.tokens
957
958
959 class Scanner(object):
960 """A simple scanner that can serve out tokens from a given list"""
961
962 def __init__(self, tokens):
963 self.tokens = tokens
964 self.length = len(tokens)
965 self.index = 0
966
967 def HasMore(self):
968 return self.index < self.length
969
970 def Current(self):
971 return self.tokens[self.index]
972
973 def Advance(self):
974 self.index = self.index + 1
975
976
977 def ParseAtomicExpression(scan):
978 if scan.Current() == "true":
979 scan.Advance()
980 return Constant(True)
981 elif scan.Current() == "false":
982 scan.Advance()
983 return Constant(False)
984 elif IsAlpha(scan.Current()):
985 name = scan.Current()
986 scan.Advance()
987 return Outcome(name.lower())
988 elif scan.Current() == '$':
989 scan.Advance()
990 if not IsAlpha(scan.Current()):
991 return None
992 name = scan.Current()
993 scan.Advance()
994 return Variable(name.lower())
995 elif scan.Current() == '(':
996 scan.Advance()
997 result = ParseLogicalExpression(scan)
998 if (not result) or (scan.Current() != ')'):
999 return None
1000 scan.Advance()
1001 return result
1002 else:
1003 return None
1004
1005
1006 BINARIES = ['==', '!=']
1007 def ParseOperatorExpression(scan):
1008 left = ParseAtomicExpression(scan)
1009 if not left: return None
1010 while scan.HasMore() and (scan.Current() in BINARIES):
1011 op = scan.Current()
1012 scan.Advance()
1013 right = ParseOperatorExpression(scan)
1014 if not right:
1015 return None
1016 left = Operation(left, op, right)
1017 return left
1018
1019
1020 def ParseConditionalExpression(scan):
1021 left = ParseOperatorExpression(scan)
1022 if not left: return None
1023 while scan.HasMore() and (scan.Current() == 'if'):
1024 scan.Advance()
1025 right = ParseOperatorExpression(scan)
1026 if not right:
1027 return None
1028 left = Operation(left, 'if', right)
1029 return left
1030
1031
1032 LOGICALS = ["&&", "||", ","]
1033 def ParseLogicalExpression(scan):
1034 left = ParseConditionalExpression(scan)
1035 if not left: return None
1036 while scan.HasMore() and (scan.Current() in LOGICALS):
1037 op = scan.Current()
1038 scan.Advance()
1039 right = ParseConditionalExpression(scan)
1040 if not right:
1041 return None
1042 left = Operation(left, op, right)
1043 return left
1044
1045
1046 def ParseCondition(expr):
1047 """Parses a logical expression into an Expression object"""
1048 tokens = Tokenizer(expr).Tokenize()
1049 if not tokens:
1050 print "Malformed expression: '%s'" % expr
1051 return None
1052 scan = Scanner(tokens)
1053 ast = ParseLogicalExpression(scan)
1054 if not ast:
1055 print "Malformed expression: '%s'" % expr
1056 return None
1057 if scan.HasMore():
1058 print "Malformed expression: '%s'" % expr
1059 return None
1060 return ast
1061
1062
1063 class ClassifiedTest(object):
1064
1065 def __init__(self, case, outcomes):
1066 self.case = case
1067 self.outcomes = outcomes
1068
1069 def TestsIsolates(self):
1070 return self.case.TestsIsolates()
1071
1072
1073 class Configuration(object):
1074 """The parsed contents of a configuration file"""
1075
1076 def __init__(self, sections, defs):
1077 self.sections = sections
1078 self.defs = defs
1079
1080 def ClassifyTests(self, cases, env):
1081 sections = [s for s in self.sections if s.condition.Evaluate(env, self.defs) ]
1082 all_rules = reduce(list.__add__, [s.rules for s in sections], [])
1083 unused_rules = set(all_rules)
1084 result = [ ]
1085 all_outcomes = set([])
1086 for case in cases:
1087 matches = [ r for r in all_rules if r.Contains(case.path) ]
1088 outcomes = set([])
1089 for rule in matches:
1090 outcomes = outcomes.union(rule.GetOutcomes(env, self.defs))
1091 unused_rules.discard(rule)
1092 if not outcomes:
1093 outcomes = [PASS]
1094 case.outcomes = outcomes
1095 all_outcomes = all_outcomes.union(outcomes)
1096 result.append(ClassifiedTest(case, outcomes))
1097 return (result, list(unused_rules), all_outcomes)
1098
1099
1100 class Section(object):
1101 """A section of the configuration file. Sections are enabled or
1102 disabled prior to running the tests, based on their conditions"""
1103
1104 def __init__(self, condition):
1105 self.condition = condition
1106 self.rules = [ ]
1107
1108 def AddRule(self, rule):
1109 self.rules.append(rule)
1110
1111
1112 class Rule(object):
1113 """A single rule that specifies the expected outcome for a single
1114 test."""
1115
1116 def __init__(self, raw_path, path, value):
1117 self.raw_path = raw_path
1118 self.path = path
1119 self.value = value
1120
1121 def GetOutcomes(self, env, defs):
1122 set = self.value.GetOutcomes(env, defs)
1123 assert isinstance(set, ListSet)
1124 return set.elms
1125
1126 def Contains(self, path):
1127 if len(self.path) > len(path):
1128 return False
1129 for i in xrange(len(self.path)):
1130 if not self.path[i].match(path[i]):
1131 return False
1132 return True
1133
1134
1135 HEADER_PATTERN = re.compile(r'\[([^]]+)\]')
1136 RULE_PATTERN = re.compile(r'\s*([^: ]*)\s*:(.*)')
1137 DEF_PATTERN = re.compile(r'^def\s*(\w+)\s*=(.*)$')
1138 PREFIX_PATTERN = re.compile(r'^\s*prefix\s+([\w\_\.\-\/]+)$')
1139
1140
1141 def ReadConfigurationInto(path, sections, defs):
1142 current_section = Section(Constant(True))
1143 sections.append(current_section)
1144 prefix = []
1145 for line in utils.ReadLinesFrom(path):
1146 header_match = HEADER_PATTERN.match(line)
1147 if header_match:
1148 condition_str = header_match.group(1).strip()
1149 condition = ParseCondition(condition_str)
1150 new_section = Section(condition)
1151 sections.append(new_section)
1152 current_section = new_section
1153 continue
1154 rule_match = RULE_PATTERN.match(line)
1155 if rule_match:
1156 path = prefix + SplitPath(rule_match.group(1).strip())
1157 value_str = rule_match.group(2).strip()
1158 value = ParseCondition(value_str)
1159 if not value:
1160 return False
1161 current_section.AddRule(Rule(rule_match.group(1), path, value))
1162 continue
1163 def_match = DEF_PATTERN.match(line)
1164 if def_match:
1165 name = def_match.group(1).lower()
1166 value = ParseCondition(def_match.group(2).strip())
1167 if not value:
1168 return False
1169 defs[name] = value
1170 continue
1171 prefix_match = PREFIX_PATTERN.match(line)
1172 if prefix_match:
1173 prefix = SplitPath(prefix_match.group(1).strip())
1174 continue
1175 print "Malformed line: '%s'." % line
1176 return False
1177 return True
1178
1179
1180 # ---------------
1181 # --- M a i n ---
1182 # ---------------
1183
1184
1185 ARCH_GUESS = utils.GuessArchitecture()
1186 TIMEOUT_DEFAULT = 60;
1187
1188
1189 def BuildOptions():
1190 result = optparse.OptionParser()
1191 result.add_option("-m", "--mode", help="The test modes in which to run (comma- separated)",
1192 default='release')
1193 result.add_option("-v", "--verbose", help="Verbose output",
1194 default=False, action="store_true")
1195 result.add_option("-S", dest="scons_flags", help="Flag to pass through to scon s",
1196 default=[], action="append")
1197 result.add_option("-p", "--progress",
1198 help="The style of progress indicator (verbose, dots, color, mono)",
1199 choices=PROGRESS_INDICATORS.keys(), default="mono")
1200 result.add_option("--no-build", help="Don't build requirements",
1201 default=False, action="store_true")
1202 result.add_option("--build-only", help="Only build requirements, don't run the tests",
1203 default=False, action="store_true")
1204 result.add_option("--build-system", help="Build system in use (scons or gyp)",
1205 default='scons')
1206 result.add_option("--report", help="Print a summary of the tests to be run",
1207 default=False, action="store_true")
1208 result.add_option("--download-data", help="Download missing test suite data",
1209 default=False, action="store_true")
1210 result.add_option("-s", "--suite", help="A test suite",
1211 default=[], action="append")
1212 result.add_option("-t", "--timeout", help="Timeout in seconds",
1213 default=-1, type="int")
1214 result.add_option("--arch", help='The architecture to run tests for',
1215 default='none')
1216 result.add_option("--snapshot", help="Run the tests with snapshot turned on",
1217 default=False, action="store_true")
1218 result.add_option("--simulator", help="Run tests with architecture simulator",
1219 default='none')
1220 result.add_option("--special-command", default=None)
1221 result.add_option("--valgrind", help="Run tests through valgrind",
1222 default=False, action="store_true")
1223 result.add_option("--cat", help="Print the source of the tests",
1224 default=False, action="store_true")
1225 result.add_option("--warn-unused", help="Report unused rules",
1226 default=False, action="store_true")
1227 result.add_option("-j", help="The number of parallel tasks to run",
1228 default=1, type="int")
1229 result.add_option("--time", help="Print timing information after running",
1230 default=False, action="store_true")
1231 result.add_option("--suppress-dialogs", help="Suppress Windows dialogs for cra shing tests",
1232 dest="suppress_dialogs", default=True, action="store_true")
1233 result.add_option("--no-suppress-dialogs", help="Display Windows dialogs for c rashing tests",
1234 dest="suppress_dialogs", action="store_false")
1235 result.add_option("--mips-arch-variant", help="mips architecture variant: mips 32r1/mips32r2", default="mips32r2");
1236 result.add_option("--shell", help="Path to V8 shell", default="d8")
1237 result.add_option("--isolates", help="Whether to test isolates", default=False , action="store_true")
1238 result.add_option("--store-unexpected-output",
1239 help="Store the temporary JS files from tests that fails",
1240 dest="store_unexpected_output", default=True, action="store_true")
1241 result.add_option("--no-store-unexpected-output",
1242 help="Deletes the temporary JS files from tests that fails",
1243 dest="store_unexpected_output", action="store_false")
1244 result.add_option("--stress-only",
1245 help="Only run tests with --always-opt --stress-opt",
1246 default=False, action="store_true")
1247 result.add_option("--nostress",
1248 help="Don't run crankshaft --always-opt --stress-op test",
1249 default=False, action="store_true")
1250 result.add_option("--shard-count",
1251 help="Split testsuites into this number of shards",
1252 default=1, type="int")
1253 result.add_option("--shard-run",
1254 help="Run this shard from the split up tests.",
1255 default=1, type="int")
1256 result.add_option("--noprof", help="Disable profiling support",
1257 default=False)
1258 return result
1259
1260
1261 def ProcessOptions(options):
1262 global VERBOSE
1263 VERBOSE = options.verbose
1264 options.mode = options.mode.split(',')
1265 for mode in options.mode:
1266 if not mode in ['debug', 'release']:
1267 print "Unknown mode %s" % mode
1268 return False
1269 if options.simulator != 'none':
1270 # Simulator argument was set. Make sure arch and simulator agree.
1271 if options.simulator != options.arch:
1272 if options.arch == 'none':
1273 options.arch = options.simulator
1274 else:
1275 print "Architecture %s does not match sim %s" %(options.arch, options.si mulator)
1276 return False
1277 # Ensure that the simulator argument is handed down to scons.
1278 options.scons_flags.append("simulator=" + options.simulator)
1279 else:
1280 # If options.arch is not set by the command line and no simulator setting
1281 # was found, set the arch to the guess.
1282 if options.arch == 'none':
1283 options.arch = ARCH_GUESS
1284 options.scons_flags.append("arch=" + options.arch)
1285 # Simulators are slow, therefore allow a longer default timeout.
1286 if options.timeout == -1:
1287 if options.arch in ['android', 'arm', 'mipsel']:
1288 options.timeout = 2 * TIMEOUT_DEFAULT;
1289 else:
1290 options.timeout = TIMEOUT_DEFAULT;
1291 if options.snapshot:
1292 options.scons_flags.append("snapshot=on")
1293 global VARIANT_FLAGS
1294 if options.mips_arch_variant:
1295 options.scons_flags.append("mips_arch_variant=" + options.mips_arch_variant)
1296
1297 if options.stress_only:
1298 VARIANT_FLAGS = [['--stress-opt', '--always-opt']]
1299 if options.nostress:
1300 VARIANT_FLAGS = [[],['--nocrankshaft']]
1301 if options.shell.endswith("d8"):
1302 if options.special_command:
1303 options.special_command += " --test"
1304 else:
1305 options.special_command = "@ --test"
1306 if options.noprof:
1307 options.scons_flags.append("prof=off")
1308 options.scons_flags.append("profilingsupport=off")
1309 if options.build_system == 'gyp':
1310 if options.build_only:
1311 print "--build-only not supported for gyp, please build manually."
1312 options.build_only = False
1313 return True
1314
1315
1316 def DoSkip(case):
1317 return (SKIP in case.outcomes) or (SLOW in case.outcomes)
1318
1319
1320 REPORT_TEMPLATE = """\
1321 Total: %(total)i tests
1322 * %(skipped)4d tests will be skipped
1323 * %(timeout)4d tests are expected to timeout sometimes
1324 * %(nocrash)4d tests are expected to be flaky but not crash
1325 * %(pass)4d tests are expected to pass
1326 * %(fail_ok)4d tests are expected to fail that we won't fix
1327 * %(fail)4d tests are expected to fail that we should fix\
1328 """
1329
1330 def PrintReport(cases):
1331 def IsFlaky(o):
1332 return (PASS in o) and (FAIL in o) and (not CRASH in o) and (not OKAY in o)
1333 def IsFailOk(o):
1334 return (len(o) == 2) and (FAIL in o) and (OKAY in o)
1335 unskipped = [c for c in cases if not DoSkip(c)]
1336 print REPORT_TEMPLATE % {
1337 'total': len(cases),
1338 'skipped': len(cases) - len(unskipped),
1339 'timeout': len([t for t in unskipped if TIMEOUT in t.outcomes]),
1340 'nocrash': len([t for t in unskipped if IsFlaky(t.outcomes)]),
1341 'pass': len([t for t in unskipped if list(t.outcomes) == [PASS]]),
1342 'fail_ok': len([t for t in unskipped if IsFailOk(t.outcomes)]),
1343 'fail': len([t for t in unskipped if list(t.outcomes) == [FAIL]])
1344 }
1345
1346
1347 class Pattern(object):
1348
1349 def __init__(self, pattern):
1350 self.pattern = pattern
1351 self.compiled = None
1352
1353 def match(self, str):
1354 if not self.compiled:
1355 pattern = "^" + self.pattern.replace('*', '.*') + "$"
1356 self.compiled = re.compile(pattern)
1357 return self.compiled.match(str)
1358
1359 def __str__(self):
1360 return self.pattern
1361
1362
1363 def SplitPath(s):
1364 stripped = [ c.strip() for c in s.split('/') ]
1365 return [ Pattern(s) for s in stripped if len(s) > 0 ]
1366
1367
1368 def GetSpecialCommandProcessor(value):
1369 if (not value) or (value.find('@') == -1):
1370 def ExpandCommand(args):
1371 return args
1372 return ExpandCommand
1373 else:
1374 pos = value.find('@')
1375 import urllib
1376 import shlex
1377 prefix = shlex.split(urllib.unquote(value[:pos]))
1378 suffix = shlex.split(urllib.unquote(value[pos+1:]))
1379 def ExpandCommand(args):
1380 return prefix + args + suffix
1381 return ExpandCommand
1382
1383
1384 BUILT_IN_TESTS = ['mjsunit', 'cctest', 'message', 'preparser']
1385
1386
1387 def GetSuites(test_root):
1388 def IsSuite(path):
1389 return isdir(path) and exists(join(path, 'testcfg.py'))
1390 return [ f for f in os.listdir(test_root) if IsSuite(join(test_root, f)) ]
1391
1392
1393 def FormatTime(d):
1394 millis = round(d * 1000) % 1000
1395 return time.strftime("%M:%S.", time.gmtime(d)) + ("%03i" % millis)
1396
1397 def ShardTests(tests, options):
1398 if options.shard_count < 2:
1399 return tests
1400 if options.shard_run < 1 or options.shard_run > options.shard_count:
1401 print "shard-run not a valid number, should be in [1:shard-count]"
1402 print "defaulting back to running all tests"
1403 return tests
1404 count = 0
1405 shard = []
1406 for test in tests:
1407 if count % options.shard_count == options.shard_run - 1:
1408 shard.append(test)
1409 count += 1
1410 return shard
1411
1412 def Main():
1413 parser = BuildOptions()
1414 (options, args) = parser.parse_args()
1415 if not ProcessOptions(options):
1416 parser.print_help()
1417 return 1
1418
1419 workspace = abspath(join(dirname(sys.argv[0]), '..'))
1420 suites = GetSuites(join(workspace, 'test'))
1421 repositories = [TestRepository(join(workspace, 'test', name)) for name in suit es]
1422 repositories += [TestRepository(a) for a in options.suite]
1423
1424 root = LiteralTestSuite(repositories)
1425 if len(args) == 0:
1426 paths = [SplitPath(t) for t in BUILT_IN_TESTS]
1427 else:
1428 paths = [ ]
1429 for arg in args:
1430 path = SplitPath(arg)
1431 paths.append(path)
1432
1433 # Check for --valgrind option. If enabled, we overwrite the special
1434 # command flag with a command that uses the run-valgrind.py script.
1435 if options.valgrind:
1436 run_valgrind = join(workspace, "tools", "run-valgrind.py")
1437 options.special_command = "python -u " + run_valgrind + " @"
1438
1439 if options.build_system == 'gyp':
1440 SUFFIX['debug'] = ''
1441
1442 shell = abspath(options.shell)
1443 buildspace = dirname(shell)
1444
1445 context = Context(workspace, buildspace, VERBOSE,
1446 shell,
1447 options.timeout,
1448 GetSpecialCommandProcessor(options.special_command),
1449 options.suppress_dialogs,
1450 options.store_unexpected_output)
1451 # First build the required targets
1452 if not options.no_build:
1453 reqs = [ ]
1454 for path in paths:
1455 reqs += root.GetBuildRequirements(path, context)
1456 reqs = list(set(reqs))
1457 if len(reqs) > 0:
1458 if options.j != 1:
1459 options.scons_flags += ['-j', str(options.j)]
1460 if not BuildRequirements(context, reqs, options.mode, options.scons_flags) :
1461 return 1
1462
1463 # Just return if we are only building the targets for running the tests.
1464 if options.build_only:
1465 return 0
1466
1467 # Get status for tests
1468 sections = [ ]
1469 defs = { }
1470 root.GetTestStatus(context, sections, defs)
1471 config = Configuration(sections, defs)
1472
1473 # Download missing test suite data if requested.
1474 if options.download_data:
1475 for path in paths:
1476 root.DownloadData(path, context)
1477
1478 # List the tests
1479 all_cases = [ ]
1480 all_unused = [ ]
1481 unclassified_tests = [ ]
1482 globally_unused_rules = None
1483 for path in paths:
1484 for mode in options.mode:
1485 env = {
1486 'mode': mode,
1487 'system': utils.GuessOS(),
1488 'arch': options.arch,
1489 'simulator': options.simulator,
1490 'isolates': options.isolates
1491 }
1492 test_list = root.ListTests([], path, context, mode, [])
1493 unclassified_tests += test_list
1494 (cases, unused_rules, all_outcomes) = config.ClassifyTests(test_list, env)
1495 if globally_unused_rules is None:
1496 globally_unused_rules = set(unused_rules)
1497 else:
1498 globally_unused_rules = globally_unused_rules.intersection(unused_rules)
1499 all_cases += ShardTests(cases, options)
1500 all_unused.append(unused_rules)
1501
1502 if options.cat:
1503 visited = set()
1504 for test in unclassified_tests:
1505 key = tuple(test.path)
1506 if key in visited:
1507 continue
1508 visited.add(key)
1509 print "--- begin source: %s ---" % test.GetLabel()
1510 source = test.GetSource().strip()
1511 print source
1512 print "--- end source: %s ---" % test.GetLabel()
1513 return 0
1514
1515 if options.warn_unused:
1516 for rule in globally_unused_rules:
1517 print "Rule for '%s' was not used." % '/'.join([str(s) for s in rule.path] )
1518
1519 if not options.isolates:
1520 all_cases = [c for c in all_cases if not c.TestsIsolates()]
1521
1522 if options.report:
1523 PrintReport(all_cases)
1524
1525 result = None
1526 cases_to_run = [ c for c in all_cases if not DoSkip(c) ]
1527 if len(cases_to_run) == 0:
1528 print "No tests to run."
1529 return 0
1530 else:
1531 try:
1532 start = time.time()
1533 if RunTestCases(cases_to_run, options.progress, options.j):
1534 result = 0
1535 else:
1536 result = 1
1537 duration = time.time() - start
1538 except KeyboardInterrupt:
1539 print "Interrupted"
1540 return 1
1541
1542 if options.time:
1543 # Write the times to stderr to make it easy to separate from the
1544 # test output.
1545 print
1546 sys.stderr.write("--- Total time: %s ---\n" % FormatTime(duration))
1547 timed_tests = [ t.case for t in cases_to_run if not t.case.duration is None ]
1548 timed_tests.sort(lambda a, b: a.CompareTime(b))
1549 index = 1
1550 for entry in timed_tests[:20]:
1551 t = FormatTime(entry.duration)
1552 sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel()))
1553 index += 1
1554
1555 return result
1556
1557
1558 if __name__ == '__main__':
1559 sys.exit(Main())
OLDNEW
« no previous file with comments | « test/test262/testcfg.py ('k') | tools/test-wrapper-gypbuild.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698