Example #1
0
        private IList <TestFileSummary> ReadFromStream(StreamReader stream, TestContext testContext, TestOptions testOptions, ITestMethodRunnerCallback callback, bool debugEnabled)
        {
            var codeCoverageEnabled = (!testContext.TestFileSettings.EnableCodeCoverage.HasValue && testOptions.CoverageOptions.Enabled) ||
                                      (testContext.TestFileSettings.EnableCodeCoverage.HasValue && testContext.TestFileSettings.EnableCodeCoverage.Value);

            var testFileContexts = testContext.ReferencedFiles
                                   .Where(x => x.IsFileUnderTest)
                                   .Select(x => new TestFileContext(x, testContext, codeCoverageEnabled))
                                   .ToList();


            var testIndex = 0;

            string          line;
            TestFileContext currentTestFileContext = null;

            if (testFileContexts.Count == 1)
            {
                currentTestFileContext = testFileContexts.First();
            }

            var deferredEvents = new List <Action <TestFileContext> >();

            while ((line = stream.ReadLine()) != null)
            {
                if (debugEnabled)
                {
                    Console.WriteLine(line);
                }

                var match = prefixRegex.Match(line);
                if (!match.Success)
                {
                    continue;
                }
                var type = match.Groups["type"].Value;
                var json = match.Groups["json"].Value;

                // Only update last event timestamp if it is an important event.
                // Log and error could happen even though no test progress is made
                if (!type.Equals("Log") && !type.Equals("Error"))
                {
                    lastTestEvent = DateTime.Now;
                }


                try
                {
                    switch (type)
                    {
                    case "FileStart":

                        FireFileStarted(callback, testContext);

                        break;

                    case "CoverageObject":

                        var jsCov = jsonSerializer.Deserialize <JsCoverage>(json);

                        if (currentTestFileContext == null)
                        {
                            deferredEvents.Add((fileContext) => FireCoverageObject(callback, fileContext, jsCov));
                        }
                        else
                        {
                            FireCoverageObject(callback, currentTestFileContext, jsCov);
                        }

                        break;

                    case "FileDone":

                        var jsFileDone = jsonSerializer.Deserialize <JsFileDone>(json);
                        FireFileFinished(callback, testContext.InputTestFilesString, testFileContexts, jsFileDone);

                        break;

                    case "TestStart":
                        var             jsTestCaseStart = jsonSerializer.Deserialize <JsTestCase>(json);
                        TestFileContext newContext      = null;
                        var             testName        = jsTestCaseStart.TestCase.TestName.Trim();
                        var             moduleName      = (jsTestCaseStart.TestCase.ModuleName ?? "").Trim();


                        var fileContexts = GetFileMatches(testName, testFileContexts);
                        if (fileContexts.Count == 0 && currentTestFileContext == null)
                        {
                            // If there are no matches and not file context has been used yet
                            // then just choose the first context
                            newContext = testFileContexts[0];
                        }
                        else if (fileContexts.Count == 0)
                        {
                            // If there is already a current context and no matches we just keep using that context
                            // unless this test name has been used already in the current context. In that case
                            // move to the next one that hasn't seen this file yet

                            var testAlreadySeenInCurrentContext = currentTestFileContext.HasTestBeenSeen(moduleName, testName);
                            if (testAlreadySeenInCurrentContext)
                            {
                                newContext = testFileContexts.FirstOrDefault(x => !x.HasTestBeenSeen(moduleName, testName)) ?? currentTestFileContext;
                            }
                        }
                        else if (fileContexts.Count > 1)
                        {
                            // If we found the test has more than one file match
                            // try to choose the best match, otherwise just choose the first one

                            // If we have no file context yet take the first one
                            if (currentTestFileContext == null)
                            {
                                newContext = fileContexts.First();
                            }
                            else
                            {
                                // In this case we have an existing file context so we need to
                                // 1. Check to see if this test has been seen already on that context
                                //    if so we need to try the next file context that matches it
                                // 2. If it is not seen yet in the current context and the current context
                                //    is one of the matches then keep using it

                                var testAlreadySeenInCurrentContext = currentTestFileContext.HasTestBeenSeen(moduleName, testName);
                                var currentContextInFileMatches     = fileContexts.Any(x => x == currentTestFileContext);
                                if (!testAlreadySeenInCurrentContext && currentContextInFileMatches)
                                {
                                    // Keep the current context
                                    newContext = currentTestFileContext;
                                }
                                else
                                {
                                    // Either take first not used context OR the first one
                                    newContext = fileContexts.Where(x => !x.IsUsed).FirstOrDefault() ?? fileContexts.First();
                                }
                            }
                        }
                        else if (fileContexts.Count == 1)
                        {
                            // We found a unique match
                            newContext = fileContexts[0];
                        }


                        if (newContext != null && newContext != currentTestFileContext)
                        {
                            currentTestFileContext = newContext;
                            testIndex = 0;
                        }

                        currentTestFileContext.IsUsed = true;

                        currentTestFileContext.MarkTestSeen(moduleName, testName);

                        PlayDeferredEvents(currentTestFileContext, deferredEvents);

                        jsTestCaseStart.TestCase.InputTestFile = currentTestFileContext.ReferencedFile.Path;
                        callback.TestStarted(jsTestCaseStart.TestCase);

                        break;

                    case "TestDone":
                        var jsTestCaseDone   = jsonSerializer.Deserialize <JsTestCase>(json);
                        var currentTestIndex = testIndex;

                        FireTestFinished(callback, currentTestFileContext, jsTestCaseDone, currentTestIndex);

                        testIndex++;

                        break;

                    case "Log":
                        var log = jsonSerializer.Deserialize <JsLog>(json);

                        if (currentTestFileContext != null)
                        {
                            FireLogOutput(callback, currentTestFileContext, log);
                        }
                        else
                        {
                            deferredEvents.Add((fileContext) => FireLogOutput(callback, fileContext, log));
                        }
                        break;

                    case "Error":
                        var error = jsonSerializer.Deserialize <JsError>(json);
                        if (currentTestFileContext != null)
                        {
                            FireErrorOutput(callback, currentTestFileContext, error);
                        }
                        else
                        {
                            deferredEvents.Add((fileContext) => FireErrorOutput(callback, fileContext, error));
                        }

                        break;
                    }
                }
                catch (SerializationException e)
                {
                    // Ignore malformed json and move on
                    ChutzpahTracer.TraceError(e, "Recieved malformed json from Phantom in this line: '{0}'", line);
                }
            }

            return(testFileContexts.Select(x => x.TestFileSummary).ToList());
        }