github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/states/state_test.go (about)

     1  package states
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/go-test/deep"
     7  	"github.com/zclconf/go-cty/cty"
     8  
     9  	"github.com/hashicorp/terraform-plugin-sdk/internal/addrs"
    10  )
    11  
    12  func TestState(t *testing.T) {
    13  	// This basic tests exercises the main mutation methods to construct
    14  	// a state. It is not fully comprehensive, so other tests should visit
    15  	// more esoteric codepaths.
    16  
    17  	state := NewState()
    18  
    19  	rootModule := state.RootModule()
    20  	if rootModule == nil {
    21  		t.Errorf("root module is nil; want valid object")
    22  	}
    23  
    24  	rootModule.SetLocalValue("foo", cty.StringVal("foo value"))
    25  	rootModule.SetOutputValue("bar", cty.StringVal("bar value"), false)
    26  	rootModule.SetOutputValue("secret", cty.StringVal("secret value"), true)
    27  	rootModule.SetResourceInstanceCurrent(
    28  		addrs.Resource{
    29  			Mode: addrs.ManagedResourceMode,
    30  			Type: "test_thing",
    31  			Name: "baz",
    32  		}.Instance(addrs.IntKey(0)),
    33  		&ResourceInstanceObjectSrc{
    34  			Status:        ObjectReady,
    35  			SchemaVersion: 1,
    36  			AttrsJSON:     []byte(`{"woozles":"confuzles"}`),
    37  		},
    38  		addrs.ProviderConfig{
    39  			Type: "test",
    40  		}.Absolute(addrs.RootModuleInstance),
    41  	)
    42  
    43  	childModule := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
    44  	childModule.SetOutputValue("pizza", cty.StringVal("hawaiian"), false)
    45  
    46  	want := &State{
    47  		Modules: map[string]*Module{
    48  			"": {
    49  				Addr: addrs.RootModuleInstance,
    50  				LocalValues: map[string]cty.Value{
    51  					"foo": cty.StringVal("foo value"),
    52  				},
    53  				OutputValues: map[string]*OutputValue{
    54  					"bar": {
    55  						Value:     cty.StringVal("bar value"),
    56  						Sensitive: false,
    57  					},
    58  					"secret": {
    59  						Value:     cty.StringVal("secret value"),
    60  						Sensitive: true,
    61  					},
    62  				},
    63  				Resources: map[string]*Resource{
    64  					"test_thing.baz": {
    65  						Addr: addrs.Resource{
    66  							Mode: addrs.ManagedResourceMode,
    67  							Type: "test_thing",
    68  							Name: "baz",
    69  						},
    70  						EachMode: EachList,
    71  						Instances: map[addrs.InstanceKey]*ResourceInstance{
    72  							addrs.IntKey(0): {
    73  								Current: &ResourceInstanceObjectSrc{
    74  									SchemaVersion: 1,
    75  									Status:        ObjectReady,
    76  									AttrsJSON:     []byte(`{"woozles":"confuzles"}`),
    77  								},
    78  								Deposed: map[DeposedKey]*ResourceInstanceObjectSrc{},
    79  							},
    80  						},
    81  						ProviderConfig: addrs.ProviderConfig{
    82  							Type: "test",
    83  						}.Absolute(addrs.RootModuleInstance),
    84  					},
    85  				},
    86  			},
    87  			"module.child": {
    88  				Addr:        addrs.RootModuleInstance.Child("child", addrs.NoKey),
    89  				LocalValues: map[string]cty.Value{},
    90  				OutputValues: map[string]*OutputValue{
    91  					"pizza": {
    92  						Value:     cty.StringVal("hawaiian"),
    93  						Sensitive: false,
    94  					},
    95  				},
    96  				Resources: map[string]*Resource{},
    97  			},
    98  		},
    99  	}
   100  
   101  	{
   102  		// Our structure goes deep, so we need to temporarily override the
   103  		// deep package settings to ensure that we visit the full structure.
   104  		oldDeepDepth := deep.MaxDepth
   105  		oldDeepCompareUnexp := deep.CompareUnexportedFields
   106  		deep.MaxDepth = 50
   107  		deep.CompareUnexportedFields = true
   108  		defer func() {
   109  			deep.MaxDepth = oldDeepDepth
   110  			deep.CompareUnexportedFields = oldDeepCompareUnexp
   111  		}()
   112  	}
   113  
   114  	for _, problem := range deep.Equal(state, want) {
   115  		t.Error(problem)
   116  	}
   117  }
   118  
   119  func TestStateDeepCopy(t *testing.T) {
   120  	state := NewState()
   121  
   122  	rootModule := state.RootModule()
   123  	if rootModule == nil {
   124  		t.Errorf("root module is nil; want valid object")
   125  	}
   126  
   127  	rootModule.SetLocalValue("foo", cty.StringVal("foo value"))
   128  	rootModule.SetOutputValue("bar", cty.StringVal("bar value"), false)
   129  	rootModule.SetOutputValue("secret", cty.StringVal("secret value"), true)
   130  	rootModule.SetResourceInstanceCurrent(
   131  		addrs.Resource{
   132  			Mode: addrs.ManagedResourceMode,
   133  			Type: "test_thing",
   134  			Name: "baz",
   135  		}.Instance(addrs.IntKey(0)),
   136  		&ResourceInstanceObjectSrc{
   137  			Status:        ObjectReady,
   138  			SchemaVersion: 1,
   139  			AttrsJSON:     []byte(`{"woozles":"confuzles"}`),
   140  			Private:       []byte("private data"),
   141  			Dependencies:  []addrs.Referenceable{},
   142  		},
   143  		addrs.ProviderConfig{
   144  			Type: "test",
   145  		}.Absolute(addrs.RootModuleInstance),
   146  	)
   147  	rootModule.SetResourceInstanceCurrent(
   148  		addrs.Resource{
   149  			Mode: addrs.ManagedResourceMode,
   150  			Type: "test_thing",
   151  			Name: "bar",
   152  		}.Instance(addrs.IntKey(0)),
   153  		&ResourceInstanceObjectSrc{
   154  			Status:        ObjectReady,
   155  			SchemaVersion: 1,
   156  			AttrsJSON:     []byte(`{"woozles":"confuzles"}`),
   157  			Private:       []byte("private data"),
   158  			Dependencies: []addrs.Referenceable{addrs.Resource{
   159  				Mode: addrs.ManagedResourceMode,
   160  				Type: "test_thing",
   161  				Name: "baz",
   162  			}},
   163  		},
   164  		addrs.ProviderConfig{
   165  			Type: "test",
   166  		}.Absolute(addrs.RootModuleInstance),
   167  	)
   168  
   169  	childModule := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
   170  	childModule.SetOutputValue("pizza", cty.StringVal("hawaiian"), false)
   171  
   172  	stateCopy := state.DeepCopy()
   173  	if !state.Equal(stateCopy) {
   174  		t.Fatalf("\nexpected:\n%q\ngot:\n%q\n", state, stateCopy)
   175  	}
   176  }