diff --git a/api/src/api/TestAdapterReporter.cs b/api/src/api/TestAdapterReporter.cs
index f481103..861bab5 100644
--- a/api/src/api/TestAdapterReporter.cs
+++ b/api/src/api/TestAdapterReporter.cs
@@ -33,6 +33,7 @@ public TestAdapterReporter()
public void Dispose()
{
+ Console.WriteLine("TestAdapterReporter: Disconnecting from GdUnit4 test report server.");
writer?.WriteLine("TestAdapterReporter: Disconnecting from GdUnit4 test report server.");
writer?.Dispose();
client.Dispose();
diff --git a/gdUnit4Net.sln.DotSettings.user b/gdUnit4Net.sln.DotSettings.user
index 837f21c..48075f1 100644
--- a/gdUnit4Net.sln.DotSettings.user
+++ b/gdUnit4Net.sln.DotSettings.user
@@ -1,6 +1,6 @@
True
- <SessionState ContinuousTestingMode="0" IsActive="True" Name="BoolAssertTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
+ <SessionState ContinuousTestingMode="0" IsActive="True" Name="BoolAssertTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
<TestAncestor>
<TestId>VsTest::B97C5043-B4BE-4156-BE0F-FDCBDECA61F6::net8.0::executor://gdunit4.testadapter/#GdUnit4.Tests.Asserts.BoolAssertTest</TestId>
</TestAncestor>
@@ -8,5 +8,14 @@
+
+
+
+
+
+
+
+
+
TRACE
D:\development\workspace\gdUnit4Net\test\.runsettings
\ No newline at end of file
diff --git a/test/project.godot b/test/project.godot
index cc04876..50237ec 100644
--- a/test/project.godot
+++ b/test/project.godot
@@ -11,7 +11,7 @@ config_version=5
[application]
config/name="gdUnit4Test"
-config/features=PackedStringArray("4.2", "4.2.1", "C#", "Forward Plus")
+config/features=PackedStringArray("4.3", "C#", "Forward Plus")
config/icon="res://icon.svg"
[dotnet]
diff --git a/testadapter/src/execution/TestExecutor.cs b/testadapter/src/execution/TestExecutor.cs
index 3fed424..1c03b3d 100644
--- a/testadapter/src/execution/TestExecutor.cs
+++ b/testadapter/src/execution/TestExecutor.cs
@@ -12,6 +12,7 @@ namespace GdUnit4.TestAdapter.Execution;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
+using Microsoft.Win32.SafeHandles;
using Settings;
@@ -34,6 +35,9 @@ public TestExecutor(RunConfiguration configuration, GdUnit4Settings gdUnit4Setti
this.gdUnit4Settings = gdUnit4Settings;
}
+ private object CancelLock { get; } = new();
+ private object ProcessLock { get; } = new();
+
#pragma warning disable IDE0052 // Remove unread private members
private int ParallelTestCount { get; set; }
#pragma warning restore IDE0052 // Remove unread private members
@@ -42,7 +46,7 @@ public TestExecutor(RunConfiguration configuration, GdUnit4Settings gdUnit4Setti
public void Cancel()
{
- lock (this)
+ lock (CancelLock)
{
Console.WriteLine("Cancel triggered");
try
@@ -52,16 +56,13 @@ public void Cancel()
}
catch (Exception)
{
- //frameworkHandle.SendMessage(TestMessageLevel.Error, @$"TestRunner ends with: {e.Message}");
+ //fh.SendMessage(TestMessageLevel.Error, @$"TestRunner ends with: {e.Message}");
}
}
}
public void Dispose()
- {
- pProcess?.Dispose();
- GC.SuppressFinalize(this);
- }
+ => pProcess?.Dispose();
public void Run(IFrameworkHandle frameworkHandle, IRunContext runContext, IReadOnlyList testCases)
{
@@ -85,7 +86,8 @@ public void Run(IFrameworkHandle frameworkHandle, IRunContext runContext, IReadO
var debugArg = runContext.IsBeingDebugged ? "-d" : "";
using var eventServer = new TestEventReportServer();
- Task.Run(() => eventServer.Start(frameworkHandle, testCases));
+ // ReSharper disable once AccessToDisposedClosure
+ var testEventServerTask = Task.Run(() => eventServer.Start(frameworkHandle, testCases));
//var filteredTestCases = filterExpression != null
// ? testCases.FindAll(t => filterExpression.MatchTestCase(t, (propertyName) =>
@@ -94,7 +96,7 @@ public void Run(IFrameworkHandle frameworkHandle, IRunContext runContext, IReadO
// return t.GetPropertyValue(testProperty);
// }) == false)
// : testCases;
- var testRunnerScene = "res://gdunit4_testadapter/TestAdapterRunner.tscn"; //Path.Combine(workingDirectory, @$"{temp_test_runner_dir}/TestRunner.tscn");
+ var testRunnerScene = "res://gdunit4_testadapter/TestAdapterRunner.tscn";
var arguments = $"{debugArg} --path . {testRunnerScene} --testadapter --configfile=\"{configName}\" {gdUnit4Settings.Parameters}";
frameworkHandle.SendMessage(TestMessageLevel.Informational, @$"Run with args {arguments}");
var processStartInfo = new ProcessStartInfo(@$"{GodotBin}", arguments)
@@ -109,30 +111,62 @@ public void Run(IFrameworkHandle frameworkHandle, IRunContext runContext, IReadO
WorkingDirectory = @$"{workingDirectory}"
};
- using (pProcess = new Process { StartInfo = processStartInfo })
- {
- pProcess.EnableRaisingEvents = true;
- pProcess.ErrorDataReceived += StdErrorProcessor(frameworkHandle);
- pProcess.Exited += ExitHandler(frameworkHandle);
- pProcess.Start();
- pProcess.BeginErrorReadLine();
- pProcess.BeginOutputReadLine();
- AttachDebuggerIfNeed(runContext, frameworkHandle, pProcess);
- while (!pProcess.WaitForExit(SessionTimeOut))
- Thread.Sleep(100);
- try
- {
- pProcess.Kill(true);
- frameworkHandle.SendMessage(TestMessageLevel.Informational, @$"Run TestRunner ends with {pProcess.ExitCode}");
- }
- catch (Exception e)
- {
- frameworkHandle.SendMessage(TestMessageLevel.Error, @$"Run TestRunner ends with: {e.Message}");
- }
- finally
+ lock (ProcessLock)
+ if (runContext.IsBeingDebugged && frameworkHandle is IFrameworkHandle2 fh2 && fh2.GetType().ToString().Contains("JetBrains") &&
+ fh2.GetType().Assembly.GetName().Version >= new Version("2.16.1.14"))
{
+ frameworkHandle.SendMessage(TestMessageLevel.Informational, $"JetBrains Rider detected {fh2.GetType().Assembly.GetName().Version}");
+ RunDebugRider(fh2, processStartInfo);
File.Delete(configName);
}
+ else
+ using (pProcess = new Process { StartInfo = processStartInfo })
+ try
+ {
+ pProcess.EnableRaisingEvents = true;
+ pProcess.ErrorDataReceived += StdErrorProcessor(frameworkHandle);
+ pProcess.Exited += ExitHandler(frameworkHandle);
+ pProcess.Start();
+ pProcess.BeginErrorReadLine();
+ pProcess.BeginOutputReadLine();
+ AttachDebuggerIfNeed(runContext, frameworkHandle, pProcess);
+ pProcess.WaitForExit(SessionTimeOut);
+ frameworkHandle.SendMessage(TestMessageLevel.Informational, @$"Run TestRunner ends with {pProcess.ExitCode}");
+ pProcess.Kill(true);
+ }
+ catch (Exception e)
+ {
+ frameworkHandle.SendMessage(TestMessageLevel.Error, @$"Run TestRunner ends with: {e.Message}");
+ }
+ finally { File.Delete(configName); }
+
+ // wait until all event messages are processed or the client is disconnected
+ testEventServerTask.Wait(TimeSpan.FromSeconds(2));
+ }
+
+ private void RunDebugRider(IFrameworkHandle2 fh2, ProcessStartInfo psi)
+ {
+ // EnableShutdownAfterTestRun is not working we need to use SafeHandle the get the process running until the ExitCode is getted
+ fh2.EnableShutdownAfterTestRun = true;
+ Console.WriteLine($"Debug process started {psi.FileName} {psi.WorkingDirectory} {psi.Arguments}");
+ var processId = fh2.LaunchProcessWithDebuggerAttached(psi.FileName, psi.WorkingDirectory, psi.Arguments, psi.Environment);
+ pProcess = Process.GetProcessById(processId);
+ SafeProcessHandle? processHandle = null;
+ try
+ {
+ processHandle = pProcess.SafeHandle;
+ var isExited = pProcess.WaitForExit(SessionTimeOut);
+ // it never exits on macOS ?
+ Console.WriteLine($"Process exited: HasExited: {pProcess.HasExited} {isExited} {processHandle}");
+ // enforce kill the process has also no affect on macOS
+ pProcess.Kill(true);
+ Console.WriteLine($"Process exited: HasExited: {pProcess.HasExited} {processHandle.IsClosed}");
+ // this line fails on macOS, maybe the SafeHandle works only on windows
+ //fh2.SendMessage(TestMessageLevel.Informational, @$"Run TestRunner ends with {pProcess.ExitCode}");
+ }
+ finally
+ {
+ processHandle?.Dispose();
}
}
@@ -141,7 +175,7 @@ private void InstallTestRunnerAndBuild(IFrameworkHandle frameworkHandle, string
var destinationFolderPath = Path.Combine(workingDirectory, @$"{TempTestRunnerDir}");
if (Directory.Exists(destinationFolderPath))
return;
- frameworkHandle.SendMessage(TestMessageLevel.Informational, "Install GdUnit4 TestRunner");
+ frameworkHandle.SendMessage(TestMessageLevel.Informational, $"Installing GdUnit4 `TestRunner` at {destinationFolderPath}...");
InstallTestRunnerClasses(destinationFolderPath);
var processStartInfo = new ProcessStartInfo(@$"{GodotBin}", @"--path . --headless --build-solutions --quit-after 20")
{
@@ -162,11 +196,11 @@ private void InstallTestRunnerAndBuild(IFrameworkHandle frameworkHandle, string
try
{
process.Kill(true);
- frameworkHandle.SendMessage(TestMessageLevel.Informational, $"TestRunner installed: {process.ExitCode}");
+ frameworkHandle.SendMessage(TestMessageLevel.Informational, $"GdUnit4 `TestRunner` successfully installed: {process.ExitCode}");
}
catch (Exception e)
{
- frameworkHandle.SendMessage(TestMessageLevel.Error, @$"TestRunner ends with: {e.Message}");
+ frameworkHandle.SendMessage(TestMessageLevel.Error, @$"Install GdUnit4 `TestRunner` ends with: {e.Message}");
}
}