func TestAugmentMap(t *testing.T) { type m map[string]interface{} var tests = []struct { arg1, arg2 map[string]interface{} expected map[string]interface{} }{ {m{}, m{}, m{}}, {m{"a": 0}, m{}, m{"a": 0}}, {m{}, m{"a": 0}, m{"a": 0}}, {m{"a": 0}, m{"a": 1}, m{"a": 1}}, {m{"a": 0}, m{"b": 1}, m{"a": 0, "b": 1}}, } for _, test := range tests { var actual = funcAugmentMap([]data.Value{data.New(test.arg1), data.New(test.arg2)}).(data.Map) if len(actual) != len(test.expected) { t.Errorf("augmentMap(%v, %v) => %v, expected %v", test.arg1, test.arg2, actual, test.expected) } for k, v := range actual { if v != data.New(test.expected[k]) { t.Errorf("augmentMap(%v, %v) => %v, expected %v", test.arg1, test.arg2, actual, test.expected) } } } }
func TestGlobals(t *testing.T) { globals["app.global_str"] = data.New("abc") globals["GLOBAL_INT"] = data.New(5) globals["global.nil"] = data.New(nil) runExecTests(t, []execTest{ exprtest("global", `{app.global_str} {GLOBAL_INT + 2} {global.nil?:'hi'}`, `abc 7 hi`), }) }
func TestStrContains(t *testing.T) { for _, test := range strContainsTests { actual := bool(funcStrContains([]data.Value{data.New(test.arg1), data.New(test.arg2)}).(data.Bool)) if actual != test.result { t.Errorf("strcontains %s %s => %v, expected %v", test.arg1, test.arg2, actual, test.result) } } }
func TestRound(t *testing.T) { type i []interface{} var tests = []struct { input []interface{} expected interface{} }{ {i{0}, 0}, {i{-5}, -5}, {i{5}, 5}, {i{1.01}, 1}, {i{1.99}, 2}, {i{1.0}, 1}, {i{-1.01}, -1}, {i{-1.99}, -2}, {i{-1.5}, -2}, {i{1.2345, 1}, 1.2}, {i{1.2345, 2}, 1.23}, {i{1.2345, 3}, 1.235}, {i{1.2345, 4}, 1.2345}, {i{-1.2345, 1}, -1.2}, {i{-1.2345, 2}, -1.23}, {i{-1.2345, 3}, -1.235}, {i{-1.2345, 4}, -1.2345}, {i{1.0, 5}, 1.0}, {i{123.456, -1}, 120}, {i{123.456, -2}, 100}, {i{123.456, -3}, 000}, } for _, test := range tests { var inputValues []data.Value for _, num := range test.input { inputValues = append(inputValues, data.New(num)) } actual := funcRound(inputValues) if len(inputValues) == 1 { // Passing one arg should have the same result as passing the second as 0 if actual != funcRound(append(inputValues, data.Int(0))) { t.Errorf("round %v returned %v, but changed when passed explicit 0", test.input, actual) } } if actual != data.New(test.expected) { t.Errorf("round %v => %v, expected %v", test.input, actual, test.expected) } } }
func TestEvalExpr(t *testing.T) { var tests = []struct { input string expected interface{} }{ {"0", 0}, {"1+1", 2}, {"'abc'", "abc"}, } for _, test := range tests { var tree, err = parse.SoyFile("", "{"+test.input+"}", nil) if err != nil { t.Error(err) return } actual, err := EvalExpr(tree) if err != nil { t.Error(err) continue } if actual != data.New(test.expected) { t.Errorf("EvalExpr(%v) => %v, expected %v", test.input, actual, test.expected) } } }
func TestMax(t *testing.T) { type i []interface{} var tests = []struct { input []interface{} expected interface{} }{ {i{0, 0}, 0}, {i{1, 2}, 2}, {i{1.1, 2}, 2.0}, // only returns int if both are ints. {i{-1.9, -1.8}, -1.8}, } for _, test := range tests { var actual = funcMax(data.New(test.input).(data.List)) if actual != data.New(test.expected) { t.Errorf("max(%v) => %v, expected %v", test.input, actual, test.expected) } } }
func TestMin(t *testing.T) { type i []interface{} var tests = []struct { input []interface{} expected interface{} }{ {i{0, 0}, 0}, {i{1, 2}, 1}, {i{1.1, 2}, 1.1}, {i{-1.9, -1.8}, -1.9}, } for _, test := range tests { var actual = funcMin(data.New(test.input).(data.List)) if actual != data.New(test.expected) { t.Errorf("min(%v) => %v, expected %v", test.input, actual, test.expected) } } }
func TestCeil(t *testing.T) { var tests = []struct { input interface{} expected interface{} }{ {0, 0}, {1, 1}, {1.1, 2}, {1.5, 2}, {1.99, 2}, {-1, -1}, {-1.1, -1}, {-1.9, -1}, } for _, test := range tests { var actual = funcCeiling([]data.Value{data.New(test.input)}) if actual != data.New(test.expected) { t.Errorf("ceiling(%v) => %v, expected %v", test.input, actual, test.expected) } } }
func TestKeys(t *testing.T) { type m map[string]interface{} type i []interface{} var tests = []struct { input map[string]interface{} expected []interface{} }{ {m{}, i{}}, {m{"a": 0}, i{"a"}}, } for _, test := range tests { var actual = funcKeys([]data.Value{data.New(test.input)}).(data.List) if len(actual) != len(test.expected) { t.Errorf("keys(%v) => %v, expected %v", test.input, actual, test.expected) } for i, v := range actual { if v != data.New(test.expected[i]) { t.Errorf("keys(%v) => %v, expected %v", test.input, actual, test.expected) } } } }
func (s *state) evalCall(node *ast.CallNode) { // get template node we're calling var calledTmpl, ok = s.registry.Template(node.Name) if !ok { s.errorf("failed to find template: %s", node.Name) } // sort out the data to pass var callData scope if node.AllData { callData = s.context.alldata() callData.push() } else if node.Data != nil { result, ok := s.eval(node.Data).(data.Map) if !ok { s.errorf("In 'call' command %q, the data reference %q does not resolve to a map.", node.String(), node.Data.String()) } callData = newScope(result) } else { callData = newScope(make(data.Map)) } // resolve the params for _, param := range node.Params { switch param := param.(type) { case *ast.CallParamValueNode: callData.set(param.Key, s.eval(param.Value)) case *ast.CallParamContentNode: callData.set(param.Key, data.New(string(s.renderBlock(param.Content)))) default: s.errorf("unexpected call param type: %T", param) } } callData.enter() state := &state{ tmpl: calledTmpl, registry: s.registry, namespace: calledTmpl.Namespace.Name, autoescape: calledTmpl.Namespace.Autoescape, wr: s.wr, context: callData, ij: s.ij, } state.walk(calledTmpl.Node) }
func TestRange(t *testing.T) { for _, test := range rangeTests { var args []data.Value for _, a := range test.args { args = append(args, data.New(a)) } result := funcRange(args).(data.List) if len(result) != len(test.result) { t.Errorf("%v => %v, expected %v", test.args, result, test.result) continue } for i, r := range test.result { if int64(result[i].(data.Int)) != int64(r) { t.Errorf("%v => %v, expected %v", test.args, result, test.result) break } } } }
func runNsExecTests(t *testing.T, tests []nsExecTest) { b := new(bytes.Buffer) for _, test := range tests { var registry = template.Registry{} for _, input := range test.input { var tree, err = parse.SoyFile("", input, globals) if err != nil { t.Errorf("%s: parse error: %s", test.name, err) continue } registry.Add(tree) } b.Reset() var datamap data.Map if test.data != nil { datamap = data.New(test.data).(data.Map) } err := NewTofu(®istry).NewRenderer(test.templateName). Inject(ij). Execute(b, datamap) switch { case !test.ok && err == nil: t.Errorf("%s: expected error; got none", test.name) continue case test.ok && err != nil: t.Errorf("%s: unexpected execute error: %s", test.name, err) continue case !test.ok && err != nil: // expected error, got one } result := b.String() if result != test.output { t.Errorf("%s: expected\n\t%q\ngot\n\t%q", test.name, test.output, result) } } }
func (s *scope) augment(m map[string]interface{}) { *s = append(*s, data.New(m).(data.Map)) }