Blame googlemock/scripts/fuse_gmock_files.py

Packit bd1cd8
#!/usr/bin/env python
Packit bd1cd8
#
Packit bd1cd8
# Copyright 2009, Google Inc.
Packit bd1cd8
# All rights reserved.
Packit bd1cd8
#
Packit bd1cd8
# Redistribution and use in source and binary forms, with or without
Packit bd1cd8
# modification, are permitted provided that the following conditions are
Packit bd1cd8
# met:
Packit bd1cd8
#
Packit bd1cd8
#     * Redistributions of source code must retain the above copyright
Packit bd1cd8
# notice, this list of conditions and the following disclaimer.
Packit bd1cd8
#     * Redistributions in binary form must reproduce the above
Packit bd1cd8
# copyright notice, this list of conditions and the following disclaimer
Packit bd1cd8
# in the documentation and/or other materials provided with the
Packit bd1cd8
# distribution.
Packit bd1cd8
#     * Neither the name of Google Inc. nor the names of its
Packit bd1cd8
# contributors may be used to endorse or promote products derived from
Packit bd1cd8
# this software without specific prior written permission.
Packit bd1cd8
#
Packit bd1cd8
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit bd1cd8
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit bd1cd8
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit bd1cd8
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit bd1cd8
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit bd1cd8
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit bd1cd8
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit bd1cd8
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit bd1cd8
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit bd1cd8
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit bd1cd8
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit bd1cd8
Packit bd1cd8
"""fuse_gmock_files.py v0.1.0
Packit bd1cd8
Fuses Google Mock and Google Test source code into two .h files and a .cc file.
Packit bd1cd8
Packit bd1cd8
SYNOPSIS
Packit bd1cd8
       fuse_gmock_files.py [GMOCK_ROOT_DIR] OUTPUT_DIR
Packit bd1cd8
Packit bd1cd8
       Scans GMOCK_ROOT_DIR for Google Mock and Google Test source
Packit bd1cd8
       code, assuming Google Test is in the GMOCK_ROOT_DIR/../googletest
Packit bd1cd8
       directory, and generates three files:
Packit bd1cd8
       OUTPUT_DIR/gtest/gtest.h, OUTPUT_DIR/gmock/gmock.h, and
Packit bd1cd8
       OUTPUT_DIR/gmock-gtest-all.cc.  Then you can build your tests
Packit bd1cd8
       by adding OUTPUT_DIR to the include search path and linking
Packit bd1cd8
       with OUTPUT_DIR/gmock-gtest-all.cc.  These three files contain
Packit bd1cd8
       everything you need to use Google Mock.  Hence you can
Packit bd1cd8
       "install" Google Mock by copying them to wherever you want.
Packit bd1cd8
Packit bd1cd8
       GMOCK_ROOT_DIR can be omitted and defaults to the parent
Packit bd1cd8
       directory of the directory holding this script.
Packit bd1cd8
Packit bd1cd8
EXAMPLES
Packit bd1cd8
       ./fuse_gmock_files.py fused_gmock
Packit bd1cd8
       ./fuse_gmock_files.py path/to/unpacked/gmock fused_gmock
Packit bd1cd8
Packit bd1cd8
This tool is experimental.  In particular, it assumes that there is no
Packit bd1cd8
conditional inclusion of Google Mock or Google Test headers.  Please
Packit bd1cd8
report any problems to googlemock@googlegroups.com.  You can read
Packit bd1cd8
http://code.google.com/p/googlemock/wiki/CookBook for more
Packit bd1cd8
information.
Packit bd1cd8
"""
Packit bd1cd8
Packit bd1cd8
__author__ = 'wan@google.com (Zhanyong Wan)'
Packit bd1cd8
Packit bd1cd8
import os
Packit bd1cd8
import re
Packit bd1cd8
import sets
Packit bd1cd8
import sys
Packit bd1cd8
Packit bd1cd8
# We assume that this file is in the scripts/ directory in the Google
Packit bd1cd8
# Mock root directory.
Packit bd1cd8
DEFAULT_GMOCK_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
Packit bd1cd8
Packit bd1cd8
# We need to call into googletest/scripts/fuse_gtest_files.py.
Packit bd1cd8
sys.path.append(os.path.join(DEFAULT_GMOCK_ROOT_DIR, '../googletest/scripts'))
Packit bd1cd8
import fuse_gtest_files
Packit bd1cd8
gtest = fuse_gtest_files
Packit bd1cd8
Packit bd1cd8
# Regex for matching '#include "gmock/..."'.
Packit bd1cd8
INCLUDE_GMOCK_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(gmock/.+)"')
Packit bd1cd8
Packit bd1cd8
# Where to find the source seed files.
Packit bd1cd8
GMOCK_H_SEED = 'include/gmock/gmock.h'
Packit bd1cd8
GMOCK_ALL_CC_SEED = 'src/gmock-all.cc'
Packit bd1cd8
Packit bd1cd8
# Where to put the generated files.
Packit bd1cd8
GTEST_H_OUTPUT = 'gtest/gtest.h'
Packit bd1cd8
GMOCK_H_OUTPUT = 'gmock/gmock.h'
Packit bd1cd8
GMOCK_GTEST_ALL_CC_OUTPUT = 'gmock-gtest-all.cc'
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
def GetGTestRootDir(gmock_root):
Packit bd1cd8
  """Returns the root directory of Google Test."""
Packit bd1cd8
Packit bd1cd8
  return os.path.join(gmock_root, '../googletest')
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
def ValidateGMockRootDir(gmock_root):
Packit bd1cd8
  """Makes sure gmock_root points to a valid gmock root directory.
Packit bd1cd8
Packit bd1cd8
  The function aborts the program on failure.
Packit bd1cd8
  """
Packit bd1cd8
Packit bd1cd8
  gtest.ValidateGTestRootDir(GetGTestRootDir(gmock_root))
Packit bd1cd8
  gtest.VerifyFileExists(gmock_root, GMOCK_H_SEED)
Packit bd1cd8
  gtest.VerifyFileExists(gmock_root, GMOCK_ALL_CC_SEED)
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
def ValidateOutputDir(output_dir):
Packit bd1cd8
  """Makes sure output_dir points to a valid output directory.
Packit bd1cd8
Packit bd1cd8
  The function aborts the program on failure.
Packit bd1cd8
  """
Packit bd1cd8
Packit bd1cd8
  gtest.VerifyOutputFile(output_dir, gtest.GTEST_H_OUTPUT)
Packit bd1cd8
  gtest.VerifyOutputFile(output_dir, GMOCK_H_OUTPUT)
Packit bd1cd8
  gtest.VerifyOutputFile(output_dir, GMOCK_GTEST_ALL_CC_OUTPUT)
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
def FuseGMockH(gmock_root, output_dir):
Packit bd1cd8
  """Scans folder gmock_root to generate gmock/gmock.h in output_dir."""
Packit bd1cd8
Packit bd1cd8
  output_file = file(os.path.join(output_dir, GMOCK_H_OUTPUT), 'w')
Packit bd1cd8
  processed_files = sets.Set()  # Holds all gmock headers we've processed.
Packit bd1cd8
Packit bd1cd8
  def ProcessFile(gmock_header_path):
Packit bd1cd8
    """Processes the given gmock header file."""
Packit bd1cd8
Packit bd1cd8
    # We don't process the same header twice.
Packit bd1cd8
    if gmock_header_path in processed_files:
Packit bd1cd8
      return
Packit bd1cd8
Packit bd1cd8
    processed_files.add(gmock_header_path)
Packit bd1cd8
Packit bd1cd8
    # Reads each line in the given gmock header.
Packit bd1cd8
    for line in file(os.path.join(gmock_root, gmock_header_path), 'r'):
Packit bd1cd8
      m = INCLUDE_GMOCK_FILE_REGEX.match(line)
Packit bd1cd8
      if m:
Packit bd1cd8
        # It's '#include "gmock/..."' - let's process it recursively.
Packit bd1cd8
        ProcessFile('include/' + m.group(1))
Packit bd1cd8
      else:
Packit bd1cd8
        m = gtest.INCLUDE_GTEST_FILE_REGEX.match(line)
Packit bd1cd8
        if m:
Packit bd1cd8
          # It's '#include "gtest/foo.h"'.  We translate it to
Packit bd1cd8
          # "gtest/gtest.h", regardless of what foo is, since all
Packit bd1cd8
          # gtest headers are fused into gtest/gtest.h.
Packit bd1cd8
Packit bd1cd8
          # There is no need to #include gtest.h twice.
Packit bd1cd8
          if not gtest.GTEST_H_SEED in processed_files:
Packit bd1cd8
            processed_files.add(gtest.GTEST_H_SEED)
Packit bd1cd8
            output_file.write('#include "%s"\n' % (gtest.GTEST_H_OUTPUT,))
Packit bd1cd8
        else:
Packit bd1cd8
          # Otherwise we copy the line unchanged to the output file.
Packit bd1cd8
          output_file.write(line)
Packit bd1cd8
Packit bd1cd8
  ProcessFile(GMOCK_H_SEED)
Packit bd1cd8
  output_file.close()
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
def FuseGMockAllCcToFile(gmock_root, output_file):
Packit bd1cd8
  """Scans folder gmock_root to fuse gmock-all.cc into output_file."""
Packit bd1cd8
Packit bd1cd8
  processed_files = sets.Set()
Packit bd1cd8
Packit bd1cd8
  def ProcessFile(gmock_source_file):
Packit bd1cd8
    """Processes the given gmock source file."""
Packit bd1cd8
Packit bd1cd8
    # We don't process the same #included file twice.
Packit bd1cd8
    if gmock_source_file in processed_files:
Packit bd1cd8
      return
Packit bd1cd8
Packit bd1cd8
    processed_files.add(gmock_source_file)
Packit bd1cd8
Packit bd1cd8
    # Reads each line in the given gmock source file.
Packit bd1cd8
    for line in file(os.path.join(gmock_root, gmock_source_file), 'r'):
Packit bd1cd8
      m = INCLUDE_GMOCK_FILE_REGEX.match(line)
Packit bd1cd8
      if m:
Packit bd1cd8
        # It's '#include "gmock/foo.h"'.  We treat it as '#include
Packit bd1cd8
        # "gmock/gmock.h"', as all other gmock headers are being fused
Packit bd1cd8
        # into gmock.h and cannot be #included directly.
Packit bd1cd8
Packit bd1cd8
        # There is no need to #include "gmock/gmock.h" more than once.
Packit bd1cd8
        if not GMOCK_H_SEED in processed_files:
Packit bd1cd8
          processed_files.add(GMOCK_H_SEED)
Packit bd1cd8
          output_file.write('#include "%s"\n' % (GMOCK_H_OUTPUT,))
Packit bd1cd8
      else:
Packit bd1cd8
        m = gtest.INCLUDE_GTEST_FILE_REGEX.match(line)
Packit bd1cd8
        if m:
Packit bd1cd8
          # It's '#include "gtest/..."'.
Packit bd1cd8
          # There is no need to #include gtest.h as it has been
Packit bd1cd8
          # #included by gtest-all.cc.
Packit bd1cd8
          pass
Packit bd1cd8
        else:
Packit bd1cd8
          m = gtest.INCLUDE_SRC_FILE_REGEX.match(line)
Packit bd1cd8
          if m:
Packit bd1cd8
            # It's '#include "src/foo"' - let's process it recursively.
Packit bd1cd8
            ProcessFile(m.group(1))
Packit bd1cd8
          else:
Packit bd1cd8
            # Otherwise we copy the line unchanged to the output file.
Packit bd1cd8
            output_file.write(line)
Packit bd1cd8
Packit bd1cd8
  ProcessFile(GMOCK_ALL_CC_SEED)
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
def FuseGMockGTestAllCc(gmock_root, output_dir):
Packit bd1cd8
  """Scans folder gmock_root to generate gmock-gtest-all.cc in output_dir."""
Packit bd1cd8
Packit bd1cd8
  output_file = file(os.path.join(output_dir, GMOCK_GTEST_ALL_CC_OUTPUT), 'w')
Packit bd1cd8
  # First, fuse gtest-all.cc into gmock-gtest-all.cc.
Packit bd1cd8
  gtest.FuseGTestAllCcToFile(GetGTestRootDir(gmock_root), output_file)
Packit bd1cd8
  # Next, append fused gmock-all.cc to gmock-gtest-all.cc.
Packit bd1cd8
  FuseGMockAllCcToFile(gmock_root, output_file)
Packit bd1cd8
  output_file.close()
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
def FuseGMock(gmock_root, output_dir):
Packit bd1cd8
  """Fuses gtest.h, gmock.h, and gmock-gtest-all.h."""
Packit bd1cd8
Packit bd1cd8
  ValidateGMockRootDir(gmock_root)
Packit bd1cd8
  ValidateOutputDir(output_dir)
Packit bd1cd8
Packit bd1cd8
  gtest.FuseGTestH(GetGTestRootDir(gmock_root), output_dir)
Packit bd1cd8
  FuseGMockH(gmock_root, output_dir)
Packit bd1cd8
  FuseGMockGTestAllCc(gmock_root, output_dir)
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
def main():
Packit bd1cd8
  argc = len(sys.argv)
Packit bd1cd8
  if argc == 2:
Packit bd1cd8
    # fuse_gmock_files.py OUTPUT_DIR
Packit bd1cd8
    FuseGMock(DEFAULT_GMOCK_ROOT_DIR, sys.argv[1])
Packit bd1cd8
  elif argc == 3:
Packit bd1cd8
    # fuse_gmock_files.py GMOCK_ROOT_DIR OUTPUT_DIR
Packit bd1cd8
    FuseGMock(sys.argv[1], sys.argv[2])
Packit bd1cd8
  else:
Packit bd1cd8
    print __doc__
Packit bd1cd8
    sys.exit(1)
Packit bd1cd8
Packit bd1cd8
Packit bd1cd8
if __name__ == '__main__':
Packit bd1cd8
  main()