2b442985cd
This is the first non-trivial expression Value implementation. Lots of code here, so hopefully while implementing other expressions some opportunities emerge to factor out some of these details.
189 lines
3.6 KiB
Go
189 lines
3.6 KiB
Go
package zclsyntax
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/apparentlymart/go-cty/cty"
|
|
"github.com/apparentlymart/go-cty/cty/function"
|
|
"github.com/apparentlymart/go-cty/cty/function/stdlib"
|
|
"github.com/apparentlymart/go-zcl/zcl"
|
|
)
|
|
|
|
func TestFunctionCallExprValue(t *testing.T) {
|
|
funcs := map[string]function.Function{
|
|
"length": stdlib.StrlenFunc,
|
|
"jsondecode": stdlib.JSONDecodeFunc,
|
|
}
|
|
|
|
tests := map[string]struct {
|
|
expr *FunctionCallExpr
|
|
ctx *zcl.EvalContext
|
|
want cty.Value
|
|
diagCount int
|
|
}{
|
|
"valid call with no conversions": {
|
|
&FunctionCallExpr{
|
|
Name: "length",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.StringVal("hello"),
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.NumberIntVal(5),
|
|
0,
|
|
},
|
|
"valid call with arg conversion": {
|
|
&FunctionCallExpr{
|
|
Name: "length",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.BoolVal(true),
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.NumberIntVal(4), // length of string "true"
|
|
0,
|
|
},
|
|
"valid call with unknown arg": {
|
|
&FunctionCallExpr{
|
|
Name: "length",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.UnknownVal(cty.String),
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.UnknownVal(cty.Number),
|
|
0,
|
|
},
|
|
"valid call with unknown arg needing conversion": {
|
|
&FunctionCallExpr{
|
|
Name: "length",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.UnknownVal(cty.Bool),
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.UnknownVal(cty.Number),
|
|
0,
|
|
},
|
|
"valid call with dynamic arg": {
|
|
&FunctionCallExpr{
|
|
Name: "length",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.DynamicVal,
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.UnknownVal(cty.Number),
|
|
0,
|
|
},
|
|
"invalid arg type": {
|
|
&FunctionCallExpr{
|
|
Name: "length",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.ListVal([]cty.Value{cty.StringVal("hello")}),
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.DynamicVal,
|
|
1,
|
|
},
|
|
"function with dynamic return type": {
|
|
&FunctionCallExpr{
|
|
Name: "jsondecode",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.StringVal(`"hello"`),
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.StringVal("hello"),
|
|
0,
|
|
},
|
|
"function with dynamic return type unknown arg": {
|
|
&FunctionCallExpr{
|
|
Name: "jsondecode",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.UnknownVal(cty.String),
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.DynamicVal, // type depends on arg value
|
|
0,
|
|
},
|
|
"error in function": {
|
|
&FunctionCallExpr{
|
|
Name: "jsondecode",
|
|
Args: []Expression{
|
|
&LiteralValueExpr{
|
|
Val: cty.StringVal("invalid-json"),
|
|
},
|
|
},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.DynamicVal,
|
|
1, // JSON parse error
|
|
},
|
|
"unknown function": {
|
|
&FunctionCallExpr{
|
|
Name: "lenth",
|
|
Args: []Expression{},
|
|
},
|
|
&zcl.EvalContext{
|
|
Functions: funcs,
|
|
},
|
|
cty.DynamicVal,
|
|
1,
|
|
},
|
|
}
|
|
|
|
for name, test := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
got, diags := test.expr.Value(test.ctx)
|
|
|
|
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.Error())
|
|
}
|
|
}
|
|
|
|
if !got.RawEquals(test.want) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|