blob: 27c7fa2295b155a0c7c58b65d71b04b266ec14d4 [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.
roger_fong@apple.com6d631f72014-12-04 02:32:40 +000058 "version": "1.0.3",
kbr@google.coma5e8b2b2013-02-22 21:20:57 +000059
60 # version used for unlabled tests
61 "default-version": "1.0",
62
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
144 return True
145
146
147def GetTestList(list_filename, dest_dir, hierarchical_options):
148 global GLOBAL_OPTIONS
149 tests = []
150 prefix = os.path.dirname(list_filename)
151 for line_number, line in FileReader(list_filename):
152 args = line.split()
153 test_options = {}
154 non_options = []
155 use_test = True
156 while len(args):
157 arg = args.pop(0)
158 if arg.startswith("-"):
159 if not arg.startswith("--"):
160 raise "%s:%d bad option" % (list_filename, line_number)
161 option = arg[2:]
162 if option == 'slow':
163 pass
roger_fong@apple.com6d631f72014-12-04 02:32:40 +0000164 elif option == 'min-version' or option == "max-version":
kbr@google.coma5e8b2b2013-02-22 21:20:57 +0000165 test_options[option] = args.pop(0)
166 else:
roger_fong@apple.com6d631f72014-12-04 02:32:40 +0000167 raise Exception("%s:%d unknown option '%s'" % (list_filename, line_number, arg))
kbr@google.coma5e8b2b2013-02-22 21:20:57 +0000168 else:
169 non_options.append(arg)
170 url = os.path.join(prefix, " ".join(non_options))
171
172 if not url.endswith(".txt"):
173 if "min-version" in test_options:
174 min_version = test_options["min-version"]
175 else:
176 min_version = hierarchical_options["default-version"]
177
178 if "min-version" in GLOBAL_OPTIONS:
179 use_test = GreaterThanOrEqualToVersion(min_version, GLOBAL_OPTIONS["min-version"])
180 else:
181 use_test = GreaterThanOrEqualToVersion(GLOBAL_OPTIONS["version"], min_version)
182
183 if not use_test:
184 continue
185
186 if url.endswith(".txt"):
187 if "min-version" in test_options:
188 hierarchical_options["default-version"] = test_options["min-version"]
189 tests = tests + GetTestList(
190 os.path.join(prefix, url), dest_dir, copy.copy(hierarchical_options))
191 else:
192 tests.append({"url": url})
193 return tests
194
195
196def main(argv):
197 """This is the main function."""
198 global GLOBAL_OPTIONS
199
200 parser = OptionParser()
201 parser.add_option(
202 "-v", "--verbose", action="store_true",
203 help="prints more output.")
204 parser.add_option(
205 "-w", "--webgl-conformance-test", dest="source_dir",
206 help="path to webgl conformance tests. REQUIRED")
207 parser.add_option(
208 "-n", "--no-copy", action="store_true",
209 help="do not copy tests")
210 parser.add_option(
211 "-e", "--generate-expectations", action="store_true",
212 help="generatet the test expectations")
213
214 (options, args) = parser.parse_args(args=argv)
215
216 if not options.source_dir:
217 parser.print_help()
218 return 1
219
220 os.chdir(os.path.dirname(__file__) or '.')
221
222 source_dir = options.source_dir;
223 webgl_tests_dir = "resources/webgl_test_files"
224 base_path = "."
225
226 # copy all the files from the WebGL conformance tests.
227 if not options.no_copy:
228 CopyTree(
229 source_dir, webgl_tests_dir, shutil.ignore_patterns(
230 '.git', '*.pyc', 'tmp*'))
231
232 test_template = ReadFile("resources/webgl-wrapper-template.html")
233 expectation_template = ReadFile("resources/webgl-expectation-template.txt")
234
235 # generate wrappers for all the tests
236 tests = GetTestList(os.path.join(source_dir, "00_test_list.txt"), ".",
237 copy.copy(GLOBAL_OPTIONS))
238
239 for test in tests:
240 url = os.path.relpath(test["url"], source_dir)
241 dst = url
242 dst_dir = os.path.dirname(dst)
243 src = os.path.relpath(os.path.join(webgl_tests_dir, url), dst_dir).replace("\\", "/")
244 base_url = os.path.relpath(base_path, dst_dir).replace("\\", "/")
245 subs = {
246 "url": src,
247 "url_name": os.path.basename(url),
248 "base_url": base_url,
249 }
250 WriteFile(dst, test_template % subs)
251 if options.generate_expectations:
252 expectation_filename = os.path.splitext(dst)[0] + "-expected.txt"
253 WriteFile(expectation_filename, expectation_template % subs)
254
255
256
257if __name__ == '__main__':
258 sys.exit(main(sys.argv[1:]))
259
260
261
262
263