From 39066900773e7857faf2d02e7ed51b71d219d97d Mon Sep 17 00:00:00 2001 From: godosa Date: Tue, 6 Oct 2026 23:39:36 +0200 Subject: godosa-engine: initial public history --- .../Runs/Scripts/RunReportTests.cs | 83 ++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/Godosa.Core.Tests/Runs/Scripts/RunReportTests.cs (limited to 'src/Godosa.Core.Tests/Runs/Scripts/RunReportTests.cs') diff --git a/src/Godosa.Core.Tests/Runs/Scripts/RunReportTests.cs b/src/Godosa.Core.Tests/Runs/Scripts/RunReportTests.cs new file mode 100644 index 0000000..00ee4b0 --- /dev/null +++ b/src/Godosa.Core.Tests/Runs/Scripts/RunReportTests.cs @@ -0,0 +1,83 @@ +using System.Text.Json; +using Godosa.Core.Runs; +using Godosa.Core.Runs.Scripts; +using Xunit; + +namespace Godosa.Core.Tests.Runs.Scripts; + +public sealed class RunReportTests : IDisposable +{ + private readonly string _dir = Path.Combine(AppContext.BaseDirectory, "rs-tmp", Guid.NewGuid().ToString("N")); + + public void Dispose() + { + if (Directory.Exists(_dir)) + Directory.Delete(_dir, recursive: true); + } + + private static (ScriptRunner Runner, RunResult Result, List Output) Run(string main, FakeGame g, ScriptRunOptions o, Dictionary? files = null) + { + var all = new Dictionary(files ?? []) { ["main.steps"] = main }; + var output = new List(); + var runner = new ScriptRunner(ScriptLoader.Load("main.steps", new MemoryScriptSource(all), new Dictionary()), g, o, output.Add); + return (runner, runner.Run(10_000), output); + } + + [Fact] + public void Failure_ReportHoldsChainStepReasonRecentDumpVars() + { + var g = new FakeGame { State = 7 }; + g.ProbeFns["quest"] = _ => RunValue.Of(1); + var (runner, _, _) = Run("format 1\nmode player\nset who = Gilbert\nkey A\ninclude act2.steps", g, new ScriptRunOptions { ReportDir = _dir }, + new() { ["act2.steps"] = "format 1\nstep talk-gilbert:\n key B\n expect quest(5) >= accepted" }); + var f = runner.Report!.Failure!; + Assert.Equal("act2.steps:4", f.At); + Assert.Equal(["main.steps:5"], f.Chain); + Assert.Equal(("expect quest(5) >= accepted", "talk-gilbert"), (f.Step, f.Label)); + Assert.Equal("expect failed: quest(5) >= accepted (quest(5)=1)", f.Reason); + Assert.Equal(["main.steps:4 key A f=2", "act2.steps:3 key B f=4"], f.Recent); + Assert.Equal("state=7 frame=4", f.Dump); + Assert.Equal("Gilbert", f.Vars["who"]); + Assert.True(File.Exists(Path.Combine(_dir, "report.txt"))); + Assert.True(File.Exists(Path.Combine(_dir, "fail.snap"))); + var json = JsonDocument.Parse(File.ReadAllText(Path.Combine(_dir, "report.json"))); + Assert.Equal("Failed", json.RootElement.GetProperty("Outcome").GetString()); + var text = File.ReadAllText(Path.Combine(_dir, "report.txt")); + Assert.Contains("main.steps:5 → act2.steps:4", text); + Assert.Contains("state=7 frame=4", text); + } + + [Fact] + public void Recent_KeepsLast20() + { + var g = new FakeGame(); + g.ProbeFns["no"] = _ => RunValue.Of(false); + var steps = string.Join("\n", Enumerable.Range(1, 25).Select(n => $"key K{n}")); + var (runner, _, _) = Run($"format 1\nmode player\n{steps}\nexpect no", g, new ScriptRunOptions()); + var recent = runner.Report!.Failure!.Recent; + Assert.Equal(20, recent.Count); + Assert.StartsWith("main.steps:8 key K6", recent[0]); + } + + [Fact] + public void Summary_StepsFramesCheckpointsDigests() + { + var g = new FakeGame { State = 3 }; + var (runner, r, output) = Run("format 1\nmode player\nkey A\ncheckpoint one\nstep s:\n key B", g, new ScriptRunOptions { Seed = 9 }); + var rep = runner.Report!; + Assert.Equal((RunOutcome.Passed, 4L, 2, 9UL), (rep.Outcome, rep.Frames, rep.Steps, rep.Seed)); + // Digest = State * 1_000_003 + Frame (FakeGame), at frame 2: 3 * 1000003 + 2 = 3000011. + Assert.Equal([new CheckpointRecord("one", 2, 3000011UL.ToString("x16"), "replayed")], rep.Checkpoints); + Assert.Contains(DigestLine.Format(2, 2 / 60.0, 3000011UL), output); + Assert.Contains(DigestLine.Format(4, 4 / 60.0, 3000013UL), output); // after the labelled step + } + + [Fact] + public void NonDeterministic_NoDigestLines_FlagInReport() + { + var (runner, _, output) = Run("format 1\nmode player\ncheckpoint one", new FakeGame(), new ScriptRunOptions { Deterministic = false }); + Assert.DoesNotContain(output, l => l.StartsWith("digest ")); + Assert.False(runner.Report!.Deterministic); + Assert.Contains("deterministic: no", ReportWriter.Text(runner.Report)); + } +} -- cgit