Add test cases for support-hold

This commit is contained in:
Tim Van Baak 2024-08-26 16:32:33 +00:00
parent b4f8f621ca
commit 33aecf876a
2 changed files with 103 additions and 2 deletions

View File

@ -5,6 +5,11 @@ using MultiversalDiplomacy.Orders;
namespace MultiversalDiplomacy.Model; namespace MultiversalDiplomacy.Model;
/// <summary>
/// This class defines the regular expressions that are used to build up larger expressions for matching orders
/// and other script inputs. It also provides helper functions to extract the captured order elements as tuples,
/// which function as the structured intermediate representation between raw user input and full Order objects.
/// </summary>
public class OrderRegex(World world) public class OrderRegex(World world)
{ {
public const string Type = "(A|F|Army|Fleet)"; public const string Type = "(A|F|Army|Fleet)";
@ -25,6 +30,8 @@ public class OrderRegex(World world)
public const string MoveVerb = "(-|(?:->)|(?:=>)|(?:attack(?:s)?)|(?:move(?:s)?(?: to)?))"; public const string MoveVerb = "(-|(?:->)|(?:=>)|(?:attack(?:s)?)|(?:move(?:s)?(?: to)?))";
public const string SupportVerb = "(s|support|supports)";
public const string ViaConvoy = "(convoy|via convoy|by convoy)"; public const string ViaConvoy = "(convoy|via convoy|by convoy)";
public Regex Hold => new( public Regex Hold => new(
@ -81,6 +88,39 @@ public class OrderRegex(World world)
match.Groups[12].Value, match.Groups[12].Value,
match.Groups[13].Value); match.Groups[13].Value);
public Regex SupportHold => new(
$"^{UnitSpec} {SupportVerb} {UnitSpec}$",
RegexOptions.IgnoreCase);
public static (
string type,
string timeline,
string province,
string location,
string turn,
string supportVerb,
string targetType,
string targetTimeline,
string targetProvince,
string targetLocation,
string targetTurn)
ParseSupportHold(Match match) => (
match.Groups[1].Value,
match.Groups[2].Value,
match.Groups[3].Value,
match.Groups[4].Length > 0
? match.Groups[4].Value
: match.Groups[5].Value,
match.Groups[6].Value,
match.Groups[7].Value,
match.Groups[8].Value,
match.Groups[9].Value,
match.Groups[10].Value,
match.Groups[11].Length > 0
? match.Groups[11].Value
: match.Groups[12].Value,
match.Groups[13].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)
{ {
newUnit = null; newUnit = null;

View File

@ -70,10 +70,18 @@ public class RegexTest
yield return Test( yield return Test(
"A F-STP - MOS", "A F-STP - MOS",
"A", "F", "STP", "", "", "-", "", "MOS", "", "", ""); "A", "F", "STP", "", "", "-", "", "MOS", "", "", "");
// No confusion of timeline and hold verb
yield return Test(
"A Mun - h-Tyr",
"A", "", "Mun", "", "", "-", "h", "Tyr", "", "", "");
// No confusion of timeline and support verb
yield return Test(
"A Mun - s-Tyr",
"A", "", "Mun", "", "", "-", "s", "Tyr", "", "", "");
// Elements with spaces // Elements with spaces
yield return Test( yield return Test(
"Fleet Western Mediterranean Sea moves to Gulf of Lyons via convoy", "Western Mediterranean Sea moves to Gulf of Lyons via convoy",
"Fleet", "", "Western Mediterranean Sea", "", "", "moves to", "", "Gulf of Lyons", "", "", "via convoy"); "", "", "Western Mediterranean Sea", "", "", "moves to", "", "Gulf of Lyons", "", "", "via convoy");
// Parenthesis location // Parenthesis location
yield return Test( yield return Test(
"F Spain(nc) - Spain(sc)", "F Spain(nc) - Spain(sc)",
@ -98,4 +106,57 @@ public class RegexTest
Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results"); Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results");
Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results"); Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
} }
static IEnumerable<TestCaseData> SupportHoldRegexMatchesTestCases()
{
static TestCaseData Test(string order, params string[] expected)
=> new TestCaseData(order, expected).SetName($"{{m}}(\"{order}\")");
// Full specification
yield return Test(
"Army a-Munich/l@0 s A a-Tyrolia/l@0",
"Army", "a", "Munich", "l", "0", "s", "A", "a", "Tyrolia", "l", "0");
// Case insensitivity
yield return Test(
"fleet B-lon/C@0 SUPPORTS B-enc/W@0",
"fleet", "B", "lon", "C", "0", "SUPPORTS", "", "B", "enc", "W", "0");
// All optionals missing
yield return Test(
"ROM s VIE",
"", "", "ROM", "", "", "s", "", "", "VIE", "", "");
// No confusion of unit type and timeline
yield return Test(
"A F-STP s MOS",
"A", "F", "STP", "", "", "s", "", "", "MOS", "", "");
// No confusion of timeline and support verb
yield return Test(
"A Mun s Tyr",
"A", "", "Mun", "", "", "s", "", "", "Tyr", "", "");
// Elements with spaces
yield return Test(
"Western Mediterranean Sea supports Gulf of Lyons",
"", "", "Western Mediterranean Sea", "", "", "supports", "", "", "Gulf of Lyons", "", "");
// Parenthesis location
yield return Test(
"F Spain(nc) s Spain(sc)",
"F", "", "Spain", "nc", "", "s", "", "", "Spain", "sc", "");
// Timeline designation spells out a province
yield return Test(
"A tyr-MUN(vie) s mun-TYR/vie",
"A", "tyr", "MUN", "vie", "", "s", "", "mun", "TYR", "vie", "");
}
[TestCaseSource(nameof(SupportHoldRegexMatchesTestCases))]
public void SupportHoldRegexMatches(string order, string[] expected)
{
OrderRegex re = new(World.WithStandardMap());
var match = re.SupportHold.Match(order);
Assert.True(match.Success, "Match failed");
var (type, timeline, province, location, turn, supportVerb,
targetType, targetTimeline, targetProvince, targetLocation, targetTurn) = OrderRegex.ParseSupportHold(match);
string[] actual = [type, timeline, province, location, turn, supportVerb,
targetType, targetTimeline, targetProvince, targetLocation, targetTurn];
// 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");
}
} }