| OLD | NEW |
| (Empty) |
| 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 | |
| 30 import logging | |
| 31 import re | |
| 32 | |
| 33 from webkitpy.common.host import Host | |
| 34 from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup as Parser | |
| 35 | |
| 36 | |
| 37 _log = logging.getLogger(__name__) | |
| 38 | |
| 39 | |
| 40 class TestParser(object): | |
| 41 | |
| 42 def __init__(self, options, filename): | |
| 43 self.options = options | |
| 44 self.filename = filename | |
| 45 self.host = Host() | |
| 46 self.filesystem = self.host.filesystem | |
| 47 | |
| 48 self.test_doc = None | |
| 49 self.ref_doc = None | |
| 50 self.load_file(filename) | |
| 51 | |
| 52 def load_file(self, filename): | |
| 53 if self.filesystem.isfile(filename): | |
| 54 try: | |
| 55 self.test_doc = Parser(self.filesystem.read_binary_file(filename
)) | |
| 56 except: | |
| 57 # FIXME: Figure out what to do if we can't parse the file. | |
| 58 _log.error("Failed to parse %s", filename) | |
| 59 self.test_doc is None | |
| 60 else: | |
| 61 if self.filesystem.isdir(filename): | |
| 62 # FIXME: Figure out what is triggering this and what to do about
it. | |
| 63 _log.error("Trying to load %s, which is a directory", filename) | |
| 64 self.test_doc = None | |
| 65 self.ref_doc = None | |
| 66 | |
| 67 def analyze_test(self, test_contents=None, ref_contents=None): | |
| 68 """ Analyzes a file to determine if it's a test, what type of test, and
what reference or support files it requires. Returns all of the test info """ | |
| 69 | |
| 70 test_info = None | |
| 71 | |
| 72 if test_contents is None and self.test_doc is None: | |
| 73 return test_info | |
| 74 | |
| 75 if test_contents is not None: | |
| 76 self.test_doc = Parser(test_contents) | |
| 77 | |
| 78 if ref_contents is not None: | |
| 79 self.ref_doc = Parser(ref_contents) | |
| 80 | |
| 81 # First check if it's a reftest | |
| 82 | |
| 83 matches = self.reference_links_of_type('match') + self.reference_links_o
f_type('mismatch') | |
| 84 if matches: | |
| 85 if len(matches) > 1: | |
| 86 # FIXME: Is this actually true? We should fix this. | |
| 87 _log.warning('Multiple references are not supported. Importing t
he first ref defined in %s', | |
| 88 self.filesystem.basename(self.filename)) | |
| 89 | |
| 90 try: | |
| 91 ref_file = self.filesystem.join(self.filesystem.dirname(self.fil
ename), matches[0]['href']) | |
| 92 except KeyError as e: | |
| 93 # FIXME: Figure out what to do w/ invalid test files. | |
| 94 _log.error('%s has a reference link but is missing the "href"',
self.filesystem) | |
| 95 return None | |
| 96 | |
| 97 if self.ref_doc is None: | |
| 98 self.ref_doc = self.load_file(ref_file) | |
| 99 | |
| 100 test_info = {'test': self.filename, 'reference': ref_file} | |
| 101 | |
| 102 # If the ref file path is relative, we need to check it for | |
| 103 # relative paths also because when it lands in WebKit, it will be | |
| 104 # moved down into the test dir. | |
| 105 # | |
| 106 # Note: The test files themselves are not checked for support files | |
| 107 # outside their directories as the convention in the CSSWG is to | |
| 108 # put all support files in the same dir or subdir as the test. | |
| 109 # | |
| 110 # All non-test files in the test's directory tree are normally | |
| 111 # copied as part of the import as they are assumed to be required | |
| 112 # support files. | |
| 113 # | |
| 114 # *But*, there is exactly one case in the entire css2.1 suite where | |
| 115 # a test depends on a file that lives in a different directory, | |
| 116 # which depends on another file that lives outside of its | |
| 117 # directory. This code covers that case :) | |
| 118 if matches[0]['href'].startswith('..'): | |
| 119 support_files = self.support_files(self.ref_doc) | |
| 120 test_info['refsupport'] = support_files | |
| 121 | |
| 122 elif self.is_jstest(): | |
| 123 test_info = {'test': self.filename, 'jstest': True} | |
| 124 elif self.options['all'] is True and not('-ref' in self.filename) and no
t('reference' in self.filename): | |
| 125 test_info = {'test': self.filename} | |
| 126 | |
| 127 return test_info | |
| 128 | |
| 129 def reference_links_of_type(self, reftest_type): | |
| 130 return self.test_doc.findAll(rel=reftest_type) | |
| 131 | |
| 132 def is_jstest(self): | |
| 133 """Returns whether the file appears to be a jstest, by searching for usa
ge of W3C-style testharness paths.""" | |
| 134 return bool(self.test_doc.find(src=re.compile('[\'\"/]?/resources/testha
rness'))) | |
| 135 | |
| 136 def support_files(self, doc): | |
| 137 """ Searches the file for all paths specified in url()'s, href or src at
tributes.""" | |
| 138 support_files = [] | |
| 139 | |
| 140 if doc is None: | |
| 141 return support_files | |
| 142 | |
| 143 elements_with_src_attributes = doc.findAll(src=re.compile('.*')) | |
| 144 elements_with_href_attributes = doc.findAll(href=re.compile('.*')) | |
| 145 | |
| 146 url_pattern = re.compile('url\(.*\)') | |
| 147 urls = [] | |
| 148 for url in doc.findAll(text=url_pattern): | |
| 149 url = re.search(url_pattern, url) | |
| 150 url = re.sub('url\([\'\"]?', '', url.group(0)) | |
| 151 url = re.sub('[\'\"]?\)', '', url) | |
| 152 urls.append(url) | |
| 153 | |
| 154 src_paths = [src_tag['src'] for src_tag in elements_with_src_attributes] | |
| 155 href_paths = [href_tag['href'] for href_tag in elements_with_href_attrib
utes] | |
| 156 | |
| 157 paths = src_paths + href_paths + urls | |
| 158 for path in paths: | |
| 159 if not(path.startswith('http:')) and not(path.startswith('mailto:'))
: | |
| 160 support_files.append(path) | |
| 161 | |
| 162 return support_files | |
| OLD | NEW |