From f1984d4045a3e19365d6ca80eb7dc8fe497ab784 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 15:30:25 +0200 Subject: [PATCH 01/35] Gitignore the .godot dir --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2cbc103..a76f38e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ +.godot *.user *.userosscache *.sln.docstates From c324509993c624969ff5936817203f744ba1c5ae Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 15:31:16 +0200 Subject: [PATCH 02/35] Godot 4 auto-upgrade Opened the project in godot 4.1 and allowed the auto upgrade to do its thing. --- GodotXUnit.csproj | 2 +- addons/GodotXUnit/GodotTestRunner.cs | 2 +- addons/GodotXUnit/GodotXUnitApi/GDI.cs | 4 +- addons/GodotXUnit/GodotXUnitApi/GDU.cs | 2 +- .../GodotXUnitApi/GodotFactAttribute.cs | 2 +- .../GodotXUnitApi/GodotXUnitApi.csproj | 2 +- .../GodotXUnitApi/GodotXUnitEvents.cs | 8 +- .../GodotXUnitApi/Internal/Consts.cs | 8 +- .../Internal/GodotFactDiscoverer.cs | 2 +- .../GodotXUnitApi/Internal/GodotTestCase.cs | 12 +- .../Internal/GodotTestOutputHelper.cs | 2 +- .../Internal/GodotXUnitRunnerBase.cs | 8 +- .../GodotXUnitApi/Internal/MessagePassing.cs | 6 +- .../GodotXUnitApi/Internal/ProjectListing.cs | 18 +- .../GodotXUnitApi/Internal/WorkFiles.cs | 2 +- addons/GodotXUnit/Plugin.cs | 6 +- addons/GodotXUnit/XUnitDock.cs | 18 +- addons/GodotXUnit/XUnitDock.tscn | 240 +++++++++--------- .../runner/RiderTestRunner/Runner.cs | 2 +- .../runner/RiderTestRunner/Runner.tscn | 10 +- default_env.tres | 2 +- project.godot | 7 +- test_scenes/AVerySpecialBall.cs | 2 +- test_scenes/ClickButtonThing.cs | 2 +- test_scenes/ClickTestScene.tscn | 8 +- test_scenes/PhysicsCollisionTest.tscn | 8 +- test_scenes/SomeTestSceneRoot.cs | 2 +- tests/ClickTest.cs | 2 +- tests/DebugDrawingTest.cs | 2 +- tests/PhysicsCollisionTest.cs | 2 +- tests/SomeBasicTests.cs | 2 +- tests/SomePrintStatementsTest.cs | 2 +- tests/SomeTestSceneTest.cs | 2 +- .../RealFailingTests.cs | 2 +- .../SomeIntegrationTest.cs | 4 +- .../SubProjectForIntegrationTests.csproj | 2 +- .../SubProjectForUnitTests.csproj | 2 +- .../UnitTestWithoutGodot.cs | 4 +- tests/TestInGodotCycle.cs | 2 +- tests/TestInGodotTree.cs | 2 +- tests/TestWithSetup.cs | 2 +- 41 files changed, 210 insertions(+), 209 deletions(-) diff --git a/GodotXUnit.csproj b/GodotXUnit.csproj index 6e3b172..0bc6ce6 100644 --- a/GodotXUnit.csproj +++ b/GodotXUnit.csproj @@ -1,4 +1,4 @@ - + {B6A000AB-04AE-4D1E-A0D5-93911E363F6D} Library diff --git a/addons/GodotXUnit/GodotTestRunner.cs b/addons/GodotXUnit/GodotTestRunner.cs index 05b4883..66f8e15 100644 --- a/addons/GodotXUnit/GodotTestRunner.cs +++ b/addons/GodotXUnit/GodotTestRunner.cs @@ -2,7 +2,7 @@ namespace GodotXUnit { - public class GodotTestRunner : GodotXUnitRunnerBase + public partial class GodotTestRunner : GodotXUnitRunnerBase { } diff --git a/addons/GodotXUnit/GodotXUnitApi/GDI.cs b/addons/GodotXUnit/GodotXUnitApi/GDI.cs index 9563779..dc454a6 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDI.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDI.cs @@ -14,7 +14,7 @@ public static class GDI /// public static float PositionXByScreenPercent(float percent) { - return GDU.Viewport.Size.x * percent; + return GDU.SubViewport.Size.x * percent; } /// @@ -22,7 +22,7 @@ public static float PositionXByScreenPercent(float percent) /// public static float PositionYByScreenPercent(float percent) { - return GDU.Viewport.Size.y * percent; + return GDU.SubViewport.Size.y * percent; } /// diff --git a/addons/GodotXUnit/GodotXUnitApi/GDU.cs b/addons/GodotXUnit/GodotXUnitApi/GDU.cs index 06c189b..6d2d32f 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDU.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDU.cs @@ -41,7 +41,7 @@ public static Node2D Instance public static SceneTree Tree => Instance.GetTree(); - public static Viewport Viewport => Instance.GetViewport(); + public static SubViewport SubViewport => Instance.GetViewport(); public static Node CurrentScene => Instance.GetTree().CurrentScene; diff --git a/addons/GodotXUnit/GodotXUnitApi/GodotFactAttribute.cs b/addons/GodotXUnit/GodotXUnitApi/GodotFactAttribute.cs index 03eed85..c0548f8 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GodotFactAttribute.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GodotFactAttribute.cs @@ -47,7 +47,7 @@ public void IsInPhysicsProcess() */ [XunitTestCaseDiscoverer("GodotXUnitApi.Internal.GodotFactDiscoverer", "GodotXUnitApi")] // ReSharper disable once ClassWithVirtualMembersNeverInherited.Global - public class GodotFactAttribute : FactAttribute + public partial class GodotFactAttribute : FactAttribute { /// /// loads the given scene before the test starts and loads an empty scene after diff --git a/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj b/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj index 80adf19..d24f757 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj +++ b/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj @@ -1,4 +1,4 @@ - + 1.0.0 rexfleischer diff --git a/addons/GodotXUnit/GodotXUnitApi/GodotXUnitEvents.cs b/addons/GodotXUnit/GodotXUnitApi/GodotXUnitEvents.cs index 6d7e52e..b91e03d 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GodotXUnitEvents.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GodotXUnitEvents.cs @@ -5,7 +5,7 @@ namespace GodotXUnitApi { [Serializable] - public class GodotXUnitSummary + public partial class GodotXUnitSummary { public int testsDiscovered; public int testsExpectedToRun; @@ -83,7 +83,7 @@ public GodotXUnitOtherDiagnostic AddDiagnostic(string message) } [Serializable] - public class GodotXUnitTestResult + public partial class GodotXUnitTestResult { public string testCaseClass; public string testCaseName; @@ -98,14 +98,14 @@ public class GodotXUnitTestResult } [Serializable] - public class GodotXUnitTestStart + public partial class GodotXUnitTestStart { public string testCaseClass; public string testCaseName; } [Serializable] - public class GodotXUnitOtherDiagnostic + public partial class GodotXUnitOtherDiagnostic { public string message; public string exceptionType; diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/Consts.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/Consts.cs index a189795..777339e 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/Consts.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/Consts.cs @@ -66,9 +66,9 @@ public static class Consts public const string ICON_CHECK = "res://addons/GodotXUnit/assets/check.png"; public const string ICON_ERROR = "res://addons/GodotXUnit/assets/error.png"; - public static Texture IconRunning => GD.Load(ICON_RUNNING); - public static Texture IconWarn => GD.Load(ICON_WARN); - public static Texture IconCheck => GD.Load(ICON_CHECK); - public static Texture IconError => GD.Load(ICON_ERROR); + public static Texture2D IconRunning => GD.Load(ICON_RUNNING); + public static Texture2D IconWarn => GD.Load(ICON_WARN); + public static Texture2D IconCheck => GD.Load(ICON_CHECK); + public static Texture2D IconError => GD.Load(ICON_ERROR); } } \ No newline at end of file diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotFactDiscoverer.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotFactDiscoverer.cs index 44ae191..94bd1ee 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotFactDiscoverer.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotFactDiscoverer.cs @@ -4,7 +4,7 @@ namespace GodotXUnitApi.Internal { - public class GodotFactDiscoverer : IXunitTestCaseDiscoverer + public partial class GodotFactDiscoverer : IXunitTestCaseDiscoverer { private readonly IMessageSink diagnosticMessageSink; diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs index d4b5cf8..e8df4f7 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs @@ -10,7 +10,7 @@ namespace GodotXUnitApi.Internal { - public class GodotTestCase : XunitTestCase + public partial class GodotTestCase : XunitTestCase { private IAttributeInfo attribute; @@ -51,7 +51,7 @@ public override async Task RunAsync(IMessageSink diagnosticMessageSi } } - public class GodotTestCaseRunner : XunitTestCaseRunner + public partial class GodotTestCaseRunner : XunitTestCaseRunner { private IAttributeInfo attribute; @@ -102,7 +102,7 @@ protected override XunitTestRunner CreateTestRunner( } } - public class GodotTestRunner : XunitTestRunner + public partial class GodotTestRunner : XunitTestRunner { private IAttributeInfo attribute; @@ -166,7 +166,7 @@ protected override Task InvokeTestMethodAsync(ExceptionAggregator aggre } } - public class GodotTestInvoker : XunitTestInvoker + public partial class GodotTestInvoker : XunitTestInvoker { private IAttributeInfo attribute; @@ -213,7 +213,7 @@ protected override async Task BeforeTestMethodInvokedAsync() { // you must be in the process frame to await GDU.OnProcessAwaiter; - if (GDU.Instance.GetTree().ChangeScene(sceneCheck) != Error.Ok) + if (GDU.Instance.GetTree().ChangeSceneToFile(sceneCheck) != Error.Ok) { Aggregator.Add(new Exception($"could not load scene: {sceneCheck}")); return; @@ -270,7 +270,7 @@ protected override async Task AfterTestMethodInvokedAsync() if (loadEmptyScene) { // change scenes again and wait for godot to catch up - GDU.Instance.GetTree().ChangeScene(Consts.EMPTY_SCENE_PATH); + GDU.Instance.GetTree().ChangeSceneToFile(Consts.EMPTY_SCENE_PATH); await GDU.OnIdleFrameAwaiter; await GDU.OnIdleFrameAwaiter; await GDU.OnProcessAwaiter; diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestOutputHelper.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestOutputHelper.cs index d5c7ca6..09a6301 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestOutputHelper.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestOutputHelper.cs @@ -20,7 +20,7 @@ namespace GodotXUnitApi.Internal /// handed in with our own because it breaks compatibility with /// IDE runners. /// - public class GodotTestOutputHelper : TextWriter + public partial class GodotTestOutputHelper : TextWriter { private TestOutputHelper wrapping; private TextWriter oldOutput; diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index 4237af4..31b5728 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -4,8 +4,8 @@ using Godot; using Newtonsoft.Json; using Xunit.Runners; -using Path = System.IO.Path; -using Directory = System.IO.Directory; +using Path3D = System.IO.Path3D; +using DirAccess = System.IO.DirAccess; namespace GodotXUnitApi.Internal { @@ -49,8 +49,8 @@ protected virtual Assembly GetTargetAssembly(GodotXUnitSummary summary) } // finally, attempt to load project.. - var currentDir = Directory.GetCurrentDirectory(); - var targetAssembly = Path.Combine(currentDir, $".mono/build/bin/Debug/{targetProject}.dll"); + var currentDir = DirAccess.GetCurrentDirectory(); + var targetAssembly = Path3D.Combine(currentDir, $".mono/build/bin/Debug/{targetProject}.dll"); var name = AssemblyName.GetAssemblyName(targetAssembly); return AppDomain.CurrentDomain.Load(name); } diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/MessagePassing.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/MessagePassing.cs index da3ab00..ee38fe2 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/MessagePassing.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/MessagePassing.cs @@ -2,7 +2,7 @@ namespace GodotXUnitApi.Internal { - public class MessageSender + public partial class MessageSender { public int idAt { get; private set; } @@ -17,9 +17,9 @@ public void SendMessage(object message, string type) } } - public class MessageWatcher + public partial class MessageWatcher { - private Directory directory = new Directory(); + private DirAccess directory = new DirAccess(); public object Poll() { diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs index 5090902..2c6ee00 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs @@ -7,7 +7,7 @@ namespace GodotXUnitApi.Internal { public static class ProjectListing { - public static readonly string sep = Path.DirectorySeparatorChar.ToString(); + public static readonly string sep = Path3D.DirectorySeparatorChar.ToString(); private static string _projectDir; @@ -17,7 +17,7 @@ public static string ProjectDir { if (!string.IsNullOrEmpty(_projectDir)) return _projectDir; - var current = Directory.GetCurrentDirectory(); + var current = DirAccess.GetCurrentDirectory(); while (!string.IsNullOrEmpty(current)) { if (File.Exists($"{current}{sep}project.godot")) @@ -25,7 +25,7 @@ public static string ProjectDir _projectDir = current; return _projectDir; } - current = Directory.GetParent(current).FullName; + current = DirAccess.GetParent(current).FullName; } GodotGD.PrintErr("unable to find root of godot project"); throw new Exception("unable to find root dir"); @@ -38,11 +38,11 @@ public static string ProjectDir public static List GetProjectList() { var result = new List(); - foreach (var filename in Directory.GetFiles(ProjectDir, "*.csproj", SearchOption.AllDirectories)) + foreach (var filename in DirAccess.GetFiles(ProjectDir, "*.csproj", SearchOption.AllDirectories)) { if (filename.Contains("GodotXUnitApi")) continue; - result.Add(Path.GetFileNameWithoutExtension(filename)); + result.Add(Path3D.GetFileNameWithoutExtension(filename)); } return result; } @@ -50,18 +50,18 @@ public static List GetProjectList() public static Dictionary GetProjectInfo() { var result = new Dictionary(); - foreach (var filename in Directory.GetFiles(ProjectDir, "*.csproj", SearchOption.AllDirectories)) + foreach (var filename in DirAccess.GetFiles(ProjectDir, "*.csproj", SearchOption.AllDirectories)) { if (filename.Contains("GodotXUnitApi")) continue; - result[Path.GetFileNameWithoutExtension(filename)] = filename; + result[Path3D.GetFileNameWithoutExtension(filename)] = filename; } return result; } public static string GetDefaultProject() { - var project = Directory.GetFiles(ProjectDir, "*.csproj", SearchOption.TopDirectoryOnly); + var project = DirAccess.GetFiles(ProjectDir, "*.csproj", SearchOption.TopDirectoryOnly); if (project.Length == 0) { GodotGD.PrintErr($"no csproj found on project root at {ProjectDir}. is this a mono project?"); @@ -72,7 +72,7 @@ public static string GetDefaultProject() GodotGD.PrintErr($"multiple csproj found on project root at {ProjectDir}."); return ""; } - return Path.GetFileNameWithoutExtension(project[0]); + return Path3D.GetFileNameWithoutExtension(project[0]); } } } \ No newline at end of file diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/WorkFiles.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/WorkFiles.cs index 964d680..f0301ae 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/WorkFiles.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/WorkFiles.cs @@ -21,7 +21,7 @@ public static string PathForResFile(string filename) public static void CleanWorkDir() { - var directory = new Godot.Directory(); + var directory = new Godot.DirAccess(); directory.MakeDirRecursive(WorkDir).ThrowIfNotOk(); directory.Open(WorkDir).ThrowIfNotOk(); directory.ListDirBegin(true, true).ThrowIfNotOk(); diff --git a/addons/GodotXUnit/Plugin.cs b/addons/GodotXUnit/Plugin.cs index f2ae7fe..f1cc007 100644 --- a/addons/GodotXUnit/Plugin.cs +++ b/addons/GodotXUnit/Plugin.cs @@ -6,7 +6,7 @@ namespace GodotXUnit { [Tool] - public class Plugin : EditorPlugin + public partial class Plugin : EditorPlugin { private static Plugin _instance; @@ -14,7 +14,7 @@ public class Plugin : EditorPlugin private XUnitDock dock; - public override string GetPluginName() + public override string _GetPluginName() { return nameof(GodotXUnit); } @@ -28,7 +28,7 @@ public override void _EnterTree() EnsureProjectSetting(Consts.SETTING_TARGET_CLASS_PROP); EnsureProjectSetting(Consts.SETTING_TARGET_METHOD_PROP); dock = (XUnitDock) GD.Load(Consts.DOCK_SCENE_PATH).Instance(); - AddControlToBottomPanel(dock, GetPluginName()); + AddControlToBottomPanel(dock, _GetPluginName()); } public override void _ExitTree() diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index b00bf49..f452077 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -11,7 +11,7 @@ namespace GodotXUnit { [Tool] - public class XUnitDock : MarginContainer + public partial class XUnitDock : MarginContainer { private RichTextLabel resultDetails; private RichTextLabel resultDiagnostics; @@ -51,29 +51,29 @@ public override void _Ready() ResetLabels(); stopButton = (Button) FindNode("StopButton"); - stopButton.Connect("pressed", this, nameof(StopTests)); + stopButton.Connect("pressed", new Callable(this, nameof(StopTests))); runAllButton = (Button) FindNode("RunAllTestsButton"); - runAllButton.Connect("pressed", this, nameof(RunAllTests)); + runAllButton.Connect("pressed", new Callable(this, nameof(RunAllTests))); reRunButton = (Button) FindNode("ReRunButton"); - reRunButton.Connect("pressed", this, nameof(ReRunTests)); + reRunButton.Connect("pressed", new Callable(this, nameof(ReRunTests))); targetClassLabel = (LineEdit) FindNode("TargetClassLabel"); targetMethodLabel = (LineEdit) FindNode("TargetMethodLabel"); runSelectedButton = (Button) FindNode("RunSelectedButton"); - runSelectedButton.Connect("pressed", this, nameof(RunSelected)); + runSelectedButton.Connect("pressed", new Callable(this, nameof(RunSelected))); runSelectedButton.Disabled = true; targetAssemblyOption = (OptionButton) FindNode("TargetAssemblyOption"); - targetAssemblyOption.Connect("pressed", this, nameof(TargetAssemblyOptionPressed)); - targetAssemblyOption.Connect("item_selected", this, nameof(TargetAssemblyOptionSelected)); + targetAssemblyOption.Connect("pressed", new Callable(this, nameof(TargetAssemblyOptionPressed))); + targetAssemblyOption.Connect("item_selected", new Callable(this, nameof(TargetAssemblyOptionSelected))); targetAssemblyLabel = (LineEdit) FindNode("TargetAssemblyLabel"); targetAssemblyLabel.Text = ProjectSettings.HasSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM) ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM).ToString() : ""; - targetAssemblyLabel.Connect("text_changed", this, nameof(TargetAssemblyLabelChanged)); + targetAssemblyLabel.Connect("text_changed", new Callable(this, nameof(TargetAssemblyLabelChanged))); TargetAssemblyOptionPressed(); resultsTree = (Tree) FindNode("ResultsTree"); resultsTree.HideRoot = true; resultsTree.SelectMode = Tree.SelectModeEnum.Single; - resultsTree.Connect("cell_selected", this, nameof(OnCellSelected)); + resultsTree.Connect("cell_selected", new Callable(this, nameof(OnCellSelected))); resultDetails = (RichTextLabel) FindNode("ResultDetails"); resultDiagnostics = (RichTextLabel) FindNode("Diagnostics"); verboseCheck = (CheckBox) FindNode("VerboseCheckBox"); diff --git a/addons/GodotXUnit/XUnitDock.tscn b/addons/GodotXUnit/XUnitDock.tscn index 052950a..81a6cef 100644 --- a/addons/GodotXUnit/XUnitDock.tscn +++ b/addons/GodotXUnit/XUnitDock.tscn @@ -5,236 +5,236 @@ [node name="Control" type="MarginContainer"] anchor_right = 1.0 anchor_bottom = 1.0 -custom_constants/margin_right = 0 -custom_constants/margin_top = 0 -custom_constants/margin_left = 0 -custom_constants/margin_bottom = 0 +theme_override_constants/margin_right = 0 +theme_override_constants/margin_top = 0 +theme_override_constants/margin_left = 0 +theme_override_constants/margin_bottom = 0 script = ExtResource( 1 ) __meta__ = { "_edit_use_anchors_": false } [node name="Rows" type="VBoxContainer" parent="."] -margin_right = 1024.0 -margin_bottom = 600.0 +offset_right = 1024.0 +offset_bottom = 600.0 [node name="Buttons" type="MarginContainer" parent="Rows"] -margin_right = 1024.0 -margin_bottom = 44.0 -custom_constants/margin_right = 5 -custom_constants/margin_top = 5 -custom_constants/margin_left = 5 -custom_constants/margin_bottom = 5 +offset_right = 1024.0 +offset_bottom = 44.0 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_bottom = 5 [node name="Panel" type="Panel" parent="Rows/Buttons"] -margin_left = 5.0 -margin_top = 5.0 -margin_right = 1019.0 -margin_bottom = 39.0 +offset_left = 5.0 +offset_top = 5.0 +offset_right = 1019.0 +offset_bottom = 39.0 __meta__ = { "_edit_use_anchors_": false } [node name="Margin" type="MarginContainer" parent="Rows/Buttons"] -margin_left = 5.0 -margin_top = 5.0 -margin_right = 1019.0 -margin_bottom = 39.0 -custom_constants/margin_right = 5 -custom_constants/margin_top = 5 -custom_constants/margin_left = 5 -custom_constants/margin_bottom = 5 +offset_left = 5.0 +offset_top = 5.0 +offset_right = 1019.0 +offset_bottom = 39.0 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_bottom = 5 [node name="Buttons" type="HBoxContainer" parent="Rows/Buttons/Margin"] -margin_left = 5.0 -margin_top = 5.0 -margin_right = 1009.0 -margin_bottom = 29.0 +offset_left = 5.0 +offset_top = 5.0 +offset_right = 1009.0 +offset_bottom = 29.0 __meta__ = { "_edit_use_anchors_": false } [node name="StopButton" type="Button" parent="Rows/Buttons/Margin/Buttons"] -margin_right = 40.0 -margin_bottom = 24.0 +offset_right = 40.0 +offset_bottom = 24.0 text = "Stop" [node name="RunAllTestsButton" type="Button" parent="Rows/Buttons/Margin/Buttons"] -margin_left = 44.0 -margin_right = 139.0 -margin_bottom = 24.0 +offset_left = 44.0 +offset_right = 139.0 +offset_bottom = 24.0 text = "Run All Tests" [node name="ReRunButton" type="Button" parent="Rows/Buttons/Margin/Buttons"] -margin_left = 143.0 -margin_right = 195.0 -margin_bottom = 24.0 +offset_left = 143.0 +offset_right = 195.0 +offset_bottom = 24.0 text = "ReRun" [node name="TargetClassLabel" type="LineEdit" parent="Rows/Buttons/Margin/Buttons"] -margin_left = 199.0 -margin_right = 389.0 -margin_bottom = 24.0 +offset_left = 199.0 +offset_right = 389.0 +offset_bottom = 24.0 size_flags_horizontal = 3 placeholder_text = "Target Class" [node name="TargetMethodLabel" type="LineEdit" parent="Rows/Buttons/Margin/Buttons"] -margin_left = 393.0 -margin_right = 583.0 -margin_bottom = 24.0 +offset_left = 393.0 +offset_right = 583.0 +offset_bottom = 24.0 size_flags_horizontal = 3 placeholder_text = "Target Method" [node name="TargetAssemblyOption" type="OptionButton" parent="Rows/Buttons/Margin/Buttons"] -margin_left = 587.0 -margin_right = 808.0 -margin_bottom = 24.0 +offset_left = 587.0 +offset_right = 808.0 +offset_bottom = 24.0 size_flags_horizontal = 3 text = "SubProjectForIntegrationTests" items = [ "GodotXUnit (main)", null, false, 0, null, "SubProjectForUnitTests", null, false, 1, null, "SubProjectForIntegrationTests", null, false, 2, null, "Custom Location ", null, false, 1000, null ] selected = 2 [node name="TargetAssemblyLabel" type="LineEdit" parent="Rows/Buttons/Margin/Buttons"] -margin_left = 812.0 -margin_right = 1004.0 -margin_bottom = 24.0 +offset_left = 812.0 +offset_right = 1004.0 +offset_bottom = 24.0 size_flags_horizontal = 3 text = "not found" -placeholder_text = "Custom Assembly Path (dll)" +placeholder_text = "Custom Assembly Path3D (dll)" __meta__ = { "_editor_description_": "" } [node name="Summary" type="MarginContainer" parent="Rows"] -margin_top = 48.0 -margin_right = 1024.0 -margin_bottom = 92.0 -custom_constants/margin_right = 5 -custom_constants/margin_top = 5 -custom_constants/margin_left = 5 -custom_constants/margin_bottom = 5 +offset_top = 48.0 +offset_right = 1024.0 +offset_bottom = 92.0 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_bottom = 5 [node name="Panel" type="Panel" parent="Rows/Summary"] -margin_left = 5.0 -margin_top = 5.0 -margin_right = 1019.0 -margin_bottom = 39.0 +offset_left = 5.0 +offset_top = 5.0 +offset_right = 1019.0 +offset_bottom = 39.0 __meta__ = { "_edit_use_anchors_": false } [node name="Margin" type="MarginContainer" parent="Rows/Summary"] -margin_left = 5.0 -margin_top = 5.0 -margin_right = 1019.0 -margin_bottom = 39.0 -custom_constants/margin_right = 5 -custom_constants/margin_top = 5 -custom_constants/margin_left = 5 -custom_constants/margin_bottom = 5 +offset_left = 5.0 +offset_top = 5.0 +offset_right = 1019.0 +offset_bottom = 39.0 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_bottom = 5 [node name="Results" type="HBoxContainer" parent="Rows/Summary/Margin"] -margin_left = 5.0 -margin_top = 5.0 -margin_right = 1009.0 -margin_bottom = 29.0 +offset_left = 5.0 +offset_top = 5.0 +offset_right = 1009.0 +offset_bottom = 29.0 __meta__ = { "_edit_use_anchors_": false } [node name="TotalRanLabel" type="Label" parent="Rows/Summary/Margin/Results"] -margin_top = 5.0 -margin_right = 227.0 -margin_bottom = 19.0 +offset_top = 5.0 +offset_right = 227.0 +offset_bottom = 19.0 size_flags_horizontal = 3 text = "TotalRan: 0" [node name="PassedLabel" type="Label" parent="Rows/Summary/Margin/Results"] -margin_left = 231.0 -margin_top = 5.0 -margin_right = 458.0 -margin_bottom = 19.0 +offset_left = 231.0 +offset_top = 5.0 +offset_right = 458.0 +offset_bottom = 19.0 size_flags_horizontal = 3 text = "Passed: 0" [node name="FailedLabel" type="Label" parent="Rows/Summary/Margin/Results"] -margin_left = 462.0 -margin_right = 689.0 -margin_bottom = 24.0 +offset_left = 462.0 +offset_right = 689.0 +offset_bottom = 24.0 size_flags_horizontal = 3 size_flags_vertical = 1 text = "Failed: 0" [node name="TimeLabel" type="Label" parent="Rows/Summary/Margin/Results"] -margin_left = 693.0 -margin_top = 5.0 -margin_right = 920.0 -margin_bottom = 19.0 +offset_left = 693.0 +offset_top = 5.0 +offset_right = 920.0 +offset_bottom = 19.0 size_flags_horizontal = 3 text = "Time: 0 ms" [node name="VerboseCheckBox" type="CheckBox" parent="Rows/Summary/Margin/Results"] -margin_left = 924.0 -margin_right = 1004.0 -margin_bottom = 24.0 +offset_left = 924.0 +offset_right = 1004.0 +offset_bottom = 24.0 text = "Verbose" [node name="Details" type="MarginContainer" parent="Rows"] -margin_top = 96.0 -margin_right = 1024.0 -margin_bottom = 600.0 +offset_top = 96.0 +offset_right = 1024.0 +offset_bottom = 600.0 size_flags_horizontal = 3 size_flags_vertical = 3 -custom_constants/margin_right = 5 -custom_constants/margin_top = 5 -custom_constants/margin_left = 5 -custom_constants/margin_bottom = 5 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_bottom = 5 [node name="HBoxContainer" type="HBoxContainer" parent="Rows/Details"] -margin_left = 5.0 -margin_top = 5.0 -margin_right = 1019.0 -margin_bottom = 499.0 +offset_left = 5.0 +offset_top = 5.0 +offset_right = 1019.0 +offset_bottom = 499.0 [node name="ResultsTree" type="Tree" parent="Rows/Details/HBoxContainer"] -margin_right = 505.0 -margin_bottom = 494.0 +offset_right = 505.0 +offset_bottom = 494.0 size_flags_horizontal = 3 size_flags_vertical = 3 hide_root = true [node name="VBoxContainer" type="VBoxContainer" parent="Rows/Details/HBoxContainer"] -margin_left = 509.0 -margin_right = 1014.0 -margin_bottom = 494.0 +offset_left = 509.0 +offset_right = 1014.0 +offset_bottom = 494.0 size_flags_horizontal = 3 size_flags_vertical = 3 [node name="HBoxContainer" type="HBoxContainer" parent="Rows/Details/HBoxContainer/VBoxContainer"] -margin_right = 505.0 -margin_bottom = 20.0 +offset_right = 505.0 +offset_bottom = 20.0 size_flags_horizontal = 3 [node name="RunSelectedButton" type="Button" parent="Rows/Details/HBoxContainer/VBoxContainer/HBoxContainer"] -margin_right = 95.0 -margin_bottom = 20.0 +offset_right = 95.0 +offset_bottom = 20.0 disabled = true text = "Run Selected" [node name="RunTabContainer" type="TabContainer" parent="Rows/Details/HBoxContainer/VBoxContainer"] -margin_top = 24.0 -margin_right = 505.0 -margin_bottom = 494.0 +offset_top = 24.0 +offset_right = 505.0 +offset_bottom = 494.0 size_flags_horizontal = 3 size_flags_vertical = 3 [node name="ResultDetails" type="RichTextLabel" parent="Rows/Details/HBoxContainer/VBoxContainer/RunTabContainer"] anchor_right = 1.0 anchor_bottom = 1.0 -margin_left = 4.0 -margin_top = 32.0 -margin_right = -4.0 -margin_bottom = -4.0 +offset_left = 4.0 +offset_top = 32.0 +offset_right = -4.0 +offset_bottom = -4.0 focus_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -244,10 +244,10 @@ selection_enabled = true visible = false anchor_right = 1.0 anchor_bottom = 1.0 -margin_left = 4.0 -margin_top = 32.0 -margin_right = -4.0 -margin_bottom = -4.0 +offset_left = 4.0 +offset_top = 32.0 +offset_right = -4.0 +offset_bottom = -4.0 focus_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 diff --git a/addons/GodotXUnit/runner/RiderTestRunner/Runner.cs b/addons/GodotXUnit/runner/RiderTestRunner/Runner.cs index 26f1cb8..ba73245 100644 --- a/addons/GodotXUnit/runner/RiderTestRunner/Runner.cs +++ b/addons/GodotXUnit/runner/RiderTestRunner/Runner.cs @@ -10,7 +10,7 @@ namespace RiderTestRunner { // ReSharper disable once UnusedType.Global - public class Runner : GodotXUnitRunnerBase // for GodotXUnit use: public class Runner : GodotTestRunner. https://github.com/fledware/GodotXUnit/issues/8#issuecomment-929849478 + public partial class Runner : GodotXUnitRunnerBase // for GodotXUnit use: public partial class Runner : GodotTestRunner. https://github.com/fledware/GodotXUnit/issues/8#issuecomment-929849478 { public override void _Ready() { diff --git a/addons/GodotXUnit/runner/RiderTestRunner/Runner.tscn b/addons/GodotXUnit/runner/RiderTestRunner/Runner.tscn index 9d9835f..3a3506f 100644 --- a/addons/GodotXUnit/runner/RiderTestRunner/Runner.tscn +++ b/addons/GodotXUnit/runner/RiderTestRunner/Runner.tscn @@ -6,11 +6,11 @@ script = ExtResource( 1 ) [node name="RichTextLabel" type="RichTextLabel" parent="."] -margin_left = 10.0 -margin_top = 10.0 -margin_right = 500.0 -margin_bottom = 200.0 -rect_scale = Vector2( 2, 2 ) +offset_left = 10.0 +offset_top = 10.0 +offset_right = 500.0 +offset_bottom = 200.0 +scale = Vector2( 2, 2 ) text = "Running" __meta__ = { "_edit_use_anchors_": false diff --git a/default_env.tres b/default_env.tres index 20207a4..1a5570b 100644 --- a/default_env.tres +++ b/default_env.tres @@ -1,6 +1,6 @@ [gd_resource type="Environment" load_steps=2 format=2] -[sub_resource type="ProceduralSky" id=1] +[sub_resource type="Sky" id=1] [resource] background_mode = 2 diff --git a/project.godot b/project.godot index 3920268..41eb108 100644 --- a/project.godot +++ b/project.godot @@ -1,3 +1,4 @@ +; Project was converted by built-in tool to Godot 4.0 ; Engine configuration file. ; It's best edited using the editor UI and not directly, ; since the parameters that go here are not all obvious. @@ -6,7 +7,7 @@ ; [section] ; section goes between [] ; param=value ; assign values to parameters -config_version=4 +config_version=5 _global_script_classes=[ ] _global_script_class_icons={ @@ -26,7 +27,7 @@ config/icon="res://icon.png" [editor_plugins] -enabled=PoolStringArray( "GodotXUnit" ) +enabled=PackedStringArray( "GodotXUnit" ) [mono] @@ -34,4 +35,4 @@ export/aot/enabled=true [rendering] -environment/default_environment="res://default_env.tres" +environment/defaults/default_environment="res://default_env.tres" diff --git a/test_scenes/AVerySpecialBall.cs b/test_scenes/AVerySpecialBall.cs index a2a8eae..059f1c6 100644 --- a/test_scenes/AVerySpecialBall.cs +++ b/test_scenes/AVerySpecialBall.cs @@ -2,7 +2,7 @@ namespace GodotXUnitTest { - public class AVerySpecialBall : KinematicBody2D + public partial class AVerySpecialBall : CharacterBody2D { [Signal] public delegate void WeCollidedd(); diff --git a/test_scenes/ClickButtonThing.cs b/test_scenes/ClickButtonThing.cs index a236482..6c395bd 100644 --- a/test_scenes/ClickButtonThing.cs +++ b/test_scenes/ClickButtonThing.cs @@ -2,7 +2,7 @@ namespace GodotXUnitTest { - public class ClickButtonThing : CheckBox + public partial class ClickButtonThing : CheckBox { public override void _UnhandledInput(InputEvent inputEvent) { diff --git a/test_scenes/ClickTestScene.tscn b/test_scenes/ClickTestScene.tscn index 3f322c1..6fd1f0f 100644 --- a/test_scenes/ClickTestScene.tscn +++ b/test_scenes/ClickTestScene.tscn @@ -14,9 +14,9 @@ anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 -margin_left = -58.5 -margin_top = -12.0 -margin_right = 58.5 -margin_bottom = 12.0 +offset_left = -58.5 +offset_top = -12.0 +offset_right = 58.5 +offset_bottom = 12.0 text = "ImAButton" script = ExtResource( 1 ) diff --git a/test_scenes/PhysicsCollisionTest.tscn b/test_scenes/PhysicsCollisionTest.tscn index c6fc2b7..b4e304c 100644 --- a/test_scenes/PhysicsCollisionTest.tscn +++ b/test_scenes/PhysicsCollisionTest.tscn @@ -1,10 +1,10 @@ [gd_scene load_steps=5 format=2] -[ext_resource path="res://icon.png" type="Texture" id=1] +[ext_resource path="res://icon.png" type="Texture2D" id=1] [ext_resource path="res://test_scenes/AVerySpecialBall.cs" type="Script" id=2] [sub_resource type="RectangleShape2D" id=1] -extents = Vector2( 48, 48 ) +size = Vector2( 48, 48 ) [sub_resource type="CircleShape2D" id=2] @@ -16,13 +16,13 @@ __meta__ = { "_edit_group_": true } -[node name="icon" type="Sprite" parent="StaticBody2D"] +[node name="icon" type="Sprite2D" parent="StaticBody2D"] texture = ExtResource( 1 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D"] shape = SubResource( 1 ) -[node name="AVerySpecialBall" type="KinematicBody2D" parent="."] +[node name="AVerySpecialBall" type="CharacterBody2D" parent="."] position = Vector2( 480, 120 ) script = ExtResource( 2 ) __meta__ = { diff --git a/test_scenes/SomeTestSceneRoot.cs b/test_scenes/SomeTestSceneRoot.cs index 6665dc7..cbb3677 100644 --- a/test_scenes/SomeTestSceneRoot.cs +++ b/test_scenes/SomeTestSceneRoot.cs @@ -2,7 +2,7 @@ namespace GodotXUnitTest { - public class SomeTestSceneRoot : Node2D + public partial class SomeTestSceneRoot : Node2D { } diff --git a/tests/ClickTest.cs b/tests/ClickTest.cs index 374d973..6a71518 100644 --- a/tests/ClickTest.cs +++ b/tests/ClickTest.cs @@ -4,7 +4,7 @@ namespace GodotXUnitTest.Tests { - public class ClickTest + public partial class ClickTest { [GodotFact(Scene = "res://test_scenes/ClickTestScene.tscn")] public async void TestButtonGetsClicked() diff --git a/tests/DebugDrawingTest.cs b/tests/DebugDrawingTest.cs index cfa168d..2e1f62d 100644 --- a/tests/DebugDrawingTest.cs +++ b/tests/DebugDrawingTest.cs @@ -4,7 +4,7 @@ namespace GodotXUnitTest.Tests { - public class DebugDrawingTest + public partial class DebugDrawingTest { [Fact] public async void TestDrawingStuffs() diff --git a/tests/PhysicsCollisionTest.cs b/tests/PhysicsCollisionTest.cs index 5c23faa..887e7b4 100644 --- a/tests/PhysicsCollisionTest.cs +++ b/tests/PhysicsCollisionTest.cs @@ -5,7 +5,7 @@ namespace GodotXUnitTest.Tests { - public class PhysicsCollisionTest + public partial class PhysicsCollisionTest { [GodotFact(Scene = "res://test_scenes/PhysicsCollisionTest.tscn")] public async void TestOhNoTooSlowOfFall() diff --git a/tests/SomeBasicTests.cs b/tests/SomeBasicTests.cs index b23095b..a3e392a 100644 --- a/tests/SomeBasicTests.cs +++ b/tests/SomeBasicTests.cs @@ -2,7 +2,7 @@ namespace GodotXUnitTest.Tests { - public class SomeBasicTests + public partial class SomeBasicTests { [Fact] public void SanityCheckThatWeGotHere() diff --git a/tests/SomePrintStatementsTest.cs b/tests/SomePrintStatementsTest.cs index 8a94a1f..2988fc1 100644 --- a/tests/SomePrintStatementsTest.cs +++ b/tests/SomePrintStatementsTest.cs @@ -5,7 +5,7 @@ namespace GodotXUnitTest.Tests { - public class SomePrintStatementsTest + public partial class SomePrintStatementsTest { private readonly ITestOutputHelper output; diff --git a/tests/SomeTestSceneTest.cs b/tests/SomeTestSceneTest.cs index deccb3d..c905092 100644 --- a/tests/SomeTestSceneTest.cs +++ b/tests/SomeTestSceneTest.cs @@ -3,7 +3,7 @@ namespace GodotXUnitTest.Tests { - public class SomeTestSceneTest + public partial class SomeTestSceneTest { [GodotFact(Scene = "res://test_scenes/SomeTestScene.tscn")] public void IsOnCorrectScene() diff --git a/tests/SubProjectForIntegrationTests/RealFailingTests.cs b/tests/SubProjectForIntegrationTests/RealFailingTests.cs index 517dfb8..e5aeb12 100644 --- a/tests/SubProjectForIntegrationTests/RealFailingTests.cs +++ b/tests/SubProjectForIntegrationTests/RealFailingTests.cs @@ -10,7 +10,7 @@ namespace SubProjectForIntegrationTests /// - we can build a CI example of running tests from a subproject /// - we can see an example of what happens when it fails /// - public class RealFailingTests + public partial class RealFailingTests { [GodotFact(Scene = "res://SomeSceneNotFound.tscn")] public void SceneUnableToBeFound() diff --git a/tests/SubProjectForIntegrationTests/SomeIntegrationTest.cs b/tests/SubProjectForIntegrationTests/SomeIntegrationTest.cs index fae9bea..c5bc167 100644 --- a/tests/SubProjectForIntegrationTests/SomeIntegrationTest.cs +++ b/tests/SubProjectForIntegrationTests/SomeIntegrationTest.cs @@ -1,10 +1,10 @@ -using GodotXUnitApi; +using GodotXUnitApi; using GodotXUnitTest; using Xunit; namespace SubProjectForIntegrationTests { - public class SomeIntegrationTest + public partial class SomeIntegrationTest { [GodotFact(Scene = "res://test_scenes/SomeTestScene.tscn")] public void IsOnCorrectScene() diff --git a/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj b/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj index 50b0286..672b5bc 100644 --- a/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj +++ b/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj @@ -1,4 +1,4 @@ - + 1.0.0 rexfleischer diff --git a/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj b/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj index a698c33..7731ce2 100644 --- a/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj +++ b/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj @@ -1,4 +1,4 @@ - + 1.0.0 rexfleischer diff --git a/tests/SubProjectForUnitTests/UnitTestWithoutGodot.cs b/tests/SubProjectForUnitTests/UnitTestWithoutGodot.cs index eec1923..fc33f0a 100644 --- a/tests/SubProjectForUnitTests/UnitTestWithoutGodot.cs +++ b/tests/SubProjectForUnitTests/UnitTestWithoutGodot.cs @@ -1,10 +1,10 @@ -using System.Configuration; +using System.Configuration; using GodotXUnitApi; using Xunit; namespace SubProjectForUnitTests { - public class SomeClassTest + public partial class SomeClassTest { [GodotFact] public void SomePrettyCoolTest() diff --git a/tests/TestInGodotCycle.cs b/tests/TestInGodotCycle.cs index 198650a..91f5139 100644 --- a/tests/TestInGodotCycle.cs +++ b/tests/TestInGodotCycle.cs @@ -4,7 +4,7 @@ namespace GodotXUnitTest.Tests { - public class TestInGodotCycle + public partial class TestInGodotCycle { /// /// this test will run in the xunit thread. diff --git a/tests/TestInGodotTree.cs b/tests/TestInGodotTree.cs index 4c14d62..cfbb386 100644 --- a/tests/TestInGodotTree.cs +++ b/tests/TestInGodotTree.cs @@ -6,7 +6,7 @@ namespace GodotXUnitTest.Tests { // tests that extend Godot.Node will automatically // be added as a child to the runner. - public class TestInGodotTree : Node + public partial class TestInGodotTree : Node { [GodotFact] public void IsInTree() diff --git a/tests/TestWithSetup.cs b/tests/TestWithSetup.cs index 38aa827..ffae56a 100644 --- a/tests/TestWithSetup.cs +++ b/tests/TestWithSetup.cs @@ -3,7 +3,7 @@ namespace GodotXUnitTest.Tests { - public class TestWithSetup + public partial class TestWithSetup { public int sayWhat = 0; From ffa973357f77bcba2b3c6567dac7762e613bac2b Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 15:36:49 +0200 Subject: [PATCH 03/35] Opening and saving the project Godot updated the SDK attribute in the GodotXUnit.csproj file. Some resources updated as well. --- GodotXUnit.csproj | 4 +-- addons/GodotXUnit/assets/check.png.import | 32 +++++++++---------- addons/GodotXUnit/assets/error.png.import | 32 +++++++++---------- addons/GodotXUnit/assets/running.png.import | 32 +++++++++---------- addons/GodotXUnit/assets/warn.png.import | 32 +++++++++---------- .../runner/GodotTestRunnerScene.tscn | 6 ++-- default_env.tres | 6 ++-- icon.png.import | 32 +++++++++---------- project.godot | 12 +++---- 9 files changed, 94 insertions(+), 94 deletions(-) diff --git a/GodotXUnit.csproj b/GodotXUnit.csproj index 0bc6ce6..79fce13 100644 --- a/GodotXUnit.csproj +++ b/GodotXUnit.csproj @@ -1,4 +1,4 @@ - + {B6A000AB-04AE-4D1E-A0D5-93911E363F6D} Library @@ -43,7 +43,7 @@ - + diff --git a/addons/GodotXUnit/assets/check.png.import b/addons/GodotXUnit/assets/check.png.import index 407fe3a..2240dfa 100644 --- a/addons/GodotXUnit/assets/check.png.import +++ b/addons/GodotXUnit/assets/check.png.import @@ -1,8 +1,9 @@ [remap] importer="texture" -type="StreamTexture" -path="res://.import/check.png-93c4fe9a01601b2e5a6e2306ca570d1e.stex" +type="CompressedTexture2D" +uid="uid://cccd5c8wn54vy" +path="res://.godot/imported/check.png-93c4fe9a01601b2e5a6e2306ca570d1e.ctex" metadata={ "vram_texture": false } @@ -10,25 +11,24 @@ metadata={ [deps] source_file="res://addons/GodotXUnit/assets/check.png" -dest_files=[ "res://.import/check.png-93c4fe9a01601b2e5a6e2306ca570d1e.stex" ] +dest_files=["res://.godot/imported/check.png-93c4fe9a01601b2e5a6e2306ca570d1e.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 +compress/hdr_compression=1 compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" process/fix_alpha_border=true process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/GodotXUnit/assets/error.png.import b/addons/GodotXUnit/assets/error.png.import index b5fe338..67f3502 100644 --- a/addons/GodotXUnit/assets/error.png.import +++ b/addons/GodotXUnit/assets/error.png.import @@ -1,8 +1,9 @@ [remap] importer="texture" -type="StreamTexture" -path="res://.import/error.png-7d7dee34d347bdc60be578dd61003c69.stex" +type="CompressedTexture2D" +uid="uid://pt7u6b6txpf4" +path="res://.godot/imported/error.png-7d7dee34d347bdc60be578dd61003c69.ctex" metadata={ "vram_texture": false } @@ -10,25 +11,24 @@ metadata={ [deps] source_file="res://addons/GodotXUnit/assets/error.png" -dest_files=[ "res://.import/error.png-7d7dee34d347bdc60be578dd61003c69.stex" ] +dest_files=["res://.godot/imported/error.png-7d7dee34d347bdc60be578dd61003c69.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 +compress/hdr_compression=1 compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" process/fix_alpha_border=true process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/GodotXUnit/assets/running.png.import b/addons/GodotXUnit/assets/running.png.import index eb787e1..fd1a506 100644 --- a/addons/GodotXUnit/assets/running.png.import +++ b/addons/GodotXUnit/assets/running.png.import @@ -1,8 +1,9 @@ [remap] importer="texture" -type="StreamTexture" -path="res://.import/running.png-f4bbeb95db62dba2dfecfd374db363b5.stex" +type="CompressedTexture2D" +uid="uid://dpjbiechcpl37" +path="res://.godot/imported/running.png-f4bbeb95db62dba2dfecfd374db363b5.ctex" metadata={ "vram_texture": false } @@ -10,25 +11,24 @@ metadata={ [deps] source_file="res://addons/GodotXUnit/assets/running.png" -dest_files=[ "res://.import/running.png-f4bbeb95db62dba2dfecfd374db363b5.stex" ] +dest_files=["res://.godot/imported/running.png-f4bbeb95db62dba2dfecfd374db363b5.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 +compress/hdr_compression=1 compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" process/fix_alpha_border=true process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/GodotXUnit/assets/warn.png.import b/addons/GodotXUnit/assets/warn.png.import index 5342fab..0b2717f 100644 --- a/addons/GodotXUnit/assets/warn.png.import +++ b/addons/GodotXUnit/assets/warn.png.import @@ -1,8 +1,9 @@ [remap] importer="texture" -type="StreamTexture" -path="res://.import/warn.png-d4a9955bdfe89d37d1373fc2d882c282.stex" +type="CompressedTexture2D" +uid="uid://q0gw22cly0cq" +path="res://.godot/imported/warn.png-d4a9955bdfe89d37d1373fc2d882c282.ctex" metadata={ "vram_texture": false } @@ -10,25 +11,24 @@ metadata={ [deps] source_file="res://addons/GodotXUnit/assets/warn.png" -dest_files=[ "res://.import/warn.png-d4a9955bdfe89d37d1373fc2d882c282.stex" ] +dest_files=["res://.godot/imported/warn.png-d4a9955bdfe89d37d1373fc2d882c282.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 +compress/hdr_compression=1 compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" process/fix_alpha_border=true process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/GodotXUnit/runner/GodotTestRunnerScene.tscn b/addons/GodotXUnit/runner/GodotTestRunnerScene.tscn index 02d806b..d625368 100644 --- a/addons/GodotXUnit/runner/GodotTestRunnerScene.tscn +++ b/addons/GodotXUnit/runner/GodotTestRunnerScene.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=2 format=3 uid="uid://dpfjqgmj8q0ex"] -[ext_resource path="res://addons/GodotXUnit/runner/GodotTestEntry.gd" type="Script" id=1] +[ext_resource type="Script" path="res://addons/GodotXUnit/runner/GodotTestEntry.gd" id="1"] [node name="GodotTestRunnerScene" type="Node2D"] -script = ExtResource( 1 ) +script = ExtResource("1") diff --git a/default_env.tres b/default_env.tres index 1a5570b..324f988 100644 --- a/default_env.tres +++ b/default_env.tres @@ -1,7 +1,7 @@ -[gd_resource type="Environment" load_steps=2 format=2] +[gd_resource type="Environment" load_steps=2 format=3 uid="uid://cweo0g4tp68x"] -[sub_resource type="Sky" id=1] +[sub_resource type="Sky" id="1"] [resource] background_mode = 2 -background_sky = SubResource( 1 ) +sky = SubResource("1") diff --git a/icon.png.import b/icon.png.import index 96cbf46..3c02652 100644 --- a/icon.png.import +++ b/icon.png.import @@ -1,8 +1,9 @@ [remap] importer="texture" -type="StreamTexture" -path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +type="CompressedTexture2D" +uid="uid://dtyr5hwjibqfx" +path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex" metadata={ "vram_texture": false } @@ -10,25 +11,24 @@ metadata={ [deps] source_file="res://icon.png" -dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] +dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"] [params] compress/mode=0 +compress/high_quality=false compress/lossy_quality=0.7 -compress/hdr_mode=0 -compress/bptc_ldr=0 +compress/hdr_compression=1 compress/normal_map=0 -flags/repeat=0 -flags/filter=true -flags/mipmaps=false -flags/anisotropic=false -flags/srgb=2 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" process/fix_alpha_border=true process/premult_alpha=false -process/HDR_as_SRGB=false -process/invert_color=false -stream=false -size_limit=0 -detect_3d=true -svg/scale=1.0 +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/project.godot b/project.godot index 41eb108..904bb19 100644 --- a/project.godot +++ b/project.godot @@ -1,4 +1,3 @@ -; Project was converted by built-in tool to Godot 4.0 ; Engine configuration file. ; It's best edited using the editor UI and not directly, ; since the parameters that go here are not all obvious. @@ -9,10 +8,6 @@ config_version=5 -_global_script_classes=[ ] -_global_script_class_icons={ -} - [GodotXUnit] target_assembly_custom="" @@ -23,11 +18,16 @@ results_summary="res://TestResults.json" config/name="GodotXUnit" run/main_scene="res://addons/GodotXUnit/runner/GodotTestRunnerScene.tscn" +config/features=PackedStringArray("4.1", "C#") config/icon="res://icon.png" +[dotnet] + +project/assembly_name="GodotXUnit" + [editor_plugins] -enabled=PackedStringArray( "GodotXUnit" ) +enabled=PackedStringArray("GodotXUnit") [mono] From 6ae009f24fd196b0f9b43f7b9f9e93eefef1bf9e Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 15:40:48 +0200 Subject: [PATCH 04/35] Update target framework to net6.0 and godot SDK --- GodotXUnit.csproj | 4 ++-- addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj | 4 ++-- .../SubProjectForIntegrationTests.csproj | 4 ++-- tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/GodotXUnit.csproj b/GodotXUnit.csproj index 79fce13..2cf691a 100644 --- a/GodotXUnit.csproj +++ b/GodotXUnit.csproj @@ -6,7 +6,7 @@ GodotXUnit 1.0.0.0 8 - net472 + net6.0 false @@ -53,4 +53,4 @@ GodotXUnitApi - \ No newline at end of file + diff --git a/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj b/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj index d24f757..8744472 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj +++ b/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj @@ -1,8 +1,8 @@ - + 1.0.0 rexfleischer - net472 + net6.0 GodotXUnitApi GodotXUnitApi 8 diff --git a/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj b/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj index 672b5bc..f7def28 100644 --- a/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj +++ b/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj @@ -1,8 +1,8 @@ - + 1.0.0 rexfleischer - net472 + net6.0 SubProjectForIntegrationTests SubProjectForIntegrationTests diff --git a/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj b/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj index 7731ce2..1f983f8 100644 --- a/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj +++ b/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj @@ -1,8 +1,8 @@ - + 1.0.0 rexfleischer - net472 + net6.0 SubProjectForUnitTests SubProjectForUnitTests From 2aaf27462c061b3611d680c4b6921adc555caa2c Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 15:53:06 +0200 Subject: [PATCH 05/35] Fix changes with Vector2 --- addons/GodotXUnit/GodotXUnitApi/GDI.cs | 22 +++++++++++----------- test_scenes/AVerySpecialBall.cs | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/GDI.cs b/addons/GodotXUnit/GodotXUnitApi/GDI.cs index dc454a6..45bc3d0 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDI.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDI.cs @@ -14,17 +14,17 @@ public static class GDI /// public static float PositionXByScreenPercent(float percent) { - return GDU.SubViewport.Size.x * percent; + return GDU.SubViewport.Size.X * percent; } - + /// /// gets the y pixel position based on the percent of the screen /// public static float PositionYByScreenPercent(float percent) { - return GDU.SubViewport.Size.y * percent; + return GDU.SubViewport.Size.Y * percent; } - + /// /// gets a vector2 representing the pixel positions based on the screen percents. /// @@ -46,7 +46,7 @@ public static Vector2 PositionBy2DWorldPos(Vector2 worldPos) throw new Exception("scene root must be a Node2D to use this method"); return (scene.GetViewportTransform() * scene.GetGlobalTransform()).Xform(worldPos); } - + /// /// sends an mouse down event into godot /// @@ -56,8 +56,8 @@ public static void InputMouseDown(Vector2 screenPosition, ButtonList index = But inputEvent.GlobalPosition = screenPosition; inputEvent.Position = screenPosition; inputEvent.Pressed = true; - inputEvent.ButtonIndex = (int) index; - inputEvent.ButtonMask = (int) index; + inputEvent.ButtonIndex = (int)index; + inputEvent.ButtonMask = (int)index; Input.ParseInputEvent(inputEvent); } @@ -70,8 +70,8 @@ public static void InputMouseUp(Vector2 screenPosition, ButtonList index = Butto inputEvent.GlobalPosition = screenPosition; inputEvent.Position = screenPosition; inputEvent.Pressed = false; - inputEvent.ButtonIndex = (int) index; - inputEvent.ButtonMask = (int) index; + inputEvent.ButtonIndex = (int)index; + inputEvent.ButtonMask = (int)index; Input.ParseInputEvent(inputEvent); } @@ -150,7 +150,7 @@ public static async Task SimulateMouseClick(Vector2 position, ButtonList index = await GDU.OnProcessAwaiter; await GDU.OnProcessAwaiter; } - + /// /// simulates a click with these steps: /// - send a mouse moved event to the requested position @@ -168,7 +168,7 @@ public static void SimulateMouseClickNoWait(Vector2 position, ButtonList index = SimulateMouseClick(position, index); #pragma warning restore 4014 } - + /// /// simulates a mouse drag with these steps: /// - move mouse to start position diff --git a/test_scenes/AVerySpecialBall.cs b/test_scenes/AVerySpecialBall.cs index 059f1c6..ade337d 100644 --- a/test_scenes/AVerySpecialBall.cs +++ b/test_scenes/AVerySpecialBall.cs @@ -6,12 +6,12 @@ public partial class AVerySpecialBall : CharacterBody2D { [Signal] public delegate void WeCollidedd(); - + // this ball doesnt really like to go anywhere public float gravity = 10f; public Vector2 velocity = new Vector2(); - + public override void _Process(float delta) { Update(); @@ -19,7 +19,7 @@ public override void _Process(float delta) public override void _PhysicsProcess(float delta) { - velocity.y += gravity * delta; + velocity.Y += gravity * delta; velocity = MoveAndSlide(velocity, Vector2.Up); if (IsOnFloor()) { From 751c73d76c256fffdedb527a2378dcec768b688f Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 15:55:15 +0200 Subject: [PATCH 06/35] Fix Transform2D changes --- addons/GodotXUnit/GodotXUnitApi/GDI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/GDI.cs b/addons/GodotXUnit/GodotXUnitApi/GDI.cs index 45bc3d0..d59bc65 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDI.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDI.cs @@ -44,7 +44,7 @@ public static Vector2 PositionBy2DWorldPos(Vector2 worldPos) var scene = GDU.CurrentScene as Node2D; if (scene == null) throw new Exception("scene root must be a Node2D to use this method"); - return (scene.GetViewportTransform() * scene.GetGlobalTransform()).Xform(worldPos); + return (scene.GetViewportTransform() * scene.GetGlobalTransform()) * worldPos; } /// From 9269b424a4d24ced8628a2bf6dbd152beba186f8 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:07:47 +0200 Subject: [PATCH 07/35] Fix mouse button enum changes --- addons/GodotXUnit/GodotXUnitApi/GDI.cs | 32 +++++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/GDI.cs b/addons/GodotXUnit/GodotXUnitApi/GDI.cs index d59bc65..6175216 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDI.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDI.cs @@ -47,31 +47,35 @@ public static Vector2 PositionBy2DWorldPos(Vector2 worldPos) return (scene.GetViewportTransform() * scene.GetGlobalTransform()) * worldPos; } + // There exists a mouse_button_to_mask in the C++ code, but it's not exposed. + private static MouseButtonMask MouseButtonToMask(MouseButton index) => + (MouseButtonMask)(1 << ((int)index) - 1); + /// /// sends an mouse down event into godot /// - public static void InputMouseDown(Vector2 screenPosition, ButtonList index = ButtonList.Left) + public static void InputMouseDown(Vector2 screenPosition, MouseButton index = MouseButton.Left) { var inputEvent = new InputEventMouseButton(); inputEvent.GlobalPosition = screenPosition; inputEvent.Position = screenPosition; inputEvent.Pressed = true; - inputEvent.ButtonIndex = (int)index; - inputEvent.ButtonMask = (int)index; + inputEvent.ButtonIndex = index; + inputEvent.ButtonMask = MouseButtonToMask(index); Input.ParseInputEvent(inputEvent); } /// /// sends an mouse up event into godot /// - public static void InputMouseUp(Vector2 screenPosition, ButtonList index = ButtonList.Left) + public static void InputMouseUp(Vector2 screenPosition, MouseButton index = MouseButton.Left) { var inputEvent = new InputEventMouseButton(); inputEvent.GlobalPosition = screenPosition; inputEvent.Position = screenPosition; inputEvent.Pressed = false; - inputEvent.ButtonIndex = (int)index; - inputEvent.ButtonMask = (int)index; + inputEvent.ButtonIndex = index; + inputEvent.ButtonMask = MouseButtonToMask(index); Input.ParseInputEvent(inputEvent); } @@ -99,7 +103,7 @@ public static void InputMouseMove(Vector2 screenPosition) /// same as PositionByScreenPercent /// the button index /// the task that will resolve when the simulation is finished - public static async Task SimulateMouseClick(float screenPercentX, float screenPercentY, ButtonList index = ButtonList.Left) + public static async Task SimulateMouseClick(float screenPercentX, float screenPercentY, MouseButton index = MouseButton.Left) { var position = PositionByScreenPercent(screenPercentX, screenPercentY); await SimulateMouseClick(position, index); @@ -117,7 +121,7 @@ public static async Task SimulateMouseClick(float screenPercentX, float screenPe /// same as PositionByScreenPercent /// same as PositionByScreenPercent /// the button index - public static void SimulateMouseClickNoWait(float screenPercentX, float screenPercentY, ButtonList index = ButtonList.Left) + public static void SimulateMouseClickNoWait(float screenPercentX, float screenPercentY, MouseButton index = MouseButton.Left) { #pragma warning disable 4014 SimulateMouseClick(screenPercentX, screenPercentY, index); @@ -138,7 +142,7 @@ public static void SimulateMouseClickNoWait(float screenPercentX, float screenPe /// the position of where to click /// the button index /// the task that will resolve when the simulation is finished - public static async Task SimulateMouseClick(Vector2 position, ButtonList index = ButtonList.Left) + public static async Task SimulateMouseClick(Vector2 position, MouseButton index = MouseButton.Left) { await GDU.OnProcessAwaiter; InputMouseMove(position); @@ -162,7 +166,7 @@ public static async Task SimulateMouseClick(Vector2 position, ButtonList index = /// /// the position of where to click /// the button index - public static void SimulateMouseClickNoWait(Vector2 position, ButtonList index = ButtonList.Left) + public static void SimulateMouseClickNoWait(Vector2 position, MouseButton index = MouseButton.Left) { #pragma warning disable 4014 SimulateMouseClick(position, index); @@ -187,7 +191,7 @@ public static void SimulateMouseClickNoWait(Vector2 position, ButtonList index = /// the task that will resolve when the simulation is finished public static async Task SimulateMouseDrag(float startScreenPercentX, float startScreenPercentY, float endScreenPercentX, float endScreenPercentY, - ButtonList index = ButtonList.Left) + MouseButton index = MouseButton.Left) { var start = PositionByScreenPercent(startScreenPercentX, startScreenPercentY); var end = PositionByScreenPercent(endScreenPercentX, endScreenPercentY); @@ -211,7 +215,7 @@ public static async Task SimulateMouseDrag(float startScreenPercentX, float star /// the button index public static void SimulateMouseDragNoWait(float startScreenPercentX, float startScreenPercentY, float endScreenPercentX, float endScreenPercentY, - ButtonList index = ButtonList.Left) + MouseButton index = MouseButton.Left) { #pragma warning disable 4014 SimulateMouseDrag(startScreenPercentX, startScreenPercentY, endScreenPercentX, endScreenPercentY, index); @@ -232,7 +236,7 @@ public static void SimulateMouseDragNoWait(float startScreenPercentX, float star /// the position of where the drag ends /// the button index /// the task that will resolve when the simulation is finished - public static async Task SimulateMouseDrag(Vector2 start, Vector2 end, ButtonList index = ButtonList.Left) + public static async Task SimulateMouseDrag(Vector2 start, Vector2 end, MouseButton index = MouseButton.Left) { await GDU.OnProcessAwaiter; InputMouseMove(start); @@ -260,7 +264,7 @@ public static async Task SimulateMouseDrag(Vector2 start, Vector2 end, ButtonLis /// the position of where the drag starts /// the position of where the drag ends /// the button index - public static void SimulateMouseDragNoWait(Vector2 start, Vector2 end, ButtonList index = ButtonList.Left) + public static void SimulateMouseDragNoWait(Vector2 start, Vector2 end, MouseButton index = MouseButton.Left) { #pragma warning disable 4014 SimulateMouseDrag(start, end, index); From 2558f03a1e566be63d9c849c1735403dbc5e5c20 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:10:16 +0200 Subject: [PATCH 08/35] FindNode is not called FindChild --- README.md | 2 +- addons/GodotXUnit/XUnitDock.cs | 60 +++++++++++++++++----------------- tests/ClickTest.cs | 6 ++-- tests/PhysicsCollisionTest.cs | 12 +++---- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 34b9375..6cafaae 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ timeouts. full example at ./tests/PhysicsCollisionTest.cs [GodotFact(Scene = "res://test_scenes/PhysicsCollisionTest.tscn")] public async void TestOhNoTooSlowOfFall() { - var ball = (AVerySpecialBall) GDU.CurrentScene.FindNode("AVerySpecialBall"); + var ball = (AVerySpecialBall) GDU.CurrentScene.FindChild("AVerySpecialBall"); Assert.NotNull(ball); // it will throw a TimeoutException here because the gravity value is too low diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index f452077..2d27f84 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -30,7 +30,7 @@ public partial class XUnitDock : MarginContainer private int runningPid = -1; private CheckBox verboseCheck; private TabContainer runTabContainer; - + // there are better ways to do this, but to try to limit the amount of user // setup required, we'll just do this the hacky way. private Label totalRanLabel; @@ -44,40 +44,40 @@ public partial class XUnitDock : MarginContainer public override void _Ready() { - totalRanLabel = (Label) FindNode("TotalRanLabel"); - passedLabel = (Label) FindNode("PassedLabel"); - failedLabel = (Label) FindNode("FailedLabel"); - timeLabel = (Label) FindNode("TimeLabel"); + totalRanLabel = (Label)FindChild("TotalRanLabel"); + passedLabel = (Label)FindChild("PassedLabel"); + failedLabel = (Label)FindChild("FailedLabel"); + timeLabel = (Label)FindChild("TimeLabel"); ResetLabels(); - - stopButton = (Button) FindNode("StopButton"); + + stopButton = (Button)FindChild("StopButton"); stopButton.Connect("pressed", new Callable(this, nameof(StopTests))); - runAllButton = (Button) FindNode("RunAllTestsButton"); + runAllButton = (Button)FindChild("RunAllTestsButton"); runAllButton.Connect("pressed", new Callable(this, nameof(RunAllTests))); - reRunButton = (Button) FindNode("ReRunButton"); + reRunButton = (Button)FindChild("ReRunButton"); reRunButton.Connect("pressed", new Callable(this, nameof(ReRunTests))); - targetClassLabel = (LineEdit) FindNode("TargetClassLabel"); - targetMethodLabel = (LineEdit) FindNode("TargetMethodLabel"); - runSelectedButton = (Button) FindNode("RunSelectedButton"); + targetClassLabel = (LineEdit)FindChild("TargetClassLabel"); + targetMethodLabel = (LineEdit)FindChild("TargetMethodLabel"); + runSelectedButton = (Button)FindChild("RunSelectedButton"); runSelectedButton.Connect("pressed", new Callable(this, nameof(RunSelected))); runSelectedButton.Disabled = true; - targetAssemblyOption = (OptionButton) FindNode("TargetAssemblyOption"); + targetAssemblyOption = (OptionButton)FindChild("TargetAssemblyOption"); targetAssemblyOption.Connect("pressed", new Callable(this, nameof(TargetAssemblyOptionPressed))); targetAssemblyOption.Connect("item_selected", new Callable(this, nameof(TargetAssemblyOptionSelected))); - targetAssemblyLabel = (LineEdit) FindNode("TargetAssemblyLabel"); + targetAssemblyLabel = (LineEdit)FindChild("TargetAssemblyLabel"); targetAssemblyLabel.Text = ProjectSettings.HasSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM) ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM).ToString() : ""; targetAssemblyLabel.Connect("text_changed", new Callable(this, nameof(TargetAssemblyLabelChanged))); TargetAssemblyOptionPressed(); - resultsTree = (Tree) FindNode("ResultsTree"); + resultsTree = (Tree)FindChild("ResultsTree"); resultsTree.HideRoot = true; resultsTree.SelectMode = Tree.SelectModeEnum.Single; resultsTree.Connect("cell_selected", new Callable(this, nameof(OnCellSelected))); - resultDetails = (RichTextLabel) FindNode("ResultDetails"); - resultDiagnostics = (RichTextLabel) FindNode("Diagnostics"); - verboseCheck = (CheckBox) FindNode("VerboseCheckBox"); - runTabContainer = (TabContainer) FindNode("RunTabContainer"); + resultDetails = (RichTextLabel)FindChild("ResultDetails"); + resultDiagnostics = (RichTextLabel)FindChild("Diagnostics"); + verboseCheck = (CheckBox)FindChild("VerboseCheckBox"); + runTabContainer = (TabContainer)FindChild("RunTabContainer"); runTabContainer.CurrentTab = 0; SetProcess(false); } @@ -124,12 +124,12 @@ public void RunSelected() } StartTests(); } - + public void StartTests() { if (IsRunningTests()) OS.Kill(runningPid); - + runAllButton.Disabled = true; reRunButton.Disabled = true; runSelectedButton.Disabled = true; @@ -140,18 +140,18 @@ public void StartTests() resultDiagnostics.Text = ""; resultDetails.Text = ""; watcher = new MessageWatcher(); - + // if things dont clean up correctly, the old messages can still // be on the file system. this will cause the XUnitDock process to // see stale messages and potentially stop picking up new messages. WorkFiles.CleanWorkDir(); - + var runArgs = new StringList(); runArgs.Add(Consts.RUNNER_SCENE_PATH); if (verboseCheck.Pressed) runArgs.Add("--verbose"); runningPid = OS.Execute(OS.GetExecutablePath(), runArgs.ToArray(), false); - + SetProcess(true); } @@ -276,7 +276,7 @@ private void GoToPostState() var missed = watcher.Poll(); if (missed == null) break; GD.PrintErr($"missed message: {missed.GetType()}"); - } + } } watcher = null; runningPid = -1; @@ -290,7 +290,7 @@ private void HandleTestStart(GodotXUnitTestStart testStart) var testItem = EnsureTreeClassAndMethod(testStart.testCaseClass, testStart.testCaseName); if (testItem.GetIcon(0) == null) { - testItem.SetIcon(0, Consts.IconRunning); + testItem.SetIcon(0, Consts.IconRunning); } } @@ -330,9 +330,9 @@ private void HandleTestResult(GodotXUnitTestResult testResult) private void SetTestResultDetails(GodotXUnitTestResult testResult, TreeItem item) { // set the header to include the time it took - var millis = (int) (testResult.time * 1000f); + var millis = (int)(testResult.time * 1000f); item.SetText(0, $"{testResult.testCaseName} ({millis} ms)"); - + // create the test result details var details = new StringBuilder(); details.AppendLine(testResult.FullName); @@ -347,7 +347,7 @@ private void SetTestResultDetails(GodotXUnitTestResult testResult, TreeItem item } details.AppendLine(string.IsNullOrEmpty(testResult.output) ? "No Output" : testResult.output); testDetails[item] = details.ToString(); - + // add the target so the run selected button can query what to run var target = new Array(); target.Add(testResult.testCaseClass); @@ -452,7 +452,7 @@ private void IncTimeLabel(float time) { // why? timeValue += time; - timeLabel.Text = $"Time: {(int) (timeValue * 1000)} ms"; + timeLabel.Text = $"Time: {(int)(timeValue * 1000)} ms"; } } } diff --git a/tests/ClickTest.cs b/tests/ClickTest.cs index 6a71518..92950e7 100644 --- a/tests/ClickTest.cs +++ b/tests/ClickTest.cs @@ -9,16 +9,16 @@ public partial class ClickTest [GodotFact(Scene = "res://test_scenes/ClickTestScene.tscn")] public async void TestButtonGetsClicked() { - var checkBox = (Button) GDU.CurrentScene.FindNode("ImAButton"); + var checkBox = (Button)GDU.CurrentScene.FindChild("ImAButton"); Assert.NotNull(checkBox); Assert.False(checkBox.Pressed); - + await GDU.RequestDrawing(60, drawer => { var position = GDI.PositionByScreenPercent(0.5f, 0.5f); drawer.DrawCircle(position, 30f, Colors.Azure); }); - + await GDI.SimulateMouseClick(0.5f, 0.5f); Assert.True(checkBox.Pressed); } diff --git a/tests/PhysicsCollisionTest.cs b/tests/PhysicsCollisionTest.cs index 887e7b4..5a34fdd 100644 --- a/tests/PhysicsCollisionTest.cs +++ b/tests/PhysicsCollisionTest.cs @@ -11,7 +11,7 @@ public partial class PhysicsCollisionTest public async void TestOhNoTooSlowOfFall() { GDU.Print("this will fail"); - var ball = (AVerySpecialBall) GDU.CurrentScene.FindNode("AVerySpecialBall"); + var ball = (AVerySpecialBall)GDU.CurrentScene.FindChild("AVerySpecialBall"); Assert.NotNull(ball); await Assert.ThrowsAsync(async () => @@ -20,25 +20,25 @@ await Assert.ThrowsAsync(async () => await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollidedd), 1000); }); } - + [GodotFact(Scene = "res://test_scenes/PhysicsCollisionTest.tscn")] public async void TestOhNoTooSlowOfFallButNoException() { - var ball = (AVerySpecialBall) GDU.CurrentScene.FindNode("AVerySpecialBall"); + var ball = (AVerySpecialBall)GDU.CurrentScene.FindChild("AVerySpecialBall"); Assert.NotNull(ball); // it will not throw here, it will just continue await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollidedd), 1000, throwOnTimeout: false); - + // it will get here, but it will fail this equals check Assert.NotEqual(new Vector2(), ball.velocity); } - + // passing test [GodotFact(Scene = "res://test_scenes/PhysicsCollisionTest.tscn")] public async void TestThatItWorksBecauseWeSetGravitySuperHigh() { - var ball = (AVerySpecialBall) GDU.CurrentScene.FindNode("AVerySpecialBall"); + var ball = (AVerySpecialBall)GDU.CurrentScene.FindChild("AVerySpecialBall"); Assert.NotNull(ball); ball.gravity = 1500f; From 863a81df6bad7916dde375c7903b6e6fa66e26dd Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:14:56 +0200 Subject: [PATCH 09/35] Fix enum to Variant casts --- .../GodotXUnitApi/Internal/Consts.cs | 30 +++++++++---------- .../GodotXUnitApi/Internal/ProjectListing.cs | 10 +++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/Consts.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/Consts.cs index 777339e..f3bc319 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/Consts.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/Consts.cs @@ -10,18 +10,18 @@ public static class Consts public static readonly Dictionary SETTING_RESULT_SUMMARY_PROP = new Dictionary { ["name"] = SETTING_RESULTS_SUMMARY, - ["type"] = Variant.Type.String, - ["hint"] = PropertyHint.Dir, + ["type"] = (long)Variant.Type.String, + ["hint"] = (long)PropertyHint.Dir, ["hint_string"] = "set where the summary json is written to.", ["default"] = SETTING_RESULTS_SUMMARY_DEF }; - + public static readonly string SETTING_TARGET_ASSEMBLY = "GodotXUnit/target_assembly"; public static readonly Dictionary SETTING_TARGET_ASSEMBLY_PROP = new Dictionary { ["name"] = SETTING_TARGET_ASSEMBLY, - ["type"] = Variant.Type.String, - ["hint"] = PropertyHint.None, + ["type"] = (long)Variant.Type.String, + ["hint"] = (long)PropertyHint.None, ["hint_string"] = "set the name of the csproj to test, or empty string for main assembly (can be set through UI)", ["default"] = "" }; @@ -31,32 +31,32 @@ public static class Consts public static readonly Dictionary SETTING_TARGET_ASSEMBLY_CUSTOM_PROP = new Dictionary { ["name"] = SETTING_TARGET_ASSEMBLY_CUSTOM, - ["type"] = Variant.Type.String, - ["hint"] = PropertyHint.None, + ["type"] = (long)Variant.Type.String, + ["hint"] = (long)PropertyHint.None, ["hint_string"] = "set the name of the csproj to test, or empty string for main assembly (can be set through UI)", ["default"] = "" }; - + public static readonly string SETTING_TARGET_CLASS = "GodotXUnit/target_class"; public static readonly Dictionary SETTING_TARGET_CLASS_PROP = new Dictionary { ["name"] = SETTING_TARGET_CLASS, - ["type"] = Variant.Type.String, - ["hint"] = PropertyHint.None, + ["type"] = (long)Variant.Type.String, + ["hint"] = (long)PropertyHint.None, ["hint_string"] = "set the name of the class to test, or empty string for all (can be set through UI)", ["default"] = "" }; - + public static readonly string SETTING_TARGET_METHOD = "GodotXUnit/target_method"; public static readonly Dictionary SETTING_TARGET_METHOD_PROP = new Dictionary { ["name"] = SETTING_TARGET_METHOD, - ["type"] = Variant.Type.String, - ["hint"] = PropertyHint.None, + ["type"] = (long)Variant.Type.String, + ["hint"] = (long)PropertyHint.None, ["hint_string"] = "set the name of the method to test, or empty string for all in class (can be set through UI)", ["default"] = "" }; - + public const string RUNNER_SCENE_PATH = "res://addons/GodotXUnit/runner/GodotTestRunnerScene.tscn"; public const string EMPTY_SCENE_PATH = "res://addons/GodotXUnit/runner/EmptyScene.tscn"; public const string DOCK_SCENE_PATH = "res://addons/GodotXUnit/XUnitDock.tscn"; @@ -65,7 +65,7 @@ public static class Consts public const string ICON_WARN = "res://addons/GodotXUnit/assets/warn.png"; public const string ICON_CHECK = "res://addons/GodotXUnit/assets/check.png"; public const string ICON_ERROR = "res://addons/GodotXUnit/assets/error.png"; - + public static Texture2D IconRunning => GD.Load(ICON_RUNNING); public static Texture2D IconWarn => GD.Load(ICON_WARN); public static Texture2D IconCheck => GD.Load(ICON_CHECK); diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs index 2c6ee00..06bfdfc 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs @@ -8,9 +8,9 @@ namespace GodotXUnitApi.Internal public static class ProjectListing { public static readonly string sep = Path3D.DirectorySeparatorChar.ToString(); - + private static string _projectDir; - + public static string ProjectDir { get @@ -29,12 +29,12 @@ public static string ProjectDir } GodotGD.PrintErr("unable to find root of godot project"); throw new Exception("unable to find root dir"); - + // TODO: if this becomes a problem, we can do OS.Execute('pwd'....), but i don't // want to do that if we don't need to. } } - + public static List GetProjectList() { var result = new List(); @@ -46,7 +46,7 @@ public static List GetProjectList() } return result; } - + public static Dictionary GetProjectInfo() { var result = new Dictionary(); From b0293ed8fc7039d3a34ca291af0da15cdafe4b3b Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:17:51 +0200 Subject: [PATCH 10/35] Fix Variant to String conversions --- .../GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs | 6 +++--- addons/GodotXUnit/Plugin.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index 31b5728..40db356 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -58,14 +58,14 @@ protected virtual Assembly GetTargetAssembly(GodotXUnitSummary summary) protected virtual string GetTargetClass(GodotXUnitSummary summary) { return ProjectSettings.HasSetting(Consts.SETTING_TARGET_CLASS) - ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_CLASS)?.ToString() + ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_CLASS).AsString() : null; } protected virtual string GetTargetMethod(GodotXUnitSummary summary) { return ProjectSettings.HasSetting(Consts.SETTING_TARGET_METHOD) - ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_METHOD)?.ToString() + ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_METHOD).AsString() : null; } @@ -166,7 +166,7 @@ public override void _Ready() GD.Print($"targeting method for discovery: {targetMethod}"); runner.TestCaseFilter = test => targetMethod.Equals(test.TestMethod.Method.Name); } - + // if its an empty string, then we need to set it to null because the runner only checks for null var targetClass = GetTargetClass(summary); if (string.IsNullOrEmpty(targetClass)) diff --git a/addons/GodotXUnit/Plugin.cs b/addons/GodotXUnit/Plugin.cs index f1cc007..9f2d120 100644 --- a/addons/GodotXUnit/Plugin.cs +++ b/addons/GodotXUnit/Plugin.cs @@ -27,7 +27,7 @@ public override void _EnterTree() EnsureProjectSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM_PROP); EnsureProjectSetting(Consts.SETTING_TARGET_CLASS_PROP); EnsureProjectSetting(Consts.SETTING_TARGET_METHOD_PROP); - dock = (XUnitDock) GD.Load(Consts.DOCK_SCENE_PATH).Instance(); + dock = (XUnitDock)GD.Load(Consts.DOCK_SCENE_PATH).Instance(); AddControlToBottomPanel(dock, _GetPluginName()); } @@ -44,7 +44,7 @@ public override void _ExitTree() private void EnsureProjectSetting(Dictionary prop) { - var name = prop["name"]?.ToString() ?? throw new Exception("no name in prop"); + var name = prop["name"].AsString() ?? throw new Exception("no name in prop"); if (!ProjectSettings.HasSetting(name)) { ProjectSettings.SetSetting(name, prop["default"]); From bb6ca835f780730959d1814544a7352c82192b26 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:19:07 +0200 Subject: [PATCH 11/35] Fix PackedScene Instantiate call --- addons/GodotXUnit/Plugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GodotXUnit/Plugin.cs b/addons/GodotXUnit/Plugin.cs index 9f2d120..ba73ed2 100644 --- a/addons/GodotXUnit/Plugin.cs +++ b/addons/GodotXUnit/Plugin.cs @@ -27,7 +27,7 @@ public override void _EnterTree() EnsureProjectSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM_PROP); EnsureProjectSetting(Consts.SETTING_TARGET_CLASS_PROP); EnsureProjectSetting(Consts.SETTING_TARGET_METHOD_PROP); - dock = (XUnitDock)GD.Load(Consts.DOCK_SCENE_PATH).Instance(); + dock = GD.Load(Consts.DOCK_SCENE_PATH).Instantiate(); AddControlToBottomPanel(dock, _GetPluginName()); } From 542fc00164a71915155a92bafdb5184cd5b4a6f8 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:29:36 +0200 Subject: [PATCH 12/35] Fix the UI querying the viewport size --- addons/GodotXUnit/GodotXUnitApi/GDI.cs | 4 ++-- addons/GodotXUnit/GodotXUnitApi/GDU.cs | 32 ++++++++++++++++---------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/GDI.cs b/addons/GodotXUnit/GodotXUnitApi/GDI.cs index 6175216..69e948a 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDI.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDI.cs @@ -14,7 +14,7 @@ public static class GDI /// public static float PositionXByScreenPercent(float percent) { - return GDU.SubViewport.Size.X * percent; + return GDU.ViewportSize.X * percent; } /// @@ -22,7 +22,7 @@ public static float PositionXByScreenPercent(float percent) /// public static float PositionYByScreenPercent(float percent) { - return GDU.SubViewport.Size.Y * percent; + return GDU.ViewportSize.Y * percent; } /// diff --git a/addons/GodotXUnit/GodotXUnitApi/GDU.cs b/addons/GodotXUnit/GodotXUnitApi/GDU.cs index 6d2d32f..d69af85 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDU.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDU.cs @@ -41,8 +41,14 @@ public static Node2D Instance public static SceneTree Tree => Instance.GetTree(); - public static SubViewport SubViewport => Instance.GetViewport(); - + public static Vector2I ViewportSize => Instance.GetViewport() switch + { + Window window => window.ContentScaleSize, + SubViewport subViewport => subViewport.Size, + var vp => throw new Exception($"Unexpected viewport type {vp.GetType().Name}") + }; + + public static Node CurrentScene => Instance.GetTree().CurrentScene; /// @@ -67,7 +73,7 @@ public static async Task WaitForFrames(int count) for (int i = 0; i < count; i++) await OnProcessAwaiter; } - + /// /// helper to wrap a SignalAwaiter to return the first element from a signal /// result into the desired type. @@ -77,9 +83,9 @@ public static async Task WaitForFrames(int count) /// the task that awaits and casts when resolved public static async Task AwaitType(this SignalAwaiter awaiter) { - return (T) (await awaiter)[0]; + return (T)(await awaiter)[0]; } - + /// /// creates a task for a godot signal with a timeout. /// @@ -97,7 +103,7 @@ public static async Task ToSignalWithTimeout( { return await source.ToSignal(source, signal).AwaitWithTimeout(timeoutMillis, throwOnTimeout); } - + /// /// wraps the given SignalAwaiter in a task with a timeout. /// @@ -113,7 +119,7 @@ public static Task AwaitWithTimeout( { return Task.Run(async () => await awaiter).AwaitWithTimeout(timeoutMillis, throwOnTimeout); } - + /// /// wraps a task with a task that will resolve after the wrapped task /// or after the specified amount of time (either by exiting or by throwing @@ -132,14 +138,15 @@ public static async Task AwaitWithTimeout( var task = Task.Run(async () => await wrapping); using var token = new CancellationTokenSource(); var completedTask = await Task.WhenAny(task, Task.Delay(timeoutMillis, token.Token)); - if (completedTask == task) { + if (completedTask == task) + { token.Cancel(); await task; } if (throwOnTimeout) throw new TimeoutException($"signal {wrapping} timed out after {timeoutMillis}ms."); } - + /// /// wraps a task with a task that will resolve after the wrapped task /// or after the specified amount of time (either by exiting or by throwing @@ -154,12 +161,13 @@ public static async Task AwaitWithTimeout( public static async Task AwaitWithTimeout( this Task wrapping, int timeoutMillis, - bool throwOnTimeout = true) + bool throwOnTimeout = true) { var task = Task.Run(async () => await wrapping); using var token = new CancellationTokenSource(); var completedTask = await Task.WhenAny(task, Task.Delay(timeoutMillis, token.Token)); - if (completedTask == task) { + if (completedTask == task) + { token.Cancel(); return await task; } @@ -181,7 +189,7 @@ public static async Task RequestDrawing(int frames, Action drawer) { for (int i = 0; i < frames; i++) { - ((GodotXUnitRunnerBase) Instance).RequestDraw(drawer); + ((GodotXUnitRunnerBase)Instance).RequestDraw(drawer); await Instance.ToSignal(Instance, "OnDrawRequestDone"); } } From 612aa524f744d1bc884994337517784bc4d32005 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:34:50 +0200 Subject: [PATCH 13/35] Fix remaining Variant errors --- addons/GodotXUnit/GodotXUnitApi/GDU.cs | 8 ++++---- addons/GodotXUnit/XUnitDock.cs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/GDU.cs b/addons/GodotXUnit/GodotXUnitApi/GDU.cs index d69af85..795ba14 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDU.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDU.cs @@ -83,7 +83,7 @@ public static async Task WaitForFrames(int count) /// the task that awaits and casts when resolved public static async Task AwaitType(this SignalAwaiter awaiter) { - return (T)(await awaiter)[0]; + return (await awaiter)[0].As(); } /// @@ -95,8 +95,8 @@ public static async Task AwaitType(this SignalAwaiter awaiter) /// makes this task throw an exception on timeout. otherwise, just resolves /// the new task with the given timeout /// only throws if throwOnTimeout is true - public static async Task ToSignalWithTimeout( - this Godot.Object source, + public static async Task ToSignalWithTimeout( + this GodotObject source, string signal, int timeoutMillis, bool throwOnTimeout = true) @@ -112,7 +112,7 @@ public static async Task ToSignalWithTimeout( /// makes this task throw an exception on timeout. otherwise, just resolves /// the new task with the given timeout /// only throws if throwOnTimeout is true - public static Task AwaitWithTimeout( + public static Task AwaitWithTimeout( this SignalAwaiter awaiter, int timeoutMillis, bool throwOnTimeout = true) diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index 2d27f84..ed3399f 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -217,10 +217,10 @@ private void TargetAssemblyOptionSelected(int index) private void AddProjectListing(GodotArray items, string text, int id) { items.Add(text); - items.Add(null); + items.Add(default); items.Add(false); items.Add(id); - items.Add(null); + items.Add(default); } private void TargetAssemblyLabelChanged(string new_text) From 161d7d2ff56859cd3cb01a798bf008302aba26e5 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:38:33 +0200 Subject: [PATCH 14/35] CanvasItem.Update is now called QueueRedraw --- .../GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs | 2 +- test_scenes/AVerySpecialBall.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index 40db356..5579ef1 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -223,7 +223,7 @@ private void WriteSummary(GodotXUnitSummary testSummary) public override void _Process(float delta) { EmitSignal(nameof(OnProcess)); - Update(); + QueueRedraw(); } public override void _PhysicsProcess(float delta) diff --git a/test_scenes/AVerySpecialBall.cs b/test_scenes/AVerySpecialBall.cs index ade337d..991ff99 100644 --- a/test_scenes/AVerySpecialBall.cs +++ b/test_scenes/AVerySpecialBall.cs @@ -14,7 +14,7 @@ public partial class AVerySpecialBall : CharacterBody2D public override void _Process(float delta) { - Update(); + QueueRedraw(); } public override void _PhysicsProcess(float delta) From 664c9ad667422aa007ec73898efc4933dddada02 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:44:53 +0200 Subject: [PATCH 15/35] Fix auto-convert mistake with Path It replaced occurrences of Path with Path3D (thinking it was the Godot node type Path). In fact it's System.IO.Path. --- .../GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs | 4 ++-- .../GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs | 8 ++++---- addons/GodotXUnit/XUnitDock.tscn | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index 5579ef1..b89c3bf 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -4,7 +4,7 @@ using Godot; using Newtonsoft.Json; using Xunit.Runners; -using Path3D = System.IO.Path3D; +using Path = System.IO.Path; using DirAccess = System.IO.DirAccess; namespace GodotXUnitApi.Internal @@ -50,7 +50,7 @@ protected virtual Assembly GetTargetAssembly(GodotXUnitSummary summary) // finally, attempt to load project.. var currentDir = DirAccess.GetCurrentDirectory(); - var targetAssembly = Path3D.Combine(currentDir, $".mono/build/bin/Debug/{targetProject}.dll"); + var targetAssembly = Path.Combine(currentDir, $".mono/build/bin/Debug/{targetProject}.dll"); var name = AssemblyName.GetAssemblyName(targetAssembly); return AppDomain.CurrentDomain.Load(name); } diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs index 06bfdfc..d817098 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs @@ -7,7 +7,7 @@ namespace GodotXUnitApi.Internal { public static class ProjectListing { - public static readonly string sep = Path3D.DirectorySeparatorChar.ToString(); + public static readonly string sep = Path.DirectorySeparatorChar.ToString(); private static string _projectDir; @@ -42,7 +42,7 @@ public static List GetProjectList() { if (filename.Contains("GodotXUnitApi")) continue; - result.Add(Path3D.GetFileNameWithoutExtension(filename)); + result.Add(Path.GetFileNameWithoutExtension(filename)); } return result; } @@ -54,7 +54,7 @@ public static Dictionary GetProjectInfo() { if (filename.Contains("GodotXUnitApi")) continue; - result[Path3D.GetFileNameWithoutExtension(filename)] = filename; + result[Path.GetFileNameWithoutExtension(filename)] = filename; } return result; } @@ -72,7 +72,7 @@ public static string GetDefaultProject() GodotGD.PrintErr($"multiple csproj found on project root at {ProjectDir}."); return ""; } - return Path3D.GetFileNameWithoutExtension(project[0]); + return Path.GetFileNameWithoutExtension(project[0]); } } } \ No newline at end of file diff --git a/addons/GodotXUnit/XUnitDock.tscn b/addons/GodotXUnit/XUnitDock.tscn index 81a6cef..82e6f5f 100644 --- a/addons/GodotXUnit/XUnitDock.tscn +++ b/addons/GodotXUnit/XUnitDock.tscn @@ -100,7 +100,7 @@ offset_right = 1004.0 offset_bottom = 24.0 size_flags_horizontal = 3 text = "not found" -placeholder_text = "Custom Assembly Path3D (dll)" +placeholder_text = "Custom Assembly Path (dll)" __meta__ = { "_editor_description_": "" } From 46d173bd21c043798d77d6b84afc50fea418600a Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:48:06 +0200 Subject: [PATCH 16/35] Fix override _Process method signatures --- .../GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs | 4 ++-- addons/GodotXUnit/XUnitDock.cs | 2 +- test_scenes/AVerySpecialBall.cs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index b89c3bf..649527c 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -220,13 +220,13 @@ private void WriteSummary(GodotXUnitSummary testSummary) file.Close(); } - public override void _Process(float delta) + public override void _Process(double delta) { EmitSignal(nameof(OnProcess)); QueueRedraw(); } - public override void _PhysicsProcess(float delta) + public override void _PhysicsProcess(double delta) { EmitSignal(nameof(OnPhysicsProcess)); } diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index ed3399f..e538eb3 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -238,7 +238,7 @@ private void OnCellSelected() runTabContainer.CurrentTab = 0; } - public override void _Process(float delta) + public override void _Process(double delta) { while (watcher != null) { diff --git a/test_scenes/AVerySpecialBall.cs b/test_scenes/AVerySpecialBall.cs index 991ff99..5d1851b 100644 --- a/test_scenes/AVerySpecialBall.cs +++ b/test_scenes/AVerySpecialBall.cs @@ -12,14 +12,14 @@ public partial class AVerySpecialBall : CharacterBody2D public Vector2 velocity = new Vector2(); - public override void _Process(float delta) + public override void _Process(double delta) { QueueRedraw(); } - public override void _PhysicsProcess(float delta) + public override void _PhysicsProcess(double delta) { - velocity.Y += gravity * delta; + velocity.Y += (float)(gravity * delta); velocity = MoveAndSlide(velocity, Vector2.Up); if (IsOnFloor()) { From afc993be08a19764999f9ae05f9006a0be330e91 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 16:51:27 +0200 Subject: [PATCH 17/35] Button.Pressed property is called ButtonPressed --- addons/GodotXUnit/XUnitDock.cs | 2 +- tests/ClickTest.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index e538eb3..76690f2 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -148,7 +148,7 @@ public void StartTests() var runArgs = new StringList(); runArgs.Add(Consts.RUNNER_SCENE_PATH); - if (verboseCheck.Pressed) + if (verboseCheck.ButtonPressed) runArgs.Add("--verbose"); runningPid = OS.Execute(OS.GetExecutablePath(), runArgs.ToArray(), false); diff --git a/tests/ClickTest.cs b/tests/ClickTest.cs index 92950e7..ef22fe3 100644 --- a/tests/ClickTest.cs +++ b/tests/ClickTest.cs @@ -11,7 +11,7 @@ public async void TestButtonGetsClicked() { var checkBox = (Button)GDU.CurrentScene.FindChild("ImAButton"); Assert.NotNull(checkBox); - Assert.False(checkBox.Pressed); + Assert.False(checkBox.ButtonPressed); await GDU.RequestDrawing(60, drawer => { @@ -20,7 +20,7 @@ await GDU.RequestDrawing(60, drawer => }); await GDI.SimulateMouseClick(0.5f, 0.5f); - Assert.True(checkBox.Pressed); + Assert.True(checkBox.ButtonPressed); } } } \ No newline at end of file From d9db082efae7e94430e849df6cb8c658eb3545e6 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 17:59:30 +0200 Subject: [PATCH 18/35] Godot.OS.Execute changed signature --- addons/GodotXUnit/XUnitDock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index 76690f2..16eccbf 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -150,7 +150,7 @@ public void StartTests() runArgs.Add(Consts.RUNNER_SCENE_PATH); if (verboseCheck.ButtonPressed) runArgs.Add("--verbose"); - runningPid = OS.Execute(OS.GetExecutablePath(), runArgs.ToArray(), false); + runningPid = OS.Execute(OS.GetExecutablePath(), runArgs.ToArray(), null, false); SetProcess(true); } From c6633a9ef44373f2fbf9d34464f13707681568fe Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:00:46 +0200 Subject: [PATCH 19/35] Fix target assembly OptionButton items --- addons/GodotXUnit/XUnitDock.cs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index 16eccbf..3165975 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -172,7 +172,6 @@ public bool IsRunningTests() private void TargetAssemblyOptionPressed() { - var items = new GodotArray(); var projectList = ProjectListing.GetProjectList(); var projectSelected = ProjectSettings.HasSetting(Consts.SETTING_TARGET_ASSEMBLY) ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_ASSEMBLY).ToString() @@ -183,14 +182,13 @@ private void TargetAssemblyOptionPressed() var projectName = projectList[i]; if (i == 0) projectName = $"{projectName} (main)"; - AddProjectListing(items, projectName, i); + targetAssemblyOption.AddItem(projectName, i); if (projectName.Equals(projectSelected)) projectSelectedIndex = i; } - AddProjectListing(items, "Custom Location ", 1000); + targetAssemblyOption.AddItem("Custom Location ", 1000); if (projectSelected.Equals(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM_FLAG)) projectSelectedIndex = projectList.Count; - targetAssemblyOption.Items = items; targetAssemblyOption.Selected = projectSelectedIndex; } @@ -214,15 +212,6 @@ private void TargetAssemblyOptionSelected(int index) ProjectSettings.Save(); } - private void AddProjectListing(GodotArray items, string text, int id) - { - items.Add(text); - items.Add(default); - items.Add(false); - items.Add(id); - items.Add(default); - } - private void TargetAssemblyLabelChanged(string new_text) { ProjectSettings.SetSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM, new_text); From f7f8249a00c01616363e7dd2de807da0a0ddb8bd Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:04:39 +0200 Subject: [PATCH 20/35] Fix TreeItem child iteration --- addons/GodotXUnit/XUnitDock.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index 3165975..06c77cf 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -389,12 +389,10 @@ private TreeItem EnsureTreeClass(string testClass) private TreeItem FindTreeChildOrCreate(TreeItem parent, string name) { - var child = parent.GetChildren(); - while (child != null) + foreach (var child in parent.GetChildren()) { var text = child.GetMeta("for"); if (text.Equals(name)) return child; - child = child.GetNext(); } var newClassItem = resultsTree.CreateItem(parent); newClassItem.SetMeta("for", name); From eaace31b3e1639c893cda3d074f8e954e747dc71 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:09:04 +0200 Subject: [PATCH 21/35] Fix CharacterBody2D changes CharacterBody2D now has a build in Velocity property which we'll use. UpDirection is also defaulted to Vector2.Up --- test_scenes/AVerySpecialBall.cs | 6 ++---- tests/PhysicsCollisionTest.cs | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/test_scenes/AVerySpecialBall.cs b/test_scenes/AVerySpecialBall.cs index 5d1851b..8285a64 100644 --- a/test_scenes/AVerySpecialBall.cs +++ b/test_scenes/AVerySpecialBall.cs @@ -10,8 +10,6 @@ public partial class AVerySpecialBall : CharacterBody2D // this ball doesnt really like to go anywhere public float gravity = 10f; - public Vector2 velocity = new Vector2(); - public override void _Process(double delta) { QueueRedraw(); @@ -19,8 +17,8 @@ public override void _Process(double delta) public override void _PhysicsProcess(double delta) { - velocity.Y += (float)(gravity * delta); - velocity = MoveAndSlide(velocity, Vector2.Up); + Velocity += new Vector2(0, gravity * (float)delta); + MoveAndSlide(); if (IsOnFloor()) { GD.Print("yay"); diff --git a/tests/PhysicsCollisionTest.cs b/tests/PhysicsCollisionTest.cs index 5a34fdd..2838305 100644 --- a/tests/PhysicsCollisionTest.cs +++ b/tests/PhysicsCollisionTest.cs @@ -31,7 +31,7 @@ public async void TestOhNoTooSlowOfFallButNoException() await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollidedd), 1000, throwOnTimeout: false); // it will get here, but it will fail this equals check - Assert.NotEqual(new Vector2(), ball.velocity); + Assert.NotEqual(new Vector2(), ball.Velocity); } // passing test @@ -44,7 +44,7 @@ public async void TestThatItWorksBecauseWeSetGravitySuperHigh() // it will pass here await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollidedd), 1000); - Assert.Equal(new Vector2(), ball.velocity); + Assert.Equal(new Vector2(), ball.Velocity); } } } \ No newline at end of file From 69512d22d0c2e3bd78d90fbc2142127ff58ba28c Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:46:33 +0200 Subject: [PATCH 22/35] Fix the file system operations --- .../GodotXUnitApi/Internal/Extensions.cs | 18 ++++++++++ .../Internal/GodotXUnitRunnerBase.cs | 19 ++++++----- .../GodotXUnitApi/Internal/MessagePassing.cs | 8 ++--- .../GodotXUnitApi/Internal/ProjectListing.cs | 10 +++--- .../GodotXUnitApi/Internal/WorkFiles.cs | 33 +++++++++++-------- 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/Extensions.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/Extensions.cs index 730a3e4..db3a8b5 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/Extensions.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/Extensions.cs @@ -5,6 +5,24 @@ namespace GodotXUnitApi.Internal { public static class Extensions { + public static FileAccess ThrowIfNotOk(this FileAccess file) + { + if (file is null) + { + ThrowIfNotOk(FileAccess.GetOpenError()); + } + return file; + } + + public static DirAccess ThrowIfNotOk(this DirAccess dir) + { + if (dir is null) + { + ThrowIfNotOk(DirAccess.GetOpenError()); + } + return dir; + } + public static void ThrowIfNotOk(this Error check) { if (check == Error.Ok) return; diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index 649527c..a319c9e 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -5,7 +5,6 @@ using Newtonsoft.Json; using Xunit.Runners; using Path = System.IO.Path; -using DirAccess = System.IO.DirAccess; namespace GodotXUnitApi.Internal { @@ -49,7 +48,7 @@ protected virtual Assembly GetTargetAssembly(GodotXUnitSummary summary) } // finally, attempt to load project.. - var currentDir = DirAccess.GetCurrentDirectory(); + var currentDir = System.IO.Directory.GetCurrentDirectory(); var targetAssembly = Path.Combine(currentDir, $".mono/build/bin/Debug/{targetProject}.dll"); var name = AssemblyName.GetAssemblyName(targetAssembly); return AppDomain.CurrentDomain.Load(name); @@ -211,13 +210,17 @@ private void WriteSummary(GodotXUnitSummary testSummary) var location = ProjectSettings.HasSetting(Consts.SETTING_RESULTS_SUMMARY) ? ProjectSettings.GetSetting(Consts.SETTING_RESULTS_SUMMARY).ToString() : Consts.SETTING_RESULTS_SUMMARY_DEF; - var file = new Godot.File(); - var result = file.Open(location, Godot.File.ModeFlags.Write); - if (result == Error.Ok) + + try + { + var file = FileAccess.Open(location, FileAccess.ModeFlags.Write).ThrowIfNotOk(); file.StoreString(JsonConvert.SerializeObject(testSummary, Formatting.Indented, WorkFiles.jsonSettings)); - else - GD.Print($"error returned for writing message at {location}: {result}"); - file.Close(); + file.Close(); + } + catch (System.IO.IOException e) + { + GD.Print($"error returned for writing message at {location}: {e}"); + } } public override void _Process(double delta) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/MessagePassing.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/MessagePassing.cs index ee38fe2..dcb5978 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/MessagePassing.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/MessagePassing.cs @@ -19,12 +19,12 @@ public void SendMessage(object message, string type) public partial class MessageWatcher { - private DirAccess directory = new DirAccess(); - public object Poll() { - directory.ChangeDir(WorkFiles.WorkDir).ThrowIfNotOk(); - directory.ListDirBegin(true, true).ThrowIfNotOk(); + var directory = DirAccess.Open(WorkFiles.WorkDir).ThrowIfNotOk(); + directory.IncludeHidden = false; + directory.IncludeNavigational = false; + directory.ListDirBegin().ThrowIfNotOk(); try { while (true) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs index d817098..93a129b 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/ProjectListing.cs @@ -17,7 +17,7 @@ public static string ProjectDir { if (!string.IsNullOrEmpty(_projectDir)) return _projectDir; - var current = DirAccess.GetCurrentDirectory(); + var current = Directory.GetCurrentDirectory(); while (!string.IsNullOrEmpty(current)) { if (File.Exists($"{current}{sep}project.godot")) @@ -25,7 +25,7 @@ public static string ProjectDir _projectDir = current; return _projectDir; } - current = DirAccess.GetParent(current).FullName; + current = Directory.GetParent(current).FullName; } GodotGD.PrintErr("unable to find root of godot project"); throw new Exception("unable to find root dir"); @@ -38,7 +38,7 @@ public static string ProjectDir public static List GetProjectList() { var result = new List(); - foreach (var filename in DirAccess.GetFiles(ProjectDir, "*.csproj", SearchOption.AllDirectories)) + foreach (var filename in Directory.GetFiles(ProjectDir, "*.csproj", SearchOption.AllDirectories)) { if (filename.Contains("GodotXUnitApi")) continue; @@ -50,7 +50,7 @@ public static List GetProjectList() public static Dictionary GetProjectInfo() { var result = new Dictionary(); - foreach (var filename in DirAccess.GetFiles(ProjectDir, "*.csproj", SearchOption.AllDirectories)) + foreach (var filename in Directory.GetFiles(ProjectDir, "*.csproj", SearchOption.AllDirectories)) { if (filename.Contains("GodotXUnitApi")) continue; @@ -61,7 +61,7 @@ public static Dictionary GetProjectInfo() public static string GetDefaultProject() { - var project = DirAccess.GetFiles(ProjectDir, "*.csproj", SearchOption.TopDirectoryOnly); + var project = Directory.GetFiles(ProjectDir, "*.csproj", SearchOption.TopDirectoryOnly); if (project.Length == 0) { GodotGD.PrintErr($"no csproj found on project root at {ProjectDir}. is this a mono project?"); diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/WorkFiles.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/WorkFiles.cs index f0301ae..6b41df0 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/WorkFiles.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/WorkFiles.cs @@ -21,25 +21,31 @@ public static string PathForResFile(string filename) public static void CleanWorkDir() { - var directory = new Godot.DirAccess(); - directory.MakeDirRecursive(WorkDir).ThrowIfNotOk(); - directory.Open(WorkDir).ThrowIfNotOk(); - directory.ListDirBegin(true, true).ThrowIfNotOk(); - while (true) + DirAccess.MakeDirRecursiveAbsolute(WorkDir).ThrowIfNotOk(); + var directory = DirAccess.Open(WorkDir).ThrowIfNotOk(); + directory.IncludeHidden = false; + directory.IncludeNavigational = false; + try + { + directory.ListDirBegin().ThrowIfNotOk(); + while (true) + { + var next = directory.GetNext(); + if (string.IsNullOrEmpty(next)) + break; + directory.Remove(next).ThrowIfNotOk(); + } + } + finally { - var next = directory.GetNext(); - if (string.IsNullOrEmpty(next)) - break; - directory.Remove(next).ThrowIfNotOk(); + directory.ListDirEnd(); } - directory.ListDirEnd(); } public static void WriteFile(string filename, object contents) { var writing = JsonConvert.SerializeObject(contents, Formatting.Indented, jsonSettings); - var file = new Godot.File(); - file.Open(PathForResFile(filename), File.ModeFlags.WriteRead).ThrowIfNotOk(); + var file = FileAccess.Open(PathForResFile(filename), FileAccess.ModeFlags.WriteRead).ThrowIfNotOk(); try { file.StoreString(writing); @@ -52,8 +58,7 @@ public static void WriteFile(string filename, object contents) public static object ReadFile(string filename) { - var file = new Godot.File(); - file.Open(PathForResFile(filename), File.ModeFlags.Read).ThrowIfNotOk(); + var file = FileAccess.Open(PathForResFile(filename), FileAccess.ModeFlags.Read).ThrowIfNotOk(); try { return JsonConvert.DeserializeObject(file.GetAsText(), jsonSettings); From 6abb05a36eb12d57c909791a275bf26c17c0f106 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:49:25 +0200 Subject: [PATCH 23/35] Missing partial keyword --- .../GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index a319c9e..15d5f0a 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -8,7 +8,7 @@ namespace GodotXUnitApi.Internal { - public abstract class GodotXUnitRunnerBase : Node2D + public abstract partial class GodotXUnitRunnerBase : Node2D { protected virtual Assembly GetTargetAssembly(GodotXUnitSummary summary) { From 06148f24dd1c68ec75993a9ed9e892eafb7d701f Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:49:52 +0200 Subject: [PATCH 24/35] Add MustBeVariant attribute to generic type arg --- addons/GodotXUnit/GodotXUnitApi/GDU.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/GDU.cs b/addons/GodotXUnit/GodotXUnitApi/GDU.cs index 795ba14..1b8dd3b 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDU.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDU.cs @@ -81,7 +81,7 @@ public static async Task WaitForFrames(int count) /// the target signal to wrap /// the type to cast to /// the task that awaits and casts when resolved - public static async Task AwaitType(this SignalAwaiter awaiter) + public static async Task AwaitType<[MustBeVariant] T>(this SignalAwaiter awaiter) { return (await awaiter)[0].As(); } From b6f783463adf9be5e642af92ec9ac596fec37e59 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:51:29 +0200 Subject: [PATCH 25/35] Signal delegate names must end with EventHandler --- .../GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs | 6 +++--- test_scenes/AVerySpecialBall.cs | 4 ++-- tests/PhysicsCollisionTest.cs | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index 15d5f0a..dd4d5c9 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -71,13 +71,13 @@ protected virtual string GetTargetMethod(GodotXUnitSummary summary) private ConcurrentQueue> drawRequests = new ConcurrentQueue>(); [Signal] - public delegate void OnProcess(); + public delegate void OnProcessEventHandler(); [Signal] - public delegate void OnPhysicsProcess(); + public delegate void OnPhysicsProcessEventHandler(); [Signal] - public delegate void OnDrawRequestDone(); + public delegate void OnDrawRequestDoneEventHandler(); public void RequestDraw(Action request) { diff --git a/test_scenes/AVerySpecialBall.cs b/test_scenes/AVerySpecialBall.cs index 8285a64..20a63a3 100644 --- a/test_scenes/AVerySpecialBall.cs +++ b/test_scenes/AVerySpecialBall.cs @@ -5,7 +5,7 @@ namespace GodotXUnitTest public partial class AVerySpecialBall : CharacterBody2D { [Signal] - public delegate void WeCollidedd(); + public delegate void WeCollidedEventHandler(); // this ball doesnt really like to go anywhere public float gravity = 10f; @@ -22,7 +22,7 @@ public override void _PhysicsProcess(double delta) if (IsOnFloor()) { GD.Print("yay"); - EmitSignal(nameof(WeCollidedd)); + EmitSignal(nameof(WeCollided)); } } diff --git a/tests/PhysicsCollisionTest.cs b/tests/PhysicsCollisionTest.cs index 2838305..e7cc674 100644 --- a/tests/PhysicsCollisionTest.cs +++ b/tests/PhysicsCollisionTest.cs @@ -17,7 +17,7 @@ public async void TestOhNoTooSlowOfFall() await Assert.ThrowsAsync(async () => { // this will throw a TimeoutException - await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollidedd), 1000); + await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollided), 1000); }); } @@ -28,7 +28,7 @@ public async void TestOhNoTooSlowOfFallButNoException() Assert.NotNull(ball); // it will not throw here, it will just continue - await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollidedd), 1000, throwOnTimeout: false); + await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollided), 1000, throwOnTimeout: false); // it will get here, but it will fail this equals check Assert.NotEqual(new Vector2(), ball.Velocity); @@ -43,7 +43,7 @@ public async void TestThatItWorksBecauseWeSetGravitySuperHigh() ball.gravity = 1500f; // it will pass here - await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollidedd), 1000); + await ball.ToSignalWithTimeout(nameof(AVerySpecialBall.WeCollided), 1000); Assert.Equal(new Vector2(), ball.Velocity); } } From 734195b7fde0ef7d5e78a29c5abc612400d03888 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:54:04 +0200 Subject: [PATCH 26/35] Update langversion to 10 --- GodotXUnit.csproj | 2 +- addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj | 2 +- .../SubProjectForIntegrationTests.csproj | 2 +- tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GodotXUnit.csproj b/GodotXUnit.csproj index 2cf691a..c1df11c 100644 --- a/GodotXUnit.csproj +++ b/GodotXUnit.csproj @@ -5,7 +5,7 @@ GodotXUnit GodotXUnit 1.0.0.0 - 8 + 10 net6.0 diff --git a/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj b/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj index 8744472..f4f5540 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj +++ b/addons/GodotXUnit/GodotXUnitApi/GodotXUnitApi.csproj @@ -5,7 +5,7 @@ net6.0 GodotXUnitApi GodotXUnitApi - 8 + 10 GodotXUnitApi true diff --git a/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj b/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj index f7def28..648960c 100644 --- a/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj +++ b/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj @@ -7,7 +7,7 @@ SubProjectForIntegrationTests SubProjectForIntegrationTests - 8 + 10 diff --git a/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj b/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj index 1f983f8..578f6e1 100644 --- a/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj +++ b/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj @@ -7,7 +7,7 @@ SubProjectForUnitTests SubProjectForUnitTests - 8 + 10 From 1400f03643e8d9435812b4e41951d1cb5fba31e0 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:54:47 +0200 Subject: [PATCH 27/35] Godot changed a project.godot entry after passing build --- project.godot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.godot b/project.godot index 904bb19..6956f1c 100644 --- a/project.godot +++ b/project.godot @@ -27,7 +27,7 @@ project/assembly_name="GodotXUnit" [editor_plugins] -enabled=PackedStringArray("GodotXUnit") +enabled=PackedStringArray("res://addons/GodotXUnit/plugin.cfg") [mono] From 71c8b9d7a688d8d570099ba7c00e1ab7b2f76b31 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 18:56:42 +0200 Subject: [PATCH 28/35] Removed conflicting reference causing build warning --- GodotXUnit.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/GodotXUnit.csproj b/GodotXUnit.csproj index c1df11c..e028928 100644 --- a/GodotXUnit.csproj +++ b/GodotXUnit.csproj @@ -13,9 +13,6 @@ false false - - - From bd199f3dbf5430acfd3dc1df16e2fa63010f6c83 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 19:11:43 +0200 Subject: [PATCH 29/35] Fix target assembly options not being cleared --- addons/GodotXUnit/XUnitDock.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/GodotXUnit/XUnitDock.cs b/addons/GodotXUnit/XUnitDock.cs index 06c77cf..68a1e57 100644 --- a/addons/GodotXUnit/XUnitDock.cs +++ b/addons/GodotXUnit/XUnitDock.cs @@ -172,6 +172,7 @@ public bool IsRunningTests() private void TargetAssemblyOptionPressed() { + targetAssemblyOption.Clear(); var projectList = ProjectListing.GetProjectList(); var projectSelected = ProjectSettings.HasSetting(Consts.SETTING_TARGET_ASSEMBLY) ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_ASSEMBLY).ToString() From 26b228b629681b28b23c7e77a2436fc797d10e0e Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Fri, 16 Jun 2023 21:47:42 +0200 Subject: [PATCH 30/35] Copy assemblies to fix xunit.core not being found Trying to run the plugin gave the error below. The tag CopyLocalLockFileAssemblies seems to fix the error, as the xunit.core.dll is included with the output files. ``` Godot Engine v4.1.beta2.mono.official (c) 2007-present Juan Linietsky, Ariel Manzur & Godot Contributors. modules/gltf/register_types.cpp:72 - Blend file import is enabled in the project settings, but no Blender path is configured in the editor settings. Blend files will not be imported. --- Debug adapter server started --- --- GDScript language server started --- modules/mono/glue/runtime_interop.cpp:1325 - System.IO.FileNotFoundException: Could not load file or assembly 'xunit.core, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c'. The system cannot find the file specified. File name: 'xunit.core, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c' at System.ModuleHandle.ResolveType(QCallModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type) at System.ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext) at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg) at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes) at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit) at System.Reflection.RuntimeMethodInfo.GetCustomAttributes(Boolean inherit) at Godot.Bridge.ScriptManagerBridge.UpdateScriptClassInfo(IntPtr scriptPtr, godot_string* outClassName, godot_bool* outTool, godot_bool* outGlobal, godot_string* outIconPath, godot_array* outMethodsDest, godot_dictionary* outRpcFunctionsDest, godot_dictionary* outEventSignalsDest, godot_ref* outBaseScript) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs:line 698 ``` --- GodotXUnit.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/GodotXUnit.csproj b/GodotXUnit.csproj index e028928..e040ff3 100644 --- a/GodotXUnit.csproj +++ b/GodotXUnit.csproj @@ -11,6 +11,7 @@ Enabling them may require other manual changes to the project and its files.--> false false + true false From 0fd16393c8d2119983121f0c0b8ba024fdae70e1 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Sat, 17 Jun 2023 11:26:14 +0200 Subject: [PATCH 31/35] Fix target assembly path resolution Don't know what changed to make the GetExecutingAssembly() return an assembly with an empty Location property, but it did and thus made the AssemblyRunner.WithoutAppDomain fail its file-exists check even though we had a valid assembly. There's no way to pass a fully qualified Assembly instance to the XUnit AssemblyRunner, only a path string. Reworked the target assembly resolution and so it now passes a full path to the default assembly correctly and there are no errors. However it still doesn't detect any tests. --- .../Internal/GodotXUnitRunnerBase.cs | 64 +++++++++++++------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index dd4d5c9..2f186ec 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -10,19 +10,43 @@ namespace GodotXUnitApi.Internal { public abstract partial class GodotXUnitRunnerBase : Node2D { - protected virtual Assembly GetTargetAssembly(GodotXUnitSummary summary) + /// + /// Get the assembly name from the project settings. + /// + /// The name of the target assembly or null if the default is requested + private String GetTargetAssemblyNameFromSettings() { - // check if we even have a project assembly set if (!ProjectSettings.HasSetting(Consts.SETTING_TARGET_ASSEMBLY)) - return Assembly.GetExecutingAssembly(); - - // get the project and if its the default (the godot project), return executing + { + return null; + } var targetProject = ProjectSettings.GetSetting(Consts.SETTING_TARGET_ASSEMBLY).ToString(); if (string.IsNullOrEmpty(targetProject) || targetProject.Equals(ProjectListing.GetDefaultProject())) - return Assembly.GetExecutingAssembly(); + { + return null; + } + return targetProject; + } - // if its a custom project target, attempt to just load the assembly directly - if (targetProject.Equals(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM_FLAG)) + private String GetAssemblyPath(String assemblyName) + { + var currentDir = System.IO.Directory.GetCurrentDirectory(); + return Path.Combine(currentDir, $".mono/build/bin/Debug/{assemblyName}.dll"); + } + + private String GetDefaultTargetAssemblyPath() + { + return GetAssemblyPath(Assembly.GetExecutingAssembly().GetName().Name); + } + + private String GetTargetAssemblyPath(GodotXUnitSummary summary) + { + var assemblyName = GetTargetAssemblyNameFromSettings(); + if (assemblyName is null) + { + return GetDefaultTargetAssemblyPath(); + } + if (assemblyName.Equals(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM_FLAG)) { var customDll = ProjectSettings.HasSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM) ? ProjectSettings.GetSetting(Consts.SETTING_TARGET_ASSEMBLY_CUSTOM).ToString() @@ -31,27 +55,25 @@ protected virtual Assembly GetTargetAssembly(GodotXUnitSummary summary) { summary.AddDiagnostic("no custom dll assembly configured."); GD.PrintErr("no custom dll assembly configured."); - return Assembly.GetExecutingAssembly(); + return GetDefaultTargetAssemblyPath(); } summary.AddDiagnostic($"attempting to load custom dll at: {customDll}"); - return AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(customDll)); + return customDll; } // find the project in the project list. if its not there, print error and leave var projectList = ProjectListing.GetProjectInfo(); - if (!projectList.ContainsKey(targetProject)) + if (!projectList.ContainsKey(assemblyName)) { GD.PrintErr( - $"unable to find project {targetProject}. expected values: {string.Join(", ", projectList.Keys)}"); - return Assembly.GetExecutingAssembly(); + $"unable to find project {assemblyName}. expected values: {string.Join(", ", projectList.Keys)}"); + return GetDefaultTargetAssemblyPath(); } // finally, attempt to load project.. - var currentDir = System.IO.Directory.GetCurrentDirectory(); - var targetAssembly = Path.Combine(currentDir, $".mono/build/bin/Debug/{targetProject}.dll"); - var name = AssemblyName.GetAssemblyName(targetAssembly); - return AppDomain.CurrentDomain.Load(name); + var targetAssembly = GetAssemblyPath(assemblyName); + return targetAssembly; } protected virtual string GetTargetClass(GodotXUnitSummary summary) @@ -181,14 +203,14 @@ private void CreateRunner() { try { - var check = GetTargetAssembly(summary); - if (check == null) + var assemblyPath = GetTargetAssemblyPath(summary); + if (String.IsNullOrEmpty(assemblyPath)) { - GD.PrintErr("no assembly returned for tests"); summary.AddDiagnostic(new Exception("no assembly returned for tests")); return; } - runner = AssemblyRunner.WithoutAppDomain(check.Location); + summary.AddDiagnostic($"Loading assembly at {assemblyPath}"); + runner = AssemblyRunner.WithoutAppDomain(assemblyPath); } catch (Exception ex) { From 82c4285585e047ec32e687e7eca70968c6a52b86 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Sat, 17 Jun 2023 12:48:13 +0200 Subject: [PATCH 32/35] Brute force assembly resolution The assemblies would continue to not be located correctly even though a fully qualified path was passed to the AssemblyRunner. I attached an event handler to the app domain's AssemblyResolve event to retry locating the assembly. Cudos to this article: https://weblog.west-wind.com/posts/2016/dec/12/loading-net-assemblies-out-of-seperate-folders Trying to run the tests/ project assemblies still complained about xunit.core and xunit.assert to be missing. Adding the CopyLocalLockFileAssemblies flag to those projects fixed the issue. --- .../Internal/GodotXUnitRunnerBase.cs | 27 +++++++++++++++++++ .../SubProjectForIntegrationTests.csproj | 1 + .../SubProjectForUnitTests.csproj | 1 + 3 files changed, 29 insertions(+) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs index 2f186ec..7f3fc3a 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotXUnitRunnerBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Concurrent; +using System.Linq; using System.Reflection; using Godot; using Newtonsoft.Json; @@ -112,6 +113,31 @@ public void RequestDraw(Action request) private MessageSender messages; + public Assembly AssemblyResolve(object sender, ResolveEventArgs args) + { + GD.Print($"Resolving {args.Name}."); + Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name); + if (assembly is not null) + { + GD.Print($"Assembly resolution success, already loaded: {assembly.Location}"); + return assembly; + } + try + { + var shortName = args.Name.Split(",")[0]; + assembly = Assembly.LoadFile(GetAssemblyPath(shortName)); + GD.Print($"Assembly resolution success {args.Name} -> {assembly.Location}"); + return assembly; + } + catch (System.IO.FileNotFoundException e) + { + var msg = $"Assembly resolution failed for {args.Name}, requested by {args.RequestingAssembly?.FullName ?? "unknown assembly"}"; + GD.PrintErr(msg); + GD.PushError(msg); + return null; + } + } + public override void _Ready() { GDU.Instance = this; @@ -119,6 +145,7 @@ public override void _Ready() WorkFiles.CleanWorkDir(); summary = new GodotXUnitSummary(); messages = new MessageSender(); + AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; CreateRunner(); if (runner == null) { diff --git a/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj b/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj index 648960c..70a6cd9 100644 --- a/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj +++ b/tests/SubProjectForIntegrationTests/SubProjectForIntegrationTests.csproj @@ -6,6 +6,7 @@ SubProjectForIntegrationTests SubProjectForIntegrationTests + true 10 diff --git a/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj b/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj index 578f6e1..8e35f2f 100644 --- a/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj +++ b/tests/SubProjectForUnitTests/SubProjectForUnitTests.csproj @@ -6,6 +6,7 @@ SubProjectForUnitTests SubProjectForUnitTests + true 10 From 56f72082f737efe2450c189a2478b972b7638006 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Sun, 18 Jun 2023 11:26:37 +0200 Subject: [PATCH 33/35] Auto-format on file with few changes --- .../GodotXUnitApi/Internal/GodotTestCase.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs index e8df4f7..52180c2 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs @@ -13,11 +13,11 @@ namespace GodotXUnitApi.Internal public partial class GodotTestCase : XunitTestCase { private IAttributeInfo attribute; - + [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")] - public GodotTestCase() {} - + public GodotTestCase() { } + public GodotTestCase(IAttributeInfo attribute, IMessageSink diagnosticMessageSink, ITestFrameworkDiscoveryOptions discoveryOptions, @@ -42,7 +42,7 @@ public override async Task RunAsync(IMessageSink diagnosticMessageSi this, DisplayName, SkipReason, - constructorArguments, + constructorArguments, TestMethodArguments, messageBus, aggregator, @@ -54,7 +54,7 @@ public override async Task RunAsync(IMessageSink diagnosticMessageSi public partial class GodotTestCaseRunner : XunitTestCaseRunner { private IAttributeInfo attribute; - + public GodotTestCaseRunner(IAttributeInfo attribute, IXunitTestCase testCase, string displayName, @@ -90,7 +90,7 @@ protected override XunitTestRunner CreateTestRunner( { return new GodotTestRunner(attribute, test, - messageBus, + messageBus, testClass, constructorArguments, testMethod, @@ -130,17 +130,17 @@ public GodotTestRunner(IAttributeInfo attribute, { this.attribute = attribute; } - + protected override async Task> InvokeTestAsync(ExceptionAggregator aggregator) { - + // override the ITestOutputHelper from XunitTestClassRunner - TestOutputHelper helper = null; + TestOutputHelper helper = null; for (int i = 0; i < ConstructorArguments.Length; i++) { if (ConstructorArguments[i] is ITestOutputHelper) { - helper = (TestOutputHelper) ConstructorArguments[i]; + helper = (TestOutputHelper)ConstructorArguments[i]; break; } } @@ -169,7 +169,7 @@ protected override Task InvokeTestMethodAsync(ExceptionAggregator aggre public partial class GodotTestInvoker : XunitTestInvoker { private IAttributeInfo attribute; - + private Node addingToTree; private bool loadEmptyScene; @@ -185,8 +185,8 @@ public GodotTestInvoker(IAttributeInfo attribute, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource) : base(test, - messageBus, - testClass, + messageBus, + testClass, constructorArguments, testMethod, testMethodArguments, From 5366d16f46e7ca4cd31e2d0f00304e5dffc9272b Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Sat, 17 Jun 2023 18:49:09 +0200 Subject: [PATCH 34/35] Idle frame is called process_frame --- addons/GodotXUnit/GodotXUnitApi/GDU.cs | 4 ++-- .../GodotXUnitApi/Internal/GodotTestCase.cs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/GDU.cs b/addons/GodotXUnit/GodotXUnitApi/GDU.cs index 1b8dd3b..4b995e7 100644 --- a/addons/GodotXUnit/GodotXUnitApi/GDU.cs +++ b/addons/GodotXUnit/GodotXUnitApi/GDU.cs @@ -36,8 +36,8 @@ public static Node2D Instance public static SignalAwaiter OnPhysicsProcessAwaiter => Instance.ToSignal(Instance, "OnPhysicsProcess"); - public static SignalAwaiter OnIdleFrameAwaiter => - Instance.ToSignal(Instance.GetTree(), "idle_frame"); + public static SignalAwaiter OnProcessFrameAwaiter => + Instance.ToSignal(Instance.GetTree(), SceneTree.SignalName.ProcessFrame); public static SceneTree Tree => Instance.GetTree(); diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs index 52180c2..2030f0c 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs @@ -202,7 +202,7 @@ protected override object CreateTestClass() var check = base.CreateTestClass(); if (check is Node node) addingToTree = node; - + return check; } @@ -219,13 +219,13 @@ protected override async Task BeforeTestMethodInvokedAsync() return; } loadEmptyScene = true; - + // the scene should be loaded within two frames - await GDU.OnIdleFrameAwaiter; - await GDU.OnIdleFrameAwaiter; + await GDU.OnProcessFrameAwaiter; + await GDU.OnProcessFrameAwaiter; await GDU.OnProcessAwaiter; } - + if (addingToTree != null) { await GDU.OnProcessAwaiter; @@ -271,8 +271,8 @@ protected override async Task AfterTestMethodInvokedAsync() { // change scenes again and wait for godot to catch up GDU.Instance.GetTree().ChangeSceneToFile(Consts.EMPTY_SCENE_PATH); - await GDU.OnIdleFrameAwaiter; - await GDU.OnIdleFrameAwaiter; + await GDU.OnProcessFrameAwaiter; + await GDU.OnProcessFrameAwaiter; await GDU.OnProcessAwaiter; } } From d7d51214aa5434a4d5d9fdd4f3fd9c8af83095e1 Mon Sep 17 00:00:00 2001 From: Kim Simmons Date: Sat, 17 Jun 2023 18:39:29 +0200 Subject: [PATCH 35/35] Make tests run via the main Godot thread Godot only allows specific threads to access Node as a safety precaution. This makes most tests always fail since XUnit spawns at least one thread to run tests in (even if parallel is disabled) To get around this, all tests are now invoked inside a deferred lambda that will run on Godot's main thread. A semaphore is then used to let XUnit wait for the test to finish. --- .../GodotXUnitApi/Internal/GodotTestCase.cs | 156 ++++++++++++------ 1 file changed, 109 insertions(+), 47 deletions(-) diff --git a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs index 2030f0c..5b28757 100644 --- a/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs +++ b/addons/GodotXUnit/GodotXUnitApi/Internal/GodotTestCase.cs @@ -206,75 +206,137 @@ protected override object CreateTestClass() return check; } + /// + /// Runs the given function in Godot's main thread. + /// + /// + private void CallInGodotMain(Func fn) + { + Exception caught = null; + var semaphore = new Godot.Semaphore(); + // Create a callable and use CallDeferred to add it to Godot's + // execution queue, which will run the function in the main thread. + // Callables do not (as of Godot 4.1) accept Task functions. + // Wrapping it in an action makes it fire-and-forget, which is + // fine; we're using a semaphore to signal completion anyway. + Callable.From(new Action(async () => + { + try + { + await fn(); + } + catch (AggregateException aggregate) + { + caught = aggregate.InnerException; + } + catch (Exception e) + { + caught = e; + } + finally + { + semaphore.Post(); + } + })).CallDeferred(); + // Note: We're blocking the thread here. Is that a bad thing? + // It's probably a XUnit worker thread, so maybe its fine, but + // if any deadlocks are discovered we might want to spawn a new + // thread for this whole operation. It might be nicer if this whole + // method was async anyway. + semaphore.Wait(); + if (caught is not null) + { + throw caught; + } + } + protected override async Task BeforeTestMethodInvokedAsync() { var sceneCheck = attribute.GetNamedArgument(nameof(GodotFactAttribute.Scene)); - if (!string.IsNullOrEmpty(sceneCheck)) + try { - // you must be in the process frame to - await GDU.OnProcessAwaiter; - if (GDU.Instance.GetTree().ChangeSceneToFile(sceneCheck) != Error.Ok) + CallInGodotMain(async () => { - Aggregator.Add(new Exception($"could not load scene: {sceneCheck}")); - return; - } - loadEmptyScene = true; + if (!string.IsNullOrEmpty(sceneCheck)) + { + // you must be in the process frame to + await GDU.OnProcessAwaiter; - // the scene should be loaded within two frames - await GDU.OnProcessFrameAwaiter; - await GDU.OnProcessFrameAwaiter; - await GDU.OnProcessAwaiter; - } + if (GDU.Instance.GetTree().ChangeSceneToFile(sceneCheck) != Error.Ok) + { + Aggregator.Add(new Exception($"could not load scene: {sceneCheck}")); + return; + } + loadEmptyScene = true; + + // the scene should be loaded within two frames + await GDU.OnProcessFrameAwaiter; + await GDU.OnProcessFrameAwaiter; + await GDU.OnProcessAwaiter; + } - if (addingToTree != null) + if (addingToTree != null) + { + await GDU.OnProcessAwaiter; + GDU.Instance.AddChild(addingToTree); + await GDU.OnProcessAwaiter; + } + }); + + } + catch (Exception e) { - await GDU.OnProcessAwaiter; - GDU.Instance.AddChild(addingToTree); - await GDU.OnProcessAwaiter; + Aggregator.Add(e); } - await base.BeforeTestMethodInvokedAsync(); } protected override async Task InvokeTestMethodAsync(object testClassInstance) { - var sceneCheck = attribute.GetNamedArgument(nameof(GodotFactAttribute.Frame)); - switch (sceneCheck) + decimal result = default; + CallInGodotMain(async () => { - case GodotFactFrame.Default: - break; - case GodotFactFrame.Process: - await GDU.OnProcessAwaiter; - break; - case GodotFactFrame.PhysicsProcess: - await GDU.OnPhysicsProcessAwaiter; - break; - default: - Aggregator.Add(new Exception($"unknown GodotFactFrame: {sceneCheck.ToString()}")); - throw new ArgumentOutOfRangeException(); - } - return await base.InvokeTestMethodAsync(testClassInstance); + var sceneCheck = attribute.GetNamedArgument(nameof(GodotFactAttribute.Frame)); + switch (sceneCheck) + { + case GodotFactFrame.Default: + break; + case GodotFactFrame.Process: + await GDU.OnProcessAwaiter; + break; + case GodotFactFrame.PhysicsProcess: + await GDU.OnPhysicsProcessAwaiter; + break; + default: + Aggregator.Add(new Exception($"unknown GodotFactFrame: {sceneCheck.ToString()}")); + throw new ArgumentOutOfRangeException(); + } + result = await base.InvokeTestMethodAsync(testClassInstance); + }); + return result; } protected override async Task AfterTestMethodInvokedAsync() { await base.AfterTestMethodInvokedAsync(); - - if (addingToTree != null) + CallInGodotMain(async () => { - await GDU.OnProcessAwaiter; - GDU.Instance.RemoveChild(addingToTree); - await GDU.OnProcessAwaiter; - } + if (addingToTree != null) + { + await GDU.OnProcessAwaiter; + GDU.Instance.RemoveChild(addingToTree); + await GDU.OnProcessAwaiter; + } - if (loadEmptyScene) - { - // change scenes again and wait for godot to catch up - GDU.Instance.GetTree().ChangeSceneToFile(Consts.EMPTY_SCENE_PATH); - await GDU.OnProcessFrameAwaiter; - await GDU.OnProcessFrameAwaiter; - await GDU.OnProcessAwaiter; - } + if (loadEmptyScene) + { + // change scenes again and wait for godot to catch up + GDU.Instance.GetTree().ChangeSceneToFile(Consts.EMPTY_SCENE_PATH); + await GDU.OnProcessFrameAwaiter; + await GDU.OnProcessFrameAwaiter; + await GDU.OnProcessAwaiter; + } + }); } } } \ No newline at end of file