1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/webrtc/trunk/testing/gtest/scripts/fuse_gtest_files.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,250 @@ 1.4 +#!/usr/bin/env python 1.5 +# 1.6 +# Copyright 2009, Google Inc. 1.7 +# All rights reserved. 1.8 +# 1.9 +# Redistribution and use in source and binary forms, with or without 1.10 +# modification, are permitted provided that the following conditions are 1.11 +# met: 1.12 +# 1.13 +# * Redistributions of source code must retain the above copyright 1.14 +# notice, this list of conditions and the following disclaimer. 1.15 +# * Redistributions in binary form must reproduce the above 1.16 +# copyright notice, this list of conditions and the following disclaimer 1.17 +# in the documentation and/or other materials provided with the 1.18 +# distribution. 1.19 +# * Neither the name of Google Inc. nor the names of its 1.20 +# contributors may be used to endorse or promote products derived from 1.21 +# this software without specific prior written permission. 1.22 +# 1.23 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.27 +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.28 +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.29 +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.30 +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.31 +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.32 +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.33 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 + 1.35 +"""fuse_gtest_files.py v0.2.0 1.36 +Fuses Google Test source code into a .h file and a .cc file. 1.37 + 1.38 +SYNOPSIS 1.39 + fuse_gtest_files.py [GTEST_ROOT_DIR] OUTPUT_DIR 1.40 + 1.41 + Scans GTEST_ROOT_DIR for Google Test source code, and generates 1.42 + two files: OUTPUT_DIR/gtest/gtest.h and OUTPUT_DIR/gtest/gtest-all.cc. 1.43 + Then you can build your tests by adding OUTPUT_DIR to the include 1.44 + search path and linking with OUTPUT_DIR/gtest/gtest-all.cc. These 1.45 + two files contain everything you need to use Google Test. Hence 1.46 + you can "install" Google Test by copying them to wherever you want. 1.47 + 1.48 + GTEST_ROOT_DIR can be omitted and defaults to the parent 1.49 + directory of the directory holding this script. 1.50 + 1.51 +EXAMPLES 1.52 + ./fuse_gtest_files.py fused_gtest 1.53 + ./fuse_gtest_files.py path/to/unpacked/gtest fused_gtest 1.54 + 1.55 +This tool is experimental. In particular, it assumes that there is no 1.56 +conditional inclusion of Google Test headers. Please report any 1.57 +problems to googletestframework@googlegroups.com. You can read 1.58 +http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide for 1.59 +more information. 1.60 +""" 1.61 + 1.62 +__author__ = 'wan@google.com (Zhanyong Wan)' 1.63 + 1.64 +import os 1.65 +import re 1.66 +import sets 1.67 +import sys 1.68 + 1.69 +# We assume that this file is in the scripts/ directory in the Google 1.70 +# Test root directory. 1.71 +DEFAULT_GTEST_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..') 1.72 + 1.73 +# Regex for matching '#include "gtest/..."'. 1.74 +INCLUDE_GTEST_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(gtest/.+)"') 1.75 + 1.76 +# Regex for matching '#include "src/..."'. 1.77 +INCLUDE_SRC_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(src/.+)"') 1.78 + 1.79 +# Where to find the source seed files. 1.80 +GTEST_H_SEED = 'include/gtest/gtest.h' 1.81 +GTEST_SPI_H_SEED = 'include/gtest/gtest-spi.h' 1.82 +GTEST_ALL_CC_SEED = 'src/gtest-all.cc' 1.83 + 1.84 +# Where to put the generated files. 1.85 +GTEST_H_OUTPUT = 'gtest/gtest.h' 1.86 +GTEST_ALL_CC_OUTPUT = 'gtest/gtest-all.cc' 1.87 + 1.88 + 1.89 +def VerifyFileExists(directory, relative_path): 1.90 + """Verifies that the given file exists; aborts on failure. 1.91 + 1.92 + relative_path is the file path relative to the given directory. 1.93 + """ 1.94 + 1.95 + if not os.path.isfile(os.path.join(directory, relative_path)): 1.96 + print 'ERROR: Cannot find %s in directory %s.' % (relative_path, 1.97 + directory) 1.98 + print ('Please either specify a valid project root directory ' 1.99 + 'or omit it on the command line.') 1.100 + sys.exit(1) 1.101 + 1.102 + 1.103 +def ValidateGTestRootDir(gtest_root): 1.104 + """Makes sure gtest_root points to a valid gtest root directory. 1.105 + 1.106 + The function aborts the program on failure. 1.107 + """ 1.108 + 1.109 + VerifyFileExists(gtest_root, GTEST_H_SEED) 1.110 + VerifyFileExists(gtest_root, GTEST_ALL_CC_SEED) 1.111 + 1.112 + 1.113 +def VerifyOutputFile(output_dir, relative_path): 1.114 + """Verifies that the given output file path is valid. 1.115 + 1.116 + relative_path is relative to the output_dir directory. 1.117 + """ 1.118 + 1.119 + # Makes sure the output file either doesn't exist or can be overwritten. 1.120 + output_file = os.path.join(output_dir, relative_path) 1.121 + if os.path.exists(output_file): 1.122 + # TODO(wan@google.com): The following user-interaction doesn't 1.123 + # work with automated processes. We should provide a way for the 1.124 + # Makefile to force overwriting the files. 1.125 + print ('%s already exists in directory %s - overwrite it? (y/N) ' % 1.126 + (relative_path, output_dir)) 1.127 + answer = sys.stdin.readline().strip() 1.128 + if answer not in ['y', 'Y']: 1.129 + print 'ABORTED.' 1.130 + sys.exit(1) 1.131 + 1.132 + # Makes sure the directory holding the output file exists; creates 1.133 + # it and all its ancestors if necessary. 1.134 + parent_directory = os.path.dirname(output_file) 1.135 + if not os.path.isdir(parent_directory): 1.136 + os.makedirs(parent_directory) 1.137 + 1.138 + 1.139 +def ValidateOutputDir(output_dir): 1.140 + """Makes sure output_dir points to a valid output directory. 1.141 + 1.142 + The function aborts the program on failure. 1.143 + """ 1.144 + 1.145 + VerifyOutputFile(output_dir, GTEST_H_OUTPUT) 1.146 + VerifyOutputFile(output_dir, GTEST_ALL_CC_OUTPUT) 1.147 + 1.148 + 1.149 +def FuseGTestH(gtest_root, output_dir): 1.150 + """Scans folder gtest_root to generate gtest/gtest.h in output_dir.""" 1.151 + 1.152 + output_file = file(os.path.join(output_dir, GTEST_H_OUTPUT), 'w') 1.153 + processed_files = sets.Set() # Holds all gtest headers we've processed. 1.154 + 1.155 + def ProcessFile(gtest_header_path): 1.156 + """Processes the given gtest header file.""" 1.157 + 1.158 + # We don't process the same header twice. 1.159 + if gtest_header_path in processed_files: 1.160 + return 1.161 + 1.162 + processed_files.add(gtest_header_path) 1.163 + 1.164 + # Reads each line in the given gtest header. 1.165 + for line in file(os.path.join(gtest_root, gtest_header_path), 'r'): 1.166 + m = INCLUDE_GTEST_FILE_REGEX.match(line) 1.167 + if m: 1.168 + # It's '#include "gtest/..."' - let's process it recursively. 1.169 + ProcessFile('include/' + m.group(1)) 1.170 + else: 1.171 + # Otherwise we copy the line unchanged to the output file. 1.172 + output_file.write(line) 1.173 + 1.174 + ProcessFile(GTEST_H_SEED) 1.175 + output_file.close() 1.176 + 1.177 + 1.178 +def FuseGTestAllCcToFile(gtest_root, output_file): 1.179 + """Scans folder gtest_root to generate gtest/gtest-all.cc in output_file.""" 1.180 + 1.181 + processed_files = sets.Set() 1.182 + 1.183 + def ProcessFile(gtest_source_file): 1.184 + """Processes the given gtest source file.""" 1.185 + 1.186 + # We don't process the same #included file twice. 1.187 + if gtest_source_file in processed_files: 1.188 + return 1.189 + 1.190 + processed_files.add(gtest_source_file) 1.191 + 1.192 + # Reads each line in the given gtest source file. 1.193 + for line in file(os.path.join(gtest_root, gtest_source_file), 'r'): 1.194 + m = INCLUDE_GTEST_FILE_REGEX.match(line) 1.195 + if m: 1.196 + if 'include/' + m.group(1) == GTEST_SPI_H_SEED: 1.197 + # It's '#include "gtest/gtest-spi.h"'. This file is not 1.198 + # #included by "gtest/gtest.h", so we need to process it. 1.199 + ProcessFile(GTEST_SPI_H_SEED) 1.200 + else: 1.201 + # It's '#include "gtest/foo.h"' where foo is not gtest-spi. 1.202 + # We treat it as '#include "gtest/gtest.h"', as all other 1.203 + # gtest headers are being fused into gtest.h and cannot be 1.204 + # #included directly. 1.205 + 1.206 + # There is no need to #include "gtest/gtest.h" more than once. 1.207 + if not GTEST_H_SEED in processed_files: 1.208 + processed_files.add(GTEST_H_SEED) 1.209 + output_file.write('#include "%s"\n' % (GTEST_H_OUTPUT,)) 1.210 + else: 1.211 + m = INCLUDE_SRC_FILE_REGEX.match(line) 1.212 + if m: 1.213 + # It's '#include "src/foo"' - let's process it recursively. 1.214 + ProcessFile(m.group(1)) 1.215 + else: 1.216 + output_file.write(line) 1.217 + 1.218 + ProcessFile(GTEST_ALL_CC_SEED) 1.219 + 1.220 + 1.221 +def FuseGTestAllCc(gtest_root, output_dir): 1.222 + """Scans folder gtest_root to generate gtest/gtest-all.cc in output_dir.""" 1.223 + 1.224 + output_file = file(os.path.join(output_dir, GTEST_ALL_CC_OUTPUT), 'w') 1.225 + FuseGTestAllCcToFile(gtest_root, output_file) 1.226 + output_file.close() 1.227 + 1.228 + 1.229 +def FuseGTest(gtest_root, output_dir): 1.230 + """Fuses gtest.h and gtest-all.cc.""" 1.231 + 1.232 + ValidateGTestRootDir(gtest_root) 1.233 + ValidateOutputDir(output_dir) 1.234 + 1.235 + FuseGTestH(gtest_root, output_dir) 1.236 + FuseGTestAllCc(gtest_root, output_dir) 1.237 + 1.238 + 1.239 +def main(): 1.240 + argc = len(sys.argv) 1.241 + if argc == 2: 1.242 + # fuse_gtest_files.py OUTPUT_DIR 1.243 + FuseGTest(DEFAULT_GTEST_ROOT_DIR, sys.argv[1]) 1.244 + elif argc == 3: 1.245 + # fuse_gtest_files.py GTEST_ROOT_DIR OUTPUT_DIR 1.246 + FuseGTest(sys.argv[1], sys.argv[2]) 1.247 + else: 1.248 + print __doc__ 1.249 + sys.exit(1) 1.250 + 1.251 + 1.252 +if __name__ == '__main__': 1.253 + main()