blob: 847c752ba755088f4cd1d50d17c3c82ea6aee0c4 [file] [log] [blame]
# Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
# Copyright (C) 2020 Apple Inc. All rights reserved.
#
# 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 os
import re
import unittest
from webkitcorepy import unicode
from webkitpy.common.host import Host
from webkitpy.common.webkit_finder import WebKitFinder
from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup
from webkitpy.w3c.test_converter import _W3CTestConverter
from webkitcorepy import OutputCapture
DUMMY_FILENAME = 'dummy.html'
DUMMY_PATH = 'dummy/testharness/path'
class W3CTestConverterTest(unittest.TestCase):
# FIXME: When we move to using a MockHost, this method should be removed, since
# then we can just pass in a dummy dir path
def fake_dir_path(self, dirname):
filesystem = Host().filesystem
webkit_root = WebKitFinder(filesystem).webkit_base()
return filesystem.abspath(filesystem.join(webkit_root, "LayoutTests", "css", dirname))
def test_read_prefixed_property_list(self):
""" Tests that the current list of properties requiring the -webkit- prefix load correctly """
# FIXME: We should be passing in a MockHost here ...
converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, None)
prop_list = converter.prefixed_properties
self.assertTrue(prop_list, 'No prefixed properties found')
property_values_list = converter.prefixed_property_values
self.assertTrue(property_values_list, 'No prefixed property values found')
def test_convert_for_webkit_nothing_to_convert(self):
""" Tests convert_for_webkit() using a basic test that has nothing to convert """
test_html = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Test: DESCRIPTION OF TEST</title>
<link rel="author" title="NAME_OF_AUTHOR"
href="mailto:EMAIL OR http://CONTACT_PAGE"/>
<link rel="help" href="RELEVANT_SPEC_SECTION"/>
<meta name="assert" content="TEST ASSERTION"/>
<style type="text/css"><![CDATA[
CSS FOR TEST
]]></style>
</head>
<body>
CONTENT OF TEST
&lt;We shouldn't convert HTML characters.&gt;
</body>
</html>
"""
converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, None)
with OutputCapture():
converter.feed(test_html)
converter.close()
converted = converter.output()
self.verify_no_conversion_happened(converted, test_html)
def test_convert_for_webkit_harness_only(self):
""" Tests convert_for_webkit() using a basic JS test that uses testharness.js only and has no prefixed properties """
test_html = """<head>
<link href="/resources/testharness.css" rel="stylesheet" type="text/css">
<script src="/resources/testharness.js"></script>
</head>
"""
fake_dir_path = self.fake_dir_path("harnessonly")
converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME, None)
converter.feed(test_html)
converter.close()
converted = converter.output()
self.verify_conversion_happened(converted)
self.verify_test_harness_paths(converter, converted[2], fake_dir_path, 1, 1)
self.verify_prefixed_properties(converted, [])
self.verify_prefixed_property_values(converted, [])
def test_convert_for_webkit_properties_only(self):
""" Tests convert_for_webkit() using a test that has 2 prefixed properties: 1 in a style block + 1 inline style """
test_html = """<html>
<head>
<link href="/resources/testharness.css" rel="stylesheet" type="text/css">
<script src="/resources/testharness.js"></script>
<style type="text/css">
#block1 { @test0@: @propvalue0@; }
</style>
</head>
<body>
<div id="elem1" style="@test1@: @propvalue1@;"></div>
</body>
</html>
"""
fake_dir_path = self.fake_dir_path('harnessandprops')
converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME, None)
test_content = self.generate_test_content_properties_and_values(converter.prefixed_properties, converter.prefixed_property_values, 1, test_html)
with OutputCapture():
converter.feed(test_content[2])
converter.close()
converted = converter.output()
self.verify_conversion_happened(converted)
self.verify_test_harness_paths(converter, converted[2], fake_dir_path, 1, 1)
self.verify_prefixed_properties(converted, test_content[0])
self.verify_prefixed_property_values(converted, test_content[1])
def test_convert_for_webkit_harness_and_properties(self):
""" 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 """
test_html = """<html>
<head>
<link href="/resources/testharness.css" rel="stylesheet" type="text/css">
<script src="/resources/testharness.js"></script>
<style type="text/css">
#block1 { @test0@: @propvalue0@; }
#block2 { @test1@: @propvalue1@; }
#block3 { @test2@: @propvalue2@; }
</style>
</head>
<body>
<div id="elem1" style="@test3@: @propvalue3@;"></div>
</body>
</html>
"""
fake_dir_path = self.fake_dir_path('harnessandprops')
converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME, None)
with OutputCapture():
test_content = self.generate_test_content_properties_and_values(converter.prefixed_properties, converter.prefixed_property_values, 2, test_html)
converter.feed(test_content[2])
converter.close()
converted = converter.output()
self.verify_conversion_happened(converted)
self.verify_test_harness_paths(converter, converted[2], fake_dir_path, 1, 1)
self.verify_prefixed_properties(converted, test_content[0])
self.verify_prefixed_property_values(converted, test_content[1])
def test_convert_test_harness_paths(self):
""" Tests convert_testharness_paths() with a test that uses all three testharness files """
test_html = """<head>
<link href="/resources/testharness.css" rel="stylesheet" type="text/css">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
"""
fake_dir_path = self.fake_dir_path('testharnesspaths')
converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME, None)
with OutputCapture():
converter.feed(test_html)
converter.close()
converted = converter.output()
self.verify_conversion_happened(converted)
self.verify_test_harness_paths(converter, converted[2], fake_dir_path, 2, 1)
def test_convert_prefixed_properties(self):
""" Tests convert_prefixed_properties() file that has 20 properties requiring the -webkit- prefix:
10 in one style block + 5 in another style
block + 5 inline styles, including one with multiple prefixed properties.
The properties in the test content are in all sorts of wack formatting.
"""
test_html = """<html>
<style type="text/css"><![CDATA[
.block1 {
width: 300px;
height: 300px
}
.block2 {
@test0@: @propvalue0@;
}
.block3{@test1@: @propvalue1@;}
.block4 { @test2@:@propvalue2@; }
.block5{ @test3@ :@propvalue3@; }
#block6 { @test4@ : @propvalue4@ ; }
#block7
{
@test5@: @propvalue5@;
}
#block8 { @test6@: @propvalue6@ }
#block9:pseudo
{
@test7@: @propvalue7@;
@test8@: propvalue propvalue propvalue;;
propname:
@propvalue8@;
}
]]></style>
</head>
<body>
<div id="elem1" style="@test9@: @propvalue9@;"></div>
<div id="elem2" style="propname: propvalue; @test10@ : @propvalue10@; propname:propvalue;"></div>
<div id="elem2" style="@test11@: @propvalue11@; @test12@ : @propvalue12@; @test13@ : @propvalue13@ ;"></div>
<div id="elem3" style="@test14@:@propvalue14@"></div>
</body>
<style type="text/css"><![CDATA[
.block10{ @test15@: @propvalue15@; }
.block11{ @test16@: @propvalue16@; }
.block12{ @test17@: @propvalue17@; }
#block13:pseudo
{
@test18@: @propvalue18@;
@test19@: @propvalue19@;
}
]]></style>
</html>
"""
converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, None)
test_content = self.generate_test_content_properties_and_values(converter.prefixed_properties, converter.prefixed_property_values, 20, test_html)
with OutputCapture():
converter.feed(test_content[2])
converter.close()
converted = converter.output()
self.verify_conversion_happened(converted)
self.verify_prefixed_properties(converted, test_content[0])
self.verify_prefixed_property_values(converted, test_content[1])
def test_convert_attributes_if_needed(self):
""" Tests convert_attributes_if_needed() using a reference file that has some relative src paths """
test_html = """<html>
<head>
<link href="../support/base-style.css">
<video src="resources/video.mkv"></video>
<script src="../../some-script.js"></script>
<style src="../../../some-style.css"></style>
</head>
<body>
<img src="../../../../some-image.jpg">
</body>
</html>
"""
test_reference_support_info = {'reference_relpath': '../', 'files': ['../../some-script.js', '../../../some-style.css', '../../../../some-image.jpg', '../support/base-style.css', 'resources/video.mkv'],
'elements': ['script', 'style', 'img', 'link', 'video']}
converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, test_reference_support_info)
with OutputCapture():
converter.feed(test_html)
converter.close()
converted = converter.output()
self.verify_conversion_happened(converted)
self.verify_reference_relative_paths(converted, test_reference_support_info)
def test_convert_style_multiple_url(self):
""" Tests convert_attributes_if_needed() using a reference file that has several relative URL paths in the style """
test_html = """<html>
<head>
<style type="text/css">
.redSquare {
position: absolute;
left:50px;
width: 100px;
height: 100px;
background-image:url(../support/yyy.png);
}
.greenSquare {
position: absolute;
left:50px;
width: 100px;
height: 100px;
background-image:url(../support/yy.png);
}
.yellowSquare {
position: absolute;
left:50px;
width: 100px;
height: 100px;
background-image:url(../../another/directory/x.png);
}
.container {
position: absolute;
}
</style>
</head>
<body>
</body>
</html>
"""
test_reference_support_info = {'reference_relpath': '../', 'files': ['../support/yyy.png', '../support/yy.png', '../../another/directory/x.png']}
converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, test_reference_support_info)
with OutputCapture():
converter.feed(test_html)
converter.close()
converted = converter.output()
self.verify_conversion_happened(converted)
for path in test_reference_support_info['files']:
expected_path = re.sub(test_reference_support_info['reference_relpath'], '', path, 1)
expected_url = 'background-image:url(' + expected_path + ');'
self.assertTrue(expected_url in converted[2], 'relative path ' + path + ' was not converted correcty')
def verify_conversion_happened(self, converted):
self.assertTrue(converted, "conversion didn't happen")
def verify_no_conversion_happened(self, converted, original):
self.assertEqual(converted[2], original, 'test should not have been converted')
def verify_test_harness_paths(self, converter, converted, test_path, num_src_paths, num_href_paths):
if isinstance(converted, str) or isinstance(converted, unicode):
converted = BeautifulSoup(converted)
resources_dir = converter.path_from_webkit_root("LayoutTests", "resources")
# Verify the original paths are gone, and the new paths are present.
orig_path_pattern = re.compile('\"/resources/testharness')
self.assertEqual(len(converted.findAll(src=orig_path_pattern)), 0, 'testharness src path was not converted')
self.assertEqual(len(converted.findAll(href=orig_path_pattern)), 0, 'testharness href path was not converted')
new_relpath = os.path.relpath(resources_dir, test_path).replace(os.sep, '/')
relpath_pattern = re.compile(new_relpath)
self.assertEqual(len(converted.findAll(src=relpath_pattern)), num_src_paths, 'testharness src relative path not correct')
self.assertEqual(len(converted.findAll(href=relpath_pattern)), num_href_paths, 'testharness href relative path not correct')
def verify_prefixed_properties(self, converted, test_properties):
self.assertEqual(len(set(converted[0])), len(set(test_properties)), 'Incorrect number of properties converted')
for test_prop in test_properties:
self.assertTrue((test_prop in converted[2]), 'Property ' + test_prop + ' not found in converted doc')
def verify_prefixed_property_values(self, converted, test_property_values):
self.assertEqual(len(set(converted[1])), len(set(test_property_values)), 'Incorrect number of property values converted ' + str(len(set(converted[1]))) + ' vs ' + str(len(set(test_property_values))))
for test_value in test_property_values:
self.assertTrue((test_value in converted[2]), 'Property value ' + test_value + ' not found in converted doc')
def verify_reference_relative_paths(self, converted, reference_support_info):
idx = 0
for path in reference_support_info['files']:
expected_path = re.sub(re.escape(reference_support_info['reference_relpath']), '', path, 1)
element = reference_support_info['elements'][idx]
element_src = 'href' if element == 'link' else 'src'
expected_tag = '<' + element + ' ' + element_src + '=\"' + expected_path + '\">'
self.assertTrue(expected_tag in converted[2], 'relative path ' + path + ' was not converted correcty')
idx += 1
def generate_test_content_properties_and_values(self, full_property_list, fully_property_values_list, num_test_properties_and_values, html):
"""Inserts properties requiring a -webkit- prefix into the content, replacing \'@testXX@\' with a property and \'@propvalueXX@\' with a value."""
test_content_properties = self.generate_test_content(full_property_list, num_test_properties_and_values, 'test', html)
test_content_property_values = self.generate_test_content(fully_property_values_list, num_test_properties_and_values, 'propvalue', test_content_properties[1])
return (test_content_properties[0], test_content_property_values[0], test_content_property_values[1])
def generate_test_content(self, full_list, num_test, suffix, html):
test_list = []
count = 0
while count < num_test:
test_list.append(full_list[count])
count += 1
# Replace the tokens in the testhtml with the test properties or values.
# Walk backward through the list to replace the double-digit tokens first.
index = len(test_list) - 1
while index >= 0:
# Use the unprefixed version
test = test_list[index].replace('-webkit-', '')
# Replace the token
html = html.replace('@' + suffix + str(index) + '@', test)
index -= 1
return (test_list, html)