From 80188909e558d883c8b1b5a255c53b945f7ab37f Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 26 Feb 2017 18:46:07 +0100 Subject: [PATCH 1/5] removed old test execution framework (#106) --- .gitignore | 2 +- GoogleTestAdapter/.gitignore | 2 +- GoogleTestAdapter/Common/Common.csproj | 1 - .../Core.Tests/Core.Tests.csproj | 5 +- .../Core.Tests/GoogleTestExecutorTests.cs | 6 +- .../Helpers/TestProcessLauncherTests.cs | 69 ----- .../Runners/SequentialTestRunnerTests.cs | 6 +- .../Settings/SettingsWrapperTests.cs | 1 - .../TestCases/ListTestsParserTests.cs | 166 ------------ .../StandardOutputTestResultParserTests.cs | 254 ------------------ ...s.cs => StreamingTestOutputParserTests.cs} | 31 ++- GoogleTestAdapter/Core/Core.csproj | 9 +- .../Framework/IDebuggedProcessLauncher.cs | 9 - .../Core/Framework/IProcessExecutor.cs | 22 -- .../Core/GoogleTestDiscoverer.cs | 38 +-- GoogleTestAdapter/Core/GoogleTestExecutor.cs | 12 +- .../Core/Helpers/ProcessExecutor.cs | 33 ++- .../Core/Helpers/ProcessLauncher.cs | 109 -------- .../Core/Helpers/TestProcessLauncher.cs | 97 ------- GoogleTestAdapter/Core/Runners/ITestRunner.cs | 4 +- .../Core/Runners/ParallelTestRunner.cs | 14 +- .../Core/Runners/PreparingTestRunner.cs | 35 +-- .../Core/Runners/SequentialTestRunner.cs | 84 ++---- .../Settings/IGoogleTestAdapterSettings.cs | 2 - .../Core/Settings/RunSettings.cs | 3 - .../Core/Settings/SettingsWrapper.cs | 8 - .../Core/TestCases/ListTestsParser.cs | 32 --- .../Core/TestCases/NewTestCaseResolver.cs | 121 --------- .../Core/TestCases/TestCaseFactory.cs | 51 +--- .../Core/TestCases/TestCaseResolver.cs | 101 ++++--- .../StandardOutputTestResultParser.cs | 194 ------------- ...StreamingStandardOutputTestResultParser.cs | 165 ------------ .../TestResults/StreamingTestOutputParser.cs | 251 +++++++++++++++++ .../Core/TestResults/XmlTestResultParser.cs | 2 +- .../Resources/AllTestSettings.gta.runsettings | 1 - .../Framework/DebuggedProcessLauncherTests.cs | 32 --- .../TestAdapter.Tests.csproj | 1 - .../Framework/DebuggedProcessLauncher.cs | 26 -- .../TestAdapter/TestAdapter.csproj | 1 - GoogleTestAdapter/TestAdapter/TestExecutor.cs | 19 +- .../Helpers}/ProcessWaiter.cs | 2 +- .../Helpers/TestProcessLauncher.cs | 1 - .../Tests.Common/Tests.Common.csproj | 1 + GoogleTestAdapter/Tests.Common/TestsBase.cs | 1 - .../GoogleTestExtensionOptionsPage.cs | 1 - .../OptionsPages/GeneralOptionsDialogPage.cs | 10 - SampleTests/.gitignore | 3 +- 47 files changed, 450 insertions(+), 1588 deletions(-) delete mode 100644 GoogleTestAdapter/Core.Tests/Helpers/TestProcessLauncherTests.cs delete mode 100644 GoogleTestAdapter/Core.Tests/TestCases/ListTestsParserTests.cs delete mode 100644 GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs rename GoogleTestAdapter/Core.Tests/TestResults/{StreamingStandardOutputTestResultParserTests.cs => StreamingTestOutputParserTests.cs} (89%) delete mode 100644 GoogleTestAdapter/Core/Framework/IDebuggedProcessLauncher.cs delete mode 100644 GoogleTestAdapter/Core/Framework/IProcessExecutor.cs delete mode 100644 GoogleTestAdapter/Core/Helpers/ProcessLauncher.cs delete mode 100644 GoogleTestAdapter/Core/Helpers/TestProcessLauncher.cs delete mode 100644 GoogleTestAdapter/Core/TestCases/ListTestsParser.cs delete mode 100644 GoogleTestAdapter/Core/TestCases/NewTestCaseResolver.cs delete mode 100644 GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs delete mode 100644 GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs create mode 100644 GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs delete mode 100644 GoogleTestAdapter/TestAdapter.Tests/Framework/DebuggedProcessLauncherTests.cs delete mode 100644 GoogleTestAdapter/TestAdapter/Framework/DebuggedProcessLauncher.cs rename GoogleTestAdapter/{Common => Tests.Common/Helpers}/ProcessWaiter.cs (95%) diff --git a/.gitignore b/.gitignore index e5041785b..7221cdb42 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ build/ [Oo]bj/ # MSTest test Results -[Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* *_i.c @@ -163,3 +162,4 @@ OpenCover/ *.VC.opendb *.VC.db-shm *.VC.db-wal +/SampleTests/TestResults diff --git a/GoogleTestAdapter/.gitignore b/GoogleTestAdapter/.gitignore index ddc887ec5..16f6fb4e7 100644 --- a/GoogleTestAdapter/.gitignore +++ b/GoogleTestAdapter/.gitignore @@ -16,7 +16,6 @@ build/ [Oo]bj/ # MSTest test Results -[Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* *_i.c @@ -159,3 +158,4 @@ $RECYCLE.BIN/ /Keys/Key_Release.snk GoogleTestAdapter.VC.db GoogleTestAdapter.VC.VC.opendb +/TestResults \ No newline at end of file diff --git a/GoogleTestAdapter/Common/Common.csproj b/GoogleTestAdapter/Common/Common.csproj index 5c3c7b1bf..fff80b701 100644 --- a/GoogleTestAdapter/Common/Common.csproj +++ b/GoogleTestAdapter/Common/Common.csproj @@ -55,7 +55,6 @@ - diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index 229460a58..be56b82a8 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -92,15 +92,12 @@ - - - + - diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs index 51742aece..f785e6535 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs @@ -1,7 +1,6 @@ using System.IO; using System.Linq; using FluentAssertions; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; using GoogleTestAdapter.Scheduling; using GoogleTestAdapter.Tests.Common; @@ -40,11 +39,10 @@ private void AssertDurationsFileIsCreated(bool parallelExecution) MockOptions.Setup(o => o.ParallelTestExecution).Returns(parallelExecution); MockOptions.Setup(o => o.MaxNrOfThreads).Returns(2); - var processExecutor = new ProcessExecutor(null, TestEnvironment.Logger); var collectingReporter = new FakeFrameworkReporter(); - var testExecutor = new GoogleTestExecutor(TestEnvironment.Logger, TestEnvironment.Options); - testExecutor.RunTests(TestDataCreator.AllTestCasesExceptLoadTests, TestDataCreator.AllTestCasesExceptLoadTests, collectingReporter, null, false, TestResources.SampleTestsSolutionDir, processExecutor); + var testExecutor = new GoogleTestExecutor(TestEnvironment.Logger, TestEnvironment.Options, null); + testExecutor.RunTests(TestDataCreator.AllTestCasesExceptLoadTests, TestDataCreator.AllTestCasesExceptLoadTests, collectingReporter, false, TestResources.SampleTestsSolutionDir); sampleTestsDurationsFile.AsFileInfo() .Should() diff --git a/GoogleTestAdapter/Core.Tests/Helpers/TestProcessLauncherTests.cs b/GoogleTestAdapter/Core.Tests/Helpers/TestProcessLauncherTests.cs deleted file mode 100644 index 45d7eb832..000000000 --- a/GoogleTestAdapter/Core.Tests/Helpers/TestProcessLauncherTests.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections.Generic; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using GoogleTestAdapter.Framework; -using GoogleTestAdapter.Tests.Common; -using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; - -namespace GoogleTestAdapter.Helpers -{ - [TestClass] - public class TestProcessLauncherTests : TestsBase - { - - [TestMethod] - [TestCategory(Unit)] - public void GetOutputOfCommand_WithSimpleCommand_ReturnsOutputOfCommand() - { - List output = new TestProcessLauncher(TestEnvironment.Logger, TestEnvironment.Options, false) - .GetOutputOfCommand(".", "cmd.exe", "/C \"echo 2\"", false, false, null); - - output.Count.Should().Be(1); - output[0].Should().Be("2"); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetOutputOfCommand_WhenDebugging_InvokesDebuggedProcessLauncherCorrectly() - { - int processId = -4711; - var mockLauncher = new Mock(); - mockLauncher.Setup(l => - l.LaunchProcessWithDebuggerAttached(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(processId); - - new TestProcessLauncher(TestEnvironment.Logger, TestEnvironment.Options, true) - .Invoking(pl => pl.GetOutputOfCommand("theDir", "theCommand", "theParams", false, false, mockLauncher.Object)) - .ShouldThrow() - .Where(e => e.Message.Contains(processId.ToString())); - - mockLauncher.Verify(l => l.LaunchProcessWithDebuggerAttached( - It.Is(s => s == "theCommand"), - It.Is(s => s == "theDir"), - It.Is(s => s == "theParams"), - It.Is(s => s == "") - ), Times.Exactly(1)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetOutputOfCommand_ThrowsIfProcessReturnsErrorCode_Throws() - { - new TestProcessLauncher(TestEnvironment.Logger, TestEnvironment.Options, false) - .Invoking(pl => pl.GetOutputOfCommand(".", "cmd.exe", "/C \"exit 2\"", false, true, null)) - .ShouldThrow(); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetOutputOfCommand_IgnoresIfProcessReturnsErrorCode_DoesNotThrow() - { - new TestProcessLauncher(TestEnvironment.Logger, TestEnvironment.Options, false) - .GetOutputOfCommand(".", "cmd.exe", "/C \"exit 2\"", false, false, null); - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs index 8f2d1b5a5..5fcc8dec1 100644 --- a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs +++ b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.Threading; using FluentAssertions; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; using GoogleTestAdapter.Scheduling; using GoogleTestAdapter.Tests.Common; @@ -43,9 +42,8 @@ private void DoRunCancelingTests(bool killProcesses, int lower, int upper) List testCasesToRun = TestDataCreator.GetTestCases("Crashing.LongRunning", "LongRunningTests.Test2"); var stopwatch = new Stopwatch(); - var runner = new SequentialTestRunner("", MockFrameworkReporter.Object, TestEnvironment.Logger, TestEnvironment.Options, new SchedulingAnalyzer(TestEnvironment.Logger)); - var executor = new ProcessExecutor(null, MockLogger.Object); - var thread = new Thread(() => runner.RunTests(allTestCases, testCasesToRun, "", "", "", false, null, executor)); + var runner = new SequentialTestRunner("", MockFrameworkReporter.Object, TestEnvironment.Logger, TestEnvironment.Options, new SchedulingAnalyzer(TestEnvironment.Logger), null); + var thread = new Thread(() => runner.RunTests(allTestCases, testCasesToRun, "", "", "")); stopwatch.Start(); thread.Start(); diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 5854de020..3d1294d31 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -334,7 +334,6 @@ public void ToString_PrintsCorrectly() MockXmlOptions.Setup(s => s.MaxNrOfThreads).Returns(1); string optionsString = TheOptions.ToString(); - optionsString.Should().Contain("UseNewTestExecutionFramework: True"); optionsString.Should().Contain("PrintTestOutput: False"); optionsString.Should().Contain("TestDiscoveryRegex: ''"); optionsString.Should().Contain("WorkingDir: '$(ExecutableDir)'"); diff --git a/GoogleTestAdapter/Core.Tests/TestCases/ListTestsParserTests.cs b/GoogleTestAdapter/Core.Tests/TestCases/ListTestsParserTests.cs deleted file mode 100644 index 24290e4ce..000000000 --- a/GoogleTestAdapter/Core.Tests/TestCases/ListTestsParserTests.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System.Collections.Generic; -using FluentAssertions; -using GoogleTestAdapter.Tests.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; - -namespace GoogleTestAdapter.TestCases -{ - - [TestClass] - public class ListTestsParserTests : TestsBase - { - - [TestMethod] - [TestCategory(Unit)] - public void ParseListTestsOutput_SimpleTest_CorrectSuiteAndName() - { - var consoleOutput = new List - { - "MySuite.", - " MyTestCase" - }; - - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); - - descriptors.Count.Should().Be(1); - descriptors[0].Suite.Should().Be("MySuite"); - descriptors[0].Name.Should().Be("MyTestCase"); - - descriptors[0].DisplayName.Should().Be("MySuite.MyTestCase"); - descriptors[0].FullyQualifiedName.Should().Be("MySuite.MyTestCase"); - descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.Simple); - } - - [TestMethod] - [TestCategory(Unit)] - public void ParseListTestsOutput_TestWithParam_CorrectParsing() - { - var consoleOutput = new List - { - "InstantiationName/ParameterizedTests.", - " Simple/0 # GetParam() = (1,)", - }; - - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); - - descriptors.Count.Should().Be(1); - descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); - descriptors[0].Name.Should().Be("Simple/0"); - descriptors[0].FullyQualifiedName.Should().Be("InstantiationName/ParameterizedTests.Simple/0"); - descriptors[0].DisplayName.Should().Be("InstantiationName/ParameterizedTests.Simple/0 [(1,)]"); - descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.Parameterized); - } - - [TestMethod] - [TestCategory(Unit)] - public void ParseListTestsOutput_TestWithTypeParam_CorrectParsing() - { - var consoleOutput = new List - { - "TypedTests/0. # TypeParam = class std::vector >", - " CanIterate", - }; - - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); - - descriptors.Count.Should().Be(1); - descriptors[0].Suite.Should().Be("TypedTests/0"); - descriptors[0].Name.Should().Be("CanIterate"); - descriptors[0].FullyQualifiedName.Should().Be("TypedTests/0.CanIterate"); - descriptors[0].DisplayName.Should().Be("TypedTests/0.CanIterate > >"); - descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.TypeParameterized); - } - - [TestMethod] - [TestCategory(Unit)] - public void ParseListTestsOutput_TestWithTypeParamAndPrefix_CorrectParsing() - { - var consoleOutput = new List - { - "Arr/TypeParameterizedTests/1. # TypeParam = struct MyStrangeArray", - " CanIterate", - }; - - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); - - descriptors.Count.Should().Be(1); - descriptors[0].Suite.Should().Be("Arr/TypeParameterizedTests/1"); - descriptors[0].Name.Should().Be("CanIterate"); - descriptors[0].FullyQualifiedName.Should().Be("Arr/TypeParameterizedTests/1.CanIterate"); - descriptors[0].DisplayName.Should().Be("Arr/TypeParameterizedTests/1.CanIterate"); - descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.TypeParameterized); - } - - [TestMethod] - [TestCategory(Unit)] - public void ParseListTestsOutput_TestWithTypeParamAndPrefixOldFormat_CorrectParsing() - { - var consoleOutput = new List - { - "Arr/TypeParameterizedTests/1", - " CanIterate", - }; - - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); - - descriptors.Count.Should().Be(1); - descriptors[0].Suite.Should().Be("Arr/TypeParameterizedTests/1"); - descriptors[0].Name.Should().Be("CanIterate"); - descriptors[0].FullyQualifiedName.Should().Be("Arr/TypeParameterizedTests/1.CanIterate"); - descriptors[0].DisplayName.Should().Be("Arr/TypeParameterizedTests/1.CanIterate"); - descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.TypeParameterized); - } - - [TestMethod] - [TestCategory(Unit)] - public void ParseListTestsOutput_TestWithParamAndTestNameSeparator_CorrectParsing() - { - MockOptions.Setup(o => o.TestNameSeparator).Returns("::"); - var consoleOutput = new List - { - "InstantiationName/ParameterizedTests.", - " Simple/0 # GetParam() = (1,)", - }; - - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); - - descriptors.Count.Should().Be(1); - descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); - descriptors[0].Name.Should().Be("Simple/0"); - descriptors[0].FullyQualifiedName.Should().Be("InstantiationName/ParameterizedTests.Simple/0"); - descriptors[0].DisplayName.Should().Be("InstantiationName::ParameterizedTests.Simple::0 [(1,)]"); - descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.Parameterized); - } - - [TestMethod] - [TestCategory(Unit)] - public void ParseListTestsOutput_TestWithParamAndTestNameSeparatorOldFormat_CorrectParsing() - { - MockOptions.Setup(o => o.TestNameSeparator).Returns("::"); - var consoleOutput = new List - { - "InstantiationName/ParameterizedTests.", - " Simple/0", - }; - - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); - - descriptors.Count.Should().Be(1); - descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); - descriptors[0].Name.Should().Be("Simple/0"); - descriptors[0].FullyQualifiedName.Should().Be("InstantiationName/ParameterizedTests.Simple/0"); - descriptors[0].DisplayName.Should().Be("InstantiationName::ParameterizedTests.Simple::0"); - descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.Parameterized); - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs deleted file mode 100644 index 6f178c8df..000000000 --- a/GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs +++ /dev/null @@ -1,254 +0,0 @@ -using System; -using System.Collections.Generic; -using FluentAssertions; -using GoogleTestAdapter.Model; -using GoogleTestAdapter.Tests.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; - -namespace GoogleTestAdapter.TestResults -{ - [TestClass] - public class StandardOutputTestResultParserTests : TestsBase - { - private string[] ConsoleOutput1 { get; } = { - @"[==========] Running 3 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 3 tests from TestMath", - @"[ RUN ] TestMath.AddFails", - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", - @" Actual: 20", - @"Expected: 1000", - @"[ FAILED ] TestMath.AddFails (3 ms)", - @"[ RUN ] TestMath.AddPasses" - }; - - private string[] ConsoleOutput1WithInvalidDuration { get; } = { - @"[==========] Running 3 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 3 tests from TestMath", - @"[ RUN ] TestMath.AddFails", - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", - @" Actual: 20", - @"Expected: 1000", - @"[ FAILED ] TestMath.AddFails (3 s)" - }; - - private string[] ConsoleOutput2 { get; } = { - @"[ OK ] TestMath.AddPasses(0 ms)", - @"[ RUN ] TestMath.Crash", - @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", - }; - - private string[] ConsoleOutput3 { get; } = { - @"[ FAILED ] TestMath.Crash(9 ms)", - @"[----------] 3 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 3 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 1 test.", - @"[ FAILED ] 2 tests, listed below:", - @"[ FAILED ] TestMath.AddFails", - @"[ FAILED ] TestMath.Crash", - @"", - @" 2 FAILED TESTS", - @"", - }; - - private string[] ConsoleOutputWithOutputOfExe { get; } = { - @"[==========] Running 1 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 1 tests from TestMath", - @"[ RUN ] TestMath.AddPasses", - @"Some output produced by the exe", - @"[ OK ] TestMath.AddPasses(0 ms)", - @"[----------] 1 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 3 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 1 test.", - }; - - private string[] ConsoleOutputWithPrefixingTest { get; } = { - @"[==========] Running 2 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 2 tests from TestMath", - @"[ RUN ] Test.AB", - @"[ OK ] Test.A(0 ms)", - @"[ RUN ] Test.A", - @"[ OK ] Test.A(0 ms)", - @"[----------] 2 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 2 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 2 test.", - }; - - - private List CrashesImmediately { get; set; } - private List CrashesAfterErrorMsg { get; set; } - private List Complete { get; set; } - private List WrongDurationUnit { get; set; } - private List PassingTestProducesConsoleOutput { get; set; } - - [TestInitialize] - public override void SetUp() - { - base.SetUp(); - - CrashesImmediately = new List(ConsoleOutput1); - - CrashesAfterErrorMsg = new List(ConsoleOutput1); - CrashesAfterErrorMsg.AddRange(ConsoleOutput2); - - Complete = new List(ConsoleOutput1); - Complete.AddRange(ConsoleOutput2); - Complete.AddRange(ConsoleOutput3); - - WrongDurationUnit = new List(ConsoleOutput1WithInvalidDuration); - - PassingTestProducesConsoleOutput = new List(ConsoleOutputWithOutputOfExe); - } - - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_CompleteOutput_ParsedCorrectly() - { - List results = ComputeTestResults(Complete); - - results.Count.Should().Be(3); - - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); - results[0].ErrorStackTrace.Should() - .Contain( - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); - - results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); - - results[2].TestCase.FullyQualifiedName.Should().Be("TestMath.Crash"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[2]); - results[2].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); - results[2].Duration.Should().Be(TimeSpan.FromMilliseconds(9)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithImmediateCrash_CorrectResultHasCrashText() - { - List results = ComputeTestResults(CrashesImmediately); - - results.Count.Should().Be(2); - - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); - results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); - - results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[1]); - results[1].ErrorMessage.Should().Contain(StandardOutputTestResultParser.CrashText); - results[1].ErrorMessage.Should().NotContain("Test output:"); - results[1].Duration.Should().Be(TimeSpan.FromMilliseconds(0)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithCrashAfterErrorMessage_CorrectResultHasCrashText() - { - List results = ComputeTestResults(CrashesAfterErrorMsg); - - results.Count.Should().Be(3); - - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); - results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); - - results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); - - results[2].TestCase.FullyQualifiedName.Should().Be("TestMath.Crash"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[2]); - results[2].ErrorMessage.Should().Contain(StandardOutputTestResultParser.CrashText); - results[2].ErrorMessage.Should().Contain("Test output:"); - results[2].ErrorMessage.Should().Contain("unknown file: error: SEH exception with code 0xc0000005 thrown in the test body."); - results[2].Duration.Should().Be(TimeSpan.FromMilliseconds(0)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithInvalidDurationUnit_DefaultDurationIsUsedAndWarningIsProduced() - { - List results = ComputeTestResults(WrongDurationUnit); - - results.Count.Should().Be(1); - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(1)); - results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); - - MockLogger.Verify(l => l.LogWarning( - It.Is(s => s.Contains("'[ FAILED ] TestMath.AddFails (3 s)'"))), Times.Exactly(1)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithConsoleOutput_ConsoleOutputIsIgnored() - { - List results = ComputeTestResults(PassingTestProducesConsoleOutput); - - results.Count.Should().Be(1); - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[0]); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithPrefixingTest_BothTestsAreFound() - { - var cases = new List - { - TestDataCreator.ToTestCase("Test.AB", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"), - TestDataCreator.ToTestCase("Test.A", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp") - }; - - var results = new StandardOutputTestResultParser(cases, ConsoleOutputWithPrefixingTest, TestEnvironment.Logger, @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\") - .GetTestResults(); - - results.Count.Should().Be(2); - results[0].TestCase.FullyQualifiedName.Should().Be("Test.AB"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[0]); - results[1].TestCase.FullyQualifiedName.Should().Be("Test.A"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - } - - - private List ComputeTestResults(List consoleOutput) - { - var cases = new List - { - TestDataCreator.ToTestCase("TestMath.AddFails", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"), - TestDataCreator.ToTestCase("TestMath.Crash", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"), - TestDataCreator.ToTestCase("TestMath.AddPasses", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp") - }; - var parser = new StandardOutputTestResultParser(cases, consoleOutput, TestEnvironment.Logger, @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\"); - return parser.GetTestResults(); - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/StreamingTestOutputParserTests.cs similarity index 89% rename from GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs rename to GoogleTestAdapter/Core.Tests/TestResults/StreamingTestOutputParserTests.cs index 9a2366e36..7929c4f09 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/StreamingTestOutputParserTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using FluentAssertions; using GoogleTestAdapter.Model; using GoogleTestAdapter.Tests.Common; @@ -10,7 +11,7 @@ namespace GoogleTestAdapter.TestResults { [TestClass] - public class StreamingStandardOutputTestResultParserTests : TestsBase + public class StreamingTestOutputParserTests : TestsBase { private string[] ConsoleOutput1 { get; } = { @"[==========] Running 3 tests from 1 test case.", @@ -142,7 +143,7 @@ public void GetTestResults_CompleteOutput_ParsedCorrectly() results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); + results[0].ErrorMessage.Should().NotContain(StreamingTestOutputParser.CrashText); results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); results[0].ErrorStackTrace.Should() .Contain( @@ -150,11 +151,11 @@ public void GetTestResults_CompleteOutput_ParsedCorrectly() results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); + results[1].Duration.Should().Be(StreamingTestOutputParser.ShortTestDuration); results[2].TestCase.FullyQualifiedName.Should().Be("TestMath.Crash"); XmlTestResultParserTests.AssertTestResultIsFailure(results[2]); - results[2].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); + results[2].ErrorMessage.Should().NotContain(StreamingTestOutputParser.CrashText); results[2].Duration.Should().Be(TimeSpan.FromMilliseconds(9)); } @@ -168,13 +169,13 @@ public void GetTestResults_OutputWithImmediateCrash_CorrectResultHasCrashText() results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); + results[0].ErrorMessage.Should().NotContain(StreamingTestOutputParser.CrashText); results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsFailure(results[1]); - results[1].ErrorMessage.Should().Contain(StandardOutputTestResultParser.CrashText); + results[1].ErrorMessage.Should().Contain(StreamingTestOutputParser.CrashText); results[1].ErrorMessage.Should().NotContain("Test output:"); results[1].Duration.Should().Be(TimeSpan.FromMilliseconds(0)); } @@ -189,17 +190,17 @@ public void GetTestResults_OutputWithCrashAfterErrorMessage_CorrectResultHasCras results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); + results[0].ErrorMessage.Should().NotContain(StreamingTestOutputParser.CrashText); results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); + results[1].Duration.Should().Be(StreamingTestOutputParser.ShortTestDuration); results[2].TestCase.FullyQualifiedName.Should().Be("TestMath.Crash"); XmlTestResultParserTests.AssertTestResultIsFailure(results[2]); - results[2].ErrorMessage.Should().Contain(StandardOutputTestResultParser.CrashText); + results[2].ErrorMessage.Should().Contain(StreamingTestOutputParser.CrashText); results[2].ErrorMessage.Should().Contain("Test output:"); results[2].ErrorMessage.Should().Contain("unknown file: error: SEH exception with code 0xc0000005 thrown in the test body."); results[2].Duration.Should().Be(TimeSpan.FromMilliseconds(0)); @@ -215,7 +216,7 @@ public void GetTestResults_OutputWithPrefixedPassedLine_PassingTestIsRecognized( results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); + results[1].Duration.Should().Be(StreamingTestOutputParser.ShortTestDuration); } [TestMethod] @@ -229,7 +230,7 @@ public void GetTestResults_OutputWithPrefixedFailedLine_FailingTestIsRecognized( results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsFailure(results[1]); results[1].ErrorMessage.Should().Contain("DummyOutput"); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); + results[1].Duration.Should().Be(StreamingTestOutputParser.ShortTestDuration); } [TestMethod] @@ -270,8 +271,10 @@ public void GetTestResults_OutputWithPrefixingTest_BothTestsAreFound() @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp") }; - var results = new StandardOutputTestResultParser(cases, ConsoleOutputWithPrefixingTest, TestEnvironment.Logger, @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\") - .GetTestResults(); + var parser = new StreamingTestOutputParser(cases, TestEnvironment.Logger, @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\", MockFrameworkReporter.Object); + ConsoleOutputWithPrefixingTest.ToList().ForEach(parser.ReportLine); + parser.Flush(); + var results = parser.TestResults; results.Count.Should().Be(2); results[0].TestCase.FullyQualifiedName.Should().Be("Test.AB"); @@ -293,7 +296,7 @@ private IList ComputeTestResults(List consoleOutput) @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp") }; - var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\", MockFrameworkReporter.Object); + var parser = new StreamingTestOutputParser(cases, MockLogger.Object, @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\", MockFrameworkReporter.Object); consoleOutput.ForEach(parser.ReportLine); parser.Flush(); diff --git a/GoogleTestAdapter/Core/Core.csproj b/GoogleTestAdapter/Core/Core.csproj index 1babae287..5c1729a63 100644 --- a/GoogleTestAdapter/Core/Core.csproj +++ b/GoogleTestAdapter/Core/Core.csproj @@ -45,8 +45,6 @@ - - @@ -56,15 +54,12 @@ - - - @@ -85,11 +80,9 @@ - - - + diff --git a/GoogleTestAdapter/Core/Framework/IDebuggedProcessLauncher.cs b/GoogleTestAdapter/Core/Framework/IDebuggedProcessLauncher.cs deleted file mode 100644 index 320868129..000000000 --- a/GoogleTestAdapter/Core/Framework/IDebuggedProcessLauncher.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace GoogleTestAdapter.Framework -{ - - public interface IDebuggedProcessLauncher - { - int LaunchProcessWithDebuggerAttached(string command, string workingDirectory, string param, string pathExtension); - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Framework/IProcessExecutor.cs b/GoogleTestAdapter/Core/Framework/IProcessExecutor.cs deleted file mode 100644 index fa4790410..000000000 --- a/GoogleTestAdapter/Core/Framework/IProcessExecutor.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace GoogleTestAdapter.Framework -{ - - public interface IProcessExecutor - { - int ExecuteCommandBlocking(string command, string parameters, string workingDir, string pathExtension, Action reportOutputLine); - void Cancel(); - } - - // ReSharper disable once InconsistentNaming - public static class IProcessExecutorExtensions - { - public static int ExecuteBatchFileBlocking(this IProcessExecutor executor, string batchFile, string parameters, string workingDir, string pathExtension, Action reportOutputLine) - { - return executor.ExecuteCommandBlocking($"cmd.exe /C {batchFile}", parameters, workingDir, pathExtension, - reportOutputLine); - } - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs index 3f4118041..d050274e7 100644 --- a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs +++ b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs @@ -30,35 +30,21 @@ public GoogleTestDiscoverer(ILogger logger, SettingsWrapper settings, IDiaResolv public void DiscoverTests(IEnumerable executables, ITestFrameworkReporter reporter) { IList googleTestExecutables = GetAllGoogleTestExecutables(executables); - if (_settings.UseNewTestExecutionFramework) + foreach (string executable in googleTestExecutables) { - foreach (string executable in googleTestExecutables) - { - _settings.ExecuteWithSettingsForExecutable(executable, () => - { - int nrOfTestCases = 0; - Action reportTestCases = tc => - { - reporter.ReportTestsFound(tc.Yield()); - _logger.DebugInfo("Added testcase " + tc.DisplayName); - nrOfTestCases++; - }; - var factory = new TestCaseFactory(executable, _logger, _settings, _diaResolverFactory); - factory.CreateTestCases(reportTestCases); - _logger.LogInfo("Found " + nrOfTestCases + " tests in executable " + executable); - }, _logger); - } - } - else - { - foreach (string executable in googleTestExecutables) + _settings.ExecuteWithSettingsForExecutable(executable, () => { - _settings.ExecuteWithSettingsForExecutable(executable, () => + int nrOfTestCases = 0; + Action reportTestCases = tc => { - IList testCases = GetTestsFromExecutable(executable); - reporter.ReportTestsFound(testCases); - }, _logger); - } + reporter.ReportTestsFound(tc.Yield()); + _logger.DebugInfo("Added testcase " + tc.DisplayName); + nrOfTestCases++; + }; + var factory = new TestCaseFactory(executable, _logger, _settings, _diaResolverFactory); + factory.CreateTestCases(reportTestCases); + _logger.LogInfo("Found " + nrOfTestCases + " tests in executable " + executable); + }, _logger); } } diff --git a/GoogleTestAdapter/Core/GoogleTestExecutor.cs b/GoogleTestAdapter/Core/GoogleTestExecutor.cs index cc84f982f..7136c29fc 100644 --- a/GoogleTestAdapter/Core/GoogleTestExecutor.cs +++ b/GoogleTestAdapter/Core/GoogleTestExecutor.cs @@ -15,20 +15,22 @@ public class GoogleTestExecutor private readonly ILogger _logger; private readonly SettingsWrapper _settings; + private readonly IDebuggerAttacher _debuggerAttacher; private readonly SchedulingAnalyzer _schedulingAnalyzer; private ITestRunner _runner; private bool _canceled; - public GoogleTestExecutor(ILogger logger, SettingsWrapper settings) + public GoogleTestExecutor(ILogger logger, SettingsWrapper settings, IDebuggerAttacher debuggerAttacher) { _logger = logger; _settings = settings; + _debuggerAttacher = debuggerAttacher; _schedulingAnalyzer = new SchedulingAnalyzer(logger); } - public void RunTests(IEnumerable allTestCasesInExecutables, IEnumerable testCasesToRun, ITestFrameworkReporter reporter, IDebuggedProcessLauncher launcher, bool isBeingDebugged, string solutionDirectory, IProcessExecutor executor) + public void RunTests(IEnumerable allTestCasesInExecutables, IEnumerable testCasesToRun, ITestFrameworkReporter reporter, bool isBeingDebugged, string solutionDirectory) { TestCase[] testCasesToRunAsArray = testCasesToRun as TestCase[] ?? testCasesToRun.ToArray(); _logger.LogInfo("Running " + testCasesToRunAsArray.Length + " tests..."); @@ -42,7 +44,7 @@ public void RunTests(IEnumerable allTestCasesInExecutables, IEnumerabl ComputeTestRunner(reporter, isBeingDebugged, solutionDirectory); } - _runner.RunTests(allTestCasesInExecutables, testCasesToRunAsArray, solutionDirectory, null, null, isBeingDebugged, launcher, executor); + _runner.RunTests(allTestCasesInExecutables, testCasesToRunAsArray, solutionDirectory, null, null); if (_settings.ParallelTestExecution) _schedulingAnalyzer.PrintStatisticsToDebugOutput(); @@ -61,11 +63,11 @@ private void ComputeTestRunner(ITestFrameworkReporter reporter, bool isBeingDebu { if (_settings.ParallelTestExecution && !isBeingDebugged) { - _runner = new ParallelTestRunner(reporter, _logger, _settings, solutionDirectory, _schedulingAnalyzer); + _runner = new ParallelTestRunner(reporter, _logger, _settings, solutionDirectory, _schedulingAnalyzer, _debuggerAttacher); } else { - _runner = new PreparingTestRunner(solutionDirectory, reporter, _logger, _settings, _schedulingAnalyzer); + _runner = new PreparingTestRunner(solutionDirectory, reporter, _logger, _settings, _schedulingAnalyzer, _debuggerAttacher); if (_settings.ParallelTestExecution && isBeingDebugged) { _logger.DebugInfo( diff --git a/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs b/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs index ebdb6baff..c1d186f7c 100644 --- a/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs +++ b/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs @@ -15,13 +15,15 @@ namespace GoogleTestAdapter.Helpers { - public class ProcessExecutor : IProcessExecutor + public class ProcessExecutor { public const int ExecutionFailed = int.MaxValue; private readonly IDebuggerAttacher _debuggerAttacher; private readonly ILogger _logger; + private int? _processId; + public ProcessExecutor(ILogger logger) : this(null, logger) { } @@ -47,12 +49,37 @@ public int ExecuteCommandBlocking(string command, string parameters, string work } } - private int? _processId; + public int ExecuteBatchFileBlocking(string batchFile, string parameters, string workingDir, string pathExtension, Action reportOutputLine) + { + return ExecuteCommandBlocking($"cmd.exe /C {batchFile}", parameters, workingDir, pathExtension, reportOutputLine); + } public void Cancel() { if (_processId.HasValue) - TestProcessLauncher.KillProcess(_processId.Value, _logger); + KillProcess(_processId.Value, _logger); + } + + private static void KillProcess(int processId, ILogger logger) + { + try + { + Process process = Process.GetProcessById(processId); + DateTime startTime = process.StartTime; + try + { + process.Kill(); + logger.DebugInfo($"Killed process {process} with startTime={startTime.ToShortTimeString()}"); + } + catch (Exception e) + { + logger.DebugWarning($"Could not kill process {process} with startTime={startTime.ToShortTimeString()}: {e.Message}"); + } + } + catch (Exception) + { + // process was not running - nothing to do + } } [SuppressMessage("ReSharper", "MemberCanBePrivate.Local")] diff --git a/GoogleTestAdapter/Core/Helpers/ProcessLauncher.cs b/GoogleTestAdapter/Core/Helpers/ProcessLauncher.cs deleted file mode 100644 index ea0f21eef..000000000 --- a/GoogleTestAdapter/Core/Helpers/ProcessLauncher.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using GoogleTestAdapter.Common; - -namespace GoogleTestAdapter.Helpers -{ - - public class ProcessLauncher - { - private readonly ILogger _logger; - private readonly string _pathExtension; - private readonly Action _reportProcessId; - - public ProcessLauncher(ILogger logger) : this(logger, "", null) - { - } - - public ProcessLauncher(ILogger logger, string pathExtension, Action reportProcessId) - { - _logger = logger; - _pathExtension = pathExtension; - _reportProcessId = reportProcessId; - } - - public List GetOutputOfCommand(string command) - { - int dummy; - return GetOutputOfCommand("", command, "", false, false, out dummy); - } - - public List GetOutputOfCommand(string workingDirectory, string command, string param, bool printTestOutput, - bool throwIfError) - { - int dummy; - return GetOutputOfCommand(workingDirectory, command, param, printTestOutput, throwIfError, out dummy); - } - - public List GetOutputOfCommand(string workingDirectory, string command, string param, bool printTestOutput, - bool throwIfError, out int processExitCode) - { - var output = new List(); - processExitCode = LaunchProcess(workingDirectory, command, param, printTestOutput, throwIfError, output); - return output; - } - - - private int LaunchProcess(string workingDirectory, string command, string param, bool printTestOutput, - bool throwIfError, List output) - { - var processStartInfo = new ProcessStartInfo(command, param) - { - StandardOutputEncoding = Encoding.Default, - RedirectStandardOutput = true, - RedirectStandardError = false, - UseShellExecute = false, - CreateNoWindow = true, - WorkingDirectory = workingDirectory - }; - - if (!string.IsNullOrEmpty(_pathExtension)) - processStartInfo.EnvironmentVariables["PATH"] = Utils.GetExtendedPath(_pathExtension); - - Process process = Process.Start(processStartInfo); - if (process != null) - _reportProcessId?.Invoke(process.Id); - try - { - var waiter = new ProcessWaiter(process); - if (printTestOutput) - { - _logger.LogInfo( - ">>>>>>>>>>>>>>> Output of command '" + command + " " + param + "'"); - } - ReadTheStream(process, output, printTestOutput, throwIfError); - if (printTestOutput) - { - _logger.LogInfo("<<<<<<<<<<<<<<< End of Output"); - } - return waiter.WaitForExit(); - } - finally - { - process?.Dispose(); - } - } - - // ReSharper disable once UnusedParameter.Local - private void ReadTheStream(Process process, List streamContent, bool printTestOutput, bool throwIfError) - { - while (!process.StandardOutput.EndOfStream) - { - string line = process.StandardOutput.ReadLine(); - streamContent.Add(line); - if (printTestOutput) - { - _logger.LogInfo(line); - } - } - if (throwIfError && process.ExitCode != 0) - { - throw new Exception("Process exited with return code " + process.ExitCode); - } - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Helpers/TestProcessLauncher.cs b/GoogleTestAdapter/Core/Helpers/TestProcessLauncher.cs deleted file mode 100644 index 3d3825312..000000000 --- a/GoogleTestAdapter/Core/Helpers/TestProcessLauncher.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using GoogleTestAdapter.Common; -using GoogleTestAdapter.Framework; -using GoogleTestAdapter.Settings; - -namespace GoogleTestAdapter.Helpers -{ - - public class TestProcessLauncher - { - private readonly ILogger _logger; - private readonly SettingsWrapper _settings; - private readonly bool _isBeingDebugged; - - public TestProcessLauncher(ILogger logger, SettingsWrapper settings, bool isBeingDebugged) - { - _logger = logger; - _settings = settings; - _isBeingDebugged = isBeingDebugged; - } - - - public List GetOutputOfCommand(string workingDirectory, string command, string param, bool printTestOutput, - bool throwIfError, IDebuggedProcessLauncher debuggedLauncher) - { - int dummy; - return GetOutputOfCommand(workingDirectory, command, param, printTestOutput, throwIfError, debuggedLauncher, out dummy); - } - - public List GetOutputOfCommand(string workingDirectory, string command, string param, bool printTestOutput, - bool throwIfError, IDebuggedProcessLauncher debuggedLauncher, out int processExitCode) - { - if (_isBeingDebugged) - { - var output = new List(); - processExitCode = LaunchProcessWithDebuggerAttached(workingDirectory, command, param, printTestOutput, debuggedLauncher); - return output; - } - - var actualLauncher = new ProcessLauncher(_logger, _settings.GetPathExtension(command), processId => _processId = processId); - return actualLauncher.GetOutputOfCommand(workingDirectory, command, param, printTestOutput, - throwIfError, out processExitCode); - } - - private int? _processId; - - public void Cancel() - { - if (_processId.HasValue) - KillProcess(_processId.Value, _logger); - } - - public static void KillProcess(int processId, ILogger logger) - { - try - { - Process process = Process.GetProcessById(processId); - DateTime startTime = process.StartTime; - try - { - process.Kill(); - logger.DebugInfo($"Killed process {process} with startTime={startTime.ToShortTimeString()}"); - } - catch (Exception e) - { - logger.DebugWarning($"Could not kill process {process} with startTime={startTime.ToShortTimeString()}: {e.Message}"); - } - } - catch (Exception) - { - // process was not running - nothing to do - } - } - - - private int LaunchProcessWithDebuggerAttached(string workingDirectory, string command, string param, bool printTestOutput, - IDebuggedProcessLauncher handle) - { - _logger.LogInfo("Attaching debugger to " + command); - if (printTestOutput) - { - _logger.DebugInfo( - "Note that due to restrictions of the VS Unit Testing framework, the test executable's output can not be displayed in the test console when debugging tests!"); - } - _processId = handle.LaunchProcessWithDebuggerAttached(command, workingDirectory, param, _settings.GetPathExtension(command)); - Process process = Process.GetProcessById(_processId.Value); - var waiter = new ProcessWaiter(process); - waiter.WaitForExit(); - process.Dispose(); - return waiter.ProcessExitCode; - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Runners/ITestRunner.cs b/GoogleTestAdapter/Core/Runners/ITestRunner.cs index b49910d67..2b7d4096c 100644 --- a/GoogleTestAdapter/Core/Runners/ITestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ITestRunner.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using GoogleTestAdapter.Framework; using GoogleTestAdapter.Model; namespace GoogleTestAdapter.Runners @@ -7,9 +6,8 @@ namespace GoogleTestAdapter.Runners public interface ITestRunner { - // TODO remove isBeingDebugged parameter (use debuggedLauncher != null) void RunTests(IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, string workingDir, - string userParameters, bool isBeingDebugged, IDebuggedProcessLauncher debuggedLauncher, IProcessExecutor executor); + string userParameters); void Cancel(); } diff --git a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs index 876c5ff4d..e60ffb8ae 100644 --- a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs @@ -18,20 +18,22 @@ public class ParallelTestRunner : ITestRunner private readonly List _testRunners = new List(); private readonly string _solutionDirectory; private readonly SchedulingAnalyzer _schedulingAnalyzer; + private readonly IDebuggerAttacher _debuggerAttacher; - public ParallelTestRunner(ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, string solutionDirectory, SchedulingAnalyzer schedulingAnalyzer) + public ParallelTestRunner(ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, string solutionDirectory, SchedulingAnalyzer schedulingAnalyzer, IDebuggerAttacher debuggerAttacher) { _frameworkReporter = reporter; _logger = logger; _settings = settings; _solutionDirectory = solutionDirectory; _schedulingAnalyzer = schedulingAnalyzer; + _debuggerAttacher = debuggerAttacher; } public void RunTests(IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, - string workingDir, string userParameters, bool isBeingDebugged, IDebuggedProcessLauncher debuggedLauncher, IProcessExecutor executor) + string workingDir, string userParameters) { List threads; lock (this) @@ -40,7 +42,7 @@ public void RunTests(IEnumerable allTestCases, IEnumerable t DebugUtils.AssertIsNull(userParameters, nameof(userParameters)); threads = new List(); - RunTests(allTestCases, testCasesToRun, baseDir, threads, isBeingDebugged, debuggedLauncher, executor); + RunTests(allTestCases, testCasesToRun, baseDir, threads); } foreach (Thread thread in threads) @@ -61,7 +63,7 @@ public void Cancel() } - private void RunTests(IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, List threads, bool isBeingDebugged, IDebuggedProcessLauncher debuggedLauncher, IProcessExecutor executor) + private void RunTests(IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, List threads) { TestCase[] testCasesToRunAsArray = testCasesToRun as TestCase[] ?? testCasesToRun.ToArray(); @@ -74,10 +76,10 @@ private void RunTests(IEnumerable allTestCases, IEnumerable int threadId = 0; foreach (List testcases in splittedTestCasesToRun) { - var runner = new PreparingTestRunner(threadId++, _solutionDirectory, _frameworkReporter, _logger, _settings.Clone(), _schedulingAnalyzer); + var runner = new PreparingTestRunner(threadId++, _solutionDirectory, _frameworkReporter, _logger, _settings.Clone(), _schedulingAnalyzer, _debuggerAttacher); _testRunners.Add(runner); - var thread = new Thread(() => runner.RunTests(allTestCases, testcases, baseDir, null, null, isBeingDebugged, debuggedLauncher, executor)); + var thread = new Thread(() => runner.RunTests(allTestCases, testcases, baseDir, null, null)); threads.Add(thread); thread.Start(); diff --git a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs index de4ea495f..a602eebad 100644 --- a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs @@ -24,25 +24,25 @@ public class PreparingTestRunner : ITestRunner private readonly string _solutionDirectory; - public PreparingTestRunner(int threadId, string solutionDirectory, ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer) + public PreparingTestRunner(int threadId, string solutionDirectory, ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer, IDebuggerAttacher debuggerAttacher) { _logger = logger; _settings = settings; string threadName = ComputeThreadName(threadId, _settings.MaxNrOfThreads); _threadName = string.IsNullOrEmpty(threadName) ? "" : $"{threadName} "; _threadId = Math.Max(0, threadId); - _innerTestRunner = new SequentialTestRunner(_threadName, reporter, _logger, _settings, schedulingAnalyzer); + _innerTestRunner = new SequentialTestRunner(_threadName, reporter, _logger, _settings, schedulingAnalyzer, debuggerAttacher); _solutionDirectory = solutionDirectory; } public PreparingTestRunner(string solutionDirectory, ITestFrameworkReporter reporter, - ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer) - : this(-1, solutionDirectory, reporter, logger, settings, schedulingAnalyzer){ + ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer, IDebuggerAttacher debuggerAttacher) + : this(-1, solutionDirectory, reporter, logger, settings, schedulingAnalyzer, debuggerAttacher){ } public void RunTests(IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, - string workingDir, string userParameters, bool isBeingDebugged, IDebuggedProcessLauncher debuggedLauncher, IProcessExecutor executor) + string workingDir, string userParameters) { DebugUtils.AssertIsNull(userParameters, nameof(userParameters)); DebugUtils.AssertIsNull(workingDir, nameof(workingDir)); @@ -57,13 +57,13 @@ public void RunTests(IEnumerable allTestCases, IEnumerable t string batch = _settings.GetBatchForTestSetup(_solutionDirectory, testDirectory, _threadId); batch = batch == "" ? "" : _solutionDirectory + batch; - SafeRunBatch(TestSetup, _solutionDirectory, batch, isBeingDebugged); + SafeRunBatch(TestSetup, _solutionDirectory, batch); - _innerTestRunner.RunTests(allTestCases, testCasesToRun, baseDir, workingDir, userParameters, isBeingDebugged, debuggedLauncher, executor); + _innerTestRunner.RunTests(allTestCases, testCasesToRun, baseDir, workingDir, userParameters); batch = _settings.GetBatchForTestTeardown(_solutionDirectory, testDirectory, _threadId); batch = batch == "" ? "" : _solutionDirectory + batch; - SafeRunBatch(TestTeardown, _solutionDirectory, batch, isBeingDebugged); + SafeRunBatch(TestTeardown, _solutionDirectory, batch); stopwatch.Stop(); _logger.DebugInfo($"{_threadName}Execution took {stopwatch.Elapsed}"); @@ -87,7 +87,7 @@ public void Cancel() } - private void SafeRunBatch(string batchType, string workingDirectory, string batch, bool isBeingDebugged) + private void SafeRunBatch(string batchType, string workingDirectory, string batch) { if (string.IsNullOrEmpty(batch)) { @@ -101,7 +101,7 @@ private void SafeRunBatch(string batchType, string workingDirectory, string batc try { - RunBatch(batchType, workingDirectory, batch, isBeingDebugged); + RunBatch(batchType, workingDirectory, batch); } catch (Exception e) { @@ -110,19 +110,10 @@ private void SafeRunBatch(string batchType, string workingDirectory, string batc } } - private void RunBatch(string batchType, string workingDirectory, string batch, bool isBeingDebugged) + private void RunBatch(string batchType, string workingDirectory, string batch) { - int batchExitCode; - if (_settings.UseNewTestExecutionFramework) - { - var executor = new ProcessExecutor(null, _logger); - batchExitCode = executor.ExecuteBatchFileBlocking(batch, "", workingDirectory, "", s => { }); - } - else - { - new TestProcessLauncher(_logger, _settings, isBeingDebugged).GetOutputOfCommand( - workingDirectory, batch, "", false, false, null, out batchExitCode); - } + var executor = new ProcessExecutor(_logger); + var batchExitCode = executor.ExecuteBatchFileBlocking(batch, "", workingDirectory, "", s => { }); if (batchExitCode == 0) { diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index da62596db..fa673796f 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -18,24 +18,26 @@ public class SequentialTestRunner : ITestRunner private bool _canceled; private readonly string _threadName; - private readonly ITestFrameworkReporter _frameworkReporter; private readonly ILogger _logger; private readonly SettingsWrapper _settings; + private readonly ProcessExecutor _processExecutor; + private readonly ITestFrameworkReporter _frameworkReporter; private readonly SchedulingAnalyzer _schedulingAnalyzer; - public SequentialTestRunner(string threadName, ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer) + public SequentialTestRunner(string threadName, ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer, IDebuggerAttacher debuggerAttacher) { _threadName = threadName; _frameworkReporter = reporter; _logger = logger; _settings = settings; _schedulingAnalyzer = schedulingAnalyzer; + _processExecutor = new ProcessExecutor(debuggerAttacher, logger); } public void RunTests(IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, - string workingDir, string userParameters, bool isBeingDebugged, IDebuggedProcessLauncher debuggedLauncher, IProcessExecutor executor) + string workingDir, string userParameters) { DebugUtils.AssertIsNotNull(userParameters, nameof(userParameters)); DebugUtils.AssertIsNotNull(workingDir, nameof(workingDir)); @@ -58,10 +60,7 @@ public void RunTests(IEnumerable allTestCases, IEnumerable t allTestCasesAsArray.Where(tc => tc.Source == executable), groupedTestCases[executable], baseDir, - finalParameters, - isBeingDebugged, - debuggedLauncher, - executor); + finalParameters); }, _logger); } @@ -72,16 +71,13 @@ public void Cancel() _canceled = true; if (_settings.KillProcessesOnCancel) { - _processLauncher?.Cancel(); _processExecutor?.Cancel(); } } - // ReSharper disable once UnusedParameter.Local private void RunTestsFromExecutable(string executable, string workingDir, - IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, string userParameters, - bool isBeingDebugged, IDebuggedProcessLauncher debuggedLauncher, IProcessExecutor executor) + IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, string userParameters) { string resultXmlFile = Path.GetTempFileName(); var serializer = new TestDurationSerializer(); @@ -93,8 +89,8 @@ private void RunTestsFromExecutable(string executable, string workingDir, { break; } - var streamingParser = new StreamingStandardOutputTestResultParser(arguments.TestCases, _logger, baseDir, _frameworkReporter); - var results = RunTests(executable, workingDir, baseDir, isBeingDebugged, debuggedLauncher, arguments, resultXmlFile, executor, streamingParser).ToArray(); + var streamingParser = new StreamingTestOutputParser(arguments.TestCases, _logger, baseDir, _frameworkReporter); + var results = RunTests(executable, workingDir, baseDir, arguments, resultXmlFile, streamingParser).ToArray(); try { @@ -120,12 +116,12 @@ private void RunTestsFromExecutable(string executable, string workingDir, } } - private IEnumerable RunTests(string executable, string workingDir, string baseDir, bool isBeingDebugged, - IDebuggedProcessLauncher debuggedLauncher, CommandLineGenerator.Args arguments, string resultXmlFile, IProcessExecutor executor, StreamingStandardOutputTestResultParser streamingParser) + private IEnumerable RunTests(string executable, string workingDir, string baseDir, + CommandLineGenerator.Args arguments, string resultXmlFile, StreamingTestOutputParser streamingParser) { try { - return TryRunTests(executable, workingDir, baseDir, isBeingDebugged, debuggedLauncher, arguments, resultXmlFile, executor, streamingParser); + return TryRunTests(executable, workingDir, baseDir, arguments, resultXmlFile, streamingParser); } catch (Exception e) { @@ -144,35 +140,19 @@ public static void LogExecutionError(ILogger logger, string executable, string w $"{threadName}In particular: launch command prompt, change into directory '{workingDir}', and execute the following command to make sure your tests can be run in general.{Environment.NewLine}{executable} {arguments}"); } - private IEnumerable TryRunTests(string executable, string workingDir, string baseDir, bool isBeingDebugged, - IDebuggedProcessLauncher debuggedLauncher, CommandLineGenerator.Args arguments, string resultXmlFile, IProcessExecutor executor, - StreamingStandardOutputTestResultParser streamingParser) + private IEnumerable TryRunTests(string executable, string workingDir, string baseDir, + CommandLineGenerator.Args arguments, string resultXmlFile, + StreamingTestOutputParser streamingParser) { - List consoleOutput; - if (_settings.UseNewTestExecutionFramework) - { - DebugUtils.AssertIsNotNull(executor, nameof(executor)); - consoleOutput = RunTestExecutableWithNewFramework(executable, workingDir, arguments, executor, streamingParser); - } - else - { - _processLauncher = new TestProcessLauncher(_logger, _settings, isBeingDebugged); - consoleOutput = - _processLauncher.GetOutputOfCommand(workingDir, executable, arguments.CommandLine, - _settings.PrintTestOutput && !_settings.ParallelTestExecution, false, - debuggedLauncher); - } + RunTestExecutable(executable, workingDir, arguments, streamingParser); var remainingTestCases = arguments.TestCases.Except(streamingParser.TestResults.Select(tr => tr.TestCase)); - return CollectTestResults(remainingTestCases, resultXmlFile, consoleOutput, baseDir, streamingParser.CrashedTestCase); + return CollectTestResults(remainingTestCases, resultXmlFile, baseDir, streamingParser.CrashedTestCase); } - private TestProcessLauncher _processLauncher; - private IProcessExecutor _processExecutor; - - private List RunTestExecutableWithNewFramework(string executable, string workingDir, CommandLineGenerator.Args arguments, IProcessExecutor executor, - StreamingStandardOutputTestResultParser streamingParser) + private void RunTestExecutable(string executable, string workingDir, CommandLineGenerator.Args arguments, + StreamingTestOutputParser streamingParser) { string pathExtension = _settings.GetPathExtension(executable); bool printTestOutput = _settings.PrintTestOutput && @@ -180,7 +160,7 @@ private List RunTestExecutableWithNewFramework(string executable, string if (printTestOutput) _logger.LogInfo( - $"{_threadName}>>>>>>>>>>>>>>> Output of command '" + executable + " " + arguments.CommandLine + "'"); + $"{_threadName}>>>>>>>>>>>>>>> Output of command '{executable} {arguments.CommandLine}'"); Action reportOutputAction = line => { @@ -198,7 +178,6 @@ private List RunTestExecutableWithNewFramework(string executable, string Cancel(); } }; - _processExecutor = executor; _processExecutor.ExecuteCommandBlocking( executable, arguments.CommandLine, workingDir, pathExtension, reportOutputAction); @@ -207,7 +186,6 @@ private List RunTestExecutableWithNewFramework(string executable, string if (printTestOutput) _logger.LogInfo($"{_threadName}<<<<<<<<<<<<<<< End of Output"); - var consoleOutput = new List(); new TestDurationSerializer().UpdateTestDurations(streamingParser.TestResults); _logger.DebugInfo( $"{_threadName}Reported {streamingParser.TestResults.Count} test results to VS during test execution, executable: '{executable}'"); @@ -216,15 +194,13 @@ private List RunTestExecutableWithNewFramework(string executable, string if (!_schedulingAnalyzer.AddActualDuration(result.TestCase, (int) result.Duration.TotalMilliseconds)) _logger.LogWarning($"{_threadName}TestCase already in analyzer: {result.TestCase.FullyQualifiedName}"); } - return consoleOutput; } - private List CollectTestResults(IEnumerable testCasesRun, string resultXmlFile, List consoleOutput, string baseDir, TestCase crashedTestCase) + private List CollectTestResults(IEnumerable testCasesRun, string resultXmlFile, string baseDir, TestCase crashedTestCase) { var testResults = new List(); TestCase[] testCasesRunAsArray = testCasesRun as TestCase[] ?? testCasesRun.ToArray(); - var consoleParser = new StandardOutputTestResultParser(testCasesRunAsArray, consoleOutput, _logger, baseDir); if (testResults.Count < testCasesRunAsArray.Length) { @@ -241,31 +217,15 @@ private List CollectTestResults(IEnumerable testCasesRun, _logger.DebugInfo($"{_threadName}Collected {nrOfCollectedTestResults} test results from result XML file {resultXmlFile}"); } - if (testResults.Count < testCasesRunAsArray.Length) - { - List consoleResults = consoleParser.GetTestResults(); - int nrOfCollectedTestResults = 0; - // ReSharper disable once AccessToModifiedClosure - foreach (TestResult testResult in consoleResults.Where(tr => !testResults.Exists(tr2 => tr.TestCase.FullyQualifiedName == tr2.TestCase.FullyQualifiedName))) - { - testResults.Add(testResult); - nrOfCollectedTestResults++; - } - if (nrOfCollectedTestResults > 0) - _logger.DebugInfo($"{_threadName}Collected {nrOfCollectedTestResults} test results from console output"); - } - if (testResults.Count < testCasesRunAsArray.Length) { string errorMessage, errorStackTrace = null; - if (consoleParser.CrashedTestCase == null && crashedTestCase == null) + if (crashedTestCase == null) { errorMessage = ""; } else { - if (crashedTestCase == null) - crashedTestCase = consoleParser.CrashedTestCase; errorMessage = $"reason is probably a crash of test {crashedTestCase.DisplayName}"; errorStackTrace = ErrorMessageParser.CreateStackTraceEntry("crash suspect", crashedTestCase.CodeFilePath, crashedTestCase.LineNumber.ToString()); diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 04e5823ce..5dae4b094 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -39,7 +39,6 @@ public interface IGoogleTestAdapterSettings bool? TimestampOutput { get; set; } bool? ShowReleaseNotes { get; set; } int? VisualStudioProcessId { get; set; } - bool? UseNewTestExecutionFramework { get; set; } bool? KillProcessesOnCancel { get; set; } } @@ -70,7 +69,6 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.TimestampOutput = self.TimestampOutput ?? other.TimestampOutput; self.ShowReleaseNotes = self.ShowReleaseNotes ?? other.ShowReleaseNotes; self.VisualStudioProcessId = self.VisualStudioProcessId ?? other.VisualStudioProcessId; - self.UseNewTestExecutionFramework = self.UseNewTestExecutionFramework ?? other.UseNewTestExecutionFramework; self.KillProcessesOnCancel = self.KillProcessesOnCancel ?? other.KillProcessesOnCancel; } } diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index 92506a903..ab4a6beb7 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -87,9 +87,6 @@ public RunSettings(string projectRegex) public virtual int? VisualStudioProcessId { get; set; } public bool ShouldSerializeVisualStudioProcessId() { return VisualStudioProcessId != null; } - public virtual bool? UseNewTestExecutionFramework { get; set; } - public bool ShouldSerializeUseNewTestExecutionFramework() { return UseNewTestExecutionFramework != null; } - public virtual bool? KillProcessesOnCancel { get; set; } public bool ShouldSerializeKillProcessesOnCancel() { return KillProcessesOnCancel != null; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index d54ed9be7..262899439 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -179,14 +179,6 @@ public static string ReplacePlaceholders(string userParameters, string executabl public virtual int VisualStudioProcessId => _currentSettings.VisualStudioProcessId ?? OptionVisualStudioProcessIdDefaultValue; - public const string OptionUseNewTestExecutionFramework = "Use new test execution framework (experimental)"; - public const bool OptionUseNewTestExecutionFrameworkDefaultValue = true; - public const string OptionUseNewTestExecutionFrameworkDescription = - "Make use of the new test execution framework. Advantages: test crash detection and test output printing also work in debug mode."; - - public virtual bool UseNewTestExecutionFramework => _currentSettings.UseNewTestExecutionFramework ?? OptionUseNewTestExecutionFrameworkDefaultValue; - - public const string OptionPrintTestOutput = "Print test output"; public const bool OptionPrintTestOutputDefaultValue = false; public const string OptionPrintTestOutputDescription = diff --git a/GoogleTestAdapter/Core/TestCases/ListTestsParser.cs b/GoogleTestAdapter/Core/TestCases/ListTestsParser.cs deleted file mode 100644 index 7b26c6007..000000000 --- a/GoogleTestAdapter/Core/TestCases/ListTestsParser.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; -using GoogleTestAdapter.Helpers; - -namespace GoogleTestAdapter.TestCases -{ - - public class ListTestsParser - { - private readonly string _testNameSeparator; - - public ListTestsParser(string testNameSeparator) - { - _testNameSeparator = testNameSeparator; - } - - public IList ParseListTestsOutput(IEnumerable consoleOutput) - { - var testCaseDescriptors = new List(); - - var actualParser = new StreamingListTestsParser(_testNameSeparator); - actualParser.TestCaseDescriptorCreated += (sender, args) => testCaseDescriptors.Add(args.TestCaseDescriptor); - - foreach (string line in consoleOutput) - { - actualParser.ReportLine(line); - } - return testCaseDescriptors; - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestCases/NewTestCaseResolver.cs b/GoogleTestAdapter/Core/TestCases/NewTestCaseResolver.cs deleted file mode 100644 index a128fe4ea..000000000 --- a/GoogleTestAdapter/Core/TestCases/NewTestCaseResolver.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using GoogleTestAdapter.Common; -using GoogleTestAdapter.DiaResolver; -using GoogleTestAdapter.Model; - -namespace GoogleTestAdapter.TestCases -{ - - internal class NewTestCaseResolver - { - // see GTA_Traits.h - private const string TraitSeparator = "__GTA__"; - private const string TraitAppendix = "_GTA_TRAIT"; - - private readonly string _executable; - private readonly string _pathExtension; - private readonly IDiaResolverFactory _diaResolverFactory; - private readonly ILogger _logger; - - private readonly List _allTestMethodSymbols = new List(); - private readonly List _allTraitSymbols = new List(); - - private bool _loadedSymbolsFromImports; - - internal NewTestCaseResolver(string executable, string pathExtension, IDiaResolverFactory diaResolverFactory, bool parseSymbolInformation, ILogger logger) - { - _executable = executable; - _pathExtension = pathExtension; - _diaResolverFactory = diaResolverFactory; - _logger = logger; - - if (parseSymbolInformation) - AddSymbolsFromBinary(executable); - else - _loadedSymbolsFromImports = true; - } - - internal TestCaseLocation FindTestCaseLocation(List testMethodSignatures) - { - TestCaseLocation result = DoFindTestCaseLocation(testMethodSignatures); - if (result == null && !_loadedSymbolsFromImports) - { - LoadSymbolsFromImports(); - _loadedSymbolsFromImports = true; - result = DoFindTestCaseLocation(testMethodSignatures); - } - return result; - } - - private void LoadSymbolsFromImports() - { - List imports = PeParser.ParseImports(_executable, _logger); - string moduleDirectory = Path.GetDirectoryName(_executable); - foreach (string import in imports) - { - // ReSharper disable once AssignNullToNotNullAttribute - string importedBinary = Path.Combine(moduleDirectory, import); - if (File.Exists(importedBinary)) - AddSymbolsFromBinary(importedBinary); - } - } - - private void AddSymbolsFromBinary(string binary) - { - using (IDiaResolver diaResolver = _diaResolverFactory.Create(binary, _pathExtension, _logger)) - { - try - { - _allTestMethodSymbols.AddRange(diaResolver.GetFunctions("*" + GoogleTestConstants.TestBodySignature)); - _allTraitSymbols.AddRange(diaResolver.GetFunctions("*" + TraitAppendix)); - - _logger.DebugInfo($"Found {_allTestMethodSymbols.Count} test method symbols and {_allTraitSymbols.Count} trait symbols in binary {binary}"); - } - catch (Exception e) - { - _logger.DebugError($"Exception while resolving test locations and traits in {binary}\n{e}"); - } - } - } - - private TestCaseLocation DoFindTestCaseLocation(List testMethodSignatures) - { - return _allTestMethodSymbols - .Where(nsfl => testMethodSignatures.Any(tms => Regex.IsMatch(nsfl.Symbol, tms))) // Contains() instead of == because nsfl might contain namespace - .Select(nsfl => ToTestCaseLocation(nsfl, _allTraitSymbols)) - .FirstOrDefault(); // we need to force immediate query execution, otherwise our session object will already be released - } - - private TestCaseLocation ToTestCaseLocation(SourceFileLocation location, IEnumerable allTraitSymbols) - { - List traits = GetTraits(location, allTraitSymbols); - var testCaseLocation = new TestCaseLocation(location.Symbol, location.Sourcefile, location.Line); - testCaseLocation.Traits.AddRange(traits); - return testCaseLocation; - } - - public static List GetTraits(SourceFileLocation nativeSymbol, IEnumerable allTraitSymbols) - { - var traits = new List(); - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (SourceFileLocation nativeTraitSymbol in allTraitSymbols) - { - if (nativeSymbol.Symbol.StartsWith(nativeTraitSymbol.TestClassSignature)) - { - int lengthOfSerializedTrait = nativeTraitSymbol.Symbol.Length - nativeTraitSymbol.IndexOfSerializedTrait - TraitAppendix.Length; - string serializedTrait = nativeTraitSymbol.Symbol.Substring(nativeTraitSymbol.IndexOfSerializedTrait, lengthOfSerializedTrait); - string[] data = serializedTrait.Split(new[] { TraitSeparator }, StringSplitOptions.None); - traits.Add(new Trait(data[0], data[1])); - } - } - - return traits; - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index 90d19296f..bf4af13ae 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -33,43 +33,9 @@ public TestCaseFactory(string executable, ILogger logger, SettingsWrapper settin public IList CreateTestCases(Action reportTestCase = null) { List standardOutput = new List(); - if (_settings.UseNewTestExecutionFramework) - { - return NewCreateTestcases(reportTestCase, standardOutput); - } - - try - { - var launcher = new ProcessLauncher(_logger, _settings.GetPathExtension(_executable), null); - int processExitCode; - standardOutput = launcher.GetOutputOfCommand("", _executable, GoogleTestConstants.ListTestsOption.Trim(), - false, false, out processExitCode); - - if (!CheckProcessExitCode(processExitCode, standardOutput)) - return new List(); - } - catch (Exception e) - { - SequentialTestRunner.LogExecutionError(_logger, _executable, Path.GetFullPath(""), - GoogleTestConstants.ListTestsOption.Trim(), e); - return new List(); - } - - IList testCaseDescriptors = new ListTestsParser(_settings.TestNameSeparator).ParseListTestsOutput(standardOutput); - if (_settings.ParseSymbolInformation) - { - List testCaseLocations = GetTestCaseLocations(testCaseDescriptors, _settings.GetPathExtension(_executable)); - return testCaseDescriptors.Select(descriptor => CreateTestCase(descriptor, testCaseLocations)).ToList(); - } - - return testCaseDescriptors.Select(CreateTestCase).ToList(); - } - - private IList NewCreateTestcases(Action reportTestCase, List standardOutput) - { var testCases = new List(); - var resolver = new NewTestCaseResolver( + var resolver = new TestCaseResolver( _executable, _settings.GetPathExtension(_executable), _diaResolverFactory, @@ -103,7 +69,7 @@ private IList NewCreateTestcases(Action reportTestCase, List try { - var executor = new ProcessExecutor(null, _logger); + var executor = new ProcessExecutor(_logger); int processExitCode = executor.ExecuteCommandBlocking( _executable, GoogleTestConstants.ListTestsOption.Trim(), @@ -142,19 +108,6 @@ private bool CheckProcessExitCode(int processExitCode, ICollection stand return true; } - private List GetTestCaseLocations(IList testCaseDescriptors, string pathExtension) - { - var testMethodSignatures = new List(); - foreach (TestCaseDescriptor descriptor in testCaseDescriptors) - { - testMethodSignatures.AddRange(_signatureCreator.GetTestMethodSignatures(descriptor)); - } - - string filterString = "*" + GoogleTestConstants.TestBodySignature; - var resolver = new TestCaseResolver(_diaResolverFactory, _logger); - return resolver.ResolveAllTestCases(_executable, testMethodSignatures, filterString, pathExtension); - } - private TestCase CreateTestCase(TestCaseDescriptor descriptor) { var testCase = new TestCase( diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseResolver.cs b/GoogleTestAdapter/Core/TestCases/TestCaseResolver.cs index cbd721211..e8859b941 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseResolver.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseResolver.cs @@ -13,74 +13,109 @@ namespace GoogleTestAdapter.TestCases internal class TestCaseResolver { // see GTA_Traits.h + private const string TraitSeparator = "__GTA__"; private const string TraitAppendix = "_GTA_TRAIT"; + private readonly string _executable; + private readonly string _pathExtension; private readonly IDiaResolverFactory _diaResolverFactory; private readonly ILogger _logger; - internal TestCaseResolver(IDiaResolverFactory diaResolverFactory, ILogger logger) + private readonly List _allTestMethodSymbols = new List(); + private readonly List _allTraitSymbols = new List(); + + private bool _loadedSymbolsFromImports; + + internal TestCaseResolver(string executable, string pathExtension, IDiaResolverFactory diaResolverFactory, bool parseSymbolInformation, ILogger logger) { + _executable = executable; + _pathExtension = pathExtension; _diaResolverFactory = diaResolverFactory; _logger = logger; + + if (parseSymbolInformation) + AddSymbolsFromBinary(executable); + else + _loadedSymbolsFromImports = true; } - internal List ResolveAllTestCases(string executable, List testMethodSignatures, string symbolFilterString, string pathExtension) + internal TestCaseLocation FindTestCaseLocation(List testMethodSignatures) { - List testCaseLocationsFound = - FindTestCaseLocationsInBinary(executable, testMethodSignatures, symbolFilterString, pathExtension).ToList(); - - if (testCaseLocationsFound.Count == 0) + TestCaseLocation result = DoFindTestCaseLocation(testMethodSignatures); + if (result == null && !_loadedSymbolsFromImports) { - List imports = PeParser.ParseImports(executable, _logger); - - string moduleDirectory = Path.GetDirectoryName(executable); - - foreach (string import in imports) - { - // ReSharper disable once AssignNullToNotNullAttribute - string importedBinary = Path.Combine(moduleDirectory, import); - if (File.Exists(importedBinary)) - { - testCaseLocationsFound.AddRange(FindTestCaseLocationsInBinary(importedBinary, testMethodSignatures, symbolFilterString, pathExtension)); - } - } + LoadSymbolsFromImports(); + _loadedSymbolsFromImports = true; + result = DoFindTestCaseLocation(testMethodSignatures); } - return testCaseLocationsFound; + return result; } + private void LoadSymbolsFromImports() + { + List imports = PeParser.ParseImports(_executable, _logger); + string moduleDirectory = Path.GetDirectoryName(_executable); + foreach (string import in imports) + { + // ReSharper disable once AssignNullToNotNullAttribute + string importedBinary = Path.Combine(moduleDirectory, import); + if (File.Exists(importedBinary)) + AddSymbolsFromBinary(importedBinary); + } + } - private IEnumerable FindTestCaseLocationsInBinary( - string binary, List testMethodSignatures, string symbolFilterString, string pathExtension) + private void AddSymbolsFromBinary(string binary) { - using (IDiaResolver diaResolver = _diaResolverFactory.Create(binary, pathExtension, _logger)) + using (IDiaResolver diaResolver = _diaResolverFactory.Create(binary, _pathExtension, _logger)) { try { - IList allTestMethodSymbols = diaResolver.GetFunctions(symbolFilterString); - IList allTraitSymbols = diaResolver.GetFunctions("*" + TraitAppendix); - _logger.DebugInfo($"Found {allTestMethodSymbols.Count} test method symbols and {allTraitSymbols.Count} trait symbols in binary {binary}"); - - return allTestMethodSymbols - .Where(nsfl => testMethodSignatures.Any(tms => Regex.IsMatch(nsfl.Symbol, tms))) // Contains() instead of == because nsfl might contain namespace - .Select(nsfl => ToTestCaseLocation(nsfl, allTraitSymbols)) - .ToList(); // we need to force immediate query execution, otherwise our session object will already be released + _allTestMethodSymbols.AddRange(diaResolver.GetFunctions("*" + GoogleTestConstants.TestBodySignature)); + _allTraitSymbols.AddRange(diaResolver.GetFunctions("*" + TraitAppendix)); + + _logger.DebugInfo($"Found {_allTestMethodSymbols.Count} test method symbols and {_allTraitSymbols.Count} trait symbols in binary {binary}"); } catch (Exception e) { _logger.DebugError($"Exception while resolving test locations and traits in {binary}\n{e}"); - return new TestCaseLocation[0]; } } } + private TestCaseLocation DoFindTestCaseLocation(List testMethodSignatures) + { + return _allTestMethodSymbols + .Where(nsfl => testMethodSignatures.Any(tms => Regex.IsMatch(nsfl.Symbol, tms))) // Contains() instead of == because nsfl might contain namespace + .Select(nsfl => ToTestCaseLocation(nsfl, _allTraitSymbols)) + .FirstOrDefault(); // we need to force immediate query execution, otherwise our session object will already be released + } + private TestCaseLocation ToTestCaseLocation(SourceFileLocation location, IEnumerable allTraitSymbols) { - List traits = NewTestCaseResolver.GetTraits(location, allTraitSymbols); + List traits = GetTraits(location, allTraitSymbols); var testCaseLocation = new TestCaseLocation(location.Symbol, location.Sourcefile, location.Line); testCaseLocation.Traits.AddRange(traits); return testCaseLocation; } + public static List GetTraits(SourceFileLocation nativeSymbol, IEnumerable allTraitSymbols) + { + var traits = new List(); + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (SourceFileLocation nativeTraitSymbol in allTraitSymbols) + { + if (nativeSymbol.Symbol.StartsWith(nativeTraitSymbol.TestClassSignature)) + { + int lengthOfSerializedTrait = nativeTraitSymbol.Symbol.Length - nativeTraitSymbol.IndexOfSerializedTrait - TraitAppendix.Length; + string serializedTrait = nativeTraitSymbol.Symbol.Substring(nativeTraitSymbol.IndexOfSerializedTrait, lengthOfSerializedTrait); + string[] data = serializedTrait.Split(new[] { TraitSeparator }, StringSplitOptions.None); + traits.Add(new Trait(data[0], data[1])); + } + } + + return traits; + } + } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs deleted file mode 100644 index 37ea30900..000000000 --- a/GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GoogleTestAdapter.Common; -using GoogleTestAdapter.Model; - -namespace GoogleTestAdapter.TestResults -{ - public class StandardOutputTestResultParser - { - private const string Run = "[ RUN ]"; - public const string Failed = "[ FAILED ]"; - public const string Passed = "[ OK ]"; - - public const string CrashText = "!! This test has probably CRASHED !!"; - - /// - /// 1000 ticks = 0.1ms to make sure VS shows "<1ms" - /// - public static readonly TimeSpan ShortTestDuration = TimeSpan.FromTicks(1000); - - public TestCase CrashedTestCase { get; private set; } - - private readonly List _consoleOutput; - private readonly List _testCasesRun; - private readonly ILogger _logger; - private readonly string _baseDir; - - - public StandardOutputTestResultParser(IEnumerable testCasesRun, IEnumerable consoleOutput, ILogger logger, string baseDir) - { - _consoleOutput = consoleOutput.ToList(); - _testCasesRun = testCasesRun.ToList(); - _logger = logger; - _baseDir = baseDir; - } - - - public List GetTestResults() - { - var testResults = new List(); - int indexOfNextTestcase = FindIndexOfNextTestcase(0); - while (indexOfNextTestcase >= 0) - { - testResults.Add(CreateTestResult(indexOfNextTestcase)); - indexOfNextTestcase = FindIndexOfNextTestcase(indexOfNextTestcase + 1); - } - return testResults; - } - - - private TestResult CreateTestResult(int indexOfTestcase) - { - int currentLineIndex = indexOfTestcase; - - string line = _consoleOutput[currentLineIndex++]; - string qualifiedTestname = RemovePrefix(line).Trim(); - TestCase testCase = FindTestcase(qualifiedTestname); - - if (currentLineIndex >= _consoleOutput.Count) - { - CrashedTestCase = testCase; - return CreateFailedTestResult(testCase, TimeSpan.FromMilliseconds(0), CrashText, ""); - } - - line = _consoleOutput[currentLineIndex++]; - - string errorMsg = ""; - while (!(IsFailedLine(line) || IsPassedLine(line)) && currentLineIndex <= _consoleOutput.Count) - { - errorMsg += line + "\n"; - line = currentLineIndex < _consoleOutput.Count ? _consoleOutput[currentLineIndex] : ""; - currentLineIndex++; - } - if (IsFailedLine(line)) - { - ErrorMessageParser parser = new ErrorMessageParser(errorMsg, _baseDir); - parser.Parse(); - return CreateFailedTestResult(testCase, ParseDuration(line), parser.ErrorMessage, parser.ErrorStackTrace); - } - if (IsPassedLine(line)) - { - return CreatePassedTestResult(testCase, ParseDuration(line)); - } - - CrashedTestCase = testCase; - string message = CrashText; - message += errorMsg == "" ? "" : "\nTest output:\n\n" + errorMsg; - return CreateFailedTestResult(testCase, TimeSpan.FromMilliseconds(0), message, ""); - } - - private TimeSpan ParseDuration(string line) - { - return ParseDuration(line, _logger); - } - - public static TimeSpan ParseDuration(string line, ILogger logger) - { - int durationInMs = 1; - try - { - // TODO check format in gtest code, replace with regex - int indexOfOpeningBracket = line.LastIndexOf('('); - int lengthOfDurationPart = line.Length - indexOfOpeningBracket - 2; - string durationPart = line.Substring(indexOfOpeningBracket + 1, lengthOfDurationPart); - durationPart = durationPart.Replace("ms", "").Trim(); - durationInMs = int.Parse(durationPart); - } - catch (Exception) - { - logger.LogWarning("Could not parse duration in line '" + line + "'"); - } - - return NormalizeDuration(TimeSpan.FromMilliseconds(durationInMs)); - } - - public static TimeSpan NormalizeDuration(TimeSpan duration) - { - return duration.TotalMilliseconds < 1 - ? ShortTestDuration - : duration; - } - - public static TestResult CreatePassedTestResult(TestCase testCase, TimeSpan duration) - { - return new TestResult(testCase) - { - ComputerName = Environment.MachineName, - DisplayName = testCase.DisplayName, - Outcome = TestOutcome.Passed, - Duration = duration - }; - } - - public static TestResult CreateFailedTestResult(TestCase testCase, TimeSpan duration, string errorMessage, string errorStackTrace) - { - return new TestResult(testCase) - { - ComputerName = Environment.MachineName, - DisplayName = testCase.DisplayName, - Outcome = TestOutcome.Failed, - ErrorMessage = errorMessage, - ErrorStackTrace = errorStackTrace, - Duration = duration - }; - } - - private int FindIndexOfNextTestcase(int currentIndex) - { - while (currentIndex < _consoleOutput.Count) - { - string line = _consoleOutput[currentIndex]; - if (IsRunLine(line)) - { - return currentIndex; - } - currentIndex++; - } - return -1; - } - - private TestCase FindTestcase(string qualifiedTestname) - { - return FindTestcase(qualifiedTestname, _testCasesRun); - } - - public static TestCase FindTestcase(string qualifiedTestname, IList testCasesRun) - { - return testCasesRun.Single(tc => tc.FullyQualifiedName == qualifiedTestname); - } - - public static bool IsRunLine(string line) - { - return line.StartsWith(Run); - } - - public static bool IsPassedLine(string line) - { - return line.StartsWith(Passed); - } - - public static bool IsFailedLine(string line) - { - return line.StartsWith(Failed); - } - - public static string RemovePrefix(string line) - { - return line.Substring(Run.Length); - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs deleted file mode 100644 index b0a3d6f1a..000000000 --- a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs +++ /dev/null @@ -1,165 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using GoogleTestAdapter.Common; -using GoogleTestAdapter.Framework; -using GoogleTestAdapter.Helpers; -using GoogleTestAdapter.Model; - -namespace GoogleTestAdapter.TestResults -{ - public class StreamingStandardOutputTestResultParser - { - private static readonly Regex PrefixedLineRegex; - - public TestCase CrashedTestCase { get; private set; } - public IList TestResults { get; } = new List(); - - private readonly List _testCasesRun; - private readonly ILogger _logger; - private readonly string _baseDir; - private readonly ITestFrameworkReporter _reporter; - - private readonly List _consoleOutput = new List(); - - static StreamingStandardOutputTestResultParser() - { - string passedMarker = Regex.Escape(StandardOutputTestResultParser.Passed); - string failedMarker = Regex.Escape(StandardOutputTestResultParser.Failed); - PrefixedLineRegex = new Regex($"(.*)((?:{passedMarker}|{failedMarker}).*)", RegexOptions.Compiled); - } - - public StreamingStandardOutputTestResultParser(IEnumerable testCasesRun, - ILogger logger, string baseDir, ITestFrameworkReporter reporter) - { - _testCasesRun = testCasesRun.ToList(); - _logger = logger; - _baseDir = baseDir; - _reporter = reporter; - } - - public void ReportLine(string line) - { - Match testEndMatch = PrefixedLineRegex.Match(line); - if (testEndMatch.Success) - { - string restOfErrorMessage = testEndMatch.Groups[1].Value; - if (!string.IsNullOrEmpty(restOfErrorMessage)) - DoReportLine(restOfErrorMessage); - - string testEndPart = testEndMatch.Groups[2].Value; - DoReportLine(testEndPart); - } - else - { - DoReportLine(line); - } - } - - private void DoReportLine(string line) - { - if (StandardOutputTestResultParser.IsRunLine(line)) - { - if (_consoleOutput.Count > 0) - { - ReportTestResult(); - _consoleOutput.Clear(); - } - ReportTestStart(line); - } - _consoleOutput.Add(line); - } - - public void Flush() - { - if (_consoleOutput.Count > 0) - { - ReportTestResult(); - _consoleOutput.Clear(); - } - } - - private void ReportTestStart(string line) - { - string qualifiedTestname = StandardOutputTestResultParser.RemovePrefix(line).Trim(); - TestCase testCase = StandardOutputTestResultParser.FindTestcase(qualifiedTestname, _testCasesRun); - _reporter.ReportTestsStarted(testCase.Yield()); - } - - private void ReportTestResult() - { - TestResult result = CreateTestResult(); - if (result != null) - { - _reporter.ReportTestResults(result.Yield()); - TestResults.Add(result); - } - } - - private TestResult CreateTestResult() - { - int currentLineIndex = 0; - while (currentLineIndex < _consoleOutput.Count && - !StandardOutputTestResultParser.IsRunLine(_consoleOutput[currentLineIndex])) - currentLineIndex++; - if (currentLineIndex == _consoleOutput.Count) - return null; - - string line = _consoleOutput[currentLineIndex++]; - string qualifiedTestname = StandardOutputTestResultParser.RemovePrefix(line).Trim(); - TestCase testCase = StandardOutputTestResultParser.FindTestcase(qualifiedTestname, _testCasesRun); - - if (currentLineIndex == _consoleOutput.Count) - { - CrashedTestCase = testCase; - return StandardOutputTestResultParser.CreateFailedTestResult( - testCase, - TimeSpan.FromMilliseconds(0), - StandardOutputTestResultParser.CrashText, - ""); - } - - line = _consoleOutput[currentLineIndex++]; - - string errorMsg = ""; - while ( - !(StandardOutputTestResultParser.IsFailedLine(line) - || StandardOutputTestResultParser.IsPassedLine(line)) - && currentLineIndex <= _consoleOutput.Count) - { - errorMsg += line + "\n"; - line = currentLineIndex < _consoleOutput.Count ? _consoleOutput[currentLineIndex] : ""; - currentLineIndex++; - } - if (StandardOutputTestResultParser.IsFailedLine(line)) - { - ErrorMessageParser parser = new ErrorMessageParser(errorMsg, _baseDir); - parser.Parse(); - return StandardOutputTestResultParser.CreateFailedTestResult( - testCase, - StandardOutputTestResultParser.ParseDuration(line, _logger), - parser.ErrorMessage, - parser.ErrorStackTrace); - } - if (StandardOutputTestResultParser.IsPassedLine(line)) - { - return StandardOutputTestResultParser.CreatePassedTestResult( - testCase, - StandardOutputTestResultParser.ParseDuration(line, _logger)); - } - - CrashedTestCase = testCase; - string message = StandardOutputTestResultParser.CrashText; - message += errorMsg == "" ? "" : $"\nTest output:\n\n{errorMsg}"; - TestResult result = StandardOutputTestResultParser.CreateFailedTestResult( - testCase, - TimeSpan.FromMilliseconds(0), - message, - ""); - return result; - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs b/GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs new file mode 100644 index 000000000..0e05e2ff3 --- /dev/null +++ b/GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs @@ -0,0 +1,251 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using GoogleTestAdapter.Common; +using GoogleTestAdapter.Framework; +using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.Model; + +namespace GoogleTestAdapter.TestResults +{ + public class StreamingTestOutputParser + { + public const string CrashText = "!! This test has probably CRASHED !!"; + + /// + /// 1000 ticks = 0.1ms to make sure VS shows "<1ms" + /// + public static readonly TimeSpan ShortTestDuration = TimeSpan.FromTicks(1000); + + private const string Run = "[ RUN ]"; + private const string Failed = "[ FAILED ]"; + private const string Passed = "[ OK ]"; + + private static readonly Regex PrefixedLineRegex; + + public TestCase CrashedTestCase { get; private set; } + public IList TestResults { get; } = new List(); + + private readonly List _testCasesRun; + private readonly ILogger _logger; + private readonly string _baseDir; + private readonly ITestFrameworkReporter _reporter; + + private readonly List _consoleOutput = new List(); + + static StreamingTestOutputParser() + { + string passedMarker = Regex.Escape(Passed); + string failedMarker = Regex.Escape(Failed); + PrefixedLineRegex = new Regex($"(.*)((?:{passedMarker}|{failedMarker}).*)", RegexOptions.Compiled); + } + + public StreamingTestOutputParser(IEnumerable testCasesRun, + ILogger logger, string baseDir, ITestFrameworkReporter reporter) + { + _testCasesRun = testCasesRun.ToList(); + _logger = logger; + _baseDir = baseDir; + _reporter = reporter; + } + + public void ReportLine(string line) + { + Match testEndMatch = PrefixedLineRegex.Match(line); + if (testEndMatch.Success) + { + string restOfErrorMessage = testEndMatch.Groups[1].Value; + if (!String.IsNullOrEmpty(restOfErrorMessage)) + DoReportLine(restOfErrorMessage); + + string testEndPart = testEndMatch.Groups[2].Value; + DoReportLine(testEndPart); + } + else + { + DoReportLine(line); + } + } + + public void Flush() + { + if (_consoleOutput.Count > 0) + { + ReportTestResult(); + _consoleOutput.Clear(); + } + } + + internal static TimeSpan NormalizeDuration(TimeSpan duration) + { + return duration.TotalMilliseconds < 1 + ? ShortTestDuration + : duration; + } + + private void DoReportLine(string line) + { + if (IsRunLine(line)) + { + if (_consoleOutput.Count > 0) + { + ReportTestResult(); + _consoleOutput.Clear(); + } + ReportTestStart(line); + } + _consoleOutput.Add(line); + } + + private void ReportTestStart(string line) + { + string qualifiedTestname = RemovePrefix(line).Trim(); + TestCase testCase = FindTestcase(qualifiedTestname, _testCasesRun); + _reporter.ReportTestsStarted(testCase.Yield()); + } + + private void ReportTestResult() + { + TestResult result = CreateTestResult(); + if (result != null) + { + _reporter.ReportTestResults(result.Yield()); + TestResults.Add(result); + } + } + + private TestResult CreateTestResult() + { + int currentLineIndex = 0; + while (currentLineIndex < _consoleOutput.Count && + !IsRunLine(_consoleOutput[currentLineIndex])) + currentLineIndex++; + if (currentLineIndex == _consoleOutput.Count) + return null; + + string line = _consoleOutput[currentLineIndex++]; + string qualifiedTestname = RemovePrefix(line).Trim(); + TestCase testCase = FindTestcase(qualifiedTestname, _testCasesRun); + + if (currentLineIndex == _consoleOutput.Count) + { + CrashedTestCase = testCase; + return CreateFailedTestResult( + testCase, + TimeSpan.FromMilliseconds(0), + CrashText, + ""); + } + + line = _consoleOutput[currentLineIndex++]; + + string errorMsg = ""; + while ( + !(IsFailedLine(line) + || IsPassedLine(line)) + && currentLineIndex <= _consoleOutput.Count) + { + errorMsg += line + "\n"; + line = currentLineIndex < _consoleOutput.Count ? _consoleOutput[currentLineIndex] : ""; + currentLineIndex++; + } + if (IsFailedLine(line)) + { + ErrorMessageParser parser = new ErrorMessageParser(errorMsg, _baseDir); + parser.Parse(); + return CreateFailedTestResult( + testCase, + ParseDuration(line), + parser.ErrorMessage, + parser.ErrorStackTrace); + } + if (IsPassedLine(line)) + { + return CreatePassedTestResult( + testCase, + ParseDuration(line)); + } + + CrashedTestCase = testCase; + string message = CrashText; + message += errorMsg == "" ? "" : $"\nTest output:\n\n{errorMsg}"; + TestResult result = CreateFailedTestResult( + testCase, + TimeSpan.FromMilliseconds(0), + message, + ""); + return result; + } + + private TimeSpan ParseDuration(string line) + { + int durationInMs = 1; + try + { + // TODO check format in gtest code, replace with regex + int indexOfOpeningBracket = line.LastIndexOf('('); + int lengthOfDurationPart = line.Length - indexOfOpeningBracket - 2; + string durationPart = line.Substring(indexOfOpeningBracket + 1, lengthOfDurationPart); + durationPart = durationPart.Replace("ms", "").Trim(); + durationInMs = Int32.Parse(durationPart); + } + catch (Exception) + { + _logger.LogWarning("Could not parse duration in line '" + line + "'"); + } + + return NormalizeDuration(TimeSpan.FromMilliseconds(durationInMs)); + } + + private TestResult CreatePassedTestResult(TestCase testCase, TimeSpan duration) + { + return new TestResult(testCase) + { + ComputerName = Environment.MachineName, + DisplayName = testCase.DisplayName, + Outcome = TestOutcome.Passed, + Duration = duration + }; + } + + private TestResult CreateFailedTestResult(TestCase testCase, TimeSpan duration, string errorMessage, string errorStackTrace) + { + return new TestResult(testCase) + { + ComputerName = Environment.MachineName, + DisplayName = testCase.DisplayName, + Outcome = TestOutcome.Failed, + ErrorMessage = errorMessage, + ErrorStackTrace = errorStackTrace, + Duration = duration + }; + } + + private TestCase FindTestcase(string qualifiedTestname, IList testCasesRun) + { + return testCasesRun.Single(tc => tc.FullyQualifiedName == qualifiedTestname); + } + + private bool IsRunLine(string line) + { + return line.StartsWith(Run); + } + + private bool IsPassedLine(string line) + { + return line.StartsWith(Passed); + } + + private bool IsFailedLine(string line) + { + return line.StartsWith(Failed); + } + + private string RemovePrefix(string line) + { + return line.Substring(Run.Length); + } + } + +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs index c1839749b..71fa2a16a 100644 --- a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs @@ -151,7 +151,7 @@ private string GetQualifiedName(XmlNode testcaseNode) private TimeSpan ParseDuration(string durationInSeconds) { return - StandardOutputTestResultParser + StreamingTestOutputParser .NormalizeDuration(TimeSpan.FromSeconds(double.Parse(durationInSeconds, NumberFormatInfo))); } diff --git a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings index b9ef65ee1..5b9fe3433 100644 --- a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings +++ b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings @@ -25,7 +25,6 @@ true - true false diff --git a/GoogleTestAdapter/TestAdapter.Tests/Framework/DebuggedProcessLauncherTests.cs b/GoogleTestAdapter/TestAdapter.Tests/Framework/DebuggedProcessLauncherTests.cs deleted file mode 100644 index 476d1449d..000000000 --- a/GoogleTestAdapter/TestAdapter.Tests/Framework/DebuggedProcessLauncherTests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; - -namespace GoogleTestAdapter.TestAdapter.Framework -{ - [TestClass] - public class DebuggedProcessLauncherTests : TestAdapterTestsBase - { - - [TestMethod] - [TestCategory(Unit)] - public void LaunchProcessWithDebuggerAttached_WithParameters_PassedInfoToFrameworkHandleCorrectly() - { - DebuggedProcessLauncher launcher = new DebuggedProcessLauncher(MockFrameworkHandle.Object); - - launcher.LaunchProcessWithDebuggerAttached("theCommand", "theDir", "theParams", @"C:\test"); - - MockFrameworkHandle.Verify(fh => - fh.LaunchProcessWithDebuggerAttached( - It.Is(s => s == "theCommand"), - It.Is(s => s == "theDir"), - It.Is(s => s == "theParams"), - It.Is>(d => d.ContainsKey("PATH") && d["PATH"].StartsWith(@"C:\test;")) - ), - Times.Exactly(1)); - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj index 3af8a2408..98c5cee5e 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj +++ b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj @@ -87,7 +87,6 @@ - diff --git a/GoogleTestAdapter/TestAdapter/Framework/DebuggedProcessLauncher.cs b/GoogleTestAdapter/TestAdapter/Framework/DebuggedProcessLauncher.cs deleted file mode 100644 index 5c7e5f6d2..000000000 --- a/GoogleTestAdapter/TestAdapter/Framework/DebuggedProcessLauncher.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using GoogleTestAdapter.Framework; -using GoogleTestAdapter.Helpers; -using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; - -namespace GoogleTestAdapter.TestAdapter.Framework -{ - public class DebuggedProcessLauncher : IDebuggedProcessLauncher - { - private readonly IFrameworkHandle _frameworkHandle; - - public DebuggedProcessLauncher(IFrameworkHandle handle) - { - _frameworkHandle = handle; - } - - public int LaunchProcessWithDebuggerAttached(string command, string workingDirectory, string param, string pathExtension) - { - IDictionary envVariables = new Dictionary(); - if (!string.IsNullOrEmpty(pathExtension)) - envVariables["PATH"] = Utils.GetExtendedPath(pathExtension); - return _frameworkHandle.LaunchProcessWithDebuggerAttached(command, workingDirectory, param, envVariables); - } - } - -} diff --git a/GoogleTestAdapter/TestAdapter/TestAdapter.csproj b/GoogleTestAdapter/TestAdapter/TestAdapter.csproj index e8420240a..d17b2be7c 100644 --- a/GoogleTestAdapter/TestAdapter/TestAdapter.csproj +++ b/GoogleTestAdapter/TestAdapter/TestAdapter.csproj @@ -163,7 +163,6 @@ - diff --git a/GoogleTestAdapter/TestAdapter/TestExecutor.cs b/GoogleTestAdapter/TestAdapter/TestExecutor.cs index ebe9d6c0f..df5855136 100644 --- a/GoogleTestAdapter/TestAdapter/TestExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/TestExecutor.cs @@ -8,7 +8,6 @@ using GoogleTestAdapter.Framework; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Settings; using GoogleTestAdapter.Model; using GoogleTestAdapter.TestAdapter.Helpers; @@ -177,18 +176,12 @@ private void DoRunTests( { bool isRunningInsideVisualStudio = !string.IsNullOrEmpty(runContext.SolutionDirectory); var reporter = new VsTestFrameworkReporter(frameworkHandle, isRunningInsideVisualStudio, _logger); - var launcher = new DebuggedProcessLauncher(frameworkHandle); - ProcessExecutor processExecutor = null; - if (_settings.UseNewTestExecutionFramework) - { - IDebuggerAttacher debuggerAttacher = null; - if (runContext.IsBeingDebugged) - debuggerAttacher = new VsDebuggerAttacher(_logger, _settings.VisualStudioProcessId); - processExecutor = new ProcessExecutor(debuggerAttacher, _logger); - } - _executor = new GoogleTestExecutor(_logger, _settings); - _executor.RunTests(allTestCasesInExecutables, testCasesToRun, reporter, launcher, - runContext.IsBeingDebugged, runContext.SolutionDirectory, processExecutor); + IDebuggerAttacher debuggerAttacher = null; + if (runContext.IsBeingDebugged) + debuggerAttacher = new VsDebuggerAttacher(_logger, _settings.VisualStudioProcessId); + _executor = new GoogleTestExecutor(_logger, _settings, debuggerAttacher); + _executor.RunTests(allTestCasesInExecutables, testCasesToRun, reporter, + runContext.IsBeingDebugged, runContext.SolutionDirectory); reporter.AllTestsFinished(); } diff --git a/GoogleTestAdapter/Common/ProcessWaiter.cs b/GoogleTestAdapter/Tests.Common/Helpers/ProcessWaiter.cs similarity index 95% rename from GoogleTestAdapter/Common/ProcessWaiter.cs rename to GoogleTestAdapter/Tests.Common/Helpers/ProcessWaiter.cs index abfccefdd..4c25e477f 100644 --- a/GoogleTestAdapter/Common/ProcessWaiter.cs +++ b/GoogleTestAdapter/Tests.Common/Helpers/ProcessWaiter.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.Threading; -namespace GoogleTestAdapter.Common +namespace GoogleTestAdapter.Tests.Common.Helpers { public class ProcessWaiter diff --git a/GoogleTestAdapter/Tests.Common/Helpers/TestProcessLauncher.cs b/GoogleTestAdapter/Tests.Common/Helpers/TestProcessLauncher.cs index 2139fa72e..a31498a5e 100644 --- a/GoogleTestAdapter/Tests.Common/Helpers/TestProcessLauncher.cs +++ b/GoogleTestAdapter/Tests.Common/Helpers/TestProcessLauncher.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using GoogleTestAdapter.Common; namespace GoogleTestAdapter.Tests.Common.Helpers { diff --git a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj index 12eb92956..ef957ac27 100644 --- a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj +++ b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj @@ -91,6 +91,7 @@ + diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index 747f11aef..f88da965a 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -66,7 +66,6 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.WorkingDir).Returns(SettingsWrapper.OptionWorkingDirDefaultValue); mockOptions.Setup(o => o.KillProcessesOnCancel).Returns(SettingsWrapper.OptionKillProcessesOnCancelDefaultValue); - mockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(true); mockOptions.Setup(o => o.VisualStudioProcessId).Returns(-1); } diff --git a/GoogleTestAdapter/VsPackage/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage/GoogleTestExtensionOptionsPage.cs index 62ae64273..a1df4e118 100644 --- a/GoogleTestAdapter/VsPackage/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage/GoogleTestExtensionOptionsPage.cs @@ -183,7 +183,6 @@ private RunSettings GetRunSettingsFromOptionPages() ParallelTestExecution = _parallelizationOptions.EnableParallelTestExecution, MaxNrOfThreads = _parallelizationOptions.MaxNrOfThreads, - UseNewTestExecutionFramework = _generalOptions.UseNewTestExecutionFramework2, VisualStudioProcessId = Process.GetCurrentProcess().Id }; } diff --git a/GoogleTestAdapter/VsPackage/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage/OptionsPages/GeneralOptionsDialogPage.cs index 5804ac3fb..359b79143 100644 --- a/GoogleTestAdapter/VsPackage/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage/OptionsPages/GeneralOptionsDialogPage.cs @@ -108,16 +108,6 @@ public string TraitsRegexesAfter #region Misc - [Category(SettingsWrapper.CategoryMiscName)] - [DisplayName(SettingsWrapper.OptionUseNewTestExecutionFramework)] - [Description(SettingsWrapper.OptionUseNewTestExecutionFrameworkDescription)] - public bool UseNewTestExecutionFramework2 - { - get { return _useNewTestExecutionFramework; } - set { SetAndNotify(ref _useNewTestExecutionFramework, value); } - } - private bool _useNewTestExecutionFramework = SettingsWrapper.OptionUseNewTestExecutionFrameworkDefaultValue; - [Category(SettingsWrapper.CategoryMiscName)] [DisplayName(SettingsWrapper.OptionPrintTestOutput)] [Description(SettingsWrapper.OptionPrintTestOutputDescription)] diff --git a/SampleTests/.gitignore b/SampleTests/.gitignore index ca08c8708..8bbc96b36 100644 --- a/SampleTests/.gitignore +++ b/SampleTests/.gitignore @@ -1,3 +1,4 @@ SampleTests.VC.db SampleTests.VC.VC.opendb -packages \ No newline at end of file +packages +/TestResults \ No newline at end of file From e3a508e549f713481f8d07aa91616e0f61e896f1 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 27 Feb 2017 10:13:05 +0100 Subject: [PATCH 2/5] re-added ListTestsParserTests as StreamingListTestsParserTests (#106) --- .../Core.Tests/Core.Tests.csproj | 1 + .../StreamingListTestsParserTests.cs | 167 ++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 GoogleTestAdapter/Core.Tests/TestCases/StreamingListTestsParserTests.cs diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index be56b82a8..f727de355 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -92,6 +92,7 @@ + diff --git a/GoogleTestAdapter/Core.Tests/TestCases/StreamingListTestsParserTests.cs b/GoogleTestAdapter/Core.Tests/TestCases/StreamingListTestsParserTests.cs new file mode 100644 index 000000000..eae78d5af --- /dev/null +++ b/GoogleTestAdapter/Core.Tests/TestCases/StreamingListTestsParserTests.cs @@ -0,0 +1,167 @@ +using System.Collections.Generic; +using FluentAssertions; +using GoogleTestAdapter.Tests.Common; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; + +namespace GoogleTestAdapter.TestCases +{ + + [TestClass] + public class StreamingListTestsParserTests : TestsBase + { + + [TestMethod] + [TestCategory(Unit)] + public void ParseListTestsOutput_SimpleTest_CorrectSuiteAndName() + { + var consoleOutput = new List + { + "MySuite.", + " MyTestCase" + }; + + var descriptors = ParseConsoleOutput(consoleOutput); + + descriptors.Count.Should().Be(1); + descriptors[0].Suite.Should().Be("MySuite"); + descriptors[0].Name.Should().Be("MyTestCase"); + + descriptors[0].DisplayName.Should().Be("MySuite.MyTestCase"); + descriptors[0].FullyQualifiedName.Should().Be("MySuite.MyTestCase"); + descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.Simple); + } + + [TestMethod] + [TestCategory(Unit)] + public void ParseListTestsOutput_TestWithParam_CorrectParsing() + { + var consoleOutput = new List + { + "InstantiationName/ParameterizedTests.", + " Simple/0 # GetParam() = (1,)", + }; + + var descriptors = ParseConsoleOutput(consoleOutput); + + descriptors.Count.Should().Be(1); + descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); + descriptors[0].Name.Should().Be("Simple/0"); + descriptors[0].FullyQualifiedName.Should().Be("InstantiationName/ParameterizedTests.Simple/0"); + descriptors[0].DisplayName.Should().Be("InstantiationName/ParameterizedTests.Simple/0 [(1,)]"); + descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.Parameterized); + } + + [TestMethod] + [TestCategory(Unit)] + public void ParseListTestsOutput_TestWithTypeParam_CorrectParsing() + { + var consoleOutput = new List + { + "TypedTests/0. # TypeParam = class std::vector >", + " CanIterate", + }; + + var descriptors = ParseConsoleOutput(consoleOutput); + + descriptors.Count.Should().Be(1); + descriptors[0].Suite.Should().Be("TypedTests/0"); + descriptors[0].Name.Should().Be("CanIterate"); + descriptors[0].FullyQualifiedName.Should().Be("TypedTests/0.CanIterate"); + descriptors[0].DisplayName.Should().Be("TypedTests/0.CanIterate > >"); + descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.TypeParameterized); + } + + [TestMethod] + [TestCategory(Unit)] + public void ParseListTestsOutput_TestWithTypeParamAndPrefix_CorrectParsing() + { + var consoleOutput = new List + { + "Arr/TypeParameterizedTests/1. # TypeParam = struct MyStrangeArray", + " CanIterate", + }; + + var descriptors = ParseConsoleOutput(consoleOutput); + + descriptors.Count.Should().Be(1); + descriptors[0].Suite.Should().Be("Arr/TypeParameterizedTests/1"); + descriptors[0].Name.Should().Be("CanIterate"); + descriptors[0].FullyQualifiedName.Should().Be("Arr/TypeParameterizedTests/1.CanIterate"); + descriptors[0].DisplayName.Should().Be("Arr/TypeParameterizedTests/1.CanIterate"); + descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.TypeParameterized); + } + + [TestMethod] + [TestCategory(Unit)] + public void ParseListTestsOutput_TestWithTypeParamAndPrefixOldFormat_CorrectParsing() + { + var consoleOutput = new List + { + "Arr/TypeParameterizedTests/1", + " CanIterate", + }; + + var descriptors = ParseConsoleOutput(consoleOutput); + + descriptors.Count.Should().Be(1); + descriptors[0].Suite.Should().Be("Arr/TypeParameterizedTests/1"); + descriptors[0].Name.Should().Be("CanIterate"); + descriptors[0].FullyQualifiedName.Should().Be("Arr/TypeParameterizedTests/1.CanIterate"); + descriptors[0].DisplayName.Should().Be("Arr/TypeParameterizedTests/1.CanIterate"); + descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.TypeParameterized); + } + + [TestMethod] + [TestCategory(Unit)] + public void ParseListTestsOutput_TestWithParamAndTestNameSeparator_CorrectParsing() + { + MockOptions.Setup(o => o.TestNameSeparator).Returns("::"); + var consoleOutput = new List + { + "InstantiationName/ParameterizedTests.", + " Simple/0 # GetParam() = (1,)", + }; + + var descriptors = ParseConsoleOutput(consoleOutput); + + descriptors.Count.Should().Be(1); + descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); + descriptors[0].Name.Should().Be("Simple/0"); + descriptors[0].FullyQualifiedName.Should().Be("InstantiationName/ParameterizedTests.Simple/0"); + descriptors[0].DisplayName.Should().Be("InstantiationName::ParameterizedTests.Simple::0 [(1,)]"); + descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.Parameterized); + } + + [TestMethod] + [TestCategory(Unit)] + public void ParseListTestsOutput_TestWithParamAndTestNameSeparatorOldFormat_CorrectParsing() + { + MockOptions.Setup(o => o.TestNameSeparator).Returns("::"); + var consoleOutput = new List + { + "InstantiationName/ParameterizedTests.", + " Simple/0", + }; + + var descriptors = ParseConsoleOutput(consoleOutput); + + descriptors.Count.Should().Be(1); + descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); + descriptors[0].Name.Should().Be("Simple/0"); + descriptors[0].FullyQualifiedName.Should().Be("InstantiationName/ParameterizedTests.Simple/0"); + descriptors[0].DisplayName.Should().Be("InstantiationName::ParameterizedTests.Simple::0"); + descriptors[0].TestType.Should().Be(TestCaseDescriptor.TestTypes.Parameterized); + } + + private List ParseConsoleOutput(List consoleOutput) + { + var descriptors = new List(); + var parser = new StreamingListTestsParser(TestEnvironment.Options.TestNameSeparator); + parser.TestCaseDescriptorCreated += (sender, args) => descriptors.Add(args.TestCaseDescriptor); + consoleOutput.ForEach(s => parser.ReportLine(s)); + return descriptors; + } + } + +} \ No newline at end of file From 3eeea7fab510541a331018d39645726a40b84dfc Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 27 Feb 2017 12:20:49 +0100 Subject: [PATCH 3/5] moved some functionality to better places --- GoogleTestAdapter/Common/LoggerBase.cs | 7 ++++ .../Core.Tests/Common/LoggerBaseTests.cs | 36 +++++++++++++++++++ .../Core.Tests/Core.Tests.csproj | 4 +-- .../Core.Tests/Helpers/DebugUtilsTests.cs | 30 ---------------- .../Core.Tests/Helpers/UtilsTests.cs | 30 +++++++--------- .../Runners/SequentialTestRunnerTests.cs | 2 +- .../RegexTraitParserTests.cs | 12 +++---- .../Settings/SettingsWrapperTests.cs | 1 - GoogleTestAdapter/Core/Core.csproj | 3 +- GoogleTestAdapter/Core/GoogleTestConstants.cs | 2 +- GoogleTestAdapter/Core/GoogleTestExecutor.cs | 4 +-- GoogleTestAdapter/Core/Helpers/DebugUtils.cs | 25 ------------- GoogleTestAdapter/Core/Helpers/Extensions.cs | 26 -------------- .../Core/Helpers/ProcessExecutor.cs | 8 ++++- GoogleTestAdapter/Core/Helpers/Utils.cs | 23 +++++++----- GoogleTestAdapter/Core/Model/TestCase.cs | 20 +++++++++++ .../Core/Runners/CommandLineGenerator.cs | 6 ++-- .../Core/Runners/ParallelTestRunner.cs | 8 ++--- .../Core/Runners/PreparingTestRunner.cs | 13 ++++--- .../Core/Runners/SequentialTestRunner.cs | 8 ++--- .../Core/Scheduling/TestDurationSerializer.cs | 3 +- .../{Helpers => Settings}/RegexTraitParser.cs | 3 +- .../Core/Settings/SettingsWrapper.cs | 2 +- .../TestAdapter/CommonFunctions.cs | 1 - .../Framework/VsTestFrameworkLogger.cs | 3 +- .../Tests.Common/Fakes/FakeLogger.cs | 3 +- 26 files changed, 132 insertions(+), 151 deletions(-) create mode 100644 GoogleTestAdapter/Core.Tests/Common/LoggerBaseTests.cs delete mode 100644 GoogleTestAdapter/Core.Tests/Helpers/DebugUtilsTests.cs rename GoogleTestAdapter/Core.Tests/{Helpers => Settings}/RegexTraitParserTests.cs (91%) delete mode 100644 GoogleTestAdapter/Core/Helpers/DebugUtils.cs rename GoogleTestAdapter/Core/{Helpers => Settings}/RegexTraitParser.cs (95%) diff --git a/GoogleTestAdapter/Common/LoggerBase.cs b/GoogleTestAdapter/Common/LoggerBase.cs index 0bab4000b..f7cb67475 100644 --- a/GoogleTestAdapter/Common/LoggerBase.cs +++ b/GoogleTestAdapter/Common/LoggerBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; namespace GoogleTestAdapter.Common @@ -69,6 +70,12 @@ public void DebugError(string message) if (_inDebugMode()) LogError(message); } + + public static void TimestampMessage(ref string message) + { + string timestamp = DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture); + message = $"{timestamp} - {message ?? ""}"; + } } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/Common/LoggerBaseTests.cs b/GoogleTestAdapter/Core.Tests/Common/LoggerBaseTests.cs new file mode 100644 index 000000000..74945fe37 --- /dev/null +++ b/GoogleTestAdapter/Core.Tests/Common/LoggerBaseTests.cs @@ -0,0 +1,36 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; + +namespace GoogleTestAdapter.Common +{ + [TestClass] + public class LoggerBaseTests + { + + [TestMethod] + [TestCategory(Unit)] + public void TimestampMessage_MessageIsNullOrEmpty_ResultIsTheSame() + { + string timestampSeparator = " - "; + string resultRegex = @"[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}" + timestampSeparator; + + string nullMessage = null; + LoggerBase.TimestampMessage(ref nullMessage); + nullMessage.Should().MatchRegex(resultRegex); + nullMessage.Should().EndWith(timestampSeparator); + + string emptyMessage = ""; + LoggerBase.TimestampMessage(ref emptyMessage); + emptyMessage.Should().MatchRegex(resultRegex); + emptyMessage.Should().EndWith(timestampSeparator); + + string fooMessage = "foo"; + LoggerBase.TimestampMessage(ref fooMessage); + fooMessage.Should().MatchRegex(resultRegex); + fooMessage.Should().EndWith(timestampSeparator + "foo"); + } + + } + +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index f727de355..c8e364c12 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -81,13 +81,13 @@ + - - + diff --git a/GoogleTestAdapter/Core.Tests/Helpers/DebugUtilsTests.cs b/GoogleTestAdapter/Core.Tests/Helpers/DebugUtilsTests.cs deleted file mode 100644 index f6cf9220b..000000000 --- a/GoogleTestAdapter/Core.Tests/Helpers/DebugUtilsTests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; - -namespace GoogleTestAdapter.Helpers -{ - - [TestClass] - public class DebugUtilsTests - { - - [TestMethod] - [TestCategory(Unit)] - [ExpectedException(typeof(ArgumentNullException))] - public void AssertIsNotNull_Null_ThrowsException() - { - DebugUtils.AssertIsNotNull(null, "foo"); - } - - [TestMethod] - [TestCategory(Unit)] - [ExpectedException(typeof(ArgumentException))] - public void AssertIsNull_NotNull_ThrowsException() - { - DebugUtils.AssertIsNull("", "foo"); - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs b/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs index f0e159b95..e85d2d97a 100644 --- a/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs +++ b/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; @@ -43,25 +44,18 @@ public void GetTempDirectory__DirectoryDoesExistAndCanBeDeleted() [TestMethod] [TestCategory(Unit)] - public void TimestampMessage_MessageIsNullOrEmpty_ResultIsTheSame() + public void AssertIsNotNull_Null_ThrowsException() { - string timestampSeparator = " - "; - string resultRegex = @"[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}" + timestampSeparator; - - string nullMessage = null; - Utils.TimestampMessage(ref nullMessage); - nullMessage.Should().MatchRegex(resultRegex); - nullMessage.Should().EndWith(timestampSeparator); - - string emptyMessage = ""; - Utils.TimestampMessage(ref emptyMessage); - emptyMessage.Should().MatchRegex(resultRegex); - emptyMessage.Should().EndWith(timestampSeparator); + Action action = () => Utils.AssertIsNotNull(null, "foo"); + action.ShouldThrow(); + } - string fooMessage = "foo"; - Utils.TimestampMessage(ref fooMessage); - fooMessage.Should().MatchRegex(resultRegex); - fooMessage.Should().EndWith(timestampSeparator + "foo"); + [TestMethod] + [TestCategory(Unit)] + public void AssertIsNull_NotNull_ThrowsException() + { + Action action = () => Utils.AssertIsNull("", "foo"); + action.ShouldThrow(); } private void SetReadonlyFlag(string dir) diff --git a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs index 5fcc8dec1..a12e98b5d 100644 --- a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs +++ b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs @@ -42,7 +42,7 @@ private void DoRunCancelingTests(bool killProcesses, int lower, int upper) List testCasesToRun = TestDataCreator.GetTestCases("Crashing.LongRunning", "LongRunningTests.Test2"); var stopwatch = new Stopwatch(); - var runner = new SequentialTestRunner("", MockFrameworkReporter.Object, TestEnvironment.Logger, TestEnvironment.Options, new SchedulingAnalyzer(TestEnvironment.Logger), null); + var runner = new SequentialTestRunner("", null, MockFrameworkReporter.Object, new SchedulingAnalyzer(TestEnvironment.Logger), TestEnvironment.Options, TestEnvironment.Logger); var thread = new Thread(() => runner.RunTests(allTestCases, testCasesToRun, "", "", "")); stopwatch.Start(); diff --git a/GoogleTestAdapter/Core.Tests/Helpers/RegexTraitParserTests.cs b/GoogleTestAdapter/Core.Tests/Settings/RegexTraitParserTests.cs similarity index 91% rename from GoogleTestAdapter/Core.Tests/Helpers/RegexTraitParserTests.cs rename to GoogleTestAdapter/Core.Tests/Settings/RegexTraitParserTests.cs index 3a7905093..a570c6212 100644 --- a/GoogleTestAdapter/Core.Tests/Helpers/RegexTraitParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/RegexTraitParserTests.cs @@ -1,11 +1,9 @@ using System.Collections.Generic; using FluentAssertions; -using GoogleTestAdapter.Settings; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; -using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; -namespace GoogleTestAdapter.Helpers +namespace GoogleTestAdapter.Settings { [TestClass] public class RegexTraitParserTests : TestsBase @@ -22,7 +20,7 @@ public override void SetUp() [TestMethod] - [TestCategory(Unit)] + [TestCategory(TestMetadata.TestCategories.Unit)] public void ParseTraitsRegexesString_UnparsableString_FailsNicely() { List result = Parser.ParseTraitsRegexesString("vrr result = Parser.ParseTraitsRegexesString(""); @@ -42,7 +40,7 @@ public void ParseTraitsRegexesString_EmptyString_EmptyResult() } [TestMethod] - [TestCategory(Unit)] + [TestCategory(TestMetadata.TestCategories.Unit)] public void ParseTraitsRegexesString_OneRegex_ParsedCorrectly() { string optionsString = CreateTraitsRegex("MyTest*", "Type", "Small"); @@ -57,7 +55,7 @@ public void ParseTraitsRegexesString_OneRegex_ParsedCorrectly() } [TestMethod] - [TestCategory(Unit)] + [TestCategory(TestMetadata.TestCategories.Unit)] public void ParseTraitsRegexesString_TwoRegexes_ParsedCorrectly() { string optionsString = ConcatTraitsRegexes( diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 3d1294d31..4b1f94244 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using FluentAssertions; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; diff --git a/GoogleTestAdapter/Core/Core.csproj b/GoogleTestAdapter/Core/Core.csproj index 5c1729a63..0a5018f30 100644 --- a/GoogleTestAdapter/Core/Core.csproj +++ b/GoogleTestAdapter/Core/Core.csproj @@ -50,11 +50,10 @@ - - + diff --git a/GoogleTestAdapter/Core/GoogleTestConstants.cs b/GoogleTestAdapter/Core/GoogleTestConstants.cs index ff64abaa9..e5d718702 100644 --- a/GoogleTestAdapter/Core/GoogleTestConstants.cs +++ b/GoogleTestAdapter/Core/GoogleTestConstants.cs @@ -28,7 +28,7 @@ public static class GoogleTestConstants public static string GetResultXmlFileOption(string resultXmlFile) { - return "--gtest_output=\"xml:" + resultXmlFile + "\""; + return $"--gtest_output=\"xml:{resultXmlFile}\""; } public static string GetCatchExceptionsOption(bool catchThem) diff --git a/GoogleTestAdapter/Core/GoogleTestExecutor.cs b/GoogleTestAdapter/Core/GoogleTestExecutor.cs index 7136c29fc..780f40201 100644 --- a/GoogleTestAdapter/Core/GoogleTestExecutor.cs +++ b/GoogleTestAdapter/Core/GoogleTestExecutor.cs @@ -63,11 +63,11 @@ private void ComputeTestRunner(ITestFrameworkReporter reporter, bool isBeingDebu { if (_settings.ParallelTestExecution && !isBeingDebugged) { - _runner = new ParallelTestRunner(reporter, _logger, _settings, solutionDirectory, _schedulingAnalyzer, _debuggerAttacher); + _runner = new ParallelTestRunner(solutionDirectory, _debuggerAttacher, reporter, _schedulingAnalyzer, _settings, _logger); } else { - _runner = new PreparingTestRunner(solutionDirectory, reporter, _logger, _settings, _schedulingAnalyzer, _debuggerAttacher); + _runner = new PreparingTestRunner(solutionDirectory, _debuggerAttacher, reporter, _schedulingAnalyzer, _settings, _logger); if (_settings.ParallelTestExecution && isBeingDebugged) { _logger.DebugInfo( diff --git a/GoogleTestAdapter/Core/Helpers/DebugUtils.cs b/GoogleTestAdapter/Core/Helpers/DebugUtils.cs deleted file mode 100644 index 2f2c960f8..000000000 --- a/GoogleTestAdapter/Core/Helpers/DebugUtils.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace GoogleTestAdapter.Helpers -{ - public static class DebugUtils - { - public static void AssertIsNotNull(object parameter, string parameterName) - { - if (parameter == null) - { - throw new ArgumentNullException(parameterName); - } - } - - public static void AssertIsNull(object parameter, string parameterName) - { - if (parameter != null) - { - throw new ArgumentException(parameterName + " must be null"); - } - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Helpers/Extensions.cs b/GoogleTestAdapter/Core/Helpers/Extensions.cs index ba95e9161..a89cd4b5e 100644 --- a/GoogleTestAdapter/Core/Helpers/Extensions.cs +++ b/GoogleTestAdapter/Core/Helpers/Extensions.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using GoogleTestAdapter.Model; namespace GoogleTestAdapter.Helpers { @@ -12,31 +11,6 @@ public static IEnumerable Yield(this T item) yield return item; } - internal static IDictionary> GroupByExecutable(this IEnumerable testcases) - { - var groupedTestCases = new Dictionary>(); - foreach (TestCase testCase in testcases) - { - List group; - if (groupedTestCases.ContainsKey(testCase.Source)) - { - group = groupedTestCases[testCase.Source]; - } - else - { - group = new List(); - groupedTestCases.Add(testCase.Source, group); - } - group.Add(testCase); - } - return groupedTestCases; - } - - internal static string AppendIfNotEmpty(this string theString, string appendix) - { - return string.IsNullOrWhiteSpace(theString) ? theString : theString + appendix; - } - } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs b/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs index c1d186f7c..b9ed1b362 100644 --- a/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs +++ b/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs @@ -166,7 +166,7 @@ private static StringBuilder CreateEnvironment(string pathExtension) StringDictionary envVariables = new ProcessStartInfo().EnvironmentVariables; if (!string.IsNullOrEmpty(pathExtension)) - envVariables["PATH"] = Utils.GetExtendedPath(pathExtension); + envVariables["PATH"] = GetExtendedPath(pathExtension); var envVariablesList = new List(); foreach (DictionaryEntry entry in envVariables) @@ -184,6 +184,12 @@ private static StringBuilder CreateEnvironment(string pathExtension) return result; } + private static string GetExtendedPath(string pathExtension) + { + string path = Environment.GetEnvironmentVariable("PATH"); + return string.IsNullOrEmpty(pathExtension) ? path : $"{pathExtension};{path}"; + } + private static PROCESS_INFORMATION CreateProcess(string command, string parameters, string workingDir, string pathExtension, SafePipeHandle outputPipeWritingEnd) { diff --git a/GoogleTestAdapter/Core/Helpers/Utils.cs b/GoogleTestAdapter/Core/Helpers/Utils.cs index 08b8934e4..ac4d8a600 100644 --- a/GoogleTestAdapter/Core/Helpers/Utils.cs +++ b/GoogleTestAdapter/Core/Helpers/Utils.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using System.IO; namespace GoogleTestAdapter.Helpers @@ -10,7 +9,11 @@ public static class Utils public static string GetTempDirectory() { - string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + string tempDirectory; + do + { + tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + } while (Directory.Exists(tempDirectory) || File.Exists(tempDirectory)); Directory.CreateDirectory(tempDirectory); return tempDirectory; } @@ -30,16 +33,20 @@ public static bool DeleteDirectory(string directory, out string errorMessage) } } - public static string GetExtendedPath(string pathExtension) + public static void AssertIsNotNull(object parameter, string parameterName) { - string path = Environment.GetEnvironmentVariable("PATH"); - return string.IsNullOrEmpty(pathExtension) ? path : $"{pathExtension};{path}"; + if (parameter == null) + { + throw new ArgumentNullException(parameterName); + } } - public static void TimestampMessage(ref string message) + public static void AssertIsNull(object parameter, string parameterName) { - string timestamp = DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture); - message = $"{timestamp} - {message ?? ""}"; + if (parameter != null) + { + throw new ArgumentException(parameterName + " must be null"); + } } } diff --git a/GoogleTestAdapter/Core/Model/TestCase.cs b/GoogleTestAdapter/Core/Model/TestCase.cs index 6ecf7b01c..80f4ebc59 100644 --- a/GoogleTestAdapter/Core/Model/TestCase.cs +++ b/GoogleTestAdapter/Core/Model/TestCase.cs @@ -46,6 +46,26 @@ public override string ToString() return DisplayName; } + internal static IDictionary> GroupByExecutable(IEnumerable testcases) + { + var groupedTestCases = new Dictionary>(); + foreach (TestCase testCase in testcases) + { + List group; + if (groupedTestCases.ContainsKey(testCase.Source)) + { + group = groupedTestCases[testCase.Source]; + } + else + { + group = new List(); + groupedTestCases.Add(testCase.Source, group); + } + group.Add(testCase); + } + return groupedTestCases; + } + } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs b/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs index b7f1cf1bd..aa0b78fd9 100644 --- a/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs +++ b/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; using GoogleTestAdapter.Settings; @@ -194,7 +193,10 @@ private string GetTestsRepetitionsParameter() private string GetFilterForSuitesRunningAllTests(List suitesRunningAllTests) { - return string.Join(".*:", suitesRunningAllTests).AppendIfNotEmpty(".*:"); + string filter = string.Join(".*:", suitesRunningAllTests); + if (!string.IsNullOrWhiteSpace(filter)) + filter += ".*:"; + return filter; } private bool AllTestCasesOfExecutableAreRun() diff --git a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs index e60ffb8ae..9a07acab9 100644 --- a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs @@ -21,7 +21,7 @@ public class ParallelTestRunner : ITestRunner private readonly IDebuggerAttacher _debuggerAttacher; - public ParallelTestRunner(ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, string solutionDirectory, SchedulingAnalyzer schedulingAnalyzer, IDebuggerAttacher debuggerAttacher) + public ParallelTestRunner(string solutionDirectory, IDebuggerAttacher debuggerAttacher, ITestFrameworkReporter reporter, SchedulingAnalyzer schedulingAnalyzer, SettingsWrapper settings, ILogger logger) { _frameworkReporter = reporter; _logger = logger; @@ -38,8 +38,8 @@ public void RunTests(IEnumerable allTestCases, IEnumerable t List threads; lock (this) { - DebugUtils.AssertIsNull(workingDir, nameof(workingDir)); - DebugUtils.AssertIsNull(userParameters, nameof(userParameters)); + Utils.AssertIsNull(workingDir, nameof(workingDir)); + Utils.AssertIsNull(userParameters, nameof(userParameters)); threads = new List(); RunTests(allTestCases, testCasesToRun, baseDir, threads); @@ -76,7 +76,7 @@ private void RunTests(IEnumerable allTestCases, IEnumerable int threadId = 0; foreach (List testcases in splittedTestCasesToRun) { - var runner = new PreparingTestRunner(threadId++, _solutionDirectory, _frameworkReporter, _logger, _settings.Clone(), _schedulingAnalyzer, _debuggerAttacher); + var runner = new PreparingTestRunner(threadId++, _solutionDirectory, _debuggerAttacher, _frameworkReporter, _schedulingAnalyzer, _settings.Clone(), _logger); _testRunners.Add(runner); var thread = new Thread(() => runner.RunTests(allTestCases, testcases, baseDir, null, null)); diff --git a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs index a602eebad..e324285bf 100644 --- a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs @@ -24,28 +24,27 @@ public class PreparingTestRunner : ITestRunner private readonly string _solutionDirectory; - public PreparingTestRunner(int threadId, string solutionDirectory, ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer, IDebuggerAttacher debuggerAttacher) + public PreparingTestRunner(int threadId, string solutionDirectory, IDebuggerAttacher debuggerAttacher, ITestFrameworkReporter reporter, SchedulingAnalyzer schedulingAnalyzer, SettingsWrapper settings, ILogger logger) { _logger = logger; _settings = settings; string threadName = ComputeThreadName(threadId, _settings.MaxNrOfThreads); _threadName = string.IsNullOrEmpty(threadName) ? "" : $"{threadName} "; _threadId = Math.Max(0, threadId); - _innerTestRunner = new SequentialTestRunner(_threadName, reporter, _logger, _settings, schedulingAnalyzer, debuggerAttacher); + _innerTestRunner = new SequentialTestRunner(_threadName, debuggerAttacher, reporter, schedulingAnalyzer, _settings, _logger); _solutionDirectory = solutionDirectory; } - public PreparingTestRunner(string solutionDirectory, ITestFrameworkReporter reporter, - ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer, IDebuggerAttacher debuggerAttacher) - : this(-1, solutionDirectory, reporter, logger, settings, schedulingAnalyzer, debuggerAttacher){ + public PreparingTestRunner(string solutionDirectory, IDebuggerAttacher debuggerAttacher, ITestFrameworkReporter reporter, SchedulingAnalyzer schedulingAnalyzer, SettingsWrapper settings, ILogger logger) + : this(-1, solutionDirectory, debuggerAttacher, reporter, schedulingAnalyzer, settings, logger){ } public void RunTests(IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, string workingDir, string userParameters) { - DebugUtils.AssertIsNull(userParameters, nameof(userParameters)); - DebugUtils.AssertIsNull(workingDir, nameof(workingDir)); + Utils.AssertIsNull(userParameters, nameof(userParameters)); + Utils.AssertIsNull(workingDir, nameof(workingDir)); try { diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index fa673796f..024f8f75e 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -25,7 +25,7 @@ public class SequentialTestRunner : ITestRunner private readonly SchedulingAnalyzer _schedulingAnalyzer; - public SequentialTestRunner(string threadName, ITestFrameworkReporter reporter, ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer, IDebuggerAttacher debuggerAttacher) + public SequentialTestRunner(string threadName, IDebuggerAttacher debuggerAttacher, ITestFrameworkReporter reporter, SchedulingAnalyzer schedulingAnalyzer, SettingsWrapper settings, ILogger logger) { _threadName = threadName; _frameworkReporter = reporter; @@ -39,10 +39,10 @@ public SequentialTestRunner(string threadName, ITestFrameworkReporter reporter, public void RunTests(IEnumerable allTestCases, IEnumerable testCasesToRun, string baseDir, string workingDir, string userParameters) { - DebugUtils.AssertIsNotNull(userParameters, nameof(userParameters)); - DebugUtils.AssertIsNotNull(workingDir, nameof(workingDir)); + Utils.AssertIsNotNull(userParameters, nameof(userParameters)); + Utils.AssertIsNotNull(workingDir, nameof(workingDir)); - IDictionary> groupedTestCases = testCasesToRun.GroupByExecutable(); + IDictionary> groupedTestCases = TestCase.GroupByExecutable(testCasesToRun); TestCase[] allTestCasesAsArray = allTestCases as TestCase[] ?? allTestCases.ToArray(); foreach (string executable in groupedTestCases.Keys) { diff --git a/GoogleTestAdapter/Core/Scheduling/TestDurationSerializer.cs b/GoogleTestAdapter/Core/Scheduling/TestDurationSerializer.cs index 8380283cc..d0e6907c1 100644 --- a/GoogleTestAdapter/Core/Scheduling/TestDurationSerializer.cs +++ b/GoogleTestAdapter/Core/Scheduling/TestDurationSerializer.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Xml.Serialization; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; namespace GoogleTestAdapter.Scheduling @@ -45,7 +44,7 @@ public class TestDurationSerializer public IDictionary ReadTestDurations(IEnumerable testcases) { - IDictionary> groupedTestcases = testcases.GroupByExecutable(); + IDictionary> groupedTestcases = TestCase.GroupByExecutable(testcases); var durations = new Dictionary(); foreach (string executable in groupedTestcases.Keys) { diff --git a/GoogleTestAdapter/Core/Helpers/RegexTraitParser.cs b/GoogleTestAdapter/Core/Settings/RegexTraitParser.cs similarity index 95% rename from GoogleTestAdapter/Core/Helpers/RegexTraitParser.cs rename to GoogleTestAdapter/Core/Settings/RegexTraitParser.cs index 9ce2b8d5a..370f94499 100644 --- a/GoogleTestAdapter/Core/Helpers/RegexTraitParser.cs +++ b/GoogleTestAdapter/Core/Settings/RegexTraitParser.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Settings; -namespace GoogleTestAdapter.Helpers +namespace GoogleTestAdapter.Settings { public class RegexTraitParser { diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 262899439..21f8ec779 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -4,8 +4,8 @@ using System.Linq; using System.Reflection; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; +using GoogleTestAdapter.TestCases; namespace GoogleTestAdapter.Settings { diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index 6d9fb9c82..a85b6aa16 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Settings; using GoogleTestAdapter.TestAdapter.Framework; using GoogleTestAdapter.TestAdapter.Settings; diff --git a/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs b/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs index 808337c90..362e15566 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs @@ -1,6 +1,5 @@ using System; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Helpers; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; namespace GoogleTestAdapter.TestAdapter.Framework @@ -42,7 +41,7 @@ public override void Log(Severity severity, string message) private void LogSafe(TestMessageLevel level, string message) { if (_timeStampOutput()) - Utils.TimestampMessage(ref message); + TimestampMessage(ref message); if (string.IsNullOrWhiteSpace(message)) { diff --git a/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs b/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs index 4e6b2770b..08786949a 100644 --- a/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs +++ b/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Helpers; namespace GoogleTestAdapter.Tests.Common.Fakes { @@ -25,7 +24,7 @@ public FakeLogger(Func inDebugMode, bool timestampLogMessages = true) public override void Log(Severity severity, string message) { if (_timeStampLogMessages) - Utils.TimestampMessage(ref message); + TimestampMessage(ref message); lock (this) { From 4d9709cd0eeecf6a00efac4db3bd1a804a04f7c6 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 27 Feb 2017 19:58:40 +0100 Subject: [PATCH 4/5] excluded VS2017 build from overall CI build result as long as end-to-end tests are unstable --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 1c1cee733..e6eb70cf6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,6 +7,9 @@ platform: Any CPU environment: RELEASE_KEY_PASSWORD: secure: 3+fpAMwxomiOZ5fzpb+3kjV4RvPSn0GRvFp71bZZs3QQr06zNU2Wvu4p77dmTKH+ +matrix: + allow_failures: + - os: Visual Studio 2017 RC install: - ps: >- if ($env:APPVEYOR_REPO_TAG -eq "true") { From 6b96cad5c7d560ac993e5d824a99bbdc56e03b79 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 11 Mar 2017 13:47:20 +0100 Subject: [PATCH 5/5] ITestFrameworkReporter now accepts single objects instead of enumerations --- .../Core/Framework/ITestFrameworkReporter.cs | 9 ++-- .../Core/GoogleTestDiscoverer.cs | 2 +- .../Core/Helpers/ProcessExecutor.cs | 10 ++++- .../Core/Runners/SequentialTestRunner.cs | 7 ++- .../TestResults/StreamingTestOutputParser.cs | 5 +-- .../Framework/VsTestFrameworkReporterTests.cs | 5 +-- .../Framework/VSTestFrameworkReporter.cs | 44 +++++++------------ .../Framework/VsDebuggerAttacher.cs | 1 + .../TestAdapter/Helpers/ParentProcessUtils.cs | 9 ++-- .../Fakes/FakeFrameworkReporter.cs | 8 ++-- 10 files changed, 51 insertions(+), 49 deletions(-) diff --git a/GoogleTestAdapter/Core/Framework/ITestFrameworkReporter.cs b/GoogleTestAdapter/Core/Framework/ITestFrameworkReporter.cs index 732c4e0ba..ed0f313d8 100644 --- a/GoogleTestAdapter/Core/Framework/ITestFrameworkReporter.cs +++ b/GoogleTestAdapter/Core/Framework/ITestFrameworkReporter.cs @@ -1,17 +1,16 @@ -using System.Collections.Generic; -using GoogleTestAdapter.Model; +using GoogleTestAdapter.Model; namespace GoogleTestAdapter.Framework { public interface ITestFrameworkReporter { - void ReportTestsFound(IEnumerable testCases); + void ReportTestFound(TestCase testCase); - void ReportTestsStarted(IEnumerable testCases); + void ReportTestStarted(TestCase testCase); /// if test execution has been canceled in the meantime - void ReportTestResults(IEnumerable testResults); + void ReportTestResult(TestResult testResult); } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs index 1e3155c89..5e06c3f21 100644 --- a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs +++ b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs @@ -44,7 +44,7 @@ private static void DiscoverTests(string executable, ITestFrameworkReporter repo int nrOfTestCases = 0; Action reportTestCases = tc => { - reporter.ReportTestsFound(tc.Yield()); + reporter.ReportTestFound(tc); logger.DebugInfo("Added testcase " + tc.DisplayName); nrOfTestCases++; }; diff --git a/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs b/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs index b9ed1b362..30372acee 100644 --- a/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs +++ b/GoogleTestAdapter/Core/Helpers/ProcessExecutor.cs @@ -265,6 +265,8 @@ private static extern bool CreatePipe( private static SafeHandle NULL_HANDLE = new SafePipeHandle(IntPtr.Zero, false); +#pragma warning disable 414 +#pragma warning disable 169 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private class STARTUPINFOEX { @@ -290,11 +292,14 @@ private class STARTUPINFO public Int16 wShowWindow; public Int16 cbReserved2; public IntPtr lpReserved2; + // ReSharper disable UnusedMember.Local + // ReSharper disable NotAccessedField.Local public SafeHandle hStdInput = NULL_HANDLE; public SafeHandle hStdOutput = NULL_HANDLE; public SafeHandle hStdError = NULL_HANDLE; + // ReSharper restore NotAccessedField.Local + // ReSharper restore UnusedMember.Local } - [StructLayout(LayoutKind.Sequential)] private struct PROCESS_INFORMATION { @@ -311,6 +316,9 @@ private class SECURITY_ATTRIBUTES public IntPtr lpSecurityDescriptor; public bool bInheritHandle; } +#pragma warning restore 169 +#pragma warning restore 414 + } } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index 024f8f75e..161e31c46 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -95,8 +95,11 @@ private void RunTestsFromExecutable(string executable, string workingDir, try { Stopwatch stopwatch = Stopwatch.StartNew(); - _frameworkReporter.ReportTestsStarted(results.Select(tr => tr.TestCase)); - _frameworkReporter.ReportTestResults(results); + foreach (TestResult testResult in results) + { + _frameworkReporter.ReportTestStarted(testResult.TestCase); + _frameworkReporter.ReportTestResult(testResult); + } stopwatch.Stop(); if (results.Length > 0) _logger.DebugInfo($"{_threadName}Reported {results.Length} test results to VS, executable: '{executable}', duration: {stopwatch.Elapsed}"); diff --git a/GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs b/GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs index 0e05e2ff3..e73f5a980 100644 --- a/GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs +++ b/GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs @@ -4,7 +4,6 @@ using System.Text.RegularExpressions; using GoogleTestAdapter.Common; using GoogleTestAdapter.Framework; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; namespace GoogleTestAdapter.TestResults @@ -102,7 +101,7 @@ private void ReportTestStart(string line) { string qualifiedTestname = RemovePrefix(line).Trim(); TestCase testCase = FindTestcase(qualifiedTestname, _testCasesRun); - _reporter.ReportTestsStarted(testCase.Yield()); + _reporter.ReportTestStarted(testCase); } private void ReportTestResult() @@ -110,7 +109,7 @@ private void ReportTestResult() TestResult result = CreateTestResult(); if (result != null) { - _reporter.ReportTestResults(result.Yield()); + _reporter.ReportTestResult(result); TestResults.Add(result); } } diff --git a/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkReporterTests.cs b/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkReporterTests.cs index 3df5a4b7a..dbe544905 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkReporterTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkReporterTests.cs @@ -1,5 +1,4 @@ using System; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; using VsTestResult = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -39,7 +38,7 @@ public void ReportTestResults_FromVsTestConsole_StacktraceEndsWithoutNewline() }; var reporter = new VsTestFrameworkReporter(MockFrameworkHandle.Object, false, MockLogger.Object); - reporter.ReportTestResults(result.Yield()); + reporter.ReportTestResult(result); MockFrameworkHandle.Verify(h => h.RecordResult( It.Is(tr => tr.ErrorStackTrace.Equals(errorStacktrace))), @@ -57,7 +56,7 @@ private void DoTestBeginOfErrorMessage(bool inVisualStudio, string beginOfErrorM }; var reporter = new VsTestFrameworkReporter(MockFrameworkHandle.Object, inVisualStudio, MockLogger.Object); - reporter.ReportTestResults(result.Yield()); + reporter.ReportTestResult(result); MockFrameworkHandle.Verify(h => h.RecordResult( It.Is(tr => tr.ErrorMessage.Equals(beginOfErrorMessage + errorMessage))), diff --git a/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs b/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs index 2a403431e..8f4e3afce 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading; using GoogleTestAdapter.Common; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; @@ -53,47 +52,38 @@ private VsTestFrameworkReporter(ITestCaseDiscoverySink sink, IFrameworkHandle fr } - public void ReportTestsFound(IEnumerable testCases) + public void ReportTestFound(TestCase testCase) { lock (Lock) { - foreach (TestCase testCase in testCases) - { - _sink.SendTestCase(testCase.ToVsTestCase()); - } + _sink.SendTestCase(testCase.ToVsTestCase()); } } - public void ReportTestsStarted(IEnumerable testCases) + public void ReportTestStarted(TestCase testCase) { lock (Lock) { - foreach (TestCase testCase in testCases) - { - _frameworkHandle.RecordStart(testCase.ToVsTestCase()); - } + _frameworkHandle.RecordStart(testCase.ToVsTestCase()); } } - public void ReportTestResults(IEnumerable testResults) + public void ReportTestResult(TestResult testResult) { lock (Lock) { - foreach (TestResult testResult in testResults) + if (_isRunningInsideVisualStudio && (testResult.Outcome == TestOutcome.Failed || testResult.Outcome == TestOutcome.Skipped)) + testResult.ErrorMessage = Environment.NewLine + testResult.ErrorMessage; + if (!_isRunningInsideVisualStudio && testResult.ErrorStackTrace != null) + testResult.ErrorStackTrace = testResult.ErrorStackTrace.Trim(); + + try + { + DoReportTestResult(testResult); + } + catch (TestCanceledException e) { - if (_isRunningInsideVisualStudio && (testResult.Outcome == TestOutcome.Failed || testResult.Outcome == TestOutcome.Skipped)) - testResult.ErrorMessage = Environment.NewLine + testResult.ErrorMessage; - if (!_isRunningInsideVisualStudio && testResult.ErrorStackTrace != null) - testResult.ErrorStackTrace = testResult.ErrorStackTrace.Trim(); - - try - { - ReportTestResult(testResult); - } - catch (TestCanceledException e) - { - throw new TestRunCanceledException($"{nameof(VsTestFrameworkReporter)} caught TestCanceledException", e); - } + throw new TestRunCanceledException($"{nameof(VsTestFrameworkReporter)} caught TestCanceledException", e); } } } @@ -104,7 +94,7 @@ private bool TestReportingNeedsToBeThrottled() return VsVersionUtils.GetVisualStudioVersion(_logger) != VsVersion.VS2017; } - private void ReportTestResult(TestResult testResult) + private void DoReportTestResult(TestResult testResult) { VsTestResult result = testResult.ToVsTestResult(); diff --git a/GoogleTestAdapter/TestAdapter/Framework/VsDebuggerAttacher.cs b/GoogleTestAdapter/TestAdapter/Framework/VsDebuggerAttacher.cs index 462676fe5..cc4935d92 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VsDebuggerAttacher.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VsDebuggerAttacher.cs @@ -19,6 +19,7 @@ namespace GoogleTestAdapter.TestAdapter.Framework { + [Serializable] internal class LastWin32Exception : Win32Exception { public LastWin32Exception() diff --git a/GoogleTestAdapter/TestAdapter/Helpers/ParentProcessUtils.cs b/GoogleTestAdapter/TestAdapter/Helpers/ParentProcessUtils.cs index f5b5d9292..691c9896a 100644 --- a/GoogleTestAdapter/TestAdapter/Helpers/ParentProcessUtils.cs +++ b/GoogleTestAdapter/TestAdapter/Helpers/ParentProcessUtils.cs @@ -19,8 +19,11 @@ public struct ParentProcessUtils internal IntPtr UniqueProcessId; internal IntPtr InheritedFromUniqueProcessId; - [DllImport("ntdll.dll")] - private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtils processInformation, int processInformationLength, out int returnLength); + private static class NativeMethods + { + [DllImport("ntdll.dll")] + internal static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtils processInformation, int processInformationLength, out int returnLength); + } /// /// Gets the parent process of the current process. @@ -51,7 +54,7 @@ public static Process GetParentProcess(IntPtr handle) { ParentProcessUtils pbi = new ParentProcessUtils(); int returnLength; - int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength); + int status = NativeMethods.NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength); if (status != 0) return null; diff --git a/GoogleTestAdapter/Tests.Common/Fakes/FakeFrameworkReporter.cs b/GoogleTestAdapter/Tests.Common/Fakes/FakeFrameworkReporter.cs index 02b1f8793..d1857c585 100644 --- a/GoogleTestAdapter/Tests.Common/Fakes/FakeFrameworkReporter.cs +++ b/GoogleTestAdapter/Tests.Common/Fakes/FakeFrameworkReporter.cs @@ -8,17 +8,17 @@ public class FakeFrameworkReporter : ITestFrameworkReporter { public IList ReportedTestResults { get; } = new List(); - public void ReportTestsFound(IEnumerable testCases) + public void ReportTestFound(TestCase testCase) { } - public void ReportTestsStarted(IEnumerable testCases) + public void ReportTestStarted(TestCase testCase) { } - public void ReportTestResults(IEnumerable testResults) + public void ReportTestResult(TestResult testResult) { - ((List)ReportedTestResults).AddRange(testResults); + ReportedTestResults.Add(testResult); } }