aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/src/Godosa.Core.Tests/Runs/Scripts/VarsTests.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/VarsTests.cs
downloadgodosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.tar.gz
godosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.zip
godosa-engine: initial public history
Diffstat (limited to 'src/Godosa.Core.Tests/Runs/Scripts/VarsTests.cs')
-rw-r--r--src/Godosa.Core.Tests/Runs/Scripts/VarsTests.cs84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/Godosa.Core.Tests/Runs/Scripts/VarsTests.cs b/src/Godosa.Core.Tests/Runs/Scripts/VarsTests.cs
new file mode 100644
index 0000000..c6d3286
--- /dev/null
+++ b/src/Godosa.Core.Tests/Runs/Scripts/VarsTests.cs
@@ -0,0 +1,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
+ }
+}