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 }