From f9f8ea2b5ae2352f98f0b4f82682ed42beaba4c4 Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Sat, 17 Aug 2024 21:24:59 -0700 Subject: [PATCH] Add script-based test framework --- .../Script/GameScriptHandler.cs | 43 +++++++++++++++++++ .../Script/SetupScriptHandler.cs | 5 ++- MultiversalDiplomacyTests/DATC_A.cs | 2 - .../MultiversalDiplomacyTests.csproj | 6 +++ MultiversalDiplomacyTests/ScriptTests.cs | 28 ++++++++++++ .../Scripts/DATC/6.A.1.txt | 14 ++++++ .../Scripts/DATC/6.A.2.txt | 14 ++++++ .../Scripts/DATC/6.A.3.txt | 14 ++++++ .../Scripts/DATC/6.A.4.txt | 14 ++++++ .../Scripts/DATC/6.A.5.txt | 31 +++++++++++++ .../Scripts/DATC/6.A.6.txt | 16 +++++++ .../Scripts/DATC/6.A.7.txt | 16 +++++++ .../Scripts/DATC/README.md | 3 ++ 13 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 MultiversalDiplomacy/Script/GameScriptHandler.cs create mode 100644 MultiversalDiplomacyTests/ScriptTests.cs create mode 100644 MultiversalDiplomacyTests/Scripts/DATC/6.A.1.txt create mode 100644 MultiversalDiplomacyTests/Scripts/DATC/6.A.2.txt create mode 100644 MultiversalDiplomacyTests/Scripts/DATC/6.A.3.txt create mode 100644 MultiversalDiplomacyTests/Scripts/DATC/6.A.4.txt create mode 100644 MultiversalDiplomacyTests/Scripts/DATC/6.A.5.txt create mode 100644 MultiversalDiplomacyTests/Scripts/DATC/6.A.6.txt create mode 100644 MultiversalDiplomacyTests/Scripts/DATC/6.A.7.txt create mode 100644 MultiversalDiplomacyTests/Scripts/DATC/README.md diff --git a/MultiversalDiplomacy/Script/GameScriptHandler.cs b/MultiversalDiplomacy/Script/GameScriptHandler.cs new file mode 100644 index 0000000..7db394c --- /dev/null +++ b/MultiversalDiplomacy/Script/GameScriptHandler.cs @@ -0,0 +1,43 @@ +using MultiversalDiplomacy.Model; + +namespace MultiversalDiplomacy.Script; + +public class GameScriptHandler(World world, bool strict = false) : IScriptHandler +{ + public string Prompt => "game> "; + + public World World { get; private set; } = world; + + /// + /// Whether unsuccessful commands should terminate the script. + /// + public bool Strict { get; } = strict; + + private string? CurrentPower = null; + + public IScriptHandler? HandleInput(string input) + { + if (input == "") { + CurrentPower = null; + return this; + } + + // --- submits the orders for validation to allow for assertions about it + if (input == "---") { + // TODO submit orders + // TODO return a new handler that handles asserts + } + + // A block of orders for a single power beginning with "{name}:" + if (World.Powers.FirstOrDefault(p => input.EqualsAnyCase($"{p}:"), null) is string power) { + CurrentPower = power; + return this; + } + + // TODO parse order, including "{power} {order}" for one-offs + + Console.WriteLine($"{CurrentPower}: {input}"); + + return this; + } +} diff --git a/MultiversalDiplomacy/Script/SetupScriptHandler.cs b/MultiversalDiplomacy/Script/SetupScriptHandler.cs index 19ae3ed..40e517b 100644 --- a/MultiversalDiplomacy/Script/SetupScriptHandler.cs +++ b/MultiversalDiplomacy/Script/SetupScriptHandler.cs @@ -32,7 +32,7 @@ public class SetupScriptHandler(World world, bool strict = false) : IScriptHandl case "help": case "?": Console.WriteLine("commands:"); - Console.WriteLine(" begin: complete setup and start the game"); + Console.WriteLine(" begin: complete setup and start the game (alias: ---)"); Console.WriteLine(" list : list things in a game category"); Console.WriteLine(" option : set a game option"); Console.WriteLine(" unit [location]: add a unit to the game"); @@ -40,7 +40,8 @@ public class SetupScriptHandler(World world, bool strict = false) : IScriptHandl break; case "begin": - return null; // TODO + case "---": + return new GameScriptHandler(World, Strict); case "list" when args.Length == 1: Console.WriteLine("usage:"); diff --git a/MultiversalDiplomacyTests/DATC_A.cs b/MultiversalDiplomacyTests/DATC_A.cs index f55de6c..e0068fa 100644 --- a/MultiversalDiplomacyTests/DATC_A.cs +++ b/MultiversalDiplomacyTests/DATC_A.cs @@ -1,8 +1,6 @@ using MultiversalDiplomacy.Adjudicate; -using MultiversalDiplomacy.Adjudicate.Decision; using MultiversalDiplomacy.Model; using MultiversalDiplomacy.Orders; - using NUnit.Framework; namespace MultiversalDiplomacyTests; diff --git a/MultiversalDiplomacyTests/MultiversalDiplomacyTests.csproj b/MultiversalDiplomacyTests/MultiversalDiplomacyTests.csproj index f9ccbde..7f04bc4 100644 --- a/MultiversalDiplomacyTests/MultiversalDiplomacyTests.csproj +++ b/MultiversalDiplomacyTests/MultiversalDiplomacyTests.csproj @@ -18,4 +18,10 @@ + + + Always + + + diff --git a/MultiversalDiplomacyTests/ScriptTests.cs b/MultiversalDiplomacyTests/ScriptTests.cs new file mode 100644 index 0000000..e173a4a --- /dev/null +++ b/MultiversalDiplomacyTests/ScriptTests.cs @@ -0,0 +1,28 @@ +using NUnit.Framework; + +using MultiversalDiplomacy.Model; +using MultiversalDiplomacy.Script; + +namespace MultiversalDiplomacyTests; + +public class ScriptTests +{ + static IEnumerable DatcTestCases() + { + foreach (var path in Directory.EnumerateFiles("Scripts/DATC")) + { + yield return new TestCaseData(path) + .SetName($"{{m}}({Path.GetFileNameWithoutExtension(path)})"); + } + } + + [TestCaseSource(nameof(DatcTestCases))] + public void Test_DATC(string testScriptPath) + { + IScriptHandler? handler = new SetupScriptHandler(World.WithStandardMap(), strict: true); + foreach (string input in File.ReadAllLines(testScriptPath)) { + handler = handler?.HandleInput(input); + Assert.That(handler, Is.Not.Null, $"Script quit unexpectedly at \"{input}\""); + } + } +} diff --git a/MultiversalDiplomacyTests/Scripts/DATC/6.A.1.txt b/MultiversalDiplomacyTests/Scripts/DATC/6.A.1.txt new file mode 100644 index 0000000..3352544 --- /dev/null +++ b/MultiversalDiplomacyTests/Scripts/DATC/6.A.1.txt @@ -0,0 +1,14 @@ +# 6.A.1. TEST CASE, MOVING TO AN AREA THAT IS NOT A NEIGHBOUR +# Check if an illegal move (without convoy) will fail. + +unit England F North Sea + +--- + +England: +F North Sea - Picardy + +--- + +# Order should fail. +assert North Sea holds diff --git a/MultiversalDiplomacyTests/Scripts/DATC/6.A.2.txt b/MultiversalDiplomacyTests/Scripts/DATC/6.A.2.txt new file mode 100644 index 0000000..527d035 --- /dev/null +++ b/MultiversalDiplomacyTests/Scripts/DATC/6.A.2.txt @@ -0,0 +1,14 @@ +# 6.A.2. TEST CASE, MOVE ARMY TO SEA +# Check if an army could not be moved to open sea. + +unit England A Liverpool + +--- + +England: +A Liverpool - Irish Sea + +--- + +# Order should fail. +assert Liverpool holds diff --git a/MultiversalDiplomacyTests/Scripts/DATC/6.A.3.txt b/MultiversalDiplomacyTests/Scripts/DATC/6.A.3.txt new file mode 100644 index 0000000..d160bef --- /dev/null +++ b/MultiversalDiplomacyTests/Scripts/DATC/6.A.3.txt @@ -0,0 +1,14 @@ +# 6.A.3. TEST CASE, MOVE FLEET TO LAND +# Check whether a fleet cannot move to land. + +unit Germany Army Kiel + +--- + +Germany: +F Kiel - Munich + +--- + +# Order should fail. +assert Kiel holds diff --git a/MultiversalDiplomacyTests/Scripts/DATC/6.A.4.txt b/MultiversalDiplomacyTests/Scripts/DATC/6.A.4.txt new file mode 100644 index 0000000..3ff5c48 --- /dev/null +++ b/MultiversalDiplomacyTests/Scripts/DATC/6.A.4.txt @@ -0,0 +1,14 @@ +# 6.A.4. TEST CASE, MOVE TO OWN SECTOR +# Moving to the same sector is an illegal move (2023 rulebook, page 7, "An Army can be ordered to move into an adjacent inland or coastal province."). + +unit Germany Army Kiel + +--- + +Germany: +F Kiel - Kiel + +--- + +# Program should not crash. +assert Kiel holds diff --git a/MultiversalDiplomacyTests/Scripts/DATC/6.A.5.txt b/MultiversalDiplomacyTests/Scripts/DATC/6.A.5.txt new file mode 100644 index 0000000..8eb3c6b --- /dev/null +++ b/MultiversalDiplomacyTests/Scripts/DATC/6.A.5.txt @@ -0,0 +1,31 @@ +# 6.A.5. TEST CASE, MOVE TO OWN SECTOR WITH CONVOY +# Moving to the same sector is still illegal with convoy (2023 rulebook, page 7, "Note: An Army can move across water provinces from one coastal province to another..."). + +unit England F North Sea +unit England A Yorkshire +unit England A Liverpool +unit Germany F London +unit Germany A Wales + +--- + +England: +F North Sea Convoys A Yorkshire - Yorkshire +A Yorkshire - Yorkshire +A Liverpool Supports A Yorkshire - Yorkshire + +Germany: +F London - Yorkshire +A Wales Supports F London - Yorkshire + +--- + +# The move of the army in Yorkshire is illegal. +assert Yorkshire holds +# This makes the support of Liverpool also illegal and without the support, the Germans have a stronger force. +assert North Sea holds +assert Liverpool holds +assert London moves +# The army in London dislodges the army in Yorkshire. +assert Wales supports +assert Yorkshire dislodged diff --git a/MultiversalDiplomacyTests/Scripts/DATC/6.A.6.txt b/MultiversalDiplomacyTests/Scripts/DATC/6.A.6.txt new file mode 100644 index 0000000..cc01be9 --- /dev/null +++ b/MultiversalDiplomacyTests/Scripts/DATC/6.A.6.txt @@ -0,0 +1,16 @@ +# 6.A.6. TEST CASE, ORDERING A UNIT OF ANOTHER COUNTRY +# Check whether someone cannot order a unit that is not his own unit. + +unit England F London +# A German unit is included here so Germany isn't considered dead +unit Germany A Munich + +--- + +Germany: +F London - North Sea + +--- + +# Order should fail. +assert London holds diff --git a/MultiversalDiplomacyTests/Scripts/DATC/6.A.7.txt b/MultiversalDiplomacyTests/Scripts/DATC/6.A.7.txt new file mode 100644 index 0000000..3057bde --- /dev/null +++ b/MultiversalDiplomacyTests/Scripts/DATC/6.A.7.txt @@ -0,0 +1,16 @@ +# 6.A.7. TEST CASE, ONLY ARMIES CAN BE CONVOYED +# A fleet cannot be convoyed. + +unit England F London +unit England North Sea + +--- + +England: +F London - Belgium +F North Sea Convoys A London - Belgium + +--- + +# Move from London to Belgium should fail. +assert London holds diff --git a/MultiversalDiplomacyTests/Scripts/DATC/README.md b/MultiversalDiplomacyTests/Scripts/DATC/README.md new file mode 100644 index 0000000..ff3d741 --- /dev/null +++ b/MultiversalDiplomacyTests/Scripts/DATC/README.md @@ -0,0 +1,3 @@ +# DATC test scripts + +These test scripts are copied from DATC v3.1.