#!/usr/bin/env python3 # # Copyright 2013 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.
"""Instruments classes and jar files.
This script corresponds to the 'jacoco_instr' action in the Java build process.
Depending on whether jacoco_instrument is set, the 'jacoco_instr' action will
call the instrument command which accepts a jar and instruments it using
jacococli.jar.
def _AddArguments(parser): """Adds arguments related to instrumentation to parser.
Args:
parser: ArgumentParser object. """
parser.add_argument( '--input-path',
required=True,
help='Path to input file(s). Either the classes ' 'directory, or the path to a jar.')
parser.add_argument( '--output-path',
required=True,
help='Path to output final file(s) to. Either the ' 'final classes directory, or the directory in ' 'which to place the instrumented/copied jar.')
parser.add_argument( '--sources-json-file',
required=True,
help='File to create with the list of source directories ' 'and input path.')
parser.add_argument( '--java-sources-file',
required=True,
help='File containing newline-separated .java paths')
parser.add_argument( '--jacococli-jar', required=True, help='Path to jacococli.jar.')
parser.add_argument( '--files-to-instrument',
help='Path to a file containing which source files are affected.')
def _GetSourceDirsFromSourceFiles(source_files): """Returns list of directories for the files in |source_files|.
Args:
source_files: List of source files.
Returns:
List of source directories. """ return list(set(os.path.dirname(source_file) for source_file in source_files))
def _CreateSourcesJsonFile(source_dirs, input_path, sources_json_file,
src_root): """Adds all normalized source directories and input path to
|sources_json_file|.
Args:
source_dirs: List of source directories.
input_path: The input path to non-instrumented class files.
sources_json_file: File into which to write the list of source directories and input path.
src_root: Root which sources added to the file should be relative to.
Returns:
An exit code. """
src_root = os.path.abspath(src_root)
relative_sources = [] for s in source_dirs:
abs_source = os.path.abspath(s) if abs_source[:len(src_root)] != src_root:
print('Error: found source directory not under repository root: %s %s' %
(abs_source, src_root)) return 1
rel_source = os.path.relpath(abs_source, src_root)
relative_sources.append(rel_source)
data = {}
data['source_dirs'] = relative_sources
data['input_path'] = [] if input_path:
data['input_path'].append(os.path.abspath(input_path)) with open(sources_json_file, 'w') as f:
json.dump(data, f)
def _GetAffectedClasses(jar_file, source_files): """Gets affected classes by affected source files to a jar.
Args:
jar_file: The jar file to get all members.
source_files: The list of affected source files.
Returns:
A tuple of affected classes and unaffected members. """ with zipfile.ZipFile(jar_file) as f:
members = f.namelist()
affected_classes = []
unaffected_members = []
for member in members: ifnot member.endswith('.class'):
unaffected_members.append(member) continue
is_affected = False
index = member.find('$') if index == -1:
index = member.find('.class') for source_file in source_files: if source_file.endswith(member[:index] + '.java'):
affected_classes.append(member)
is_affected = True break ifnot is_affected:
unaffected_members.append(member)
return affected_classes, unaffected_members
def _InstrumentClassFiles(instrument_cmd,
input_path,
output_path,
temp_dir,
affected_source_files=None): """Instruments class files from input jar.
Args:
instrument_cmd: JaCoCo instrument command.
input_path: The input path to non-instrumented jar.
output_path: The output path to instrumented jar.
temp_dir: The temporary directory.
affected_source_files: The affected source file paths to input jar.
Default isNone, which means instrumenting all class files in jar. """
affected_classes = None
unaffected_members = None if affected_source_files:
affected_classes, unaffected_members = _GetAffectedClasses(
input_path, affected_source_files)
# Extract affected class files. with zipfile.ZipFile(input_path) as f:
f.extractall(temp_dir, affected_classes)
# Instrument extracted class files.
instrument_cmd.extend([temp_dir, '--dest', instrumented_dir])
build_utils.CheckOutput(instrument_cmd)
if affected_source_files and unaffected_members: # Extract unaffected members to instrumented_dir. with zipfile.ZipFile(input_path) as f:
f.extractall(instrumented_dir, unaffected_members)
# Zip all files to output_path
build_utils.ZipDir(output_path, instrumented_dir)
def _RunInstrumentCommand(parser): """Instruments class or Jar files using JaCoCo.
Args:
parser: ArgumentParser object.
Returns:
An exit code. """
args = parser.parse_args()
source_files = [] if args.java_sources_file:
source_files.extend(build_utils.ReadSourcesList(args.java_sources_file))
with build_utils.TempDir() as temp_dir:
instrument_cmd = build_utils.JavaCmd() + [ '-jar', args.jacococli_jar, 'instrument'
]
ifnot args.files_to_instrument:
_InstrumentClassFiles(instrument_cmd, args.input_path, args.output_path,
temp_dir) else:
affected_files = build_utils.ReadSourcesList(args.files_to_instrument)
source_set = set(source_files)
affected_source_files = [f for f in affected_files if f in source_set]
# Copy input_path to output_path and return if no source file affected. ifnot affected_source_files:
shutil.copyfile(args.input_path, args.output_path) # Create a dummy sources_json_file.
_CreateSourcesJsonFile([], None, args.sources_json_file,
build_utils.DIR_SOURCE_ROOT) return 0 else:
_InstrumentClassFiles(instrument_cmd, args.input_path, args.output_path,
temp_dir, affected_source_files)
source_dirs = _GetSourceDirsFromSourceFiles(source_files) # TODO(GYP): In GN, we are passed the list of sources, detecting source # directories, then walking them to re-establish the list of sources. # This can obviously be simplified!
_CreateSourcesJsonFile(source_dirs, args.input_path, args.sources_json_file,
build_utils.DIR_SOURCE_ROOT)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.