# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
import textwrap
import unittest
from unittest import mock
from blinkpy.common.host_mock import MockHost
from blinkpy.common.net.git_cl import BuildStatus
from blinkpy.common.net.git_cl_mock import MockGitCL
from blinkpy.common.net.results_fetcher import Build
from blinkpy.common.net.web_test_results import WebTestResults
from blinkpy.common.system.executive import ScriptError
from blinkpy.common.system.log_testing import LoggingTestCase
from blinkpy.w3c.gerrit_mock import MockGerritAPI
from blinkpy.w3c.wpt_expectations_updater import WPTExpectationsUpdater
from blinkpy.w3c.wpt_manifest import (
WPTManifest, BASE_MANIFEST_NAME, MANIFEST_NAME)
from blinkpy.web_tests.builder_list import BuilderList
from blinkpy.web_tests.models.test_expectations import TestExpectations
from blinkpy.web_tests.models.typ_types import ResultType
from blinkpy.web_tests.port.factory_mock import MockPortFactory
from blinkpy.web_tests.port.test import MOCK_WEB_TESTS
@mock.patch('blinkpy.tool.commands.build_resolver.GerritAPI', MockGerritAPI)
class WPTExpectationsUpdaterTest(LoggingTestCase):
def mock_host(self):
"""Returns a mock host with fake values set up for testing."""
host = MockHost()
host.port_factory = MockPortFactory(host)
host.executive._output = ''
# Set up a fake list of try builders.
host.builders = BuilderList({
'MOCK Try Mac10.10': {
'port_name': 'test-mac-mac10.10',
'specifiers': ['Mac10.10', 'Release'],
'is_try_builder': True,
'steps': {
'blink_wpt_tests': {},
},
},
'MOCK Try Mac10.11': {
'port_name': 'test-mac-mac10.11',
'specifiers': ['Mac10.11', 'Release'],
'is_try_builder': True,
'steps': {
'blink_wpt_tests': {},
},
},
'MOCK Try Trusty': {
'port_name': 'test-linux-trusty',
'specifiers': ['Trusty', 'Release'],
'main': 'tryserver.blink',
'is_try_builder': True,
'steps': {
'blink_web_tests': {},
'blink_wpt_tests': {},
'fake_flag_blink_wpt_tests': {
'flag_specific': 'fake-flag',
},
},
},
'MOCK Try Precise': {
'port_name': 'test-linux-precise',
'specifiers': ['Precise', 'Release'],
'is_try_builder': True,
'steps': {
'blink_wpt_tests': {},
},
},
'MOCK Try Win10': {
'port_name': 'test-win-win10',
'specifiers': ['Win10', 'Release'],
'is_try_builder': True,
'steps': {
'blink_wpt_tests': {},
},
},
'MOCK Try Win7': {
'port_name': 'test-win-win7',
'specifiers': ['Win7', 'Release'],
'is_try_builder': True,
'steps': {
'blink_wpt_tests': {},
},
},
})
# Null `SearchBuilds` response so that `BuildResolver` ignores CI
# builds.
host.web.append_prpc_response({})
fs = host.filesystem
port = host.port_factory.get()
for path in ('TestExpectations', 'FlagExpectations/fake-flag'):
fs.write_text_file(
fs.join(port.web_tests_dir(), path),
textwrap.dedent("""\
# tags: [ Mac10.10 Mac10.11 Mac Trusty Precise Linux Win7 Win10 Win ]
# results: [ Timeout Crash Pass Failure Skip ]
"""))
fs.write_text_file(fs.join(port.web_tests_dir(), 'FlagSpecificConfig'),
json.dumps([{
'name': 'fake-flag',
'args': [],
}]))
# Write a dummy manifest file, describing what tests exist.
fs.write_text_file(
fs.join(port.web_tests_dir(), 'external', BASE_MANIFEST_NAME),
json.dumps({
'items': {
'reftest': {
'reftest.html': [
'abcdef123',
[None, [['/reftest-ref.html', '==']], {}]
]
},
'testharness': {
'test/path.html': ['abcdef123', [None, {}]],
'test/zzzz.html': ['ghijkl456', [None, {}]],
'fake/some_test.html':
['ghijkl456', ['fake/some_test.html?HelloWorld', {}]],
'fake/file/deleted_path.html':
['ghijkl456', [None, {}]],
'test/task.js': [
'mnpqrs789', ['test/task.html', {}],
['test/task2.html', {}]
],
},
'manual': {
'x-manual.html': ['abcdef123', [None, {}]],
},
},
}))
return host
def mock_updater(self, host) -> WPTExpectationsUpdater:
updater = WPTExpectationsUpdater(host)
updater.git_cl = MockGitCL(
host, {
Build('MOCK Try Mac10.10', 333, 'Build-1'):
BuildStatus.FAILURE,
Build('MOCK Try Mac10.11', 111, 'Build-2'):
BuildStatus.FAILURE,
Build('MOCK Try Trusty', 222, 'Build-3'): BuildStatus.FAILURE,
Build('MOCK Try Precise', 333, 'Build-4'): BuildStatus.FAILURE,
Build('MOCK Try Win10', 444, 'Build-5'): BuildStatus.FAILURE,
Build('MOCK Try Win7', 555, 'Build-6'): BuildStatus.FAILURE,
})
return updater
def test_suite_for_builder(self):
host = self.mock_host()
host.builders = BuilderList({
'MOCK Try Trusty': {
'port_name': 'test-linux-trusty',
'specifiers': ['Trusty', 'Release'],
'is_try_builder': True,
'steps': {
'blink_web_tests': {},
'blink_wpt_tests': {},
'webdriver_wpt_tests': {},
'fake_flag_blink_wpt_tests': {
'flag_specific': 'fake-flag',
},
},
},
})
updater = WPTExpectationsUpdater(host)
self.assertEqual(
updater.suites_for_builder('MOCK Try Trusty'), {
'blink_wpt_tests',
'webdriver_wpt_tests',
'fake_flag_blink_wpt_tests',
})
def test_run_single_platform_failure(self):
"""Tests the main run method in a case where one test fails on one platform."""
host = self.mock_host()
# Fill in an initial value for TestExpectations
expectations_path = \
host.port_factory.get().path_to_generic_test_expectations_file()
host.filesystem.write_text_file(
expectations_path,
textwrap.dedent(f"""\
# tags: [ Mac10.10 Mac10.11 Mac Trusty Precise Linux Win7 Win10 Win ]
# results: [ Pass Timeout ]
"""))
# Set up fake try job results.
updater = WPTExpectationsUpdater(host)
updater.git_cl = MockGitCL(
updater.host, {
Build('MOCK Try Mac10.10', 333, 'Build-1'):
BuildStatus.FAILURE,
Build('MOCK Try Mac10.11', 111, 'Build-2'):
BuildStatus.SUCCESS,
Build('MOCK Try Trusty', 222, 'Build-3'): BuildStatus.SUCCESS,
Build('MOCK Try Precise', 333, 'Build-4'): BuildStatus.SUCCESS,
Build('MOCK Try Win10', 444, 'Build-5'): BuildStatus.SUCCESS,
Build('MOCK Try Win7', 555, 'Build-6'): BuildStatus.SUCCESS,
})
# Set up failing results for one try bot. It shouldn't matter what
# results are for the other builders since we shouldn't need to even
# fetch results, since the try job status already tells us that all
# of the tests passed.
host.results_fetcher.set_results(
Build('MOCK Try Mac10.10', 333, 'Build-1'),
WebTestResults.from_rdb_responses(
{'external/wpt/test/path.html': [{
'status': 'ABORT'
}] * 3},
# The real `TestResultsFetcher.gather_results` removes the `(with
# patch)` suffix anyways. The mock is not that sophisticated, so
# omit the suffix here.
step_name='blink_wpt_tests'))
self.assertEqual(0, updater.run())
self.assertEqual(
host.filesystem.read_text_file(expectations_path),
textwrap.dedent("""\
# tags: [ Mac10.10 Mac10.11 Mac Trusty Precise Linux Win7 Win10 Win ]
# results: [ Pass Timeout ]
# ====== New tests from wpt-importer added here ======
[ Mac10.10 ] external/wpt/test/path.html [ Timeout ]
"""))
def test_run_webdriver_only_failure(self):
host = self.mock_host()
host.builders = BuilderList({
'MOCK Try Linux': {
'port_name': 'test-linux-trusty',
'specifiers': ['Linux', 'Release'],
'is_try_builder': True,
'steps': {
'webdriver_wpt_tests': {},
},
},
})
updater = WPTExpectationsUpdater(host)
expectations_path = updater.finder.path_from_web_tests(
'TestExpectations')
host.filesystem.write_text_file(
expectations_path,
textwrap.dedent("""\
# results: [ Timeout ]
external/wpt/not-a-wdspec-test.html [ Timeout ]
# ====== New tests from wpt-importer added here ======
"""))
updater.git_cl = MockGitCL(
updater.host, {
Build('MOCK Try Linux', 333, 'Build-4'): BuildStatus.FAILURE,
})
host.results_fetcher.set_results(
Build('MOCK Try Linux', 333, 'Build-4'),
WebTestResults.from_rdb_responses(
{'external/wpt/webdriver/test.py': [{
'status': 'ABORT'
}] * 3},
step_name='webdriver_wpt_tests'))
self.assertEqual(0, updater.run())
self.assertEqual(
host.filesystem.read_text_file(expectations_path),
textwrap.dedent("""\
# results: [ Timeout ]
external/wpt/not-a-wdspec-test.html [ Timeout ]
# ====== New tests from wpt-importer added here ======
external/wpt/webdriver/test.py [ Timeout ]
"""))
def test_run_inherited_results(self):
host = self.mock_host()
# Fill in an initial value for TestExpectations
port = host.port_factory.get('test-linux-trusty')
expectations_path = port.path_to_generic_test_expectations_file()
host.filesystem.write_text_file(
expectations_path,
textwrap.dedent("""\
# tags: [ Mac10.10 Mac10.11 Mac Trusty Precise Linux Win7 Win10 Win ]
# results: [ Timeout Crash Pass Failure Skip ]
# ====== New tests from wpt-importer added here ======
"""))
host.filesystem.write_text_file(
port.path_to_never_fix_tests_file(),
textwrap.dedent("""\
# tags: [ Mac10.10 Mac10.11 Mac Trusty Precise Linux Win7 Win10 Win ]
# results: [ Skip ]
# Mac10.10 is an old platform that does not run the failing
# test. The updater should still generate a `[ Mac ]`
# expectation instead of `[ Mac10.11 ]`.
[ Mac10.10 ] external/wpt/test/path.html [ Skip ]
"""))
# Set up fake try job results.
updater = WPTExpectationsUpdater(host)
updater.git_cl = MockGitCL(
updater.host, {
Build('MOCK Try Mac10.10', 333, 'Build-1'):
BuildStatus.SUCCESS,
Build('MOCK Try Mac10.11', 111, 'Build-2'):
BuildStatus.FAILURE,
Build('MOCK Try Trusty', 222, 'Build-3'): BuildStatus.FAILURE,
Build('MOCK Try Precise', 333, 'Build-4'):
BuildStatus.INFRA_FAILURE,
Build('MOCK Try Win10', 444, 'Build-5'): BuildStatus.SUCCESS,
Build('MOCK Try Win7', 555, 'Build-6'): BuildStatus.SUCCESS,
})
rdb_results = {
'external/wpt/test/path.html': [{
'status': 'ABORT',
'expected': False,
}] * 3,
}
host.results_fetcher.set_results(
Build('MOCK Try Mac10.11', 111, 'Build-2'),
WebTestResults.from_rdb_responses(rdb_results,
step_name='blink_wpt_tests'))
# Precise should be filled in from Trusty.
host.results_fetcher.set_results(
Build('MOCK Try Precise', 333, 'Build-4'),
WebTestResults.from_rdb_responses({}, step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Trusty', 222, 'Build-3'),
WebTestResults.from_rdb_responses(rdb_results,
step_name='blink_wpt_tests'))
self.assertEqual(0, updater.run())
self.assertEqual(
host.filesystem.read_text_file(expectations_path),
textwrap.dedent("""\
# tags: [ Mac10.10 Mac10.11 Mac Trusty Precise Linux Win7 Win10 Win ]
# results: [ Timeout Crash Pass Failure Skip ]
# ====== New tests from wpt-importer added here ======
[ Mac ] external/wpt/test/path.html [ Timeout ]
[ Linux ] external/wpt/test/path.html [ Timeout ]
"""))
def test_run_single_flag_specific_failure(self):
"""Tests the main run method in a case where one test fails on one
flag-specific suite.
"""
host = self.mock_host()
# Fill in an initial value for TestExpectations
expectations_path = \
host.port_factory.get().path_to_flag_specific_expectations_file('fake-flag')
host.filesystem.write_text_file(
expectations_path, WPTExpectationsUpdater.MARKER_COMMENT + '\n')
# Set up fake try job results.
updater = WPTExpectationsUpdater(host)
updater.git_cl = MockGitCL(
updater.host, {
Build('MOCK Try Mac10.10', 333, 'Build-1'):
BuildStatus.SUCCESS,
Build('MOCK Try Mac10.11', 111, 'Build-2'):
BuildStatus.SUCCESS,
Build('MOCK Try Trusty', 222, 'Build-3'): BuildStatus.FAILURE,
Build('MOCK Try Precise', 333, 'Build-4'): BuildStatus.SUCCESS,
Build('MOCK Try Win10', 444, 'Build-5'): BuildStatus.SUCCESS,
Build('MOCK Try Win7', 555, 'Build-6'): BuildStatus.SUCCESS,
})
# Set up failing results for one try bot. It shouldn't matter what
# results are for the other builders since we shouldn't need to even
# fetch results, since the try job status already tells us that all
# of the tests passed.
host.results_fetcher.set_results(
Build('MOCK Try Trusty', 222, 'Build-3'),
WebTestResults.from_rdb_responses(
{'external/wpt/test/path.html': [{
'status': 'ABORT'
}] * 3},
step_name='fake_flag_blink_wpt_tests'))
# `updater.run` does not update flag-specific expectations.
updater.update_expectations()
self.assertEqual(
host.filesystem.read_text_file(expectations_path),
'# ====== New tests from wpt-importer added here ======\n'
'external/wpt/test/path.html [ Timeout ]\n')
def test_filter_results_for_update_only_passing_results(self):
host = self.mock_host()
results = WebTestResults.from_rdb_responses(
{
'external/wpt/x/passing-test.html': [{
'status': 'PASS',
'expected': True,
}] * 3,
},
step_name='blink_wpt_tests',
build=Build('MOCK Try Mac10.10'))
updater = WPTExpectationsUpdater(host)
_, filtered_results = updater.filter_results_for_update(results)
self.assertEqual(0, len(filtered_results))
self.assertEqual('blink_wpt_tests', results.step_name())
self.assertEqual('MOCK Try Mac10.10', results.builder_name)
def test_filter_results_for_update_unexpected_pass(self):
host = self.mock_host()
results = WebTestResults.from_rdb_responses(
{'external/wpt/x/passing-test.html': [{
'status': 'PASS'
}] * 3},
step_name='blink_wpt_tests',
build=Build('MOCK Try Mac10.10'))
updater = WPTExpectationsUpdater(host)
_, filtered_results = updater.filter_results_for_update(results)
self.assertEqual(0, len(filtered_results))
def test_filter_results_for_update_some_failing_results(self):
host = self.mock_host()
results = WebTestResults.from_rdb_responses(
{'external/wpt/x/failing-test.html': [{
'status': 'ABORT'
}] * 3},
step_name='blink_wpt_tests',
build=Build('MOCK Try Mac10.10'))
updater = WPTExpectationsUpdater(host)
_, (result, ) = updater.filter_results_for_update(results)
self.assertEqual('external/wpt/x/failing-test.html',
result.test_name())
self.assertEqual({'TIMEOUT'}, set(result.actual_results()))
def test_filter_results_for_update_non_wpt_test(self):
host = self.mock_host()
# This shouldn't happen because WPT suite results shouldn't contain
# non-WPT tests in the first place.
results = WebTestResults.from_rdb_responses(
{'x/failing-test.html': [{
'status': 'FAIL',
}] * 3},
step_name='blink_wpt_tests',
build=Build('MOCK Try Mac10.10'))
updater = WPTExpectationsUpdater(host)
_, filtered_results = updater.filter_results_for_update(results)
self.assertEqual(0, len(filtered_results))
def test_filter_results_for_update_not_retried_test(self):
host = self.mock_host()
results = WebTestResults.from_rdb_responses(
{'external/wpt/reftest.html': [{
'status': 'FAIL',
}]},
step_name='blink_wpt_tests',
build=Build('MOCK Try Mac10.10'))
updater = WPTExpectationsUpdater(host)
_, filtered_results = updater.filter_results_for_update(results)
self.assertEqual(0, len(filtered_results))
def test_remove_configurations(self):
host = self.mock_host()
initial_expectations = textwrap.dedent("""\
# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.15 Mac11 Win Win7 Win10 ]
# results: [ Timeout Crash Pass Failure Skip ]
crbug.com/1234 external/wpt/test/foo.html [ Failure ]
crbug.com/1235 [ Win ] external/wpt/test/bar.html [ Timeout ]
""")
final_expectations = textwrap.dedent("""\
# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.15 Mac11 Win Win7 Win10 ]
# results: [ Timeout Crash Pass Failure Skip ]
crbug.com/1234 [ Linux ] external/wpt/test/foo.html [ Failure ]
crbug.com/1234 [ Mac ] external/wpt/test/foo.html [ Failure ]
crbug.com/1234 [ Win10 ] external/wpt/test/foo.html [ Failure ]
crbug.com/1235 [ Win10 ] external/wpt/test/bar.html [ Timeout ]
# ====== New tests from wpt-importer added here ======
[ Win7 ] external/wpt/test/bar.html [ Failure Timeout ]
[ Win7 ] external/wpt/test/foo.html [ Failure Timeout ]
""")
# Fill in an initial value for TestExpectations
expectations_path = \
host.port_factory.get().path_to_generic_test_expectations_file()
host.filesystem.write_text_file(expectations_path, initial_expectations)
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Win7', 555, 'Build-6'),
WebTestResults.from_rdb_responses(
{
'external/wpt/test/foo.html': [{
'status': 'FAIL',
'expected': True,
}] * 2 + [{
'status': 'ABORT',
}],
'external/wpt/test/bar.html': [{
'status': 'FAIL',
}] * 2 + [{
'status': 'ABORT',
'expected': True,
}],
},
step_name='blink_wpt_tests'))
updater.update_expectations()
value = host.filesystem.read_text_file(expectations_path)
self.assertMultiLineEqual(value, final_expectations)
def test_create_line_dict_for_flag_specific(self):
# In this example, there are three unexpected results for wpt tests.
# One of them has match results in generic test expectations,
# another one has non-match results, and the last one has no
# corresponding line in generic test expectations.
host = self.mock_host()
port = host.port_factory.get('test-linux-trusty')
# Fill in an initial value for TestExpectations
expectations_path = port.path_to_generic_test_expectations_file()
content = (
"# results: [ Timeout Crash Pass Failure Skip ]\n"
"external/wpt/reftest.html [ Failure ]\n"
"external/wpt/test/path.html [ Failure ]\n")
host.filesystem.write_text_file(expectations_path, content)
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Trusty', 222, 'Build-3'),
WebTestResults.from_rdb_responses(
{
'external/wpt/reftest.html': [{
'status': 'FAIL',
'expected': True,
}] * 3,
'external/wpt/test/path.html': [{
'status': 'CRASH',
}] * 3,
'external/wpt/test/zzzz.html': [{
'status': 'CRASH',
}] * 3,
},
step_name='fake_flag_blink_wpt_tests'))
updater.update_expectations()
port.set_option_default('flag_specific', 'fake-flag')
expectations = TestExpectations(port)
self.assertEqual(
expectations.get_expectations_from_file(
expectations_path, 'external/wpt/test/zzzz.html'), [])
expectations_path = port.path_to_flag_specific_expectations_file(
'fake-flag')
self.assertEqual(
expectations.get_expectations_from_file(
expectations_path, 'external/wpt/reftest.html'), [])
(line, ) = expectations.get_expectations_from_file(
expectations_path, 'external/wpt/test/path.html')
self.assertEqual(line.reason, '')
self.assertEqual(line.tags, set())
self.assertEqual(line.results, {ResultType.Crash})
(line, ) = expectations.get_expectations_from_file(
expectations_path, 'external/wpt/test/zzzz.html')
self.assertEqual(line.reason, '')
self.assertEqual(line.tags, set())
self.assertEqual(line.results, {ResultType.Crash})
def test_create_line_dict_new_tests(self):
# In this example, there are three unexpected results for wpt tests.
# The new test expectation lines are sorted by test, and then specifier.
host = self.mock_host()
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Mac10.10', 333, 'Build-1'),
WebTestResults.from_rdb_responses(
{'external/wpt/test/zzzz.html': [{
'status': 'CRASH',
}] * 3},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Trusty', 222, 'Build-3'),
WebTestResults.from_rdb_responses(
{
'virtual/foo/external/wpt/test/zzzz.html':
[{
'status': 'ABORT',
}] * 3,
},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Mac10.11', 111, 'Build-2'),
WebTestResults.from_rdb_responses(
{
'virtual/foo/external/wpt/test/zzzz.html':
[{
'status': 'ABORT',
}] * 3,
},
step_name='blink_wpt_tests'))
updater.update_expectations()
expectations = TestExpectations(updater.port)
path = updater.port.path_to_generic_test_expectations_file()
(line, ) = expectations.get_expectations_from_file(
path, 'external/wpt/test/zzzz.html')
self.assertEqual(line.reason, '')
self.assertEqual(line.tags, {'mac10.10'})
self.assertEqual(line.results, {ResultType.Crash})
lines = expectations.get_expectations_from_file(
path, 'virtual/foo/external/wpt/test/zzzz.html')
self.assertEqual(len(lines), 2)
line1, line2 = sorted(lines, key=lambda line: line.tags)
self.assertEqual(line1.reason, '')
self.assertEqual(line1.tags, {'mac10.11'})
self.assertEqual(line1.results, {ResultType.Timeout})
self.assertEqual(line2.reason, '')
self.assertEqual(line2.tags, {'trusty'})
self.assertEqual(line2.results, {ResultType.Timeout})
def test_create_line_dict_with_asterisks(self):
# Literal asterisks in test names need to be escaped in expectations.
updater = WPTExpectationsUpdater(self.mock_host())
results = WebTestResults.from_rdb_responses(
{
'external/wpt/html/dom/interfaces.https.html?exclude=(Document.*|HTML.*)':
[{
'status': 'FAIL',
}] * 3
},
build=Build('MOCK Try Trusty'))
line_dict = updater.write_to_test_expectations([results])
self.assertEqual(
line_dict, {
'external/wpt/html/dom/interfaces.https.html?exclude=(Document.*|HTML.*)':
[
'external/wpt/html/dom/'
'interfaces.https.html?exclude=(Document.\*|HTML.\*) '
'[ Failure ]',
],
})
def test_unsimplifiable_specifiers(self):
host = self.mock_host()
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Win7', 555, 'Build-6'),
WebTestResults.from_rdb_responses(
{'external/wpt/x/z.html': [{
'status': 'ABORT',
}] * 3},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Mac10.10', 333, 'Build-1'),
WebTestResults.from_rdb_responses(
{
'external/wpt/x/y.html': [{
'status': 'ABORT',
}] * 3,
'external/wpt/x/z.html': [{
'status': 'ABORT',
}] * 3,
},
step_name='blink_wpt_tests'))
updater.update_expectations()
expectations = TestExpectations(updater.port)
path = updater.port.path_to_generic_test_expectations_file()
(line, ) = expectations.get_expectations_from_file(
path, 'external/wpt/x/y.html')
self.assertEqual(line.tags, {'mac10.10'})
line1, line2 = expectations.get_expectations_from_file(
path, 'external/wpt/x/z.html')
self.assertEqual(line1.tags | line2.tags, {'win7', 'mac10.10'})
def test_specifiers_can_extend_to_all_platforms(self):
host = self.mock_host()
expectations_path = MOCK_WEB_TESTS + 'NeverFixTests'
host.filesystem.write_text_file(
expectations_path,
('# tags: [ Linux ]\n'
'# results: [ Skip ]\n'
'crbug.com/111 [ Linux ] external/wpt/reftest.html [ Skip ]\n'))
host.filesystem.write_text_file(
MOCK_WEB_TESTS + 'external/wpt/test.html', '')
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Mac10.10', 333, 'Build-1'),
WebTestResults.from_rdb_responses(
{'external/wpt/reftest.html': [{
'status': 'FAIL',
}] * 3},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Win10', 444, 'Build-5'),
WebTestResults.from_rdb_responses(
{'external/wpt/reftest.html': [{
'status': 'FAIL',
}] * 3},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Win7', 555, 'Build-6'),
WebTestResults.from_rdb_responses(
{'external/wpt/reftest.html': [{
'status': 'FAIL',
}] * 3},
step_name='blink_wpt_tests'))
updater.update_expectations()
expectations = TestExpectations(updater.port)
path = updater.port.path_to_generic_test_expectations_file()
line1, line2 = expectations.get_expectations_from_file(
path, 'external/wpt/reftest.html')
self.assertEqual(line1.tags | line2.tags, {'mac10.10', 'win'})
host.results_fetcher.set_results(
Build('MOCK Try Mac10.11', 111, 'Build-2'),
WebTestResults.from_rdb_responses(
{'external/wpt/reftest.html': [{
'status': 'FAIL',
}] * 3},
step_name='blink_wpt_tests'))
host.web.append_prpc_response({})
updater.update_expectations()
expectations = TestExpectations(updater.port)
(line, ) = expectations.get_expectations_from_file(
path, 'external/wpt/reftest.html')
self.assertEqual(line.tags, set())
def test_normalized_specifiers_with_skipped_test(self):
host = self.mock_host()
expectations_path = MOCK_WEB_TESTS + 'NeverFixTests'
host.filesystem.write_text_file(
expectations_path,
('# tags: [ Linux Mac10.11 ]\n'
'# results: [ Skip ]\n'
'crbug.com/111 [ Linux ] external/wpt/x/y.html [ Skip ]\n'
'crbug.com/111 [ Mac10.11 ] external/wpt/x/y.html [ Skip ]\n'))
host.filesystem.write_text_file(
MOCK_WEB_TESTS + 'external/wpt/test.html', '')
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Mac10.10', 333, 'Build-1'),
WebTestResults.from_rdb_responses(
{'external/wpt/x/y.html': [{
'status': 'ABORT',
}] * 3},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Win7', 555, 'Build-6'),
WebTestResults.from_rdb_responses(
{
'external/wpt/x/y.html': [{
'status': 'ABORT',
}] * 3,
'external/wpt/x/z.html': [{
'status': 'ABORT',
}] * 3,
},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Win10', 444, 'Build-5'),
WebTestResults.from_rdb_responses(
{
'external/wpt/x/y.html': [{
'status': 'ABORT',
}] * 3,
'external/wpt/x/z.html': [{
'status': 'ABORT',
}] * 3,
},
step_name='blink_wpt_tests'))
updater.update_expectations()
expectations = TestExpectations(updater.port)
path = updater.port.path_to_generic_test_expectations_file()
(line, ) = expectations.get_expectations_from_file(
path, 'external/wpt/x/y.html')
self.assertEqual(line.tags, set())
(line, ) = expectations.get_expectations_from_file(
path, 'external/wpt/x/z.html')
self.assertEqual(line.tags, {'win'})
def test_no_expectations_to_write(self):
host = self.mock_host()
updater = self.mock_updater(host)
_, exp_dict = updater.update_expectations()
self.assertEqual(exp_dict, {})
logs = ''.join(self.logMessages()).lower()
self.assertIn('no lines to write to testexpectations.', logs)
def test_cleanup_outside_affected_expectations_in_cl(self):
host = self.mock_host()
expectations_path = \
host.port_factory.get().path_to_generic_test_expectations_file()
host.filesystem.write_text_file(
expectations_path,
'# tags: [ Linux ]\n' +
'# results: [ Pass Failure ]\n' +
WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
'[ linux ] external/wpt/fake/some_test.html?HelloWorld [ Failure ]\n' +
'external/wpt/fake/file/non_existent_file.html [ Pass ]\n' +
'external/wpt/fake/file/deleted_path.html [ Pass ]\n')
updater = WPTExpectationsUpdater(
host, ['--clean-up-test-expectations-only'])
updater.port.tests = lambda: {
'external/wpt/fake/new.html?HelloWorld'}
def _git_command_return_val(cmd):
if '--diff-filter=D' in cmd:
return 'external/wpt/fake/file/deleted_path.html'
if '--diff-filter=R' in cmd:
return 'C\texternal/wpt/fake/some_test.html\texternal/wpt/fake/new.html'
return ''
updater.git.run = _git_command_return_val
updater._relative_to_web_test_dir = lambda test_path: test_path
updater.run()
value = host.filesystem.read_text_file(expectations_path)
self.assertMultiLineEqual(
value, ('# tags: [ Linux ]\n' +
'# results: [ Pass Failure ]\n' +
WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
'[ linux ] external/wpt/fake/new.html?HelloWorld [ Failure ]\n'))
def test_clean_expectations_for_deleted_test_harness(self):
host = self.mock_host()
port = host.port_factory.get()
expectations_path = \
port.path_to_generic_test_expectations_file()
host.filesystem.write_text_file(
expectations_path,
'# tags: [ Win Linux ]\n' +
'# results: [ Pass Failure ]\n' +
WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
'[ linux ] wpt_internal/test/task.html [ Failure ]\n' +
'[ win ] wpt_internal/test/task2.html [ Failure ]\n' +
'[ linux ] external/wpt/test/task.html [ Failure ]\n' +
'external/wpt/test/task2.html [ Pass ]\n')
def _git_command_return_val(cmd):
if '--diff-filter=D' in cmd:
return '\n'.join(['external/wpt/test/task.js',
'wpt_internal/test/task.js'])
return ''
wpt_manifest = port.wpt_manifest('external/wpt')
host.filesystem.maybe_make_directory(
port.web_tests_dir(), 'wpt_internal')
host.filesystem.copyfile(
host.filesystem.join(port.web_tests_dir(),
'external', 'wpt', MANIFEST_NAME),
host.filesystem.join(port.web_tests_dir(), 'wpt_internal',
MANIFEST_NAME))
wpt_internal_manifest = WPTManifest.from_file(
port,
host.filesystem.join(port.web_tests_dir(), 'wpt_internal',
MANIFEST_NAME))
updater = WPTExpectationsUpdater(
host,
['--clean-up-affected-tests-only',
'--clean-up-test-expectations-only'],
[wpt_manifest, wpt_internal_manifest])
updater.git.run = _git_command_return_val
updater._relative_to_web_test_dir = lambda test_path: test_path
updater.cleanup_test_expectations_files()
results = WebTestResults.from_rdb_responses(
{'external/wpt/fake/file/path.html': [{
'status': 'FAIL',
}] * 3},
build=Build('MOCK Try Trusty'))
skip_path = host.port_factory.get().path_to_never_fix_tests_file()
skip_value_origin = host.filesystem.read_text_file(skip_path)
updater.write_to_test_expectations([results])
value = host.filesystem.read_text_file(expectations_path)
self.assertMultiLineEqual(
value,
textwrap.dedent("""\
# tags: [ Win Linux ]
# results: [ Pass Failure ]
# ====== New tests from wpt-importer added here ======
external/wpt/fake/file/path.html [ Failure ]
"""))
skip_value = host.filesystem.read_text_file(skip_path)
self.assertMultiLineEqual(skip_value, skip_value_origin)
def test_write_to_test_expectations_and_cleanup_expectations(self):
host = self.mock_host()
expectations_path = \
host.port_factory.get().path_to_generic_test_expectations_file()
host.filesystem.write_text_file(
expectations_path,
'# tags: [ Linux ]\n' +
'# results: [ Pass Failure ]\n' +
WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
'[ linux ] external/wpt/fake/some_test.html?HelloWorld [ Failure ]\n' +
'external/wpt/fake/file/deleted_path.html [ Pass ]\n')
updater = WPTExpectationsUpdater(
host, ['--clean-up-affected-tests-only',
'--clean-up-test-expectations-only'])
def _git_command_return_val(cmd):
if '--diff-filter=D' in cmd:
return 'external/wpt/fake/file/deleted_path.html'
if '--diff-filter=R' in cmd:
return 'C\texternal/wpt/fake/some_test.html\texternal/wpt/fake/new.html'
return ''
updater.git.run = _git_command_return_val
updater._relative_to_web_test_dir = lambda test_path: test_path
updater.cleanup_test_expectations_files()
results = WebTestResults.from_rdb_responses(
{'external/wpt/fake/file/path.html': [{
'status': 'FAIL',
}] * 3},
build=Build('MOCK Try Trusty'))
skip_path = host.port_factory.get().path_to_never_fix_tests_file()
skip_value_origin = host.filesystem.read_text_file(skip_path)
updater.write_to_test_expectations([results])
value = host.filesystem.read_text_file(expectations_path)
self.assertMultiLineEqual(
value,
('# tags: [ Linux ]\n' + '# results: [ Pass Failure ]\n' +
WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
'external/wpt/fake/file/path.html [ Failure ]\n' +
'[ linux ] external/wpt/fake/new.html?HelloWorld [ Failure ]\n'))
skip_value = host.filesystem.read_text_file(skip_path)
self.assertMultiLineEqual(skip_value, skip_value_origin)
def test_clean_up_affected_tests_arg_raises_exception(self):
host = self.mock_host()
with self.assertRaises(AssertionError) as ctx:
updater = WPTExpectationsUpdater(
host, ['--clean-up-affected-tests-only'])
updater.run()
self.assertIn('Cannot use --clean-up-affected-tests-only',
str(ctx.exception))
def test_clean_up_affected_tests_arg_does_not_raise_exception(self):
host = self.mock_host()
updater = WPTExpectationsUpdater(
host, ['--clean-up-affected-tests-only',
'--clean-up-test-expectations'])
def test_write_to_test_expectations_with_marker_comment(self):
host = self.mock_host()
expectations_path = \
host.port_factory.get().path_to_generic_test_expectations_file()
host.filesystem.write_text_file(
expectations_path,
textwrap.dedent(f"""\
# tags: [ Trusty ]
# results: [ Timeout ]
{WPTExpectationsUpdater.MARKER_COMMENT}
"""))
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Trusty', 222, 'Build-3'),
WebTestResults.from_rdb_responses(
{'external/wpt/x/y.html': [{
'status': 'ABORT',
}] * 3},
step_name='blink_wpt_tests'))
updater.update_expectations()
skip_path = host.port_factory.get().path_to_never_fix_tests_file()
skip_value_origin = host.filesystem.read_text_file(skip_path)
value = host.filesystem.read_text_file(expectations_path)
self.assertEqual(
value,
textwrap.dedent(f"""\
# tags: [ Trusty ]
# results: [ Timeout ]
{WPTExpectationsUpdater.MARKER_COMMENT}
[ Trusty ] external/wpt/x/y.html [ Timeout ]
"""))
skip_value = host.filesystem.read_text_file(skip_path)
self.assertMultiLineEqual(skip_value, skip_value_origin)
def test_write_to_test_expectations_with_no_marker_comment(self):
host = self.mock_host()
expectations_path = \
host.port_factory.get().path_to_generic_test_expectations_file()
host.filesystem.write_text_file(
expectations_path,
textwrap.dedent("""\
# tags: [ Trusty ]
# results: [ Pass Failure Timeout ]
crbug.com/111 [ Trusty ] foo/bar.html [ Failure ]
"""))
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Trusty', 222, 'Build-3'),
WebTestResults.from_rdb_responses(
{'external/wpt/x/y.html': [{
'status': 'ABORT',
}] * 3},
step_name='blink_wpt_tests'))
updater.update_expectations()
skip_path = host.port_factory.get().path_to_never_fix_tests_file()
skip_value_origin = host.filesystem.read_text_file(skip_path)
value = host.filesystem.read_text_file(expectations_path)
self.assertMultiLineEqual(
value,
textwrap.dedent("""\
# tags: [ Trusty ]
# results: [ Pass Failure Timeout ]
crbug.com/111 [ Trusty ] foo/bar.html [ Failure ]
# ====== New tests from wpt-importer added here ======
[ Trusty ] external/wpt/x/y.html [ Timeout ]
"""))
skip_value = host.filesystem.read_text_file(skip_path)
self.assertMultiLineEqual(skip_value, skip_value_origin)
def test_write_to_test_expectations_with_marker_and_no_lines(self):
host = self.mock_host()
expectations_path = \
host.port_factory.get().path_to_generic_test_expectations_file()
raw_exps = '# tags: [ Trusty ]\n# results: [ Pass ]\n'
host.filesystem.write_text_file(
expectations_path,
raw_exps + '\n' + WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
'[ Trusty ] fake/file/path.html [ Pass ]\n')
updater = self.mock_updater(host)
updater.update_expectations()
skip_path = host.port_factory.get().path_to_never_fix_tests_file()
skip_value_origin = host.filesystem.read_text_file(skip_path)
value = host.filesystem.read_text_file(expectations_path)
self.assertMultiLineEqual(
value, raw_exps + '\n' + WPTExpectationsUpdater.MARKER_COMMENT +
'\n' + '[ Trusty ] fake/file/path.html [ Pass ]\n')
skip_value = host.filesystem.read_text_file(skip_path)
self.assertMultiLineEqual(skip_value, skip_value_origin)
def test_is_reference_test_given_testharness_test(self):
updater = WPTExpectationsUpdater(self.mock_host())
self.assertFalse(updater.is_reference_test('test/path.html'))
def test_is_reference_test_given_reference_test(self):
updater = WPTExpectationsUpdater(self.mock_host())
self.assertTrue(updater.is_reference_test('external/wpt/reftest.html'))
def test_is_reference_test_given_non_existent_file(self):
updater = WPTExpectationsUpdater(self.mock_host())
self.assertFalse(updater.is_reference_test('foo/bar.html'))
def test_get_test_to_rebaseline_returns_only_tests_with_failures(self):
host = self.mock_host()
updater = WPTExpectationsUpdater(host)
raw_results = WebTestResults.from_rdb_responses({
'external/wpt/x/y.html': [{
'status': 'PASS',
}] * 3,
'external/wpt/x/z.html': [{
'status': 'FAIL',
}] * 3,
})
tests_to_rebaseline, results = updater.filter_results_for_update(
raw_results)
self.assertEqual(len(results), 0)
self.assertEqual(tests_to_rebaseline, {'external/wpt/x/z.html'})
def test_get_test_to_rebaseline_does_not_return_ref_tests(self):
host = self.mock_host()
updater = WPTExpectationsUpdater(host)
results = WebTestResults.from_rdb_responses(
{'external/wpt/reftest.html': [{
'status': 'FAIL',
}] * 3})
tests_to_rebaseline, _ = updater.filter_results_for_update(results)
self.assertEqual(tests_to_rebaseline, set())
results = WebTestResults.from_rdb_responses(
{'external/wpt/reftest.html': [{
'status': 'ABORT',
}] * 3})
tests_to_rebaseline, _ = updater.filter_results_for_update(results)
self.assertEqual(tests_to_rebaseline, set())
results = WebTestResults.from_rdb_responses(
{'external/wpt/reftest.html': [{
'status': 'PASS',
}] * 3})
tests_to_rebaseline, _ = updater.filter_results_for_update(results)
self.assertEqual(tests_to_rebaseline, set())
def test_get_tests_to_rebaseline_some_rebaselined(self):
host = self.mock_host()
updater = WPTExpectationsUpdater(host)
raw_results = WebTestResults.from_rdb_responses({
'external/wpt/x/y.html': [{
'status': 'FAIL',
}] * 3,
'external/wpt/x/z.html': [{
'status': 'ABORT',
}] * 3,
})
tests_to_rebaseline, (
result, ) = updater.filter_results_for_update(raw_results)
self.assertEqual(tests_to_rebaseline, {'external/wpt/x/y.html'})
# The record for the builder with a timeout is kept, but not with a text mismatch,
# since that should be covered by downloading a new baseline.
self.assertEqual(result.test_name(), 'external/wpt/x/z.html')
# The original container isn't modified.
self.assertEqual(len(raw_results), 2)
def test_run_no_builds(self):
updater = WPTExpectationsUpdater(self.mock_host())
updater.git_cl = MockGitCL(updater.host, {})
with self.assertRaises(ScriptError) as e:
updater.run()
self.assertEqual(e.exception.message,
'No try job information was collected.')
@unittest.skip('The MISSING status is not supported by ResultDB')
def test_new_manual_tests_get_skip_expectation(self):
host = self.mock_host()
updater = self.mock_updater(host)
for build in [
Build('MOCK Try Mac10.10', 333, 'Build-1'),
Build('MOCK Try Mac10.11', 111, 'Build-2'),
Build('MOCK Try Trusty', 222, 'Build-3'),
Build('MOCK Try Precise', 333, 'Build-4'),
Build('MOCK Try Win10', 444, 'Build-5'),
Build('MOCK Try Win7', 555, 'Build-6'),
]:
host.results_fetcher.set_results(
build,
WebTestResults.from_rdb_responses(
{'external/wpt/x-manual.html': [{
'status': 'FAIL',
}] * 3},
step_name='blink_wpt_tests'))
_, line_dict = updater.update_expectations()
self.assertEqual(
line_dict, {
'external/wpt/x-manual.html':
['external/wpt/x-manual.html [ Skip ]']
})
def test_same_platform_one_without_results(self):
# In this example, there are two configs using the same platform
# (Mac10.10), and one of them has no results while the other one does.
# The specifiers are "filled in" and the failure is assumed to apply
# to the platform with missing results.
host = self.mock_host()
updater = self.mock_updater(host)
host.results_fetcher.set_results(
Build('MOCK Try Precise', 333, 'Build-4'),
WebTestResults.from_rdb_responses(
{'external/wpt/x.html': [{
'status': 'ABORT',
}] * 3},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Trusty', 222, 'Build-3'),
WebTestResults.from_rdb_responses(
{'external/wpt/x.html': [{
'status': 'ABORT',
}] * 3},
step_name='blink_wpt_tests'))
host.results_fetcher.set_results(
Build('MOCK Try Mac10.10', 333, 'Build-1'),
WebTestResults.from_rdb_responses(
{'external/wpt/x.html': [{
'status': 'ABORT',
}] * 3},
step_name='blink_wpt_tests'))
_, line_dict = updater.update_expectations()
self.assertEqual(
line_dict, {
'external/wpt/x.html': [
'[ Linux ] external/wpt/x.html [ Timeout ]',
'[ Mac10.10 ] external/wpt/x.html [ Timeout ]',
],
})
def test_cleanup_all_deleted_tests_in_expectations_files(self):
host = self.mock_host()
port = host.port_factory.get()
fs = host.filesystem
expectations_path = fs.join(MOCK_WEB_TESTS, 'TestExpectations')
fs.write_text_file(
expectations_path,
('# results: [ Failure ]\n'
'external/wpt/some/test/a.html?hello%20world [ Failure ]\n'
'some/test/b.html [ Failure ]\n'
'# This line should be deleted\n'
'some/test/c.html [ Failure ]\n'
'# line below should exist in new file\n'
'some/test/d.html [ Failure ]\n'))
fs.write_text_file(fs.join(MOCK_WEB_TESTS, 'VirtualTestSuites'), '[]')
fs.write_text_file(fs.join(MOCK_WEB_TESTS, 'new', 'a.html'), '')
fs.write_text_file(fs.join(MOCK_WEB_TESTS, 'new', 'b.html'), '')
fs.write_text_file(
fs.join(port.web_tests_dir(), 'some', 'test', 'd.html'), '')
updater = WPTExpectationsUpdater(host)
def _git_command_return_val(cmd):
if '--diff-filter=D' in cmd:
return 'some/test/b.html'
return ''
updater.git.run = _git_command_return_val
updater._relative_to_web_test_dir = lambda test_path: test_path
updater.cleanup_test_expectations_files()
self.assertMultiLineEqual(fs.read_text_file(expectations_path),
('# results: [ Failure ]\n'
'# line below should exist in new file\n'
'some/test/d.html [ Failure ]\n'))
def test_skip_slow_timeout_tests(self):
host = self.mock_host()
fs = host.filesystem
expectations_path = fs.join(MOCK_WEB_TESTS, 'TestExpectations')
data = ('# results: [ Pass Failure Crash Timeout Skip ]\n'
'foo/failure.html [ Failure ]\n'
'foo/slow_timeout.html [ Timeout ]\n'
'bar/text.html [ Pass ]\n')
fs.write_text_file(fs.join(MOCK_WEB_TESTS, 'SlowTests'),
('# results: [ Slow ]\n'
'foo/slow_timeout.html [ Slow ]\n'
'bar/slow.html [ Slow ]\n'))
fs.write_text_file(expectations_path, data)
newdata = data.replace('foo/slow_timeout.html [ Timeout ]',
'foo/slow_timeout.html [ Skip Timeout ]')
updater = WPTExpectationsUpdater(host)
rv = updater.skip_slow_timeout_tests(host.port_factory.get())
self.assertTrue(rv)
self.assertEqual(newdata, fs.read_text_file(expectations_path))
def test_cleanup_all_test_expectations_files(self):
host = self.mock_host()
fs = host.filesystem
test_expect_path = fs.join(MOCK_WEB_TESTS, 'TestExpectations')
fs.write_text_file(
test_expect_path,
(
'# results: [ Failure ]\n'
'some/test/a.html [ Failure ]\n'
'some/test/b.html [ Failure ]\n'
'ignore/globs/* [ Failure ]\n'
'some/test/c\*.html [ Failure ]\n'
# default test case, line below should exist in new file
'some/test/d.html [ Failure ]\n'))
fs.write_text_file(fs.join(MOCK_WEB_TESTS, 'VirtualTestSuites'), '[]')
fs.write_text_file(fs.join(MOCK_WEB_TESTS, 'new', 'a.html'), '')
fs.write_text_file(fs.join(MOCK_WEB_TESTS, 'new', 'b.html'), '')
updater = WPTExpectationsUpdater(
host, ['--clean-up-test-expectations-only',
'--clean-up-affected-tests-only'])
deleted_files = [
'some/test/b.html',
]
renamed_file_pairs = {
'some/test/a.html': 'new/a.html',
'some/test/c*.html': 'new/c*.html',
}
updater._list_deleted_files = lambda: deleted_files
updater._list_renamed_files = lambda: renamed_file_pairs
updater.cleanup_test_expectations_files()
self.assertMultiLineEqual(fs.read_text_file(test_expect_path),
('# results: [ Failure ]\n'
'new/a.html [ Failure ]\n'
'ignore/globs/* [ Failure ]\n'
'new/c\*.html [ Failure ]\n'
'some/test/d.html [ Failure ]\n'))
def test_merging_platforms_if_possible(self):
host = self.mock_host()
updater = self.mock_updater(host)
for build in [
Build('MOCK Try Mac10.10', 333, 'Build-1'),
Build('MOCK Try Mac10.11', 111, 'Build-2'),
Build('MOCK Try Trusty', 222, 'Build-3'),
Build('MOCK Try Precise', 333, 'Build-4'),
Build('MOCK Try Win7', 555, 'Build-6'),
]:
host.results_fetcher.set_results(
build,
WebTestResults.from_rdb_responses(
{'external/wpt/x.html': [{
'status': 'ABORT',
}] * 3},
step_name='blink_wpt_tests'))
_, line_dict = updater.update_expectations()
self.assertEqual(
line_dict, {
'external/wpt/x.html': [
'[ Linux ] external/wpt/x.html [ Timeout ]',
'[ Mac ] external/wpt/x.html [ Timeout ]',
'[ Win7 ] external/wpt/x.html [ Timeout ]',
],
})
def test_inheriting_results(self):
# We make sure that platforms that have no results are able to inherit
# results from other builds.
host = self.mock_host()
# Reset the fake list of try builders to use 3 Macs, 2 Wins and 1 Linux.
host.builders = BuilderList({
'MOCK Try Mac10.10': {
'port_name': 'test-mac-mac10.10',
'specifiers': ['Mac10.10', 'Release'],
'is_try_builder': True,
},
'MOCK Try Mac10.11': {
'port_name': 'test-mac-mac10.11',
'specifiers': ['Mac10.11', 'Release'],
'is_try_builder': True,
},
'MOCK Try Mac11-arm64': {
'port_name': 'test-mac-mac11-arm64',
'specifiers': ['Mac11-arm64', 'Release'],
'is_try_builder': True,
},
'MOCK Try Trusty': {
'port_name': 'test-linux-trusty',
'specifiers': ['Trusty', 'Release'],
'main': 'tryserver.blink',
'is_try_builder': True,
},
'MOCK Try Win10': {
'port_name': 'test-win-win10',
'specifiers': ['Win10', 'Release'],
'is_try_builder': True,
},
'MOCK Try Win7': {
'port_name': 'test-win-win7',
'specifiers': ['Win7', 'Release'],
'is_try_builder': True,
},
})
updater = WPTExpectationsUpdater(host)
test_name = 'external/wpt/x.html'
completed_results = [
WebTestResults.from_rdb_responses(
{
test_name: [{
'status': 'ABORT'
}],
'external/wpt/skipped-on-mac.html': [{
'status': 'PASS'
}],
},
build=Build('MOCK Try Win7')),
WebTestResults.from_rdb_responses(
{test_name: [{
'status': 'CRASH'
}]},
build=Build('MOCK Try Mac10.10')),
WebTestResults.from_rdb_responses(
{test_name: [{
'status': 'FAIL'
}]},
build=Build('MOCK Try Mac10.11')),
]
# Win10 will inherit the result from win7
filled_results = updater.fill_missing_results(
WebTestResults([], build=Build('MOCK Try Win10')),
completed_results)
self.assertEqual(
{'TIMEOUT'},
set(filled_results.result_for_test(test_name).actual_results()))
# Mac11-arm64 will inherit the union of results from Mac10.10 and
# Mac10.11
filled_results = updater.fill_missing_results(
WebTestResults([], build=Build('MOCK Try Mac11-arm64')),
completed_results)
self.assertEqual(
{'CRASH', 'FAIL'},
set(filled_results.result_for_test(test_name).actual_results()))
# Linux will inherit all results from Mac and Win since there is no
# other Linux result to take.
filled_results = updater.fill_missing_results(
WebTestResults([], build=Build('MOCK Try Trusty')),
completed_results)
self.assertEqual(
{'CRASH', 'FAIL', 'TIMEOUT'},
set(filled_results.result_for_test(test_name).actual_results()))
def test_inheriting_results_dedupe(self):
# In this test we make sure that we dedupe the inherited results.
host = self.mock_host()
# Set up a fake list of try builders.
# This uses 2 Macs, 2 Wins and 1 Linux.
host.builders = BuilderList({
'MOCK Try Mac10.10': {
'port_name': 'test-mac-mac10.10',
'specifiers': ['Mac10.10', 'Release'],
'is_try_builder': True,
},
'MOCK Try Mac10.11': {
'port_name': 'test-mac-mac10.11',
'specifiers': ['Mac10.11', 'Release'],
'is_try_builder': True,
},
'MOCK Try Trusty': {
'port_name': 'test-linux-trusty',
'specifiers': ['Trusty', 'Release'],
'main': 'tryserver.blink',
'is_try_builder': True,
},
'MOCK Try Win10': {
'port_name': 'test-win-win10',
'specifiers': ['Win10', 'Release'],
'is_try_builder': True,
},
'MOCK Try Win7': {
'port_name': 'test-win-win7',
'specifiers': ['Win7', 'Release'],
'is_try_builder': True,
},
})
updater = WPTExpectationsUpdater(host)
test_name = 'external/wpt/x.html'
completed_results = [
WebTestResults.from_rdb_responses(
{test_name: [{
'status': 'ABORT'
}]},
build=Build('MOCK Try Win7')),
WebTestResults.from_rdb_responses(
{test_name: [{
'status': 'ABORT'
}]},
build=Build('MOCK Try Mac10.10')),
WebTestResults.from_rdb_responses(
{test_name: [{
'status': 'FAIL'
}]},
build=Build('MOCK Try Mac10.11')),
]
# Linux will inherit all results from Mac and Win since there is no
# other Linux result to take. The results are deduped so we should not
# get two TIMEOUT statuses in the result.
filled_results = updater.fill_missing_results(
WebTestResults([], build=Build('MOCK Try Trusty')),
completed_results)
self.assertEqual(
{'FAIL', 'TIMEOUT'},
set(filled_results.result_for_test(test_name).actual_results()))
def test_no_fill_skipped(self):
host = self.mock_host()
host.builders = BuilderList({
'MOCK Try Mac10.10': {
'port_name': 'test-mac-mac10.10',
'specifiers': ['Mac10.10', 'Release'],
'is_try_builder': True,
},
'MOCK Try Mac10.11': {
'port_name': 'test-mac-mac10.11',
'specifiers': ['Mac10.11', 'Release'],
'is_try_builder': True,
},
})
port = host.port_factory.get('test-mac-mac10.11')
host.filesystem.write_text_file(
port.path_to_never_fix_tests_file(),
textwrap.dedent("""\
# tags: [ Mac10.10 Mac10.11 ]
# results: [ Skip ]
# Simulate an old platform that runs fewer tests.
[ Mac10.10 ] external/wpt/x.html [ Skip ]
"""))
updater = WPTExpectationsUpdater(host)
completed_results = [
WebTestResults.from_rdb_responses(
{'external/wpt/x.html': [{
'status': 'FAIL'
}]},
build=Build('MOCK Try Mac10.11')),
]
filled_results = updater.fill_missing_results(
WebTestResults([], build=Build('MOCK Try Mac10.10')),
completed_results)
self.assertIsNone(
filled_results.result_for_test('external/wpt/x.html'))