github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/states/statefile/version4_test.go (about)

     1  package statefile
     2  
     3  import (
     4  	"sort"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/internal/tfdiags"
     9  	"github.com/zclconf/go-cty/cty"
    10  )
    11  
    12  // This test verifies that modules are sorted before resources:
    13  // https://github.com/hashicorp/terraform/issues/21552
    14  func TestVersion4_sort(t *testing.T) {
    15  	resources := sortResourcesV4{
    16  		{
    17  			Module: "module.child",
    18  			Type:   "test_instance",
    19  			Name:   "foo",
    20  		},
    21  		{
    22  			Type: "test_instance",
    23  			Name: "foo",
    24  		},
    25  		{
    26  			Module: "module.kinder",
    27  			Type:   "test_instance",
    28  			Name:   "foo",
    29  		},
    30  		{
    31  			Module: "module.child.grandchild",
    32  			Type:   "test_instance",
    33  			Name:   "foo",
    34  		},
    35  	}
    36  	sort.Stable(resources)
    37  
    38  	moduleOrder := []string{"", "module.child", "module.child.grandchild", "module.kinder"}
    39  
    40  	for i, resource := range resources {
    41  		if resource.Module != moduleOrder[i] {
    42  			t.Errorf("wrong sort order: expected %q, got %q\n", moduleOrder[i], resource.Module)
    43  		}
    44  	}
    45  }
    46  
    47  func TestVersion4_unmarshalPaths(t *testing.T) {
    48  	testCases := map[string]struct {
    49  		json  string
    50  		paths []cty.Path
    51  		diags []string
    52  	}{
    53  		"no paths": {
    54  			json:  `[]`,
    55  			paths: []cty.Path{},
    56  		},
    57  		"attribute path": {
    58  			json: `[
    59    [
    60      {
    61        "type": "get_attr",
    62  	  "value": "password"
    63      }
    64    ]
    65  ]`,
    66  			paths: []cty.Path{cty.GetAttrPath("password")},
    67  		},
    68  		"attribute and string index": {
    69  			json: `[
    70    [
    71      {
    72        "type": "get_attr",
    73  	  "value": "triggers"
    74      },
    75      {
    76        "type": "index",
    77        "value": {
    78          "value": "secret",
    79  		"type": "string"
    80        }
    81      }
    82    ]
    83  ]`,
    84  			paths: []cty.Path{cty.GetAttrPath("triggers").IndexString("secret")},
    85  		},
    86  		"attribute, number index, attribute": {
    87  			json: `[
    88    [
    89      {
    90        "type": "get_attr",
    91  	  "value": "identities"
    92      },
    93      {
    94        "type": "index",
    95        "value": {
    96          "value": 2,
    97  		"type": "number"
    98        }
    99      },
   100      {
   101        "type": "get_attr",
   102        "value": "private_key"
   103      }
   104    ]
   105  ]`,
   106  			paths: []cty.Path{cty.GetAttrPath("identities").IndexInt(2).GetAttr("private_key")},
   107  		},
   108  		"multiple paths": {
   109  			json: `[
   110    [
   111      {
   112        "type": "get_attr",
   113  	  "value": "alpha"
   114      }
   115    ],
   116    [
   117      {
   118        "type": "get_attr",
   119  	  "value": "beta"
   120      }
   121    ],
   122    [
   123      {
   124        "type": "get_attr",
   125  	  "value": "gamma"
   126      }
   127    ]
   128  ]`,
   129  			paths: []cty.Path{cty.GetAttrPath("alpha"), cty.GetAttrPath("beta"), cty.GetAttrPath("gamma")},
   130  		},
   131  		"errors": {
   132  			json: `[
   133    [
   134      {
   135        "type": "get_attr",
   136  	  "value": 5
   137      }
   138    ],
   139    [
   140      {
   141        "type": "index",
   142  	  "value": "test"
   143      }
   144    ],
   145    [
   146      {
   147        "type": "invalid_type",
   148  	  "value": ["this is invalid too"]
   149      }
   150    ]
   151  ]`,
   152  			paths: []cty.Path{},
   153  			diags: []string{
   154  				"Failed to unmarshal get attr step name",
   155  				"Failed to unmarshal index step key",
   156  				"Unsupported path step",
   157  			},
   158  		},
   159  		"one invalid path, others valid": {
   160  			json: `[
   161    [
   162      {
   163        "type": "get_attr",
   164  	  "value": "alpha"
   165      }
   166    ],
   167    [
   168      {
   169        "type": "invalid_type",
   170  	  "value": ["this is invalid too"]
   171      }
   172    ],
   173    [
   174      {
   175        "type": "get_attr",
   176  	  "value": "gamma"
   177      }
   178    ]
   179  ]`,
   180  			paths: []cty.Path{cty.GetAttrPath("alpha"), cty.GetAttrPath("gamma")},
   181  			diags: []string{"Unsupported path step"},
   182  		},
   183  		"invalid structure": {
   184  			json:  `{}`,
   185  			paths: []cty.Path{},
   186  			diags: []string{"Error unmarshaling path steps"},
   187  		},
   188  	}
   189  
   190  	for name, tc := range testCases {
   191  		t.Run(name, func(t *testing.T) {
   192  			paths, diags := unmarshalPaths([]byte(tc.json))
   193  
   194  			if len(tc.diags) == 0 {
   195  				if len(diags) != 0 {
   196  					t.Errorf("expected no diags, got: %#v", diags)
   197  				}
   198  			} else {
   199  				if got, want := len(diags), len(tc.diags); got != want {
   200  					t.Fatalf("got %d diags, want %d\n%s", got, want, diags.Err())
   201  				}
   202  				for i := range tc.diags {
   203  					got := tfdiags.Diagnostics{diags[i]}.Err().Error()
   204  					if !strings.Contains(got, tc.diags[i]) {
   205  						t.Errorf("expected diag %d to contain %q, but was:\n%s", i, tc.diags[i], got)
   206  					}
   207  				}
   208  			}
   209  
   210  			if len(paths) != len(tc.paths) {
   211  				t.Fatalf("got %d paths, want %d", len(paths), len(tc.paths))
   212  			}
   213  			for i, path := range paths {
   214  				if !path.Equals(tc.paths[i]) {
   215  					t.Errorf("wrong paths\n got: %#v\nwant: %#v", path, tc.paths[i])
   216  				}
   217  			}
   218  		})
   219  	}
   220  }
   221  
   222  func TestVersion4_marshalPaths(t *testing.T) {
   223  	testCases := map[string]struct {
   224  		paths []cty.Path
   225  		json  string
   226  	}{
   227  		"no paths": {
   228  			paths: []cty.Path{},
   229  			json:  `[]`,
   230  		},
   231  		"attribute path": {
   232  			paths: []cty.Path{cty.GetAttrPath("password")},
   233  			json:  `[[{"type":"get_attr","value":"password"}]]`,
   234  		},
   235  		"attribute, number index, attribute": {
   236  			paths: []cty.Path{cty.GetAttrPath("identities").IndexInt(2).GetAttr("private_key")},
   237  			json:  `[[{"type":"get_attr","value":"identities"},{"type":"index","value":{"value":2,"type":"number"}},{"type":"get_attr","value":"private_key"}]]`,
   238  		},
   239  		"multiple paths": {
   240  			paths: []cty.Path{cty.GetAttrPath("a"), cty.GetAttrPath("b"), cty.GetAttrPath("c")},
   241  			json:  `[[{"type":"get_attr","value":"a"}],[{"type":"get_attr","value":"b"}],[{"type":"get_attr","value":"c"}]]`,
   242  		},
   243  	}
   244  
   245  	for name, tc := range testCases {
   246  		t.Run(name, func(t *testing.T) {
   247  			json, diags := marshalPaths(tc.paths)
   248  
   249  			if len(diags) != 0 {
   250  				t.Fatalf("expected no diags, got: %#v", diags)
   251  			}
   252  
   253  			if got, want := string(json), tc.json; got != want {
   254  				t.Fatalf("wrong JSON output\n got: %s\nwant: %s\n", got, want)
   255  			}
   256  		})
   257  	}
   258  }