1#!/usr/bin/env python 2 3# Copyright (C) 2010 Google Inc. 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# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 14# THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26from __future__ import with_statement 27 28import glob 29import logging 30import optparse 31import os 32import re 33import sys 34from webkitpy.common.checkout import scm 35 36_log = logging.getLogger("webkitpy.layout_tests." 37 "update-webgl-conformance-tests") 38 39 40def remove_first_line_comment(text): 41 return re.compile(r'^<!--.*?-->\s*', re.DOTALL).sub('', text) 42 43 44def translate_includes(text): 45 # Mapping of single filename to relative path under WebKit root. 46 # Assumption: these filenames are globally unique. 47 include_mapping = { 48 "js-test-style.css": "../../js/resources", 49 "js-test-pre.js": "../../js/resources", 50 "js-test-post.js": "../../js/resources", 51 "desktop-gl-constants.js": "resources", 52 } 53 54 for filename, path in include_mapping.items(): 55 search = r'(?:[^"\'= ]*/)?' + re.escape(filename) 56 # We use '/' instead of os.path.join in order to produce consistent 57 # output cross-platform. 58 replace = path + '/' + filename 59 text = re.sub(search, replace, text) 60 61 return text 62 63 64def translate_khronos_test(text): 65 """ 66 This method translates the contents of a Khronos test to a WebKit test. 67 """ 68 69 translateFuncs = [ 70 remove_first_line_comment, 71 translate_includes, 72 ] 73 74 for f in translateFuncs: 75 text = f(text) 76 77 return text 78 79 80def update_file(in_filename, out_dir): 81 # check in_filename exists 82 # check out_dir exists 83 out_filename = os.path.join(out_dir, os.path.basename(in_filename)) 84 85 _log.debug("Processing " + in_filename) 86 with open(in_filename, 'r') as in_file: 87 with open(out_filename, 'w') as out_file: 88 out_file.write(translate_khronos_test(in_file.read())) 89 90 91def update_directory(in_dir, out_dir): 92 for filename in glob.glob(os.path.join(in_dir, '*.html')): 93 update_file(os.path.join(in_dir, filename), out_dir) 94 95 96def default_out_dir(): 97 current_scm = scm.detect_scm_system(os.path.dirname(sys.argv[0])) 98 if not current_scm: 99 return os.getcwd() 100 root_dir = current_scm.checkout_root 101 if not root_dir: 102 return os.getcwd() 103 out_dir = os.path.join(root_dir, "LayoutTests/fast/canvas/webgl") 104 if os.path.isdir(out_dir): 105 return out_dir 106 return os.getcwd() 107 108 109def configure_logging(options): 110 """Configures the logging system.""" 111 log_fmt = '%(levelname)s: %(message)s' 112 log_datefmt = '%y%m%d %H:%M:%S' 113 log_level = logging.INFO 114 if options.verbose: 115 log_fmt = ('%(asctime)s %(filename)s:%(lineno)-4d %(levelname)s ' 116 '%(message)s') 117 log_level = logging.DEBUG 118 logging.basicConfig(level=log_level, format=log_fmt, 119 datefmt=log_datefmt) 120 121 122def option_parser(): 123 usage = "usage: %prog [options] (input file or directory)" 124 parser = optparse.OptionParser(usage=usage) 125 parser.add_option('-v', '--verbose', 126 action='store_true', 127 default=False, 128 help='include debug-level logging') 129 parser.add_option('-o', '--output', 130 action='store', 131 type='string', 132 default=default_out_dir(), 133 metavar='DIR', 134 help='specify an output directory to place files ' 135 'in [default: %default]') 136 return parser 137 138 139def main(): 140 parser = option_parser() 141 (options, args) = parser.parse_args() 142 configure_logging(options) 143 144 if len(args) == 0: 145 _log.error("Must specify an input directory or filename.") 146 parser.print_help() 147 return 1 148 149 in_name = args[0] 150 if os.path.isfile(in_name): 151 update_file(in_name, options.output) 152 elif os.path.isdir(in_name): 153 update_directory(in_name, options.output) 154 else: 155 _log.error("'%s' is not a directory or a file.", in_name) 156 return 2 157 158 return 0 159 160 161if __name__ == "__main__": 162 sys.exit(main()) 163