github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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 current = current.DeepCopy() 96 current.Modules = []*terraform.ModuleState{ 97 &terraform.ModuleState{ 98 Path: []string{"root", "somewhere"}, 99 Outputs: map[string]*terraform.OutputState{ 100 "serialCheck": &terraform.OutputState{ 101 Type: "string", 102 Sensitive: false, 103 Value: "true", 104 }, 105 }, 106 }, 107 } 108 if err := writer.WriteState(current); err != nil { 109 t.Fatalf("err: %s", err) 110 } 111 if err := persister.PersistState(); err != nil { 112 t.Fatalf("err: %s", err) 113 } 114 115 if reader.State().Serial <= serial { 116 t.Fatalf("bad: expected %d, got %d", serial, reader.State().Serial) 117 } 118 119 // Check that State() returns a copy by modifying the copy and comparing 120 // to the current state. 121 stateCopy := reader.State() 122 stateCopy.Serial++ 123 if reflect.DeepEqual(stateCopy, current) { 124 t.Fatal("State() should return a copy") 125 } 126 } 127 } 128 129 // TestStateInitial is the initial state that a State should have 130 // for TestState. 131 func TestStateInitial() *terraform.State { 132 initial := &terraform.State{ 133 Modules: []*terraform.ModuleState{ 134 &terraform.ModuleState{ 135 Path: []string{"root", "child"}, 136 Outputs: map[string]*terraform.OutputState{ 137 "foo": &terraform.OutputState{ 138 Type: "string", 139 Sensitive: false, 140 Value: "bar", 141 }, 142 }, 143 }, 144 }, 145 } 146 147 initial.Init() 148 149 return initial 150 }