blob: 95a3c343c17b8cd8b550cb0fa3e61724397290d5 [file] [log] [blame]
# Copyright (C) 2018 Igalia S.L.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import unittest
from webkitpy.common.config.ports_mock import MockPort
from webkitpy.common.host_mock import MockHost
from webkitpy.w3c.wpt_runner import WPTRunner, parse_args
TEST_EXPECTATIONS_JSON_CONTENT = """{
"passing_test.html": { "expected": "PASS" },
"failing_test.html": { "expected": "FAIL" },
"disabled_test.html": { "disabled": "Test Name #1" },
"custom_test_name.html": {
"test_name": "Custom Test Name",
"expected": "FAIL"
},
"test_with_subtests.html": {
"subtests": {
"Subtest #1": { "expected": "PASS" },
"Subtest #2": { "expected": "TIMEOUT" }
}
},
"nested/test_file.html": { "expected": "PASS" },
"nested/nested/test_file.html": {
"test_name": "Deeper-nested test case",
"subtests": {
"Only Subtest": { "expected": "PASS" }
}
}
}"""
EXPECTED_TEST_MANIFESTS = {
"passing_test.html.ini":
"""[passing_test.html]
expected: PASS
""",
"failing_test.html.ini":
"""[failing_test.html]
expected: FAIL
""",
"disabled_test.html.ini":
"""[disabled_test.html]
disabled: Test Name #1
""",
"custom_test_name.html.ini":
"""[Custom Test Name]
expected: FAIL
""",
"test_with_subtests.html.ini":
"""[test_with_subtests.html]
[Subtest #1]
expected: PASS
[Subtest #2]
expected: TIMEOUT
""",
"nested/test_file.html.ini":
"""[test_file.html]
expected: PASS
""",
"nested/nested/test_file.html.ini":
"""[Deeper-nested test case]
[Only Subtest]
expected: PASS
"""
}
class WPTRunnerTest(unittest.TestCase):
class MockTestDownloader(object):
@staticmethod
def default_options():
return {}
def __init__(self, repository_directory, host, options):
self._repository_directory = repository_directory
self._host = host
def clone_tests(self):
self._host.filesystem.maybe_make_directory(self._repository_directory, "web-platform-tests")
class MockWebDriver(object):
@staticmethod
def create(port):
return WPTRunnerTest.MockWebDriver()
def binary_path(self):
return "/mock-webdriver/bin/webdriver"
def browser_path(self):
return "/mock-webdriver/bin/browser"
def browser_args(self):
return ["webdriver_arg1", "webdriver_arg2"]
class MockSpawnWPT(object):
def __init__(self, test_case, expected_wpt_checkout=None, expected_wpt_args=None):
self._test_case = test_case
self._expected_wpt_checkout = expected_wpt_checkout
self._expected_wpt_args = expected_wpt_args
def __call__(self, script_name, wpt_checkout, wpt_args):
self._test_case.assertEquals(script_name, "wptrunner_unittest")
self._test_case.assertEquals(wpt_checkout, self._expected_wpt_checkout)
self._test_case.assertEquals(wpt_args, self._expected_wpt_args)
class TestInstance(object):
def __init__(self, options, spawn_wpt_func=None):
self.port = MockPort()
self.host = MockHost()
# In non-test environments, this value is by default set to the WEBKIT_TEST_CHILD_PROCESSES
# env value or, if that's not present, to the default number of child processes. Here we
# manually set it to 4 for consistency, unless the test case specifies it.
if not options.child_processes:
options.child_processes = 4
self.runner = WPTRunner(self.port, self.host, "wptrunner_unittest", options,
WPTRunnerTest.MockTestDownloader, WPTRunnerTest.MockWebDriver.create, spawn_wpt_func)
def prepare_mock_files_for_run(self):
self.host.filesystem.maybe_make_directory(self.port.wpt_metadata_directory())
self.host.filesystem.write_text_file(
"/mock-checkout/WebPlatformTests/MockPort/TestExpectations.json", "{}")
self.host.filesystem.write_text_file(
"/mock-checkout/WebPlatformTests/MockPort/TestManifest.ini", "{}")
def test_prepare_wpt_checkout(self):
# Tests the prepare_wpt_checkout() method with no WPT checkout specified in options.
options, _ = parse_args([])
instance = WPTRunnerTest.TestInstance(options)
self.assertTrue(instance.runner.prepare_wpt_checkout())
expected_wpt_checkout = "/mock-checkout/WebKitBuild/w3c-tests/web-platform-tests"
self.assertEquals(instance.runner._options.wpt_checkout, expected_wpt_checkout)
self.assertTrue(instance.host.filesystem.isdir(expected_wpt_checkout))
def test_prepare_wpt_checkout_specified_path(self):
# Tests the prepare_wpt_checkout() method with WPT checkout specified in options.
specified_wpt_checkout = "/mock-path/web-platform-tests"
options, _ = parse_args(["--wpt-checkout", specified_wpt_checkout])
instance = WPTRunnerTest.TestInstance(options)
instance.host.filesystem.maybe_make_directory(specified_wpt_checkout)
self.assertTrue(instance.runner.prepare_wpt_checkout())
self.assertEquals(instance.runner._options.wpt_checkout, specified_wpt_checkout)
def test_generate_metadata_directory(self):
# Tests the _generate_metadata_directory() method. TestExpectations.json file is mocked with
# TEST_EXPECTATIONS_JSON_CONTENT value as contents. Expected metadata is generated under
# /mock-metadata and should correspond to files and files' content in the
# EXPECTED_TEST_MANIFESTS dictionary.
expectations_json_path = "/mock-checkout/WebPlatformTests/MockPort/TestExpectations.json"
metadata_path = "/mock-metadata"
options, _ = parse_args([])
instance = WPTRunnerTest.TestInstance(options)
instance.host.filesystem.write_text_file(
"/mock-checkout/WebPlatformTests/MockPort/TestExpectations.json",
TEST_EXPECTATIONS_JSON_CONTENT)
# Specify a stale metadata file that should be removed before generation.
stale_metadata_file = "/mock-metadata/test/stale_metadata_file.html.ini"
instance.host.filesystem.write_text_file(
stale_metadata_file, "[This file should be removed during generation]")
self.assertTrue(instance.runner._generate_metadata_directory(metadata_path))
# Check that the stale metadata file was indeed removed.
self.assertFalse(instance.host.filesystem.exists(stale_metadata_file))
for path, content in EXPECTED_TEST_MANIFESTS.items():
manifest_path = instance.host.filesystem.join(metadata_path, path)
self.assertTrue(instance.host.filesystem.isfile(manifest_path))
self.assertEquals(instance.host.filesystem.read_text_file(manifest_path), content)
def test_run(self):
# Tests the run() method. Files are mocked to the point that helper methods don't fail.
# Goal of this test is for the WPT spawn command to match the desired WPT directory and
# arguments. No options or arguments are used.
spawn_wpt_func = WPTRunnerTest.MockSpawnWPT(self,
"/mock-checkout/WebKitBuild/w3c-tests/web-platform-tests",
["run", "--webkit-port=MockPort", "--processes=4",
"--metadata=/mock-path/mock-wpt-tests-metadata",
"--manifest=/mock-path/mock-wpt-manifest.json",
"--include-manifest=/mock-checkout/WebPlatformTests/MockPort/TestManifest.ini",
"--webdriver-binary=/mock-webdriver/bin/webdriver",
"--binary=/mock-webdriver/bin/browser",
"--binary-arg=webdriver_arg1", "--binary-arg=webdriver_arg2", "webkit"])
options, _ = parse_args([])
instance = WPTRunnerTest.TestInstance(options, spawn_wpt_func)
instance.prepare_mock_files_for_run()
self.assertTrue(instance.runner.run([]))
def test_run_with_specified_options(self):
# Tests the run() method. Files are mocked to the point that helper methods don't fail.
# Goal of this test is for the WPT spawn command to match the desired WPT directory and
# arguments. Custom WPT checkout and child process count are specified. Note that the
# WPT checkout doesn't have an impact on the resulting WPT argument list, as intended.
specified_wpt_checkout = "/mock-path/web-platform-tests"
specified_wpt_metadata = "/mock-path/wpt-metadata"
specified_child_processes = 16
spawn_wpt_func = WPTRunnerTest.MockSpawnWPT(self, specified_wpt_checkout,
["run", "--webkit-port=MockPort", "--processes=16",
"--metadata=/mock-path/wpt-metadata",
"--manifest=/mock-path/wpt-metadata/MANIFEST.json",
"--include-manifest=/mock-path/wpt-metadata/MockPort/TestManifest.ini",
"--webdriver-binary=/mock-webdriver/bin/webdriver",
"--binary=/mock-webdriver/bin/browser",
"--binary-arg=webdriver_arg1", "--binary-arg=webdriver_arg2", "webkit"])
options, _ = parse_args(["--wpt-checkout", specified_wpt_checkout,
"--wpt-metadata", specified_wpt_metadata,
"--child-processes", specified_child_processes])
instance = WPTRunnerTest.TestInstance(options, spawn_wpt_func)
instance.prepare_mock_files_for_run()
# Also create the mock WPT checkout and metadata directories.
instance.host.filesystem.maybe_make_directory(specified_wpt_checkout)
instance.host.filesystem.maybe_make_directory(specified_wpt_metadata)
self.assertTrue(instance.runner.run([]))
def test_run_with_args(self):
# Tests the run() method. Files are mocked to the point that helper methods don't fail.
# Goal of this test is for the WPT spawn command to match the desired WPT directory and
# arguments. A custom two-element argument list is used. It's expected to be appended
# to the resulting WPT argument list.
specified_args = ["test1.html", "test2.html"]
spawn_wpt_func = WPTRunnerTest.MockSpawnWPT(self,
"/mock-checkout/WebKitBuild/w3c-tests/web-platform-tests",
["run", "--webkit-port=MockPort", "--processes=4",
"--metadata=/mock-path/mock-wpt-tests-metadata",
"--manifest=/mock-path/mock-wpt-manifest.json",
"--include-manifest=/mock-checkout/WebPlatformTests/MockPort/TestManifest.ini",
"--webdriver-binary=/mock-webdriver/bin/webdriver",
"--binary=/mock-webdriver/bin/browser",
"--binary-arg=webdriver_arg1", "--binary-arg=webdriver_arg2", "webkit"] + specified_args)
options, _ = parse_args([])
instance = WPTRunnerTest.TestInstance(options, spawn_wpt_func)
instance.prepare_mock_files_for_run()
self.assertTrue(instance.runner.run(specified_args))