#!/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 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())
