hcl/integrationtest/convertfunc_test.go

57 lines
2.1 KiB
Go

package integrationtest
import (
"testing"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/ext/typeexpr"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
// TestTypeConvertFunc is an integration test of all of the layers involved
// in making the type conversion function from ext/typeexpr work.
//
// This requires co-operation between the hclsyntax package, the ext/typeexpr
// package, and the underlying cty functionality in order to work correctly.
//
// There are unit tests for the function implementation itself in the
// ext/typeexpr package, so this test is focused on making sure the function
// is given the opportunity to decode the second argument as a type expression
// when the function is called from HCL native syntax.
func TestTypeConvertFunc(t *testing.T) {
// The convert function is special because it takes a type expression
// rather than a value expression as its second argument. In this case,
// we're asking it to convert a tuple into a list of strings:
const exprSrc = `convert(["hello"], list(string))`
// It achieves this by marking that second argument as being of a custom
// type (a "capsule type", in cty terminology) that has a special
// annotation which hclsyntax.FunctionCallExpr understands as allowing
// the type to handle the analysis of the unevaluated expression, instead
// of evaluating it as normal.
//
// To see more details of how this works, look at the definitions of
// typexpr.TypeConstraintType and typeexpr.ConvertFunc, and at the
// implementation of hclsyntax.FunctionCallExpr.Value.
expr, diags := hclsyntax.ParseExpression([]byte(exprSrc), "", hcl.Pos{Line: 1, Column: 1})
if diags.HasErrors() {
t.Fatalf("unexpected problems: %s", diags.Error())
}
ctx := &hcl.EvalContext{
Functions: map[string]function.Function{
"convert": typeexpr.ConvertFunc,
},
}
got, diags := expr.Value(ctx)
if diags.HasErrors() {
t.Fatalf("unexpected problems: %s", diags.Error())
}
want := cty.ListVal([]cty.Value{cty.StringVal("hello")})
if !want.RawEquals(got) {
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, want)
}
}