hcl/hclwrite/ast_body_test.go
Martin Atkins c8c208e083 hclwrite: Body.SetAttributeValue
For now, this is the only way to set an attribute, and so attributes can
only be set to literal values.

Later this will be generalized so that this is just a helper wrapper
around a "SetAttribute" method that just uses a given expression, which
then helps by constructing the expression from the value first.
2018-08-09 08:44:48 -07:00

415 lines
8.2 KiB
Go

package hclwrite
import (
"fmt"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/zclconf/go-cty/cty"
)
func TestBodyGetAttribute(t *testing.T) {
tests := []struct {
src string
name string
want Tokens
}{
{
"",
"a",
nil,
},
{
"a = 1\n",
"a",
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'a'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNumberLit,
Bytes: []byte{'1'},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
},
},
{
"a = 1\nb = 1\nc = 1\n",
"a",
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'a'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNumberLit,
Bytes: []byte{'1'},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
},
},
{
"a = 1\nb = 2\nc = 3\n",
"b",
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'b'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNumberLit,
Bytes: []byte{'2'},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
},
},
{
"a = 1\nb = 2\nc = 3\n",
"c",
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'c'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNumberLit,
Bytes: []byte{'3'},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
},
},
{
"a = 1\n# b is a b\nb = 2\nc = 3\n",
"b",
Tokens{
{
// Recognized as a lead comment and so attached to the attribute
Type: hclsyntax.TokenComment,
Bytes: []byte("# b is a b\n"),
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'b'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNumberLit,
Bytes: []byte{'2'},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
},
},
{
"a = 1\n# not attached to a or b\n\nb = 2\nc = 3\n",
"b",
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'b'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNumberLit,
Bytes: []byte{'2'},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
},
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("%s in %s", test.name, test.src), func(t *testing.T) {
f, diags := ParseConfig([]byte(test.src), "", hcl.Pos{Line: 1, Column: 1})
if len(diags) != 0 {
for _, diag := range diags {
t.Logf("- %s", diag.Error())
}
t.Fatalf("unexpected diagnostics")
}
attr := f.Body().GetAttribute(test.name)
if attr == nil {
if test.want != nil {
t.Fatal("attribute not found, but want it to exist")
}
} else {
if test.want == nil {
t.Fatal("attribute found, but expecting not found")
}
got := attr.BuildTokens(nil)
if !reflect.DeepEqual(got, test.want) {
t.Errorf("wrong result\ngot: %s\nwant: %s", spew.Sdump(got), spew.Sdump(test.want))
}
}
})
}
}
func TestBodySetAttributeValue(t *testing.T) {
tests := []struct {
src string
name string
val cty.Value
want Tokens
}{
{
"",
"a",
cty.True,
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'a'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte("true"),
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEOF,
Bytes: []byte{},
SpacesBefore: 0,
},
},
},
{
"b = false\n",
"a",
cty.True,
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'b'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte("false"),
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'a'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte("true"),
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEOF,
Bytes: []byte{},
SpacesBefore: 0,
},
},
},
{
"a = false\n",
"a",
cty.True,
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'a'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte("true"),
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEOF,
Bytes: []byte{},
SpacesBefore: 0,
},
},
},
{
"a = 1\nb = false\n",
"a",
cty.True,
Tokens{
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'a'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte("true"),
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte{'b'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEqual,
Bytes: []byte{'='},
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte("false"),
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
SpacesBefore: 0,
},
{
Type: hclsyntax.TokenEOF,
Bytes: []byte{},
SpacesBefore: 0,
},
},
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("%s = %#v in %s", test.name, test.val, test.src), func(t *testing.T) {
f, diags := ParseConfig([]byte(test.src), "", hcl.Pos{Line: 1, Column: 1})
if len(diags) != 0 {
for _, diag := range diags {
t.Logf("- %s", diag.Error())
}
t.Fatalf("unexpected diagnostics")
}
f.Body().SetAttributeValue(test.name, test.val)
got := f.BuildTokens(nil)
format(got)
if !reflect.DeepEqual(got, test.want) {
diff := cmp.Diff(test.want, got)
t.Errorf("wrong result\ngot: %s\nwant: %s\ndiff:\n%s", spew.Sdump(got), spew.Sdump(test.want), diff)
}
})
}
}