Add test cases for move order

This commit is contained in:
Tim Van Baak 2024-08-26 15:39:42 +00:00
parent ffe164975b
commit b4f8f621ca
3 changed files with 99 additions and 96 deletions

View File

@ -27,7 +27,9 @@ public class OrderRegex(World world)
public const string ViaConvoy = "(convoy|via convoy|by convoy)"; public const string ViaConvoy = "(convoy|via convoy|by convoy)";
public Regex Hold => new($"^{UnitSpec} {HoldVerb}$", RegexOptions.IgnoreCase); public Regex Hold => new(
$"^{UnitSpec} {HoldVerb}$",
RegexOptions.IgnoreCase);
public static ( public static (
string type, string type,
@ -46,10 +48,11 @@ public class OrderRegex(World world)
match.Groups[6].Value, match.Groups[6].Value,
match.Groups[7].Value); match.Groups[7].Value);
public Regex Move => new($"^{UnitSpec} {MoveVerb} {FullLocation}(?: {ViaConvoy})?$"); public Regex Move => new(
$"^{UnitSpec} {MoveVerb} {FullLocation}(?: {ViaConvoy})?$",
RegexOptions.IgnoreCase);
public static ( public static (
string power,
string type, string type,
string timeline, string timeline,
string province, string province,
@ -65,19 +68,18 @@ public class OrderRegex(World world)
match.Groups[1].Value, match.Groups[1].Value,
match.Groups[2].Value, match.Groups[2].Value,
match.Groups[3].Value, match.Groups[3].Value,
match.Groups[4].Value, match.Groups[4].Length > 0
match.Groups[5].Length > 0 ? match.Groups[4].Value
? match.Groups[5].Value : match.Groups[5].Value,
: match.Groups[6].Value, match.Groups[6].Value,
match.Groups[7].Value, match.Groups[7].Value,
match.Groups[8].Value, match.Groups[8].Value,
match.Groups[9].Value, match.Groups[9].Value,
match.Groups[10].Value, match.Groups[10].Length > 0
match.Groups[11].Length > 1 ? match.Groups[10].Value
? match.Groups[11].Value : match.Groups[11].Value,
: match.Groups[12].Value, match.Groups[12].Value,
match.Groups[13].Value, match.Groups[13].Value);
match.Groups[14].Value);
public static bool TryParseUnit(World world, string unitSpec, [NotNullWhen(true)] out Unit? newUnit) public static bool TryParseUnit(World world, string unitSpec, [NotNullWhen(true)] out Unit? newUnit)
{ {

View File

@ -71,8 +71,8 @@ public class GameScriptHandler(World world, bool strict = false) : IScriptHandle
if (OrderRegex.TryParseOrder(World, orderPower, orderText, out Order? order)) { if (OrderRegex.TryParseOrder(World, orderPower, orderText, out Order? order)) {
Console.WriteLine($"Parsed {orderPower} order \"{orderText}\" but doing anything with it isn't implemented yet"); Console.WriteLine($"Parsed {orderPower} order \"{orderText}\" but doing anything with it isn't implemented yet");
return this; return this;
} }
Console.WriteLine($"Failed to parse \"{orderText}\""); Console.WriteLine($"Failed to parse \"{orderText}\"");
return Strict ? null : this; return Strict ? null : this;

View File

@ -6,95 +6,96 @@ namespace MultiversalDiplomacyTests;
public class RegexTest public class RegexTest
{ {
[TestCase( private static TestCaseData Test(string order, params string[] expected)
"Army a-Munich/l@0 holds", => new TestCaseData(order, expected).SetName($"{{m}}(\"{order}\")");
ExpectedResult = new string[] {"Army", "a", "Munich", "l", "0", "holds"},
Description = "Full specification")] static IEnumerable<TestCaseData> HoldRegexMatchesTestCases()
[TestCase( {
"fleet B-lon/C@0 H", // Full specification
ExpectedResult = new string[] {"fleet", "B", "lon", "C", "0", "H"}, yield return Test(
Description = "Case insensitivity")] "Army a-Munich/l@0 holds",
[TestCase( "Army", "a", "Munich", "l", "0", "holds");
"ROM h", // Case insensitivity
ExpectedResult = new string[] {"", "", "ROM", "", "", "h"}, yield return Test(
Description = "All optionals missing")] "fleet B-lon/C@0 H",
[TestCase( "fleet", "B", "lon", "C", "0", "H");
"A F-STP hold", // All optionals missing
ExpectedResult = new string[] {"A", "F", "STP", "", "", "hold"}, yield return Test(
Description = "No confusion of unit type and timeline")] "ROM h",
[TestCase( "", "", "ROM", "", "", "h");
"Fleet North Sea Hold", // No confusion of unit type and timeline
ExpectedResult = new string[] {"Fleet", "", "North Sea", "", "", "Hold"}, yield return Test(
Description = "Province with space in name")] "A F-STP hold",
[TestCase( "A", "F", "STP", "", "", "hold");
"F Spain(nc) holds", // Province with space in name
ExpectedResult = new string[] {"F", "", "Spain", "nc", "", "holds"}, yield return Test(
Description = "Parenthesis location")] "Fleet North Sea Hold",
public string[] HoldRegexMatches(string order) "Fleet", "", "North Sea", "", "", "Hold");
// Parenthesis location
yield return Test(
"F Spain(nc) holds",
"F", "", "Spain", "nc", "", "holds");
}
[TestCaseSource(nameof(HoldRegexMatchesTestCases))]
public void HoldRegexMatches(string order, string[] expected)
{ {
OrderRegex re = new(World.WithStandardMap()); OrderRegex re = new(World.WithStandardMap());
var match = re.Hold.Match(order); var match = re.Hold.Match(order);
Assert.True(match.Success, "Match failed"); Assert.True(match.Success, "Match failed");
var (type, timeline, province, location, turn, holdVerb) = OrderRegex.ParseHold(match); var (type, timeline, province, location, turn, holdVerb) = OrderRegex.ParseHold(match);
return [type, timeline, province, location, turn, holdVerb]; string[] actual = [type, timeline, province, location, turn, holdVerb];
// Use EquivalentTo for more detailed error message
Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results");
Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
} }
[Test] static IEnumerable<TestCaseData> MoveRegexMatchesTestCases()
public void UnitTokenizer()
{ {
World world = World.WithStandardMap(); static TestCaseData Test(string order, params string[] expected)
OrderRegex re = new(world); => new TestCaseData(order, expected).SetName($"{{m}}(\"{order}\")");
// Full specification
yield return Test(
"Army a-Munich/l@0 - a-Tyrolia/l@0",
"Army", "a", "Munich", "l", "0", "-", "a", "Tyrolia", "l", "0", "");
// Case insensitivity
yield return Test(
"fleet B-lon/C@0 - B-enc/W@0",
"fleet", "B", "lon", "C", "0", "-", "B", "enc", "W", "0", "");
// All optionals missing
yield return Test(
"ROM - VIE",
"", "", "ROM", "", "", "-", "", "VIE", "", "", "");
// No confusion of unit type and timeline
yield return Test(
"A F-STP - MOS",
"A", "F", "STP", "", "", "-", "", "MOS", "", "", "");
// Elements with spaces
yield return Test(
"Fleet Western Mediterranean Sea moves to Gulf of Lyons via convoy",
"Fleet", "", "Western Mediterranean Sea", "", "", "moves to", "", "Gulf of Lyons", "", "", "via convoy");
// Parenthesis location
yield return Test(
"F Spain(nc) - Spain(sc)",
"F", "", "Spain", "nc", "", "-", "", "Spain", "sc", "", "");
// Timeline designation spells out a province
yield return Test(
"A tyr-MUN(vie) - mun-TYR/vie",
"A", "tyr", "MUN", "vie", "", "-", "mun", "TYR", "vie", "", "");
}
var match = re.Hold.Match("Germany Army a-Munich/l@0 holds"); [TestCaseSource(nameof(MoveRegexMatchesTestCases))]
Assert.That(match.Success, Is.True); public void MoveRegexMatches(string order, string[] expected)
var hold = OrderRegex.ParseHold(match); {
// Assert.That(hold.power, Is.EqualTo("Germany")); OrderRegex re = new(World.WithStandardMap());
Assert.That(hold.type, Is.EqualTo("Army")); var match = re.Move.Match(order);
Assert.That(hold.timeline, Is.EqualTo("a")); Assert.True(match.Success, "Match failed");
Assert.That(hold.province, Is.EqualTo("Munich")); var (type, timeline, province, location, turn, moveVerb,
Assert.That(hold.location, Is.EqualTo("l")); destTimeline, destProvince, destLocation, destTurn, viaConvoy) = OrderRegex.ParseMove(match);
Assert.That(hold.turn, Is.EqualTo("0")); string[] actual = [type, timeline, province, location, turn, moveVerb,
Assert.That(hold.holdVerb, Is.EqualTo("holds")); destTimeline, destProvince, destLocation, destTurn, viaConvoy];
// Use EquivalentTo for more detailed error message
match = re.Hold.Match("F Venice hold"); Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results");
Assert.That(match.Success, Is.True); Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
hold = OrderRegex.ParseHold(match);
// Assert.That(hold.power, Is.Null);
Assert.That(hold.type, Is.EqualTo("F"));
Assert.That(hold.timeline, Is.Null);
Assert.That(hold.province, Is.EqualTo("Venice"));
Assert.That(hold.location, Is.Null);
Assert.That(hold.turn, Is.Null);
Assert.That(hold.holdVerb, Is.EqualTo("hold"));
match = re.Move.Match("F Gascony - Spain(nc)");
Assert.That(match.Success, Is.True);
var move = OrderRegex.ParseMove(match);
Assert.That(move.power, Is.Null);
Assert.That(move.type, Is.EqualTo("F"));
Assert.That(move.timeline, Is.Null);
Assert.That(move.province, Is.EqualTo("Gascony"));
Assert.That(move.location, Is.Null);
Assert.That(move.turn, Is.Null);
Assert.That(move.moveVerb, Is.EqualTo("-"));
Assert.That(move.destTimeline, Is.Null);
Assert.That(move.destProvince, Is.EqualTo("Spain"));
Assert.That(move.destLocation, Is.EqualTo("nc"));
Assert.That(move.destTurn, Is.Null);
match = re.Move.Match("F North Sea - Picardy");
Assert.That(match.Success, Is.True);
move = OrderRegex.ParseMove(match);
Assert.That(move.power, Is.Null);
Assert.That(move.type, Is.EqualTo("F"));
Assert.That(move.timeline, Is.Null);
Assert.That(move.province, Is.EqualTo("North Sea"));
Assert.That(move.location, Is.Null);
Assert.That(move.turn, Is.Null);
Assert.That(move.moveVerb, Is.EqualTo("-"));
Assert.That(move.destTimeline, Is.Null);
Assert.That(move.destProvince, Is.EqualTo("Picardy"));
Assert.That(move.destLocation, Is.Null);
Assert.That(move.destTurn, Is.Null);
} }
} }