js/src/tests/lib/results.py

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 import re
michael@0 2 from progressbar import NullProgressBar, ProgressBar
michael@0 3 import pipes
michael@0 4
michael@0 5 # subprocess.list2cmdline does not properly escape for sh-like shells
michael@0 6 def escape_cmdline(args):
michael@0 7 return ' '.join([ pipes.quote(a) for a in args ])
michael@0 8
michael@0 9 class TestOutput:
michael@0 10 """Output from a test run."""
michael@0 11 def __init__(self, test, cmd, out, err, rc, dt, timed_out):
michael@0 12 self.test = test # Test
michael@0 13 self.cmd = cmd # str: command line of test
michael@0 14 self.out = out # str: stdout
michael@0 15 self.err = err # str: stderr
michael@0 16 self.rc = rc # int: return code
michael@0 17 self.dt = dt # float: run time
michael@0 18 self.timed_out = timed_out # bool: did the test time out
michael@0 19
michael@0 20 def describe_failure(self):
michael@0 21 if self.timed_out:
michael@0 22 return "Timeout"
michael@0 23 lines = self.err.splitlines()
michael@0 24 for line in lines:
michael@0 25 # Skip the asm.js compilation success message.
michael@0 26 if "Successfully compiled asm.js code" not in line:
michael@0 27 return line
michael@0 28 return "Unknown"
michael@0 29
michael@0 30 class NullTestOutput:
michael@0 31 """Variant of TestOutput that indicates a test was not run."""
michael@0 32 def __init__(self, test):
michael@0 33 self.test = test
michael@0 34 self.cmd = ''
michael@0 35 self.out = ''
michael@0 36 self.err = ''
michael@0 37 self.rc = 0
michael@0 38 self.dt = 0.0
michael@0 39 self.timed_out = False
michael@0 40
michael@0 41 class TestResult:
michael@0 42 PASS = 'PASS'
michael@0 43 FAIL = 'FAIL'
michael@0 44 CRASH = 'CRASH'
michael@0 45
michael@0 46 """Classified result from a test run."""
michael@0 47 def __init__(self, test, result, results):
michael@0 48 self.test = test
michael@0 49 self.result = result
michael@0 50 self.results = results
michael@0 51
michael@0 52 @classmethod
michael@0 53 def from_output(cls, output):
michael@0 54 test = output.test
michael@0 55 result = None # str: overall result, see class-level variables
michael@0 56 results = [] # (str,str) list: subtest results (pass/fail, message)
michael@0 57
michael@0 58 out, rc = output.out, output.rc
michael@0 59
michael@0 60 failures = 0
michael@0 61 passes = 0
michael@0 62
michael@0 63 expected_rcs = []
michael@0 64 if test.path.endswith('-n.js'):
michael@0 65 expected_rcs.append(3)
michael@0 66
michael@0 67 for line in out.split('\n'):
michael@0 68 if line.startswith(' FAILED!'):
michael@0 69 failures += 1
michael@0 70 msg = line[len(' FAILED! '):]
michael@0 71 results.append((cls.FAIL, msg))
michael@0 72 elif line.startswith(' PASSED!'):
michael@0 73 passes += 1
michael@0 74 msg = line[len(' PASSED! '):]
michael@0 75 results.append((cls.PASS, msg))
michael@0 76 else:
michael@0 77 m = re.match('--- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE ((?:-|\\d)+) ---', line)
michael@0 78 if m:
michael@0 79 expected_rcs.append(int(m.group(1)))
michael@0 80
michael@0 81 if rc and not rc in expected_rcs:
michael@0 82 if rc == 3:
michael@0 83 result = cls.FAIL
michael@0 84 else:
michael@0 85 result = cls.CRASH
michael@0 86 else:
michael@0 87 if (rc or passes > 0) and failures == 0:
michael@0 88 result = cls.PASS
michael@0 89 else:
michael@0 90 result = cls.FAIL
michael@0 91
michael@0 92 return cls(test, result, results)
michael@0 93
michael@0 94 class ResultsSink:
michael@0 95 def __init__(self, options, testcount):
michael@0 96 self.options = options
michael@0 97 self.fp = options.output_fp
michael@0 98
michael@0 99 self.groups = {}
michael@0 100 self.counts = {'PASS': 0, 'FAIL': 0, 'TIMEOUT': 0, 'SKIP': 0}
michael@0 101 self.n = 0
michael@0 102
michael@0 103 if options.hide_progress:
michael@0 104 self.pb = NullProgressBar()
michael@0 105 else:
michael@0 106 fmt = [
michael@0 107 {'value': 'PASS', 'color': 'green'},
michael@0 108 {'value': 'FAIL', 'color': 'red'},
michael@0 109 {'value': 'TIMEOUT', 'color': 'blue'},
michael@0 110 {'value': 'SKIP', 'color': 'brightgray'},
michael@0 111 ]
michael@0 112 self.pb = ProgressBar(testcount, fmt)
michael@0 113
michael@0 114 def push(self, output):
michael@0 115 if output.timed_out:
michael@0 116 self.counts['TIMEOUT'] += 1
michael@0 117 if isinstance(output, NullTestOutput):
michael@0 118 if self.options.tinderbox:
michael@0 119 self.print_tinderbox_result('TEST-KNOWN-FAIL', output.test.path, time=output.dt, skip=True)
michael@0 120 self.counts['SKIP'] += 1
michael@0 121 self.n += 1
michael@0 122 else:
michael@0 123 result = TestResult.from_output(output)
michael@0 124 tup = (result.result, result.test.expect, result.test.random)
michael@0 125 dev_label = self.LABELS[tup][1]
michael@0 126 if output.timed_out:
michael@0 127 dev_label = 'TIMEOUTS'
michael@0 128 self.groups.setdefault(dev_label, []).append(result.test.path)
michael@0 129
michael@0 130 show = self.options.show
michael@0 131 if self.options.failed_only and dev_label not in ('REGRESSIONS', 'TIMEOUTS'):
michael@0 132 show = False
michael@0 133 if show:
michael@0 134 self.pb.beginline()
michael@0 135
michael@0 136 if show:
michael@0 137 if self.options.show_output:
michael@0 138 print >> self.fp, '## %s: rc = %d, run time = %f' % (output.test.path, output.rc, output.dt)
michael@0 139
michael@0 140 if self.options.show_cmd:
michael@0 141 print >> self.fp, escape_cmdline(output.cmd)
michael@0 142
michael@0 143 if self.options.show_output:
michael@0 144 self.fp.write(output.out)
michael@0 145 self.fp.write(output.err)
michael@0 146
michael@0 147 self.n += 1
michael@0 148
michael@0 149 if result.result == TestResult.PASS and not result.test.random:
michael@0 150 self.counts['PASS'] += 1
michael@0 151 elif result.test.expect and not result.test.random:
michael@0 152 self.counts['FAIL'] += 1
michael@0 153 else:
michael@0 154 self.counts['SKIP'] += 1
michael@0 155
michael@0 156 if self.options.tinderbox:
michael@0 157 if len(result.results) > 1:
michael@0 158 for sub_ok, msg in result.results:
michael@0 159 label = self.LABELS[(sub_ok, result.test.expect, result.test.random)][0]
michael@0 160 if label == 'TEST-UNEXPECTED-PASS':
michael@0 161 label = 'TEST-PASS (EXPECTED RANDOM)'
michael@0 162 self.print_tinderbox_result(label, result.test.path, time=output.dt, message=msg)
michael@0 163 self.print_tinderbox_result(self.LABELS[
michael@0 164 (result.result, result.test.expect, result.test.random)][0],
michael@0 165 result.test.path, time=output.dt)
michael@0 166 return
michael@0 167
michael@0 168 if dev_label:
michael@0 169 def singular(label):
michael@0 170 return "FIXED" if label == "FIXES" else label[:-1]
michael@0 171 self.pb.message("%s - %s" % (singular(dev_label), output.test.path))
michael@0 172
michael@0 173 self.pb.update(self.n, self.counts)
michael@0 174
michael@0 175 def finish(self, completed):
michael@0 176 self.pb.finish(completed)
michael@0 177 if not self.options.tinderbox:
michael@0 178 self.list(completed)
michael@0 179
michael@0 180 # Conceptually, this maps (test result x test expection) to text labels.
michael@0 181 # key is (result, expect, random)
michael@0 182 # value is (tinderbox label, dev test category)
michael@0 183 LABELS = {
michael@0 184 (TestResult.CRASH, False, False): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
michael@0 185 (TestResult.CRASH, False, True): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
michael@0 186 (TestResult.CRASH, True, False): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
michael@0 187 (TestResult.CRASH, True, True): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
michael@0 188
michael@0 189 (TestResult.FAIL, False, False): ('TEST-KNOWN-FAIL', ''),
michael@0 190 (TestResult.FAIL, False, True): ('TEST-KNOWN-FAIL (EXPECTED RANDOM)', ''),
michael@0 191 (TestResult.FAIL, True, False): ('TEST-UNEXPECTED-FAIL', 'REGRESSIONS'),
michael@0 192 (TestResult.FAIL, True, True): ('TEST-KNOWN-FAIL (EXPECTED RANDOM)', ''),
michael@0 193
michael@0 194 (TestResult.PASS, False, False): ('TEST-UNEXPECTED-PASS', 'FIXES'),
michael@0 195 (TestResult.PASS, False, True): ('TEST-PASS (EXPECTED RANDOM)', ''),
michael@0 196 (TestResult.PASS, True, False): ('TEST-PASS', ''),
michael@0 197 (TestResult.PASS, True, True): ('TEST-PASS (EXPECTED RANDOM)', ''),
michael@0 198 }
michael@0 199
michael@0 200 def list(self, completed):
michael@0 201 for label, paths in sorted(self.groups.items()):
michael@0 202 if label == '': continue
michael@0 203
michael@0 204 print label
michael@0 205 for path in paths:
michael@0 206 print ' %s'%path
michael@0 207
michael@0 208 if self.options.failure_file:
michael@0 209 failure_file = open(self.options.failure_file, 'w')
michael@0 210 if not self.all_passed():
michael@0 211 if 'REGRESSIONS' in self.groups:
michael@0 212 for path in self.groups['REGRESSIONS']:
michael@0 213 print >> failure_file, path
michael@0 214 if 'TIMEOUTS' in self.groups:
michael@0 215 for path in self.groups['TIMEOUTS']:
michael@0 216 print >> failure_file, path
michael@0 217 failure_file.close()
michael@0 218
michael@0 219 suffix = '' if completed else ' (partial run -- interrupted by user)'
michael@0 220 if self.all_passed():
michael@0 221 print 'PASS' + suffix
michael@0 222 else:
michael@0 223 print 'FAIL' + suffix
michael@0 224
michael@0 225 def all_passed(self):
michael@0 226 return 'REGRESSIONS' not in self.groups and 'TIMEOUTS' not in self.groups
michael@0 227
michael@0 228 def print_tinderbox_result(self, label, path, message=None, skip=False, time=None):
michael@0 229 result = label
michael@0 230 result += " | " + path
michael@0 231 result += " |" + self.options.shell_args
michael@0 232 if message:
michael@0 233 result += " | " + message
michael@0 234 if skip:
michael@0 235 result += ' | (SKIP)'
michael@0 236 if time > self.options.timeout:
michael@0 237 result += ' | (TIMEOUT)'
michael@0 238 print result
michael@0 239

mercurial