#!/usr/bin/env python3
# Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

# Compare multiple CTS test_result.xml files

from __future__ import print_function
from os.path import basename
import argparse
import os
import sys

import utils

class Module:
  def __init__(self):
    self.test_cases = {}
    self.bf_covered_in_file = 0 # bitfield, one bit per file

  def get_test_case_maybe_create(self, test_case_name):
    return self.test_cases.setdefault(test_case_name, TestCase())

  def set_file_index_present(self, file_idx):
    self.bf_covered_in_file |= (1 << file_idx)

  def report(self, module_name, files, diff_only):
    bf_all_files = self.bf_covered_in_file
    for test_case_name, test_case in self.test_cases.iteritems():
      if test_case.bf_covered_in_file != bf_all_files:
        report_missing_thing('test_case', module_name + '/' + test_case_name,
            test_case.bf_covered_in_file, files)
    for test_case_name, test_case in self.test_cases.iteritems():
      test_case.report(module_name, test_case_name, files, diff_only)

class TestCase:
  def __init__(self):
    self.tests = {}
    self.bf_covered_in_file = 0 # bitfield, one bit per file

  def get_test_maybe_create(self, test_name):
    return self.tests.setdefault(test_name, Test())

  def set_file_index_present(self, file_idx):
    self.bf_covered_in_file |= (1 << file_idx)

  def report(self, module_name, test_case_name, files, diff_only):
    bf_all_files = self.bf_covered_in_file
    for test_name, test in self.tests.iteritems():
      do_report = test.bf_passing_in_file != bf_all_files
      if diff_only:
        do_report = do_report and test.bf_failing_in_file != bf_all_files
      if do_report:
        test.report(module_name, test_case_name, test_name, files)

class Test:
  def __init__(self):
    self.bf_failing_in_file = 0 # bitfields, one bit per file
    self.bf_passing_in_file = 0

  def set_file_index_outcome(self, outcome_is_passed, file_idx):
    bf_value = (1 << file_idx)
    if outcome_is_passed:
      self.bf_passing_in_file |= bf_value
    else:
      self.bf_failing_in_file |= bf_value

  # Report test's status in all files: pass/fail/missing
  def report(self, module_name, test_case_name, test_name, files):
    print('Test: {}/{}/{}:'.format(module_name, test_case_name, test_name))
    for file_idx, f in enumerate(files):
      bf_value = 1 << file_idx
      print('\t- {:20}'.format(basename(f)), end = '')
      if self.bf_passing_in_file & bf_value:
        print('PASS')
      elif self.bf_failing_in_file & bf_value:
        print('     FAIL')
      else:
        print(' --   --  (missing)')

def parse_arguments():
  parser = argparse.ArgumentParser(
      description = 'Compare multiple Android CTS test_result.xml files.')
  parser.add_argument('files', nargs = '+',
      help = 'List of (possibly renamed) test_result.xml files')
  parser.add_argument('--diff-only',
      action = 'store_true',
      help = "Don't list tests that consistently fail in all result files,"
      " list only differences.")
  return parser.parse_args()

# Read CTS test_result.xml from file and merge into result_tree
def add_to_result_tree(result_tree, file_xml, file_idx):
  module = None
  test_case = None
  for x in utils.read_cts_test_result(file_xml):
    if type(x) is utils.CtsModule:
      module = result_tree.setdefault(x.name, Module())
      module.set_file_index_present(file_idx)
    elif type(x) is utils.CtsTestCase:
      test_case = module.get_test_case_maybe_create(x.name)
      test_case.set_file_index_present(file_idx)
    else:
      assert(type(x) is utils.CtsTest)
      v = test_case.get_test_maybe_create(x.name)
      v.set_file_index_outcome(x.outcome, file_idx)

# main tree_report function
def tree_report(result_tree, files, diff_only):
  bf_all_files = (1 << len(files)) - 1
  for module_name, module in result_tree.iteritems():
    if module.bf_covered_in_file != bf_all_files:
      report_missing_thing('module', module_name, module.bf_covered_in_file,
          files)
  for module_name, module in result_tree.iteritems():
    module.report(module_name, files, diff_only)

def report_missing_thing(thing_type, thing_name, bf_covered_in_file, files):
  print('Missing {}: {}, from:'.format(thing_type, thing_name))
  for file_idx, f in enumerate(files):
    if not (bf_covered_in_file & (1 << file_idx)):
      print('\t- ' + f)

def Main():
  m = Module()
  m.get_test_case_maybe_create('qwe')

  args = parse_arguments()

  result_tree = {}
  for file_idx, f in enumerate(args.files):
    add_to_result_tree(result_tree, f, file_idx)

  tree_report(result_tree, args.files, args.diff_only)

  return 0

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