From 81361f7a129a16cf5f7022cc93bd2502cd107b5a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 5 Oct 2012 19:44:09 +0200 Subject: [PATCH] Use named pipe instead of temporary file for sending the unit tests results to SharpDevelop. --- .../Interfaces/IUnitTestProcessRunner.cs | 2 +- .../Interfaces/UnitTestProcessRunner.cs | 5 + .../NUnit/NUnitConsoleApplication.cs | 10 +- .../UnitTesting/NUnit/NUnitTestDebugger.cs | 13 +- .../UnitTesting/NUnit/NUnitTestRunner.cs | 19 +- .../NUnit/NUnitConsoleCommandLineTests.cs | 8 +- .../Test/TestRunner/TestResultsReaderTests.cs | 93 +++++---- .../TestRunner/ITestResultsMonitor.cs | 20 -- .../TestRunner/TestDebuggerBase.cs | 24 ++- .../TestRunner/TestProcessRunnerBase.cs | 28 +-- .../TestProcessRunnerBaseContext.cs | 12 +- .../TestRunner/TestResultsMonitor.cs | 178 ------------------ .../TestRunner/TestResultsReader.cs | 122 +++++++++--- .../UnitTesting/TestRunner/TestRunnerBase.cs | 11 +- .../Analysis/UnitTesting/UnitTesting.csproj | 4 +- .../Base/Project/Src/Util/ProcessRunner.cs | 23 +-- src/Tools/NUnit/buildnunitconsole.bat | 2 +- src/Tools/NUnit/nunit-console-dotnet2-x86.exe | Bin 32768 -> 32768 bytes src/Tools/NUnit/nunit-console-dotnet2.exe | Bin 32768 -> 32768 bytes src/Tools/NUnit/nunit-console-x86.exe | Bin 32768 -> 32768 bytes src/Tools/NUnit/nunit-console.exe | Bin 32768 -> 32768 bytes .../nunit-console/ExtendedConsoleOptions.cs | 8 +- .../NUnit/nunit-console/ExtendedConsoleUi.cs | 9 +- .../NUnit/nunit-console/nunit-console.csproj | 8 +- 24 files changed, 268 insertions(+), 331 deletions(-) delete mode 100644 src/AddIns/Analysis/UnitTesting/TestRunner/ITestResultsMonitor.cs delete mode 100644 src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsMonitor.cs diff --git a/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestProcessRunner.cs b/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestProcessRunner.cs index 9706138701..10a47ab395 100644 --- a/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestProcessRunner.cs +++ b/src/AddIns/Analysis/UnitTesting/Interfaces/IUnitTestProcessRunner.cs @@ -7,7 +7,7 @@ using ICSharpCode.SharpDevelop.Util; namespace ICSharpCode.UnitTesting { - public interface IUnitTestProcessRunner + public interface IUnitTestProcessRunner : IDisposable { bool LogStandardOutputAndError { get; set; } string WorkingDirectory { get; set; } diff --git a/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestProcessRunner.cs b/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestProcessRunner.cs index 3d60a93130..3467ecd5d8 100644 --- a/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestProcessRunner.cs +++ b/src/AddIns/Analysis/UnitTesting/Interfaces/UnitTestProcessRunner.cs @@ -54,5 +54,10 @@ namespace ICSharpCode.UnitTesting { runner.Kill(); } + + public void Dispose() + { + runner.Dispose(); + } } } diff --git a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitConsoleApplication.cs b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitConsoleApplication.cs index 5ae1495847..e9b3a3fc19 100644 --- a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitConsoleApplication.cs +++ b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitConsoleApplication.cs @@ -141,9 +141,9 @@ namespace ICSharpCode.UnitTesting public string Test; /// - /// File to write test results to. + /// Pipe to write test results to. /// - public string Results; + public string ResultsPipe; /// /// The namespace that tests need to be a part of if they are to @@ -206,9 +206,9 @@ namespace ICSharpCode.UnitTesting b.Append(XmlOutputFile); b.Append('"'); } - if (Results != null) { - b.Append(" /results=\""); - b.Append(Results); + if (ResultsPipe != null) { + b.Append(" /pipe=\""); + b.Append(ResultsPipe); b.Append('"'); } string run = null; diff --git a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestDebugger.cs b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestDebugger.cs index d0886ce178..f94a4e8667 100644 --- a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestDebugger.cs +++ b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestDebugger.cs @@ -18,16 +18,16 @@ namespace ICSharpCode.UnitTesting public NUnitTestDebugger() : this(new UnitTestDebuggerService(), SD.MessageService, - new TestResultsMonitor(), + new TestResultsReader(), UnitTestingOptions.Instance.Clone()) { } public NUnitTestDebugger(IUnitTestDebuggerService debuggerService, IMessageService messageService, - ITestResultsMonitor testResultsMonitor, + ITestResultsReader testResultsReader, UnitTestingOptions options) - : base(debuggerService, messageService, testResultsMonitor) + : base(debuggerService, messageService, testResultsReader) { this.options = options; } @@ -35,7 +35,7 @@ namespace ICSharpCode.UnitTesting protected override ProcessStartInfo GetProcessStartInfo(IEnumerable selectedTests) { NUnitConsoleApplication app = new NUnitConsoleApplication(selectedTests, options); - app.Results = base.TestResultsMonitor.FileName; + app.ResultsPipe = base.TestResultsReader.PipeName; return app.GetProcessStartInfo(); } @@ -43,5 +43,10 @@ namespace ICSharpCode.UnitTesting { return new NUnitTestResult(testResult); } + + public override int GetExpectedNumberOfTestResults(IEnumerable selectedTests) + { + return NUnitTestRunner.GetNumberOfTestMethods(selectedTests); + } } } diff --git a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestRunner.cs b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestRunner.cs index cecc5eb4e4..171de60d4e 100644 --- a/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestRunner.cs +++ b/src/AddIns/Analysis/UnitTesting/NUnit/NUnitTestRunner.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.UnitTesting protected override ProcessStartInfo GetProcessStartInfo(IEnumerable selectedTests) { NUnitConsoleApplication app = new NUnitConsoleApplication(selectedTests, options); - app.Results = base.TestResultsMonitor.FileName; + app.ResultsPipe = base.TestResultsReader.PipeName; return app.GetProcessStartInfo(); } @@ -38,5 +38,22 @@ namespace ICSharpCode.UnitTesting { return new NUnitTestResult(testResult); } + + public override int GetExpectedNumberOfTestResults(IEnumerable selectedTests) + { + return GetNumberOfTestMethods(selectedTests); + } + + public static int GetNumberOfTestMethods(IEnumerable selectedTests) + { + int count = 0; + foreach (ITest test in selectedTests) { + if (test is NUnitTestMethod) + count++; + else + count += GetNumberOfTestMethods(test.NestedTests); + } + return count; + } } } diff --git a/src/AddIns/Analysis/UnitTesting/Test/NUnit/NUnitConsoleCommandLineTests.cs b/src/AddIns/Analysis/UnitTesting/Test/NUnit/NUnitConsoleCommandLineTests.cs index 9ea19fbeb0..b90bd4d3f9 100644 --- a/src/AddIns/Analysis/UnitTesting/Test/NUnit/NUnitConsoleCommandLineTests.cs +++ b/src/AddIns/Analysis/UnitTesting/Test/NUnit/NUnitConsoleCommandLineTests.cs @@ -38,9 +38,9 @@ namespace UnitTesting.Tests.NUnit app.NoLogo = false; app.ShadowCopy = true; app.NoXmlOutputFile = false; - app.Results = @"C:\results.txt"; + app.ResultsPipe = @"C:\results.txt"; - string expectedCommandLine = "\"C:\\Projects\\MyTests\\MyTests.dll\" /results=\"C:\\results.txt\""; + string expectedCommandLine = "\"C:\\Projects\\MyTests\\MyTests.dll\" /pipe=\"C:\\results.txt\""; Assert.AreEqual(expectedCommandLine, app.GetArguments()); } @@ -229,13 +229,13 @@ namespace UnitTesting.Tests.NUnit app.Assemblies.Add("SecondAssembly.dll"); app.NoLogo = false; app.ShadowCopy = true; - app.Results = @"C:\results.txt"; + app.ResultsPipe = @"C:\results.txt"; app.NoXmlOutputFile = false; string expectedCommandLine = "\"C:\\Projects\\MyTests\\MyTests.dll\" " + "\"SecondAssembly.dll\" " + - "/results=\"C:\\results.txt\""; + "/pipe=\"C:\\results.txt\""; Assert.AreEqual(expectedCommandLine, app.GetArguments()); } diff --git a/src/AddIns/Analysis/UnitTesting/Test/TestRunner/TestResultsReaderTests.cs b/src/AddIns/Analysis/UnitTesting/Test/TestRunner/TestResultsReaderTests.cs index ddb9204ea9..45ddb56468 100644 --- a/src/AddIns/Analysis/UnitTesting/Test/TestRunner/TestResultsReaderTests.cs +++ b/src/AddIns/Analysis/UnitTesting/Test/TestRunner/TestResultsReaderTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using ICSharpCode.UnitTesting; using NUnit.Framework; @@ -17,10 +18,12 @@ namespace UnitTesting.Tests.TestRunner string resultsText = "Name: MyTest\r\n" + "Result: Success\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(1, results.Length); + Assert.AreEqual(1, results.Count); TestResult result = results[0]; Assert.AreEqual("MyTest", result.Name); @@ -34,10 +37,12 @@ namespace UnitTesting.Tests.TestRunner string resultsText = "Name: MyTest\r\n" + "Result: Ignored\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(1, results.Length); + Assert.AreEqual(1, results.Count); TestResult result = results[0]; Assert.AreEqual("MyTest", result.Name); @@ -45,7 +50,7 @@ namespace UnitTesting.Tests.TestRunner Assert.IsFalse(result.IsSuccess); Assert.AreEqual(TestResultType.Ignored, result.ResultType); } - + /* [Test] public void OneTestPassInParts() { @@ -70,17 +75,19 @@ namespace UnitTesting.Tests.TestRunner Assert.AreEqual("MyTest", result.Name); Assert.IsTrue(result.IsSuccess); } - + */ [Test] public void OneTestFailure() { string resultsText = "Name: MyTest\r\n" + "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(1, results.Length); + Assert.AreEqual(1, results.Count); TestResult result = results[0]; Assert.AreEqual("MyTest", result.Name); @@ -97,10 +104,12 @@ namespace UnitTesting.Tests.TestRunner "Message: Should not be 0.\r\n" + "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(1, results.Length); + Assert.AreEqual(1, results.Count); TestResult result = results[0]; Assert.AreEqual("Test", result.Name); @@ -115,10 +124,12 @@ namespace UnitTesting.Tests.TestRunner "StackTrace: stack trace\r\n" + "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(1, results.Length); + Assert.AreEqual(1, results.Count); TestResult result = results[0]; Assert.AreEqual("Test", result.Name); @@ -131,10 +142,12 @@ namespace UnitTesting.Tests.TestRunner { string resultsText = "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(0, results.Length); + Assert.AreEqual(0, results.Count); } [Test] @@ -144,10 +157,12 @@ namespace UnitTesting.Tests.TestRunner "Name: Test\r\n" + "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(1, results.Length); + Assert.AreEqual(1, results.Count); TestResult result = results[0]; Assert.AreEqual("Test", result.Name); @@ -162,10 +177,12 @@ namespace UnitTesting.Tests.TestRunner " Should be 1.\r\n" + "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(1, results.Length); + Assert.AreEqual(1, results.Count); TestResult result = results[0]; Assert.AreEqual("Test", result.Name); @@ -182,10 +199,12 @@ namespace UnitTesting.Tests.TestRunner " End of message.\r\n" + "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(1, results.Length); + Assert.AreEqual(1, results.Count); TestResult result = results[0]; Assert.AreEqual("Test", result.Name); @@ -201,10 +220,12 @@ namespace UnitTesting.Tests.TestRunner "Name: MyTest2\r\n" + "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(2, results.Length); + Assert.AreEqual(2, results.Count); TestResult result1 = results[0]; Assert.AreEqual("MyTest1", result1.Name); @@ -228,10 +249,12 @@ namespace UnitTesting.Tests.TestRunner " ThirdLine\r\n" + "Result: Failure\r\n"; - TestResultsReader reader = new TestResultsReader(); - TestResult[] results = reader.Read(resultsText); + TestResultsReader reader = new TestResultsReader(new StringReader(resultsText)); + List results = new List(); + reader.TestFinished += (sender, e) => results.Add(e.Result); + reader.Run(); - Assert.AreEqual(2, results.Length); + Assert.AreEqual(2, results.Count); TestResult result1 = results[0]; Assert.AreEqual("MyTest1", result1.Name); diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/ITestResultsMonitor.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/ITestResultsMonitor.cs deleted file mode 100644 index 6a67c16e74..0000000000 --- a/src/AddIns/Analysis/UnitTesting/TestRunner/ITestResultsMonitor.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.UnitTesting -{ - public interface ITestResultsMonitor : IDisposable - { - event EventHandler TestFinished; - - string FileName { get; set; } - - void Stop(); - void Start(); - void Read(); - - long InitialFilePosition { get; set; } - } -} diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestDebuggerBase.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestDebuggerBase.cs index 865aeabfeb..acb320b8b1 100644 --- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestDebuggerBase.cs +++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestDebuggerBase.cs @@ -16,29 +16,29 @@ namespace ICSharpCode.UnitTesting IUnitTestDebuggerService debuggerService; IMessageService messageService; IDebugger debugger; - ITestResultsMonitor testResultsMonitor; + ITestResultsReader testResultsReader; public TestDebuggerBase() : this(new UnitTestDebuggerService(), SD.MessageService, - new TestResultsMonitor()) + new TestResultsReader()) { } public TestDebuggerBase(IUnitTestDebuggerService debuggerService, IMessageService messageService, - ITestResultsMonitor testResultsMonitor) + ITestResultsReader testResultsReader) { this.debuggerService = debuggerService; this.messageService = messageService; - this.testResultsMonitor = testResultsMonitor; + this.testResultsReader = testResultsReader; this.debugger = debuggerService.CurrentDebugger; - testResultsMonitor.TestFinished += OnTestFinished; + testResultsReader.TestFinished += OnTestFinished; } - protected ITestResultsMonitor TestResultsMonitor { - get { return testResultsMonitor; } + protected ITestResultsReader TestResultsReader { + get { return testResultsReader; } } public override void Start(IEnumerable selectedTests) @@ -67,7 +67,7 @@ namespace ICSharpCode.UnitTesting void Start(ProcessStartInfo startInfo) { - testResultsMonitor.Start(); + testResultsReader.Start(); StartDebugger(startInfo); } @@ -90,6 +90,7 @@ namespace ICSharpCode.UnitTesting void DebugStopped(object source, EventArgs e) { debugger.DebugStopped -= DebugStopped; + testResultsReader.Join(); OnAllTestsFinished(source, e); } @@ -98,15 +99,12 @@ namespace ICSharpCode.UnitTesting if (debugger.IsDebugging) { debugger.Stop(); } - - testResultsMonitor.Stop(); - testResultsMonitor.Read(); } public override void Dispose() { - Stop(); - testResultsMonitor.Dispose(); + testResultsReader.Dispose(); + testResultsReader.TestFinished -= OnTestFinished; } } } diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBase.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBase.cs index 9595482b47..c76080b0c6 100644 --- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBase.cs +++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBase.cs @@ -11,17 +11,17 @@ using ICSharpCode.SharpDevelop.Util; namespace ICSharpCode.UnitTesting { - public class TestProcessRunnerBase : TestRunnerBase + public abstract class TestProcessRunnerBase : TestRunnerBase { IUnitTestProcessRunner processRunner; - ITestResultsMonitor testResultsMonitor; + ITestResultsReader testResultsReader; IFileSystem fileSystem; IMessageService messageService; public TestProcessRunnerBase(TestProcessRunnerBaseContext context) { this.processRunner = context.TestProcessRunner; - this.testResultsMonitor = context.TestResultsMonitor; + this.testResultsReader = context.TestResultsReader; this.fileSystem = context.FileSystem; this.messageService = context.MessageService; @@ -29,11 +29,11 @@ namespace ICSharpCode.UnitTesting processRunner.OutputLineReceived += OutputLineReceived; processRunner.ErrorLineReceived += OutputLineReceived; processRunner.ProcessExited += OnAllTestsFinished; - testResultsMonitor.TestFinished += OnTestFinished; + testResultsReader.TestFinished += OnTestFinished; } - protected ITestResultsMonitor TestResultsMonitor { - get { return testResultsMonitor; } + protected ITestResultsReader TestResultsReader { + get { return testResultsReader; } } protected IUnitTestProcessRunner ProcessRunner { @@ -56,7 +56,7 @@ namespace ICSharpCode.UnitTesting LogCommandLine(processStartInfo); if (ApplicationFileNameExists(processStartInfo.FileName)) { - testResultsMonitor.Start(); + testResultsReader.Start(); processRunner.WorkingDirectory = processStartInfo.WorkingDirectory; processRunner.Start(processStartInfo.FileName, processStartInfo.Arguments); } else { @@ -75,17 +75,23 @@ namespace ICSharpCode.UnitTesting messageService.ShowErrorFormatted(resourceString, fileName); } + protected override void OnAllTestsFinished(object source, EventArgs e) + { + testResultsReader.Join(); + base.OnAllTestsFinished(source, e); + } + public override void Stop() { + SD.Log.Info("Killing unit test runner"); processRunner.Kill(); - testResultsMonitor.Stop(); - testResultsMonitor.Read(); } public override void Dispose() { - testResultsMonitor.Dispose(); - testResultsMonitor.TestFinished -= OnTestFinished; + processRunner.Dispose(); + testResultsReader.Dispose(); + testResultsReader.TestFinished -= OnTestFinished; processRunner.ErrorLineReceived -= OutputLineReceived; processRunner.OutputLineReceived -= OutputLineReceived; } diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBaseContext.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBaseContext.cs index 56f2e6c38d..2a8288b55e 100644 --- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBaseContext.cs +++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestProcessRunnerBaseContext.cs @@ -11,25 +11,25 @@ namespace ICSharpCode.UnitTesting public class TestProcessRunnerBaseContext { IUnitTestProcessRunner processRunner; - ITestResultsMonitor testResultsMonitor; + ITestResultsReader testResultsReader; IFileSystem fileSystem; IMessageService messageService; public TestProcessRunnerBaseContext() : this(new UnitTestProcessRunner(), - new TestResultsMonitor(), + new TestResultsReader(), new UnitTestFileService(), SD.MessageService) { } public TestProcessRunnerBaseContext(IUnitTestProcessRunner processRunner, - ITestResultsMonitor testResultsMonitor, + ITestResultsReader testResultsMonitor, IFileSystem fileSystem, IMessageService messageService) { this.processRunner = processRunner; - this.testResultsMonitor = testResultsMonitor; + this.testResultsReader = testResultsMonitor; this.fileSystem = fileSystem; this.messageService = messageService; } @@ -38,8 +38,8 @@ namespace ICSharpCode.UnitTesting get { return processRunner; } } - public ITestResultsMonitor TestResultsMonitor { - get { return testResultsMonitor; } + public ITestResultsReader TestResultsReader { + get { return testResultsReader; } } public IFileSystem FileSystem { diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsMonitor.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsMonitor.cs deleted file mode 100644 index 297dc87fb5..0000000000 --- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsMonitor.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.IO; -using System.Text; - -namespace ICSharpCode.UnitTesting -{ - /// - /// Watches for new test results as they occur. Test results - /// are written to a file and read in by this class. - /// - public class TestResultsMonitor : ITestResultsMonitor - { - FileInfo fileInfo; - TestResultsReader testResultsReader; - FileSystemWatcher fileSystemWatcher; - - long initialFilePosition = 3; - long filePosition; - - const int BytesBufferLength = 1024; - byte[] bytes = new byte[BytesBufferLength]; - - /// - /// Raised when a single test has been completed. - /// - public event EventHandler TestFinished; - - public TestResultsMonitor(string fileName) - { - fileInfo = new FileInfo(fileName); - ResetFilePosition(); - } - - public TestResultsMonitor() - : this(Path.GetTempFileName()) - { - ResetFilePosition(); - } - - public long InitialFilePosition { - get { return initialFilePosition; } - set { initialFilePosition = value; } - } - - /// - /// Gets or sets the test results filename. - /// - public string FileName { - get { return fileInfo.FullName; } - set { fileInfo = new FileInfo(value); } - } - - /// - /// Starts monitoring for test results. - /// - public void Start() - { - testResultsReader = new TestResultsReader(); - ResetFilePosition(); - - string filter = fileInfo.Name; - fileSystemWatcher = new FileSystemWatcher(fileInfo.DirectoryName, filter); - - if (File.Exists(fileInfo.FullName)) { - fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; - fileSystemWatcher.Changed += FileChanged; - } else { - fileSystemWatcher.Created += FileCreated; - } - fileSystemWatcher.Error += FileSystemWatcherError; - fileSystemWatcher.EnableRaisingEvents = true; - } - - /// - /// Stops monitoring. - /// - public void Stop() - { - if (fileSystemWatcher != null) { - fileSystemWatcher.Dispose(); - fileSystemWatcher = null; - } - } - - /// - /// Reads the rest of the file from the current position. - /// Raises the TestFinished event for each test result - /// still in the file. - /// - public void Read() - { - string text = ReadTextAdded(); - if (text != null) { - TestResult[] results = testResultsReader.Read(text); - OnTestResultsReceived(results); - } - } - - /// - /// Stops monitoring and releases any resources used - /// by the TestResultsMonitor. - /// - public void Dispose() - { - Stop(); - - try { - File.Delete(FileName); - } catch { } - } - - void FileCreated(object source, FileSystemEventArgs e) - { - fileSystemWatcher.Created -= FileCreated; - fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; - fileSystemWatcher.Changed += FileChanged; - } - - void FileChanged(object source, FileSystemEventArgs e) - { - Read(); - } - - void OnTestResultsReceived(TestResult[] results) - { - if ((results.Length > 0) && (TestFinished != null)) { - foreach (TestResult result in results) { - TestFinished(this, new TestFinishedEventArgs(result)); - } - } - } - - /// - /// Reads the text added to the end of the file from the last - /// position we read from. - /// - string ReadTextAdded() - { - StringBuilder text = null; - try { - using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { - if (fs.Length > 0) { - text = new StringBuilder(); - int bytesRead = 0; - fs.Seek(filePosition, SeekOrigin.Begin); - do { - bytesRead = fs.Read(bytes, 0, BytesBufferLength); - if (bytesRead > 0) { - filePosition += bytesRead; - text.Append(UTF8Encoding.UTF8.GetString(bytes, 0, bytesRead)); - } - } while ((bytesRead > 0) && (filePosition < fs.Length)); - } - } - } catch (FileNotFoundException) { - // Test was aborted before it even started execution - return null; - } - if (text != null) { - return text.ToString(); - } - return null; - } - - void FileSystemWatcherError(object source, ErrorEventArgs e) - { - Console.WriteLine(e.GetException().ToString()); - } - - void ResetFilePosition() - { - filePosition = initialFilePosition; - } - } -} diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsReader.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsReader.cs index 35b13b7ee7..c3bffa260d 100644 --- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsReader.cs +++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestResultsReader.cs @@ -2,52 +2,118 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; -using System.Collections.Generic; +using System.IO; +using System.IO.Pipes; using System.Text; +using System.Threading; +using System.Threading.Tasks; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; namespace ICSharpCode.UnitTesting { - /// - /// Reads the test results file produced by the custom - /// nunit-console application. - /// - public class TestResultsReader + public interface ITestResultsReader : IDisposable { - StringBuilder nameBuilder = new StringBuilder(); - StringBuilder valueBuilder = new StringBuilder(); - bool firstNameChar = true; - TestResult result; + event EventHandler TestFinished; + string PipeName { get; } + void Start(); + void Join(); + } + + public class TestResultsReader : ITestResultsReader + { + TextReader reader; + readonly NamedPipeServerStream namedPipe; + readonly string pipeName; + TaskCompletionSource tcs = new TaskCompletionSource(); - enum State { - WaitingForEndOfName = 0, - WaitingForStartOfValue = 1, - WaitingForEndOfValue = 2 + public TestResultsReader() + { + pipeName = Guid.NewGuid().ToString(); + namedPipe = new NamedPipeServerStream(this.PipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte); } - State state = State.WaitingForEndOfName; + /// + /// Creates a new TestResultsReader that reads from an existing text reader. + /// + public TestResultsReader(TextReader reader) + { + this.reader = reader; + } - public TestResultsReader() + public string PipeName { + get { return pipeName; } + } + + public void Dispose() + { + reader.Dispose(); + namedPipe.Dispose(); + } + + public event EventHandler TestFinished; + + Thread thread; + + /// + /// Runs the pipe reader on a background thread. + /// The returned task will be signalled as completed when the worker process closes the pipe, after + /// all contents have been read from the pipe. + /// + public void Start() { + thread = new Thread(Run); + thread.Name = "UnitTesting Pipe Reader"; + thread.Start(); + } + + public void Join() + { + SD.Log.Debug("Waiting for pipe reader to finish"); + thread.Join(); + SD.Log.Debug("Pipe reader has finished"); } /// - /// Returns any TestResults that are in the text. + /// Run the pipe reader on the current thread. + /// This method blocks until the worker process closes the pipe. /// - /// The text read in from the - /// TestResults file. - public TestResult[] Read(string text) + public void Run() { - List results = new List(); - foreach (char ch in text) { - if (ReadNameValuePair(ch)) { - if (ReadTestResult()) { - results.Add(result); + if (reader == null) { + SD.Log.Debug("Waiting for connection to pipe"); + namedPipe.WaitForConnection(); + SD.Log.Debug("Start reading pipe"); + reader = new StreamReader(namedPipe); + } + char[] buffer = new char[1024]; + int read; + while ((read = reader.Read(buffer, 0, buffer.Length)) != 0) { + for (int i = 0; i < read; i++) { + if (ReadNameValuePair(buffer[i])) { + if (ReadTestResult()) { + if (TestFinished != null) + TestFinished(this, new TestFinishedEventArgs(result)); + } } } } - return results.ToArray(); + SD.Log.Debug("End of pipe"); + } + + StringBuilder nameBuilder = new StringBuilder(); + StringBuilder valueBuilder = new StringBuilder(); + bool firstNameChar = true; + TestResult result; + + enum State { + WaitingForEndOfName = 0, + WaitingForStartOfValue = 1, + WaitingForEndOfValue = 2 } + State state = State.WaitingForEndOfName; + /// /// Reads a name-value pair of the form: /// @@ -119,8 +185,8 @@ namespace ICSharpCode.UnitTesting /// True if a TestResult is ready to be returned /// to the caller. /// - /// The first name-value pair for a test result is the - /// test name. The last name-value pair is the result of + /// The first name-value pair for a test result is the + /// test name. The last name-value pair is the result of /// the test (Success, Failure or Ignored). bool ReadTestResult() { diff --git a/src/AddIns/Analysis/UnitTesting/TestRunner/TestRunnerBase.cs b/src/AddIns/Analysis/UnitTesting/TestRunner/TestRunnerBase.cs index 2a4352d5c6..4923c61e42 100644 --- a/src/AddIns/Analysis/UnitTesting/TestRunner/TestRunnerBase.cs +++ b/src/AddIns/Analysis/UnitTesting/TestRunner/TestRunnerBase.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -11,12 +12,17 @@ namespace ICSharpCode.UnitTesting { public abstract class TestRunnerBase : ITestRunner { + IProgress progress; + double progressPerTest; + int testsFinished; TaskCompletionSource tcs; CancellationTokenRegistration cancellationTokenRegistration; bool wasCancelled; public Task RunAsync(IEnumerable selectedTests, IProgress progress, CancellationToken cancellationToken) { + this.progress = progress; + progressPerTest = 1.0 / GetExpectedNumberOfTestResults(selectedTests); tcs = new TaskCompletionSource(); Start(selectedTests); cancellationTokenRegistration = cancellationToken.Register(Cancel, true); @@ -45,7 +51,7 @@ namespace ICSharpCode.UnitTesting return String.Format("\"{0}\" {1}", startInfo.FileName, startInfo.Arguments); } - protected void OnAllTestsFinished(object source, EventArgs e) + protected virtual void OnAllTestsFinished(object source, EventArgs e) { cancellationTokenRegistration.Dispose(); if (wasCancelled) @@ -62,6 +68,8 @@ namespace ICSharpCode.UnitTesting TestResult testResult = CreateTestResultForTestFramework(e.Result); TestFinished(source, new TestFinishedEventArgs(testResult)); } + if (!double.IsInfinity(progressPerTest)) + progress.Report(progressPerTest * Interlocked.Increment(ref testsFinished)); } protected virtual TestResult CreateTestResultForTestFramework(TestResult testResult) @@ -78,6 +86,7 @@ namespace ICSharpCode.UnitTesting } } + public abstract int GetExpectedNumberOfTestResults(IEnumerable selectedTests); public abstract void Dispose(); public abstract void Stop(); public abstract void Start(IEnumerable selectedTests); diff --git a/src/AddIns/Analysis/UnitTesting/UnitTesting.csproj b/src/AddIns/Analysis/UnitTesting/UnitTesting.csproj index 689f7266f0..a94333e6f4 100644 --- a/src/AddIns/Analysis/UnitTesting/UnitTesting.csproj +++ b/src/AddIns/Analysis/UnitTesting/UnitTesting.csproj @@ -107,17 +107,15 @@ - + - - diff --git a/src/Main/Base/Project/Src/Util/ProcessRunner.cs b/src/Main/Base/Project/Src/Util/ProcessRunner.cs index 31d90542ad..e2c0fda14a 100644 --- a/src/Main/Base/Project/Src/Util/ProcessRunner.cs +++ b/src/Main/Base/Project/Src/Util/ProcessRunner.cs @@ -26,7 +26,7 @@ namespace ICSharpCode.SharpDevelop.Util Process process; StringBuilder standardOutput = new StringBuilder(); StringBuilder standardError = new StringBuilder(); - ManualResetEvent endOfOutput = new ManualResetEvent(false); + ManualResetEventSlim endOfOutput = new ManualResetEventSlim(false); int outputStreamsFinished; /// @@ -91,7 +91,7 @@ namespace ICSharpCode.SharpDevelop.Util public void Dispose() { process.Dispose(); - endOfOutput.Close(); + endOfOutput.Dispose(); } /// @@ -130,7 +130,7 @@ namespace ICSharpCode.SharpDevelop.Util bool exited = process.WaitForExit(timeout); if (exited) { - endOfOutput.WaitOne(timeout == int.MaxValue ? Timeout.Infinite : timeout, false); + endOfOutput.Wait(timeout == int.MaxValue ? Timeout.Infinite : timeout); } return exited; @@ -216,14 +216,15 @@ namespace ICSharpCode.SharpDevelop.Util { if (process != null) { if (!process.HasExited) { - process.Kill(); - process.Close(); - process.Dispose(); - process = null; - endOfOutput.WaitOne(); - } else { - process = null; + try { + process.Kill(); + } catch (InvalidOperationException) { + // race condition (if the process has already exited) + } + // don't call process.Dispose() here - that causes the OnProcessExited + // event not to fire correctly } + endOfOutput.Wait(); } } @@ -234,7 +235,7 @@ namespace ICSharpCode.SharpDevelop.Util { if (ProcessExited != null) { if (endOfOutput != null) { - endOfOutput.WaitOne(); + endOfOutput.Wait(); } ProcessExited(this, e); diff --git a/src/Tools/NUnit/buildnunitconsole.bat b/src/Tools/NUnit/buildnunitconsole.bat index 313b203d35..7ab9fe4557 100644 --- a/src/Tools/NUnit/buildnunitconsole.bat +++ b/src/Tools/NUnit/buildnunitconsole.bat @@ -1,6 +1,6 @@ %windir%\microsoft.net\framework\v4.0.30319\msbuild /Target:Rebuild /property:Configuration=Release nunit-console\nunit-console.sln copy nunit-console.exe nunit-console-x86.exe -corflags /32bit+ nunit-console-x86.exe +"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\corflags" /32bit+ nunit-console-x86.exe @IF %ERRORLEVEL% NEQ 0 GOTO err copy nunit-console.exe nunit-console-dotnet2.exe copy nunit-console-x86.exe nunit-console-dotnet2-x86.exe diff --git a/src/Tools/NUnit/nunit-console-dotnet2-x86.exe b/src/Tools/NUnit/nunit-console-dotnet2-x86.exe index 00416949ecb85df4b4b8431ec00f9abfe21d8b68..499ed1807ccdd5497f684767484c7cf0da893be7 100755 GIT binary patch delta 8671 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 delta 8514 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 KUn4^;#{U9rQsD0Z diff --git a/src/Tools/NUnit/nunit-console-dotnet2.exe b/src/Tools/NUnit/nunit-console-dotnet2.exe index 468fa7ec48edde95333d1b45ab41ed0828fc1c66..c564243903d3d3a3cc115570ee2581ccfaff1278 100755 GIT binary patch delta 8671 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 delta 8514 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 JYhlVErqFL_3`|~ zXviHi8FS3C7AKWqjoHVENKGQkt{lHR219co^%m>>Qk8CCjo~IRL<3F$B&JzooPZ0* zR&xRb;#r9*Kx&ELA|^q)&45illruW=^`D|Zs%AP`+U80HH?=?+wbSEx2&tLzSrEx( zAb3&;kSJqGd#YbLWO1UEVFJK2OH2eAt&K(NP=Z>gZhJKBgq*O8J+_>>vd(CoQ|Hv) z);-~OPAF=tnMsf*)805N#LCp;2$A*V!(*_08i&S;I*#L_xK=dMRO3Wq?iA1?>sw5O zi+JG%^-iSu=+S`VBy~)g3bWU|*wa8JuTV2Q4vW3Wlcc9p7E3!D%4jt80@87!?m6I2 zr{mb}x$Hx8qEWl4y8Kq;Bch|6Q8CBf?TjjOqQLZd>;X%ifpO|hIK&<~EMm%&AYw6K zx{c?I$fizl*b)CS>Q2xQKOS3EXnnpp%%Gmge$_EqVP-WG;gV|bFL zl2kwZMyr(!Jo%jJL^-tS3P7~Rsc|aZ4v;vEH7HL_@i2M|DXyZkm|`c&k`21Jbz0JP zf-a(HgXOA-j)aQ8V57|+ERz{r0r--y~`Yv~q@GcfWW%YTew z`Y}F(akzbzLSyJXI5Du2K}B@DkB(uhFwu$mV}TJt)m>6J9xF9Eu`Z{?U0V1!R-Rn~ zX2MIVdl|;${KPWW`C{AM&w_}en9F%Y6HlV~pp~y+z2;ty!TlV7nUxp=7(b8EKd4*< zCfL;A_-^Yin`pDkG*)d{<^HC~2*;Q1Vn!>=x>tax@T-|CF(!3y^doQ*yn7WuJN;2G zWXE;8PfNMW>#{>jshLFlI;c~)-#w<3>17i`i8YWV)&ktCPfy;fP!`>G9VD@jMc)Ou zTf==H!tqcu>;HxJeW`V!?VI_DiH=G=-l-byt{GDAfS-<}W-~qTP~K8iOna6zVp-p; zA+L?m@d|%)`P=KHuYuCi(kTq-G(bu80yWur@I~Q$e+agGhEl8GuIg5t0%2(}#oYiy zneA?^Op$joTV%@>c`=Jzh2ma&+O$$}zrY-tf!M7jt^=LYeAH7Z9s6}S=1b_!)!~@$ zZIOfDji)*Iz5X=Ep0bv_(~Z|Fu^V+How^Q=@9o$V&xcs^FH$`>#(>YMRxHiI4G#OBL z^AI(^bu^)Gz$Z)ujHG6GcXwEn!bO#1vb%@nYMz-ZdQdS}nc&%unxfLZd)~QD_7e-mQ#f=dr5NTX%CrbvJ|WL$?+3JT%p&_9IEJ3VrC~VwgqZi?Fp) zhhdK>Z5UiIk9@YI4n_|s8 z4w+iX#$o}HCTkK~8Cn5N{-R_XOC}Uvu4LT(^vHg2%EuZyyq5kdXtw}h?>yDLqp&|- z+JWj=sSgLYw9G0h?}RweRA;z35WR7f(4WFrtw$SO*6E#cJ#iOQhIejWIqDel+yqVj zz)meRRX2&vg(cM;tEORA;%hKfGU)EU)Vbi53>vymR$F!NhR(f*VLL!>kGliZ7;l1C zdRaC1>uhx|gESZ{Um;u*_j6f2gZm1fuBmI-2|l$5!BY4t^(4LlHdsud4+1l>OZq8f zYo=@4+2U)3{WasJa}GB~xwM%eP*yY%C;$2SDQOT&}}{#Z5C(1A}zYJ)XEp!n6NQKDwbYFqO{Or%;DmA0ykaNzKo1Sxjj2siWqncw&3B|` zXom(TL331Uywd|uas!8{ZIc)LZPv8o#H7vzpLo~{iP=MGHR2ubUFW$}ah3e&(}Os90uJL1A`;&L)#50S7v8QNH&ecBxrFXsz?f7goO^pAcd}R()q9Ha;`!R}CuADN zfNY@OEi9|6D&NOG_?6SBWI|ZJ>UxsGZFTiodGlM@;(LH$tq)wXL&=~C`BFbcXsIvq zN9DR@C#dFzI5fYg|C`jy%P+6`nMUXjveP-RMu+yL0#?yIGy@zrT=bJ1Qpkm+urQoa zN5RX`{XPtvHQ9C=m0`E#G04N@eLj^yEZ8*BFy&7XzaI5DzL8do0Sva3H`!Whc9tXj z08_>^8EDRrGi8=_22Dc-m~e3DgIhITrOWZk!o6^mH0rBa=_g?B*Heq&B-XbKd+7cM zk_VUyXqg{_PU_wmNZkS>Bk>c+HpO_+-{;6r@)t_W{1n(+!oQp~E%Ovl3ux|sHa!4n z)H46Zva`I2@5qS|B%TJOrulK^CV(p1x(C^|%KM$U9!j}!XSj2J29xGa&3%S1hWtuK z&8BL{Jl*_)-u&-kzA3Lhl=6f5+oPq9DLWs2Yh!ti<$W}Z0sbAH8xubV>h7~ZNv59z zHH`hmX_nWYe*QGi>eZ|MEdl;hTI>(pz zB@^YTe_}1*MuXeLX-19L3;f)|Y`L-@VP$@AWkXN-!n0?^m%IpLufo5Q(~h=B^;9AN zZ@PE+q|28)U9*;X8C0^Af38`n%U~uqAn|LkW4s-_gN08P&K{i~0BTfH^1e@_xWuUvJ0)Ht@fL{>NZc>+h{V51oT8O$ z8g)wCrfr3{-B~$2t@R=NOA_CbsOqd9tM@52v|eAK*U(K8zY5god-{XGgV1X93%x7V+WNLn=*L%;}KY}_d#v=V634N|^C;u8{IF%B9Qy>Db&5N3qQj_M?yXKuyhWhPI% z&184m&4Y$bk4StPk_dg-%3Be7(c%EFO8iJ-v;R(^(Pn>xT1k)jdF~(lFZeYY72w58 zm$)F%7SL#IfETba(3e#rv?ajPo`>2dJ;+5K7vznY4zy_vBoR6gX=&T}}qy9-CgX0nTvC<$6A z@fwMnB;KT40{Jdw4)9@#k4yYOSpbPpJAjrN16E3Urn(d#{TqD!G_MxNnYNVA5*5&P zdK_IUs=*x_!@4|OF6!~{e?EccOw>=;<2|g>2MJd8(>^gCzxf^+%Uqrgiplu>@qCdx z4o;)%_#FV<2jFzNyU4|q$z+hx{XM?K%hxl8J8Or(i z*NEhhayhuCJkID;&!-R__BdLjR)D)0ca`W5;(E0k+$BZsW_2`Z}}Vo`Y$OUK-C_p8l?8sEi1&57wDJmnvvck&F8_ z<4|mu+%weR+e%gR4aw!H%{Lj`=g_aXqVs)y6sKd7yNhzZJE@xbCb2HtPdEE^;2ZI+ z$;^7YRzv-g^U8*%g`K+z?}9VY}tJ3l~jip!gKT(_by?zq-URM7nEfuxKe`E3_Lx`o~JVO^NF}Z@e#g`0QTqEu> zV!&NS9QbXc0!i#MV$?>Hj8P&lZr2iGo3wZ6ZOD()yT(E3ty%O7#hd`GVIoBem@&FX zrn^fd%_-tIO)|4*i#_5}lbtSvdY@G96YI@3VbVqz<;7<6d^!O6MZ%$P!sc1fbHxET zohzOdKQN!8Ys5=thiIeUz)u?;1)iYao6W)$r_9wrvKS{BJ7_A+!cBC@v^qeKu-0V7 zR2pfm5v`Q8&d2GU0(9s?sa^p2RQf#7p%f$z-GSn_QO4RyN5p-Q9})Ykr^I}EPd^Bo z{g``Pykk8pP6*3?2on4wAe|J|{++<-{$Gnz;&SntI4NfPj{}$c|0uGj#5(_bVl497 ziM^R6-Uq$a{~Utd?f-AkJ2AOUJmM$CR1W$z<+%8VKLA<}L==ZA0-RQ(#EF3@=#_yA zrB&hWn+lw$v;n69?+Q%DiXRB@lD;SL>A;1GnMGMHQKr(br05M`EBz_JmH0qnG}x)M zQhjiRvQ)V!xLR4MEDml(7hV};n`?s`l;gA|n1Ri$!6~xHn?Y{}-AWGvPtaq*y>yN8 zVz3X%aXZ^6lRHj-4Gz$J%5tU^Q1A)(ILNChu{$WQ#Ox!=HkiJlb1a_Q%RfnM6Aorm7yN4YmQy+d<$KJ1XfZqF>o(SF$8nr?%6q zECS!7Ofs5r8s9Z4A>uIY2s2gPg|$u*yX0C~d!E`#Tr{RgaL zIv;_rP_LocAs4tfGzCX;lCcwYS`os@psPb`5akP@pxUZrLm7$L&FZtVAiwm=q8tj{ ztvdAE&~Ejl^5@XE)Qxm1#FyvekgQF(14qvaSI{ZtLo{lf07!&7F1!QsnPEP>bAd-h zXLyBjO8FnynCcDTy{f5xHT;+=RIc<1+#pn)=`7Vr(O8M5`ZQdh5Wf!pL~T|75+0zX zaxYIQei22;B+wzn>A?L?ntQ2D9pn5?ZBs9H-d5YyPUp{{S37@K_t13?N=;jUC+H#P zBlQGzI;wA}_yHs*m1mrCUklaK&wO|?HPK68R#A=Cf^07UT}4j;C(;{0Kh*-K)0-tN zv=F~GT4))SYCH^91^U1h6Wf&Xp6;G5 zy0WYH^2O<{c}y3_foCRZCD{wyR2MDWnC|Ub*U~<>g$>d)XXU!C)l6P+b$8eLUc9cm zR<0u!%>jBR;~rx({nalef8YbtaUxT8wVn7uCO@a*I} z$=y>}dFhOS!__6zLctx)2CcwFiqEg?nNaShT)?oquKwogP#OPB>>!jmO%V8?x0BzK?? zUtF>L0E|R+B=dTb`ZC@~GAJ;AqwMy0ti5UESAq74GX8Q`;ufFZVK<1%K?w(tQTj$8ie3@0ggK zguGQ<7&43b*h$!MXoQ3*)|8*`r4-38HVCU(?BtiDrbZmIxRg$QB~}UK>gFrB0K8;V zFW~{seF8TMM<|ltfWRBLbnA4k2F4P+Y$N%by%e{>tzy^e!AKyI?}pa4BZz-*q#4Kw z7t6y_cFBBs=OXz%MlFhp%oMptIF2l|bsc85jiTdVJgOu2b6_({Q1z_qdb`%I?pj?t zXYoL3XGj@AWUL*$_xQgpn6B-wiz(r?1D9RqD;cmq_g^7p{PY2*=P#lD@%sM)s!$d0 delta 8514 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 KUn4^;#{U9rQsD0Z diff --git a/src/Tools/NUnit/nunit-console.exe b/src/Tools/NUnit/nunit-console.exe index 468fa7ec48edde95333d1b45ab41ed0828fc1c66..c564243903d3d3a3cc115570ee2581ccfaff1278 100644 GIT binary patch delta 8671 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 delta 8514 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 JYh + + Exe NUnit.ConsoleRunner @@ -14,7 +15,7 @@ 512 4 false - v2.0 + v3.5 App.ico C:\Users\matt\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis @@ -54,6 +55,9 @@ False + + 3.5 +