diff options
| author | godosa <godosa@godosa.eu> | 2026-10-06 23:39:36 +0200 |
|---|---|---|
| committer | godosa <godosa@godosa.eu> | 2026-10-06 23:39:36 +0200 |
| commit | 39066900773e7857faf2d02e7ed51b71d219d97d (patch) | |
| tree | ffab8e4ddd971626776c3b1f4ce1da2c186c2187 /src/Godosa.Core.Tests/Runs/Scripts/ConditionTests.cs | |
| download | godosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.tar.gz godosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.zip | |
godosa-engine: initial public history
Diffstat (limited to 'src/Godosa.Core.Tests/Runs/Scripts/ConditionTests.cs')
| -rw-r--r-- | src/Godosa.Core.Tests/Runs/Scripts/ConditionTests.cs | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/Godosa.Core.Tests/Runs/Scripts/ConditionTests.cs b/src/Godosa.Core.Tests/Runs/Scripts/ConditionTests.cs new file mode 100644 index 0000000..d14ea6a --- /dev/null +++ b/src/Godosa.Core.Tests/Runs/Scripts/ConditionTests.cs @@ -0,0 +1,63 @@ +using Godosa.Core.Runs.Scripts; +using Xunit; + +namespace Godosa.Core.Tests.Runs.Scripts; + +public class ConditionTests +{ + private sealed class Ctx : IConditionContext + { + public Dictionary<string, RunValue> Values { get; } = new() + { + ["quest(1)"] = RunValue.Of(2), ["map"] = RunValue.Of("tarant"), ["dialog-open"] = RunValue.Of(true), + ["global(gold)"] = RunValue.Of(500), ["alive"] = RunValue.Of(false), + }; + + public bool HasProbe(string name) => name is "quest" or "map" or "dialog-open" or "global" or "alive"; + + public RunValue Probe(string name, IReadOnlyList<string> args) => + Values[args.Count == 0 ? name : $"{name}({string.Join(",", args)})"]; + + public long? Constant(string name) => name switch { "accepted" => 2, "completed" => 4, _ => null }; + } + + private static bool Test(string text) => ConditionParser.Parse(text).Test(new Ctx()); + + [Theory] + [InlineData("quest(1) >= accepted", true)] + [InlineData("quest(1) = completed", false)] + [InlineData("map = \"tarant\"", true)] + [InlineData("map != \"ashbury\"", true)] + [InlineData("dialog-open", true)] + [InlineData("alive", false)] + [InlineData("not alive", true)] + [InlineData("dialog-open and global(gold) > 499", true)] + [InlineData("alive or global(gold) < 100", false)] + [InlineData("not (alive or dialog-open)", false)] + [InlineData("alive or dialog-open and quest(1) = 2", true)] // and binds tighter than or + [InlineData("global(gold) <= 500", true)] + public void Evaluates(string text, bool expected) => Assert.Equal(expected, Test(text)); + + [Fact] + public void MismatchedTypes_Fault() => + Assert.Equal("cannot compare tarant with 3", Assert.Throws<ScriptFault>(() => Test("map > 3")).Message); + + [Theory] + [InlineData("quest(1) >=")] + [InlineData("(alive")] + [InlineData("alive alive")] + [InlineData("\"open")] + public void BadSyntax_Throws(string text) => Assert.Throws<FormatException>(() => ConditionParser.Parse(text)); + + [Fact] + public void ListsProbesAndBareNames() + { + var c = ConditionParser.Parse("quest(1) >= accepted and not dialog-open"); + Assert.Equal(["quest(1)", "accepted", "dialog-open"], c.Probes().Select(p => p.Args.Count == 0 ? p.Name : $"{p.Name}({string.Join(",", p.Args)})")); + Assert.Equal(["accepted", "dialog-open"], c.Bare()); + } + + [Fact] + public void Describe_ListsProbeValues() => + Assert.Equal("quest(1)=2 map=tarant", Cond.Describe(ConditionParser.Parse("quest(1) > 3 and map = \"x\""), new Ctx())); +} |
