blob: 633c6d8cb3c8dc2eed8d258371411704a1568f20 [file] [log] [blame] [edit]
package userfunc
import (
"fmt"
"testing"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty/cty"
)
func TestDecodeUserFunctions(t *testing.T) {
tests := []struct {
src string
testExpr string
baseCtx *hcl.EvalContext
want cty.Value
diagCount int
}{
{
`
function "greet" {
params = [name]
result = "Hello, ${name}."
}
`,
`greet("Ermintrude")`,
nil,
cty.StringVal("Hello, Ermintrude."),
0,
},
{
`
function "greet" {
params = [name]
result = "Hello, ${name}."
}
`,
`greet()`,
nil,
cty.DynamicVal,
1, // missing value for "name"
},
{
`
function "greet" {
params = [name]
result = "Hello, ${name}."
}
`,
`greet("Ermintrude", "extra")`,
nil,
cty.DynamicVal,
1, // too many arguments
},
{
`
function "add" {
params = [a, b]
result = a + b
}
`,
`add(1, 5)`,
nil,
cty.NumberIntVal(6),
0,
},
{
`
function "argstuple" {
params = []
variadic_param = args
result = args
}
`,
`argstuple("a", true, 1)`,
nil,
cty.TupleVal([]cty.Value{cty.StringVal("a"), cty.True, cty.NumberIntVal(1)}),
0,
},
{
`
function "missing_var" {
params = []
result = nonexist
}
`,
`missing_var()`,
nil,
cty.DynamicVal,
1, // no variable named "nonexist"
},
{
`
function "closure" {
params = []
result = upvalue
}
`,
`closure()`,
&hcl.EvalContext{
Variables: map[string]cty.Value{
"upvalue": cty.True,
},
},
cty.True,
0,
},
{
`
function "neg" {
params = [val]
result = -val
}
function "add" {
params = [a, b]
result = a + b
}
`,
`neg(add(1, 3))`,
nil,
cty.NumberIntVal(-4),
0,
},
{
`
function "neg" {
parrams = [val]
result = -val
}
`,
`null`,
nil,
cty.NullVal(cty.DynamicPseudoType),
2, // missing attribute "params", and unknown attribute "parrams"
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
f, diags := hclsyntax.ParseConfig([]byte(test.src), "config", hcl.Pos{Line: 1, Column: 1})
if f == nil || f.Body == nil {
t.Fatalf("got nil file or body")
}
funcs, _, funcsDiags := decodeUserFunctions(f.Body, "function", func() *hcl.EvalContext {
return test.baseCtx
})
diags = append(diags, funcsDiags...)
expr, exprParseDiags := hclsyntax.ParseExpression([]byte(test.testExpr), "testexpr", hcl.Pos{Line: 1, Column: 1})
diags = append(diags, exprParseDiags...)
if expr == nil {
t.Fatalf("parsing test expr returned nil")
}
got, exprDiags := expr.Value(&hcl.EvalContext{
Functions: funcs,
})
diags = append(diags, exprDiags...)
if len(diags) != test.diagCount {
t.Errorf("wrong number of diagnostics %d; want %d", len(diags), test.diagCount)
for _, diag := range diags {
t.Logf("- %s", diag)
}
}
if !got.RawEquals(test.want) {
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.want)
}
})
}
}