aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/src/Godosa.Core.Tests/Runs/Scripts/RunReportTests.cs
blob: 00ee4b0db63568d9124ed37fe9bce547bc1e2b7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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<string> Output) Run(string main, FakeGame g, ScriptRunOptions o, Dictionary<string, string>? files = null)
    {
        var all = new Dictionary<string, string>(files ?? []) { ["main.steps"] = main };
        var output = new List<string>();
        var runner = new ScriptRunner(ScriptLoader.Load("main.steps", new MemoryScriptSource(all), new Dictionary<string, string>()), 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));
    }
}