github.com/Burmuley/terraform@v0.11.12-beta1/repl/session_test.go (about) 1 package repl 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/hashicorp/terraform/config/module" 8 "github.com/hashicorp/terraform/terraform" 9 ) 10 11 func TestSession_basicState(t *testing.T) { 12 state := &terraform.State{ 13 Modules: []*terraform.ModuleState{ 14 &terraform.ModuleState{ 15 Path: []string{"root"}, 16 Resources: map[string]*terraform.ResourceState{ 17 "test_instance.foo": &terraform.ResourceState{ 18 Type: "test_instance", 19 Primary: &terraform.InstanceState{ 20 ID: "bar", 21 Attributes: map[string]string{ 22 "id": "bar", 23 }, 24 }, 25 }, 26 }, 27 }, 28 29 &terraform.ModuleState{ 30 Path: []string{"root", "module"}, 31 Resources: map[string]*terraform.ResourceState{ 32 "test_instance.foo": &terraform.ResourceState{ 33 Type: "test_instance", 34 Primary: &terraform.InstanceState{ 35 ID: "bar", 36 Attributes: map[string]string{ 37 "id": "bar", 38 }, 39 }, 40 }, 41 }, 42 }, 43 }, 44 } 45 46 t.Run("basic", func(t *testing.T) { 47 testSession(t, testSessionTest{ 48 State: state, 49 Inputs: []testSessionInput{ 50 { 51 Input: "test_instance.foo.id", 52 Output: "bar", 53 }, 54 }, 55 }) 56 }) 57 58 t.Run("resource count", func(t *testing.T) { 59 testSession(t, testSessionTest{ 60 State: state, 61 Inputs: []testSessionInput{ 62 { 63 Input: "test_instance.foo.count", 64 Output: "1", 65 }, 66 }, 67 }) 68 }) 69 70 t.Run("missing resource", func(t *testing.T) { 71 testSession(t, testSessionTest{ 72 State: state, 73 Inputs: []testSessionInput{ 74 { 75 Input: "test_instance.bar.id", 76 Error: true, 77 ErrorContains: "'test_instance.bar' not found", 78 }, 79 }, 80 }) 81 }) 82 83 t.Run("missing module", func(t *testing.T) { 84 testSession(t, testSessionTest{ 85 State: state, 86 Inputs: []testSessionInput{ 87 { 88 Input: "module.child.foo", 89 Error: true, 90 ErrorContains: "Couldn't find module \"child\"", 91 }, 92 }, 93 }) 94 }) 95 96 t.Run("missing module output", func(t *testing.T) { 97 testSession(t, testSessionTest{ 98 State: state, 99 Inputs: []testSessionInput{ 100 { 101 Input: "module.module.foo", 102 Error: true, 103 ErrorContains: "Couldn't find output \"foo\"", 104 }, 105 }, 106 }) 107 }) 108 } 109 110 func TestSession_stateless(t *testing.T) { 111 t.Run("exit", func(t *testing.T) { 112 testSession(t, testSessionTest{ 113 Inputs: []testSessionInput{ 114 { 115 Input: "exit", 116 Error: true, 117 ErrorContains: ErrSessionExit.Error(), 118 }, 119 }, 120 }) 121 }) 122 123 t.Run("help", func(t *testing.T) { 124 testSession(t, testSessionTest{ 125 Inputs: []testSessionInput{ 126 { 127 Input: "help", 128 OutputContains: "allows you to", 129 }, 130 }, 131 }) 132 }) 133 134 t.Run("help with spaces", func(t *testing.T) { 135 testSession(t, testSessionTest{ 136 Inputs: []testSessionInput{ 137 { 138 Input: "help ", 139 OutputContains: "allows you to", 140 }, 141 }, 142 }) 143 }) 144 145 t.Run("basic math", func(t *testing.T) { 146 testSession(t, testSessionTest{ 147 Inputs: []testSessionInput{ 148 { 149 Input: "1 + 5", 150 Output: "6", 151 }, 152 }, 153 }) 154 }) 155 156 t.Run("missing resource", func(t *testing.T) { 157 testSession(t, testSessionTest{ 158 Inputs: []testSessionInput{ 159 { 160 Input: "test_instance.bar.id", 161 Error: true, 162 ErrorContains: "'test_instance.bar' not found", 163 }, 164 }, 165 }) 166 }) 167 } 168 169 func testSession(t *testing.T, test testSessionTest) { 170 // Build the TF context 171 ctx, err := terraform.NewContext(&terraform.ContextOpts{ 172 State: test.State, 173 Module: module.NewEmptyTree(), 174 }) 175 if err != nil { 176 t.Fatalf("err: %s", err) 177 } 178 179 // Build the session 180 s := &Session{ 181 Interpolater: ctx.Interpolater(), 182 } 183 184 // Test the inputs. We purposely don't use subtests here because 185 // the inputs don't recognize subtests, but a sequence of stateful 186 // operations. 187 for _, input := range test.Inputs { 188 result, err := s.Handle(input.Input) 189 if (err != nil) != input.Error { 190 t.Fatalf("%q: err: %s", input.Input, err) 191 } 192 if err != nil { 193 if input.ErrorContains != "" { 194 if !strings.Contains(err.Error(), input.ErrorContains) { 195 t.Fatalf( 196 "%q: err should contain: %q\n\n%s", 197 input.Input, input.ErrorContains, err) 198 } 199 } 200 201 continue 202 } 203 204 if input.Output != "" && result != input.Output { 205 t.Fatalf( 206 "%q: expected:\n\n%s\n\ngot:\n\n%s", 207 input.Input, input.Output, result) 208 } 209 210 if input.OutputContains != "" && !strings.Contains(result, input.OutputContains) { 211 t.Fatalf( 212 "%q: expected contains:\n\n%s\n\ngot:\n\n%s", 213 input.Input, input.OutputContains, result) 214 } 215 } 216 } 217 218 type testSessionTest struct { 219 State *terraform.State // State to use 220 Module string // Module name in test-fixtures to load 221 222 // Inputs are the list of test inputs that are run in order. 223 // Each input can test the output of each step. 224 Inputs []testSessionInput 225 } 226 227 // testSessionInput is a single input to test for a session. 228 type testSessionInput struct { 229 Input string // Input string 230 Output string // Exact output string to check 231 OutputContains string 232 Error bool // Error is true if error is expected 233 ErrorContains string 234 }