Closed akupila closed 5 years ago
When multiple blocks have the same type, the attributes within the block are somehow set on the previously decoded blocks too. This is a bit tricky to explain so an example is better:
package main import ( "fmt" "log" "github.com/hashicorp/hcl2/gohcl" "github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hclpack" ) func main() { src := ` foo { bar = "123" } foo { bar = "abc" } ` body, diags := hclpack.PackNativeFile([]byte(src), "file.hcl", hcl.Pos{Line: 1, Column: 1}) if diags.HasErrors() { log.Fatal(diags) } got := struct { Foos []struct { Bar string `hcl:"bar"` } `hcl:"foo,block"` }{} diags = gohcl.DecodeBody(body, nil, &got) if diags.HasErrors() { log.Fatal(diags) } fmt.Printf("Result: %+v\n", got) // Output: // Result: {Foos:[{Bar:abc} {Bar:abc}]} }
Here I would expect the output to be Result: {Foos:[{Bar:123} {Bar:abc}]}.
Result: {Foos:[{Bar:123} {Bar:abc}]}
If we change lines 23-26 to this:
file, diags := hclsyntax.ParseConfig([]byte(src), "file.hcl", hcl.Pos{Byte: 0, Line: 1, Column: 1}) if diags.HasErrors() { log.Fatal(diags) } body := file.Body
The result is what I would expect.
This seems like a bug to me but it's possible I've misunderstood something.
Here's a failing test case:
diff --git hclpack/structure_test.go hclpack/structure_test.go index 0d5f11c..78b1037 100644 --- a/hclpack/structure_test.go +++ b/hclpack/structure_test.go @@ -75,6 +75,73 @@ func TestBodyContent(t *testing.T) { }, }, }, + "block attributes": { + &Body{ + ChildBlocks: []Block{ + { + Type: "foo", + Body: Body{ + Attributes: map[string]Attribute{ + "bar": { + Expr: Expression{ + Source: []byte(`"hello"`), + SourceType: ExprNative, + }, + }, + }, + }, + }, + { + Type: "foo", + Body: Body{ + Attributes: map[string]Attribute{ + "bar": { + Expr: Expression{ + Source: []byte(`"world"`), + SourceType: ExprNative, + }, + }, + }, + }, + }, + }, + }, + &hcl.BodySchema{ + Blocks: []hcl.BlockHeaderSchema{ + {Type: "foo"}, + }, + }, + &hcl.BodyContent{ + Blocks: hcl.Blocks{ + { + Type: "foo", + Body: &Body{ + Attributes: map[string]Attribute{ + "bar": { + Expr: Expression{ + Source: []byte(`"hello"`), + SourceType: ExprNative, + }, + }, + }, + }, + }, + { + Type: "foo", + Body: &Body{ + Attributes: map[string]Attribute{ + "bar": { + Expr: Expression{ + Source: []byte(`"world"`), + SourceType: ExprNative, + }, + }, + }, + }, + }, + }, + }, + }, } for name, test := range tests { @@ -85,7 +152,13 @@ func TestBodyContent(t *testing.T) { } if !cmp.Equal(test.Want, got) { - t.Errorf("wrong result\n%s", cmp.Diff(test.Want, got)) + bytesAsString := func(s []byte) string { + return string(s) + } + t.Errorf("wrong result\n%s", cmp.Diff( + test.Want, got, + cmp.Transformer("bytesAsString", bytesAsString), + )) } }) }
When multiple blocks have the same type, the attributes within the block are somehow set on the previously decoded blocks too. This is a bit tricky to explain so an example is better:
Here I would expect the output to be
Result: {Foos:[{Bar:123} {Bar:abc}]}
.If we change lines 23-26 to this:
The result is what I would expect.
This seems like a bug to me but it's possible I've misunderstood something.
Here's a failing test case: