#!/usr/bin/python
#
# Copyright (C) 2014 Free Software Foundation, Inc.
#
# This script is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.

import sys
import getopt
import re
import io
from datetime import datetime
from operator import attrgetter

# True if unrecognised lines should cause a fatal error.  Might want to turn
# this on by default later.
strict = False

# True if the order of .log segments should match the .sum file, false if
# they should keep the original order.
sort_logs = True

# A version of open() that is safe against whatever binary output
# might be added to the log.
def safe_open (filename):
    if sys.version_info >= (3, 0):
        return open (filename, 'r', errors = 'surrogateescape')
    return open (filename, 'r')

# Force stdout to handle escape sequences from a safe_open file.
if sys.version_info >= (3, 0):
    sys.stdout = io.TextIOWrapper (sys.stdout.buffer,
                                   errors = 'surrogateescape')

class Named:
    def __init__ (self, name):
        self.name = name

class ToolRun (Named):
    def __init__ (self, name):
        Named.__init__ (self, name)
        # The variations run for this tool, mapped by --target_board name.
        self.variations = dict()

    # Return the VariationRun for variation NAME.
    def get_variation (self, name):
        if name not in self.variations:
            self.variations[name] = VariationRun (name)
        return self.variations[name]

class VariationRun (Named):
    def __init__ (self, name):
        Named.__init__ (self, name)
        # A segment of text before the harness runs start, describing which
        # baseboard files were loaded for the target.
        self.header = None
        # The harnesses run for this variation, mapped by filename.
        self.harnesses = dict()
        # A list giving the number of times each type of result has
        # been seen.
        self.counts = []

    # Return the HarnessRun for harness NAME.
    def get_harness (self, name):
        if name not in self.harnesses:
            self.harnesses[name] = HarnessRun (name)
        return self.harnesses[name]

class HarnessRun (Named):
    def __init__ (self, name):
        Named.__init__ (self, name)
        # Segments of text that make up the harness run, mapped by a test-based
        # key that can be used to order them.
        self.segments = dict()
        # Segments of text that make up the harness run but which have
        # no recognized test results.  These are typically harnesses that
        # are completely skipped for the target.
        self.empty = []
        # A list of results.  Each entry is a pair in which the first element
        # is a unique sorting key and in which the second is the full
        # PASS/FAIL line.
        self.results = []

    # Add a segment of text to the harness run.  If the segment includes
    # test results, KEY is an example of one of them, and can be used to
    # combine the individual segments in order.  If the segment has no
    # test results (e.g. because the harness doesn't do anything for the
    # current configuration) then KEY is None instead.  In that case
    # just collect the segments in the order that we see them.
    def add_segment (self, key, segment):
        if key:
            assert key not in self.segments
            self.segments[key] = segment
        else:
            self.empty.append (segment)

class Segment:
    def __init__ (self, filename, start):
        self.filename = filename
        self.start = start
        self.lines = 0

class Prog:
    def __init__ (self):
        # The variations specified on the command line.
        self.variations = []
        # The variations seen in the input files.
        self.known_variations = set()
        # The tools specified on the command line.
        self.tools = []
        # Whether to create .sum rather than .log output.
        self.do_sum = True
        # Regexps used while parsing.
        self.test_run_re = re.compile (r'^Test Run By (\S+) on (.*)$')
        self.tool_re = re.compile (r'^\t\t=== (.*) tests ===$')
        self.result_re = re.compile (r'^(PASS|XPASS|FAIL|XFAIL|UNRESOLVED'
                                     r'|WARNING|ERROR|UNSUPPORTED|UNTESTED'
                                     r'|KFAIL):\s*(.+)')
        self.completed_re = re.compile (r'.* completed at (.*)')
        # Pieces of text to write at the head of the output.
        # start_line is a pair in which the first element is a datetime
        # and in which the second is the associated 'Test Run By' line.
        self.start_line = None
        self.native_line = ''
        self.target_line = ''
        self.host_line = ''
        self.acats_premable = ''
        # Pieces of text to write at the end of the output.
        # end_line is like start_line but for the 'runtest completed' line.
        self.acats_failures = []
        self.version_output = ''
        self.end_line = None
        # Known summary types.
        self.count_names = [
            '# of DejaGnu errors\t\t',
            '# of expected passes\t\t',
            '# of unexpected failures\t',
            '# of unexpected successes\t',
            '# of expected failures\t\t',
            '# of unknown successes\t\t',
            '# of known failures\t\t',
            '# of untested testcases\t\t',
            '# of unresolved testcases\t',
            '# of unsupported tests\t\t'
        ]
        self.runs = dict()

    def usage (self):
        name = sys.argv[0]
        sys.stderr.write ('Usage: ' + name
                          + ''' [-t tool] [-l variant-list] [-L] log-or-sum-file ...

    tool           The tool (e.g. g++, libffi) for which to create a
                   new test summary file.  If not specified then output
                   is created for all tools.
    variant-list   One or more test variant names.  If the list is
                   not specified then one is constructed from all
                   variants in the files for <tool>.
    sum-file       A test summary file with the format of those
                   created by runtest from DejaGnu.
    If -L is used, merge *.log files instead of *.sum.  In this
    mode the exact order of lines may not be preserved, just different
    Running *.exp chunks should be in correct order.
''')
        sys.exit (1)

    def fatal (self, what, string):
        if not what:
            what = sys.argv[0]
        sys.stderr.write (what + ': ' + string + '\n')
        sys.exit (1)

    # Parse the command-line arguments.
    def parse_cmdline (self):
        try:
            (options, self.files) = getopt.getopt (sys.argv[1:], 'l:t:L')
            if len (self.files) == 0:
                self.usage()
            for (option, value) in options:
                if option == '-l':
                    self.variations.append (value)
                elif option == '-t':
                    self.tools.append (value)
                else:
                    self.do_sum = False
        except getopt.GetoptError as e:
            self.fatal (None, e.msg)

    # Try to parse time string TIME, returning an arbitrary time on failure.
    # Getting this right is just a nice-to-have so failures should be silent.
    def parse_time (self, time):
        try:
            return datetime.strptime (time, '%c')
        except ValueError:
            return datetime.now()

    # Parse an integer and abort on failure.
    def parse_int (self, filename, value):
        try:
            return int (value)
        except ValueError:
            self.fatal (filename, 'expected an integer, got: ' + value)

    # Return a list that represents no test results.
    def zero_counts (self):
        return [0 for x in self.count_names]

    # Return the ToolRun for tool NAME.
    def get_tool (self, name):
        if name not in self.runs:
            self.runs[name] = ToolRun (name)
        return self.runs[name]

    # Add the result counts in list FROMC to TOC.
    def accumulate_counts (self, toc, fromc):
        for i in range (len (self.count_names)):
            toc[i] += fromc[i]

    # Parse the list of variations after 'Schedule of variations:'.
    # Return the number seen.
    def parse_variations (self, filename, file):
        num_variations = 0
        while True:
            line = file.readline()
            if line == '':
                self.fatal (filename, 'could not parse variation list')
            if line == '\n':
                break
            self.known_variations.add (line.strip())
            num_variations += 1
        return num_variations

    # Parse from the first line after 'Running target ...' to the end
    # of the run's summary.
    def parse_run (self, filename, file, tool, variation, num_variations):
        header = None
        harness = None
        segment = None
        final_using = 0

        # If this is the first run for this variation, add any text before
        # the first harness to the header.
        if not variation.header:
            segment = Segment (filename, file.tell())
            variation.header = segment

        # Parse the rest of the summary (the '# of ' lines).
        if len (variation.counts) == 0:
            variation.counts = self.zero_counts()

        # Parse up until the first line of the summary.
        if num_variations == 1:
            end = '\t\t=== ' + tool.name + ' Summary ===\n'
        else:
            end = ('\t\t=== ' + tool.name + ' Summary for '
                   + variation.name + ' ===\n')
        while True:
            line = file.readline()
            if line == '':
                self.fatal (filename, 'no recognised summary line')
            if line == end:
                break

            # Look for the start of a new harness.
            if line.startswith ('Running ') and line.endswith (' ...\n'):
                # Close off the current harness segment, if any.
                if harness:
                    segment.lines -= final_using
                    harness.add_segment (first_key, segment)
                name = line[len ('Running '):-len(' ...\n')]
                harness = variation.get_harness (name)
                segment = Segment (filename, file.tell())
                first_key = None
                final_using = 0
                continue

            # Record test results.  Associate the first test result with
            # the harness segment, so that if a run for a particular harness
            # has been split up, we can reassemble the individual segments
            # in a sensible order.
            #
            # dejagnu sometimes issues warnings about the testing environment
            # before running any tests.  Treat them as part of the header
            # rather than as a test result.
            match = self.result_re.match (line)
            if match and (harness or not line.startswith ('WARNING:')):
                if not harness:
                    self.fatal (filename, 'saw test result before harness name')
                name = match.group (2)
                # Ugly hack to get the right order for gfortran.
                if name.startswith ('gfortran.dg/g77/'):
                    name = 'h' + name
                key = (name, len (harness.results))
                harness.results.append ((key, line))
                if not first_key and sort_logs:
                    first_key = key
                if line.startswith ('ERROR: (DejaGnu)'):
                    for i in range (len (self.count_names)):
                        if 'DejaGnu errors' in self.count_names[i]:
                            variation.counts[i] += 1
                            break

            # 'Using ...' lines are only interesting in a header.  Splitting
            # the test up into parallel runs leads to more 'Using ...' lines
            # than there would be in a single log.
            if line.startswith ('Using '):
                final_using += 1
            else:
                final_using = 0

            # Add other text to the current segment, if any.
            if segment:
                segment.lines += 1

        # Close off the final harness segment, if any.
        if harness:
            segment.lines -= final_using
            harness.add_segment (first_key, segment)

        while True:
            before = file.tell()
            line = file.readline()
            if line == '':
                break
            if line == '\n':
                continue
            if not line.startswith ('# '):
                file.seek (before)
                break
            found = False
            for i in range (len (self.count_names)):
                if line.startswith (self.count_names[i]):
                    count = line[len (self.count_names[i]):-1].strip()
                    variation.counts[i] += self.parse_int (filename, count)
                    found = True
                    break
            if not found:
                self.fatal (filename, 'unknown test result: ' + line[:-1])

    # Parse an acats run, which uses a different format from dejagnu.
    # We have just skipped over '=== acats configuration ==='.
    def parse_acats_run (self, filename, file):
        # Parse the preamble, which describes the configuration and logs
        # the creation of support files.
        record = (self.acats_premable == '')
        if record:
            self.acats_premable = '\t\t=== acats configuration ===\n'
        while True:
            line = file.readline()
            if line == '':
                self.fatal (filename, 'could not parse acats preamble')
            if line == '\t\t=== acats tests ===\n':
                break
            if record:
                self.acats_premable += line

        # Parse the test results themselves, using a dummy variation name.
        tool = self.get_tool ('acats')
        variation = tool.get_variation ('none')
        self.parse_run (filename, file, tool, variation, 1)

        # Parse the failure list.
        while True:
            before = file.tell()
            line = file.readline()
            if line.startswith ('*** FAILURES: '):
                self.acats_failures.append (line[len ('*** FAILURES: '):-1])
                continue
            file.seek (before)
            break

    # Parse the final summary at the end of a log in order to capture
    # the version output that follows it.
    def parse_final_summary (self, filename, file):
        record = (self.version_output == '')
        while True:
            line = file.readline()
            if line == '':
                break
            if line.startswith ('# of '):
                continue
            if record:
                self.version_output += line
            if line == '\n':
                break

    # Parse a .log or .sum file.
    def parse_file (self, filename, file):
        tool = None
        target = None
        num_variations = 1
        while True:
            line = file.readline()
            if line == '':
                return

            # Parse the list of variations, which comes before the test
            # runs themselves.
            if line.startswith ('Schedule of variations:'):
                num_variations = self.parse_variations (filename, file)
                continue

            # Parse a testsuite run for one tool/variation combination.
            if line.startswith ('Running target '):
                name = line[len ('Running target '):-1]
                if not tool:
                    self.fatal (filename, 'could not parse tool name')
                if name not in self.known_variations:
                    self.fatal (filename, 'unknown target: ' + name)
                self.parse_run (filename, file, tool,
                                tool.get_variation (name),
                                num_variations)
                # If there is only one variation then there is no separate
                # summary for it.  Record any following version output.
                if num_variations == 1:
                    self.parse_final_summary (filename, file)
                continue

            # Parse the start line.  In the case where several files are being
            # parsed, pick the one with the earliest time.
            match = self.test_run_re.match (line)
            if match:
                time = self.parse_time (match.group (2))
                if not self.start_line or self.start_line[0] > time:
                    self.start_line = (time, line)
                continue

            # Parse the form used for native testing.
            if line.startswith ('Native configuration is '):
                self.native_line = line
                continue

            # Parse the target triplet.
            if line.startswith ('Target is '):
                self.target_line = line
                continue

            # Parse the host triplet.
            if line.startswith ('Host   is '):
                self.host_line = line
                continue

            # Parse the acats premable.
            if line == '\t\t=== acats configuration ===\n':
                self.parse_acats_run (filename, file)
                continue

            # Parse the tool name.
            match = self.tool_re.match (line)
            if match:
                tool = self.get_tool (match.group (1))
                continue

            # Skip over the final summary (which we instead create from
            # individual runs) and parse the version output.
            if tool and line == '\t\t=== ' + tool.name + ' Summary ===\n':
                if file.readline() != '\n':
                    self.fatal (filename, 'expected blank line after summary')
                self.parse_final_summary (filename, file)
                continue

            # Parse the completion line.  In the case where several files
            # are being parsed, pick the one with the latest time.
            match = self.completed_re.match (line)
            if match:
                time = self.parse_time (match.group (1))
                if not self.end_line or self.end_line[0] < time:
                    self.end_line = (time, line)
                continue

            # Sanity check to make sure that important text doesn't get
            # dropped accidentally.
            if strict and line.strip() != '':
                self.fatal (filename, 'unrecognised line: ' + line[:-1])

    # Output a segment of text.
    def output_segment (self, segment):
        with safe_open (segment.filename) as file:
            file.seek (segment.start)
            for i in range (segment.lines):
                sys.stdout.write (file.readline())

    # Output a summary giving the number of times each type of result has
    # been seen.
    def output_summary (self, tool, counts):
        for i in range (len (self.count_names)):
            name = self.count_names[i]
            # dejagnu only prints result types that were seen at least once,
            # but acats always prints a number of unexpected failures.
            if (counts[i] > 0
                or (tool.name == 'acats'
                    and name.startswith ('# of unexpected failures'))):
                sys.stdout.write ('%s%d\n' % (name, counts[i]))

    # Output unified .log or .sum information for a particular variation,
    # with a summary at the end.
    def output_variation (self, tool, variation):
        self.output_segment (variation.header)
        for harness in sorted (variation.harnesses.values(),
                               key = attrgetter ('name')):
            sys.stdout.write ('Running ' + harness.name + ' ...\n')
            if self.do_sum:
                harness.results.sort()
                for (key, line) in harness.results:
                    sys.stdout.write (line)
            else:
                # Rearrange the log segments into test order (but without
                # rearranging text within those segments).
                for key in sorted (harness.segments.keys()):
                    self.output_segment (harness.segments[key])
                for segment in harness.empty:
                    self.output_segment (segment)
        if len (self.variations) > 1:
            sys.stdout.write ('\t\t=== ' + tool.name + ' Summary for '
                              + variation.name + ' ===\n\n')
            self.output_summary (tool, variation.counts)

    # Output unified .log or .sum information for a particular tool,
    # with a summary at the end.
    def output_tool (self, tool):
        counts = self.zero_counts()
        if tool.name == 'acats':
            # acats doesn't use variations, so just output everything.
            # It also has a different approach to whitespace.
            sys.stdout.write ('\t\t=== ' + tool.name + ' tests ===\n')
            for variation in tool.variations.values():
                self.output_variation (tool, variation)
                self.accumulate_counts (counts, variation.counts)
            sys.stdout.write ('\t\t=== ' + tool.name + ' Summary ===\n')
        else:
            # Output the results in the usual dejagnu runtest format.
            sys.stdout.write ('\n\t\t=== ' + tool.name + ' tests ===\n\n'
                              'Schedule of variations:\n')
            for name in self.variations:
                if name in tool.variations:
                    sys.stdout.write ('    ' + name + '\n')
            sys.stdout.write ('\n')
            for name in self.variations:
                if name in tool.variations:
                    variation = tool.variations[name]
                    sys.stdout.write ('Running target '
                                      + variation.name + '\n')
                    self.output_variation (tool, variation)
                    self.accumulate_counts (counts, variation.counts)
            sys.stdout.write ('\n\t\t=== ' + tool.name + ' Summary ===\n\n')
        self.output_summary (tool, counts)

    def main (self):
        self.parse_cmdline()
        try:
            # Parse the input files.
            for filename in self.files:
                with safe_open (filename) as file:
                    self.parse_file (filename, file)

            # Decide what to output.
            if len (self.variations) == 0:
                self.variations = sorted (self.known_variations)
            else:
                for name in self.variations:
                    if name not in self.known_variations:
                        self.fatal (None, 'no results for ' + name)
            if len (self.tools) == 0:
                self.tools = sorted (self.runs.keys())

            # Output the header.
            if self.start_line:
                sys.stdout.write (self.start_line[1])
            sys.stdout.write (self.native_line)
            sys.stdout.write (self.target_line)
            sys.stdout.write (self.host_line)
            sys.stdout.write (self.acats_premable)

            # Output the main body.
            for name in self.tools:
                if name not in self.runs:
                    self.fatal (None, 'no results for ' + name)
                self.output_tool (self.runs[name])

            # Output the footer.
            if len (self.acats_failures) > 0:
                sys.stdout.write ('*** FAILURES: '
                                  + ' '.join (self.acats_failures) + '\n')
            sys.stdout.write (self.version_output)
            if self.end_line:
                sys.stdout.write (self.end_line[1])
        except IOError as e:
            self.fatal (e.filename, e.strerror)

Prog().main()
