Create a script to import W3C tests
[WebKit-https.git] / Tools / Scripts / webkitpy / w3c / test_converter_unittest.py
1 #!/usr/bin/env python
2
3 # Copyright (C) 2013 Adobe Systems Incorporated. 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 #
9 # 1. Redistributions of source code must retain the above
10 #    copyright notice, this list of conditions and the following
11 #    disclaimer.
12 # 2. Redistributions in binary form must reproduce the above
13 #    copyright notice, this list of conditions and the following
14 #    disclaimer in the documentation and/or other materials
15 #    provided with the distribution.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
18 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
21 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22 # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 # SUCH DAMAGE.
29 import os
30 from random import randint
31 import re
32 import unittest2 as unittest
33
34 from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup
35
36 from webkitpy.w3c.test_converter import TestConverter
37 from webkitpy.w3c import test_converter
38
39
40 class TestConverterTest(unittest.TestCase):
41
42     def testLoadPrefixedPropList(self):
43         """ Tests that the current list of properties requiring the -webkit- prefix load correctly """
44
45         # Get the full list of prefixed properties
46         converter = TestConverter()
47         prop_list = converter.prefixed_properties
48
49         # Verify we got properties back
50         self.assertGreater(len(prop_list), 0, 'No prefixed properties found')
51
52         # Verify they're all prefixed
53         for prop in prop_list:
54             self.assertTrue(prop.startswith('-webkit-'))
55
56     def test_convertForWebkitNothingToConvert(self):
57         """ Tests convert_for_webkit() using a basic test that has nothing to convert """
58
59         test_html = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
60 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
61 <html xmlns="http://www.w3.org/1999/xhtml">
62 <head>
63 <title>CSS Test: DESCRIPTION OF TEST</title>
64 <link rel="author" title="NAME_OF_AUTHOR"
65 href="mailto:EMAIL OR http://CONTACT_PAGE"/>
66 <link rel="help" href="RELEVANT_SPEC_SECTION"/>
67 <meta name="assert" content="TEST ASSERTION"/>
68 <style type="text/css"><![CDATA[
69 CSS FOR TEST
70 ]]></style>
71 </head>
72 <body>
73 CONTENT OF TEST
74 </body>
75 </html>
76 """
77         converter = TestConverter()
78
79         # Try to convert the html
80         converted = converter.convert_for_webkit('/nothing/to/convert', contents=test_html, filename='somefile.html')
81
82         # Verify nothing was converted
83         self.assertEqual(converted, None, 'test was should not have been converted')
84
85     def test_convertForWebkitHarnessOnly(self):
86         """ Tests convert_for_webkit() using a basic JS test that uses testharness.js only and has no prefixed properties """
87
88         test_html = """<head>
89 <link href="/resources/testharness.css" rel="stylesheet" type="text/css">
90 <script src="/resources/testharness.js"></script>
91 </head>
92 """
93         converter = TestConverter()
94
95         # Create path to a fake test directory
96         test_path = os.path.join(os.path.sep, test_converter.WEBKIT_ROOT,
97                                               test_converter.LAYOUT_TESTS_DIRECTORY,
98                                               test_converter.CSS_SUBDIR,
99                                               'harnessonly')
100
101         # Convert the html
102         converted = converter.convert_for_webkit(test_path, contents=test_html, filename='somefile.html')
103
104         # Verify a conversion happened
105         self.assertNotEqual(converted, None, 'test was not converted')
106
107         # Verify that both the harness paths were converted correctly
108         self.verifyTestHarnessPaths(converted[1], test_path, 1, 1)
109
110         # Verify no properties were converted
111         self.verifyPrefixedProperties(converted, [])
112
113     def test_convertForWebkitPropsOnly(self):
114         """ Tests convert_for_webkit() using a test that has 2 prefixed properties: 1 in a style block + 1 inline style """
115
116         test_html = """<html>
117 <head>
118 <link href="/resources/testharness.css" rel="stylesheet" type="text/css">
119 <script src="/resources/testharness.js"></script>
120 <style type="text/css">
121
122 #block1 { @test0@: propvalue; }
123
124 </style>
125 </head>
126 <body>
127 <div id="elem1" style="@test1@: propvalue;"></div>
128 </body>
129 </html>
130 """
131
132         converter = TestConverter()
133
134         # Create path to a fake test directory
135         test_path = os.path.join(os.path.sep, test_converter.WEBKIT_ROOT,
136                                               test_converter.LAYOUT_TESTS_DIRECTORY,
137                                               test_converter.CSS_SUBDIR,
138                                               'harnessandprops')
139
140         # Generate & insert the test properties into the test_html
141         test_content = self.generateTestContent(converter.prefixed_properties, 2, test_html)
142
143         # Convert the html
144         converted = converter.convert_for_webkit(test_path, contents=test_content[1], filename='somefile.html')
145
146         # Verify a conversion happened
147         self.assertNotEqual(converted, None, 'test was not converted')
148
149         # Verify that both the harness paths and properties were all converted correctly
150         self.verifyTestHarnessPaths(converted[1], test_path, 1, 1)
151         self.verifyPrefixedProperties(converted, test_content[0])
152
153     def test_convertForWebkitHarnessAndProps(self):
154         """ Tests convert_for_webkit() using a basic JS test that uses testharness.js and testharness.css and has 4 prefixed properties: 3 in a style block + 1 inline style """
155
156         test_html = """<html>
157 <head>
158 <link href="/resources/testharness.css" rel="stylesheet" type="text/css">
159 <script src="/resources/testharness.js"></script>
160 <style type="text/css">
161
162 #block1 { @test0@: propvalue; }
163 #block2 { @test1@: propvalue; }
164 #block3 { @test2@: propvalue; }
165
166 </style>
167 </head>
168 <body>
169 <div id="elem1" style="@test3@: propvalue;"></div>
170 </body>
171 </html>
172 """
173         converter = TestConverter()
174
175         # Create path to a fake test directory
176         test_path = os.path.join(os.path.sep, test_converter.WEBKIT_ROOT,
177                                               test_converter.LAYOUT_TESTS_DIRECTORY,
178                                               test_converter.CSS_SUBDIR,
179                                               'harnessandprops')
180
181         # Generate & insert the test properties into the test_html
182         test_content = self.generateTestContent(converter.prefixed_properties, 4, test_html)
183
184         # Convert the html
185         converted = converter.convert_for_webkit(test_path, contents=test_content[1], filename='somefile.html')
186
187         # Verify a conversion happened
188         self.assertNotEqual(converted, None, 'test was not converted')
189
190         # Verify that both the harness paths and properties were all converted correctly
191         self.verifyTestHarnessPaths(converted[1], test_path, 1, 1)
192         self.verifyPrefixedProperties(converted, test_content[0])
193
194     def test_convertTestHarnessPaths(self):
195         """ Tests convert_testharness_paths() with a test that uses all three testharness files """
196
197         # Basic test content using all three testharness files
198         test_html = """<head>
199 <link href="/resources/testharness.css" rel="stylesheet" type="text/css">
200 <script src="/resources/testharness.js"></script>
201 <script src="/resources/testharnessreport.js"></script>
202 </head>
203 """
204         converter = TestConverter()
205
206         # Create path to a fake test directory
207         test_path = os.path.join(os.path.sep, test_converter.WEBKIT_ROOT,
208                                               test_converter.LAYOUT_TESTS_DIRECTORY,
209                                               test_converter.CSS_SUBDIR,
210                                               'testharnesspaths')
211
212         # Convert the html
213         doc = BeautifulSoup(test_html)
214         converted = converter.convert_testharness_paths(doc, test_path)
215
216         # Verify a conversion happened
217         self.assertTrue(converted, 'test was not converted')
218
219         # Verify all got converted correctly
220         self.verifyTestHarnessPaths(doc, test_path, 2, 1)
221
222     def test_convertPrefixedProperties(self):
223         """ Tests convert_prefixed_properties() file that has 20 properties requiring the -webkit- prefix:
224         10 in one style block + 5 in another style
225         block + 5 inline styles, including one with multiple prefixed properties.
226         The properties in the test content are in all sorts of wack formatting.
227         """
228
229         test_html = """<html>
230 <style type="text/css"><![CDATA[
231
232 .block1 {
233     width: 300px;
234     height: 300px
235 }
236
237 .block2 {
238     @test0@: propvalue;
239 }
240
241 .block3{@test1@: propvalue;}
242
243 .block4 { @test2@:propvalue; }
244
245 .block5{ @test3@ :propvalue; }
246
247 #block6 {    @test4@   :   propvalue;  }
248
249 #block7
250 {
251     @test5@: propvalue;
252 }
253
254 #block8 { @test6@: propvalue; }
255
256 #block9:pseudo
257 {
258
259     @test7@: propvalue;
260     @test8@:  propvalue propvalue propvalue;;
261 }
262
263 ]]></style>
264 </head>
265 <body>
266     <div id="elem1" style="@test9@: propvalue;"></div>
267     <div id="elem2" style="propname: propvalue; @test10@ : propvalue; propname:propvalue;"></div>
268     <div id="elem2" style="@test11@: propvalue; @test12@ : propvalue; @test13@   :propvalue;"></div>
269     <div id="elem3" style="@test14@:propvalue"></div>
270 </body>
271 <style type="text/css"><![CDATA[
272
273 .block10{ @test15@: propvalue; }
274 .block11{ @test16@: propvalue; }
275 .block12{ @test17@: propvalue; }
276 #block13:pseudo
277 {
278     @test18@: propvalue;
279     @test19@: propvalue;
280 }
281
282 ]]></style>
283 </html>
284 """
285         converter = TestConverter()
286
287         # Generate & insert the test properties into the test_html
288         test_content = self.generateTestContent(converter.prefixed_properties, 20, test_html)
289
290         # Convert the html
291         converted = converter.convert_prefixed_properties(BeautifulSoup(test_content[1]))
292
293         # Verify a conversion happened
294         self.assertNotEqual(converted, None, 'test was not converted')
295
296         # Verify all the generated test properties were converted correctly
297         self.verifyPrefixedProperties(converted, test_content[0])
298
299     def verifyTestHarnessPaths(self, converted, test_path, num_src_paths, num_href_paths):
300         """ Verifies all W3C-style paths to test harness files were converted correctly """
301
302         # Make soup if we need to
303         if isinstance(converted, basestring):
304             converted = BeautifulSoup(converted)
305
306         # Build the path to LayoutTests/resources
307         resources_dir = os.path.join(os.path.sep, test_converter.WEBKIT_ROOT,
308                                                   test_converter.LAYOUT_TESTS_DIRECTORY,
309                                                   test_converter.RESOURCES_DIRECTORY)
310
311         # Verify the original paths are no longer there
312         orig_path_pattern = re.compile('\"/resources/testharness')
313         self.assertEquals(len(converted.findAll(src=orig_path_pattern)), 0,
314                           'testharness src path was not converted')
315         self.assertEquals(len(converted.findAll(href=orig_path_pattern)), 0,
316                           'testharness href path was not converted')
317
318         # Get the new relpath from the tester dir
319         new_relpath = os.path.relpath(resources_dir, test_path)
320
321         # Verify it's in all the right places
322         relpath_pattern = re.compile(new_relpath)
323         self.assertEquals(len(converted.findAll(src=relpath_pattern)), num_src_paths,
324                           'testharness src relative path not correct')
325         self.assertEquals(len(converted.findAll(href=relpath_pattern)), num_href_paths,
326                           'testharness href relative path not correct')
327
328     def verifyPrefixedProperties(self, converted, test_properties):
329         """ Verifies a list of test_properties were converted correctly """
330
331         # Verify that the number of test properties equals the number that were converted
332         self.assertEqual(len(converted[0]), len(test_properties), 'Incorrect number of properties converted')
333
334         # Verify they're all in the converted document
335         for test_prop in test_properties:
336             self.assertTrue((test_prop in converted[1]), 'Property ' + test_prop + ' not found in converted doc')
337
338     def generateTestContent(self, full_prop_list, num_test_properties, html):
339         """ Generates a random list of unique properties requiring the -webkit- prefix and inserts them into html content that's been tokenized using \'@testXX@\' syntax """
340
341         test_properties = []
342
343         # Grab a random bunch of 20 unique properties requiring prefixes to test with
344         count = 0
345         while count < num_test_properties:
346             idx = randint(0, len(full_prop_list) - 1)
347             if not(full_prop_list[idx] in test_properties):
348                 test_properties.append(full_prop_list[idx])
349                 count += 1
350
351         # Replace the tokens in the testhtml with the test properties. Walk backward
352         # through the list to replace the double-digit tokens first
353         idx = len(test_properties) - 1
354         while idx >= 0:
355             # Use the unprefixed version
356             test_prop = test_properties[idx].replace('-webkit-', '')
357             # Replace the token
358             html = html.replace('@test' + str(idx) + '@', test_prop)
359             idx -= 1
360
361         return (test_properties, html)