blob: 172e44c936f47d8765c1c7a9babd18e11876f37a [file] [log] [blame]
kbr@google.coma5e8b2b2013-02-22 21:20:57 +00001# Copyright (C) 2013 Google 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 are
5# met:
6#
7# * Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9# * Redistributions in binary form must reproduce the above
10# copyright notice, this list of conditions and the following disclaimer
11# in the documentation and/or other materials provided with the
12# distribution.
13# * Neither the name of Google Inc. nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29"""generates webgl layout tests from the Khronos WebGL Conformance Tests"""
30
31# To use this, get a copy of the WebGL conformance tests then run this script
32# eg.
33#
34# cd ~/temp
35# git clone git://github.com/KhronosGroup/WebGL.git
36# cd ~/WebKit/LayoutTests/webgl
37# python generate-webgl-tests.py -w ~/temp/WebGL/sdk/tests -e
38#
39# Now check run the LayoutTests, update TestExpectations and check in the
40# result.
41
42import copy
43import os
44import os.path
45import sys
46import re
47import json
48import shutil
49from optparse import OptionParser
50
51if sys.version < '2.6':
52 print 'Wrong Python Version !!!: Need >= 2.6'
53 sys.exit(1)
54
55
56GLOBAL_OPTIONS = {
57 # version use. Tests at or below this will be included.
achristensen@apple.com4f814112018-06-13 00:27:15 +000058 "version": "2.0.0",
kbr@google.coma5e8b2b2013-02-22 21:20:57 +000059
60 # version used for unlabled tests
achristensen@apple.com4f814112018-06-13 00:27:15 +000061 "default-version": "2.0",
kbr@google.coma5e8b2b2013-02-22 21:20:57 +000062
63 # If set, the version we require. Tests below this will be ignored.
roger_fong@apple.com6d631f72014-12-04 02:32:40 +000064 "min-version": "1.0.3",
kbr@google.coma5e8b2b2013-02-22 21:20:57 +000065}
66
67
68def ReadFile(filename):
69 """Reads a file as a string"""
70 file = open(filename, "r")
71 data = file.read()
72 file.close()
73 return data
74
75
76def WriteFile(filename, data):
77 """Writes a string as a file"""
78 print "Writing: ", filename
79 dirname = os.path.dirname(filename)
80 if not os.path.exists(dirname):
81 os.makedirs(dirname)
82 file = open(filename, "wb")
83 file.write(data)
84 file.close()
85
86
87def CopyTree(src, dst, ignore=None):
88 """Recursively copy a directory tree"""
89 names = os.listdir(src)
90 if ignore is not None:
91 ignored_names = ignore(src, names)
92 else:
93 ignored_names = set()
94
95 if not os.path.exists(dst):
96 os.makedirs(dst)
97 errors = []
98 for name in names:
99 if name in ignored_names:
100 continue
101 srcname = os.path.join(src, name)
102 dstname = os.path.join(dst, name)
103 try:
104 if os.path.isdir(srcname):
105 CopyTree(srcname, dstname, ignore)
106 else:
107 # Will raise a SpecialFileError for unsupported file types
108 shutil.copyfile(srcname, dstname)
109 # catch the Error from the recursive copytree so that we can
110 # continue with other files
111 except Error, err:
112 errors.extend(err.args[0])
113 except EnvironmentError, why:
114 errors.append((srcname, dstname, str(why)))
115 if errors:
116 raise Error, errors
117
118
119def FileReader(filename):
120 """A File generator that returns only non empty, non comment lines"""
121 file = open(filename, "r")
122 lines = file.readlines()
123 file.close()
124 for line_number, line in enumerate(lines):
125 line = line.strip()
126 if (len(line) > 0 and
127 not line.startswith("#") and
128 not line.startswith(";") and
129 not line.startswith("//")):
130 yield line_number + 1, line
131
132
133def GreaterThanOrEqualToVersion(have, want):
134 """Compares to version strings"""
135 have = have.split(" ")[0].split(".")
136 want = want.split(" ")[0].split(".")
137 for ndx, want_str in enumerate(want):
138 want_num = int(want_str)
139 have_num = 0
140 if ndx < len(have):
141 have_num = int(have[ndx])
142 if have_num < want_num:
143 return False
achristensen@apple.com4f814112018-06-13 00:27:15 +0000144 if have_num >= want_num:
145 return True
kbr@google.coma5e8b2b2013-02-22 21:20:57 +0000146 return True
147
148
149def GetTestList(list_filename, dest_dir, hierarchical_options):
150 global GLOBAL_OPTIONS
151 tests = []
152 prefix = os.path.dirname(list_filename)
153 for line_number, line in FileReader(list_filename):
154 args = line.split()
155 test_options = {}
156 non_options = []
157 use_test = True
158 while len(args):
159 arg = args.pop(0)
160 if arg.startswith("-"):
161 if not arg.startswith("--"):
162 raise "%s:%d bad option" % (list_filename, line_number)
163 option = arg[2:]
164 if option == 'slow':
165 pass
roger_fong@apple.com6d631f72014-12-04 02:32:40 +0000166 elif option == 'min-version' or option == "max-version":
kbr@google.coma5e8b2b2013-02-22 21:20:57 +0000167 test_options[option] = args.pop(0)
168 else:
roger_fong@apple.com6d631f72014-12-04 02:32:40 +0000169 raise Exception("%s:%d unknown option '%s'" % (list_filename, line_number, arg))
kbr@google.coma5e8b2b2013-02-22 21:20:57 +0000170 else:
171 non_options.append(arg)
172 url = os.path.join(prefix, " ".join(non_options))
173
174 if not url.endswith(".txt"):
175 if "min-version" in test_options:
176 min_version = test_options["min-version"]
177 else:
178 min_version = hierarchical_options["default-version"]
179
180 if "min-version" in GLOBAL_OPTIONS:
181 use_test = GreaterThanOrEqualToVersion(min_version, GLOBAL_OPTIONS["min-version"])
182 else:
183 use_test = GreaterThanOrEqualToVersion(GLOBAL_OPTIONS["version"], min_version)
184
185 if not use_test:
186 continue
187
188 if url.endswith(".txt"):
189 if "min-version" in test_options:
190 hierarchical_options["default-version"] = test_options["min-version"]
191 tests = tests + GetTestList(
192 os.path.join(prefix, url), dest_dir, copy.copy(hierarchical_options))
193 else:
194 tests.append({"url": url})
195 return tests
196
197
198def main(argv):
199 """This is the main function."""
200 global GLOBAL_OPTIONS
201
202 parser = OptionParser()
203 parser.add_option(
204 "-v", "--verbose", action="store_true",
205 help="prints more output.")
206 parser.add_option(
207 "-w", "--webgl-conformance-test", dest="source_dir",
208 help="path to webgl conformance tests. REQUIRED")
209 parser.add_option(
210 "-n", "--no-copy", action="store_true",
211 help="do not copy tests")
212 parser.add_option(
213 "-e", "--generate-expectations", action="store_true",
214 help="generatet the test expectations")
215
216 (options, args) = parser.parse_args(args=argv)
217
218 if not options.source_dir:
219 parser.print_help()
220 return 1
221
222 os.chdir(os.path.dirname(__file__) or '.')
223
224 source_dir = options.source_dir;
225 webgl_tests_dir = "resources/webgl_test_files"
226 base_path = "."
227
228 # copy all the files from the WebGL conformance tests.
229 if not options.no_copy:
230 CopyTree(
231 source_dir, webgl_tests_dir, shutil.ignore_patterns(
232 '.git', '*.pyc', 'tmp*'))
233
234 test_template = ReadFile("resources/webgl-wrapper-template.html")
235 expectation_template = ReadFile("resources/webgl-expectation-template.txt")
236
237 # generate wrappers for all the tests
238 tests = GetTestList(os.path.join(source_dir, "00_test_list.txt"), ".",
239 copy.copy(GLOBAL_OPTIONS))
240
241 for test in tests:
242 url = os.path.relpath(test["url"], source_dir)
243 dst = url
244 dst_dir = os.path.dirname(dst)
245 src = os.path.relpath(os.path.join(webgl_tests_dir, url), dst_dir).replace("\\", "/")
246 base_url = os.path.relpath(base_path, dst_dir).replace("\\", "/")
247 subs = {
248 "url": src,
249 "url_name": os.path.basename(url),
250 "base_url": base_url,
251 }
252 WriteFile(dst, test_template % subs)
253 if options.generate_expectations:
254 expectation_filename = os.path.splitext(dst)[0] + "-expected.txt"
255 WriteFile(expectation_filename, expectation_template % subs)
256
257
258
259if __name__ == '__main__':
260 sys.exit(main(sys.argv[1:]))
261
262
263
264
265