4fe3ec16cf515e17ac78577c10ff3af405f1ab04
[WebKit.git] / WebKitTools / Scripts / webkitpy / layout_tests / port / test.py
1 #!/usr/bin/env python
2 # Copyright (C) 2010 Google Inc. All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 #     * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 #     * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
13 # distribution.
14 #     * Neither the Google name nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 """Dummy Port implementation used for testing."""
31 from __future__ import with_statement
32
33 import codecs
34 import os
35 import time
36
37 import base
38
39
40 class TestPort(base.Port):
41     """Test implementation of the Port interface."""
42
43     def __init__(self, port_name=None, options=None):
44         base.Port.__init__(self, port_name, options)
45
46     def baseline_path(self):
47         return os.path.join(self.layout_tests_dir(), 'platform',
48                             self.name() + self.version())
49
50     def baseline_search_path(self):
51         return [self.baseline_path()]
52
53     def check_build(self, needs_http):
54         return True
55
56     def diff_image(self, expected_filename, actual_filename,
57                    diff_filename=None, tolerance=0):
58         with codecs.open(actual_filename, "r", "utf-8") as actual_fh:
59             actual_contents = actual_fh.read()
60         with codecs.open(expected_filename, "r", "utf-8") as expected_fh:
61             expected_contents = expected_fh.read()
62         diffed = actual_contents != expected_contents
63         if diffed and diff_filename:
64             with codecs.open(diff_filename, "w", "utf-8") as diff_fh:
65                 diff_fh.write("< %s\n---\n> %s\n" %
66                               (expected_contents, actual_contents))
67         return diffed
68
69     def layout_tests_dir(self):
70         return self.path_from_webkit_base('WebKitTools', 'Scripts',
71                                           'webkitpy', 'layout_tests', 'data')
72
73     def name(self):
74         return self._name
75
76     def options(self):
77         return self._options
78
79     def path_to_test_expectations_file(self):
80         return self.path_from_webkit_base('WebKitTools', 'Scripts',
81             'webkitpy', 'layout_tests', 'data', 'platform', 'test',
82             'test_expectations.txt')
83
84     def _path_to_wdiff(self):
85         return None
86
87     def results_directory(self):
88         return '/tmp/' + self._options.results_directory
89
90     def setup_test_run(self):
91         pass
92
93     def show_results_html_file(self, filename):
94         pass
95
96     def create_driver(self, image_path, options):
97         return TestDriver(image_path, options, self)
98
99     def start_http_server(self):
100         pass
101
102     def start_websocket_server(self):
103         pass
104
105     def stop_http_server(self):
106         pass
107
108     def stop_websocket_server(self):
109         pass
110
111     def test_expectations(self):
112         """Returns the test expectations for this port.
113
114         Basically this string should contain the equivalent of a
115         test_expectations file. See test_expectations.py for more details."""
116         expectations_path = self.path_to_test_expectations_file()
117         with codecs.open(expectations_path, "r", "utf-8") as file:
118             return file.read()
119
120     def test_base_platform_names(self):
121         return ('test',)
122
123     def test_platform_name(self):
124         return 'test'
125
126     def test_platform_names(self):
127         return self.test_base_platform_names()
128
129     def test_platform_name_to_name(self, test_platform_name):
130         return test_platform_name
131
132     def version(self):
133         return ''
134
135
136 class TestDriver(base.Driver):
137     """Test/Dummy implementation of the DumpRenderTree interface."""
138
139     def __init__(self, image_path, test_driver_options, port):
140         self._driver_options = test_driver_options
141         self._image_path = image_path
142         self._port = port
143         self._image_written = False
144
145     def poll(self):
146         return True
147
148     def returncode(self):
149         return 0
150
151     def run_test(self, uri, timeoutms, image_hash):
152         basename = uri[(uri.rfind("/") + 1):uri.rfind(".html")]
153
154         error = ''
155         checksum = None
156         # There are four currently supported types of tests: text, image,
157         # image hash (checksum), and stderr output. The fake output
158         # is the basename of the file + "-" plus the type of test output
159         # (or a blank string for stderr).
160         #
161         # If 'image' or 'check' appears in the basename, we assume this is
162         # simulating a pixel test.
163         #
164         # If 'failures' appears in the URI, then we assume this test should
165         # fail. Which type of failures are determined by which strings appear
166         # in the basename of the test. For failures that produce outputs,
167         # we change the fake output to basename + "_failed-".
168         #
169         # The fact that each test produces (more or less) unique output data
170         # will allow us to see if any results get crossed by the rest of the
171         # program.
172         if 'failures' in uri:
173             crash = 'crash' in basename
174             timeout = 'timeout' in basename
175             if 'error' in basename:
176                 error = basename + "_error\n"
177             if 'text' in basename:
178                 output = basename + '_failed-txt\n'
179             else:
180                 output = basename + '-txt\n'
181             if self._port.options().pixel_tests:
182                 if ('image' in basename or 'check' in basename):
183                     checksum = basename + "-checksum\n"
184
185                 if 'image' in basename:
186                     with open(self._image_path, "w") as f:
187                         f.write(basename + "_failed-png\n")
188                 elif 'check' in basename:
189                     with open(self._image_path, "w") as f:
190                         f.write(basename + "-png\n")
191                 if 'checksum' in basename:
192                     checksum = basename + "_failed-checksum\n"
193         else:
194             crash = False
195             timeout = False
196             output = basename + '-txt\n'
197             if self._port.options().pixel_tests and (
198                 'image' in basename or 'check' in basename):
199                 checksum = basename + '-checksum\n'
200                 with open(self._image_path, "w") as f:
201                     f.write(basename + "-png")
202
203         return (crash, timeout, checksum, output, error)
204
205     def start(self):
206         pass
207
208     def stop(self):
209         pass