2019-07-20 15:23:02 +00:00
|
|
|
package hclwrite
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
2020-01-29 05:21:48 +00:00
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
2019-07-20 15:23:02 +00:00
|
|
|
"github.com/hashicorp/hcl/v2"
|
2020-01-29 05:21:48 +00:00
|
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
2019-07-20 15:23:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestBlockType(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
src string
|
|
|
|
want string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
`
|
|
|
|
service {
|
|
|
|
attr0 = "val0"
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
"service",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(fmt.Sprintf("%s", test.want), 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")
|
|
|
|
}
|
|
|
|
|
|
|
|
block := f.Body().Blocks()[0]
|
|
|
|
got := string(block.Type())
|
|
|
|
if got != test.want {
|
|
|
|
t.Errorf("wrong result\ngot: %s\nwant: %s", got, test.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBlockLabels(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
src string
|
|
|
|
want []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
`
|
|
|
|
nolabel {
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
[]string{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
quoted "label1" {
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
[]string{"label1"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
quoted "label1" "label2" {
|
|
|
|
}
|
2020-08-21 18:20:48 +00:00
|
|
|
`,
|
|
|
|
[]string{"label1", "label2"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
quoted "label1" /* foo */ "label2" {
|
|
|
|
}
|
2019-07-20 15:23:02 +00:00
|
|
|
`,
|
|
|
|
[]string{"label1", "label2"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
unquoted label1 {
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
[]string{"label1"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
2020-08-21 18:20:48 +00:00
|
|
|
unquoted label1 /* foo */ label2 {
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
[]string{"label1", "label2"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
|
|
|
mixed label1 "label2" {
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
[]string{"label1", "label2"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`
|
2019-07-20 15:23:02 +00:00
|
|
|
escape "\u0041" {
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
[]string{"\u0041"},
|
|
|
|
},
|
2020-11-18 14:21:23 +00:00
|
|
|
{
|
|
|
|
`
|
|
|
|
blank "" {
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
[]string{""},
|
|
|
|
},
|
2019-07-20 15:23:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(fmt.Sprintf("%s", strings.Join(test.want, " ")), 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")
|
|
|
|
}
|
|
|
|
|
|
|
|
block := f.Body().Blocks()[0]
|
|
|
|
got := block.Labels()
|
|
|
|
if !reflect.DeepEqual(got, test.want) {
|
|
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2020-01-29 05:21:48 +00:00
|
|
|
|
|
|
|
func TestBlockSetType(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
src string
|
|
|
|
oldTypeName string
|
|
|
|
newTypeName string
|
|
|
|
labels []string
|
|
|
|
want Tokens
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"foo {}",
|
|
|
|
"foo",
|
|
|
|
"bar",
|
|
|
|
nil,
|
|
|
|
Tokens{
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenIdent,
|
|
|
|
Bytes: []byte(`bar`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOBrace,
|
|
|
|
Bytes: []byte{'{'},
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCBrace,
|
|
|
|
Bytes: []byte{'}'},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenEOF,
|
|
|
|
Bytes: []byte{},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(fmt.Sprintf("%s %s %s in %s", test.oldTypeName, test.newTypeName, test.labels, 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")
|
|
|
|
}
|
|
|
|
|
|
|
|
b := f.Body().FirstMatchingBlock(test.oldTypeName, test.labels)
|
|
|
|
b.SetType(test.newTypeName)
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBlockSetLabels(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
src string
|
|
|
|
typeName string
|
|
|
|
oldLabels []string
|
|
|
|
newLabels []string
|
|
|
|
want Tokens
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
`foo "hoge" {}`,
|
|
|
|
"foo",
|
|
|
|
[]string{"hoge"},
|
|
|
|
[]string{"fuga"}, // update first label
|
|
|
|
Tokens{
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenIdent,
|
|
|
|
Bytes: []byte(`foo`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenQuotedLit,
|
|
|
|
Bytes: []byte(`fuga`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOBrace,
|
|
|
|
Bytes: []byte{'{'},
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCBrace,
|
|
|
|
Bytes: []byte{'}'},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenEOF,
|
|
|
|
Bytes: []byte{},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`foo "hoge" "fuga" {}`,
|
|
|
|
"foo",
|
|
|
|
[]string{"hoge", "fuga"},
|
|
|
|
[]string{"hoge", "piyo"}, // update second label
|
|
|
|
Tokens{
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenIdent,
|
|
|
|
Bytes: []byte(`foo`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenQuotedLit,
|
|
|
|
Bytes: []byte(`hoge`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenQuotedLit,
|
|
|
|
Bytes: []byte(`piyo`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOBrace,
|
|
|
|
Bytes: []byte{'{'},
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCBrace,
|
|
|
|
Bytes: []byte{'}'},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenEOF,
|
|
|
|
Bytes: []byte{},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`foo {}`,
|
|
|
|
"foo",
|
|
|
|
[]string{},
|
|
|
|
[]string{"fuga"}, // insert a new label to empty list
|
|
|
|
Tokens{
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenIdent,
|
|
|
|
Bytes: []byte(`foo`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenQuotedLit,
|
|
|
|
Bytes: []byte(`fuga`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOBrace,
|
|
|
|
Bytes: []byte{'{'},
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCBrace,
|
|
|
|
Bytes: []byte{'}'},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenEOF,
|
|
|
|
Bytes: []byte{},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`foo "hoge" {}`,
|
|
|
|
"foo",
|
|
|
|
[]string{"hoge"},
|
|
|
|
[]string{}, // remove all labels
|
|
|
|
Tokens{
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenIdent,
|
|
|
|
Bytes: []byte(`foo`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOBrace,
|
|
|
|
Bytes: []byte{'{'},
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCBrace,
|
|
|
|
Bytes: []byte{'}'},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenEOF,
|
|
|
|
Bytes: []byte{},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2020-08-21 18:20:48 +00:00
|
|
|
`foo "hoge" /* fuga */ "piyo" {}`,
|
|
|
|
"foo",
|
|
|
|
[]string{"hoge", "piyo"},
|
|
|
|
[]string{"fuga"}, // force quoted form even if the old one is unquoted.
|
|
|
|
Tokens{
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenIdent,
|
|
|
|
Bytes: []byte(`foo`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenQuotedLit,
|
|
|
|
Bytes: []byte(`fuga`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOBrace,
|
|
|
|
Bytes: []byte{'{'},
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCBrace,
|
|
|
|
Bytes: []byte{'}'},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenEOF,
|
|
|
|
Bytes: []byte{},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`foo "hoge" /* foo */ "" {}`,
|
2020-01-29 05:21:48 +00:00
|
|
|
"foo",
|
2020-11-18 14:21:23 +00:00
|
|
|
[]string{"hoge", ""},
|
2020-01-29 05:21:48 +00:00
|
|
|
[]string{"fuga"}, // force quoted form even if the old one is unquoted.
|
|
|
|
Tokens{
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenIdent,
|
|
|
|
Bytes: []byte(`foo`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenQuotedLit,
|
|
|
|
Bytes: []byte(`fuga`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCQuote,
|
|
|
|
Bytes: []byte(`"`),
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenOBrace,
|
|
|
|
Bytes: []byte{'{'},
|
|
|
|
SpacesBefore: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenCBrace,
|
|
|
|
Bytes: []byte{'}'},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: hclsyntax.TokenEOF,
|
|
|
|
Bytes: []byte{},
|
|
|
|
SpacesBefore: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(fmt.Sprintf("%s %s %s in %s", test.typeName, test.oldLabels, test.newLabels, 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")
|
|
|
|
}
|
|
|
|
|
|
|
|
b := f.Body().FirstMatchingBlock(test.typeName, test.oldLabels)
|
|
|
|
b.SetLabels(test.newLabels)
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|