Commit 6056d32b authored by Michal Majewski's avatar Michal Majewski Committed by Commit Bot

[test] Extract expected outcomes. Simpler FAIL_* handling.

Bug: v8:6917
Cq-Include-Trybots: master.tryserver.v8:v8_linux_noi18n_rel_ng
Change-Id: I864de452bacb9e34fa1bc70722bf4c2fa3de4204
Reviewed-on: https://chromium-review.googlesource.com/782723Reviewed-by: 's avatarMichael Achenbach <machenbach@chromium.org>
Reviewed-by: 's avatarSergiy Byelozyorov <sergiyb@chromium.org>
Commit-Queue: Michał Majewski <majeski@google.com>
Cr-Commit-Position: refs/heads/master@{#49614}
parent c1f2966d
...@@ -39,8 +39,8 @@ class BenchmarksVariantGenerator(testsuite.VariantGenerator): ...@@ -39,8 +39,8 @@ class BenchmarksVariantGenerator(testsuite.VariantGenerator):
# always opt to match the way the benchmarks are run for performance # always opt to match the way the benchmarks are run for performance
# testing. # testing.
def FilterVariantsByTest(self, testcase): def FilterVariantsByTest(self, testcase):
outcomes = self.suite.GetOutcomesForTestCase(testcase) outcomes = self.suite.GetStatusFileOutcomes(testcase)
if outcomes and statusfile.OnlyStandardVariant(outcomes): if statusfile.OnlyStandardVariant(outcomes):
return self.standard_variant return self.standard_variant
return self.fast_variants return self.fast_variants
......
...@@ -102,7 +102,7 @@ FAST_VARIANTS = { ...@@ -102,7 +102,7 @@ FAST_VARIANTS = {
class Test262VariantGenerator(testsuite.VariantGenerator): class Test262VariantGenerator(testsuite.VariantGenerator):
def GetFlagSets(self, testcase, variant): def GetFlagSets(self, testcase, variant):
outcomes = testcase.suite.GetOutcomesForTestCase(testcase) outcomes = testcase.suite.GetStatusFileOutcomes(testcase)
if outcomes and statusfile.OnlyFastVariants(outcomes): if outcomes and statusfile.OnlyFastVariants(outcomes):
variant_flags = FAST_VARIANTS variant_flags = FAST_VARIANTS
else: else:
...@@ -242,16 +242,12 @@ class Test262TestSuite(testsuite.TestSuite): ...@@ -242,16 +242,12 @@ class Test262TestSuite(testsuite.TestSuite):
return True return True
return "FAILED!" in output.stdout return "FAILED!" in output.stdout
def HasUnexpectedOutput(self, testcase): def GetExpectedOutcomes(self, testcase):
outcome = self.GetOutcome(testcase) outcomes = self.GetStatusFileOutcomes(testcase)
outcomes = self.GetOutcomesForTestCase(testcase)
if (statusfile.FAIL_SLOPPY in outcomes and if (statusfile.FAIL_SLOPPY in outcomes and
"--use-strict" not in testcase.flags): '--use-strict' not in testcase.flags):
return outcome != statusfile.FAIL return [statusfile.FAIL]
return not outcome in ([outcome for outcome in outcomes return super(Test262TestSuite, self).GetExpectedOutcomes(testcase)
if not outcome.startswith('--')
and outcome != statusfile.FAIL_SLOPPY]
or [statusfile.PASS])
def PrepareSources(self): def PrepareSources(self):
# The archive is created only on swarming. Local checkouts have the # The archive is created only on swarming. Local checkouts have the
......
...@@ -209,7 +209,7 @@ class Runner(object): ...@@ -209,7 +209,7 @@ class Runner(object):
self.suite_names = [s.name for s in suites] self.suite_names = [s.name for s in suites]
# Always pre-sort by status file, slowest tests first. # Always pre-sort by status file, slowest tests first.
slow_key = lambda t: statusfile.IsSlow(t.suite.GetOutcomesForTestCase(t)) slow_key = lambda t: statusfile.IsSlow(t.suite.GetStatusFileOutcomes(t))
self.tests.sort(key=slow_key, reverse=True) self.tests.sort(key=slow_key, reverse=True)
# Sort by stored duration of not opted out. # Sort by stored duration of not opted out.
......
...@@ -337,7 +337,7 @@ class JsonTestProgressIndicator(ProgressIndicator): ...@@ -337,7 +337,7 @@ class JsonTestProgressIndicator(ProgressIndicator):
"command": self._EscapeCommand(test).replace(ABS_PATH_PREFIX, ""), "command": self._EscapeCommand(test).replace(ABS_PATH_PREFIX, ""),
"duration": test.duration, "duration": test.duration,
"marked_slow": statusfile.IsSlow( "marked_slow": statusfile.IsSlow(
test.suite.GetOutcomesForTestCase(test)), test.suite.GetStatusFileOutcomes(test)),
} for test in timed_tests[:20] } for test in timed_tests[:20]
] ]
...@@ -370,7 +370,7 @@ class JsonTestProgressIndicator(ProgressIndicator): ...@@ -370,7 +370,7 @@ class JsonTestProgressIndicator(ProgressIndicator):
"stderr": test.output.stderr, "stderr": test.output.stderr,
"exit_code": test.output.exit_code, "exit_code": test.output.exit_code,
"result": test.suite.GetOutcome(test), "result": test.suite.GetOutcome(test),
"expected": list(test.suite.GetOutcomesForTestCase(test) or ["PASS"]), "expected": test.suite.GetExpectedOutcomes(test),
"duration": test.duration, "duration": test.duration,
# TODO(machenbach): This stores only the global random seed from the # TODO(machenbach): This stores only the global random seed from the
...@@ -415,11 +415,7 @@ class FlakinessTestProgressIndicator(ProgressIndicator): ...@@ -415,11 +415,7 @@ class FlakinessTestProgressIndicator(ProgressIndicator):
assert outcome in ["PASS", "FAIL", "CRASH", "TIMEOUT"] assert outcome in ["PASS", "FAIL", "CRASH", "TIMEOUT"]
if test.run == 1: if test.run == 1:
# First run of this test. # First run of this test.
expected_outcomes = ([ expected_outcomes = test.suite.GetExpectedOutcomes(test)
expected
for expected in (test.suite.GetOutcomesForTestCase(test) or ["PASS"])
if expected in ["PASS", "FAIL", "CRASH", "TIMEOUT"]
] or ["PASS"])
self.results[key] = { self.results[key] = {
"actual": outcome, "actual": outcome,
"expected": " ".join(expected_outcomes), "expected": " ".join(expected_outcomes),
......
...@@ -31,29 +31,29 @@ import re ...@@ -31,29 +31,29 @@ import re
from variants import ALL_VARIANTS from variants import ALL_VARIANTS
from utils import Freeze from utils import Freeze
# These outcomes can occur in a TestCase's outcomes list: # Possible outcomes
SKIP = "SKIP"
FAIL = "FAIL" FAIL = "FAIL"
PASS = "PASS" PASS = "PASS"
OKAY = "OKAY" # TODO(majeski): unused in status files
TIMEOUT = "TIMEOUT" # TODO(majeski): unused in status files TIMEOUT = "TIMEOUT" # TODO(majeski): unused in status files
CRASH = "CRASH" # TODO(majeski): unused in status files CRASH = "CRASH" # TODO(majeski): unused in status files
# Outcomes only for status file, need special handling
FAIL_OK = "FAIL_OK"
FAIL_SLOPPY = "FAIL_SLOPPY"
# Modifiers
SKIP = "SKIP"
SLOW = "SLOW" SLOW = "SLOW"
FAST_VARIANTS = "FAST_VARIANTS" FAST_VARIANTS = "FAST_VARIANTS"
NO_VARIANTS = "NO_VARIANTS" NO_VARIANTS = "NO_VARIANTS"
# These are just for the status files and are mapped below in DEFS:
FAIL_OK = "FAIL_OK"
FAIL_SLOPPY = "FAIL_SLOPPY"
ALWAYS = "ALWAYS" ALWAYS = "ALWAYS"
KEYWORDS = {} KEYWORDS = {}
for key in [SKIP, FAIL, PASS, OKAY, CRASH, SLOW, FAIL_OK, for key in [SKIP, FAIL, PASS, CRASH, SLOW, FAIL_OK, FAST_VARIANTS, NO_VARIANTS,
FAST_VARIANTS, NO_VARIANTS, FAIL_SLOPPY, ALWAYS]: FAIL_SLOPPY, ALWAYS]:
KEYWORDS[key] = key KEYWORDS[key] = key
DEFS = {FAIL_OK: [FAIL, OKAY]}
# Support arches, modes to be written as keywords instead of strings. # Support arches, modes to be written as keywords instead of strings.
VARIABLES = {ALWAYS: True} VARIABLES = {ALWAYS: True}
for var in ["debug", "release", "big", "little", for var in ["debug", "release", "big", "little",
...@@ -85,24 +85,13 @@ def OnlyFastVariants(outcomes): ...@@ -85,24 +85,13 @@ def OnlyFastVariants(outcomes):
def IsPassOrFail(outcomes): def IsPassOrFail(outcomes):
return ((PASS in outcomes) and (FAIL in outcomes) and return (PASS in outcomes and
(not CRASH in outcomes) and (not OKAY in outcomes)) FAIL in outcomes and
CRASH not in outcomes)
def IsFailOk(outcomes): def IsFailOk(outcomes):
return (FAIL in outcomes) and (OKAY in outcomes) return FAIL_OK in outcomes
def _AddOutcome(result, new):
if new in DEFS:
mapped = DEFS[new]
if type(mapped) == list:
for m in mapped:
_AddOutcome(result, m)
elif type(mapped) == str:
_AddOutcome(result, mapped)
else:
result.add(new)
def _JoinsPassAndFail(outcomes1, outcomes2): def _JoinsPassAndFail(outcomes1, outcomes2):
...@@ -111,8 +100,8 @@ def _JoinsPassAndFail(outcomes1, outcomes2): ...@@ -111,8 +100,8 @@ def _JoinsPassAndFail(outcomes1, outcomes2):
""" """
return ( return (
PASS in outcomes1 and PASS in outcomes1 and
not FAIL in outcomes1 and not (FAIL in outcomes1 or FAIL_OK in outcomes1) and
FAIL in outcomes2 (FAIL in outcomes2 or FAIL_OK in outcomes2)
) )
VARIANT_EXPRESSION = object() VARIANT_EXPRESSION = object()
...@@ -155,7 +144,7 @@ def _ParseOutcomeList(rule, outcomes, variables, target_dict): ...@@ -155,7 +144,7 @@ def _ParseOutcomeList(rule, outcomes, variables, target_dict):
outcomes = [outcomes] outcomes = [outcomes]
for item in outcomes: for item in outcomes:
if type(item) == str: if type(item) == str:
_AddOutcome(result, item) result.add(item)
elif type(item) == list: elif type(item) == list:
condition = item[0] condition = item[0]
exp = _EvalExpression(condition, variables) exp = _EvalExpression(condition, variables)
...@@ -170,7 +159,7 @@ def _ParseOutcomeList(rule, outcomes, variables, target_dict): ...@@ -170,7 +159,7 @@ def _ParseOutcomeList(rule, outcomes, variables, target_dict):
for outcome in item[1:]: for outcome in item[1:]:
assert type(outcome) == str assert type(outcome) == str
_AddOutcome(result, outcome) result.add(outcome)
else: else:
assert False assert False
if len(result) == 0: if len(result) == 0:
......
...@@ -50,7 +50,7 @@ class VariantGenerator(object): ...@@ -50,7 +50,7 @@ class VariantGenerator(object):
def FilterVariantsByTest(self, testcase): def FilterVariantsByTest(self, testcase):
result = self.all_variants result = self.all_variants
outcomes = testcase.suite.GetOutcomesForTestCase(testcase) outcomes = testcase.suite.GetStatusFileOutcomes(testcase)
if outcomes: if outcomes:
if statusfile.OnlyStandardVariant(outcomes): if statusfile.OnlyStandardVariant(outcomes):
return self.standard_variant return self.standard_variant
...@@ -59,7 +59,7 @@ class VariantGenerator(object): ...@@ -59,7 +59,7 @@ class VariantGenerator(object):
return result return result
def GetFlagSets(self, testcase, variant): def GetFlagSets(self, testcase, variant):
outcomes = testcase.suite.GetOutcomesForTestCase(testcase) outcomes = testcase.suite.GetStatusFileOutcomes(testcase)
if outcomes and statusfile.OnlyFastVariants(outcomes): if outcomes and statusfile.OnlyFastVariants(outcomes):
return FAST_VARIANT_FLAGS[variant] return FAST_VARIANT_FLAGS[variant]
else: else:
...@@ -147,7 +147,7 @@ class TestSuite(object): ...@@ -147,7 +147,7 @@ class TestSuite(object):
before using this function. before using this function.
""" """
flags = [] flags = []
for outcome in self.GetOutcomesForTestCase(test): for outcome in self.GetStatusFileOutcomes(test):
if outcome.startswith('--'): if outcome.startswith('--'):
flags.append(outcome) flags.append(outcome)
return flags return flags
...@@ -179,7 +179,7 @@ class TestSuite(object): ...@@ -179,7 +179,7 @@ class TestSuite(object):
(mode == 'skip' and pass_fail)) (mode == 'skip' and pass_fail))
def _compliant(test): def _compliant(test):
outcomes = self.GetOutcomesForTestCase(test) outcomes = self.GetStatusFileOutcomes(test)
if statusfile.DoSkip(outcomes): if statusfile.DoSkip(outcomes):
return False return False
if _skip_slow(statusfile.IsSlow(outcomes), slow_tests_mode): if _skip_slow(statusfile.IsSlow(outcomes), slow_tests_mode):
...@@ -256,7 +256,29 @@ class TestSuite(object): ...@@ -256,7 +256,29 @@ class TestSuite(object):
break break
self.tests = filtered self.tests = filtered
def GetOutcomesForTestCase(self, testcase): def GetExpectedOutcomes(self, testcase):
"""Gets expected outcomes from status file.
It differs from GetStatusFileOutcomes by selecting only outcomes that can
be result of test execution.
Status file has to be loaded before using this function.
"""
outcomes = self.GetStatusFileOutcomes(testcase)
expected = []
if (statusfile.FAIL in outcomes or
statusfile.FAIL_OK in outcomes):
expected.append(statusfile.FAIL)
if statusfile.CRASH in outcomes:
expected.append(statusfile.CRASH)
if statusfile.PASS in outcomes:
expected.append(statusfile.PASS)
return expected or [statusfile.PASS]
def GetStatusFileOutcomes(self, testcase):
"""Gets outcomes from status file. """Gets outcomes from status file.
Merges variant dependent and independent rules. Status file has to be loaded Merges variant dependent and independent rules. Status file has to be loaded
...@@ -323,9 +345,7 @@ class TestSuite(object): ...@@ -323,9 +345,7 @@ class TestSuite(object):
return statusfile.PASS return statusfile.PASS
def HasUnexpectedOutput(self, testcase): def HasUnexpectedOutput(self, testcase):
outcome = self.GetOutcome(testcase) return self.GetOutcome(testcase) not in self.GetExpectedOutcomes(testcase)
return not outcome in (self.GetOutcomesForTestCase(testcase)
or [statusfile.PASS])
def StripOutputForTransmit(self, testcase): def StripOutputForTransmit(self, testcase):
if not self.HasUnexpectedOutput(testcase): if not self.HasUnexpectedOutput(testcase):
......
...@@ -39,7 +39,7 @@ class TestSuiteTest(unittest.TestCase): ...@@ -39,7 +39,7 @@ class TestSuiteTest(unittest.TestCase):
[TestCase(suite, 'baz/bar')], [TestCase(suite, 'baz/bar')],
suite.tests, suite.tests,
) )
outcomes = suite.GetOutcomesForTestCase(suite.tests[0]) outcomes = suite.GetStatusFileOutcomes(suite.tests[0])
self.assertEquals(set(['PASS', 'FAIL', 'SLOW']), outcomes) self.assertEquals(set(['PASS', 'FAIL', 'SLOW']), outcomes)
def test_filter_testcases_by_status_second_pass(self): def test_filter_testcases_by_status_second_pass(self):
...@@ -89,13 +89,31 @@ class TestSuiteTest(unittest.TestCase): ...@@ -89,13 +89,31 @@ class TestSuiteTest(unittest.TestCase):
self.assertEquals( self.assertEquals(
set(['PREV', 'PASS', 'SLOW']), set(['PREV', 'PASS', 'SLOW']),
suite.GetOutcomesForTestCase(suite.tests[0]), suite.GetStatusFileOutcomes(suite.tests[0]),
) )
self.assertEquals( self.assertEquals(
set(['PREV', 'PASS', 'FAIL', 'SLOW']), set(['PREV', 'PASS', 'FAIL', 'SLOW']),
suite.GetOutcomesForTestCase(suite.tests[1]), suite.GetStatusFileOutcomes(suite.tests[1]),
) )
def test_fail_ok_outcome(self):
suite = TestSuite('foo', 'bar')
suite.tests = [
TestCase(suite, 'foo/bar'),
TestCase(suite, 'baz/bar'),
]
suite.rules = {
'': {
'foo/bar': set(['FAIL_OK']),
'baz/bar': set(['FAIL']),
},
}
suite.prefix_rules = {}
for t in suite.tests:
expected_outcomes = suite.GetExpectedOutcomes(t)
self.assertEquals(['FAIL'], expected_outcomes)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -45,7 +45,7 @@ def PrintReport(tests): ...@@ -45,7 +45,7 @@ def PrintReport(tests):
total = len(tests) total = len(tests)
skipped = nocrash = passes = fail_ok = fail = 0 skipped = nocrash = passes = fail_ok = fail = 0
for t in tests: for t in tests:
outcomes = t.suite.GetOutcomesForTestCase(t) outcomes = t.suite.GetStatusFileOutcomes(t)
if not outcomes: if not outcomes:
passes += 1 passes += 1
continue continue
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment