| package hclwrite |
| |
| import ( |
| "fmt" |
| "reflect" |
| "strings" |
| "testing" |
| |
| "github.com/davecgh/go-spew/spew" |
| "github.com/google/go-cmp/cmp" |
| "github.com/hashicorp/hcl/v2" |
| "github.com/hashicorp/hcl/v2/hclsyntax" |
| ) |
| |
| 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" { |
| } |
| `, |
| []string{"label1", "label2"}, |
| }, |
| { |
| ` |
| quoted "label1" /* foo */ "label2" { |
| } |
| `, |
| []string{"label1", "label2"}, |
| }, |
| { |
| ` |
| unquoted label1 { |
| } |
| `, |
| []string{"label1"}, |
| }, |
| { |
| ` |
| unquoted label1 /* foo */ label2 { |
| } |
| `, |
| []string{"label1", "label2"}, |
| }, |
| { |
| ` |
| mixed label1 "label2" { |
| } |
| `, |
| []string{"label1", "label2"}, |
| }, |
| { |
| ` |
| escape "\u0041" { |
| } |
| `, |
| []string{"\u0041"}, |
| }, |
| { |
| ` |
| blank "" { |
| } |
| `, |
| []string{""}, |
| }, |
| } |
| |
| 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) |
| } |
| }) |
| } |
| } |
| |
| 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, |
| }, |
| }, |
| }, |
| { |
| `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 */ "" {}`, |
| "foo", |
| []string{"hoge", ""}, |
| []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) |
| } |
| }) |
| } |
| } |