#!/usr/bin/env python
# Copyright 2015 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.

import json
import optparse
import os
import shutil
import subprocess
import sys
import tempfile
import traceback

from recipes import slave_utils

MISSING_SHARDS_MSG = r"""Missing results from the following shard(s): %s

It can happen in following cases:
  * Test failed to start (missing *.dll/*.so dependency for example)
  * Test crashed or hung
  * Task expired because there are not enough bots available and are all used
  * Swarming service experiences problems

Please examine logs to figure out what happened.
"""


class BadShards:

  def __init__(self):
    self.missing = []
    self.incomplete = []

  def add_incomplete(self, shard):
    self.incomplete.append(shard)

  def add_missing(self, shard):
    self.missing.append(shard)

  def not_empty(self):
    return self.missing or self.incomplete

  def as_str(self):
    return ', '.join(map(str, sorted(self.missing + self.incomplete)))

  def missing_count(self):
    return len(self.missing)


class AggregatedResults:

  def __init__(self, slow_tests_cutoff):
    self.slowest_tests = []
    self.results = []
    self.slow_tests_cutoff = slow_tests_cutoff

  def append(self, json_data):
    # TODO(machenbach): This is to flexibly switch to a single dict as json
    # output instead of a list wrapping a dict. Remove after V8 has
    # switched to flattened output on all release branches.
    if isinstance(json_data, list):
      # On continuous bots, the test driver outputs exactly one item in the
      # test results list for one architecture.
      assert len(json_data) == 1
      json_data = json_data[0]
    assert isinstance(json_data, dict)
    self.slowest_tests.extend(json_data['slowest_tests'])
    self.results.extend(json_data['results'])

  def as_json(self, tags):
    sorted_tests = sorted(
        self.slowest_tests, key=lambda t: t['duration'], reverse=True)
    return {
        'slowest_tests': sorted_tests[:self.slow_tests_cutoff],
        'results': self.results,
        'tags': sorted(tags),
    }


def emit_warning(title, log=None):
  print '@@@STEP_WARNINGS@@@'
  print title
  if log:
    slave_utils.WriteLogLines(title, log.split('\n'))


def get_shards_info(output_dir):
  # summary.json is produced by swarming.py itself. We are mostly interested
  # in the number of shards.
  try:
    with open(os.path.join(output_dir, 'summary.json')) as f:
      summary = json.load(f)
    return summary['shards']
  except (IOError, ValueError):
    emit_warning(
        'summary.json is missing or can not be read',
        'Something is seriously wrong with swarming_client/ or the bot.')
    return None


def merge_shard_results(output_dir, shards, options):
  """Reads JSON test output from all shards and combines them into one.

  Also merges sancov coverage data if coverage_dir is spefied.

  Returns dict with merged test output on success or None on failure. Emits
  annotations.
  """
  if not shards:
    return None

  # Merge all JSON files together.

  tags = set()
  aggregated_results = AggregatedResults(options.slow_tests_cutoff)
  bad_shards = BadShards()
  for index, result in enumerate(shards):
    if result is not None:
      if int(result.get('exit_code', 0)):
        # When receiving a sigterm, the test runner terminates gracefully
        # with json output, but has a non-zero return code.
        bad_shards.add_incomplete(index)
      json_data = load_shard_json(output_dir, result['task_id'], 'output.json')
      if json_data:
        aggregated_results.append(json_data)
        continue
    bad_shards.add_missing(index)

  # If some shards are missing, make it known. Continue parsing anyway. Step
  # should be red anyway, since swarming.py return non-zero exit code in that
  # case.
  if bad_shards.not_empty():
    # Not all tests run, combined JSON summary can not be trusted.
    tags.add('UNRELIABLE_RESULTS')
    as_str = bad_shards.as_str()
    emit_warning('some shards did not complete: %s' % as_str,
                 MISSING_SHARDS_MSG % as_str)

  # Handle the case when all shards fail. Return minimalistic dict that has all
  # fields that a calling recipe expects to avoid recipe-level exceptions.
  if bad_shards.missing_count() == len(shards):
    return {'slowest_tests': [], 'results': [], 'tags': sorted(tags)}

  return aggregated_results.as_json(tags)


def merge_test_results(output_dir, shards, options):
  with open(options.merged_test_output, 'wb') as f:
    merged_data = merge_shard_results(output_dir, shards, options)
    json.dump(merged_data, f, separators=(',', ':'))


def merge_coverage_data(output_dir, shards, options):
  # Merge coverage data if specified.
  if options.coverage_dir:
    for index, result in enumerate(shards):
      exit_code = subprocess.call([
          sys.executable, '-u', options.sancov_merger, '--coverage-dir',
          options.coverage_dir, '--swarming-output-dir',
          os.path.join(output_dir, result['task_id'])
      ])
      if exit_code:
        emit_warning('error when merging coverage data of shard %d' % index)


def load_shard_json(output_dir, task_id, file_name):
  """Reads JSON output of a single shard."""
  # 'output.json' is set in v8/testing.py, V8SwarmingTest.
  path = os.path.join(output_dir, task_id, file_name)
  try:
    with open(path) as f:
      return json.load(f)
  except (IOError, ValueError):
    print >> sys.stderr, 'Missing or invalid v8 JSON file: %s' % path
    return None


def swarming_cmd(swarming_args, options):
  # Prepare a directory to store JSON files fetched from isolate.
  task_output_dir = tempfile.mkdtemp(
      suffix='_swarming', dir=options.temp_root_dir)
  # Start building the command line for swarming.py.
  cmd = [
      'swarming',
  ]

  cmd.extend(swarming_args)
  cmd.extend([
      '-output-dir',
      task_output_dir,
      '-task-summary-json',
      os.path.join(task_output_dir, 'summary.json'),
  ])
  return cmd, task_output_dir


def parse_args(args):
  # Split |args| into options for shim and options for swarming.py script.
  if '--' in args:
    index = args.index('--')
    shim_args, swarming_args = args[:index], args[index + 1:]
  else:
    shim_args, swarming_args = args, []

  # Parse shim's own options.
  parser = optparse.OptionParser()
  parser.add_option('--temp-root-dir', default=tempfile.gettempdir())
  parser.add_option('--merged-test-output')
  parser.add_option('--slow-tests-cutoff', type="int", default=100)
  parser.add_option('--coverage-dir')
  parser.add_option('--sancov-merger')
  options, extra_args = parser.parse_args(shim_args)

  # Validate options.
  if extra_args:
    parser.error('Unexpected command line arguments')
  if options.coverage_dir and not options.sancov_merger:
    parser.error('--sancov-merger is required for merging coverage data')

  return options, swarming_args


def main(args):
  options, swarming_args = parse_args(args)
  cmd, output_dir = swarming_cmd(swarming_args, options)

  exit_code = 1
  try:
    # Run the real script, regardless of an exit code try to find and parse
    # JSON output files, since exit code may indicate that the isolated task
    # failed, not the swarming.py invocation itself.
    exit_code = subprocess.call(cmd)

    # Output parsing should not change exit code no matter what, so catch any
    # exceptions and just log them.
    try:
      shards = get_shards_info(output_dir)
      merge_test_results(output_dir, shards, options)
      merge_coverage_data(output_dir, shards, options)
    except Exception:
      emit_warning('failed to process v8 output JSON', traceback.format_exc())

  finally:
    shutil.rmtree(output_dir, ignore_errors=True)

  return exit_code


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
