/// <summary>
        /// Default constructor accepting only test run manager instance, rest of the requirements assume default values
        /// </summary>
        public PythonTestResultParser(ITestRunManager testRunManager, ITraceLogger logger, ITelemetryDataCollector telemetry)
            : base(testRunManager, logger, telemetry)
        {
            Logger.Info("PythonTestResultParser : Starting python test result parser.");
            Telemetry.AddOrUpdate(PythonTelemetryConstants.Initialize, true, PythonTelemetryConstants.EventArea);

            _state          = ParserState.ExpectingTestResults;
            _currentTestRun = new TestRun($"{Name}/{Version}", "Python", _currentTestRunId);
        }
Beispiel #2
0
        /// <summary>
        /// Detailed constructor where specified logger and telemetry data collector are initialized along with test run manager
        /// </summary>
        /// <param name="testRunPublisher"></param>
        /// <param name="diagnosticDataCollector"></param>
        /// <param name="telemetryDataCollector"></param>
        public MochaTestResultParser(ITestRunManager testRunManager, ITraceLogger logger, ITelemetryDataCollector telemetryDataCollector) : base(testRunManager, logger, telemetryDataCollector)
        {
            Logger.Info("MochaTestResultParser : Starting mocha test result parser.");
            Telemetry.AddOrUpdate(MochaTelemetryConstants.Initialize, true, MochaTelemetryConstants.EventArea);

            // Initialize the starting state of the parser
            var testRun = new TestRun($"{Name}/{Version}", "Mocha", 1);

            _stateContext = new MochaParserStateContext(testRun);
            _currentState = MochaParserStates.ExpectingTestResults;
        }
        /// <summary>
        /// Parses input data to detect python test result.
        /// </summary>
        /// <param name="logData">Data to be parsed.</param>
        public override void Parse(LogData logData)
        {
            // Validate data input
            if (!IsValidInput(logData.Line))
            {
                return;
            }

            // TODO: Fix an appropriate threshold based on performance on hosted machine with load
            using (var timer = new SimpleTimer("PythonParserParseOperation", PythonTelemetryConstants.EventArea,
                                               PythonTelemetryConstants.PythonParserTotalTime, logData.LineNumber, Logger, Telemetry, ParseOperationPermissibleThreshold))
            {
                try
                {
                    Telemetry.AddOrUpdate(PythonTelemetryConstants.TotalLinesParsed,
                                          logData.LineNumber, PythonTelemetryConstants.EventArea);

                    switch (_state)
                    {
                    case ParserState.ExpectingSummary:

                        if (string.IsNullOrWhiteSpace(logData.Line))
                        {
                            return;
                        }

                        // Summary Test count and total time should have already been parsed
                        // Try to parse test outcome, number of tests for each outcome
                        if (TryParseSummaryOutcome(logData))
                        {
                            PublishAndReset(logData);
                            return;
                        }

                        // Summary was not parsed, reset the parser and try parse again.
                        Reset(logData);
                        Parse(logData);
                        break;

                    case ParserState.ExpectingFailedResults:

                        // Try to parse for failed results and summary
                        // If summary is parsed, change the state
                        if (TryParseForFailedResult(logData))
                        {
                            _stackTraceLinesAllowedToParse = 50;
                            return;
                        }

                        if (TryParseSummaryTestAndTime(logData))
                        {
                            _state = ParserState.ExpectingSummary;
                            Logger.Info($"PythonTestResultParser : ExpectingFailedResults: transitioned to state ExpectingSummary at line {logData.LineNumber}");
                            return;
                        }

                        // Not expected, as Summary has not been encountered yet
                        // If a new TestResult is found, reset the parser and Parse again
                        if (TryParseTestResult(logData))
                        {
                            Logger.Error($"PythonTestResultParser : Parse : Expecting failed result or summary but found new test result at line {logData.LineNumber}.");
                            Telemetry.AddAndAggregate(PythonTelemetryConstants.SummaryOrFailedTestsNotFound,
                                                      new List <int> {
                                _currentTestRunId
                            }, PythonTelemetryConstants.EventArea);
                            Reset(logData);
                            Parse(logData);
                        }

                        TryParseStackTrace(logData);

                        break;

                    case ParserState.ExpectingTestResults:

                    default:

                        if (TryParseTestResult(logData))
                        {
                            return;
                        }

                        // Change the state and clear the partial result if failed result or summary is found
                        if (TryParseForFailedResult(logData))
                        {
                            _partialTestResult             = null;
                            _state                         = ParserState.ExpectingFailedResults;
                            _stackTraceLinesAllowedToParse = 50;
                            Logger.Info($"PythonTestResultParser : ExpectingTestResults: transitioned to state ExpectingFailedResults at line {logData.LineNumber}");

                            return;
                        }

                        if (TryParseSummaryTestAndTime(logData))
                        {
                            _partialTestResult = null;
                            _state             = ParserState.ExpectingSummary;
                            Logger.Info($"PythonTestResultParser : ExpectingTestResults: transitioned to state ExpectingSummary at line {logData.LineNumber}");
                            return;
                        }

                        break;
                    }
                }
                catch (RegexMatchTimeoutException regexMatchTimeoutException)
                {
                    Logger.Warning($"PythonTestResultParser : Parse : failed due to timeout with exception { regexMatchTimeoutException } at line {logData.LineNumber}");
                    Telemetry.AddAndAggregate(PythonTelemetryConstants.RegexTimeout,
                                              new List <string> {
                        "UnknownRegex"
                    }, PythonTelemetryConstants.EventArea);
                }
                catch (Exception ex)
                {
                    Logger.Error($"PythonTestResultParser : Parse : Unable to parse the log line {logData.Line} with exception {ex.ToString()} at line {logData.LineNumber}");
                    Telemetry.AddAndAggregate(PythonTelemetryConstants.ParseException,
                                              new List <string> {
                        ex.Message
                    }, PythonTelemetryConstants.EventArea);

                    Reset(logData);

                    // Rethrow the exception so that the invoker of Parser is notified of a failure
                    throw;
                }
            }
        }
Beispiel #4
0
        /// <inheritdoc/>
        public override void Parse(LogData logData)
        {
            if (logData == null || logData.Line == null)
            {
                Logger.Error("JestTestResultParser : Parse : Input line was null.");
                return;
            }

            // TODO: Fix an appropriate threshold based on performance on hosted machine with load
            using (var timer = new SimpleTimer("JestParserParseOperation", JestTelemetryConstants.EventArea,
                                               JestTelemetryConstants.JestParserTotalTime, logData.LineNumber, Logger, Telemetry, ParseOperationPermissibleThreshold))
            {
                try
                {
                    _stateContext.CurrentLineNumber = logData.LineNumber;
                    Telemetry.AddOrUpdate(JestTelemetryConstants.TotalLinesParsed, logData.LineNumber, JestTelemetryConstants.EventArea);

                    // State model for the jest parser that defines the Regexs to match against in each state
                    // Each state re-orders the Regexs based on the frequency of expected matches
                    switch (_currentState)
                    {
                    // This state primarily looks for test run start indicator and
                    // transitions to the next one after encountering one
                    case JestParserStates.ExpectingTestRunStart:

                        if (AttemptMatch(TestRunStart, logData))
                        {
                            return;
                        }
                        break;

                    // This state primarily looks for test results and transitions
                    // to the next one after a stack trace or summary is encountered
                    case JestParserStates.ExpectingTestResults:

                        if (AttemptMatch(ExpectingTestResults, logData))
                        {
                            return;
                        }
                        break;

                    // This state primarily looks for stack traces/failed test cases
                    // and transitions on encountering summary
                    case JestParserStates.ExpectingStackTraces:

                        if (AttemptMatch(ExpectingStackTraces, logData))
                        {
                            return;
                        }
                        break;

                    // This state primarily looks for test run summary
                    // and transitions back to testresults state on encountering
                    // another test run start marker indicating tests being run from
                    // more than one file
                    case JestParserStates.ExpectingTestRunSummary:

                        if (AttemptMatch(ExpectingTestRunSummary, logData))
                        {
                            return;
                        }
                        break;
                    }
                }
                catch (Exception e)
                {
                    Logger.Error($"JestTestResultParser : Parse : Failed with exception {e}.");

                    // This might start taking a lot of space if each and every parse operation starts throwing
                    // But if that happens then there's a lot more stuff broken.
                    Telemetry.AddAndAggregate(JestTelemetryConstants.Exceptions, new List <string> {
                        e.Message
                    }, JestTelemetryConstants.EventArea);

                    // Rethrowing this so that the plugin is aware that the parser is erroring out
                    // Ideally this would never should happen
                    throw;
                }
            }
        }
Beispiel #5
0
        /// <inheritdoc/>
        public override void Parse(LogData logData)
        {
            if (logData == null || logData.Line == null)
            {
                Logger.Error("MochaTestResultParser : Parse : Input line was null.");
                return;
            }

            // TODO: Fix an appropriate threshold based on performance on hosted machine with load
            using (var timer = new SimpleTimer("MochaParserParseOperation", MochaTelemetryConstants.EventArea,
                                               MochaTelemetryConstants.MochaParserTotalTime, logData.LineNumber, Logger, Telemetry, ParseOperationPermissibleThreshold))
            {
                try
                {
                    _stateContext.CurrentLineNumber = logData.LineNumber;
                    Telemetry.AddOrUpdate(MochaTelemetryConstants.TotalLinesParsed, logData.LineNumber, MochaTelemetryConstants.EventArea);

                    // State model for the mocha parser that defines the Regexs to match against in each state
                    // Each state re-orders the Regexs based on the frequency of expected matches
                    switch (_currentState)
                    {
                    // This state primarily looks for test results
                    // and transitions to the next one after a line of summary is encountered
                    case MochaParserStates.ExpectingTestResults:

                        if (AttemptMatch(ExpectingTestResults, logData))
                        {
                            return;
                        }
                        break;

                    // This state primarily looks for test run summary
                    // If failed tests were found to be present transitions to the next one to look for stack traces
                    // else goes back to the first state after publishing the run
                    case MochaParserStates.ExpectingTestRunSummary:

                        if (AttemptMatch(ExpectingTestRunSummary, logData))
                        {
                            return;
                        }
                        break;

                    // This state primarily looks for stack traces
                    // If any other match occurs before all the expected stack traces are found,
                    // it fires telemetry for unexpected behavior but moves on to the next test run
                    case MochaParserStates.ExpectingStackTraces:

                        if (AttemptMatch(ExpectingStackTraces, logData))
                        {
                            return;
                        }
                        break;
                    }
                }
                catch (Exception e)
                {
                    Logger.Error($"MochaTestResultParser : Parse : Failed with exception {e}.");

                    // This might start taking a lot of space if each and every parse operation starts throwing
                    // But if that happens then there's a lot more stuff broken.
                    Telemetry.AddAndAggregate("Exceptions", new List <string> {
                        e.Message
                    }, MochaTelemetryConstants.EventArea);

                    // Rethrowing this so that the plugin is aware that the parser is erroring out
                    // Ideally this never should happen
                    throw;
                }
            }
        }