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