blob: 5b01d0224bf99ca4c1bfd32c5da6856f6737af42 [file] [log] [blame] [edit]
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)
}
})
}
}