github.com/aznashwan/terraform@v0.4.3-0.20151118032030-21f93ca4558d/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]string{ 40 "bar": "baz", 41 }, 42 }) 43 44 if err := ws.WriteState(current); err != nil { 45 t.Fatalf("err: %s", err) 46 } 47 48 if actual := reader.State(); !actual.Equal(current) { 49 t.Fatalf("bad: %#v\n\n%#v", actual, current) 50 } 51 } 52 53 // Test persistence 54 if ps, ok := s.(StatePersister); ok { 55 if err := ps.PersistState(); err != nil { 56 t.Fatalf("err: %s", err) 57 } 58 59 // Refresh if we got it 60 if rs, ok := s.(StateRefresher); ok { 61 if err := rs.RefreshState(); err != nil { 62 t.Fatalf("err: %s", err) 63 } 64 } 65 66 // Just set the serials the same... Then compare. 67 actual := reader.State() 68 if !actual.Equal(current) { 69 t.Fatalf("bad: %#v\n\n%#v", actual, current) 70 } 71 } 72 73 // If we can write and persist then verify that the serial 74 // is only implemented on change. 75 writer, writeOk := s.(StateWriter) 76 persister, persistOk := s.(StatePersister) 77 if writeOk && persistOk { 78 // Same serial 79 serial := current.Serial 80 if err := writer.WriteState(current); err != nil { 81 t.Fatalf("err: %s", err) 82 } 83 if err := persister.PersistState(); err != nil { 84 t.Fatalf("err: %s", err) 85 } 86 87 if reader.State().Serial != serial { 88 t.Fatalf("bad: expected %d, got %d", serial, reader.State().Serial) 89 } 90 91 // Change the serial 92 currentCopy := *current 93 current = ¤tCopy 94 current.Modules = []*terraform.ModuleState{ 95 &terraform.ModuleState{ 96 Path: []string{"root", "somewhere"}, 97 Outputs: map[string]string{"serialCheck": "true"}, 98 }, 99 } 100 if err := writer.WriteState(current); err != nil { 101 t.Fatalf("err: %s", err) 102 } 103 if err := persister.PersistState(); err != nil { 104 t.Fatalf("err: %s", err) 105 } 106 107 if reader.State().Serial <= serial { 108 t.Fatalf("bad: expected %d, got %d", serial, reader.State().Serial) 109 } 110 111 // Check that State() returns a copy 112 reader.State().Serial++ 113 if reflect.DeepEqual(reader.State(), current) { 114 t.Fatal("State() should return a copy") 115 } 116 } 117 } 118 119 // TestStateInitial is the initial state that a State should have 120 // for TestState. 121 func TestStateInitial() *terraform.State { 122 initial := &terraform.State{ 123 Modules: []*terraform.ModuleState{ 124 &terraform.ModuleState{ 125 Path: []string{"root", "child"}, 126 Outputs: map[string]string{ 127 "foo": "bar", 128 }, 129 }, 130 }, 131 } 132 133 var scratch bytes.Buffer 134 terraform.WriteState(initial, &scratch) 135 return initial 136 }