| Differences between
and this patch
- a/Tools/ChangeLog +46 lines
Lines 1-3 a/Tools/ChangeLog_sec1
1
2014-09-16  Youenn Fablet  <youenn.fablet@crf.canon.fr>
2
3
        Add support for automated W3C conformance testing
4
        https://bugs.webkit.org/show_bug.cgi?id=134766
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * Scripts/run-w3c-conformance-tests: Added (main script).
9
        * Scripts/webkitpy/port/base.py:
10
        (Port.w3c_conformance_results_directory): Path to the working directory for conformance testing.
11
        * Scripts/webkitpy/w3c/run_w3c_conformance_tests.py: Added (Handle conformance test runnning using rwt).
12
        (W3CConformanceRunner):
13
        (W3CConformanceRunner.__init__):
14
        (W3CConformanceRunner.conformance_results_directory):
15
        (W3CConformanceRunner.layout_tests_result_directory):
16
        (W3CConformanceRunner.test_suites):
17
        (W3CConformanceRunner.run_webkit_tests):
18
        (W3CConformanceRunner.run_test_list):
19
        (W3CConformanceRunner.results_manager):
20
        (W3CConformanceRunner.tests):
21
        (W3CConformanceRunner.conformance_result):
22
        (W3CConformanceRunner.run_tests):
23
        (W3CConformanceRunner.print_results_to_console):
24
        (W3CConformanceRunner.print_potential_test_expectations_update):
25
        (W3CConformanceRunner.write_conformance_results):
26
        (configure_logging):
27
        (configure_logging.LogHandler):
28
        (configure_logging.LogHandler.format):
29
        (main):
30
        * Scripts/webkitpy/w3c/test_results_manager.py: Added (Parse rwt results to compute conformance results).
31
        (TestResultsManager):
32
        (TestResultsManager.__init__):
33
        (TestResultsManager.w3c_test_name):
34
        (TestResultsManager._get_test_results):
35
        (TestResultsManager.process_test_results):
36
        (TestResultsManager._compute_conformance_status):
37
        (TestResultsManager.compute_conformance_results):
38
        (TestResultsManager.summary):
39
        (TestResultsManager.write_conformance_results):
40
        * Scripts/webkitpy/w3c/web_platform_test_setup.py: Added (update wpt files, wpt testharness-report.js and wpt server config file).
41
        (WebPlatformTestSetup):
42
        (WebPlatformTestSetup.__init__):
43
        (WebPlatformTestSetup.restore_w3c_testharnessreport):
44
        (WebPlatformTestSetup.copy_webkit_testharnessreport):
45
        (WebPlatformTestSetup.copy_wpt_json_config):
46
1
2014-09-12  Brian J. Burg  <burg@cs.washington.edu>
47
2014-09-12  Brian J. Burg  <burg@cs.washington.edu>
2
48
3
        Web Inspector: remind about rebaselining generator test results
49
        Web Inspector: remind about rebaselining generator test results
- a/Tools/Scripts/run-w3c-conformance-tests +31 lines
Line 0 a/Tools/Scripts/run-w3c-conformance-tests_sec1
1
#!/usr/bin/env python
2
3
# Copyright (c) 2014, Canon Inc. All rights reserved.
4
#
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions
7
# are met:
8
# 1.  Redistributions of source code must retain the above copyright
9
#     notice, this list of conditions and the following disclaimer.
10
# 2.  Redistributions in binary form must reproduce the above copyright
11
#     notice, this list of conditions and the following disclaimer in the
12
#     documentation and/or other materials provided with the distribution.
13
# 3.  Neither the name of Canon Inc. nor the names of
14
#     its contributors may be used to endorse or promote products derived
15
#     from this software without specific prior written permission.
16
#
17
# THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
18
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
# DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
21
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
"""Wrapper around webkitpy/w3c/run_w3c_conformance_tests.py"""
29
from webkitpy.common import multiprocessing_bootstrap
30
31
multiprocessing_bootstrap.run('webkitpy', 'w3c', 'run_w3c_conformance_tests.py')
- a/Tools/Scripts/webkitpy/port/base.py +4 lines
Lines 790-795 class Port(object): a/Tools/Scripts/webkitpy/port/base.py_sec1
790
    def perf_results_directory(self):
790
    def perf_results_directory(self):
791
        return self._build_path()
791
        return self._build_path()
792
792
793
    def w3c_conformance_results_directory(self):
794
        """Absolute path to the place to store the test results (uses --w3c-conformance-directory)."""
795
        return self._build_path('w3c-conformance-results')
796
793
    def default_results_directory(self):
797
    def default_results_directory(self):
794
        """Absolute path to the default place to store the test results."""
798
        """Absolute path to the default place to store the test results."""
795
        # Results are store relative to the built products to make it easy
799
        # Results are store relative to the built products to make it easy
- a/Tools/Scripts/webkitpy/w3c/run_w3c_conformance_tests.py +196 lines
Line 0 a/Tools/Scripts/webkitpy/w3c/run_w3c_conformance_tests.py_sec1
1
# Copyright (c) 2014, Canon Inc. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or without
4
# modification, are permitted provided that the following conditions
5
# are met:
6
# 1.  Redistributions of source code must retain the above copyright
7
#     notice, this list of conditions and the following disclaimer.
8
# 2.  Redistributions in binary form must reproduce the above copyright
9
#     notice, this list of conditions and the following disclaimer in the
10
#     documentation and/or other materials provided with the distribution.
11
# 3.  Neither the name of Canon Inc. nor the names of
12
#     its contributors may be used to endorse or promote products derived
13
#     from this software without specific prior written permission.
14
#
15
# THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
16
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
# DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
19
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26
"""
27
 This script evaluates W3C tests conformance by:
28
    - importing W3C tests as WebKit tests (using web_platform_test_importer)
29
    - generating expected.txt files (using run-webkit-tests)
30
    - computing whether a test is passing or not by checking PASS/FAIL assertions outputted within the expected.txt files
31
"""
32
33
import argparse
34
import logging
35
import optparse
36
import sys
37
38
from webkitpy.common.host import Host
39
from webkitpy.common.system.executive import Executive
40
from webkitpy.layout_tests.models.test_expectations import TestExpectations
41
from webkitpy.port import platform_options
42
from webkitpy.w3c.factory import w3c_create_argument_parser
43
from webkitpy.w3c.test_results_manager import TestResultsManager
44
from webkitpy.w3c.web_platform_test_setup import WebPlatformTestSetup
45
from webkitpy.w3c.web_platform_test_importer import WebPlatformTestImporter
46
47
_log = logging.getLogger(__name__)
48
49
50
class W3CConformanceRunner(object):
51
52
    def __init__(self, port, options):
53
        self._port = port
54
        self._filesystem = port.host.filesystem
55
        self._options = options
56
        self._results_manager = None
57
        self._tests = None
58
        self._conformance_results = None
59
60
        self.web_platform_test_importer = WebPlatformTestImporter(port, options)
61
        self.imported_tests_directory = self.web_platform_test_importer.imported_tests_directory
62
        self.runned_tests_directory = self._filesystem.join(port.w3c_conformance_results_directory(), "runned-tests")
63
64
    def conformance_results_directory(self):
65
        return self._port.w3c_conformance_results_directory()
66
67
    def layout_tests_result_directory(self):
68
        return self._filesystem.join(self.conformance_results_directory(), "layout-test-results")
69
70
    def test_suites(self):
71
        return self.web_platform_test_importer.test_suites()
72
73
    def run_webkit_tests(self, parameters):
74
        tmp_args = [self._port.path_to_script('run-webkit-tests')] + parameters
75
        if self._options.platform:
76
            tmp_args.append('--' + self._options.platform)
77
        if self._options.webkit_test_runner is True:
78
            tmp_args.append('-2')
79
        Executive().run_command(tmp_args, error_handler=Executive.ignore_error, return_stderr=(self._options.__dict__['w3c_quiet']), decode_output=False)
80
81
    def run_test_list(self, tests):
82
        test_list_filename = self._filesystem.join(self.runned_tests_directory, 'test_list.txt')
83
        with open(test_list_filename, 'w+') as out:
84
            for test in tests:
85
                out.write(test + '\n')
86
            out.close()
87
88
        run_webkit_args = ['-q', '--no-retry-failures', '--no-show-results', '--full-results-html', '--results-directory=' + self.layout_tests_result_directory(), '--wptserver-doc-root=' + self.runned_tests_directory, '--test-list=' + test_list_filename]
89
90
        self.run_webkit_tests(run_webkit_args)
91
        self._results_manager = TestResultsManager(self._port, self.runned_tests_directory, self.layout_tests_result_directory(), self.tests())
92
        return self._results_manager.process_test_results()
93
94
    def results_manager(self):
95
        return self._results_manager
96
97
    def tests(self):
98
        if self._tests is None:
99
            test_suite_paths = [self._filesystem.join(self.runned_tests_directory, test_suite) for test_suite in self.test_suites()]
100
            self._tests = self._port.tests(test_suite_paths)
101
        return self._tests
102
103
    def conformance_result(self, test):
104
        if self._conformance_results is None:
105
            self._conformance_results = self.results_manager().compute_conformance_results()
106
        return self._conformance_results[self.results_manager().w3c_test_name(test)]
107
108
    def run_tests(self):
109
        if self._options.__dict__['w3c_list'] is True:
110
            return False
111
112
        if self._options.__dict__['w3c_refresh'] is True:
113
            _log.info('Importing tests...')
114
            self.web_platform_test_importer.import_tests()
115
        else:
116
            _log.info('Skipping test import...')
117
118
        _log.info('Setting up configuration files...')
119
        wpt_setup = WebPlatformTestSetup(self._port.host, self.imported_tests_directory)
120
        wpt_setup.copy_webkit_testharnessreport()
121
        wpt_setup.copy_wpt_json_config()
122
123
        _log.info('Copying imported_tests_directory as runned_test_directory')
124
        # A different directory, runned_test_directory, is used to run tests so that imported_tests_directory remains clean.
125
        # runned_test_directory is also recreated each time to start in a clean state.
126
        self._filesystem.rmtree(self.runned_tests_directory)
127
        self._filesystem.copytree(self.imported_tests_directory, self.runned_tests_directory)
128
129
        _log.info('Running tests...')
130
        self.run_test_list(self.tests())
131
132
        _log.info('Generating conformance results...')
133
        self._filesystem.maybe_make_directory(self.conformance_results_directory())
134
        self.write_conformance_results()
135
136
        return True
137
138
    def print_results_to_console(self):
139
        summary = self.results_manager().summary()
140
        _log.info('Run ' + str(summary['total']) + ' tests')
141
        _log.info('Pass: ' + str(summary['num_pass']))
142
        _log.info('Partial: ' + str(summary['num_partial']))
143
        _log.info('Fail: ' + str(summary['num_fail']))
144
        _log.info('Error: ' + str(summary['num_error']))
145
146
    def print_potential_test_expectations_update(self):
147
        test_expectations = TestExpectations(self._port).model()
148
        conformance = self.results_manager().compute_conformance_results()
149
        for test in self.tests():
150
            w3c_test_name = self.results_manager().w3c_test_name(test)
151
            wk_test_name = self._filesystem.join('imported', 'w3c', 'wpt', w3c_test_name)
152
            if not test_expectations.has_test(wk_test_name):
153
                if not conformance[w3c_test_name] == 'PASS':
154
                    _log.info('test ' + wk_test_name + ' is not passing')
155
            elif conformance[w3c_test_name] == 'PASS':
156
                _log.info('test ' + wk_test_name + ' is passing')
157
158
    def write_conformance_results(self):
159
        test_run_info = {}
160
        test_run_info['port_name'] = self._port.port_name
161
        test_run_info['tests_version'] = self.web_platform_test_importer.wptsha()
162
        test_run_info['results_directory'] = self._filesystem.relpath(self.layout_tests_result_directory(), self.conformance_results_directory())
163
        test_run_info['tests_directory'] = self._filesystem.relpath(self.runned_tests_directory, self.conformance_results_directory())
164
        self.results_manager().write_conformance_results(self.conformance_results_directory(), test_run_info)
165
166
167
def configure_logging():
168
    class LogHandler(logging.StreamHandler):
169
        def format(self, record):
170
            if record.levelno > logging.INFO:
171
                return "%s: %s" % (record.levelname, record.getMessage())
172
            return record.getMessage()
173
174
    logger = logging.getLogger()
175
    logger.setLevel(logging.INFO)
176
    handler = LogHandler()
177
    handler.setLevel(logging.INFO)
178
    logger.addHandler(handler)
179
    return handler
180
181
182
def main(argv, stdout, stderr):
183
    configure_logging()
184
    host = Host()
185
    parser = w3c_create_argument_parser(host, host.filesystem.basename(__file__))
186
    options, args = parser.parse_known_args(argv)
187
    port = host.port_factory.get(options.platform, optparse.Values({'webkit_test_runner': options.webkit_test_runner}))
188
189
    runner = W3CConformanceRunner(port, options)
190
    if runner.run_tests():
191
        runner.print_results_to_console()
192
        runner.print_potential_test_expectations_update()
193
        _log.info("Results exported in '" + runner.conformance_results_directory() + "'")
194
195
if '__main__' == __name__:
196
    sys.exit(main(sys.argv[1:], sys.stdout, sys.stderr))
- a/Tools/Scripts/webkitpy/w3c/test_results_manager.py +139 lines
Line 0 a/Tools/Scripts/webkitpy/w3c/test_results_manager.py_sec1
1
# Copyright (c) 2014, Canon Inc. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or without
4
# modification, are permitted provided that the following conditions
5
# are met:
6
# 1.  Redistributions of source code must retain the above copyright
7
#     notice, this list of conditions and the following disclaimer.
8
# 2.  Redistributions in binary form must reproduce the above copyright
9
#     notice, this list of conditions and the following disclaimer in the
10
#     documentation and/or other materials provided with the distribution.
11
# 3.  Neither the name of Canon Inc. nor the names of
12
#     its contributors may be used to endorse or promote products derived
13
#     from this software without specific prior written permission.
14
#
15
# THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
16
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
# DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
19
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26
"""
27
 This script manage JSON and results.html files for W3C test results.
28
"""
29
30
import io
31
import json
32
33
from webkitpy.layout_tests.layout_package import json_results_generator
34
35
36
class TestResultsManager(object):
37
38
    _JSON_PREFIX = 'ADD_CONFORMANCE_RESULTS('
39
    _JSON_SUFFIX = ');'
40
41
    def __init__(self, port, base_directory, result_dir, tests):
42
        self._port = port
43
        self._filesystem = port.host.filesystem
44
        self._results_directory = result_dir
45
        self._tests = tests
46
47
        # Root directory of W3C imported test
48
        self._base_directory = base_directory
49
50
    def w3c_test_name(self, test):
51
        return self._filesystem.relpath(test, self._base_directory)
52
53
    def _get_test_results(self, tests, test_dict, path):
54
        for key in test_dict.keys():
55
            _path = self._filesystem.join(path, key)
56
            _potential_test = test_dict[key]
57
            if 'actual' in _potential_test:
58
                # Store the test
59
                tests[_path] = _potential_test
60
            else:
61
                # Process subdirectories
62
                self._get_test_results(tests, _potential_test, _path)
63
64
    def process_test_results(self):
65
        test_results = {}
66
        results_json_path = self._filesystem.join(self._results_directory, 'full_results.json')
67
        results_json = json_results_generator.load_json(self._filesystem, results_json_path)
68
        path = self._filesystem.sep if self._filesystem.isabs(self._base_directory) else ''
69
        self._get_test_results(test_results, results_json['tests'], path)
70
        return test_results
71
72
    def _compute_conformance_status(self, test_name, test_results):
73
        text = self._port.expected_text(test_name)
74
        if text is None or len(text) == 0:
75
            # if the empty expected file, test may be failing or a ref test.
76
            # Let's find out from json results if the test is failing.
77
            if test_name in test_results and 'actual' in test_results[test_name]:
78
                reason = test_results[test_name]['actual']
79
                if reason == 'CRASH' or reason == 'TIMEOUT':
80
                    return reason
81
                return 'ERROR'
82
            # TODO: We may want to validate that this is actually a ref test
83
            return 'PASS'
84
        # Let's check whether some lines start with PASS or FAIL
85
        # Test is said to PASS if at least one line is PASS an no line is FAIL
86
        hasFail = False
87
        hasPass = False
88
        buf = io.StringIO(unicode(text, "utf-8"))
89
        for line in buf.readlines():
90
            if line.startswith('PASS'):
91
                hasPass = True
92
            elif line.startswith('FAIL'):
93
                hasFail = True
94
        if hasPass:
95
            return 'PARTIAL' if hasFail else 'PASS'
96
        if hasFail:
97
            return 'FAIL'
98
        return 'ERROR'
99
100
    def compute_conformance_results(self):
101
        status = {}
102
        test_results = self.process_test_results()
103
        for test_name in self._tests:
104
            status[self.w3c_test_name(test_name)] = self._compute_conformance_status(test_name, test_results)
105
        return status
106
107
    def summary(self):
108
        num_pass = num_partial = num_fail = num_error = 0
109
        status = self.compute_conformance_results()
110
        for test_name in self._tests:
111
            result = status[self.w3c_test_name(test_name)]
112
            if result == 'PASS':
113
                num_pass += 1
114
            elif result == 'PARTIAL':
115
                num_partial += 1
116
            elif result == 'FAIL':
117
                num_fail += 1
118
            else:
119
                num_error += 1
120
        summary = {}
121
        summary['total'] = num_pass + num_fail + num_partial + num_error
122
        summary['num_pass'] = num_pass
123
        summary['num_fail'] = num_fail
124
        summary['num_partial'] = num_partial
125
        summary['num_error'] = num_error
126
        return summary
127
128
    def write_conformance_results(self, path, test_run_info):
129
        results = {}
130
        results['conformance_results'] = self.compute_conformance_results()
131
        results.update(test_run_info)
132
        # copy conformance results as json data
133
        json_string = json.dumps(results, separators=(',', ':'))
134
        json_string = self._JSON_PREFIX + json_string + self._JSON_SUFFIX
135
        self._filesystem.write_text_file(self._filesystem.join(path, 'w3c_conformance_results.json'), json_string)
136
        # copy html template
137
        results_file = self._port.path_from_webkit_base('LayoutTests', 'imported', 'w3c', 'resources', 'w3c_conformance_results.html')
138
        if self._filesystem.exists(results_file):
139
            self._filesystem.copyfile(results_file, self._filesystem.join(path, 'w3c_conformance_results.html'))
- a/Tools/Scripts/webkitpy/w3c/web_platform_test_setup.py +67 lines
Line 0 a/Tools/Scripts/webkitpy/w3c/web_platform_test_setup.py_sec1
1
#!/usr/bin/env python
2
3
# Copyright (c) 2014, Canon Inc. All rights reserved.
4
#
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions
7
# are met:
8
# 1.  Redistributions of source code must retain the above copyright
9
#     notice, this list of conditions and the following disclaimer.
10
# 2.  Redistributions in binary form must reproduce the above copyright
11
#     notice, this list of conditions and the following disclaimer in the
12
#     documentation and/or other materials provided with the distribution.
13
# 3.  Neither the name of Canon Inc. nor the names of
14
#     its contributors may be used to endorse or promote products derived
15
#     from this software without specific prior written permission.
16
#
17
# THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
18
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
# DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
21
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
"""
29
 This script allows setting up the web platform test parameters such as:
30
    - The config.json file used by the WPT http server
31
    - The testharnessreport.js used for web platform tests (copy of webkit testharnessreport.js).
32
"""
33
34
import logging
35
36
from webkitpy.common.host import Host
37
from webkitpy.common.webkit_finder import WebKitFinder
38
39
_log = logging.getLogger(__name__)
40
41
42
class WebPlatformTestSetup(object):
43
44
    def __init__(self, host, test_directory):
45
        self._filesystem = host.filesystem
46
        self._wpt_root = test_directory
47
        self._layout_root = self._filesystem.join(WebKitFinder(self._filesystem).webkit_base(), "LayoutTests")
48
49
    def restore_w3c_testharnessreport(self):
50
        _log.debug('Using W3C WPT testharnessreport.js')
51
        testharnessreport_wpt_filename = self._filesystem.join(self._wpt_root, "resources", "testharnessreport.js~")
52
        if self._filesystem.isfile(testharnessreport_wpt_filename):
53
            self._filesystem.copyfile(testharnessreport_wpt_filename, self._filesystem.join(self._wpt_root, "resources", "testharnessreport.js"))
54
            self._filesystem.remove(testharnessreport_wpt_filename)
55
56
    def copy_webkit_testharnessreport(self):
57
        _log.debug('Using WebKit testharnessreport.js')
58
        testharnessreport_wk_filename = self._filesystem.join(self._layout_root, "resources", "testharnessreport.js")
59
        if self._filesystem.isfile(testharnessreport_wk_filename):
60
            self._filesystem.copyfile(self._filesystem.join(self._wpt_root, "resources", "testharnessreport.js"), self._filesystem.join(self._wpt_root, "resources", "testharnessreport.js~"))
61
            self._filesystem.copyfile(self._filesystem.join(self._layout_root, "resources", "testharnessreport.js"), self._filesystem.join(self._wpt_root, "resources", "testharnessreport.js"))
62
63
    def copy_wpt_json_config(self):
64
        _log.debug('Copying json web platform server config')
65
        config_wpt_filename = self._filesystem.join(self._layout_root, "imported", "w3c", "resources", "config.json")
66
        if self._filesystem.isfile(config_wpt_filename):
67
            self._filesystem.copyfile(config_wpt_filename, self._filesystem.join(self._wpt_root, "config.json"))
- a/LayoutTests/imported/w3c/ChangeLog +10 lines
Lines 1-3 a/LayoutTests/imported/w3c/ChangeLog_sec1
1
2014-09-16  Youenn Fablet  <youenn.fablet@crf.canon.fr>
2
3
        Add support for automated W3C conformance testing
4
        https://bugs.webkit.org/show_bug.cgi?id=134766
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * resources/config.json: Added (test server config file).
9
        * resources/w3c_conformance_results.html: Added (conformance result template file).
10
1
2013-12-03  Ryosuke Niwa  <rniwa@webkit.org>
11
2013-12-03  Ryosuke Niwa  <rniwa@webkit.org>
2
12
3
        Import the XHTML parsing and serialization tests for template elements
13
        Import the XHTML parsing and serialization tests for template elements
- a/LayoutTests/imported/w3c/resources/config.json +7 lines
Line 0 a/LayoutTests/imported/w3c/resources/config.json_sec1
1
{"host": "localhost",
2
 "ports":{"http":[8800, 8801],
3
          "https":[],
4
          "ws":[49001]},
5
 "check_subdomains": false,
6
 "log_level":"debug",
7
 "bind_hostname": false}
- a/LayoutTests/imported/w3c/resources/w3c_conformance_results.html +427 lines
Line 0 a/LayoutTests/imported/w3c/resources/w3c_conformance_results.html_sec1
1
<!DOCTYPE html>
2
<html>
3
<head>
4
<style>
5
#results {
6
	display: table;
7
    padding: 20px;
8
	clear: both;
9
}
10
#summary {
11
    margin-top: 20px;
12
    margin-bottom: 20px;
13
}
14
15
.test, .firstline {
16
	display: table;
17
}
18
.testname, .testresult, .firstLine > div {
19
    background-color: lavender;
20
    border-bottom:solid 1px white;
21
}
22
23
.firstLineCell{
24
	display: table-cell;
25
	text-align: center;
26
	width: 800px;
27
}
28
29
.secondLineCell {
30
	display: table-cell;
31
	padding-left: 50px;
32
	width: 750px;
33
}
34
35
.testname {
36
	display: table-cell;
37
	width: 800px;
38
	margin-left:20px;
39
}
40
41
.testresult, .port {
42
	display: table-cell;
43
	width: 250px;
44
	text-align: center;
45
}
46
47
.testresult a {
48
    text-transform: capitalize;
49
}
50
51
.partial, .pass, .fail, .timeout, .error {
52
	text-align: center;
53
}
54
.pass a {
55
    color: green;
56
}
57
58
.partial a {
59
    color: yellow;
60
}
61
62
.fail a {
63
    color: orange;
64
}
65
66
.timeout a {
67
    color: red;
68
}
69
70
.crash a {
71
    color: red;
72
}
73
74
.error a {
75
    color: red;
76
}
77
78
.error-results-hist {
79
    background-color: red;
80
    float: left; 
81
}
82
 
83
.fail-results-hist {
84
    background-color: orange;
85
    float: left;
86
}
87
88
.partial-results-hist {
89
    background-color: yellow;
90
    float: left;
91
}
92
.pass-results-hist {
93
    background-color: green;
94
    float: left;
95
}
96
97
.module-name {
98
	display:table-cell;
99
	width: 800px;
100
}
101
102
.number-of-tests {
103
	display:inline-block;
104
	width: 50px;
105
}
106
107
.module-results {
108
	text-align: center;
109
	display:table-cell;
110
	width: 250px;
111
}
112
113
.histogram {
114
	display:inline-block;
115
	margin-left: 40px;
116
	margin-top: 5px;
117
	width:150px;
118
}
119
120
.module{
121
    background-color: lavender;
122
    border:solid 1px white;
123
	display:table;
124
}
125
126
.module-summary, .secondLine {
127
	display:table;
128
    background: lavender;
129
    border:solid 1px white;
130
    height: 25px;
131
    cursor:pointer;
132
}
133
134
.box{
135
	display: table;
136
}
137
138
.hidden-data {
139
    display: none
140
}
141
142
.legend > div {
143
	float: left;
144
	margin-right: 5px;
145
	min-width: 20px;
146
}
147
148
.legend {
149
}
150
</style>
151
<script>
152
153
function getTestsDirectory(results)
154
{
155
    return (results.root_directory ? results.root_directory : results.port_name) + "/" + 
156
            (results.tests_directory ? results.tests_directory : "imported-tests")
157
}
158
159
function getResultsDirectory(results)
160
{
161
    return (results.root_directory ? results.root_directory : results.port_name) + "/" + 
162
            (results.results_directory ? results.results_directory : "layout-test-results")
163
}
164
165
function getTestLink(testname, results)
166
{
167
	return "<div style='float:left; margin-right:10px'><a href='" + getTestsDirectory(results) + "/" + testname + "'>" + testname + "</a></div>"
168
		+ "<div>(<a href='https://github.com/w3c/web-platform-tests/blob/" + results.tests_version + "/" + testname + "'>github</a>)</div>" 
169
}
170
171
function getTestResultLink(testname, result, results)
172
{
173
	suffix = "." + testname.split('.').pop();
174
	return "<a href='" + getTestsDirectory(results) + "/" + testname.replace(suffix,"-expected.txt") + "'>" + result.toLowerCase() + "</a>"
175
}
176
177
function testSuiteHist(numError, numFail, numPartial, numPass)
178
{
179
    var total = numError + numPass + numPartial + numFail;
180
181
    html = '<div class="module-results">'
182
183
    html += '<div class="number-of-tests">' + numPass + '/' + total + '</div>'
184
185
	html += '<div class="histogram">'
186
    if (numError)
187
        html += '<div class="error-results-hist" style="width:' + (100 * numError / total) + '%">&nbsp;</div>'
188
    if (numFail)
189
        html += '<div class="fail-results-hist" style="width:' + (100 * numFail / total)  + '%">&nbsp;</div>'
190
    if (numPartial)
191
        html += '<div class="partial-results-hist" style="width:' + (100 * numPartial / total) + '%">&nbsp;</div>'
192
    if (numPass)
193
        html += '<div class="pass-results-hist" style="width:' + (100 * numPass / total) + '%">&nbsp;</div>'
194
    html += '</div>'
195
196
    return html + '</div>';
197
}
198
199
function getTestsuiteModules(results)
200
 {
201
	var modules = {}
202
	// first try to only show module from URL hash
203
	var hash = window.location.hash.substring(1)
204
	var hasTest = false
205
	if (hash.length)
206
		Object.keys(results.conformance_results)
207
			.sort()
208
			.forEach(function(key, i) {
209
				var testName = key
210
				if (testName.indexOf(hash) == 0) {
211
					hasTest = true
212
					var items = testName.split("/")
213
					var name = items[0]
214
					if (modules[name])
215
						modules[name].push(key)
216
					else
217
						modules[name] = [key]
218
				}
219
		})
220
	if (hasTest)
221
		return modules
222
	// if no tests, show all modules
223
    Object.keys(results.conformance_results)
224
        .sort()
225
        .forEach(function(key, i) {
226
			var testName = key
227
			var items = testName.split("/")
228
			var name = items[0]
229
			// In case of html module, we split again
230
			if (name == 'html')
231
				name += '/' + items[1]
232
			if (modules[name])
233
				modules[name].push(key)
234
			else
235
				modules[name] = [key]
236
	})
237
	return modules
238
 }
239
240
function toggleTests(div)
241
{
242
	var box = div.nextElementSibling
243
	if (box) {
244
		if (box.className == 'box')
245
            box.className ='hidden-data'
246
		else
247
			box.className = 'box'
248
	}
249
}
250
251
function computeGlobalConformance(results)
252
{
253
	var summary = {numPass: 0, numPartial: 0, numFail: 0, numError: 0}
254
	for (var test in results.conformance_results) {
255
		if (results.conformance_results.hasOwnProperty(test)) {
256
			result = results.conformance_results[test]
257
			if (result == "PASS") summary.numPass++
258
			else if (result == "PARTIAL") summary.numPartial++
259
			else if (result == "FAIL") summary.numFail++
260
			else summary.numError++
261
		}
262
	}
263
	return summary
264
}
265
266
function computeStatistics(resultsSummary, result, results)
267
{
268
	summary = resultsSummary[results.port_name]
269
	if (!summary)
270
		resultsSummary[results.port_name] = summary = {numPass: 0, numPartial: 0, numFail: 0, numError: 0}
271
	if (result == "PASS") summary.numPass++
272
	else if (result == "PARTIAL") summary.numPartial++
273
	else if (result == "FAIL") summary.numFail++
274
	else summary.numError++
275
}
276
277
function addTestSuiteListOfResults(moduleName, tests, listOfResults, isOpen)
278
{
279
	var resultsSummary =  {}
280
    var numPass = numPartial = numFail = numError = 0
281
    var innerHTML = ""
282
    tests.forEach(function(key, i) {
283
			innerHTML += "<div class='test'><div class='testname'>" + getTestLink(key, listOfResults[0]) + "</div>"
284
			listOfResults.forEach(function(results) {
285
				result = results.conformance_results[key]
286
                if (!result) {
287
                    result = "Missing"
288
                    console.log("WARNING: test " + key + " is missing");
289
                }
290
				innerHTML += "<div class='testresult " + result.toLowerCase() + "'>" + getTestResultLink(key, result, results) + "</div>"
291
				computeStatistics(resultsSummary, result, results)
292
			})
293
			innerHTML += "</div>"
294
       })
295
    var html = '<div class="module"><div class="module-summary" onclick="toggleTests(event.currentTarget)"><div class="module-name">' + moduleName + '</div>'
296
	listOfResults.forEach(function(results) {
297
		var summary = resultsSummary[results.port_name]
298
		html += testSuiteHist(summary.numError, summary.numFail, summary.numPartial, summary.numPass)
299
	})
300
	html += '</div><div class="' + (isOpen ? "box" : "hidden-data") + '">';
301
    html += innerHTML
302
    html += '</div></div>'
303
    document.getElementById("results").innerHTML += html
304
}
305
306
function writeSummary()
307
{
308
	var html = "<div>W3C conformance results from run-webkit-test ("
309
    listOfResults.forEach(function(results) {
310
        html += "<a href='" + getResultsDirectory(results) + "'>" + results.port_name + "</a> &nbsp;"
311
    })
312
    html += ")</div>"
313
314
	if (listOfResults.length > 1) {
315
		var sameTestVersion = true
316
		listOfResults.forEach(function(results) {
317
			if (listOfResults[0].tests_version != results.tests_version) {
318
				sameTestVersion = false
319
                html += "<div>Warning: W3C test version are not the same for all platforms: "
320
                html += listOfResults[0].tests_version + " vs " + results.tests_version + " of platform " + results.port_name
321
                console.log(results)
322
                html += "</div>"
323
			}
324
		})
325
		if (!sameTestVersion) {/*
326
			html += "<div>Warning: W3C test version are not the same for all platforms: "
327
            html += listOfResults[0].tests_version + " vs " + results.tests_version + " of platform " + results.port_name
328
            console.log(results)
329
            html += "</div>"*/
330
        }
331
		else if (listOfResults[0].tests_version == "master")
332
			html += "<div>Warning: using master as W3C test version</div>"
333
	}
334
335
    document.getElementById("summary").innerHTML = html
336
}
337
338
function displayResults()
339
{
340
    setTimeout(function()  {
341
	var firstLineHTML = "<div class='firstLine'><div class='firstLineCell'>Module/Test Name</div>"
342
	listOfResults.forEach(function(results) {
343
		firstLineHTML += "<div class='port'>" + results.port_name.toUpperCase() + "</div>"
344
	})
345
	firstLineHTML += "</div>"
346
	var secondLineHTML = "<div class='secondLine'><div class='secondLineCell'>Overall conformance</div>"
347
	listOfResults.forEach(function(results) {
348
		summary = computeGlobalConformance(results)
349
		secondLineHTML += testSuiteHist(summary.numError, summary.numFail, summary.numPartial, summary.numPass)
350
	})
351
	secondLineHTML += "</div>"
352
353
	document.getElementById("results").innerHTML = firstLineHTML + secondLineHTML
354
	var modules =  getTestsuiteModules(listOfResults[0])
355
	var keys = Object.keys(modules)
356
    keys.sort().forEach( function(key, i) {
357
		addTestSuiteListOfResults(key, modules[key], listOfResults, keys.length == 1)
358
	})
359
	writeSummary(listOfResults)
360
    }, 0)
361
}
362
363
 
364
listOfResults = [] 
365
function ADD_CONFORMANCE_RESULTS(results)
366
{
367
    results.root_directory = dirs[counter]
368
	listOfResults.push(results)
369
    setTimeout(loadScripts, 0)
370
    
371
}
372
373
//window.onload = displayResults
374
var counter
375
var dirs
376
function loadScripts(directories)
377
{
378
    if (directories) {
379
        dirs = directories
380
        counter = -1
381
    }
382
    if (counter < dirs.length - 1) {
383
        document.getElementById('summary').innerHTML = "Loading " + dirs[++counter] + "..."
384
        var head= document.getElementsByTagName('head')[0];
385
        var script= document.createElement('script');
386
        script.type= 'text/javascript';
387
        script.src= dirs[counter] + '/w3c_conformance_results.json';
388
        head.appendChild(script);
389
    }
390
    else {
391
        document.getElementById('summary').innerHTML = "Displaying results..."
392
        setTimeout(displayResults, 0)
393
    }
394
}
395
396
</script>
397
</head>
398
<body>
399
<div id="summary">
400
    Loading...
401
</div>
402
<div class="legend">
403
	<div class="error-results-hist legend">&nbsp;</div>
404
	<div>Error, Timeout or Crash</div>
405
	<div class="fail-results-hist legend">&nbsp;</div>
406
	<div> All assertions failing</div>
407
	<div class="partial-results-hist legend">&nbsp;</div>
408
	<div> Some assertions passing</div>
409
	<div class="pass-results-hist legend">&nbsp;</div>
410
	<div> All assertions passing</div>
411
</div>
412
<div id="results">
413
</div>
414
<!-- place as many .json file as needed -->
415
<script>
416
    setTimeout(function() {
417
        loadScripts([
418
            "."
419
        ])
420
    }, 0)
421
</script>
422
<!--script src="efl/w3c_conformance_results.json"></script>
423
<script src="gtk/w3c_conformance_results.json"></script>
424
<script src="mac/w3c_conformance_results.json"></script>
425
<script src="mac-wk2/w3c_conformance_results.json"></script-->
426
</body>
427
</html>

Return to Bug 134766