1// SPDX-License-Identifier: MIT
2
3package expr
4
5import (
6 "context"
7 "strings"
8 "testing"
9)
10
11// mustJSON parses JSON text into a Value or fails the test.
12func mustJSON(tb testing.TB, s string) Value {
13 tb.Helper()
14 v, err := FromJSON([]byte(s))
15 if err != nil {
16 tb.Fatalf("FromJSON(%q): %v", s, err)
17 }
18 return v
19}
20
21// testContexts is the environment of the table tests.
22func testContexts(tb testing.TB) map[string]Value {
23 tb.Helper()
24 return map[string]Value{
25 "github": mustJSON(tb, `{
26 "event_name": "push",
27 "ref": "refs/heads/main",
28 "actor": "Octocat",
29 "run_number": 7,
30 "event": {
31 "number": 12,
32 "commits": [
33 {"id": "1", "message": "fix: bug", "author": {"name": "Ann"}, "added": ["a.txt"]},
34 {"id": "2", "message": "feat: thing", "author": {"name": "Bob"}, "added": []},
35 {"id": "3", "message": "Chore", "added": ["b", "c"]}
36 ],
37 "issue": {"labels": [{"name": "bug"}, {"name": "Docs"}]},
38 "nested": [[1, 2], [3], [], [4, 5, 6]]
39 }
40 }`),
41 "env": mustJSON(tb, `{"FOO": "bar", "EMPTY": "", "NUM": "42", "Mixed": "MiXeD"}`),
42 "matrix": mustJSON(tb, `{"os": "ubuntu", "node": [14, 16, 18], "nothing": null, "ver": "3.10", "obj": {"k": "v"}}`),
43 "inputs": mustJSON(tb, `{"name": "World", "count": 3, "deploy": false, "empty": {}}`),
44 "steps": mustJSON(tb, `{"10": {"outputs": {"r": "ten"}}, "2": {"outputs": {"r": "two"}}}`),
45 }
46}
47
48var testContextNames = []string{"github", "env", "matrix", "inputs", "steps"}
49
50// evalString parses and evaluates src against the test contexts and returns
51// the result as "kind:string" or the error text prefixed by "ERR ".
52func evalString(tb testing.TB, src string) string {
53 tb.Helper()
54 node, err := Parse(src, testContextNames, nil)
55 if err != nil {
56 // The runner appends ". Located at position N within expression: ..."
57 // to errors that name a token; TestRunnerErrorPositions covers that.
58 msg, _, _ := strings.Cut(err.Error(), ". Located at position ")
59 return "PARSE " + msg
60 }
61 v, err := Evaluate(context.Background(), node, EvalContext{Contexts: testContexts(tb)})
62 if err != nil {
63 return "ERR " + err.Error()
64 }
65 return v.Kind().String() + ":" + CoerceString(v)
66}