# Copyright (C) 2013 Google 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: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * 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. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "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 # OWNER OR CONTRIBUTORS 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. """generates webgl layout tests from the Khronos WebGL Conformance Tests""" # To use this, get a copy of the WebGL conformance tests then run this script # eg. # # cd ~/temp # git clone git://github.com/KhronosGroup/WebGL.git # cd ~/WebKit/LayoutTests/webgl # python generate-webgl-tests.py -w ~/temp/WebGL/sdk/tests -e # # Now check run the LayoutTests, update TestExpectations and check in the # result. import copy import os import os.path import sys import re import json import shutil from optparse import OptionParser if sys.version < '2.6': print 'Wrong Python Version !!!: Need >= 2.6' sys.exit(1) GLOBAL_OPTIONS = { # version use. Tests at or below this will be included. "version": "1.0.2", # version used for unlabled tests "default-version": "1.0", # If set, the version we require. Tests below this will be ignored. #"min-version": "1.0.2", } def ReadFile(filename): """Reads a file as a string""" file = open(filename, "r") data = file.read() file.close() return data def WriteFile(filename, data): """Writes a string as a file""" print "Writing: ", filename dirname = os.path.dirname(filename) if not os.path.exists(dirname): os.makedirs(dirname) file = open(filename, "wb") file.write(data) file.close() def CopyTree(src, dst, ignore=None): """Recursively copy a directory tree""" names = os.listdir(src) if ignore is not None: ignored_names = ignore(src, names) else: ignored_names = set() if not os.path.exists(dst): os.makedirs(dst) errors = [] for name in names: if name in ignored_names: continue srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: if os.path.isdir(srcname): CopyTree(srcname, dstname, ignore) else: # Will raise a SpecialFileError for unsupported file types shutil.copyfile(srcname, dstname) # catch the Error from the recursive copytree so that we can # continue with other files except Error, err: errors.extend(err.args[0]) except EnvironmentError, why: errors.append((srcname, dstname, str(why))) if errors: raise Error, errors def FileReader(filename): """A File generator that returns only non empty, non comment lines""" file = open(filename, "r") lines = file.readlines() file.close() for line_number, line in enumerate(lines): line = line.strip() if (len(line) > 0 and not line.startswith("#") and not line.startswith(";") and not line.startswith("//")): yield line_number + 1, line def GreaterThanOrEqualToVersion(have, want): """Compares to version strings""" have = have.split(" ")[0].split(".") want = want.split(" ")[0].split(".") for ndx, want_str in enumerate(want): want_num = int(want_str) have_num = 0 if ndx < len(have): have_num = int(have[ndx]) if have_num < want_num: return False return True def GetTestList(list_filename, dest_dir, hierarchical_options): global GLOBAL_OPTIONS tests = [] prefix = os.path.dirname(list_filename) for line_number, line in FileReader(list_filename): args = line.split() test_options = {} non_options = [] use_test = True while len(args): arg = args.pop(0) if arg.startswith("-"): if not arg.startswith("--"): raise "%s:%d bad option" % (list_filename, line_number) option = arg[2:] if option == 'slow': pass elif option == 'min-version': test_options[option] = args.pop(0) else: raise "%s:%d unknown option '%s'" % (list_filename, line_number, arg) else: non_options.append(arg) url = os.path.join(prefix, " ".join(non_options)) if not url.endswith(".txt"): if "min-version" in test_options: min_version = test_options["min-version"] else: min_version = hierarchical_options["default-version"] if "min-version" in GLOBAL_OPTIONS: use_test = GreaterThanOrEqualToVersion(min_version, GLOBAL_OPTIONS["min-version"]) else: use_test = GreaterThanOrEqualToVersion(GLOBAL_OPTIONS["version"], min_version) if not use_test: continue if url.endswith(".txt"): if "min-version" in test_options: hierarchical_options["default-version"] = test_options["min-version"] tests = tests + GetTestList( os.path.join(prefix, url), dest_dir, copy.copy(hierarchical_options)) else: tests.append({"url": url}) return tests def main(argv): """This is the main function.""" global GLOBAL_OPTIONS parser = OptionParser() parser.add_option( "-v", "--verbose", action="store_true", help="prints more output.") parser.add_option( "-w", "--webgl-conformance-test", dest="source_dir", help="path to webgl conformance tests. REQUIRED") parser.add_option( "-n", "--no-copy", action="store_true", help="do not copy tests") parser.add_option( "-e", "--generate-expectations", action="store_true", help="generatet the test expectations") (options, args) = parser.parse_args(args=argv) if not options.source_dir: parser.print_help() return 1 os.chdir(os.path.dirname(__file__) or '.') source_dir = options.source_dir; webgl_tests_dir = "resources/webgl_test_files" base_path = "." # copy all the files from the WebGL conformance tests. if not options.no_copy: CopyTree( source_dir, webgl_tests_dir, shutil.ignore_patterns( '.git', '*.pyc', 'tmp*')) test_template = ReadFile("resources/webgl-wrapper-template.html") expectation_template = ReadFile("resources/webgl-expectation-template.txt") # generate wrappers for all the tests tests = GetTestList(os.path.join(source_dir, "00_test_list.txt"), ".", copy.copy(GLOBAL_OPTIONS)) for test in tests: url = os.path.relpath(test["url"], source_dir) dst = url dst_dir = os.path.dirname(dst) src = os.path.relpath(os.path.join(webgl_tests_dir, url), dst_dir).replace("\\", "/") base_url = os.path.relpath(base_path, dst_dir).replace("\\", "/") subs = { "url": src, "url_name": os.path.basename(url), "base_url": base_url, } WriteFile(dst, test_template % subs) if options.generate_expectations: expectation_filename = os.path.splitext(dst)[0] + "-expected.txt" WriteFile(expectation_filename, expectation_template % subs) if __name__ == '__main__': sys.exit(main(sys.argv[1:]))