#!/usr/bin/env python
# Copyright 2016 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Script to transform and merge sancov files into human readable json-format.

The script supports three actions:
all: Writes a json file with all instrumented lines of all executables.
merge: Merges sancov files with coverage output into an existing json file.
split: Split json file into separate files per covered source file.

The json data is structured as follows:
{
  "version": 1,
  "tests": ["executable1", "executable2", ...],
  "files": {
    "file1": [[<instr line 1>, <bit_mask>], [<instr line 2>, <bit_mask>], ...],
    "file2": [...],
    ...
  }
}

The executables are sorted and determine the test bit mask. Their index+1 is
the bit, e.g. executable1 = 1, executable3 = 4, etc. Hence, a line covered by
executable1 and executable3 will have bit_mask == 5 == 0b101. The number of
tests is restricted to 52 in version 1, to allow javascript JSON parsing of
the bitsets encoded as numbers. JS max safe int is (1 << 53) - 1.

The line-number-bit_mask pairs are sorted by line number and don't contain
duplicates.

Split json data preserves the same format, but only contains one file per
json file.

The sancov tool is expected to be in the llvm compiler-rt third-party
directory. It's not checked out by default and must be added as a custom deps:
'v8/third_party/llvm/projects/compiler-rt':
    'https://chromium.googlesource.com/external/llvm.org/compiler-rt.git'
"""

import argparse
import json
import logging
import os
import re
import subprocess
import sys

from multiprocessing import Pool, cpu_count


logging.basicConfig(level=logging.INFO)

# Files to exclude from coverage. Dropping their data early adds more speed.
# The contained cc files are already excluded from instrumentation, but inlined
# data is referenced through v8's object files.
EXCLUSIONS = [
  'buildtools',
  'src/third_party',
  'third_party',
  'test',
  'testing',
]

# Executables found in the build output for which no coverage is generated.
# Exclude them from the coverage data file.
EXE_BLACKLIST = [
  'generate-bytecode-expectations',
  'hello-world',
  'mksnapshot',
  'parser-shell',
  'process',
  'shell',
]

# V8 checkout directory.
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(
    os.path.abspath(__file__))))

# The sancov tool location.
SANCOV_TOOL = os.path.join(
    BASE_DIR, 'third_party', 'llvm', 'projects', 'compiler-rt',
    'lib', 'sanitizer_common', 'scripts', 'sancov.py')

# Simple script to sanitize the PCs from objdump.
SANITIZE_PCS = os.path.join(BASE_DIR, 'tools', 'sanitizers', 'sanitize_pcs.py')

# The llvm symbolizer location.
SYMBOLIZER = os.path.join(
    BASE_DIR, 'third_party', 'llvm-build', 'Release+Asserts', 'bin',
    'llvm-symbolizer')

# Number of cpus.
CPUS = cpu_count()

# Regexp to find sancov files as output by sancov_merger.py. Also grabs the
# executable name in group 1.
SANCOV_FILE_RE = re.compile(r'^(.*)\.result.sancov$')


def executables(build_dir):
  """Iterates over executable files in the build directory."""
  for f in os.listdir(build_dir):
    file_path = os.path.join(build_dir, f)
    if (os.path.isfile(file_path) and
        os.access(file_path, os.X_OK) and
        f not in EXE_BLACKLIST):
      yield file_path


def process_symbolizer_output(output, build_dir):
  """Post-process llvm symbolizer output.

  Excludes files outside the v8 checkout or given in exclusion list above
  from further processing. Drops the character index in each line.

  Returns: A mapping of file names to lists of line numbers. The file names
           have relative paths to the v8 base directory. The lists of line
           numbers don't contain duplicate lines and are sorted.
  """
  # Path prefix added by the llvm symbolizer including trailing slash.
  output_path_prefix = os.path.join(build_dir, '..', '..', '')

  # Drop path prefix when iterating lines. The path is redundant and takes
  # too much space. Drop files outside that path, e.g. generated files in
  # the build dir and absolute paths to c++ library headers.
  def iter_lines():
    for line in output.strip().splitlines():
      if line.startswith(output_path_prefix):
        yield line[len(output_path_prefix):]

  # Map file names to sets of instrumented line numbers.
  file_map = {}
  for line in iter_lines():
    # Drop character number, we only care for line numbers. Each line has the
    # form: <file name>:<line number>:<character number>.
    file_name, number, _ = line.split(':')
    file_map.setdefault(file_name, set([])).add(int(number))

  # Remove exclusion patterns from file map. It's cheaper to do it after the
  # mapping, as there are few excluded files and we don't want to do this
  # check for numerous lines in ordinary files.
  def keep(file_name):
    for e in EXCLUSIONS:
      if file_name.startswith(e):
        return False
    return True

  # Return in serializable form and filter.
  return {k: sorted(file_map[k]) for k in file_map if keep(k)}


def get_instrumented_lines(executable):
  """Return the instrumented lines of an executable.

  Called trough multiprocessing pool.

  Returns: Post-processed llvm output as returned by process_symbolizer_output.
  """
  # The first two pipes are from llvm's tool sancov.py with 0x added to the hex
  # numbers. The results are piped into the llvm symbolizer, which outputs for
  # each PC: <file name with abs path>:<line number>:<character number>.
  # We don't call the sancov tool to get more speed.
  process = subprocess.Popen(
      'objdump -d %s | '
      'grep \'^\s\+[0-9a-f]\+:.*\scall\(q\|\)\s\+[0-9a-f]\+ '
      '<__sanitizer_cov\(_with_check\|\|_trace_pc_guard\)\(@plt\|\)>\' | '
      'grep \'^\s\+[0-9a-f]\+\' -o | '
      '%s | '
      '%s --obj %s -functions=none' %
          (executable, SANITIZE_PCS, SYMBOLIZER, executable),
      stdout=subprocess.PIPE,
      stderr=subprocess.PIPE,
      stdin=subprocess.PIPE,
      cwd=BASE_DIR,
      shell=True,
  )
  output, _ = process.communicate()
  assert process.returncode == 0
  return process_symbolizer_output(output, os.path.dirname(executable))


def merge_instrumented_line_results(exe_list, results):
  """Merge multiprocessing results for all instrumented lines.

  Args:
    exe_list: List of all executable names with absolute paths.
    results: List of results as returned by get_instrumented_lines.

  Returns: Dict to be used as json data as specified on the top of this page.
           The dictionary contains all instrumented lines of all files
           referenced by all executables.
  """
  def merge_files(x, y):
    for file_name, lines in y.iteritems():
      x.setdefault(file_name, set([])).update(lines)
    return x
  result = reduce(merge_files, results, {})

  # Return data as file->lines mapping. The lines are saved as lists
  # with (line number, test bits (as int)). The test bits are initialized with
  # 0, meaning instrumented, but no coverage.
  # The order of the test bits is given with key 'tests'. For now, these are
  # the executable names. We use a _list_ with two items instead of a tuple to
  # ease merging by allowing mutation of the second item.
  return {
    'version': 1,
    'tests': sorted(map(os.path.basename, exe_list)),
    'files': {f: map(lambda l: [l, 0], sorted(result[f])) for f in result},
  }


def write_instrumented(options):
  """Implements the 'all' action of this tool."""
  exe_list = list(executables(options.build_dir))
  logging.info('Reading instrumented lines from %d executables.',
               len(exe_list))
  pool = Pool(CPUS)
  try:
    results = pool.imap_unordered(get_instrumented_lines, exe_list)
  finally:
    pool.close()

  # Merge multiprocessing results and prepare output data.
  data = merge_instrumented_line_results(exe_list, results)

  logging.info('Read data from %d executables, which covers %d files.',
               len(data['tests']), len(data['files']))
  logging.info('Writing results to %s', options.json_output)

  # Write json output.
  with open(options.json_output, 'w') as f:
    json.dump(data, f, sort_keys=True)


def get_covered_lines(args):
  """Return the covered lines of an executable.

  Called trough multiprocessing pool. The args are expected to unpack to:
    cov_dir: Folder with sancov files merged by sancov_merger.py.
    executable: Absolute path to the executable that was called to produce the
                given coverage data.
    sancov_file: The merged sancov file with coverage data.

  Returns: A tuple of post-processed llvm output as returned by
           process_symbolizer_output and the executable name.
  """
  cov_dir, executable, sancov_file = args

  # Let the sancov tool print the covered PCs and pipe them through the llvm
  # symbolizer.
  process = subprocess.Popen(
      '%s print %s 2> /dev/null | '
      '%s --obj %s -functions=none' %
          (SANCOV_TOOL,
           os.path.join(cov_dir, sancov_file),
           SYMBOLIZER,
           executable),
      stdout=subprocess.PIPE,
      stderr=subprocess.PIPE,
      stdin=subprocess.PIPE,
      cwd=BASE_DIR,
      shell=True,
  )
  output, _ = process.communicate()
  assert process.returncode == 0
  return (
      process_symbolizer_output(output, os.path.dirname(executable)),
      os.path.basename(executable),
  )


def merge_covered_line_results(data, results):
  """Merge multiprocessing results for covered lines.

  The data is mutated, the results are merged into it in place.

  Args:
    data: Existing coverage data from json file containing all instrumented
          lines.
    results: List of results as returned by get_covered_lines.
  """

  # List of executables and mapping to the test bit mask. The number of
  # tests is restricted to 52, to allow javascript JSON parsing of
  # the bitsets encoded as numbers. JS max safe int is (1 << 53) - 1.
  exe_list = data['tests']
  assert len(exe_list) <= 52, 'Max 52 different tests are supported.'
  test_bit_masks = {exe:1<<i for i, exe in enumerate(exe_list)}

  def merge_lines(old_lines, new_lines, mask):
    """Merge the coverage data of a list of lines.

    Args:
      old_lines: Lines as list of pairs with line number and test bit mask.
                 The new lines will be merged into the list in place.
      new_lines: List of new (covered) lines (sorted).
      mask: The bit to be set for covered lines. The bit index is the test
            index of the executable that covered the line.
    """
    i = 0
    # Iterate over old and new lines, both are sorted.
    for l in new_lines:
      while old_lines[i][0] < l:
        # Forward instrumented lines not present in this coverage data.
        i += 1
        # TODO: Add more context to the assert message.
        assert i < len(old_lines), 'Covered line %d not in input file.' % l
      assert old_lines[i][0] == l, 'Covered line %d not in input file.' % l

      # Add coverage information to the line.
      old_lines[i][1] |= mask

  def merge_files(data, result):
    """Merge result into data.

    The data is mutated in place.

    Args:
      data: Merged coverage data from the previous reduce step.
      result: New result to be merged in. The type is as returned by
              get_covered_lines.
    """
    file_map, executable = result
    files = data['files']
    for file_name, lines in file_map.iteritems():
      merge_lines(files[file_name], lines, test_bit_masks[executable])
    return data

  reduce(merge_files, results, data)


def merge(options):
  """Implements the 'merge' action of this tool."""

  # Check if folder with coverage output exists.
  assert (os.path.exists(options.coverage_dir) and
          os.path.isdir(options.coverage_dir))

  # Inputs for multiprocessing. List of tuples of:
  # Coverage dir, absoluate path to executable, sancov file name.
  inputs = []
  for sancov_file in os.listdir(options.coverage_dir):
    match = SANCOV_FILE_RE.match(sancov_file)
    if match:
      inputs.append((
          options.coverage_dir,
          os.path.join(options.build_dir, match.group(1)),
          sancov_file,
      ))

  logging.info('Merging %d sancov files into %s',
               len(inputs), options.json_input)

  # Post-process covered lines in parallel.
  pool = Pool(CPUS)
  try:
    results = pool.imap_unordered(get_covered_lines, inputs)
  finally:
    pool.close()

  # Load existing json data file for merging the results.
  with open(options.json_input, 'r') as f:
    data = json.load(f)

  # Merge muliprocessing results. Mutates data.
  merge_covered_line_results(data, results)

  logging.info('Merged data from %d executables, which covers %d files.',
               len(data['tests']), len(data['files']))
  logging.info('Writing results to %s', options.json_output)

  # Write merged results to file.
  with open(options.json_output, 'w') as f:
    json.dump(data, f, sort_keys=True)


def split(options):
  """Implements the 'split' action of this tool."""
  # Load existing json data file for splitting.
  with open(options.json_input, 'r') as f:
    data = json.load(f)

  logging.info('Splitting off %d coverage files from %s',
               len(data['files']), options.json_input)

  for file_name, coverage in data['files'].iteritems():
    # Preserve relative directories that are part of the file name.
    file_path = os.path.join(options.output_dir, file_name + '.json')
    try:
      os.makedirs(os.path.dirname(file_path))
    except OSError:
      # Ignore existing directories.
      pass

    with open(file_path, 'w') as f:
      # Flat-copy the old dict.
      new_data = dict(data)

      # Update current file.
      new_data['files'] = {file_name: coverage}

      # Write json data.
      json.dump(new_data, f, sort_keys=True)


def main(args=None):
  parser = argparse.ArgumentParser()
  # TODO(machenbach): Make this required and deprecate the default.
  parser.add_argument('--build-dir',
                      default=os.path.join(BASE_DIR, 'out', 'Release'),
                      help='Path to the build output directory.')
  parser.add_argument('--coverage-dir',
                      help='Path to the sancov output files.')
  parser.add_argument('--json-input',
                      help='Path to an existing json file with coverage data.')
  parser.add_argument('--json-output',
                      help='Path to a file to write json output to.')
  parser.add_argument('--output-dir',
                      help='Directory where to put split output files to.')
  parser.add_argument('action', choices=['all', 'merge', 'split'],
                      help='Action to perform.')

  options = parser.parse_args(args)
  options.build_dir = os.path.abspath(options.build_dir)
  if options.action.lower() == 'all':
    if not options.json_output:
      print '--json-output is required'
      return 1
    write_instrumented(options)
  elif options.action.lower() == 'merge':
    if not options.coverage_dir:
      print '--coverage-dir is required'
      return 1
    if not options.json_input:
      print '--json-input is required'
      return 1
    if not options.json_output:
      print '--json-output is required'
      return 1
    merge(options)
  elif options.action.lower() == 'split':
    if not options.json_input:
      print '--json-input is required'
      return 1
    if not options.output_dir:
      print '--output-dir is required'
      return 1
    split(options)
  return 0


if __name__ == '__main__':
  sys.exit(main())
