github.com/spirius/terraform@v0.10.0-beta2.0.20170714185654-87b2c0cf8fea/state/testing.go (about)

     1  package state
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/terraform/terraform"
     8  )
     9  
    10  // TestState is a helper for testing state implementations. It is expected
    11  // that the given implementation is pre-loaded with the TestStateInitial
    12  // state.
    13  func TestState(t *testing.T, s State) {
    14  	if err := s.RefreshState(); err != nil {
    15  		t.Fatalf("err: %s", err)
    16  	}
    17  
    18  	// Check that the initial state is correct.
    19  	// These do have different Lineages, but we will replace current below.
    20  	initial := TestStateInitial()
    21  	if state := s.State(); !state.Equal(initial) {
    22  		t.Fatalf("state does not match expected initial state:\n%#v\n\n%#v", state, initial)
    23  	}
    24  
    25  	// Now we've proven that the state we're starting with is an initial
    26  	// state, we'll complete our work here with that state, since otherwise
    27  	// further writes would violate the invariant that we only try to write
    28  	// states that share the same lineage as what was initially written.
    29  	current := s.State()
    30  
    31  	// Write a new state and verify that we have it
    32  	current.AddModuleState(&terraform.ModuleState{
    33  		Path: []string{"root"},
    34  		Outputs: map[string]*terraform.OutputState{
    35  			"bar": &terraform.OutputState{
    36  				Type:      "string",
    37  				Sensitive: false,
    38  				Value:     "baz",
    39  			},
    40  		},
    41  	})
    42  
    43  	if err := s.WriteState(current); err != nil {
    44  		t.Fatalf("err: %s", err)
    45  	}
    46  
    47  	if actual := s.State(); !actual.Equal(current) {
    48  		t.Fatalf("bad:\n%#v\n\n%#v", actual, current)
    49  	}
    50  
    51  	// Test persistence
    52  	if err := s.PersistState(); err != nil {
    53  		t.Fatalf("err: %s", err)
    54  	}
    55  
    56  	// Refresh if we got it
    57  	if err := s.RefreshState(); err != nil {
    58  		t.Fatalf("err: %s", err)
    59  	}
    60  
    61  	if s.State().Lineage != current.Lineage {
    62  		t.Fatalf("Lineage changed from %s to %s", s.State().Lineage, current.Lineage)
    63  	}
    64  
    65  	// Just set the serials the same... Then compare.
    66  	actual := s.State()
    67  	if !actual.Equal(current) {
    68  		t.Fatalf("bad: %#v\n\n%#v", actual, current)
    69  	}
    70  
    71  	// Same serial
    72  	serial := s.State().Serial
    73  	if err := s.WriteState(current); err != nil {
    74  		t.Fatalf("err: %s", err)
    75  	}
    76  	if err := s.PersistState(); err != nil {
    77  		t.Fatalf("err: %s", err)
    78  	}
    79  
    80  	if s.State().Serial != serial {
    81  		t.Fatalf("serial changed after persisting with no changes: got %d, want %d", s.State().Serial, serial)
    82  	}
    83  
    84  	// Change the serial
    85  	current = current.DeepCopy()
    86  	current.Modules = []*terraform.ModuleState{
    87  		&terraform.ModuleState{
    88  			Path: []string{"root", "somewhere"},
    89  			Outputs: map[string]*terraform.OutputState{
    90  				"serialCheck": &terraform.OutputState{
    91  					Type:      "string",
    92  					Sensitive: false,
    93  					Value:     "true",
    94  				},
    95  			},
    96  		},
    97  	}
    98  	if err := s.WriteState(current); err != nil {
    99  		t.Fatalf("err: %s", err)
   100  	}
   101  	if err := s.PersistState(); err != nil {
   102  		t.Fatalf("err: %s", err)
   103  	}
   104  
   105  	if s.State().Serial <= serial {
   106  		t.Fatalf("serial incorrect after persisting with changes: got %d, want > %d", s.State().Serial, serial)
   107  	}
   108  
   109  	if s.State().Version != current.Version {
   110  		t.Fatalf("Version changed from %d to %d", s.State().Version, current.Version)
   111  	}
   112  
   113  	if s.State().TFVersion != current.TFVersion {
   114  		t.Fatalf("TFVersion changed from %s to %s", s.State().TFVersion, current.TFVersion)
   115  	}
   116  
   117  	// verify that Lineage doesn't change along with Serial, or during copying.
   118  	if s.State().Lineage != current.Lineage {
   119  		t.Fatalf("Lineage changed from %s to %s", s.State().Lineage, current.Lineage)
   120  	}
   121  
   122  	// Check that State() returns a copy by modifying the copy and comparing
   123  	// to the current state.
   124  	stateCopy := s.State()
   125  	stateCopy.Serial++
   126  	if reflect.DeepEqual(stateCopy, s.State()) {
   127  		t.Fatal("State() should return a copy")
   128  	}
   129  
   130  	// our current expected state should also marhsal identically to the persisted state
   131  	if current.MarshalEqual(s.State()) {
   132  		t.Fatalf("Persisted state altered unexpectedly. Expected: %#v\b Got: %#v", current, s.State())
   133  	}
   134  }
   135  
   136  // TestStateInitial is the initial state that a State should have
   137  // for TestState.
   138  func TestStateInitial() *terraform.State {
   139  	initial := &terraform.State{
   140  		Modules: []*terraform.ModuleState{
   141  			&terraform.ModuleState{
   142  				Path: []string{"root", "child"},
   143  				Outputs: map[string]*terraform.OutputState{
   144  					"foo": &terraform.OutputState{
   145  						Type:      "string",
   146  						Sensitive: false,
   147  						Value:     "bar",
   148  					},
   149  				},
   150  			},
   151  		},
   152  	}
   153  
   154  	initial.Init()
   155  
   156  	return initial
   157  }