| package configs |
| |
| import ( |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/hashicorp/hcl/v2" |
| "github.com/hashicorp/hcl/v2/hcltest" |
| "github.com/hashicorp/terraform/internal/addrs" |
| ) |
| |
| func TestMovedBlock_decode(t *testing.T) { |
| blockRange := hcl.Range{ |
| Filename: "mock.tf", |
| Start: hcl.Pos{Line: 3, Column: 12, Byte: 27}, |
| End: hcl.Pos{Line: 3, Column: 19, Byte: 34}, |
| } |
| |
| foo_expr := hcltest.MockExprTraversalSrc("test_instance.foo") |
| bar_expr := hcltest.MockExprTraversalSrc("test_instance.bar") |
| |
| foo_index_expr := hcltest.MockExprTraversalSrc("test_instance.foo[1]") |
| bar_index_expr := hcltest.MockExprTraversalSrc("test_instance.bar[\"one\"]") |
| |
| mod_foo_expr := hcltest.MockExprTraversalSrc("module.foo") |
| mod_bar_expr := hcltest.MockExprTraversalSrc("module.bar") |
| |
| tests := map[string]struct { |
| input *hcl.Block |
| want *Moved |
| err string |
| }{ |
| "success": { |
| &hcl.Block{ |
| Type: "moved", |
| Body: hcltest.MockBody(&hcl.BodyContent{ |
| Attributes: hcl.Attributes{ |
| "from": { |
| Name: "from", |
| Expr: foo_expr, |
| }, |
| "to": { |
| Name: "to", |
| Expr: bar_expr, |
| }, |
| }, |
| }), |
| DefRange: blockRange, |
| }, |
| &Moved{ |
| From: mustMoveEndpointFromExpr(foo_expr), |
| To: mustMoveEndpointFromExpr(bar_expr), |
| DeclRange: blockRange, |
| }, |
| ``, |
| }, |
| "indexed resources": { |
| &hcl.Block{ |
| Type: "moved", |
| Body: hcltest.MockBody(&hcl.BodyContent{ |
| Attributes: hcl.Attributes{ |
| "from": { |
| Name: "from", |
| Expr: foo_index_expr, |
| }, |
| "to": { |
| Name: "to", |
| Expr: bar_index_expr, |
| }, |
| }, |
| }), |
| DefRange: blockRange, |
| }, |
| &Moved{ |
| From: mustMoveEndpointFromExpr(foo_index_expr), |
| To: mustMoveEndpointFromExpr(bar_index_expr), |
| DeclRange: blockRange, |
| }, |
| ``, |
| }, |
| "modules": { |
| &hcl.Block{ |
| Type: "moved", |
| Body: hcltest.MockBody(&hcl.BodyContent{ |
| Attributes: hcl.Attributes{ |
| "from": { |
| Name: "from", |
| Expr: mod_foo_expr, |
| }, |
| "to": { |
| Name: "to", |
| Expr: mod_bar_expr, |
| }, |
| }, |
| }), |
| DefRange: blockRange, |
| }, |
| &Moved{ |
| From: mustMoveEndpointFromExpr(mod_foo_expr), |
| To: mustMoveEndpointFromExpr(mod_bar_expr), |
| DeclRange: blockRange, |
| }, |
| ``, |
| }, |
| "error: missing argument": { |
| &hcl.Block{ |
| Type: "moved", |
| Body: hcltest.MockBody(&hcl.BodyContent{ |
| Attributes: hcl.Attributes{ |
| "from": { |
| Name: "from", |
| Expr: foo_expr, |
| }, |
| }, |
| }), |
| DefRange: blockRange, |
| }, |
| &Moved{ |
| From: mustMoveEndpointFromExpr(foo_expr), |
| DeclRange: blockRange, |
| }, |
| "Missing required argument", |
| }, |
| "error: type mismatch": { |
| &hcl.Block{ |
| Type: "moved", |
| Body: hcltest.MockBody(&hcl.BodyContent{ |
| Attributes: hcl.Attributes{ |
| "to": { |
| Name: "to", |
| Expr: foo_expr, |
| }, |
| "from": { |
| Name: "from", |
| Expr: mod_foo_expr, |
| }, |
| }, |
| }), |
| DefRange: blockRange, |
| }, |
| &Moved{ |
| To: mustMoveEndpointFromExpr(foo_expr), |
| From: mustMoveEndpointFromExpr(mod_foo_expr), |
| DeclRange: blockRange, |
| }, |
| "Invalid \"moved\" addresses", |
| }, |
| } |
| |
| for name, test := range tests { |
| t.Run(name, func(t *testing.T) { |
| got, diags := decodeMovedBlock(test.input) |
| |
| if diags.HasErrors() { |
| if test.err == "" { |
| t.Fatalf("unexpected error: %s", diags.Errs()) |
| } |
| if gotErr := diags[0].Summary; gotErr != test.err { |
| t.Errorf("wrong error, got %q, want %q", gotErr, test.err) |
| } |
| } else if test.err != "" { |
| t.Fatal("expected error") |
| } |
| |
| if !cmp.Equal(got, test.want, cmp.AllowUnexported(addrs.MoveEndpoint{})) { |
| t.Fatalf("wrong result: %s", cmp.Diff(got, test.want)) |
| } |
| }) |
| } |
| } |
| |
| func TestMovedBlock_inModule(t *testing.T) { |
| parser := NewParser(nil) |
| mod, diags := parser.LoadConfigDir("testdata/valid-modules/moved-blocks") |
| if diags.HasErrors() { |
| t.Errorf("unexpected error: %s", diags.Error()) |
| } |
| |
| var gotPairs [][2]string |
| for _, mc := range mod.Moved { |
| gotPairs = append(gotPairs, [2]string{mc.From.String(), mc.To.String()}) |
| } |
| wantPairs := [][2]string{ |
| {`test.foo`, `test.bar`}, |
| {`test.foo`, `test.bar["bloop"]`}, |
| {`module.a`, `module.b`}, |
| {`module.a`, `module.a["foo"]`}, |
| {`test.foo`, `module.a.test.foo`}, |
| {`data.test.foo`, `data.test.bar`}, |
| } |
| if diff := cmp.Diff(wantPairs, gotPairs); diff != "" { |
| t.Errorf("wrong addresses\n%s", diff) |
| } |
| } |
| |
| func mustMoveEndpointFromExpr(expr hcl.Expression) *addrs.MoveEndpoint { |
| traversal, hcldiags := hcl.AbsTraversalForExpr(expr) |
| if hcldiags.HasErrors() { |
| panic(hcldiags.Errs()) |
| } |
| |
| ep, diags := addrs.ParseMoveEndpoint(traversal) |
| if diags.HasErrors() { |
| panic(diags.Err()) |
| } |
| |
| return ep |
| } |