aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/src/Godosa.Core.Tests/Runs/Scripts/VarsTests.cs
blob: c6d3286175579d2df7448cd590db90fb3791f145 (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
84
using Godosa.Core.Runs.Scripts;
using Xunit;

namespace Godosa.Core.Tests.Runs.Scripts;

public class VarsTests
{
    private static readonly Dictionary<string, string> Values = new()
    {
        ["res"] = "1920x1080", ["hours"] = "8", ["ui.rest.8"] = "400,300", ["a"] = "b", ["b"] = "deep",
    };

    private static string Expand(string text) => VarExpander.Expand(text, n => Values.GetValueOrDefault(n),
        p => p == "global(gold)" ? RunValue.Of(1250) : throw new ScriptFault($"no probe {p}"));

    [Theory]
    [InlineData("ui/${res}.vars", "ui/1920x1080.vars")]
    [InlineData("click ${ui.rest.${hours}}", "click 400,300")]
    [InlineData("${${a}}", "deep")]
    [InlineData("gold ${probe:global(gold)}", "gold 1250")]
    [InlineData("cost $5 and $", "cost $5 and $")] // review focus 4: lone $ is literal
    [InlineData("no vars", "no vars")]
    public void Expand_Values(string text, string expected) => Assert.Equal(expected, Expand(text));

    [Theory]
    [InlineData("${missing}", "unresolved variable ${missing}")]
    [InlineData("x ${a", "unclosed ${ in 'x ${a'")]
    [InlineData("${}", "empty ${}")]
    public void Expand_Errors_AreFaults(string text, string message) =>
        Assert.Equal(message, Assert.Throws<ScriptFault>(() => Expand(text)).Message);

    [Fact]
    public void Names_InnermostPlainOnly() =>
        Assert.Equal(["hours", "res"], VarExpander.Names("${ui.${hours}} ${res} ${probe:quest(1)}").Order());

    [Fact]
    public void VarsFile_ParsesAndReportsBadLines()
    {
        var (values, errors) = VarsFile.Parse("ui/hd.vars", "# hd\nui.answer1 = 412,520\n\nui.rest.8=400,300\nbroken line\n");
        Assert.Equal("412,520", values["ui.answer1"]);
        Assert.Equal("400,300", values["ui.rest.8"]);
        Assert.Equal(["ui/hd.vars:5: bad vars line (name = value)"], errors.Select(e => e.ToString()));
    }

    [Fact]
    public void Scopes_SetGoesToLocalOrRoot()
    {
        var s = new VarScopes(OutputLevel.Labels);
        s.Set("g", "1");
        s.Push(local: false, OutputLevel.Labels, []); // include
        s.Set("inc", "2");                             // global: root
        s.Push(local: true, OutputLevel.Labels, [new("p", "x")]); // def call
        s.Set("loc", "3");
        Assert.Equal(("1", "2", "3", "x"), (s.Get("g"), s.Get("inc"), s.Get("loc"), s.Get("p")));
        s.Pop();
        Assert.Null(s.Get("loc"));
        Assert.Null(s.Get("p"));
        s.Pop();
        Assert.Equal("2", s.Get("inc"));
    }

    [Fact]
    public void Scopes_OutputLevelRestoredOnPop()
    {
        var s = new VarScopes(OutputLevel.Labels);
        s.Push(local: false, s.Level, []);
        s.Level = OutputLevel.Trace;
        s.Pop();
        Assert.Equal(OutputLevel.Labels, s.Level);
    }

    [Fact]
    public void Scopes_SnapshotRestore_RoundTrips()
    {
        var s = new VarScopes(OutputLevel.Labels);
        s.Set("g", "1");
        s.Push(local: true, OutputLevel.Steps, [new("p", "x")]);
        var copy = new VarScopes(OutputLevel.Quiet);
        copy.Restore(s.Snapshot());
        Assert.Equal(("1", "x", OutputLevel.Steps), (copy.Get("g"), copy.Get("p"), copy.Level));
        s.Set("p", "changed");
        Assert.Equal("x", copy.Get("p")); // deep copy
    }
}