/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.tradefed.testtype;

import com.android.ddmlib.MultiLineReceiver;
import com.android.tradefed.error.HarnessRuntimeException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.error.TestErrorIdentifier;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Interprets the output of tests run with Python's unittest framework and translates it into calls
 * on a series of {@link ITestInvocationListener}s. Output from these tests follows this EBNF
 * grammar:
 *
 * <p>TestReport ::= TestResult* Line TimeMetric [FailMessage*] Status. TestResult ::= string
 * “(“string”)” “…” SingleStatus. FailMessage ::= EqLine “ERROR:” string “(“string”)” Line Traceback
 * Line. SingleStatus ::= “ok” | “ERROR”. TimeMetric ::= “Ran” integer “tests in” float ”s”. Status
 * ::= “OK” | “FAILED (errors=” int “)”. Traceback ::= string+.
 *
 * <p>Example output (passing): test_size (test_rangelib.RangeSetTest) ... ok test_str
 * (test_rangelib.RangeSetTest) ... ok test_subtract (test_rangelib.RangeSetTest) ... ok
 * test_to_string_raw (test_rangelib.RangeSetTest) ... ok test_union (test_rangelib.RangeSetTest)
 * ... ok
 *
 * <p>---------------------------------------------------------------------- Ran 5 tests in 0.002s
 *
 * <p>OK
 *
 * <p>Example output (failed) test_size (test_rangelib.RangeSetTest) ... ERROR
 *
 * <p>====================================================================== ERROR: test_size
 * (test_rangelib.RangeSetTest)
 * ---------------------------------------------------------------------- Traceback (most recent
 * call last): File "test_rangelib.py", line 129, in test_rangelib raise ValueError() ValueError
 * ---------------------------------------------------------------------- Ran 1 test in 0.001s
 * FAILED (errors=1)
 *
 * <p>Example output with several edge cases (failed): testError (foo.testFoo) ... ERROR
 * testExpectedFailure (foo.testFoo) ... expected failure testFail (foo.testFoo) ... FAIL
 * testFailWithDocString (foo.testFoo) foo bar ... FAIL testOk (foo.testFoo) ... ok
 * testOkWithDocString (foo.testFoo) foo bar ... ok testSkipped (foo.testFoo) ... skipped 'reason
 * foo' testUnexpectedSuccess (foo.testFoo) ... unexpected success
 *
 * <p>====================================================================== ERROR: testError
 * (foo.testFoo) ---------------------------------------------------------------------- Traceback
 * (most recent call last): File "foo.py", line 11, in testError self.assertEqual(2+2, 5/0)
 * ZeroDivisionError: integer division or modulo by zero
 *
 * <p>====================================================================== FAIL: testFail
 * (foo.testFoo) ---------------------------------------------------------------------- Traceback
 * (most recent call last): File "foo.py", line 8, in testFail self.assertEqual(2+2, 5)
 * AssertionError: 4 != 5
 *
 * <p>====================================================================== FAIL:
 * testFailWithDocString (foo.testFoo) foo bar
 * ---------------------------------------------------------------------- Traceback (most recent
 * call last): File "foo.py", line 31, in testFailWithDocString self.assertEqual(2+2, 5)
 * AssertionError: 4 != 5
 *
 * <p>---------------------------------------------------------------------- Ran 8 tests in 0.001s
 *
 * <p>FAILED (failures=2, errors=1, skipped=1, expected failures=1, unexpected successes=1)
 *
 * <p>TODO: Consider refactoring the full class, handling is quite messy right now.
 */
public class PythonUnitTestResultParser extends MultiLineReceiver {

    private boolean mFinalizeWhenParsing = true;
    // Current test state
    private ParserState mCurrentParseState;
    private String mCurrentTestName;
    private String mCurrentTestClass;
    private String mCurrentTestStatus;
    private Matcher mCurrentMatcher;
    private StringBuilder mCurrentTraceback;
    private long mTotalElapsedTime;
    private int mTotalTestCount;
    private String mCurrentTestCaseString = null;

    // Filters used for parsing test methods.
    private Set<String> mIncludeFilters = new LinkedHashSet<>();
    private Set<String> mExcludeFilters = new LinkedHashSet<>();

    // General state
    private Collection<ITestInvocationListener> mListeners = new ArrayList<>();
    private final String mRunName;
    private Map<TestDescription, String> mTestResultCache;
    // Use a special entry to mark skipped test in mTestResultCache
    static final String SKIPPED_ENTRY = "Skipped";

    // Constant tokens that appear in the result grammar.
    static final String EQUAL_LINE =
            "======================================================================";
    static final String DASH_LINE =
            "----------------------------------------------------------------------";
    static final String TRACEBACK_LINE = "Traceback (most recent call last):";

    static final Pattern PATTERN_TEST_SUCCESS = Pattern.compile("ok|expected failure");
    static final Pattern PATTERN_TEST_FAILURE = Pattern.compile("FAIL|ERROR");
    static final Pattern PATTERN_TEST_SKIPPED = Pattern.compile("skipped '.*");
    static final Pattern PATTERN_TEST_UNEXPECTED_SUCCESS = Pattern.compile("unexpected success");

    static final Pattern PATTERN_ONE_LINE_RESULT =
            Pattern.compile(
                    "(\\S*) \\((\\S*)\\) \\.\\.\\. "
                            + "(ok|expected failure|FAIL|ERROR|skipped '.*'|unexpected success)?");
    static final Pattern PATTERN_TWO_LINE_RESULT_FIRST = Pattern.compile("(\\S*) \\((\\S*)\\)");
    static final Pattern PATTERN_TWO_LINE_RESULT_SECOND =
            Pattern.compile(
                    "(.*) \\.\\.\\. "
                            + "(ok|expected failure|FAIL|ERROR|skipped '.*'|unexpected success)");
    static final Pattern PATTERN_TWO_LINE_RESULT_SECOND_ERROR =
            Pattern.compile(
                    "(.*) \\.\\.\\. error: (.*)"
                            + "(ok|expected failure|FAIL|ERROR|skipped '.*'|unexpected success)",
                    Pattern.DOTALL);
    static final Pattern PATTERN_FAIL_MESSAGE =
            Pattern.compile("(FAIL|ERROR): (\\S*) \\((\\S*)\\)( \\(.*\\))?");

    static final Pattern PATTERN_RUN_SUMMARY =
            Pattern.compile("Ran (\\d+) tests? in (\\d+(.\\d*)?)s(.*)");

    /** In case of error spanning over multiple lines. */
    static final Pattern MULTILINE_RESULT_WITH_WARNING =
            Pattern.compile("(.*) \\.\\.\\. (.*)", Pattern.DOTALL);

    static final Pattern MULTILINE_FINAL_RESULT_WITH_WARNING =
            Pattern.compile("(.*) \\.\\.\\. (.*)ok(.*)", Pattern.DOTALL);

    /** Unexpected (multiline) text between ... and test status - likely corrupted */
    static final Pattern PATTERN_MULTILINE_RESULT_FIRST =
            Pattern.compile("(\\S*) \\((\\S*)\\) \\.\\.\\. .+");

    static final Pattern PATTERN_MULTILINE_RESULT_FIRST_NEGATIVE =
            Pattern.compile(
                    "(\\S*) \\((\\S*)\\) \\.\\.\\. (ok|expected failure|FAIL|ERROR|error|skipped"
                            + " '.*'|unexpected success).*");
    static final Pattern PATTERN_MULTILINE_RESULT_LAST =
            Pattern.compile("(ok|expected failure|FAIL|ERROR|skipped '.*'|unexpected success)");

    static final Pattern PATTERN_RUN_RESULT = Pattern.compile("(OK|FAILED).*");

    enum ParserState {
        TEST_CASE,
        FAIL_MESSAGE,
        TRACEBACK,
        SUMMARY,
        COMPLETE,
    }

    private class PythonUnitTestParseException extends Exception {
        static final long serialVersionUID = -3387516993124229948L;

        public PythonUnitTestParseException(String reason) {
            super(reason);
        }
    }

    /**
     * Create a new {@link PythonUnitTestResultParser} that reports to the given {@link
     * ITestInvocationListener}.
     */
    public PythonUnitTestResultParser(ITestInvocationListener listener, String runName) {
        this(Arrays.asList(listener), runName);
    }

    /**
     * Create a new {@link PythonUnitTestResultParser} that reports to the given {@link
     * ITestInvocationListener}s.
     */
    public PythonUnitTestResultParser(
            Collection<ITestInvocationListener> listeners, String runName) {
        this(listeners, runName, new LinkedHashSet<>(), new LinkedHashSet<>());
    }

    /**
     * Create a new {@link PythonUnitTestResultParser} that reports to the given {@link
     * ITestInvocationListener}s, with specified include and exclude filters.
     */
    public PythonUnitTestResultParser(
            Collection<ITestInvocationListener> listeners,
            String runName,
            Set<String> includeFilters,
            Set<String> excludeFilters) {
        mListeners.addAll(listeners);
        mRunName = runName;
        mTestResultCache = new LinkedHashMap<>();
        mIncludeFilters = includeFilters;
        mExcludeFilters = excludeFilters;
        mCurrentParseState = ParserState.TEST_CASE;
    }

    /**
     * Process Python unittest output and report parsed results.
     *
     * <p>This method should be called only once with the full output, unlike the base method in
     * {@link MultiLineReceiver}.
     */
    @Override
    public void processNewLines(String[] lines) {
        try {
            if (lines.length < 1 || isTracebackLine(lines[0])) {
                throw new PythonUnitTestParseException("Test execution failed");
            }

            for (String line : lines) {
                parse(line);
            }

            if (mFinalizeWhenParsing) {
                finalizeParser();
            }
        } catch (PythonUnitTestParseException e) {
            throw new HarnessRuntimeException(
                    e.getMessage(), TestErrorIdentifier.OUTPUT_PARSER_ERROR);
        }
    }

    public void setFinalizeWhenParsing(boolean shouldFinalize) {
        mFinalizeWhenParsing = shouldFinalize;
    }

    public void finalizeParser() {
        if (mCurrentParseState != ParserState.COMPLETE) {
            throw new HarnessRuntimeException(
                    "Parser finished in unexpected state " + mCurrentParseState.toString(),
                    TestErrorIdentifier.OUTPUT_PARSER_ERROR);
        }
    }

    /** Parse the next result line according to current parser state. */
    void parse(String line) throws PythonUnitTestParseException {
        CLog.v(line);
        switch (mCurrentParseState) {
            case TEST_CASE:
                processTestCase(line);
                break;
            case TRACEBACK:
                processTraceback(line);
                break;
            case SUMMARY:
                processRunSummary(line);
                break;
            case FAIL_MESSAGE:
                processFailMessage(line);
                break;
            case COMPLETE:
                break;
        }
    }

    /** Process a test case line and collect the test name, class, and status. */
    void processTestCase(String line) throws PythonUnitTestParseException {
        if (mCurrentTestCaseString != null) {
            mCurrentTestCaseString = mCurrentTestCaseString + "\n" + line;
            line = mCurrentTestCaseString;
        }

        if (isEqualLine(line)) {
            // equal line before fail message
            mCurrentParseState = ParserState.FAIL_MESSAGE;
            mCurrentTestCaseString = null;
        } else if (isDashLine(line)) {
            // dash line before run summary
            mCurrentParseState = ParserState.SUMMARY;
            mCurrentTestCaseString = null;
        } else if (lineStartswithPattern(line, PATTERN_ONE_LINE_RESULT)) {
            // The below parsing is involved due to output from tests that use Python's subTest
            // feature. In particular, a line could contain multiple test case summary lines such
            // as; a (T) ... b (T) ... ok.
            // TODO(hzalek): Consider adding a Python support library for writing the output of the
            // test in a structured format to avoid parsing string output.
            List<MatchResult> matchResults = new ArrayList<>();

            // Collect the results to avoid modifying state in case the entire line doesn't match.
            do {
                matchResults.add(mCurrentMatcher.toMatchResult());
            } while (mCurrentMatcher.find());

            int lastMatchEnd = matchResults.get(matchResults.size() - 1).end();
            if (lastMatchEnd != line.length()) {
                boolean canBeMultiline =
                        !lineMatchesPattern(line, PATTERN_MULTILINE_RESULT_FIRST_NEGATIVE);
                if (canBeMultiline && lineMatchesPattern(line, PATTERN_MULTILINE_RESULT_FIRST)) {
                    mCurrentTestName = mCurrentMatcher.group(1);
                    mCurrentTestClass =
                            removeTestNameFromClassNameGroup(
                                    mCurrentMatcher.group(2), mCurrentTestName);
                    mCurrentTestCaseString = null;
                }
                return; // The entire line doesn't match so just ignore it.
            }

            for (MatchResult r : matchResults) {
                mCurrentTestName = r.group(1);
                mCurrentTestClass = removeTestNameFromClassNameGroup(r.group(2), mCurrentTestName);
                mCurrentTestStatus = r.group(3);

                // Tests with failed subtests have no status printed so we add an entry with 'FAIL'
                // status. In any case, subsequent failed subtest assertions have the same test name
                // and will clobber whatever status we set here. Passed subtest assertions don't
                // appear in the output and do not risk overwriting the status.
                if (mCurrentTestStatus == null) {
                    mCurrentTestStatus = "FAIL";
                }

                reportNonFailureTestResult();
            }

            mCurrentTestCaseString = null;
        } else if (lineMatchesPattern(line, PATTERN_MULTILINE_RESULT_LAST)) {
            mCurrentTestStatus = mCurrentMatcher.group(1);
            reportNonFailureTestResult();
            mCurrentTestCaseString = null;
        } else if (lineMatchesPattern(line, PATTERN_TWO_LINE_RESULT_FIRST)) {
            mCurrentTestName = mCurrentMatcher.group(1);
            mCurrentTestClass =
                    removeTestNameFromClassNameGroup(mCurrentMatcher.group(2), mCurrentTestName);
            mCurrentTestCaseString = null;
        } else if (lineMatchesPattern(line, PATTERN_TWO_LINE_RESULT_SECOND)) {
            mCurrentTestStatus = mCurrentMatcher.group(2);
            reportNonFailureTestResult();
            mCurrentTestCaseString = null;
        } else if (lineMatchesPattern(line, PATTERN_TWO_LINE_RESULT_SECOND_ERROR)) {
            // Skip that odd error message
            mCurrentTestCaseString = null;
        } else if (lineMatchesPattern(line, MULTILINE_FINAL_RESULT_WITH_WARNING)) {
            StringBuilder message = new StringBuilder("Test seems to pass but with Warnings:\n");
            message.append(mCurrentMatcher.group(2));
            mCurrentTraceback = message;
            reportFailureTestResult();
            mCurrentTestCaseString = null;
        } else if (lineMatchesPattern(line, MULTILINE_RESULT_WITH_WARNING)) {
            if (mCurrentTestCaseString == null) {
                mCurrentTestCaseString = line;
            }
        }
    }

    String removeTestNameFromClassNameGroup(String classNameGroup, String testName) {
        if (!classNameGroup.endsWith(testName)) {
            return classNameGroup;
        }
        Pattern p = Pattern.compile("(.*)\\." + testName);
        Matcher matcher = p.matcher(classNameGroup);
        if (!matcher.matches()) {
            return classNameGroup;
        }
        return matcher.group(1);
    }

    /** Process a fail message line and collect the test name, class, and status. */
    void processFailMessage(String line) {
        if (isDashLine(line)) {
            // dash line before traceback
            mCurrentParseState = ParserState.TRACEBACK;
            mCurrentTraceback = new StringBuilder();
        } else if (lineMatchesPattern(line, PATTERN_FAIL_MESSAGE)) {
            mCurrentTestName = mCurrentMatcher.group(2);
            mCurrentTestClass =
                    removeTestNameFromClassNameGroup(mCurrentMatcher.group(3), mCurrentTestName);
            mCurrentTestStatus = mCurrentMatcher.group(1);
        }
        // optional docstring - do nothing
    }

    /** Process a traceback line and append it to the full traceback message. */
    void processTraceback(String line) {
        if (isDashLine(line)) {
            // dash line before run summary
            mCurrentParseState = ParserState.SUMMARY;
            reportFailureTestResult();
        } else if (isEqualLine(line)) {
            // equal line before another fail message followed by traceback
            mCurrentParseState = ParserState.FAIL_MESSAGE;
            reportFailureTestResult();
        } else {
            if (mCurrentTraceback.length() > 0) {
                mCurrentTraceback.append(System.lineSeparator());
            }
            mCurrentTraceback.append(line);
        }
    }

    /** Process the run summary line and collect the test count and run time. */
    void processRunSummary(String line) {
        if (lineMatchesPattern(line, PATTERN_RUN_SUMMARY)) {
            mTotalTestCount = Integer.parseInt(mCurrentMatcher.group(1));
            double timeInSeconds = Double.parseDouble(mCurrentMatcher.group(2));
            mTotalElapsedTime = (long) (timeInSeconds * 1000D);
            reportToListeners();
            mCurrentParseState = ParserState.COMPLETE;
        }
        // ignore status message on the last line because Python consider "unexpected success"
        // passed while we consider it failed
    }

    boolean isEqualLine(String line) {
        return line.startsWith(EQUAL_LINE);
    }

    boolean isDashLine(String line) {
        return line.startsWith(DASH_LINE);
    }

    boolean isTracebackLine(String line) {
        return line.startsWith(TRACEBACK_LINE);
    }

    /** Check if the given line matches the given pattern and caches the matcher object */
    private boolean lineMatchesPattern(String line, Pattern p) {
        mCurrentMatcher = p.matcher(line);
        return mCurrentMatcher.matches();
    }

    private boolean lineStartswithPattern(String line, Pattern p) {
        mCurrentMatcher = p.matcher(line);
        return mCurrentMatcher.find();
    }

    /** Send recorded test results to all listeners. */
    private void reportToListeners() {
        for (ITestInvocationListener listener : mListeners) {
            listener.testRunStarted(mRunName, mTotalTestCount);

            for (Entry<TestDescription, String> test : mTestResultCache.entrySet()) {
                listener.testStarted(test.getKey());
                if (SKIPPED_ENTRY.equals(test.getValue())) {
                    listener.testIgnored(test.getKey());
                } else if (test.getValue() != null) {
                    listener.testFailed(test.getKey(), test.getValue());
                }
                listener.testEnded(test.getKey(), new HashMap<String, Metric>());
            }
            listener.testRunEnded(mTotalElapsedTime, new HashMap<String, Metric>());
        }
    }

    /** Record a non-failure test case. */
    private void reportNonFailureTestResult() throws PythonUnitTestParseException {
        TestDescription testId = new TestDescription(mCurrentTestClass, mCurrentTestName);

        if (shouldSkipCurrentTest()) {
            // Force to skip any test not listed in include filters, or listed in exclude filters.
            mTestResultCache.put(testId, SKIPPED_ENTRY);
        } else if (PATTERN_TEST_SUCCESS.matcher(mCurrentTestStatus).matches()) {
            mTestResultCache.put(testId, null);
        } else if (PATTERN_TEST_SKIPPED.matcher(mCurrentTestStatus).matches()) {
            mTestResultCache.put(testId, SKIPPED_ENTRY);
        } else if (PATTERN_TEST_UNEXPECTED_SUCCESS.matcher(mCurrentTestStatus).matches()) {
            mTestResultCache.put(testId, "Test unexpected succeeded");
        } else if (PATTERN_TEST_FAILURE.matcher(mCurrentTestStatus).matches()) {
            // do nothing for now, report only after traceback is collected
        } else {
            throw new PythonUnitTestParseException("Unrecognized test status");
        }
    }

    /** Record a failed test case and its traceback message. */
    private void reportFailureTestResult() {
        TestDescription testId = new TestDescription(mCurrentTestClass, mCurrentTestName);
        if (shouldSkipCurrentTest()) {
            mTestResultCache.put(testId, SKIPPED_ENTRY);
        } else {
            mTestResultCache.put(testId, mCurrentTraceback.toString());
        }
    }

    /**
     * Check if current test should be skipped.
     *
     * @return true if the test should be skipped.
     */
    private boolean shouldSkipCurrentTest() {
        // Force to skip any test not listed in include filters, or listed in exclude filters.
        // exclude filters have highest priority.
        if (mExcludeFilters.contains(mCurrentTestClass + "#" + mCurrentTestName)
                || mExcludeFilters.contains(mCurrentTestClass)) {
            return true;
        }
        if (!mIncludeFilters.isEmpty()) {
            if (mIncludeFilters.contains(mCurrentTestClass + "#" + mCurrentTestName)
                    || mIncludeFilters.contains(mCurrentTestClass)) {
                return false;
            }
            for (String filter : mIncludeFilters) {
                if ((mCurrentTestClass + "#" + mCurrentTestName).matches(filter)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    @Override
    public boolean isCancelled() {
        return false;
    }
}
