# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import contextlib
import json
import textwrap
import unittest
from unittest import mock
from blinkpy.common import path_finder
from blinkpy.common.host_mock import MockHost
from blinkpy.wpt_tests.test_loader import (
allow_any_subtests_on_timeout,
TestLoader,
wpt_url_to_blink_test,
)
path_finder.bootstrap_wpt_imports()
from tools.manifest.manifest import load_and_update
from wptrunner import wptlogging, wpttest
from wptrunner.testloader import Subsuite
class TestLoaderTestCase(unittest.TestCase):
def setUp(self):
self.host = MockHost()
self.fs = self.host.filesystem
self.finder = path_finder.PathFinder(self.fs)
self.fs.write_text_file(
self.finder.path_from_wpt_tests('MANIFEST.json'),
json.dumps({
'version': 8,
'items': {
'testharness': {
'variant.html': [
'abcdef',
['variant.html?foo=bar/abc', {}],
['variant.html?foo=baz', {}],
],
'dir': {
'multiglob.https.any.js': [
'123456',
['dir/multiglob.https.any.html', {}],
['dir/multiglob.https.any.worker.html', {}],
],
},
},
'reftest': {
'reftest.html': [
'7890ab',
[None, [['reftest-ref.html', '==']], {}],
],
},
},
}))
wptlogging.setup({}, {})
@contextlib.contextmanager
def _make_loader(self, **kwargs):
port = self.host.port_factory.get('test-linux-trusty')
with self.fs.patch_builtins():
manifest = load_and_update(
self.finder.path_from_wpt_tests(),
self.finder.path_from_wpt_tests('MANIFEST.json'),
'/',
update=False,
parallel=False)
test_root = {
'url_base': manifest.url_base,
'tests_path': manifest.tests_root,
'metadata_path': manifest.tests_root,
}
yield TestLoader(port, {manifest: test_root},
['testharness', 'reftest'],
base_run_info={},
**kwargs)
def _load_metadata(self, test_path: str, virtual_suite: str = ''):
with self._make_loader() as loader:
run_info = {**loader.base_run_info, 'virtual_suite': virtual_suite}
manifest, *_ = loader.manifests
inherit_metadata, test_metadata = loader.load_metadata(
run_info, manifest, manifest.tests_root, test_path)
self.assertEqual(inherit_metadata, [])
return test_metadata
def test_load_all_pass(self):
test_file = self._load_metadata('variant.html')
self.assertIsNone(test_file)
def test_load_exp_line_fail_testharness(self):
self.fs.write_text_file(
self.finder.path_from_web_tests('TestExpectations'),
textwrap.dedent("""\
# tags: [ Linux Mac Win ]
# results: [ Failure ]
[ Linux ] external/wpt/variant.html?foo=baz [ Failure ]
"""))
test_file = self._load_metadata('variant.html')
test = test_file.get_test('variant.html?foo=baz')
self.assertEqual(test.expected, 'OK')
self.assertEqual(test.known_intermittent,
['ERROR', 'PRECONDITION_FAILED'])
self.assertFalse(test.disabled)
# Any status is allowed, even without an explicit baseline.
subtest = test.get_subtest('implicit subtest')
self.assertEqual(subtest.expected, 'FAIL')
self.assertEqual(subtest.known_intermittent,
['PASS', 'TIMEOUT', 'PRECONDITION_FAILED', 'NOTRUN'])
self.assertFalse(subtest.disabled)
self.assertFalse(subtest.has_key('expected-fail-message'))
def test_load_exp_line_fail_reftest(self):
self.fs.write_text_file(
self.finder.path_from_web_tests('TestExpectations'),
textwrap.dedent("""\
# tags: [ Linux Mac Win ]
# results: [ Failure ]
[ Linux ] external/wpt/reftest* [ Failure ]
"""))
test_file = self._load_metadata('reftest.html')
test = test_file.get_test('reftest.html')
self.assertEqual(test.expected, 'FAIL')
self.assertEqual(test.known_intermittent, ['PASS', 'ERROR'])
self.assertFalse(test.disabled)
self.assertIsNone(test.get_subtest('should not exist'))
def test_load_baseline_fail(self):
self.fs.write_text_file(
self.finder.path_from_web_tests(
'external', 'wpt', 'dir', 'multiglob.https.any-expected.txt'),
textwrap.dedent("""\
This is a testharness.js-based test.
CONSOLE WARNING: warning
Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: AriaUtils is not defined
[FAIL] subtest2
assert_unreached:\\n message 2
[NOTRUN] sub\\n test3
promise_rejects_dom: message\\n 3
Harness: the test ran to completion.
"""))
test_file = self._load_metadata('dir/multiglob.https.any.js')
test = test_file.get_test('multiglob.https.any.html')
self.assertEqual(test.expected, 'ERROR')
self.assertEqual(test.known_intermittent, [])
self.assertFalse(test.disabled)
subtest = test.get_subtest('subtest1')
self.assertEqual(subtest.expected, 'PASS')
self.assertEqual(subtest.known_intermittent, [])
self.assertFalse(subtest.disabled)
self.assertFalse(subtest.has_key('expected-fail-message'))
subtest = test.get_subtest('subtest2')
self.assertEqual(subtest.expected, 'FAIL')
self.assertEqual(subtest.known_intermittent, [])
self.assertFalse(subtest.disabled)
self.assertEqual(subtest.get('expected-fail-message'),
'assert_unreached:\n message 2')
subtest = test.get_subtest('sub\n test3')
self.assertEqual(subtest.expected, 'NOTRUN')
self.assertEqual(subtest.known_intermittent, [])
self.assertFalse(subtest.disabled)
self.assertEqual(subtest.get('expected-fail-message'),
'promise_rejects_dom: message\n 3')
def test_load_variant_one_skipped(self):
self.fs.write_text_file(
self.finder.path_from_web_tests('TestExpectations'),
textwrap.dedent("""\
# results: [ Failure Skip ]
external/wpt/variant.html?foo=bar/abc [ Failure ]
external/wpt/variant.html?foo=baz [ Skip ]
"""))
self.fs.write_text_file(
self.finder.path_from_wpt_tests('variant_foo=baz-expected.txt'),
textwrap.dedent("""\
This is a testharness.js-based test.
[FAIL] subtest
Harness: the test ran to completion.
"""))
test_file = self._load_metadata('variant.html')
test = test_file.get_test('variant.html?foo=bar/abc')
self.assertEqual(test.expected, 'OK')
self.assertEqual(test.known_intermittent,
['ERROR', 'PRECONDITION_FAILED'])
# Even though this test is annotated with `[ Skip ]`, the test loader
# should still translate its expectations in case it was explicitly
# specified on the command line, which overrides `[ Skip ]`. See
# https://crbug.com/329898284.
test = test_file.get_test('variant.html?foo=baz')
self.assertEqual(test.expected, 'OK')
self.assertEqual(test.known_intermittent, [])
subtest = test.get_subtest('subtest')
self.assertEqual(subtest.expected, 'FAIL')
self.assertEqual(subtest.known_intermittent, [])
def test_load_failure_with_baseline(self):
"""A `[ Failure ]` line allows harness OK, even with a baseline."""
self.fs.write_text_file(
self.finder.path_from_web_tests('TestExpectations'),
textwrap.dedent("""\
# results: [ Failure ]
external/wpt/variant.html?foo=bar/abc [ Failure ]
"""))
self.fs.write_text_file(
self.finder.path_from_wpt_tests(
'variant_foo=bar_abc-expected.txt'),
textwrap.dedent("""\
This is a testharness.js-based test.
Harness Error. harness_status.status = 3 , harness_status.message =
Harness: the test ran to completion.
"""))
test_file = self._load_metadata('variant.html')
test = test_file.get_test('variant.html?foo=bar/abc')
self.assertEqual(test.expected, 'OK')
self.assertEqual(test.known_intermittent,
['ERROR', 'PRECONDITION_FAILED'])
def test_load_baseline_precondition_failed(self):
self.fs.write_text_file(
self.finder.path_from_web_tests(
'external', 'wpt', 'dir', 'multiglob.https.any-expected.txt'),
textwrap.dedent("""\
This is a testharness.js-based test.
Harness Error. harness_status.status = 3 , harness_status.message = Uncaught ReferenceError: AriaUtils is not defined
Harness: the test ran to completion.
"""))
test_file = self._load_metadata('dir/multiglob.https.any.js')
test = test_file.get_test('multiglob.https.any.html')
self.assertEqual(test.expected, 'PRECONDITION_FAILED')
self.assertEqual(test.known_intermittent, [])
self.assertFalse(test.disabled)
def test_load_baseline_harness_ok(self):
self.fs.write_text_file(
self.finder.path_from_web_tests(
'external', 'wpt', 'dir', 'multiglob.https.any-expected.txt'),
textwrap.dedent("""\
This is a testharness.js-based test.
[FAIL] subtest
Harness: the test ran to completion.
"""))
test_file = self._load_metadata('dir/multiglob.https.any.js')
test = test_file.get_test('multiglob.https.any.html')
self.assertEqual(test.expected, 'OK')
self.assertEqual(test.known_intermittent, [])
self.assertFalse(test.disabled)
def test_ignore_irrelevant_expectations(self):
self.fs.write_text_file(
self.finder.path_from_web_tests(
'platform', 'test-mac-mac10.11', 'external', 'wpt', 'dir',
'multiglob.https.any-expected.txt'),
textwrap.dedent("""\
This is a testharness.js-based test.
FAIL subtest message
Harness: the test ran to completion.
"""))
self.fs.write_text_file(
self.finder.path_from_web_tests('TestExpectations'),
textwrap.dedent("""\
# tags: [ Linux Mac Win ]
# results: [ Pass Failure Timeout Crash Skip ]
[ Mac ] external/wpt/dir/multiglob.https.any.worker.html [ Failure ]
"""))
test_file = self._load_metadata('dir/multiglob.https.any.js')
self.assertIsNone(test_file)
def test_load_exp_line_timeout(self):
self.fs.write_text_file(
self.finder.path_from_web_tests('TestExpectations'),
textwrap.dedent("""\
# results: [ Timeout ]
external/wpt/variant.html?foo=baz [ Timeout ]
"""))
test_file = self._load_metadata('variant.html')
test = test_file.get_test('variant.html?foo=baz')
self.assertEqual(test.expected, 'OK')
self.assertEqual(test.known_intermittent, ['TIMEOUT'])
self.assertFalse(test.disabled)
def test_load_virtual_expectations(self):
self.fs.write_text_file(
self.finder.path_from_web_tests('TestExpectations'),
textwrap.dedent("""\
# results: [ Pass Failure Crash Timeout Skip ]
virtual/fake-vts/external/wpt/variant.html?foo=baz [ Pass Crash Timeout ]
"""))
self.fs.write_text_file(
self.finder.path_from_web_tests('virtual', 'fake-vts', 'external',
'wpt',
'variant_foo=baz-expected.txt'),
textwrap.dedent("""\
This is a testharness.js-based test.
[FAIL] subtest1
assert_equals: message
Harness: the test ran to completion.
"""))
test_file = self._load_metadata('variant.html',
virtual_suite='fake-vts')
test = test_file.get_test('variant.html?foo=baz')
self.assertEqual(test.expected, 'OK')
self.assertEqual(test.known_intermittent, ['TIMEOUT', 'CRASH'])
self.assertFalse(test.disabled)
subtest = test.get_subtest('subtest1')
self.assertEqual(subtest.expected, 'FAIL')
self.assertEqual(subtest.known_intermittent, [])
subtest = test.get_subtest('subtest2')
self.assertEqual(subtest.expected, 'PASS')
self.assertEqual(subtest.known_intermittent, [])
def test_wpt_url_to_exp_test(self):
self.assertEqual(wpt_url_to_blink_test('/css/test.html?a'),
'external/wpt/css/test.html?a')
self.assertEqual(wpt_url_to_blink_test('/wpt_internal/test.html'),
'wpt_internal/test.html')
def test_allow_any_subtests_on_timeout(self):
test = mock.Mock()
test.expected_fail_message.return_value = 'expect this message'
test_result = wpttest.TestharnessResult('TIMEOUT',
message=None,
expected='TIMEOUT')
subtest_result = wpttest.TestharnessSubtestResult('subtest',
'TIMEOUT',
message=None,
expected='FAIL')
test_result, (subtest_result, ) = allow_any_subtests_on_timeout(
test, (test_result, [subtest_result]))
self.assertEqual(subtest_result.expected, 'TIMEOUT')
self.assertEqual(subtest_result.known_intermittent, [])
self.assertEqual(subtest_result.message, 'expect this message')
test.expected_fail_message.assert_called_once_with('subtest')
def test_do_not_allow_any_subtests_on_completion(self):
test = mock.Mock()
test.expected_fail_message.return_value = (
'should not expect this message')
test_result = wpttest.TestharnessResult('OK',
message=None,
expected='TIMEOUT')
subtest_result = wpttest.TestharnessSubtestResult('subtest',
'FAIL',
message=None,
expected='TIMEOUT')
test_result, (subtest_result, ) = allow_any_subtests_on_timeout(
test, (test_result, [subtest_result]))
self.assertEqual(subtest_result.expected, 'TIMEOUT')
self.assertEqual(subtest_result.known_intermittent, [])
self.assertIsNone(subtest_result.message)
test.expected_fail_message.assert_not_called()
def test_load_tests(self):
subsuites = {
'':
Subsuite('', config={}),
'fake-vts':
Subsuite('fake-vts',
config={},
include=['/variant.html?foo=baz',
'/does-not-exist.html']),
}
with self._make_loader(subsuites=subsuites,
include=['reftest.html']) as loader:
self.assertEqual(set(loader.tests), {'', 'fake-vts'})
self.assertEqual(set(loader.tests['']), {'reftest'})
self.assertEqual(set(loader.tests['fake-vts']), {'testharness'})
(base_test, ) = loader.tests['']['reftest']
(virtual_test, ) = loader.tests['fake-vts']['testharness']
self.assertEqual(base_test.id, '/reftest.html')
self.assertEqual(virtual_test.id, '/variant.html?foo=baz')
self.assertEqual(loader.disabled_tests, {'': {}, 'fake-vts': {}})
def test_load_no_tests(self):
subsuites = {'': Subsuite('', config={})}
with self._make_loader(subsuites=subsuites, include=[]) as loader:
self.assertEqual(set(loader.tests), {''})
self.assertEqual(loader.tests[''], {})