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