github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/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 interface{}) { 14 reader, ok := s.(StateReader) 15 if !ok { 16 t.Fatalf("must at least be a StateReader") 17 } 18 19 // If it implements refresh, refresh 20 if rs, ok := s.(StateRefresher); ok { 21 if err := rs.RefreshState(); err != nil { 22 t.Fatalf("err: %s", err) 23 } 24 } 25 26 // current will track our current state 27 current := TestStateInitial() 28 29 // Check that the initial state is correct 30 if state := reader.State(); !current.Equal(state) { 31 t.Fatalf("not initial:\n%#v\n\n%#v", state, current) 32 } 33 34 // Write a new state and verify that we have it 35 if ws, ok := s.(StateWriter); ok { 36 current.AddModuleState(&terraform.ModuleState{ 37 Path: []string{"root"}, 38 Outputs: map[string]*terraform.OutputState{ 39 "bar": &terraform.OutputState{ 40 Type: "string", 41 Sensitive: false, 42 Value: "baz", 43 }, 44 }, 45 }) 46 47 if err := ws.WriteState(current); err != nil { 48 t.Fatalf("err: %s", err) 49 } 50 51 if actual := reader.State(); !actual.Equal(current) { 52 t.Fatalf("bad:\n%#v\n\n%#v", actual, current) 53 } 54 } 55 56 // Test persistence 57 if ps, ok := s.(StatePersister); ok { 58 if err := ps.PersistState(); err != nil { 59 t.Fatalf("err: %s", err) 60 } 61 62 // Refresh if we got it 63 if rs, ok := s.(StateRefresher); ok { 64 if err := rs.RefreshState(); err != nil { 65 t.Fatalf("err: %s", err) 66 } 67 } 68 69 // Just set the serials the same... Then compare. 70 actual := reader.State() 71 if !actual.Equal(current) { 72 t.Fatalf("bad: %#v\n\n%#v", actual, current) 73 } 74 } 75 76 // If we can write and persist then verify that the serial 77 // is only implemented on change. 78 writer, writeOk := s.(StateWriter) 79 persister, persistOk := s.(StatePersister) 80 if writeOk && persistOk { 81 // Same serial 82 serial := current.Serial 83 if err := writer.WriteState(current); err != nil { 84 t.Fatalf("err: %s", err) 85 } 86 if err := persister.PersistState(); err != nil { 87 t.Fatalf("err: %s", err) 88 } 89 90 if reader.State().Serial != serial { 91 t.Fatalf("bad: expected %d, got %d", serial, reader.State().Serial) 92 } 93 94 // Change the serial 95 currentCopy := *current 96 current = ¤tCopy 97 current.Modules = []*terraform.ModuleState{ 98 &terraform.ModuleState{ 99 Path: []string{"root", "somewhere"}, 100 Outputs: map[string]*terraform.OutputState{ 101 "serialCheck": &terraform.OutputState{ 102 Type: "string", 103 Sensitive: false, 104 Value: "true", 105 }, 106 }, 107 }, 108 } 109 if err := writer.WriteState(current); err != nil { 110 t.Fatalf("err: %s", err) 111 } 112 if err := persister.PersistState(); err != nil { 113 t.Fatalf("err: %s", err) 114 } 115 116 if reader.State().Serial <= serial { 117 t.Fatalf("bad: expected %d, got %d", serial, reader.State().Serial) 118 } 119 120 // Check that State() returns a copy by modifying the copy and comparing 121 // to the current state. 122 stateCopy := reader.State() 123 stateCopy.Serial++ 124 if reflect.DeepEqual(stateCopy, current) { 125 t.Fatal("State() should return a copy") 126 } 127 } 128 } 129 130 // TestStateInitial is the initial state that a State should have 131 // for TestState. 132 func TestStateInitial() *terraform.State { 133 initial := &terraform.State{ 134 Modules: []*terraform.ModuleState{ 135 &terraform.ModuleState{ 136 Path: []string{"root", "child"}, 137 Outputs: map[string]*terraform.OutputState{ 138 "foo": &terraform.OutputState{ 139 Type: "string", 140 Sensitive: false, 141 Value: "bar", 142 }, 143 }, 144 }, 145 }, 146 } 147 148 initial.Init() 149 150 return initial 151 }