Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 # Library for JSTest tests.
2 #
3 # This contains classes that represent an individual test, including
4 # metadata, and know how to run the tests and determine failures.
6 import datetime, os, sys, time
7 from subprocess import Popen, PIPE
8 from threading import Thread
10 from results import TestOutput
12 # When run on tbpl, we run each test multiple times with the following arguments.
13 TBPL_FLAGS = [
14 [], # no flags, normal baseline and ion
15 ['--ion-eager', '--ion-parallel-compile=off'], # implies --baseline-eager
16 ['--ion-eager', '--ion-parallel-compile=off', '--ion-check-range-analysis', '--no-sse3'],
17 ['--baseline-eager'],
18 ['--baseline-eager', '--no-fpu'],
19 ['--no-baseline', '--no-ion'],
20 ]
22 def do_run_cmd(cmd):
23 l = [ None, None ]
24 th_run_cmd(cmd, l)
25 return l[1]
27 def set_limits():
28 # resource module not supported on all platforms
29 try:
30 import resource
31 GB = 2**30
32 resource.setrlimit(resource.RLIMIT_AS, (2*GB, 2*GB))
33 except:
34 return
36 def th_run_cmd(cmd, l):
37 t0 = datetime.datetime.now()
39 # close_fds and preexec_fn are not supported on Windows and will
40 # cause a ValueError.
41 options = {}
42 if sys.platform != 'win32':
43 options["close_fds"] = True
44 options["preexec_fn"] = set_limits
45 p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, **options)
47 l[0] = p
48 out, err = p.communicate()
49 t1 = datetime.datetime.now()
50 dd = t1-t0
51 dt = dd.seconds + 1e-6 * dd.microseconds
52 l[1] = (out, err, p.returncode, dt)
54 def run_cmd(cmd, timeout=60.0):
55 if timeout is None:
56 return do_run_cmd(cmd)
58 l = [ None, None ]
59 timed_out = False
60 th = Thread(target=th_run_cmd, args=(cmd, l))
61 th.start()
62 th.join(timeout)
63 while th.isAlive():
64 if l[0] is not None:
65 try:
66 # In Python 3, we could just do l[0].kill().
67 import signal
68 if sys.platform != 'win32':
69 os.kill(l[0].pid, signal.SIGKILL)
70 time.sleep(.1)
71 timed_out = True
72 except OSError:
73 # Expecting a "No such process" error
74 pass
75 th.join()
76 return l[1] + (timed_out,)
78 class Test(object):
79 """A runnable test."""
80 def __init__(self, path):
81 self.path = path # str: path of JS file relative to tests root dir
83 @staticmethod
84 def prefix_command(path):
85 """Return the '-f shell.js' options needed to run a test with the given path."""
86 if path == '':
87 return [ '-f', 'shell.js' ]
88 head, base = os.path.split(path)
89 return Test.prefix_command(head) + [ '-f', os.path.join(path, 'shell.js') ]
91 def get_command(self, js_cmd_prefix):
92 dirname, filename = os.path.split(self.path)
93 cmd = js_cmd_prefix + self.options + Test.prefix_command(dirname) + [ '-f', self.path ]
94 return cmd
96 def run(self, js_cmd_prefix, timeout=30.0):
97 cmd = self.get_command(js_cmd_prefix)
98 out, err, rc, dt, timed_out = run_cmd(cmd, timeout)
99 return TestOutput(self, cmd, out, err, rc, dt, timed_out)
101 class TestCase(Test):
102 """A test case consisting of a test and an expected result."""
103 js_cmd_prefix = None
105 def __init__(self, path):
106 Test.__init__(self, path)
107 self.enable = True # bool: True => run test, False => don't run
108 self.expect = True # bool: expected result, True => pass
109 self.random = False # bool: True => ignore output as 'random'
110 self.slow = False # bool: True => test may run slowly
111 self.options = [] # [str]: Extra options to pass to the shell
113 # The terms parsed to produce the above properties.
114 self.terms = None
116 # The tag between |...| in the test header.
117 self.tag = None
119 # Anything occuring after -- in the test header.
120 self.comment = None
122 def __str__(self):
123 ans = self.path
124 if not self.enable:
125 ans += ', skip'
126 if not self.expect:
127 ans += ', fails'
128 if self.random:
129 ans += ', random'
130 if self.slow:
131 ans += ', slow'
132 if '-d' in self.options:
133 ans += ', debugMode'
134 return ans
136 @classmethod
137 def set_js_cmd_prefix(self, js_path, js_args, debugger_prefix):
138 parts = []
139 if debugger_prefix:
140 parts += debugger_prefix
141 parts.append(js_path)
142 if js_args:
143 parts += js_args
144 self.js_cmd_prefix = parts
146 def __cmp__(self, other):
147 if self.path == other.path:
148 return 0
149 elif self.path < other.path:
150 return -1
151 return 1
153 def __hash__(self):
154 return self.path.__hash__()