diff options
author | maruel@google.com <maruel@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-25 22:08:44 +0000 |
---|---|---|
committer | maruel@google.com <maruel@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-25 22:08:44 +0000 |
commit | de8d2667d6953abb31b7c5385ca718ad47adf6a1 (patch) | |
tree | 3d4499631bbf551dd81bb50b43452705b37d7bfb /tools/code_coverage | |
parent | c9ec45429c64884c35f83b74131c0e3ae5b2bbe9 (diff) | |
download | chromium_src-de8d2667d6953abb31b7c5385ca718ad47adf6a1.zip chromium_src-de8d2667d6953abb31b7c5385ca718ad47adf6a1.tar.gz chromium_src-de8d2667d6953abb31b7c5385ca718ad47adf6a1.tar.bz2 |
Wow, it's been a while since we cleaned EOL.
Ran dos2unix on *.cc, *.h, *.py and SCons*.*
Ran for /R /D %a in (*.*) do @if exist %a\.svn\. svn pset svn:eol-style LF %a\*.cc
Ran for /R /D %a in (*.*) do @if exist %a\.svn\. svn pset svn:eol-style LF %a\*.h
Ran for /R /D %a in (*.*) do @if exist %a\.svn\. svn pset svn:eol-style LF %a\*.py
Ran for /R /D %a in (*.*) do @if exist %a\.svn\. svn pset svn:eol-style LF %a\SCons*.*
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2611 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/code_coverage')
-rw-r--r-- | tools/code_coverage/coverage.py | 538 | ||||
-rw-r--r-- | tools/code_coverage/process_coverage.py | 466 |
2 files changed, 502 insertions, 502 deletions
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py index a805cd7..ca6cd17 100644 --- a/tools/code_coverage/coverage.py +++ b/tools/code_coverage/coverage.py @@ -1,269 +1,269 @@ -#!/bin/env python
-# Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-"""Module to setup and generate code coverage data
-
-This module first sets up the environment for code coverage, instruments the
-binaries, runs the tests and collects the code coverage data.
-
-
-Usage:
- coverage.py --upload=<upload_location>
- --revision=<revision_number>
- --src_root=<root_of_source_tree>
- [--tools_path=<tools_path>]
-"""
-
-import logging
-import optparse
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-
-import google.logging_utils
-import google.process_utils as proc
-
-
-# The list of binaries that will be instrumented for code coverage
-# TODO(niranjan): Add a complete list of binaries
-windows_binaries = ['unit_tests.exe',
- 'ui_tests.exe']
-
-# The list of tests that will be run
-#TODO(niranjan): Add more tests
-windows_tests = ['unit_tests.exe',
- 'ui_tests.exe']
-
-
-def IsWindows():
- """Checks if the current platform is Windows.
- """
- return sys.platform[:3] == 'win'
-
-
-class Coverage(object):
- """Class to set up and generate code coverage.
-
- This class contains methods that are useful to set up the environment for
- code coverage.
-
- Attributes:
- instrumented: A boolean indicating if all the binaries have been
- instrumented.
- """
-
- def __init__(self,
- revision,
- vsts_path = None,
- lcov_converter_path = None):
- google.logging_utils.config_root()
- self.revision = revision
- self.instrumented = False
- self.vsts_path = vsts_path
- self.lcov_converter_path = lcov_converter_path
- self._dir = None
-
-
- def SetUp(self, binaries):
- """Set up the platform specific environment and instrument the binaries for
- coverage.
-
- This method sets up the environment, instruments all the compiled binaries
- and sets up the code coverage counters.
-
- Args:
- binaries: List of binaries that need to be instrumented.
-
- Returns:
- Path of the file containing code coverage data on successful
- instrumentation.
- None on error.
- """
- if self.instrumented:
- logging.error('Binaries already instrumented')
- return None
- coverage_file = None
- if IsWindows():
- # Stop all previous instance of VSPerfMon counters
- counters_command = ('%s -shutdown' %
- (os.path.join(self.vsts_path, 'vsperfcmd.exe')))
- (retcode, output) = proc.RunCommandFull(counters_command,
- collect_output=True)
- # TODO(niranjan): Add a check that to verify that the binaries were built
- # using the /PROFILE linker flag.
- if self.vsts_path == None or self.lcov_converter_path == None:
- return None
- # Remove trailing slashes
- self.vsts_path = self.vsts_path.rstrip('\\')
- instrument_command = '%s /COVERAGE ' % (os.path.join(self.vsts_path,
- 'vsinstr.exe'))
- for binary in binaries:
- logging.info('binary = %s' % (binary))
- logging.info('instrument_command = %s' % (instrument_command))
- # Instrument each binary in the list
- (retcode, output) = proc.RunCommandFull(instrument_command + binary,
- collect_output=True)
- # Check if the file has been instrumented correctly.
- if output.pop().rfind('Successfully instrumented') == -1:
- logging.error('Error instrumenting %s' % (binary))
- return None
-
- # Generate the file name for the coverage results
- self._dir = tempfile.mkdtemp()
- coverage_file = os.path.join(self._dir, 'chrome_win32_%s.coverage' %
- (self.revision))
- logging.info('.coverage file: %s' % (coverage_file))
-
- # After all the binaries have been instrumented, we start the counters.
- counters_command = ('%s -start:coverage -output:%s' %
- (os.path.join(self.vsts_path, 'vsperfcmd.exe'),
- coverage_file))
- # Here we use subprocess.call() instead of the RunCommandFull because the
- # VSPerfCmd spawns another process before terminating and this confuses
- # the subprocess.Popen() used by RunCommandFull.
- retcode = subprocess.call(counters_command)
- # TODO(niranjan): Check whether the counters have been started
- # successfully.
-
- # We are now ready to run tests and measure code coverage.
- self.instrumented = True
- else:
- return None
- return coverage_file
-
-
- def TearDown(self):
- """Tear down method.
-
- This method shuts down the counters, and cleans up all the intermediate
- artifacts.
- """
- if self.instrumented == False:
- return
-
- if IsWindows():
- # Stop counters
- counters_command = ('%s -shutdown' %
- (os.path.join(self.vsts_path, 'vsperfcmd.exe')))
- (retcode, output) = proc.RunCommandFull(counters_command,
- collect_output=True)
- logging.info('Counters shut down: %s' % (output))
- # TODO(niranjan): Revert the instrumented binaries to their original
- # versions.
- else:
- return
- # Delete all the temp files and folders
- if self._dir != None:
- shutil.rmtree(self._dir, ignore_errors=True)
- logging.info('Cleaned up temporary files and folders')
- # Reset the instrumented flag.
- self.instrumented = False
-
-
- def Upload(self, coverage_file, upload_path, sym_path=None, src_root=None):
- """Upload the results to the dashboard.
-
- This method uploads the coverage data to a dashboard where it will be
- processed. On Windows, this method will first convert the .coverage file to
- the lcov format. This method needs to be called before the TearDown method.
-
- Args:
- coverage_file: The coverage data file to upload.
- upload_path: Destination where the coverage data will be processed.
- sym_path: Symbol path for the build (Win32 only)
- src_root: Root folder of the source tree (Win32 only)
-
- Returns:
- True on success.
- False on failure.
- """
- if self.IsWindows():
- # Stop counters
- counters_command = ('%s -shutdown' %
- (os.path.join(self.vsts_path, 'vsperfcmd.exe')))
- (retcode, output) = proc.RunCommandFull(counters_command,
- collect_output=True)
- logging.info('Counters shut down: %s' % (output))
- # Convert the .coverage file to lcov format
- if self.lcov_converter_path == False:
- logging.error('Lcov converter tool not found')
- return False
- self.lcov_converter_path = self.lcov_converter_path.rstrip('\\')
- convert_command = ('%s -sym_path=%s -src_root=%s ' %
- (os.path.join(self.lcov_converter_path,
- 'coverage_analyzer.exe'),
- sym_path,
- src_root))
- logging.info('Conversion to lcov complete')
- (retcode, output) = proc.RunCommandFull(convert_command + coverage_file,
- collect_output=True)
- shutil.copy(coverage_file, coverage_file.replace('.coverage', ''))
- # TODO(niranjan): Upload this somewhere!
-
-
-def main():
- # Command line parsing
- parser = optparse.OptionParser()
- # Path where the .coverage to .lcov converter tools are stored.
- parser.add_option('-t',
- '--tools_path',
- dest='tools_path',
- default=None,
- help='Location of the coverage tools (windows only)')
- parser.add_option('-u',
- '--upload',
- dest='upload_path'
- default=None,
- help='Location where the results should be uploaded')
- # We need the revision number so that we can generate the output file of the
- # format chrome_<platform>_<revision>.lcov
- parser.add_option('-r',
- '--revision',
- dest='revision',
- default=None,
- help='Revision number of the Chromium source repo')
- # Root of the source tree. Needed for converting the generated .coverage file
- # on Windows to the open source lcov format.
- parser.add_option('-s',
- '--src_root',
- dest='src_root',
- default=None,
- help='Root of the source repository')
-
- if revision == None or src_root == None or upload_path == None:
- logging.error('Invalid command line arguments')
- sys.exit(1)
-
- if IsWindows():
- # Initialize coverage
- cov = coverage.Coverage(revision,
- tools_path,
- tools_path)
- # Instrument the binaries
- coverage_file = cov.SetUp(windows_binaries)
- if coverage_file != None:
- # Run all the tests
- for test in windows_tests:
- logging.info('Executing test %s: ' % binary)
- (retcode, output) = proc.RunCommandFull(binary, collect_output=True)
- if retcode != 0:
- sys.exit(retcode)
- else:
- logging.error('Error during instrumentation.')
- sys.exit(1)
-
- cov.Upload(coverage_file,
- upload_path,
- os.path.join(src_root, 'chrome', 'Release'),
- src_root)
- cov.TearDown()
-
-
-if __name__ == '__main__':
- sys.exit(main())
-
+#!/bin/env python +# Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + + +"""Module to setup and generate code coverage data + +This module first sets up the environment for code coverage, instruments the +binaries, runs the tests and collects the code coverage data. + + +Usage: + coverage.py --upload=<upload_location> + --revision=<revision_number> + --src_root=<root_of_source_tree> + [--tools_path=<tools_path>] +""" + +import logging +import optparse +import os +import shutil +import subprocess +import sys +import tempfile + +import google.logging_utils +import google.process_utils as proc + + +# The list of binaries that will be instrumented for code coverage +# TODO(niranjan): Add a complete list of binaries +windows_binaries = ['unit_tests.exe', + 'ui_tests.exe'] + +# The list of tests that will be run +#TODO(niranjan): Add more tests +windows_tests = ['unit_tests.exe', + 'ui_tests.exe'] + + +def IsWindows(): + """Checks if the current platform is Windows. + """ + return sys.platform[:3] == 'win' + + +class Coverage(object): + """Class to set up and generate code coverage. + + This class contains methods that are useful to set up the environment for + code coverage. + + Attributes: + instrumented: A boolean indicating if all the binaries have been + instrumented. + """ + + def __init__(self, + revision, + vsts_path = None, + lcov_converter_path = None): + google.logging_utils.config_root() + self.revision = revision + self.instrumented = False + self.vsts_path = vsts_path + self.lcov_converter_path = lcov_converter_path + self._dir = None + + + def SetUp(self, binaries): + """Set up the platform specific environment and instrument the binaries for + coverage. + + This method sets up the environment, instruments all the compiled binaries + and sets up the code coverage counters. + + Args: + binaries: List of binaries that need to be instrumented. + + Returns: + Path of the file containing code coverage data on successful + instrumentation. + None on error. + """ + if self.instrumented: + logging.error('Binaries already instrumented') + return None + coverage_file = None + if IsWindows(): + # Stop all previous instance of VSPerfMon counters + counters_command = ('%s -shutdown' % + (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) + (retcode, output) = proc.RunCommandFull(counters_command, + collect_output=True) + # TODO(niranjan): Add a check that to verify that the binaries were built + # using the /PROFILE linker flag. + if self.vsts_path == None or self.lcov_converter_path == None: + return None + # Remove trailing slashes + self.vsts_path = self.vsts_path.rstrip('\\') + instrument_command = '%s /COVERAGE ' % (os.path.join(self.vsts_path, + 'vsinstr.exe')) + for binary in binaries: + logging.info('binary = %s' % (binary)) + logging.info('instrument_command = %s' % (instrument_command)) + # Instrument each binary in the list + (retcode, output) = proc.RunCommandFull(instrument_command + binary, + collect_output=True) + # Check if the file has been instrumented correctly. + if output.pop().rfind('Successfully instrumented') == -1: + logging.error('Error instrumenting %s' % (binary)) + return None + + # Generate the file name for the coverage results + self._dir = tempfile.mkdtemp() + coverage_file = os.path.join(self._dir, 'chrome_win32_%s.coverage' % + (self.revision)) + logging.info('.coverage file: %s' % (coverage_file)) + + # After all the binaries have been instrumented, we start the counters. + counters_command = ('%s -start:coverage -output:%s' % + (os.path.join(self.vsts_path, 'vsperfcmd.exe'), + coverage_file)) + # Here we use subprocess.call() instead of the RunCommandFull because the + # VSPerfCmd spawns another process before terminating and this confuses + # the subprocess.Popen() used by RunCommandFull. + retcode = subprocess.call(counters_command) + # TODO(niranjan): Check whether the counters have been started + # successfully. + + # We are now ready to run tests and measure code coverage. + self.instrumented = True + else: + return None + return coverage_file + + + def TearDown(self): + """Tear down method. + + This method shuts down the counters, and cleans up all the intermediate + artifacts. + """ + if self.instrumented == False: + return + + if IsWindows(): + # Stop counters + counters_command = ('%s -shutdown' % + (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) + (retcode, output) = proc.RunCommandFull(counters_command, + collect_output=True) + logging.info('Counters shut down: %s' % (output)) + # TODO(niranjan): Revert the instrumented binaries to their original + # versions. + else: + return + # Delete all the temp files and folders + if self._dir != None: + shutil.rmtree(self._dir, ignore_errors=True) + logging.info('Cleaned up temporary files and folders') + # Reset the instrumented flag. + self.instrumented = False + + + def Upload(self, coverage_file, upload_path, sym_path=None, src_root=None): + """Upload the results to the dashboard. + + This method uploads the coverage data to a dashboard where it will be + processed. On Windows, this method will first convert the .coverage file to + the lcov format. This method needs to be called before the TearDown method. + + Args: + coverage_file: The coverage data file to upload. + upload_path: Destination where the coverage data will be processed. + sym_path: Symbol path for the build (Win32 only) + src_root: Root folder of the source tree (Win32 only) + + Returns: + True on success. + False on failure. + """ + if self.IsWindows(): + # Stop counters + counters_command = ('%s -shutdown' % + (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) + (retcode, output) = proc.RunCommandFull(counters_command, + collect_output=True) + logging.info('Counters shut down: %s' % (output)) + # Convert the .coverage file to lcov format + if self.lcov_converter_path == False: + logging.error('Lcov converter tool not found') + return False + self.lcov_converter_path = self.lcov_converter_path.rstrip('\\') + convert_command = ('%s -sym_path=%s -src_root=%s ' % + (os.path.join(self.lcov_converter_path, + 'coverage_analyzer.exe'), + sym_path, + src_root)) + logging.info('Conversion to lcov complete') + (retcode, output) = proc.RunCommandFull(convert_command + coverage_file, + collect_output=True) + shutil.copy(coverage_file, coverage_file.replace('.coverage', '')) + # TODO(niranjan): Upload this somewhere! + + +def main(): + # Command line parsing + parser = optparse.OptionParser() + # Path where the .coverage to .lcov converter tools are stored. + parser.add_option('-t', + '--tools_path', + dest='tools_path', + default=None, + help='Location of the coverage tools (windows only)') + parser.add_option('-u', + '--upload', + dest='upload_path' + default=None, + help='Location where the results should be uploaded') + # We need the revision number so that we can generate the output file of the + # format chrome_<platform>_<revision>.lcov + parser.add_option('-r', + '--revision', + dest='revision', + default=None, + help='Revision number of the Chromium source repo') + # Root of the source tree. Needed for converting the generated .coverage file + # on Windows to the open source lcov format. + parser.add_option('-s', + '--src_root', + dest='src_root', + default=None, + help='Root of the source repository') + + if revision == None or src_root == None or upload_path == None: + logging.error('Invalid command line arguments') + sys.exit(1) + + if IsWindows(): + # Initialize coverage + cov = coverage.Coverage(revision, + tools_path, + tools_path) + # Instrument the binaries + coverage_file = cov.SetUp(windows_binaries) + if coverage_file != None: + # Run all the tests + for test in windows_tests: + logging.info('Executing test %s: ' % binary) + (retcode, output) = proc.RunCommandFull(binary, collect_output=True) + if retcode != 0: + sys.exit(retcode) + else: + logging.error('Error during instrumentation.') + sys.exit(1) + + cov.Upload(coverage_file, + upload_path, + os.path.join(src_root, 'chrome', 'Release'), + src_root) + cov.TearDown() + + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/tools/code_coverage/process_coverage.py b/tools/code_coverage/process_coverage.py index c902f4d..6cec95b 100644 --- a/tools/code_coverage/process_coverage.py +++ b/tools/code_coverage/process_coverage.py @@ -1,233 +1,233 @@ -#!/usr/bin/python2.4
-#
-# Copyright 2008, 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.
-
-
-"""Script to clean the lcov files and convert it to HTML
-
-TODO(niranjan): Add usage information here
-"""
-
-
-import optparse
-import os
-import shutil
-import sys
-import tempfile
-
-
-# These are source files that were generated during compile time. We want to
-# remove references to these files from the lcov file otherwise genhtml will
-# throw an error.
-win32_srcs_exclude = ['parse.y',
- 'xpathgrammar.cpp',
- 'cssgrammar.cpp']
-
-
-def CleanPathNames(dir):
- """Clean the pathnames of the HTML generated by genhtml.
-
- This method is required only for code coverage on Win32. Due to a known issue
- with reading from CIFS shares mounted on Linux, genhtml appends a ^M to every
- file name it reads from the Windows share, causing corrupt filenames in
- genhtml's output folder.
-
- Args:
- dir: Output folder of the genhtml output.
-
- Returns:
- None
- """
- # Stip off the ^M characters that get appended to the file name
- for file in os.walk(dir):
- file_clean = file.replace('\r', '')
- if file_clean != file:
- os.rename(file, file_clean)
-
-
-def GenerateHtml(lcov_path, dash_root):
- """Runs genhtml to convert lcov data to human readable HTML.
-
- This script expects the LCOV file name to be in the format:
- chrome_<platform>_<revision#>.lcov.
- This method parses the file name and then sets up the correct folder
- hierarchy for the coverage data and then runs genhtml to get the actual HTML
- formatted coverage data.
-
- Args:
- lcov_path: Path of the lcov data file.
- dash_root: Root location of the dashboard.
-
- Returns:
- Code coverage percentage on sucess.
- None on failure.
- """
- # Parse the LCOV file name.
- filename = os.path.basename(lcov_path).split('.')[0]
- buffer = filename.split('_')
- dash_root = dash_root.rstrip('/') # Remove trailing '/'
-
- # Set up correct folder heirarchy in the dashboard root
- # TODO(niranjan): Check the formatting using a regexp
- if len(buffer) >= 3: # Check if filename has right formatting
- platform = buffer[len(buffer) - 2]
- revision = buffer[len(buffer) - 1]
- if os.path.exists(os.path.join(dash_root, platform)) == False:
- os.mkdir(os.path.join(dash_root, platform))
- output_dir = os.join.path(dash_root, platform, revision)
- os.mkdir(output_dir)
- else:
- # TODO(niranjan): Add failure logging here.
- return None # File not formatted correctly
-
- # Run genhtml
- os.system('/usr/bin/genhtml -o %s %s' % (output_dir, lcov_path))
- # TODO(niranjan): Check the exit status of the genhtml command.
- # TODO(niranjan): Parse the stdout and return coverage percentage.
- CleanPathNames(output_dir)
- return 'dummy' # TODO(niranjan): Return actual percentage.
-
-
-def CleanWin32Lcov(lcov_path, src_root):
- """Cleanup the lcov data generated on Windows.
-
- This method fixes up the paths inside the lcov file from the Win32 specific
- paths to the actual paths of the mounted CIFS share. The lcov files generated
- on Windows have the following format:
-
- SF:c:\chrome_src\src\skia\sgl\skscan_antihair.cpp
- DA:97,0
- DA:106,0
- DA:107,0
- DA:109,0
- ...
- end_of_record
-
- This method changes the source-file (SF) lines to a format compatible with
- genhtml on Linux by fixing paths. This method also removes references to
- certain dynamically generated files to be excluded from the code ceverage.
-
- Args:
- lcov_path: Path of the Win32 lcov file to be cleaned.
- src_root: Location of the source and symbols dir.
- Returns:
- None
- """
- strip_flag = False
- lcov = open(lcov_path, 'r')
- (tmpfile, tmpfile_name) = tempfile.mkstemp()
- src_root = src_root.rstrip('/') # Remove trailing '/'
- for line in lcov:
- if line.startswith('SF'):
- # We want to exclude certain auto-generated files otherwise genhtml will
- # fail to convert lcov to HTML.
- for exp in win32_srcs_exclude:
- if line.rfind(exp) != -1:
- strip_flag = True # Indicates that we want to remove this section
-
- # Now we normalize the paths
- # e.g. Change SF:c:\foo\src\... to SF:/chrome_src/...
- parse_buffer = line.split(':')
- buffer = '%s:%s%s' % (parse_buffer[0],
- src_root,
- parse_buffer[2])
- buffer = buffer.replace('\\', '/')
- line = buffer
-
- # Write to the temp file if the section to write is valid
- if strip_flag == False:
- tmpfile.write('%s' % (line))
-
- # Reset the strip flag
- if line.endswith('end_of_record'):
- strip_flag = False
-
- # Close the files and replace the lcov file by the 'clean' tmpfile
- tmpfile.close()
- lcov.close()
- shutil.move(tmpfile_name, lcov_path)
-
-
-def main():
- if sys.platform[:5] != 'linux': # Run this only on Linux
- print 'This script is supported only on Linux'
- os.exit(1)
-
- # Command line parsing
- parser = optparse.OptionParser()
- parser.add_option('-p',
- '--platform',
- dest='platform',
- default=None,
- help='Platform that the locv file was generated on. Must be
- one of {win32, linux2, macosx}')
- parser.add_option('-s',
- '--source',
- dest='src_dir',
- default=None,
- help='Path to the source code and symbols')
- parser.add_option('-d',
- '--dash_root',
- dest='dash_root',
- default=None,
- help='Root directory for the dashboard')
- parser.add_option('-l',
- '--lcov',
- dest='lcov_path',
- default=None,
- help='Location of the LCOV file to process')
- (options, args) = parser.parse_args()
-
- if options.platform == None:
- parser.error('Platform not specified')
- if options.lcov_path == None:
- parser.error('lcov file path not specified')
- if options.src_dir == None:
- parser.error('Source directory not specified')
- if options.dash_root == None:
- parser.error('Dashboard root not specified')
- if options.platform == 'win32':
- CleanWin32Lcov(options.lcov_path, options.src_dir)
- percent = GenerateHtml(options.lcov_path, options.dash_root)
- if percent == None:
- # TODO(niranjan): Add logging.
- print 'Failed to generate code coverage'
- os.exit(1)
- else:
- # TODO(niranjan): Do something with the code coverage numbers
- pass
- else:
- print 'Unsupported platform'
- os.exit(1)
-
-
-if __name__ == '__main__':
- main()
-
+#!/usr/bin/python2.4 +# +# Copyright 2008, 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. + + +"""Script to clean the lcov files and convert it to HTML + +TODO(niranjan): Add usage information here +""" + + +import optparse +import os +import shutil +import sys +import tempfile + + +# These are source files that were generated during compile time. We want to +# remove references to these files from the lcov file otherwise genhtml will +# throw an error. +win32_srcs_exclude = ['parse.y', + 'xpathgrammar.cpp', + 'cssgrammar.cpp'] + + +def CleanPathNames(dir): + """Clean the pathnames of the HTML generated by genhtml. + + This method is required only for code coverage on Win32. Due to a known issue + with reading from CIFS shares mounted on Linux, genhtml appends a ^M to every + file name it reads from the Windows share, causing corrupt filenames in + genhtml's output folder. + + Args: + dir: Output folder of the genhtml output. + + Returns: + None + """ + # Stip off the ^M characters that get appended to the file name + for file in os.walk(dir): + file_clean = file.replace('\r', '') + if file_clean != file: + os.rename(file, file_clean) + + +def GenerateHtml(lcov_path, dash_root): + """Runs genhtml to convert lcov data to human readable HTML. + + This script expects the LCOV file name to be in the format: + chrome_<platform>_<revision#>.lcov. + This method parses the file name and then sets up the correct folder + hierarchy for the coverage data and then runs genhtml to get the actual HTML + formatted coverage data. + + Args: + lcov_path: Path of the lcov data file. + dash_root: Root location of the dashboard. + + Returns: + Code coverage percentage on sucess. + None on failure. + """ + # Parse the LCOV file name. + filename = os.path.basename(lcov_path).split('.')[0] + buffer = filename.split('_') + dash_root = dash_root.rstrip('/') # Remove trailing '/' + + # Set up correct folder heirarchy in the dashboard root + # TODO(niranjan): Check the formatting using a regexp + if len(buffer) >= 3: # Check if filename has right formatting + platform = buffer[len(buffer) - 2] + revision = buffer[len(buffer) - 1] + if os.path.exists(os.path.join(dash_root, platform)) == False: + os.mkdir(os.path.join(dash_root, platform)) + output_dir = os.join.path(dash_root, platform, revision) + os.mkdir(output_dir) + else: + # TODO(niranjan): Add failure logging here. + return None # File not formatted correctly + + # Run genhtml + os.system('/usr/bin/genhtml -o %s %s' % (output_dir, lcov_path)) + # TODO(niranjan): Check the exit status of the genhtml command. + # TODO(niranjan): Parse the stdout and return coverage percentage. + CleanPathNames(output_dir) + return 'dummy' # TODO(niranjan): Return actual percentage. + + +def CleanWin32Lcov(lcov_path, src_root): + """Cleanup the lcov data generated on Windows. + + This method fixes up the paths inside the lcov file from the Win32 specific + paths to the actual paths of the mounted CIFS share. The lcov files generated + on Windows have the following format: + + SF:c:\chrome_src\src\skia\sgl\skscan_antihair.cpp + DA:97,0 + DA:106,0 + DA:107,0 + DA:109,0 + ... + end_of_record + + This method changes the source-file (SF) lines to a format compatible with + genhtml on Linux by fixing paths. This method also removes references to + certain dynamically generated files to be excluded from the code ceverage. + + Args: + lcov_path: Path of the Win32 lcov file to be cleaned. + src_root: Location of the source and symbols dir. + Returns: + None + """ + strip_flag = False + lcov = open(lcov_path, 'r') + (tmpfile, tmpfile_name) = tempfile.mkstemp() + src_root = src_root.rstrip('/') # Remove trailing '/' + for line in lcov: + if line.startswith('SF'): + # We want to exclude certain auto-generated files otherwise genhtml will + # fail to convert lcov to HTML. + for exp in win32_srcs_exclude: + if line.rfind(exp) != -1: + strip_flag = True # Indicates that we want to remove this section + + # Now we normalize the paths + # e.g. Change SF:c:\foo\src\... to SF:/chrome_src/... + parse_buffer = line.split(':') + buffer = '%s:%s%s' % (parse_buffer[0], + src_root, + parse_buffer[2]) + buffer = buffer.replace('\\', '/') + line = buffer + + # Write to the temp file if the section to write is valid + if strip_flag == False: + tmpfile.write('%s' % (line)) + + # Reset the strip flag + if line.endswith('end_of_record'): + strip_flag = False + + # Close the files and replace the lcov file by the 'clean' tmpfile + tmpfile.close() + lcov.close() + shutil.move(tmpfile_name, lcov_path) + + +def main(): + if sys.platform[:5] != 'linux': # Run this only on Linux + print 'This script is supported only on Linux' + os.exit(1) + + # Command line parsing + parser = optparse.OptionParser() + parser.add_option('-p', + '--platform', + dest='platform', + default=None, + help='Platform that the locv file was generated on. Must be + one of {win32, linux2, macosx}') + parser.add_option('-s', + '--source', + dest='src_dir', + default=None, + help='Path to the source code and symbols') + parser.add_option('-d', + '--dash_root', + dest='dash_root', + default=None, + help='Root directory for the dashboard') + parser.add_option('-l', + '--lcov', + dest='lcov_path', + default=None, + help='Location of the LCOV file to process') + (options, args) = parser.parse_args() + + if options.platform == None: + parser.error('Platform not specified') + if options.lcov_path == None: + parser.error('lcov file path not specified') + if options.src_dir == None: + parser.error('Source directory not specified') + if options.dash_root == None: + parser.error('Dashboard root not specified') + if options.platform == 'win32': + CleanWin32Lcov(options.lcov_path, options.src_dir) + percent = GenerateHtml(options.lcov_path, options.dash_root) + if percent == None: + # TODO(niranjan): Add logging. + print 'Failed to generate code coverage' + os.exit(1) + else: + # TODO(niranjan): Do something with the code coverage numbers + pass + else: + print 'Unsupported platform' + os.exit(1) + + +if __name__ == '__main__': + main() + |