hcl/hcltest/mock_test.go
James Bardin 94baef9aa6 add an ExprMap method to the mock expression
Add an ExprMethod so that the mock expressions can be handled by the
hcl.ExprMap function.

Added basic tests for both ExprList and ExprMap
2021-02-08 15:52:16 -05:00

396 lines
8.3 KiB
Go

package hcltest
import (
"strings"
"testing"
"reflect"
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"
)
var mockBodyIsBody hcl.Body = mockBody{}
var mockExprLiteralIsExpr hcl.Expression = mockExprLiteral{}
var mockExprVariableIsExpr hcl.Expression = mockExprVariable("")
func TestMockBodyPartialContent(t *testing.T) {
tests := map[string]struct {
In *hcl.BodyContent
Schema *hcl.BodySchema
Want *hcl.BodyContent
Remain *hcl.BodyContent
DiagCount int
}{
"empty": {
&hcl.BodyContent{},
&hcl.BodySchema{},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
0,
},
"attribute requested": {
&hcl.BodyContent{
Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")),
}),
},
&hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "name",
},
},
},
&hcl.BodyContent{
Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")),
}),
Blocks: hcl.Blocks{},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
0,
},
"attribute remains": {
&hcl.BodyContent{
Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")),
}),
},
&hcl.BodySchema{},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
&hcl.BodyContent{
Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")),
}),
Blocks: hcl.Blocks{},
},
0,
},
"attribute missing": {
&hcl.BodyContent{
Attributes: hcl.Attributes{},
},
&hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "name",
Required: true,
},
},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
1, // missing attribute "name"
},
"block requested, no labels": {
&hcl.BodyContent{
Blocks: hcl.Blocks{
{
Type: "baz",
},
},
},
&hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{
Type: "baz",
},
},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{
{
Type: "baz",
},
},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
0,
},
"block requested, wrong labels": {
&hcl.BodyContent{
Blocks: hcl.Blocks{
{
Type: "baz",
},
},
},
&hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{
Type: "baz",
LabelNames: []string{"foo"},
},
},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{
{
Type: "baz",
},
},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
1, // "baz" requires 1 label
},
"block remains": {
&hcl.BodyContent{
Blocks: hcl.Blocks{
{
Type: "baz",
},
},
},
&hcl.BodySchema{},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{},
},
&hcl.BodyContent{
Attributes: hcl.Attributes{},
Blocks: hcl.Blocks{
{
Type: "baz",
},
},
},
0,
},
"various": {
&hcl.BodyContent{
Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")),
"age": MockExprLiteral(cty.NumberIntVal(32)),
}),
Blocks: hcl.Blocks{
{
Type: "baz",
},
{
Type: "bar",
Labels: []string{"foo1"},
},
{
Type: "bar",
Labels: []string{"foo2"},
},
},
},
&hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "name",
},
},
Blocks: []hcl.BlockHeaderSchema{
{
Type: "bar",
LabelNames: []string{"name"},
},
},
},
&hcl.BodyContent{
Attributes: MockAttrs(map[string]hcl.Expression{
"name": MockExprLiteral(cty.StringVal("Ermintrude")),
}),
Blocks: hcl.Blocks{
{
Type: "bar",
Labels: []string{"foo1"},
},
{
Type: "bar",
Labels: []string{"foo2"},
},
},
},
&hcl.BodyContent{
Attributes: MockAttrs(map[string]hcl.Expression{
"age": MockExprLiteral(cty.NumberIntVal(32)),
}),
Blocks: hcl.Blocks{
{
Type: "baz",
},
},
},
0,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
inBody := MockBody(test.In)
got, remainBody, diags := inBody.PartialContent(test.Schema)
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 !reflect.DeepEqual(got, test.Want) {
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
}
gotRemain := remainBody.(mockBody).C
if !reflect.DeepEqual(gotRemain, test.Remain) {
t.Errorf("wrong remain\ngot: %#v\nwant: %#v", gotRemain, test.Remain)
}
})
}
}
func TestExprList(t *testing.T) {
tests := map[string]struct {
In hcl.Expression
Want []hcl.Expression
Diags string
}{
"as list": {
In: MockExprLiteral(cty.ListVal([]cty.Value{
cty.StringVal("foo"),
cty.StringVal("bar"),
})),
Want: []hcl.Expression{
MockExprLiteral(cty.StringVal("foo")),
MockExprLiteral(cty.StringVal("bar")),
},
},
"as tuple": {
In: MockExprLiteral(cty.TupleVal([]cty.Value{
cty.StringVal("foo"),
cty.StringVal("bar"),
})),
Want: []hcl.Expression{
MockExprLiteral(cty.StringVal("foo")),
MockExprLiteral(cty.StringVal("bar")),
},
},
"not list": {
In: MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("foo"),
"b": cty.StringVal("bar"),
})),
Want: nil,
Diags: "list expression is required",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
got, diags := hcl.ExprList(tc.In)
if tc.Diags != "" {
if diags.HasErrors() && !strings.Contains(diags.Error(), tc.Diags) {
t.Errorf("expected error %q, got %q", tc.Diags, diags)
}
if !diags.HasErrors() {
t.Errorf("expected diagnostic message %q", tc.Diags)
}
} else if diags.HasErrors() {
t.Error(diags)
}
if !reflect.DeepEqual(got, tc.Want) {
t.Errorf("incorrect expression,\ngot: %#v\nwant: %#v", got, tc.Want)
}
})
}
}
func TestExprMap(t *testing.T) {
tests := map[string]struct {
In hcl.Expression
Want []hcl.KeyValuePair
Diags string
}{
"as object": {
In: MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("test"),
"count": cty.NumberIntVal(2),
})),
Want: []hcl.KeyValuePair{
{
Key: MockExprLiteral(cty.StringVal("count")),
Value: MockExprLiteral(cty.NumberIntVal(2)),
},
{
Key: MockExprLiteral(cty.StringVal("name")),
Value: MockExprLiteral(cty.StringVal("test")),
},
},
},
"as map": {
In: MockExprLiteral(cty.MapVal(map[string]cty.Value{
"name": cty.StringVal("test"),
"version": cty.StringVal("2.0.0"),
})),
Want: []hcl.KeyValuePair{
{
Key: MockExprLiteral(cty.StringVal("name")),
Value: MockExprLiteral(cty.StringVal("test")),
},
{
Key: MockExprLiteral(cty.StringVal("version")),
Value: MockExprLiteral(cty.StringVal("2.0.0")),
},
},
},
"not map": {
In: MockExprLiteral(cty.ListVal([]cty.Value{
cty.StringVal("foo"),
cty.StringVal("bar"),
})),
Want: nil,
Diags: "map expression is required",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
got, diags := hcl.ExprMap(tc.In)
if tc.Diags != "" {
if diags.HasErrors() && !strings.Contains(diags.Error(), tc.Diags) {
t.Errorf("expected error %q, got %q", tc.Diags, diags)
}
if !diags.HasErrors() {
t.Errorf("expected diagnostic message %q", tc.Diags)
}
} else if diags.HasErrors() {
t.Error(diags)
}
if !reflect.DeepEqual(got, tc.Want) {
t.Errorf("incorrect expression,\ngot: %#v\nwant: %#v", got, tc.Want)
}
})
}
}