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/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 5057fc1f8..75892291e 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -81,27 +81,25 @@ + - - + - - - + + - 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/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/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/Helpers/UtilsTests.cs b/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs index 652a32f65..526157512 100644 --- a/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs +++ b/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs @@ -46,25 +46,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); - - string fooMessage = "foo"; - Utils.TimestampMessage(ref fooMessage); - fooMessage.Should().MatchRegex(resultRegex); - fooMessage.Should().EndWith(timestampSeparator + "foo"); + Action action = () => Utils.AssertIsNotNull(null, "foo"); + action.ShouldThrow(); + } + + [TestMethod] + [TestCategory(Unit)] + public void AssertIsNull_NotNull_ThrowsException() + { + Action action = () => Utils.AssertIsNull("", "foo"); + action.ShouldThrow(); } [TestMethod] diff --git a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs index 8f2d1b5a5..a12e98b5d 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("", null, MockFrameworkReporter.Object, new SchedulingAnalyzer(TestEnvironment.Logger), TestEnvironment.Options, TestEnvironment.Logger); + var thread = new Thread(() => runner.RunTests(allTestCases, testCasesToRun, "", "", "")); stopwatch.Start(); thread.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 b980fb9d7..3c21bc7f5 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; @@ -334,7 +333,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/StreamingListTestsParserTests.cs similarity index 83% rename from GoogleTestAdapter/Core.Tests/TestCases/ListTestsParserTests.cs rename to GoogleTestAdapter/Core.Tests/TestCases/StreamingListTestsParserTests.cs index 24290e4ce..eae78d5af 100644 --- a/GoogleTestAdapter/Core.Tests/TestCases/ListTestsParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestCases/StreamingListTestsParserTests.cs @@ -8,7 +8,7 @@ namespace GoogleTestAdapter.TestCases { [TestClass] - public class ListTestsParserTests : TestsBase + public class StreamingListTestsParserTests : TestsBase { [TestMethod] @@ -21,8 +21,7 @@ public void ParseListTestsOutput_SimpleTest_CorrectSuiteAndName() " MyTestCase" }; - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); + var descriptors = ParseConsoleOutput(consoleOutput); descriptors.Count.Should().Be(1); descriptors[0].Suite.Should().Be("MySuite"); @@ -43,8 +42,7 @@ public void ParseListTestsOutput_TestWithParam_CorrectParsing() " Simple/0 # GetParam() = (1,)", }; - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); + var descriptors = ParseConsoleOutput(consoleOutput); descriptors.Count.Should().Be(1); descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); @@ -64,8 +62,7 @@ public void ParseListTestsOutput_TestWithTypeParam_CorrectParsing() " CanIterate", }; - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); + var descriptors = ParseConsoleOutput(consoleOutput); descriptors.Count.Should().Be(1); descriptors[0].Suite.Should().Be("TypedTests/0"); @@ -85,8 +82,7 @@ public void ParseListTestsOutput_TestWithTypeParamAndPrefix_CorrectParsing() " CanIterate", }; - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); + var descriptors = ParseConsoleOutput(consoleOutput); descriptors.Count.Should().Be(1); descriptors[0].Suite.Should().Be("Arr/TypeParameterizedTests/1"); @@ -106,8 +102,7 @@ public void ParseListTestsOutput_TestWithTypeParamAndPrefixOldFormat_CorrectPars " CanIterate", }; - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); + var descriptors = ParseConsoleOutput(consoleOutput); descriptors.Count.Should().Be(1); descriptors[0].Suite.Should().Be("Arr/TypeParameterizedTests/1"); @@ -128,8 +123,7 @@ public void ParseListTestsOutput_TestWithParamAndTestNameSeparator_CorrectParsin " Simple/0 # GetParam() = (1,)", }; - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); + var descriptors = ParseConsoleOutput(consoleOutput); descriptors.Count.Should().Be(1); descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); @@ -150,8 +144,7 @@ public void ParseListTestsOutput_TestWithParamAndTestNameSeparatorOldFormat_Corr " Simple/0", }; - IList descriptors = new ListTestsParser(TestEnvironment.Options.TestNameSeparator) - .ParseListTestsOutput(consoleOutput); + var descriptors = ParseConsoleOutput(consoleOutput); descriptors.Count.Should().Be(1); descriptors[0].Suite.Should().Be("InstantiationName/ParameterizedTests"); @@ -161,6 +154,14 @@ public void ParseListTestsOutput_TestWithParamAndTestNameSeparatorOldFormat_Corr 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 diff --git a/GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs deleted file mode 100644 index d998abc1d..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) - .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); - 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 800f59e89..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) - .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, 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 256ecaf16..b0d2ed748 100644 --- a/GoogleTestAdapter/Core/Core.csproj +++ b/GoogleTestAdapter/Core/Core.csproj @@ -45,26 +45,20 @@ - - - - - - + - @@ -85,11 +79,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/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/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/GoogleTestDiscoverer.cs b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs index 3cfd25222..3f694c1c1 100644 --- a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs +++ b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs @@ -33,24 +33,10 @@ public GoogleTestDiscoverer(ILogger logger, SettingsWrapper settings, IDiaResolv public void DiscoverTests(IEnumerable executables, ITestFrameworkReporter reporter) { IList googleTestExecutables = GetAllGoogleTestExecutables(executables); - if (_settings.UseNewTestExecutionFramework) - { - var discoveryActions = googleTestExecutables - .Select(e => (Action)(() => DiscoverTests(e, reporter, _settings.Clone(), _logger, _diaResolverFactory))) - .ToArray(); - Utils.SpawnAndWait(discoveryActions); - } - else - { - foreach (string executable in googleTestExecutables) - { - _settings.ExecuteWithSettingsForExecutable(executable, () => - { - IList testCases = GetTestsFromExecutable(executable); - reporter.ReportTestsFound(testCases); - }, _logger); - } - } + var discoveryActions = googleTestExecutables + .Select(e => (Action)(() => DiscoverTests(e, reporter, _settings.Clone(), _logger, _diaResolverFactory))) + .ToArray(); + Utils.SpawnAndWait(discoveryActions); } private static void DiscoverTests(string executable, ITestFrameworkReporter reporter, SettingsWrapper settings, ILogger logger, IDiaResolverFactory diaResolverFactory) @@ -60,7 +46,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/GoogleTestExecutor.cs b/GoogleTestAdapter/Core/GoogleTestExecutor.cs index cc84f982f..780f40201 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(solutionDirectory, _debuggerAttacher, reporter, _schedulingAnalyzer, _settings, _logger); } else { - _runner = new PreparingTestRunner(solutionDirectory, reporter, _logger, _settings, _schedulingAnalyzer); + _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 ebdb6baff..30372acee 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")] @@ -139,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) @@ -157,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) { @@ -232,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 { @@ -257,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 { @@ -278,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/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/Helpers/Utils.cs b/GoogleTestAdapter/Core/Helpers/Utils.cs index 512c2c33a..84720cff0 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; using System.Threading; using System.Threading.Tasks; @@ -12,7 +11,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; } @@ -32,16 +35,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"); + } } /// If at least one of the actions has thrown an exception 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/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 ae37be2e8..15c208f7c 100644 --- a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs @@ -18,29 +18,31 @@ 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(string solutionDirectory, IDebuggerAttacher debuggerAttacher, ITestFrameworkReporter reporter, SchedulingAnalyzer schedulingAnalyzer, SettingsWrapper settings, ILogger logger) { _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) { - 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, 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,11 +76,11 @@ 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, _debuggerAttacher, _frameworkReporter, _schedulingAnalyzer, _settings.Clone(), _logger); _testRunners.Add(runner); var thread = new Thread( - () => runner.RunTests(allTestCases, testcases, baseDir, null, null, isBeingDebugged, debuggedLauncher, executor)){ Name = $"GTA Testrunner {threadId}" }; + () => runner.RunTests(allTestCases, testcases, baseDir, null, null)){ Name = $"GTA Testrunner {threadId}" }; threads.Add(thread); thread.Start(); diff --git a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs index de4ea495f..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) + 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); + _innerTestRunner = new SequentialTestRunner(_threadName, debuggerAttacher, reporter, schedulingAnalyzer, _settings, _logger); _solutionDirectory = solutionDirectory; } - public PreparingTestRunner(string solutionDirectory, ITestFrameworkReporter reporter, - ILogger logger, SettingsWrapper settings, SchedulingAnalyzer schedulingAnalyzer) - : this(-1, solutionDirectory, reporter, logger, settings, schedulingAnalyzer){ + 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, bool isBeingDebugged, IDebuggedProcessLauncher debuggedLauncher, IProcessExecutor executor) + 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 { @@ -57,13 +56,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 +86,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 +100,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 +109,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 04b86a6b5..7cc165739 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -18,29 +18,31 @@ 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, IDebuggerAttacher debuggerAttacher, ITestFrameworkReporter reporter, SchedulingAnalyzer schedulingAnalyzer, SettingsWrapper settings, ILogger logger) { _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)); + 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) { @@ -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,14 +89,17 @@ private void RunTestsFromExecutable(string executable, string workingDir, { break; } - var streamingParser = new StreamingStandardOutputTestResultParser(arguments.TestCases, _logger, _frameworkReporter); - var results = RunTests(executable, workingDir, 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 { 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}"); @@ -120,12 +119,12 @@ private void RunTestsFromExecutable(string executable, string workingDir, } } - private IEnumerable RunTests(string executable, string workingDir, 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, isBeingDebugged, debuggedLauncher, arguments, resultXmlFile, executor, streamingParser); + return TryRunTests(executable, workingDir, baseDir, arguments, resultXmlFile, streamingParser); } catch (Exception e) { @@ -144,35 +143,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, 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, 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 +163,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 +181,6 @@ private List RunTestExecutableWithNewFramework(string executable, string Cancel(); } }; - _processExecutor = executor; _processExecutor.ExecuteCommandBlocking( executable, arguments.CommandLine, workingDir, pathExtension, reportOutputAction); @@ -207,7 +189,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 +197,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, 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); if (testResults.Count < testCasesRunAsArray.Length) { @@ -241,31 +220,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/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/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index c1976f467..bd4c97b1b 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -40,7 +40,6 @@ public interface IGoogleTestAdapterSettings bool? TimestampOutput { get; set; } bool? ShowReleaseNotes { get; set; } int? VisualStudioProcessId { get; set; } - bool? UseNewTestExecutionFramework { get; set; } bool? KillProcessesOnCancel { get; set; } } @@ -72,7 +71,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/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/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index 682003e79..8adbb2095 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -90,9 +90,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 0d46e5262..15577e8b0 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -5,8 +5,8 @@ using System.Reflection; using System.Threading; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; +using GoogleTestAdapter.TestCases; namespace GoogleTestAdapter.Settings { @@ -234,14 +234,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 3396e110f..2d16e18bd 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -34,43 +34,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, @@ -108,7 +74,7 @@ private IList NewCreateTestcases(Action reportTestCase, List ProcessExecutor executor = null; var listAndParseTestsTask = new Task(() => { - executor = new ProcessExecutor(null, _logger); + executor = new ProcessExecutor(_logger); processExitCode = executor.ExecuteCommandBlocking( _executable, GoogleTestConstants.ListTestsOption.Trim(), @@ -164,19 +130,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 8e34d624a..000000000 --- a/GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs +++ /dev/null @@ -1,192 +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; - - - public StandardOutputTestResultParser(IEnumerable testCasesRun, IEnumerable consoleOutput, ILogger logger) - { - _consoleOutput = consoleOutput.ToList(); - _testCasesRun = testCasesRun.ToList(); - _logger = logger; - } - - - 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); - 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 5472fd0ec..000000000 --- a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs +++ /dev/null @@ -1,163 +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 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, ITestFrameworkReporter reporter) - { - _testCasesRun = testCasesRun.ToList(); - _logger = logger; - _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); - 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..44adb48fa --- /dev/null +++ b/GoogleTestAdapter/Core/TestResults/StreamingTestOutputParser.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using GoogleTestAdapter.Common; +using GoogleTestAdapter.Framework; +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.ReportTestStarted(testCase); + } + + private void ReportTestResult() + { + TestResult result = CreateTestResult(); + if (result != null) + { + _reporter.ReportTestResult(result); + 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); + 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 ab13c60c4..2dc586871 100644 --- a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs @@ -149,7 +149,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 c959108e2..b6113c77a 100644 --- a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings +++ b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings @@ -26,7 +26,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/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.Tests/TestAdapter.Tests.csproj b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj index e89a42082..067a7a08d 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj +++ b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj @@ -88,7 +88,6 @@ - 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/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/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/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/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/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 fe3ab5550..894e09d52 100644 --- a/GoogleTestAdapter/TestAdapter/TestExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/TestExecutor.cs @@ -9,7 +9,6 @@ using GoogleTestAdapter.Helpers; 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; @@ -189,24 +188,19 @@ 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); - } + IDebuggerAttacher debuggerAttacher = null; + if (runContext.IsBeingDebugged) + debuggerAttacher = new VsDebuggerAttacher(_logger, _settings.VisualStudioProcessId); lock (_lock) { if (_canceled) return; - _executor = new GoogleTestExecutor(_logger, _settings); + _executor = new GoogleTestExecutor(_logger, _settings, debuggerAttacher); } - _executor.RunTests(allTestCasesInExecutables, testCasesToRun, reporter, launcher, - runContext.IsBeingDebugged, runContext.SolutionDirectory, processExecutor); + _executor.RunTests(allTestCasesInExecutables, testCasesToRun, reporter, + runContext.IsBeingDebugged, runContext.SolutionDirectory); + reporter.AllTestsFinished(); } 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); } } 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) { 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 f179ea272..86db64e2b 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 cbb6ef271..5c77f78c8 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -70,7 +70,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 c874ba4c4..e290aac5c 100644 --- a/GoogleTestAdapter/VsPackage/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage/GoogleTestExtensionOptionsPage.cs @@ -184,7 +184,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 70f2dc2ef..92171dc9c 100644 --- a/GoogleTestAdapter/VsPackage/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage/OptionsPages/GeneralOptionsDialogPage.cs @@ -118,16 +118,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 diff --git a/appveyor.yml b/appveyor.yml index 766889a38..352841f4d 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") {