blob: f000a54196badf5ad74d0dcce2dc390736274adb [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package stackaddrs
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty-debug/ctydebug"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/internal/tfdiags"
)
func TestParseRemovedFrom(t *testing.T) {
mustExpr := func(t *testing.T, expr string) hcl.Expression {
ret, diags := hclsyntax.ParseExpression([]byte(expr), "", hcl.InitialPos)
if diags.HasErrors() {
t.Fatal(diags.Error())
}
return ret
}
tcs := []struct {
from string
component Component
index cty.Value
vars map[string]cty.Value
diags func() tfdiags.Diagnostics
}{
{
from: "component.component_name",
component: Component{
Name: "component_name",
},
},
{
from: "component.component_name[0]",
component: Component{
Name: "component_name",
},
index: cty.NumberIntVal(0),
},
{
from: "component.component_name[\"key\"]",
component: Component{
Name: "component_name",
},
index: cty.StringVal("key"),
},
{
from: "component.component_name[each.key]",
component: Component{
Name: "component_name",
},
index: cty.StringVal("key"),
vars: map[string]cty.Value{
"each": cty.ObjectVal(map[string]cty.Value{
"key": cty.StringVal("key"),
}),
},
},
{
from: "component.component_name[each.value.attribute]",
component: Component{
Name: "component_name",
},
index: cty.StringVal("attribute"),
vars: map[string]cty.Value{
"each": cty.ObjectVal(map[string]cty.Value{
"value": cty.ObjectVal(map[string]cty.Value{
"attribute": cty.StringVal("attribute"),
}),
}),
},
},
{
from: "component.component_name[each.value[\"key\"]]",
component: Component{
Name: "component_name",
},
index: cty.StringVal("key"),
vars: map[string]cty.Value{
"each": cty.ObjectVal(map[string]cty.Value{
"value": cty.MapVal(map[string]cty.Value{
"key": cty.StringVal("key"),
}),
}),
},
},
{
from: "component.component_name[each.value[\"key\"].attribute]",
component: Component{
Name: "component_name",
},
index: cty.StringVal("attribute"),
vars: map[string]cty.Value{
"each": cty.ObjectVal(map[string]cty.Value{
"value": cty.MapVal(map[string]cty.Value{
"key": cty.ObjectVal(map[string]cty.Value{
"attribute": cty.StringVal("attribute"),
}),
}),
}),
},
},
{
from: "component.component_name[each.value[local.key]]",
component: Component{
Name: "component_name",
},
index: cty.StringVal("key"),
vars: map[string]cty.Value{
"each": cty.ObjectVal(map[string]cty.Value{
"value": cty.MapVal(map[string]cty.Value{
"key": cty.StringVal("key"),
}),
}),
"local": cty.ObjectVal(map[string]cty.Value{
"key": cty.StringVal("key"),
}),
},
},
{
from: "component.component_name[each.value[local.key].attribute]",
component: Component{
Name: "component_name",
},
index: cty.StringVal("attribute"),
vars: map[string]cty.Value{
"each": cty.ObjectVal(map[string]cty.Value{
"value": cty.MapVal(map[string]cty.Value{
"key": cty.ObjectVal(map[string]cty.Value{
"attribute": cty.StringVal("attribute"),
}),
}),
}),
"local": cty.ObjectVal(map[string]cty.Value{
"key": cty.StringVal("key"),
}),
},
},
{
from: "component.component_name.attribute_key",
diags: func() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid 'from' attribute",
Detail: "The 'from' attribute must designate a component that has been removed, in the form `component.component_name` or `component.component_name[\"key\"].",
})
return diags
},
},
{
from: "component.component_name[0].attribute_key",
diags: func() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid 'from' attribute",
Detail: "The 'from' attribute must designate a component that has been removed, in the form `component.component_name` or `component.component_name[\"key\"].",
})
return diags
},
},
{
from: "component.component_name[\"key\"].attribute_key",
diags: func() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid 'from' attribute",
Detail: "The 'from' attribute must designate a component that has been removed, in the form `component.component_name` or `component.component_name[\"key\"].",
})
return diags
},
},
{
from: "component.component_name[each.key].attribute_key",
diags: func() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid 'from' attribute",
Detail: "The 'from' attribute must designate a component that has been removed, in the form `component.component_name` or `component.component_name[\"key\"].",
})
return diags
},
},
{
from: "component.component_name.attribute_key[0]",
diags: func() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid 'from' attribute",
Detail: "The 'from' attribute must designate a component that has been removed, in the form `component.component_name` or `component.component_name[\"key\"].",
})
return diags
},
},
{
from: "component[0].component_name",
diags: func() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid 'from' attribute",
Detail: "The 'from' attribute must designate a component that has been removed, in the form `component.component_name` or `component.component_name[\"key\"].",
})
return diags
},
},
}
for _, tc := range tcs {
t.Run(tc.from, func(t *testing.T) {
expr := mustExpr(t, tc.from)
component, index, gotDiags := ParseRemovedFrom(expr)
// validate the component first
if diff := cmp.Diff(tc.component, component); len(diff) > 0 {
t.Errorf("unexpected result\n%s", diff)
}
// validate the index
if index == nil {
if tc.index != cty.NilVal {
t.Errorf("expected index but got nil")
}
} else {
gotIndex, indexDiags := index.Value(&hcl.EvalContext{
Variables: tc.vars,
})
if len(indexDiags) > 0 {
t.Errorf("unexpected index diagnostics: %s", indexDiags.Error())
}
if diff := cmp.Diff(tc.index, gotIndex, ctydebug.CmpOptions); len(diff) > 0 {
t.Errorf("unexpected index\n%s", diff)
}
}
// validate the diagnostics
var wantDiags tfdiags.Diagnostics
if tc.diags != nil {
wantDiags = tc.diags()
}
if len(gotDiags) != len(wantDiags) {
t.Errorf("wrong number of diagnostics")
}
for ix, got := range gotDiags {
want := wantDiags[ix]
if want.Severity() != got.Severity() {
t.Errorf("unexpected severity: got %s, want %s", got.Severity(), want.Severity())
}
if diff := cmp.Diff(want.Description(), got.Description()); len(diff) > 0 {
t.Errorf("unexpected description\n%s", diff)
}
}
})
}
}