diff --git a/.gitattributes b/.gitattributes
index badb96a3e..52d4937c4 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -5,7 +5,7 @@
*.ps1 text
*.yml text
-*.sln text
+*.slnx text
*.sln.DotSettings text
*.props text
@@ -14,4 +14,3 @@
*.csproj text
*.cs text diff=csharp
*.fs text
-*.nuspec text
diff --git a/.vscode/launch.json b/.vscode/launch.json
index ccf63665d..1d129f556 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,9 +10,9 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceFolder}/src/artifacts/bin/Fixie.Tests/debug_net8.0/Fixie.Tests.dll",
+ "program": "${workspaceFolder}/src/artifacts/bin/Fixie.Tests/debug/Fixie.Tests.dll",
"args": [],
- "cwd": "${workspaceFolder}/src/artifacts/bin/Fixie.Tests/debug_net8.0",
+ "cwd": "${workspaceFolder}/src/artifacts/bin/Fixie.Tests/debug",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
diff --git a/build.ps1 b/build.ps1
index 66442e9a9..be9d4f435 100644
--- a/build.ps1
+++ b/build.ps1
@@ -19,5 +19,4 @@ step { dotnet $fixie *.Tests -c Release --no-build }
if ($pack) {
step { dotnet pack src/Fixie -o packages -c Release --no-build --nologo }
step { dotnet pack src/Fixie.Console -o packages -c Release --no-build --nologo }
- step { dotnet pack src/Fixie.TestAdapter -o packages -c Release --no-build --nologo }
}
\ No newline at end of file
diff --git a/build/Fixie.props b/build/Fixie.props
index 1d320bed2..c15dae3fe 100644
--- a/build/Fixie.props
+++ b/build/Fixie.props
@@ -1,13 +1,4 @@
-
- true
- true
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/Fixie.targets b/build/Fixie.targets
index b60021b10..8578e15e9 100644
--- a/build/Fixie.targets
+++ b/build/Fixie.targets
@@ -3,7 +3,6 @@
Exe
- false
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 5fadd5eba..abbaf02ac 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -19,7 +19,7 @@
true
true
snupkg
- 4.1
+ 5.0
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index 3638c728b..db2eaebdc 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -4,7 +4,6 @@
-
diff --git a/src/Fixie.Console/Fixie.Console.csproj b/src/Fixie.Console/Fixie.Console.csproj
index e78f48987..e472485b3 100644
--- a/src/Fixie.Console/Fixie.Console.csproj
+++ b/src/Fixie.Console/Fixie.Console.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net9.0
true
fixie
`dotnet fixie` console test runner for the Fixie test framework.
diff --git a/src/Fixie.TestAdapter/DebuggerAttachmentFailure.cs b/src/Fixie.TestAdapter/DebuggerAttachmentFailure.cs
deleted file mode 100644
index 8f69dd48f..000000000
--- a/src/Fixie.TestAdapter/DebuggerAttachmentFailure.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-namespace Fixie.TestAdapter;
-
-class DebuggerAttachmentFailure
-{
- public string Message { get; }
- public Exception ThirdPartyTestHostException { get; }
-
- public DebuggerAttachmentFailure(Exception thirdPartyTestHostException)
- {
- ThirdPartyTestHostException = thirdPartyTestHostException;
- Message = UserGuidanceMessage(thirdPartyTestHostException);
- }
-
- static string UserGuidanceMessage(Exception thirdPartyTestHostException)
- {
- var host = TryGetTestHost(out var testHost)
- ? $"{Environment.NewLine}{testHost}{Environment.NewLine}"
- : "";
-
- return $@"Fixie attempted to run your test assembly
-under the active debugger session, but the
-third-party test host {host}failed to honor the request to attach to the
-test assembly process. The run continued
-without the debugger so that this message
-could be reported.
-
-
-In order to debug your test, bypass your
-test runner's unimplemented ""Debug""
-option using one of the following two
-approaches.
-
-If your operating system supports
-Debugger.Launch():
-
- 1. Add the following line at the start
- of your test:
-
- System.Diagnostics.Debugger.Launch();
-
- 2. Use your test runner's ""Run"" option
- to start the test instead of using
- its unimplemented ""Debug"" option.
-
- 3. Make a selection in the resulting
- debugger session dialog.
-
-
-If your operating system does not support
-Debugger.Launch():
-
- 1. Note that Fixie test projects are in
- fact normal console applications that
- run their own tests.
-
- 2. Instead of using your test runner,
- run your test project under your
- development environment's debugger
- as a normal console application.
-
-
-When filing a bug report to your specific
-third-party test runner's organization,
-please include the following exception
-thrown by their implementation of the VSTest
-API. Test runners are meant to implement
-IFrameworkHandle.LaunchProcessWithDebuggerAttached
-since they have control over the active
-debugger session.
-
-
-{thirdPartyTestHostException.Message}";
- }
-
- static bool TryGetTestHost([NotNullWhen(true)] out string? testHost)
- {
- try
- {
- testHost = Environment.GetCommandLineArgs().First();
- }
- catch
- {
- testHost = null;
- }
-
- return testHost != null;
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/Fixie.TestAdapter.csproj b/src/Fixie.TestAdapter/Fixie.TestAdapter.csproj
deleted file mode 100644
index f1cdc343c..000000000
--- a/src/Fixie.TestAdapter/Fixie.TestAdapter.csproj
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- $(NuspecProperties);id=$(PackageId)
- $(NuspecProperties);version=$(PackageVersion)
- $(NuspecProperties);authors=$(Authors)
- $(NuspecProperties);description=$(Description)
- $(NuspecProperties);copyright=$(Copyright)
-
-
-
-
- net8.0;net9.0
- Visual Studio integration for the Fixie test framework.
- Fixie.TestAdapter.nuspec
- true
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/Fixie.TestAdapter.nuspec b/src/Fixie.TestAdapter/Fixie.TestAdapter.nuspec
deleted file mode 100644
index 0c19b1625..000000000
--- a/src/Fixie.TestAdapter/Fixie.TestAdapter.nuspec
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- $id$
- $version$
- $authors$
- $authors$
- false
- README.md
- MIT
- https://fixie.github.io
- icon.png
- $description$
- $copyright$
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/InternalsVisibleTo.cs b/src/Fixie.TestAdapter/InternalsVisibleTo.cs
deleted file mode 100644
index f5102558f..000000000
--- a/src/Fixie.TestAdapter/InternalsVisibleTo.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-using System.Runtime.CompilerServices;
-
-[assembly:InternalsVisibleTo("Fixie.Tests")]
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/LoggingExtensions.cs b/src/Fixie.TestAdapter/LoggingExtensions.cs
deleted file mode 100644
index ca70cd3b2..000000000
--- a/src/Fixie.TestAdapter/LoggingExtensions.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using Fixie.Internal;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
-
-namespace Fixie.TestAdapter;
-
-static class LoggingExtensions
-{
- public static void Info(this IMessageLogger logger, string message)
- => logger.SendMessage(TestMessageLevel.Informational, message);
-
- public static void Error(this IMessageLogger logger, string message)
- => logger.SendMessage(TestMessageLevel.Error, message);
-
- public static void Error(this IMessageLogger logger, Exception exception)
- => logger.SendMessage(TestMessageLevel.Error, exception.ToString());
-
- public static void Version(this IMessageLogger logger)
- => logger.Info(Framework.Version);
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/RunnerException.cs b/src/Fixie.TestAdapter/RunnerException.cs
deleted file mode 100644
index df0b79f4b..000000000
--- a/src/Fixie.TestAdapter/RunnerException.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System.Text;
-using Fixie.Internal;
-
-namespace Fixie.TestAdapter;
-
-class RunnerException : Exception
-{
- public RunnerException(Exception exception)
- : base(exception.ToString())
- {
- }
-
- public RunnerException(PipeMessage.Exception exception)
- : base(new StringBuilder()
- .AppendLine()
- .AppendLine()
- .AppendLine(exception.Message)
- .AppendLine()
- .AppendLine(exception.Type)
- .AppendLine(exception.StackTrace)
- .ToString())
- {
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/SourceLocation.cs b/src/Fixie.TestAdapter/SourceLocation.cs
deleted file mode 100644
index a508be5a0..000000000
--- a/src/Fixie.TestAdapter/SourceLocation.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Fixie.TestAdapter;
-
-class SourceLocation
-{
- public SourceLocation(string codeFilePath, int lineNumber)
- {
- CodeFilePath = codeFilePath;
- LineNumber = lineNumber;
- }
-
- public string CodeFilePath { get; }
- public int LineNumber { get; }
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/TestAssembly.cs b/src/Fixie.TestAdapter/TestAssembly.cs
deleted file mode 100644
index 4253711db..000000000
--- a/src/Fixie.TestAdapter/TestAssembly.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
-
-namespace Fixie.TestAdapter;
-
-static class TestAssembly
-{
- public static bool IsTestAssembly(string assemblyPath)
- {
- string[] fixieAssemblies =
- [
- "Fixie.dll", "Fixie.TestAdapter.dll"
- ];
-
- if (fixieAssemblies.Contains(Path.GetFileName(assemblyPath)))
- return false;
-
- var folderPath = new FileInfo(assemblyPath).Directory!.FullName;
-
- return File.Exists(Path.Combine(folderPath, "Fixie.dll"));
- }
-
- public static int? TryGetExitCode(this Process? process)
- {
- if (process != null && process.WaitForExit(5000))
- return process.ExitCode;
-
- return null;
- }
-
- public static Process StartDiscovery(string assemblyPath)
- {
- return Run(assemblyPath);
- }
-
- public static Process? StartExecution(string assemblyPath, IFrameworkHandle frameworkHandle,
- out DebuggerAttachmentFailure? attachmentFailure)
- {
- attachmentFailure = null;
-
- if (Debugger.IsAttached)
- return RunAttemptingDebuggerAttachment(assemblyPath, frameworkHandle, out attachmentFailure);
-
- return Run(assemblyPath);
- }
-
- static Process Run(string assemblyPath)
- {
- return Start(new ProcessStartInfo("dotnet", [assemblyPath])
- {
- WorkingDirectory = WorkingDirectory(assemblyPath),
- UseShellExecute = false
- });
- }
-
- static Process? RunAttemptingDebuggerAttachment(string assemblyPath, IFrameworkHandle frameworkHandle,
- out DebuggerAttachmentFailure? attachmentFailure)
- {
- attachmentFailure = null;
-
- // LaunchProcessWithDebuggerAttached sends a request back
- // to the third-party test runner process which started
- // this TestAdapter's host process. That test runner
- // process does not know about environment variables
- // created so far by this TestAdapter. That test runner
- // cannot reliably resolve the meaning of bare commands
- // like `dotnet` to the full file path of the corresponding
- // executable. To ensure the test runner process can
- // successfully honor the request, we must explicitly
- // pass along new environment variables and resolve the
- // full path for the `dotnet` executable.
-
- var environmentVariables = new Dictionary
- {
- ["FIXIE_NAMED_PIPE"] = Environment.GetEnvironmentVariable("FIXIE_NAMED_PIPE")
- };
-
- var filePath = FindDotnet();
-
- try
- {
- frameworkHandle
- .LaunchProcessWithDebuggerAttached(
- filePath,
- WorkingDirectory(assemblyPath),
- Serialize([assemblyPath]),
- environmentVariables);
-
- return null;
- }
- catch (Exception thirdPartyTestHostException)
- {
- attachmentFailure = new DebuggerAttachmentFailure(thirdPartyTestHostException);
-
- frameworkHandle.Error(thirdPartyTestHostException);
-
- return Run(assemblyPath);
- }
- }
-
- static string WorkingDirectory(string assemblyPath)
- {
- return Path.GetDirectoryName(Path.GetFullPath(assemblyPath))!;
- }
-
- static Process Start(ProcessStartInfo startInfo)
- {
- var process = new Process
- {
- StartInfo = startInfo
- };
-
- if (process.Start())
- return process;
-
- throw new Exception("Failed to start process: " + startInfo.FileName);
- }
-
- static string FindDotnet()
- {
- var fileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "dotnet.exe" : "dotnet";
-
- var folderPath = Environment
- .GetEnvironmentVariable("PATH")?
- .Split(Path.PathSeparator)
- .FirstOrDefault(path => File.Exists(Path.Combine(path.Trim(), fileName)));
-
- if (folderPath == null)
- throw new Exception(
- $"Could not locate {fileName} when searching the PATH environment variable. " +
- "Verify that you have installed the .NET SDK.");
-
- return Path.Combine(folderPath.Trim(), fileName);
- }
-
- ///
- /// Serialize the given string[] to a single string, so that when used as a ProcessStartInfo.Arguments
- /// value, the process's Main method will receive the original string[].
- ///
- /// See https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
- /// See https://stackoverflow.com/a/6040946 for the regex approach used here.
- ///
- public static string Serialize(string[] arguments)
- => string.Join(" ", arguments.Select(Quote));
-
- static string Quote(string argument)
- {
- //For each substring of zero or more \ followed by "
- //replace it with twice as many \ followed by \"
- var s = Regex.Replace(argument, @"(\\*)" + '"', @"$1$1\" + '"');
-
- //When an argument ends in \ double the number of \ at the end.
- s = Regex.Replace(s, @"(\\+)$", @"$1$1");
-
- //Now that the content has been escaped, surround the value in quotes.
- return '"' + s + '"';
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/TestProcessExitException.cs b/src/Fixie.TestAdapter/TestProcessExitException.cs
deleted file mode 100644
index 80c8ca129..000000000
--- a/src/Fixie.TestAdapter/TestProcessExitException.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace Fixie.TestAdapter;
-
-public class TestProcessExitException : Exception
-{
- const int StackOverflowExitCode = -1073741571;
-
- public TestProcessExitException(int? exitCode)
- : base(GetMessage(exitCode))
- {
- }
-
- static string GetMessage(int? exitCode)
- {
- const string exitedUnexpectedly = "The test assembly process exited unexpectedly";
-
- if (exitCode != null)
- {
- var withExitCode = $"with exit code {exitCode}";
-
- return exitCode == StackOverflowExitCode
- ? $"{exitedUnexpectedly} {withExitCode}, indicating the test threw a StackOverflowException."
- : $"{exitedUnexpectedly} {withExitCode}.";
- }
-
- return $"{exitedUnexpectedly}.";
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/VsDiscoveryRecorder.cs b/src/Fixie.TestAdapter/VsDiscoveryRecorder.cs
deleted file mode 100644
index 9e97481a6..000000000
--- a/src/Fixie.TestAdapter/VsDiscoveryRecorder.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using Fixie.Internal;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
-
-namespace Fixie.TestAdapter;
-
-class VsDiscoveryRecorder
-{
- readonly IMessageLogger log;
- readonly ITestCaseDiscoverySink discoverySink;
- readonly string assemblyPath;
- readonly SourceLocationProvider sourceLocationProvider;
-
- public VsDiscoveryRecorder(IMessageLogger log, ITestCaseDiscoverySink discoverySink, string assemblyPath)
- {
- this.log = log;
- this.discoverySink = discoverySink;
- this.assemblyPath = assemblyPath;
-
- sourceLocationProvider = new SourceLocationProvider(assemblyPath);
- }
-
- public void Record(PipeMessage.TestDiscovered testDiscovered)
- {
- var test = testDiscovered.Test;
-
- SourceLocation? sourceLocation = null;
-
- try
- {
- sourceLocationProvider.TryGetSourceLocation(test, out sourceLocation);
- }
- catch (Exception exception)
- {
- log.Error(exception.ToString());
- }
-
- var discoveredTest = new TestCase(test, VsTestExecutor.Uri, assemblyPath)
- {
- DisplayName = test
- };
-
- if (sourceLocation != null)
- {
- discoveredTest.CodeFilePath = sourceLocation.CodeFilePath;
- discoveredTest.LineNumber = sourceLocation.LineNumber;
- }
-
- discoverySink.SendTestCase(discoveredTest);
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/VsExecutionRecorder.cs b/src/Fixie.TestAdapter/VsExecutionRecorder.cs
deleted file mode 100644
index c279ed7a0..000000000
--- a/src/Fixie.TestAdapter/VsExecutionRecorder.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-using Fixie.Internal;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
-using static System.Environment;
-
-namespace Fixie.TestAdapter;
-
-using TestResult = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult;
-
-class VsExecutionRecorder
-{
- readonly ITestExecutionRecorder log;
- readonly string assemblyPath;
-
- public VsExecutionRecorder(ITestExecutionRecorder log, string assemblyPath)
- {
- this.log = log;
- this.assemblyPath = assemblyPath;
- }
-
- public void Record(PipeMessage.TestStarted message)
- {
- var testCase = ToVsTestCase(message.Test);
-
- log.RecordStart(testCase);
- }
-
- public void Record(PipeMessage.TestSkipped result)
- {
- Record(result, x =>
- {
- x.Outcome = TestOutcome.Skipped;
- x.ErrorMessage = result.Reason;
- });
- }
-
- public void Record(PipeMessage.TestPassed result)
- {
- Record(result, x =>
- {
- x.Outcome = TestOutcome.Passed;
- });
- }
-
- public void Record(PipeMessage.TestFailed result)
- {
- Record(result, x =>
- {
- x.Outcome = TestOutcome.Failed;
- x.ErrorMessage = result.Reason.Message;
- x.ErrorStackTrace = result.Reason.Type +
- NewLine +
- result.Reason.StackTrace;
- });
- }
-
- void Record(PipeMessage.TestCompleted result, Action customize)
- {
- var testCase = ToVsTestCase(result.Test);
-
- var testResult = new TestResult(testCase)
- {
- DisplayName = result.TestCase,
- Duration = TimeSpan.FromMilliseconds(result.DurationInMilliseconds),
- ComputerName = MachineName
- };
-
- customize(testResult);
-
- log.RecordResult(testResult);
- }
-
- TestCase ToVsTestCase(string test)
- {
- return new TestCase(test, VsTestExecutor.Uri, assemblyPath);
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/VsTestDiscoverer.cs b/src/Fixie.TestAdapter/VsTestDiscoverer.cs
deleted file mode 100644
index 20c9d1a31..000000000
--- a/src/Fixie.TestAdapter/VsTestDiscoverer.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-using System.IO.Pipes;
-using Fixie.Internal;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
-using static Fixie.TestAdapter.TestAssembly;
-
-namespace Fixie.TestAdapter;
-
-[DefaultExecutorUri(VsTestExecutor.Id)]
-[FileExtension(".exe")]
-[FileExtension(".dll")]
-class VsTestDiscoverer : ITestDiscoverer
-{
- public void DiscoverTests(IEnumerable sources, IDiscoveryContext discoveryContext, IMessageLogger log, ITestCaseDiscoverySink discoverySink)
- {
- try
- {
- log.Version();
-
- foreach (var assemblyPath in sources)
- DiscoverTests(log, discoverySink, assemblyPath);
- }
- catch (Exception exception)
- {
- throw new RunnerException(exception);
- }
- }
-
- static void DiscoverTests(IMessageLogger log, ITestCaseDiscoverySink discoverySink, string assemblyPath)
- {
- if (!IsTestAssembly(assemblyPath))
- {
- log.Info("Skipping " + assemblyPath + " because it is not a test assembly.");
- return;
- }
-
- log.Info("Processing " + assemblyPath);
-
- var pipeName = Guid.NewGuid().ToString();
- Environment.SetEnvironmentVariable("FIXIE_NAMED_PIPE", pipeName);
-
- using (var pipeStream = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte))
- using (var pipe = new TestAdapterPipe(pipeStream))
- using (var process = StartDiscovery(assemblyPath))
- {
- pipeStream.WaitForConnection();
-
- pipe.Send();
-
- var recorder = new VsDiscoveryRecorder(log, discoverySink, assemblyPath);
-
- while (true)
- {
- var messageType = pipe.ReceiveMessageType();
-
- if (messageType == typeof(PipeMessage.TestDiscovered).FullName)
- {
- var testDiscovered = pipe.Receive();
- recorder.Record(testDiscovered);
- }
- else if (messageType == typeof(PipeMessage.Exception).FullName)
- {
- var exception = pipe.Receive();
- throw new RunnerException(exception);
- }
- else if (messageType == typeof(PipeMessage.EndOfPipe).FullName)
- {
- var endOfPipe = pipe.Receive();
- break;
- }
- else if (!string.IsNullOrEmpty(messageType))
- {
- var body = pipe.ReceiveMessageBody();
- log.Error($"The test runner received an unexpected message of type {messageType}: {body}");
- }
- else
- {
- throw new TestProcessExitException(process.TryGetExitCode());
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/VsTestExecutor.cs b/src/Fixie.TestAdapter/VsTestExecutor.cs
deleted file mode 100644
index 6fd67ba75..000000000
--- a/src/Fixie.TestAdapter/VsTestExecutor.cs
+++ /dev/null
@@ -1,213 +0,0 @@
-using System.IO.Pipes;
-using Fixie.Internal;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
-using static Fixie.TestAdapter.TestAssembly;
-
-namespace Fixie.TestAdapter;
-
-[ExtensionUri(Id)]
-public class VsTestExecutor : ITestExecutor
-{
- public const string Id = "executor://fixie.testadapter/";
- public static readonly Uri Uri = new(Id);
-
- ///
- /// This method was originally intended to be called by VsTest when running
- /// all tests. However, VsTest no longer appears to call this method, instead
- /// favoring its overload with all individual tests specified as if they were
- /// all selected by the user. The stated reason is for performance, but in
- /// fact requires far larger messages to be passed between processes and far
- /// more cross-referencing of test names within each specific test framework
- /// at execution time. This overload is maintained optimistically and for
- /// protection in the event that VsTest changes back to the more efficient
- /// approach.
- ///
- public void RunTests(IEnumerable? sources, IRunContext? runContext, IFrameworkHandle? frameworkHandle)
- {
- ArgumentNullException.ThrowIfNull(sources);
- ArgumentNullException.ThrowIfNull(frameworkHandle);
-
- try
- {
- IMessageLogger log = frameworkHandle;
-
- log.Version();
-
- HandlePoorVsTestImplementationDetails(runContext, frameworkHandle);
-
- var executeTests = new PipeMessage.ExecuteTests
- {
- Filter = []
- };
-
- foreach (var assemblyPath in sources)
- RunTests(log, frameworkHandle, assemblyPath, executeTests);
- }
- catch (Exception exception)
- {
- throw new RunnerException(exception);
- }
- }
-
- ///
- /// This method was originally intended to be called by VsTest only when running
- /// a selected subset of previously discovered tests. However, VsTest appears to
- /// call this method even in the event the user is running *all* tests, with all
- /// individual tests specified in the input as if all were individually selected
- /// by the user. The stated reason is for performance, but in fact requires far
- /// larger messages to be passed between processes and far more cross-referencing
- /// of test names within each specific test framework at execution time. Still,
- /// this overload is functionally correct even when all tests are passed to it.
- ///
- public void RunTests(IEnumerable? tests, IRunContext? runContext, IFrameworkHandle? frameworkHandle)
- {
- ArgumentNullException.ThrowIfNull(tests);
- ArgumentNullException.ThrowIfNull(frameworkHandle);
-
- try
- {
- IMessageLogger log = frameworkHandle;
-
- log.Version();
-
- HandlePoorVsTestImplementationDetails(runContext, frameworkHandle);
-
- var assemblyGroups = tests.GroupBy(tc => tc.Source);
-
- foreach (var assemblyGroup in assemblyGroups)
- {
- var assemblyPath = assemblyGroup.Key;
-
- var executeTests = new PipeMessage.ExecuteTests
- {
- Filter = assemblyGroup.Select(x => x.FullyQualifiedName).ToArray()
- };
-
- RunTests(log, frameworkHandle, assemblyPath, executeTests);
- }
- }
- catch (Exception exception)
- {
- throw new RunnerException(exception);
- }
- }
-
- public void Cancel() { }
-
- static void RunTests(IMessageLogger log, IFrameworkHandle frameworkHandle, string assemblyPath, PipeMessage.ExecuteTests executeTests)
- {
- if (!IsTestAssembly(assemblyPath))
- {
- log.Info("Skipping " + assemblyPath + " because it is not a test assembly.");
- return;
- }
-
- log.Info("Processing " + assemblyPath);
-
- var pipeName = Guid.NewGuid().ToString();
- Environment.SetEnvironmentVariable("FIXIE_NAMED_PIPE", pipeName);
-
- using (var pipeStream = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte))
- using (var pipe = new TestAdapterPipe(pipeStream))
- using (var process = StartExecution(assemblyPath, frameworkHandle, out var attachmentFailure))
- {
- pipeStream.WaitForConnection();
-
- pipe.Send(executeTests);
-
- var recorder = new VsExecutionRecorder(frameworkHandle, assemblyPath);
-
- PipeMessage.TestStarted? lastTestStarted = null;
-
- while (true)
- {
- var messageType = pipe.ReceiveMessageType();
-
- if (messageType == typeof(PipeMessage.TestStarted).FullName)
- {
- var message = pipe.Receive();
- lastTestStarted = message;
- recorder.Record(message);
- }
- else if (messageType == typeof(PipeMessage.TestSkipped).FullName)
- {
- var testResult = pipe.Receive();
- recorder.Record(testResult);
- }
- else if (messageType == typeof(PipeMessage.TestPassed).FullName)
- {
- var testResult = pipe.Receive();
- recorder.Record(testResult);
- }
- else if (messageType == typeof(PipeMessage.TestFailed).FullName)
- {
- var testResult = pipe.Receive();
- recorder.Record(testResult);
- }
- else if (messageType == typeof(PipeMessage.Exception).FullName)
- {
- var exception = pipe.Receive();
- throw new RunnerException(exception);
- }
- else if (messageType == typeof(PipeMessage.EndOfPipe).FullName)
- {
- var endOfPipe = pipe.Receive();
- break;
- }
- else if (!string.IsNullOrEmpty(messageType))
- {
- var body = pipe.ReceiveMessageBody();
- log.Error($"The test runner received an unexpected message of type {messageType}: {body}");
- }
- else
- {
- var exception = new TestProcessExitException(process.TryGetExitCode());
-
- if (lastTestStarted != null)
- {
- recorder.Record(new PipeMessage.TestFailed
- {
- Test = lastTestStarted.Test,
- TestCase = lastTestStarted.Test,
- Reason = new PipeMessage.Exception(exception),
- DurationInMilliseconds = 0
- });
- }
-
- throw exception;
- }
- }
-
- if (attachmentFailure != null)
- {
- var exception = attachmentFailure.ThirdPartyTestHostException;
-
- var reason = new PipeMessage.Exception
- {
- Type = exception.GetType().FullName!,
- Message = attachmentFailure.Message,
- StackTrace = exception.StackTrace!
- };
-
- foreach (var selectedTest in executeTests.Filter)
- {
- recorder.Record(new PipeMessage.TestFailed
- {
- Test = selectedTest,
- TestCase = selectedTest,
- Reason = reason,
- DurationInMilliseconds = 0
- });
- }
- }
- }
- }
-
- static void HandlePoorVsTestImplementationDetails(IRunContext? runContext, IFrameworkHandle frameworkHandle)
- {
- if (runContext?.KeepAlive == true)
- frameworkHandle.EnableShutdownAfterTestRun = true;
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.Tests/CaseNameTests.cs b/src/Fixie.Tests/CaseNameTests.cs
index 5e0dfabe1..5bb965c87 100644
--- a/src/Fixie.Tests/CaseNameTests.cs
+++ b/src/Fixie.Tests/CaseNameTests.cs
@@ -36,13 +36,9 @@ public async Task ShouldIncludeEscapeSequencesInNameWhenTheUnderlyingMethodHasCh
foreach (var c in new[] {'\"', '"', '\''})
await Run(test, c);
- foreach (var c in new[] {'\\', '\0', '\a', '\b', '\f', '\n', '\r', '\t', '\v'})
+ foreach (var c in new[] {'\\', '\0', '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\e'})
await Run(test, c);
- #if NET9_0_OR_GREATER
- await Run(test, '\e');
- #endif
-
foreach (var c in new[] {'\u0000', '\u0085', '\u2028', '\u2029', '\u263A'})
await Run(test, c);
@@ -55,20 +51,11 @@ public async Task ShouldIncludeEscapeSequencesInNameWhenTheUnderlyingMethodHasCh
foreach (var c in new[] {'\U00000000', '\U00000085', '\U00002028', '\U00002029', '\U0000263A'})
await Run(test, c);
- foreach (var c in UnicodeEscapedCharacters()
- #if NET9_0_OR_GREATER
- .Where(c => c != '\e')
- #endif
- )
+ foreach (var c in UnicodeEscapedCharacters())
await Run(test, c);
});
var unicodeEscapeExpectations = UnicodeEscapedCharacters()
-
- #if NET9_0_OR_GREATER
- .Where(c => c != '\e')
- #endif
-
.Select(c => $"""
CharParametersTestClass.Char('\u{(int)c:X4}')
""");
@@ -87,10 +74,7 @@ public async Task ShouldIncludeEscapeSequencesInNameWhenTheUnderlyingMethodHasCh
"CharParametersTestClass.Char('\\r')",
"CharParametersTestClass.Char('\\t')",
"CharParametersTestClass.Char('\\v')",
-
- #if NET9_0_OR_GREATER
"CharParametersTestClass.Char('\\e')",
- #endif
"CharParametersTestClass.Char('\\0')",
"CharParametersTestClass.Char('\\u0085')",
@@ -131,11 +115,7 @@ public async Task ShouldIncludeEscapeSequencesInNameWhenTheUnderlyingMethodHasSt
{
await Run(test, " \' ' \" ");
await Run(test, " \\ \0 \a \b ");
- await Run(test, " \f \n \r \t \v ");
-
- #if NET9_0_OR_GREATER
- await Run(test, " \e ");
- #endif
+ await Run(test, " \f \n \r \t \v \e ");
await Run(test, " \u0000 \u0085 \u2028 \u2029 \u263A ");
await Run(test, " \x0000 \x000 \x00 \x0 ");
@@ -143,11 +123,6 @@ public async Task ShouldIncludeEscapeSequencesInNameWhenTheUnderlyingMethodHasSt
await Run(test, " \U00000000 \U00000085 \U00002028 \U00002029 \U0000263A ");
foreach (var c in UnicodeEscapedCharacters().Chunk(5)
-
- #if NET9_0_OR_GREATER
- .Select(chunk => chunk.Where(c => c != '\e'))
- #endif
-
.Select(chunk => string.Join(' ', chunk)))
await Run(test, c);
});
@@ -155,11 +130,7 @@ public async Task ShouldIncludeEscapeSequencesInNameWhenTheUnderlyingMethodHasSt
ShouldHaveNames(output,
"StringParametersTestClass.String(\" ' ' \\\" \")",
"StringParametersTestClass.String(\" \\\\ \\0 \\a \\b \")",
- "StringParametersTestClass.String(\" \\f \\n \\r \\t \\v \")",
-
- #if NET9_0_OR_GREATER
- "StringParametersTestClass.String(\" \\e \")",
- #endif
+ "StringParametersTestClass.String(\" \\f \\n \\r \\t \\v \\e \")",
"StringParametersTestClass.String(\" \\0 \\u0085 \\u2028 \\u2029 ☺ \")",
"StringParametersTestClass.String(\" \\0 \\0 \\0 \\0 \")",
@@ -169,24 +140,19 @@ public async Task ShouldIncludeEscapeSequencesInNameWhenTheUnderlyingMethodHasSt
"StringParametersTestClass.String(\"\\u0006 \\u000E \\u000F \\u0010 \\u0011\")",
"StringParametersTestClass.String(\"\\u0012 \\u0013 \\u0014 \\u0015 \\u0016\")",
- #if NET8_0
- "StringParametersTestClass.String(\"\\u0017 \\u0018 \\u0019 \\u001A \\u001B\")",
- #else
- "StringParametersTestClass.String(\"\\u0017 \\u0018 \\u0019 \\u001A\")",
- #endif
-
- "StringParametersTestClass.String(\"\\u001C \\u001D \\u001E \\u001F \\u007F\")",
- "StringParametersTestClass.String(\"\\u0080 \\u0081 \\u0082 \\u0083 \\u0084\")",
- "StringParametersTestClass.String(\"\\u0085 \\u0086 \\u0087 \\u0088 \\u0089\")",
- "StringParametersTestClass.String(\"\\u008A \\u008B \\u008C \\u008D \\u008E\")",
- "StringParametersTestClass.String(\"\\u008F \\u0090 \\u0091 \\u0092 \\u0093\")",
- "StringParametersTestClass.String(\"\\u0094 \\u0095 \\u0096 \\u0097 \\u0098\")",
- "StringParametersTestClass.String(\"\\u0099 \\u009A \\u009B \\u009C \\u009D\")",
- "StringParametersTestClass.String(\"\\u009E \\u009F \\u0085 \\u00A0 \\u1680\")",
- "StringParametersTestClass.String(\"\\u2000 \\u2001 \\u2002 \\u2003 \\u2004\")",
- "StringParametersTestClass.String(\"\\u2005 \\u2006 \\u2007 \\u2008 \\u2009\")",
- "StringParametersTestClass.String(\"\\u200A \\u2028 \\u2029 \\u202F \\u205F\")",
- "StringParametersTestClass.String(\"\\u3000\")"
+ "StringParametersTestClass.String(\"\\u0017 \\u0018 \\u0019 \\u001A \\u001C\")",
+
+ "StringParametersTestClass.String(\"\\u001D \\u001E \\u001F \\u007F \\u0080\")",
+ "StringParametersTestClass.String(\"\\u0081 \\u0082 \\u0083 \\u0084 \\u0085\")",
+ "StringParametersTestClass.String(\"\\u0086 \\u0087 \\u0088 \\u0089 \\u008A\")",
+ "StringParametersTestClass.String(\"\\u008B \\u008C \\u008D \\u008E \\u008F\")",
+ "StringParametersTestClass.String(\"\\u0090 \\u0091 \\u0092 \\u0093 \\u0094\")",
+ "StringParametersTestClass.String(\"\\u0095 \\u0096 \\u0097 \\u0098 \\u0099\")",
+ "StringParametersTestClass.String(\"\\u009A \\u009B \\u009C \\u009D \\u009E\")",
+ "StringParametersTestClass.String(\"\\u009F \\u0085 \\u00A0 \\u1680 \\u2000\")",
+ "StringParametersTestClass.String(\"\\u2001 \\u2002 \\u2003 \\u2004 \\u2005\")",
+ "StringParametersTestClass.String(\"\\u2006 \\u2007 \\u2008 \\u2009 \\u200A\")",
+ "StringParametersTestClass.String(\"\\u2028 \\u2029 \\u202F \\u205F \\u3000\")"
);
}
@@ -298,7 +264,8 @@ static IEnumerable UnicodeEscapedCharacters()
// '\uHHHH' hex escape sequences.
for (char c = '\u0001'; c <= '\u0006'; c++) yield return c;
- for (char c = '\u000E'; c <= '\u001F'; c++) yield return c;
+ for (char c = '\u000E'; c <= '\u001A'; c++) yield return c;
+ for (char c = '\u001C'; c <= '\u001F'; c++) yield return c;
yield return '\u007F';
for (char c = '\u0080'; c <= '\u009F'; c++) yield return c;
diff --git a/src/Fixie.Tests/Console/CommandLineTests.cs b/src/Fixie.Tests/Console/CommandLineTests.cs
index 7030350bb..ed860cf28 100644
--- a/src/Fixie.Tests/Console/CommandLineTests.cs
+++ b/src/Fixie.Tests/Console/CommandLineTests.cs
@@ -7,11 +7,11 @@ public class CommandLineTests
public void ShouldPartitionRunnerArgumentsFromCustomArguments()
{
CommandLine.Partition([
- "Example.Tests", "--configuration", "Release", "--framework", "net8.0",
+ "Example.Tests", "--configuration", "Release", "--framework", "net9.0",
"--",
"customA", "customB", "customC"
], out var runnerArguments, out var customArguments);
- runnerArguments.ShouldMatch(["Example.Tests", "--configuration", "Release", "--framework", "net8.0"]);
+ runnerArguments.ShouldMatch(["Example.Tests", "--configuration", "Release", "--framework", "net9.0"]);
customArguments.ShouldMatch(["customA", "customB", "customC"]);
CommandLine.Partition(["Example.Tests", "--", "custom"], out runnerArguments, out customArguments);
diff --git a/src/Fixie.Tests/Fixie.Tests.csproj b/src/Fixie.Tests/Fixie.Tests.csproj
index 3cf5bdaf9..360dd718a 100644
--- a/src/Fixie.Tests/Fixie.Tests.csproj
+++ b/src/Fixie.Tests/Fixie.Tests.csproj
@@ -3,7 +3,7 @@
- net8.0;net9.0
+ net9.0
@@ -13,7 +13,6 @@
-
diff --git a/src/Fixie.Tests/Internal/PipeMessageSerializationTests.cs b/src/Fixie.Tests/Internal/PipeMessageSerializationTests.cs
deleted file mode 100644
index 55a6e7118..000000000
--- a/src/Fixie.Tests/Internal/PipeMessageSerializationTests.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using Fixie.Internal;
-using Fixie.Tests.Reports;
-
-namespace Fixie.Tests.Internal;
-
-public class PipeMessageSerializationTests : MessagingTests
-{
- public void ShouldSerializeDiscoverTestsMessage()
- {
- Expect(new PipeMessage.DiscoverTests(), "{}");
- }
-
- public void ShouldSerializeExecuteTestsMessage()
- {
- Expect(new PipeMessage.ExecuteTests { Filter = [] },
- "{\"Filter\":[]}");
-
- Expect(new PipeMessage.ExecuteTests { Filter =
- [
- TestClass + ".Pass",
- GenericTestClass + ".ShouldBeString"
- ] },
- "{\"Filter\":[\"Fixie.Tests.Reports.MessagingTests\\u002BSampleTestClass.Pass\",\"Fixie.Tests.Reports.MessagingTests\\u002BSampleGenericTestClass.ShouldBeString\"]}");
- }
-
- public void ShouldSerializeTestDiscoveredMessage()
- {
- Expect(new PipeMessage.TestDiscovered { Test = TestClass + ".Pass" },
- "{\"Test\":\"Fixie.Tests.Reports.MessagingTests\\u002BSampleTestClass.Pass\"}");
- }
-
- public void ShouldSerializeTestStartedMessage()
- {
- Expect(new PipeMessage.TestStarted { Test = TestClass + ".Pass" },
- "{\"Test\":\"Fixie.Tests.Reports.MessagingTests\\u002BSampleTestClass.Pass\"}");
- }
-
- public void ShouldSerializeTestSkippedMessage()
- {
- Expect(new PipeMessage.TestSkipped
- {
- Reason = "⚠ Skipped!",
- Test = GenericTestClass + ".ShouldBeString",
- TestCase = GenericTestClass + ".ShouldBeString(123)",
- DurationInMilliseconds = 123.456d
- },
- "{\"Reason\":\"\\u26A0 Skipped!\",\"Test\":\"Fixie.Tests.Reports.MessagingTests\\u002BSampleGenericTestClass.ShouldBeString\",\"TestCase\":\"Fixie.Tests.Reports.MessagingTests\\u002BSampleGenericTestClass.ShouldBeString\\u003CSystem.Int32\\u003E(123)\",\"DurationInMilliseconds\":123.456}");
- }
-
- public void ShouldSerializeTestPassedMessage()
- {
- Expect(new PipeMessage.TestPassed
- {
- Test = GenericTestClass + ".ShouldBeString",
- TestCase = GenericTestClass + ".ShouldBeString(123)",
- DurationInMilliseconds = 123.456d
- },
- "{\"Test\":\"Fixie.Tests.Reports.MessagingTests\\u002BSampleGenericTestClass.ShouldBeString\",\"TestCase\":\"Fixie.Tests.Reports.MessagingTests\\u002BSampleGenericTestClass.ShouldBeString\\u003CSystem.Int32\\u003E(123)\",\"DurationInMilliseconds\":123.456}");
- }
-
- public void ShouldSerializeTestFailedMessage()
- {
- var at = At("ShouldBeString[T](T genericArgument)").Replace("\\", "\\\\");
-
- Expect(new PipeMessage.TestFailed
- {
- Reason = new PipeMessage.Exception
- {
- Type = "Fixie.Assertions.AssertException",
- Message = "Expected: System.String\nActual: System.Int32",
- StackTrace = At("ShouldBeString[T](T genericArgument)")
- },
- Test = GenericTestClass + ".ShouldBeString",
- TestCase = GenericTestClass + ".ShouldBeString(123)",
- DurationInMilliseconds = 123.456d
- },
- "{\"Reason\":{\"Type\":\"Fixie.Assertions.AssertException\",\"Message\":\"Expected: System.String\\nActual: System.Int32\",\"StackTrace\":\"" + at + "\"},\"Test\":\"Fixie.Tests.Reports.MessagingTests\\u002BSampleGenericTestClass.ShouldBeString\",\"TestCase\":\"Fixie.Tests.Reports.MessagingTests\\u002BSampleGenericTestClass.ShouldBeString\\u003CSystem.Int32\\u003E(123)\",\"DurationInMilliseconds\":123.456}");
- }
-
- public void ShouldSerializeExceptionMessage()
- {
- var at = At("ShouldBeString[T](T genericArgument)").Replace("\\", "\\\\");
-
- Expect(new PipeMessage.Exception
- {
- Type = "Fixie.Assertions.AssertException",
- Message = "Expected: System.String\nActual: System.Int32",
- StackTrace = At("ShouldBeString[T](T genericArgument)")
- },
- "{\"Type\":\"Fixie.Assertions.AssertException\",\"Message\":\"Expected: System.String\\nActual: System.Int32\",\"StackTrace\":\"" + at + "\"}");
- }
-
- public void ShouldSerializeEndOfPipeMessage()
- {
- Expect(new PipeMessage.EndOfPipe(), "{}");
- }
-
- public void ShouldThrowForNullDeserialization()
- {
- var nullMessage = () => PipeMessage.Deserialize("null");
- nullMessage.ShouldThrow("Message of type Fixie.Internal.PipeMessage+TestFailed was unexpectedly null.");
- }
-
- static void Expect(TMessage message, string expectedJson)
- {
- PipeMessage.Serialize(PipeMessage.Deserialize(expectedJson)).ShouldBe(expectedJson);
- PipeMessage.Serialize(message).ShouldBe(expectedJson);
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.Tests/TestAdapter/SourceLocationProviderTests.cs b/src/Fixie.Tests/Internal/SourceLocationProviderTests.cs
similarity index 98%
rename from src/Fixie.Tests/TestAdapter/SourceLocationProviderTests.cs
rename to src/Fixie.Tests/Internal/SourceLocationProviderTests.cs
index fc4c742c1..cbb430697 100644
--- a/src/Fixie.Tests/TestAdapter/SourceLocationProviderTests.cs
+++ b/src/Fixie.Tests/Internal/SourceLocationProviderTests.cs
@@ -1,7 +1,7 @@
-using Fixie.TestAdapter;
+using Fixie.Internal;
using static Fixie.Tests.Utility;
-namespace Fixie.Tests.TestAdapter;
+namespace Fixie.Tests.Internal;
public class SourceLocationProviderTests
{
diff --git a/src/Fixie.Tests/TestAdapter/SourceLocationSamples.cs b/src/Fixie.Tests/Internal/SourceLocationSamples.cs
similarity index 97%
rename from src/Fixie.Tests/TestAdapter/SourceLocationSamples.cs
rename to src/Fixie.Tests/Internal/SourceLocationSamples.cs
index 57b47a603..abae0c284 100644
--- a/src/Fixie.Tests/TestAdapter/SourceLocationSamples.cs
+++ b/src/Fixie.Tests/Internal/SourceLocationSamples.cs
@@ -1,4 +1,4 @@
-namespace Fixie.Tests.TestAdapter;
+namespace Fixie.Tests.Internal;
// Avoid changes in this file that would move the well-known line numbers indicated in comments.
// Otherwise, these comments and the associated assertions would need to be updated together
diff --git a/src/Fixie.Tests/TestAdapter/TestCaseMappingAssertions.cs b/src/Fixie.Tests/TestAdapter/TestCaseMappingAssertions.cs
deleted file mode 100644
index f0bf8689d..000000000
--- a/src/Fixie.Tests/TestAdapter/TestCaseMappingAssertions.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using Microsoft.VisualStudio.TestPlatform.ObjectModel;
-
-namespace Fixie.Tests.TestAdapter;
-
-public static class TestCaseMappingAssertions
-{
- public static void ShouldBeDiscoveryTimeTest(this TestCase test, string expectedFullyQualifiedName, string expectedSource)
- {
- ShouldHaveIdentity(test, expectedFullyQualifiedName, expectedSource);
-
- ShouldUseDefaultsForUnmappedProperties(test);
-
- ShouldHaveSourceLocation(test);
- }
-
- public static void ShouldBeDiscoveryTimeTestMissingSourceLocation(this TestCase test, string expectedFullyQualifiedName, string expectedSource)
- {
- ShouldHaveIdentity(test, expectedFullyQualifiedName, expectedSource);
-
- ShouldUseDefaultsForUnmappedProperties(test);
-
- ShouldNotHaveSourceLocation(test);
- }
-
- public static void ShouldBeExecutionTimeTest(this TestCase test, string expectedFullyQualifiedName, string expectedSource)
- {
- ShouldHaveIdentity(test, expectedFullyQualifiedName, expectedSource);
-
- ShouldUseDefaultsForUnmappedProperties(test);
-
- //Source locations are a discovery-time concern.
- ShouldNotHaveSourceLocation(test);
- }
-
- static void ShouldHaveIdentity(TestCase test, string expectedFullyQualifiedName, string expectedSource)
- {
- test.FullyQualifiedName.ShouldBe(expectedFullyQualifiedName);
- test.DisplayName.ShouldBe(test.FullyQualifiedName);
- test.Source.ShouldBe(expectedSource);
- }
-
- static void ShouldUseDefaultsForUnmappedProperties(TestCase test)
- {
- test.Traits.ToArray().ShouldMatch([]);
- test.ExecutorUri.ToString().ShouldBe("executor://fixie.testadapter/");
- }
-
- static void ShouldHaveSourceLocation(TestCase test)
- {
- test.CodeFilePath.ShouldNotBeNull();
- test.CodeFilePath.EndsWith("MessagingTests.cs").ShouldBe(true);
- test.LineNumber.ShouldSatisfy(x => x > 0);
- }
-
- static void ShouldNotHaveSourceLocation(TestCase test)
- {
- test.CodeFilePath.ShouldBe(null);
- test.LineNumber.ShouldBe(-1);
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.Tests/TestAdapter/VsDiscoveryRecorderTests.cs b/src/Fixie.Tests/TestAdapter/VsDiscoveryRecorderTests.cs
deleted file mode 100644
index 7fcbb26d1..000000000
--- a/src/Fixie.Tests/TestAdapter/VsDiscoveryRecorderTests.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using Fixie.Internal;
-using Fixie.TestAdapter;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
-using Fixie.Tests.Reports;
-using static System.IO.Directory;
-
-namespace Fixie.Tests.TestAdapter;
-
-public class VsDiscoveryRecorderTests : MessagingTests
-{
- public void ShouldMapDiscoveredTestsToVsTestDiscoverySink()
- {
- var assemblyPath = typeof(MessagingTests).Assembly.Location;
-
- var log = new StubMessageLogger();
- var discoverySink = new StubTestCaseDiscoverySink();
-
- var vsDiscoveryRecorder = new VsDiscoveryRecorder(log, discoverySink, assemblyPath);
-
- RecordAnticipatedPipeMessages(vsDiscoveryRecorder);
-
- log.Messages.ShouldMatch([]);
-
- discoverySink.TestCases.ItemsShouldSatisfy([
- x => x.ShouldBeDiscoveryTimeTest(TestClass + ".Fail", assemblyPath),
- x => x.ShouldBeDiscoveryTimeTest(TestClass + ".FailByAssertion", assemblyPath),
- x => x.ShouldBeDiscoveryTimeTestMissingSourceLocation(TestClass + ".Pass", assemblyPath),
- x => x.ShouldBeDiscoveryTimeTest(TestClass + ".Skip", assemblyPath),
- x => x.ShouldBeDiscoveryTimeTest(GenericTestClass + ".ShouldBeString", assemblyPath)
- ]);
- }
-
- public void ShouldDefaultSourceLocationPropertiesWhenSourceInspectionThrows()
- {
- const string invalidAssemblyPath = "assembly.path.dll";
-
- var log = new StubMessageLogger();
- var discoverySink = new StubTestCaseDiscoverySink();
-
- var discoveryRecorder = new VsDiscoveryRecorder(log, discoverySink, invalidAssemblyPath);
-
- RecordAnticipatedPipeMessages(discoveryRecorder);
-
- var expectedError =
- $"Error: {typeof(FileNotFoundException).FullName}: " +
- $"Could not find file '{Path.Combine(GetCurrentDirectory(), invalidAssemblyPath)}'.";
- log.Messages.ItemsShouldSatisfy([
- x => x.Contains(expectedError).ShouldBe(true),
- x => x.Contains(expectedError).ShouldBe(true),
- x => x.Contains(expectedError).ShouldBe(true),
- x => x.Contains(expectedError).ShouldBe(true),
- x => x.Contains(expectedError).ShouldBe(true)
- ]);
-
- discoverySink.TestCases.ItemsShouldSatisfy([
- x => x.ShouldBeDiscoveryTimeTestMissingSourceLocation(TestClass + ".Fail", invalidAssemblyPath),
- x => x.ShouldBeDiscoveryTimeTestMissingSourceLocation(TestClass + ".FailByAssertion", invalidAssemblyPath),
- x => x.ShouldBeDiscoveryTimeTestMissingSourceLocation(TestClass + ".Pass", invalidAssemblyPath),
- x => x.ShouldBeDiscoveryTimeTestMissingSourceLocation(TestClass + ".Skip", invalidAssemblyPath),
- x => x.ShouldBeDiscoveryTimeTestMissingSourceLocation(GenericTestClass + ".ShouldBeString", invalidAssemblyPath)
- ]);
- }
-
- void RecordAnticipatedPipeMessages(VsDiscoveryRecorder vsDiscoveryRecorder)
- {
- vsDiscoveryRecorder.Record(new PipeMessage.TestDiscovered
- {
- Test = TestClass + ".Fail"
- });
-
- vsDiscoveryRecorder.Record(new PipeMessage.TestDiscovered
- {
- Test = TestClass + ".FailByAssertion"
- });
-
- vsDiscoveryRecorder.Record(new PipeMessage.TestDiscovered
- {
- Test = TestClass + ".Pass"
- });
-
- vsDiscoveryRecorder.Record(new PipeMessage.TestDiscovered
- {
- Test = TestClass + ".Skip"
- });
-
- vsDiscoveryRecorder.Record(new PipeMessage.TestDiscovered
- {
- Test = GenericTestClass + ".ShouldBeString"
- });
- }
-
- class StubMessageLogger : IMessageLogger
- {
- public List Messages { get; } = [];
-
- public void SendMessage(TestMessageLevel testMessageLevel, string message)
- => Messages.Add($"{testMessageLevel}: {message}");
- }
-
- class StubTestCaseDiscoverySink : ITestCaseDiscoverySink
- {
- public List TestCases { get; } = [];
-
- public void SendTestCase(TestCase discoveredTest)
- => TestCases.Add(discoveredTest);
- }
-}
\ No newline at end of file
diff --git a/src/Fixie.Tests/TestAdapter/VsExecutionRecorderTests.cs b/src/Fixie.Tests/TestAdapter/VsExecutionRecorderTests.cs
deleted file mode 100644
index b03110660..000000000
--- a/src/Fixie.Tests/TestAdapter/VsExecutionRecorderTests.cs
+++ /dev/null
@@ -1,270 +0,0 @@
-using Fixie.TestAdapter;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
-using Fixie.Internal;
-using Fixie.Tests.Reports;
-using static System.Environment;
-
-namespace Fixie.Tests.TestAdapter;
-
-using TestResult = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult;
-
-public class VsExecutionRecorderTests : MessagingTests
-{
- public void ShouldMapMessagesToVsTestExecutionRecorder()
- {
- const string assemblyPath = "assembly.path.dll";
- var recorder = new StubExecutionRecorder();
-
- var vsExecutionRecorder = new VsExecutionRecorder(recorder, assemblyPath);
-
- RecordAnticipatedPipeMessages(vsExecutionRecorder);
-
- var messages = recorder.Messages;
-
- messages.Count.ShouldBe(13);
-
- foreach (var message in messages)
- {
- if (message is TestResult result)
- {
- result.Traits.ToArray().ShouldMatch([]);
- result.Attachments.ShouldMatch([]);
- result.ComputerName.ShouldBe(MachineName);
- }
- }
-
- var failStart = (TestCase)messages[0];
- var fail = (TestResult)messages[1];
-
- var failByAssertionStart = (TestCase)messages[2];
- var failByAssertion = (TestResult)messages[3];
-
- var passStart = (TestCase)messages[4];
- var pass = (TestResult)messages[5];
-
- var skip = (TestResult)messages[6];
-
- var shouldBeStringPassAStart = (TestCase)messages[7];
- var shouldBeStringPassA = (TestResult)messages[8];
-
- var shouldBeStringPassBStart = (TestCase)messages[9];
- var shouldBeStringPassB = (TestResult)messages[10];
-
- var shouldBeStringFailStart = (TestCase)messages[11];
- var shouldBeStringFail = (TestResult)messages[12];
-
- failStart.ShouldBeExecutionTimeTest(TestClass + ".Fail", assemblyPath);
-
- fail.TestCase.ShouldBeExecutionTimeTest(TestClass+".Fail", assemblyPath);
- fail.TestCase.DisplayName.ShouldBe(TestClass+".Fail");
- fail.Outcome.ShouldBe(TestOutcome.Failed);
- fail.ErrorMessage.ShouldBe("'Fail' failed!");
- fail.ErrorStackTrace
- .ShouldBeStackTrace(["Fixie.Tests.FailureException", At("Fail()")]);
- fail.DisplayName.ShouldBe(TestClass+".Fail");
- fail.Messages.ShouldMatch([]);
- fail.Duration.ShouldBe(TimeSpan.FromMilliseconds(102));
-
- failByAssertionStart.ShouldBeExecutionTimeTest(TestClass + ".FailByAssertion", assemblyPath);
-
- failByAssertion.TestCase.ShouldBeExecutionTimeTest(TestClass+".FailByAssertion", assemblyPath);
- failByAssertion.TestCase.DisplayName.ShouldBe(TestClass+".FailByAssertion");
- failByAssertion.Outcome.ShouldBe(TestOutcome.Failed);
- failByAssertion.ErrorMessage.ShouldBe(xShouldBe2ButWas1);
- failByAssertion.ErrorStackTrace
- .ShouldBeStackTrace(["Fixie.Assertions.AssertException", At("FailByAssertion()")]);
- failByAssertion.DisplayName.ShouldBe(TestClass+".FailByAssertion");
- failByAssertion.Messages.ShouldMatch([]);
- failByAssertion.Duration.ShouldBe(TimeSpan.FromMilliseconds(103));
-
- passStart.ShouldBeExecutionTimeTest(TestClass + ".Pass", assemblyPath);
-
- pass.TestCase.ShouldBeExecutionTimeTest(TestClass+".Pass", assemblyPath);
- pass.TestCase.DisplayName.ShouldBe(TestClass+".Pass");
- pass.Outcome.ShouldBe(TestOutcome.Passed);
- pass.ErrorMessage.ShouldBe(null);
- pass.ErrorStackTrace.ShouldBe(null);
- pass.DisplayName.ShouldBe(TestClass+".Pass");
- pass.Messages.ShouldMatch([]);
- pass.Duration.ShouldBe(TimeSpan.FromMilliseconds(104));
-
- skip.TestCase.ShouldBeExecutionTimeTest(TestClass+".Skip", assemblyPath);
- skip.TestCase.DisplayName.ShouldBe(TestClass+".Skip");
- skip.Outcome.ShouldBe(TestOutcome.Skipped);
- skip.ErrorMessage.ShouldBe("⚠ Skipped with attribute.");
- skip.ErrorStackTrace.ShouldBe(null);
- skip.DisplayName.ShouldBe(TestClass+".Skip");
- skip.Messages.ShouldMatch([]);
- skip.Duration.ShouldBe(TimeSpan.Zero);
-
- shouldBeStringPassAStart.ShouldBeExecutionTimeTest(GenericTestClass + ".ShouldBeString", assemblyPath);
-
- shouldBeStringPassA.TestCase.ShouldBeExecutionTimeTest(GenericTestClass+".ShouldBeString", assemblyPath);
- shouldBeStringPassA.TestCase.DisplayName.ShouldBe(GenericTestClass+".ShouldBeString");
- shouldBeStringPassA.Outcome.ShouldBe(TestOutcome.Passed);
- shouldBeStringPassA.ErrorMessage.ShouldBe(null);
- shouldBeStringPassA.ErrorStackTrace.ShouldBe(null);
- shouldBeStringPassA.DisplayName.ShouldBe(GenericTestClass+".ShouldBeString(\"A\")");
- shouldBeStringPassA.Messages.ShouldMatch([]);
- shouldBeStringPassA.Duration.ShouldBe(TimeSpan.FromMilliseconds(105));
-
- shouldBeStringPassBStart.ShouldBeExecutionTimeTest(GenericTestClass + ".ShouldBeString", assemblyPath);
-
- shouldBeStringPassB.TestCase.ShouldBeExecutionTimeTest(GenericTestClass+".ShouldBeString", assemblyPath);
- shouldBeStringPassB.TestCase.DisplayName.ShouldBe(GenericTestClass+".ShouldBeString");
- shouldBeStringPassB.Outcome.ShouldBe(TestOutcome.Passed);
- shouldBeStringPassB.ErrorMessage.ShouldBe(null);
- shouldBeStringPassB.ErrorStackTrace.ShouldBe(null);
- shouldBeStringPassB.DisplayName.ShouldBe(GenericTestClass+".ShouldBeString(\"B\")");
- shouldBeStringPassB.Messages.ShouldMatch([]);
- shouldBeStringPassB.Duration.ShouldBe(TimeSpan.FromMilliseconds(106));
-
- shouldBeStringFailStart.ShouldBeExecutionTimeTest(GenericTestClass + ".ShouldBeString", assemblyPath);
-
- shouldBeStringFail.TestCase.ShouldBeExecutionTimeTest(GenericTestClass+".ShouldBeString", assemblyPath);
- shouldBeStringFail.TestCase.DisplayName.ShouldBe(GenericTestClass+".ShouldBeString");
- shouldBeStringFail.Outcome.ShouldBe(TestOutcome.Failed);
- shouldBeStringFail.ErrorMessage.ShouldBe(genericArgumentShouldMatchStringButWasInt);
- shouldBeStringFail.ErrorStackTrace
- .ShouldBeStackTrace([
- "Fixie.Assertions.AssertException",
- At("ShouldBeString[T](T genericArgument)")
- ]);
- shouldBeStringFail.DisplayName.ShouldBe(GenericTestClass+".ShouldBeString(123)");
- shouldBeStringFail.Messages.ShouldMatch([]);
- shouldBeStringFail.Duration.ShouldBe(TimeSpan.FromMilliseconds(107));
- }
-
- void RecordAnticipatedPipeMessages(VsExecutionRecorder vsExecutionRecorder)
- {
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestStarted
- {
- Test = TestClass + ".Fail"
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestFailed
- {
- Test = TestClass + ".Fail",
- TestCase = TestClass + ".Fail",
- DurationInMilliseconds = 102,
- Reason = new PipeMessage.Exception
- {
- Type = "Fixie.Tests.FailureException",
- Message = "'Fail' failed!",
- StackTrace = At("Fail()")
- }
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestStarted
- {
- Test = TestClass + ".FailByAssertion"
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestFailed
- {
- Test = TestClass + ".FailByAssertion",
- TestCase = TestClass + ".FailByAssertion",
- DurationInMilliseconds = 103,
- Reason = new PipeMessage.Exception
- {
- Type = "Fixie.Assertions.AssertException",
- Message = xShouldBe2ButWas1,
- StackTrace = At("FailByAssertion()")
- }
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestStarted
- {
- Test = TestClass + ".Pass"
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestPassed
- {
- Test = TestClass+".Pass",
- TestCase = TestClass+".Pass",
- DurationInMilliseconds = 104
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestSkipped
- {
- Test =TestClass+".Skip",
- TestCase = TestClass+".Skip",
- DurationInMilliseconds = 0,
- Reason = "⚠ Skipped with attribute."
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestStarted
- {
- Test = GenericTestClass + ".ShouldBeString"
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestPassed
- {
- Test = GenericTestClass+".ShouldBeString",
- TestCase = GenericTestClass+".ShouldBeString(\"A\")",
- DurationInMilliseconds = 105
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestStarted
- {
- Test = GenericTestClass + ".ShouldBeString"
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestPassed
- {
- Test = GenericTestClass+".ShouldBeString",
- TestCase = GenericTestClass+".ShouldBeString(\"B\")",
- DurationInMilliseconds = 106
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestStarted
- {
- Test = GenericTestClass + ".ShouldBeString"
- }));
-
- vsExecutionRecorder.Record(Deserialized(new PipeMessage.TestFailed
- {
- Test = GenericTestClass+".ShouldBeString",
- TestCase = GenericTestClass+".ShouldBeString(123)",
- DurationInMilliseconds = 107,
- Reason = new PipeMessage.Exception
- {
- Type = "Fixie.Assertions.AssertException",
- Message = genericArgumentShouldMatchStringButWasInt,
- StackTrace = At("ShouldBeString[T](T genericArgument)")
- }
- }));
- }
-
- static T Deserialized(T original)
- {
- // Because the inter-process communication between the VsTest process
- // and the test assembly process is not exercised in these single-process
- // tests, put a given sample message through the same serialization round
- // trip that would be applied at runtime, in order to detect data loss.
-
- return PipeMessage.Deserialize(PipeMessage.Serialize(original));
- }
-
- class StubExecutionRecorder : ITestExecutionRecorder
- {
- public List
+
+
+
+
\ No newline at end of file
diff --git a/src/Fixie/Internal/CaseNameBuilder.cs b/src/Fixie/Internal/CaseNameBuilder.cs
index 1950d1a21..cfe944972 100644
--- a/src/Fixie/Internal/CaseNameBuilder.cs
+++ b/src/Fixie/Internal/CaseNameBuilder.cs
@@ -76,11 +76,7 @@ static string Escape(char ch, Literal literal) =>
'\v' => @"\v",
'\f' => @"\f",
'\r' => @"\r",
-
- #if NET9_0_OR_GREATER
'\e' => @"\e",
- #endif
-
' ' => " ",
'\"' => literal == Literal.String ? @"\""" : char.ToString(ch),
'\'' => literal == Literal.Character ? @"\'" : char.ToString(ch),
diff --git a/src/Fixie/Internal/EntryPoint.cs b/src/Fixie/Internal/EntryPoint.cs
index a687bc4c6..7262d9981 100644
--- a/src/Fixie/Internal/EntryPoint.cs
+++ b/src/Fixie/Internal/EntryPoint.cs
@@ -1,5 +1,4 @@
-using System.IO.Pipes;
-using System.Reflection;
+using System.Reflection;
using Fixie.Reports;
using static System.Environment;
using static Fixie.Internal.Maybe;
@@ -25,64 +24,13 @@ public static async Task Main(Assembly assembly, string[] customArguments)
try
{
- var pipeName = GetEnvironmentVariable("FIXIE_NAMED_PIPE");
+ var reports = DefaultReports(environment).ToArray();
- if (pipeName == null)
- {
- var reports = DefaultReports(environment).ToArray();
+ var pattern = GetEnvironmentVariable("FIXIE_TESTS_PATTERN");
- var pattern = GetEnvironmentVariable("FIXIE_TESTS_PATTERN");
-
- return pattern == null
- ? (int) await Run(environment, reports, async runner => await runner.Run())
- : (int) await Run(environment, reports, async runner => await runner.Run(new TestPattern(pattern)));
- }
-
- using var pipeStream = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut);
- using var pipe = new TestAdapterPipe(pipeStream);
-
- pipeStream.Connect();
- pipeStream.ReadMode = PipeTransmissionMode.Byte;
-
- var testAdapterReport = new TestAdapterReport(pipe);
-
- var exitCode = ExitCode.Success;
-
- try
- {
- var messageType = pipe.ReceiveMessageType();
-
- if (messageType == typeof(PipeMessage.DiscoverTests).FullName)
- {
- var discoverTests = pipe.Receive();
- await DiscoverMethods(environment, testAdapterReport);
- }
- else if (messageType == typeof(PipeMessage.ExecuteTests).FullName)
- {
- var executeTests = pipe.Receive();
-
- var reports = new IReport[] { testAdapterReport };
-
- exitCode = executeTests.Filter.Length == 0
- ? await Run(environment, reports, async runner => await runner.Run())
- : await Run(environment, reports, async runner => await runner.Run([..executeTests.Filter]));
- }
- else
- {
- var body = pipe.ReceiveMessageBody();
- throw new Exception($"Test assembly received unexpected message of type {messageType}: {body}");
- }
- }
- catch (Exception exception)
- {
- pipe.Send(exception);
- }
- finally
- {
- pipe.Send();
- }
-
- return (int)exitCode;
+ return pattern == null
+ ? (int) await Run(environment, reports, async runner => await runner.Run())
+ : (int) await Run(environment, reports, async runner => await runner.Run(new TestPattern(pattern)));
}
catch (Exception exception)
{
@@ -93,12 +41,6 @@ public static async Task Main(Assembly assembly, string[] customArguments)
}
}
- static async Task DiscoverMethods(TestEnvironment environment, TestAdapterReport testAdapterReport)
- {
- var runner = new Runner(environment, testAdapterReport);
- await runner.Discover();
- }
-
static async Task Run(TestEnvironment environment, IReport[] reports, Func> run)
{
var runner = new Runner(environment, reports);
diff --git a/src/Fixie/Internal/PipeMessage.cs b/src/Fixie/Internal/PipeMessage.cs
deleted file mode 100644
index dea8a91da..000000000
--- a/src/Fixie/Internal/PipeMessage.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Text.Json;
-using Fixie.Reports;
-
-namespace Fixie.Internal;
-
-static class PipeMessage
-{
- public static string Serialize(TMessage message)
- {
- return JsonSerializer.Serialize(message);
- }
-
- public static TMessage Deserialize(string json)
- {
- var message = JsonSerializer.Deserialize(json);
-
- if (message == null)
- throw new System.Exception($"Message of type {typeof(TMessage).FullName} was unexpectedly null.");
-
- return message;
- }
-
- public class DiscoverTests { }
-
- public class ExecuteTests
- {
- public required string[] Filter { get; init; }
- }
-
- public class TestDiscovered
- {
- public required string Test { get; init; }
- }
-
- public class TestStarted
- {
- public required string Test { get; init; }
- }
-
- public abstract class TestCompleted
- {
- public required string Test { get; init; }
- public required string TestCase { get; init; }
- public required double DurationInMilliseconds { get; init; }
- }
-
- public class TestSkipped : TestCompleted
- {
- public required string Reason { get; init; }
- }
-
- public class TestPassed : TestCompleted
- {
- }
-
- public class TestFailed : TestCompleted
- {
- public required Exception Reason { get; init; }
- }
-
- public class Exception
- {
- public Exception()
- {
- }
-
- [SetsRequiredMembers]
- public Exception(System.Exception exception)
- {
- Type = exception.GetType().FullName!;
- Message = exception.Message;
- StackTrace = exception.StackTraceSummary();
- }
-
- public required string Type { get; init; }
- public required string Message { get; init; }
- public required string StackTrace { get; init; }
- }
-
- public class EndOfPipe { }
-}
\ No newline at end of file
diff --git a/src/Fixie/Internal/SourceLocation.cs b/src/Fixie/Internal/SourceLocation.cs
new file mode 100644
index 000000000..440ec7b0c
--- /dev/null
+++ b/src/Fixie/Internal/SourceLocation.cs
@@ -0,0 +1,7 @@
+namespace Fixie.Internal;
+
+class SourceLocation
+{
+ public required string CodeFilePath { get; init; }
+ public required int LineNumber { get; init; }
+}
\ No newline at end of file
diff --git a/src/Fixie.TestAdapter/SourceLocationProvider.cs b/src/Fixie/Internal/SourceLocationProvider.cs
similarity index 95%
rename from src/Fixie.TestAdapter/SourceLocationProvider.cs
rename to src/Fixie/Internal/SourceLocationProvider.cs
index 71c9e63bb..21106aa2e 100644
--- a/src/Fixie.TestAdapter/SourceLocationProvider.cs
+++ b/src/Fixie/Internal/SourceLocationProvider.cs
@@ -4,7 +4,7 @@
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
-namespace Fixie.TestAdapter;
+namespace Fixie.Internal;
class SourceLocationProvider
{
@@ -80,7 +80,11 @@ static Dictionary MethodLocations(TypeDefinition type)
var sequencePoint = FirstOrDefaultSequencePoint(method);
if (sequencePoint != null)
- return new SourceLocation(sequencePoint.Document.Url, sequencePoint.StartLine);
+ return new SourceLocation
+ {
+ CodeFilePath = sequencePoint.Document.Url,
+ LineNumber = sequencePoint.StartLine
+ };
return null;
}
diff --git a/src/Fixie/Internal/TestAdapterPipe.cs b/src/Fixie/Internal/TestAdapterPipe.cs
deleted file mode 100644
index 7ff5b1685..000000000
--- a/src/Fixie/Internal/TestAdapterPipe.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System.IO.Pipes;
-using System.Text;
-
-namespace Fixie.Internal;
-
-class TestAdapterPipe : IDisposable
-{
- readonly StreamReader reader;
- readonly StreamWriter writer;
-
- public TestAdapterPipe(PipeStream pipeStream)
- {
- // Normal attempts to call dispose on this reader
- // and writer cause the underlying PipeStream to
- // throw ObjectDisposedException when the original
- // PipeStream's 'using' block ends. Here we allow
- // the reader and writer to be disposed of, ignoring
- // the PipeStream itself by leaving that open.
- // Then, the original using block for the PipeStream
- // is trusted to own that cleanup.
-
- reader = new StreamReader(pipeStream, leaveOpen: true);
- writer = new StreamWriter(pipeStream, leaveOpen: true);
- }
-
- const string EndOfMessage = "--End of Message--";
-
- public string? ReceiveMessageType()
- {
- return reader.ReadLine();
- }
-
- public TMessage Receive()
- {
- return PipeMessage.Deserialize(ReceiveMessageBody());
- }
-
- public string ReceiveMessageBody()
- {
- var lines = new StringBuilder();
-
- while (true)
- {
- var line = reader.ReadLine();
-
- if (line == null || line == EndOfMessage)
- break;
-
- lines.AppendLine(line);
- }
-
- return lines.ToString();
- }
-
- public void Send() where TMessage: new()
- {
- Send(new TMessage());
- }
-
- public void Send(Exception exception)
- {
- Send(new PipeMessage.Exception(exception));
- }
-
- public void Send(TMessage message)
- {
- var messageType = typeof(TMessage).FullName!;
-
- writer.WriteLine(messageType);
- writer.WriteLine(PipeMessage.Serialize(message));
- writer.WriteLine(EndOfMessage);
- writer.Flush();
- }
-
- public void Dispose()
- {
- reader.Dispose();
- writer.Dispose();
- }
-}
\ No newline at end of file
diff --git a/src/Fixie/InternalsVisibleTo.cs b/src/Fixie/InternalsVisibleTo.cs
index 0cc608e5c..f5102558f 100644
--- a/src/Fixie/InternalsVisibleTo.cs
+++ b/src/Fixie/InternalsVisibleTo.cs
@@ -1,4 +1,3 @@
using System.Runtime.CompilerServices;
-[assembly:InternalsVisibleTo("Fixie.Tests")]
-[assembly:InternalsVisibleTo("Fixie.TestAdapter")]
\ No newline at end of file
+[assembly:InternalsVisibleTo("Fixie.Tests")]
\ No newline at end of file
diff --git a/src/Fixie/Reports/TestAdapterReport.cs b/src/Fixie/Reports/TestAdapterReport.cs
deleted file mode 100644
index f626a720f..000000000
--- a/src/Fixie/Reports/TestAdapterReport.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using Fixie.Internal;
-
-namespace Fixie.Reports;
-
-class TestAdapterReport(TestAdapterPipe pipe) :
- IHandler,
- IHandler,
- IHandler,
- IHandler,
- IHandler
-{
- public Task Handle(TestDiscovered message)
- {
- pipe.Send(new PipeMessage.TestDiscovered
- {
- Test = message.Test
- });
-
- return Task.CompletedTask;
- }
-
- public Task Handle(TestStarted message)
- {
- pipe.Send(new PipeMessage.TestStarted
- {
- Test = message.Test
- });
-
- return Task.CompletedTask;
- }
-
- public Task Handle(TestSkipped message)
- {
- pipe.Send(new PipeMessage.TestSkipped
- {
- Test = message.Test,
- TestCase = message.TestCase,
- DurationInMilliseconds = message.Duration.TotalMilliseconds,
- Reason = message.Reason
- });
-
- return Task.CompletedTask;
- }
-
- public Task Handle(TestPassed message)
- {
- pipe.Send(new PipeMessage.TestPassed
- {
- Test = message.Test,
- TestCase = message.TestCase,
- DurationInMilliseconds = message.Duration.TotalMilliseconds
- });
-
- return Task.CompletedTask;
- }
-
- public Task Handle(TestFailed message)
- {
- pipe.Send(new PipeMessage.TestFailed
- {
- Test = message.Test,
- TestCase = message.TestCase,
- DurationInMilliseconds = message.Duration.TotalMilliseconds,
- Reason = new PipeMessage.Exception(message.Reason)
- });
-
- return Task.CompletedTask;
- }
-}
\ No newline at end of file