aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/src/Godosa.Core.Tests/Runs/Scripts/ScriptValidatorTests.cs
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-06 23:39:36 +0200
committergodosa <godosa@godosa.eu>2026-10-06 23:39:36 +0200
commit39066900773e7857faf2d02e7ed51b71d219d97d (patch)
treeffab8e4ddd971626776c3b1f4ce1da2c186c2187 /src/Godosa.Core.Tests/Runs/Scripts/ScriptValidatorTests.cs
downloadgodosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.tar.gz
godosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.zip
godosa-engine: initial public history
Diffstat (limited to 'src/Godosa.Core.Tests/Runs/Scripts/ScriptValidatorTests.cs')
-rw-r--r--src/Godosa.Core.Tests/Runs/Scripts/ScriptValidatorTests.cs63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/Godosa.Core.Tests/Runs/Scripts/ScriptValidatorTests.cs b/src/Godosa.Core.Tests/Runs/Scripts/ScriptValidatorTests.cs
new file mode 100644
index 0000000..98dcc73
--- /dev/null
+++ b/src/Godosa.Core.Tests/Runs/Scripts/ScriptValidatorTests.cs
@@ -0,0 +1,63 @@
+using Godosa.Core.Runs.Scripts;
+using Xunit;
+
+namespace Godosa.Core.Tests.Runs.Scripts;
+
+public class ScriptValidatorTests
+{
+ private static FakeGame Game()
+ {
+ var g = new FakeGame();
+ g.ProbeFns["quest"] = _ => RunValue.Of(0);
+ g.ProbeFns["dialog-open"] = _ => RunValue.Of(false);
+ g.ActionTable["talk"] = new FakeAction(VerbKind.Player, _ => new ActionStart(), min: 1, max: 1);
+ g.ActionTable["cheat"] = new FakeAction(VerbKind.Debug, _ => new ActionStart(Status: StepStatus.Done), min: 1, max: 20);
+ return g;
+ }
+
+ private static string Validate(string main, bool deterministic = true, FakeGame? game = null) =>
+ string.Join(" | ", ScriptValidator.Validate(
+ ScriptLoader.Load("main.steps", new MemoryScriptSource(new Dictionary<string, string> { ["main.steps"] = main }), new Dictionary<string, string>()),
+ game ?? Game(), deterministic).Select(e => e.ToString()));
+
+ [Fact]
+ public void ValidPlayerScript_NoErrors() =>
+ Assert.Equal("", Validate("format 1\nmode player\nsetup:\n cheat gold 5\ntalk @obj(Virgil)\nwait dialog-open 2s\nexpect quest(1) >= accepted\nclick 1,2\nkey R\nlog \"hi\""));
+
+ [Theory]
+ [InlineData("format 1\nmode player\ndance", "main.steps:3: unknown verb dance")]
+ [InlineData("format 1\nmode player\nwalk-to 3,4", "main.steps:3: verb walk-to not supported by game fake")]
+ [InlineData("format 1\nmode player\nclick", "main.steps:3: verb click takes 1..1 arguments, got 0")]
+ [InlineData("format 1\nmode player\ncheat gold 5", "main.steps:3: debug verb cheat outside setup in player mode")]
+ [InlineData("format 1\nmode player\nwait nope 10", "main.steps:3: unknown probe or constant nope")]
+ [InlineData("format 1\nmode player\nexpect quest(1) >=", "main.steps:3: condition ends early")]
+ [InlineData("format 1\nmode player\ntalk @npc(Virgil)", "main.steps:3: unknown locator @npc")]
+ [InlineData("format 1\nmode player\ntry:\n key R", "main.steps:3: try needs a non-deterministic run")]
+ [InlineData("format 1\nmode player\noutput loud", "main.steps:3: output level must be quiet|checkpoints|labels|steps|trace")]
+ public void Errors(string main, string error) => Assert.Contains(error, Validate(main));
+
+ [Fact]
+ public void DebugMode_DebugVerbAnywhere() => Assert.Equal("", Validate("format 1\nmode debug\ncheat gold 5\nkey R"));
+
+ [Fact]
+ public void Try_AllowedNonDeterministic() => Assert.Equal("", Validate("format 1\nmode player\ntry:\n key R", deterministic: false));
+
+ [Fact]
+ public void Rng_NeedsTheGameHook()
+ {
+ var g = Game();
+ g.RngImpl = null;
+ Assert.Contains("main.steps:3: verb rng not supported by game fake", Validate("format 1\nmode player\nrng seed 4", game: g));
+ }
+
+ [Fact]
+ public void GameVerb_ShadowingALibVerbWithAnotherKind_Rejected()
+ {
+ var g = Game();
+ g.ActionTable["click"] = new FakeAction(VerbKind.Debug, _ => new ActionStart());
+ Assert.Contains("game verb click shadows a lib verb", Validate("format 1\nmode debug\nkey R", game: g));
+ }
+
+ [Fact]
+ public void LoaderErrorsComeThrough() => Assert.Contains("main.steps:3: unknown def x", Validate("format 1\nmode debug\ncall x()"));
+}