github.com/tomaszheflik/terraform@v0.7.3-0.20160827060421-32f990b41594/terraform/graph_builder_test.go (about) 1 package terraform 2 3 import ( 4 "reflect" 5 "strings" 6 "testing" 7 8 "github.com/hashicorp/terraform/dag" 9 ) 10 11 func TestBasicGraphBuilder_impl(t *testing.T) { 12 var _ GraphBuilder = new(BasicGraphBuilder) 13 } 14 15 func TestBasicGraphBuilder(t *testing.T) { 16 b := &BasicGraphBuilder{ 17 Steps: []GraphTransformer{ 18 &testBasicGraphBuilderTransform{1}, 19 }, 20 } 21 22 g, err := b.Build(RootModulePath) 23 if err != nil { 24 t.Fatalf("err: %s", err) 25 } 26 27 if !reflect.DeepEqual(g.Path, RootModulePath) { 28 t.Fatalf("bad: %#v", g.Path) 29 } 30 31 actual := strings.TrimSpace(g.String()) 32 expected := strings.TrimSpace(testBasicGraphBuilderStr) 33 if actual != expected { 34 t.Fatalf("bad: %s", actual) 35 } 36 } 37 38 func TestBasicGraphBuilder_validate(t *testing.T) { 39 b := &BasicGraphBuilder{ 40 Steps: []GraphTransformer{ 41 &testBasicGraphBuilderTransform{1}, 42 &testBasicGraphBuilderTransform{2}, 43 }, 44 Validate: true, 45 } 46 47 _, err := b.Build(RootModulePath) 48 if err == nil { 49 t.Fatal("should error") 50 } 51 } 52 53 func TestBasicGraphBuilder_validateOff(t *testing.T) { 54 b := &BasicGraphBuilder{ 55 Steps: []GraphTransformer{ 56 &testBasicGraphBuilderTransform{1}, 57 &testBasicGraphBuilderTransform{2}, 58 }, 59 Validate: false, 60 } 61 62 _, err := b.Build(RootModulePath) 63 if err != nil { 64 t.Fatalf("expected no error, got: %s", err) 65 } 66 } 67 68 func TestBuiltinGraphBuilder_impl(t *testing.T) { 69 var _ GraphBuilder = new(BuiltinGraphBuilder) 70 } 71 72 // This test is not meant to test all the transforms but rather just 73 // to verify we get some basic sane graph out. Special tests to ensure 74 // specific ordering of steps should be added in other tests. 75 func TestBuiltinGraphBuilder(t *testing.T) { 76 b := &BuiltinGraphBuilder{ 77 Root: testModule(t, "graph-builder-basic"), 78 Validate: true, 79 } 80 81 g, err := b.Build(RootModulePath) 82 if err != nil { 83 t.Fatalf("err: %s", err) 84 } 85 86 actual := strings.TrimSpace(g.String()) 87 expected := strings.TrimSpace(testBuiltinGraphBuilderBasicStr) 88 if actual != expected { 89 t.Fatalf("bad: %s", actual) 90 } 91 } 92 93 func TestBuiltinGraphBuilder_Verbose(t *testing.T) { 94 b := &BuiltinGraphBuilder{ 95 Root: testModule(t, "graph-builder-basic"), 96 Validate: true, 97 Verbose: true, 98 } 99 100 g, err := b.Build(RootModulePath) 101 if err != nil { 102 t.Fatalf("err: %s", err) 103 } 104 105 actual := strings.TrimSpace(g.String()) 106 expected := strings.TrimSpace(testBuiltinGraphBuilderVerboseStr) 107 if actual != expected { 108 t.Fatalf("bad: %s", actual) 109 } 110 } 111 112 // This tests that the CreateBeforeDestoryTransformer is not present when 113 // we perform a "terraform destroy" operation. We don't actually do anything 114 // else. 115 func TestBuiltinGraphBuilder_CreateBeforeDestroy_Destroy_Bypass(t *testing.T) { 116 b := &BuiltinGraphBuilder{ 117 Root: testModule(t, "graph-builder-basic"), 118 Validate: true, 119 Destroy: true, 120 } 121 122 steps := b.Steps([]string{}) 123 124 actual := false 125 expected := false 126 for _, v := range steps { 127 switch v.(type) { 128 case *CreateBeforeDestroyTransformer: 129 actual = true 130 } 131 } 132 133 if actual != expected { 134 t.Fatalf("bad: CreateBeforeDestroyTransformer still in root path") 135 } 136 } 137 138 // This tests that the CreateBeforeDestoryTransformer *is* present 139 // during a non-destroy operation (ie: Destroy not set). 140 func TestBuiltinGraphBuilder_CreateBeforeDestroy_NonDestroy_Present(t *testing.T) { 141 b := &BuiltinGraphBuilder{ 142 Root: testModule(t, "graph-builder-basic"), 143 Validate: true, 144 } 145 146 steps := b.Steps([]string{}) 147 148 actual := false 149 expected := true 150 for _, v := range steps { 151 switch v.(type) { 152 case *CreateBeforeDestroyTransformer: 153 actual = true 154 } 155 } 156 157 if actual != expected { 158 t.Fatalf("bad: CreateBeforeDestroyTransformer not in root path") 159 } 160 } 161 162 // This tests a cycle we got when a CBD resource depends on a non-CBD 163 // resource. This cycle shouldn't happen in the general case anymore. 164 func TestBuiltinGraphBuilder_cbdDepNonCbd(t *testing.T) { 165 b := &BuiltinGraphBuilder{ 166 Root: testModule(t, "graph-builder-cbd-non-cbd"), 167 Validate: true, 168 } 169 170 _, err := b.Build(RootModulePath) 171 if err != nil { 172 t.Fatalf("err: %s", err) 173 } 174 } 175 176 func TestBuiltinGraphBuilder_cbdDepNonCbd_errorsWhenVerbose(t *testing.T) { 177 b := &BuiltinGraphBuilder{ 178 Root: testModule(t, "graph-builder-cbd-non-cbd"), 179 Validate: true, 180 Verbose: true, 181 } 182 183 _, err := b.Build(RootModulePath) 184 if err == nil { 185 t.Fatalf("expected err, got none") 186 } 187 } 188 189 func TestBuiltinGraphBuilder_multiLevelModule(t *testing.T) { 190 b := &BuiltinGraphBuilder{ 191 Root: testModule(t, "graph-builder-multi-level-module"), 192 Validate: true, 193 } 194 195 g, err := b.Build(RootModulePath) 196 if err != nil { 197 t.Fatalf("err: %s", err) 198 } 199 200 actual := strings.TrimSpace(g.String()) 201 expected := strings.TrimSpace(testBuiltinGraphBuilderMultiLevelStr) 202 if actual != expected { 203 t.Fatalf("bad: %s", actual) 204 } 205 } 206 207 func TestBuiltinGraphBuilder_orphanDeps(t *testing.T) { 208 state := &State{ 209 Modules: []*ModuleState{ 210 &ModuleState{ 211 Path: rootModulePath, 212 Resources: map[string]*ResourceState{ 213 "aws_instance.foo": &ResourceState{ 214 Type: "aws_instance", 215 Primary: &InstanceState{ 216 ID: "foo", 217 }, 218 }, 219 220 "aws_instance.bar": &ResourceState{ 221 Type: "aws_instance", 222 Dependencies: []string{"aws_instance.foo"}, 223 Primary: &InstanceState{ 224 ID: "bar", 225 }, 226 }, 227 }, 228 }, 229 }, 230 } 231 232 b := &BuiltinGraphBuilder{ 233 Root: testModule(t, "graph-builder-orphan-deps"), 234 State: state, 235 Validate: true, 236 } 237 238 g, err := b.Build(RootModulePath) 239 if err != nil { 240 t.Fatalf("err: %s", err) 241 } 242 243 actual := strings.TrimSpace(g.String()) 244 expected := strings.TrimSpace(testBuiltinGraphBuilderOrphanDepsStr) 245 if actual != expected { 246 t.Fatalf("bad: %s", actual) 247 } 248 } 249 250 /* 251 TODO: This exposes a really bad bug we need to fix after we merge 252 the f-ast-branch. This bug still exists in master. 253 254 // This test tests that the graph builder properly expands modules. 255 func TestBuiltinGraphBuilder_modules(t *testing.T) { 256 b := &BuiltinGraphBuilder{ 257 Root: testModule(t, "graph-builder-modules"), 258 } 259 260 g, err := b.Build(RootModulePath) 261 if err != nil { 262 t.Fatalf("err: %s", err) 263 } 264 265 actual := strings.TrimSpace(g.String()) 266 expected := strings.TrimSpace(testBuiltinGraphBuilderModuleStr) 267 if actual != expected { 268 t.Fatalf("bad: %s", actual) 269 } 270 } 271 */ 272 273 type testBasicGraphBuilderTransform struct { 274 V dag.Vertex 275 } 276 277 func (t *testBasicGraphBuilderTransform) Transform(g *Graph) error { 278 g.Add(t.V) 279 return nil 280 } 281 282 const testBasicGraphBuilderStr = ` 283 1 284 ` 285 286 const testBuiltinGraphBuilderBasicStr = ` 287 aws_instance.db 288 provider.aws 289 aws_instance.web 290 aws_instance.db 291 provider.aws 292 provider.aws (close) 293 aws_instance.web 294 ` 295 296 const testBuiltinGraphBuilderVerboseStr = ` 297 aws_instance.db 298 aws_instance.db (destroy) 299 aws_instance.db (destroy) 300 aws_instance.web (destroy) 301 aws_instance.web 302 aws_instance.db 303 aws_instance.web (destroy) 304 provider.aws 305 provider.aws 306 provider.aws (close) 307 aws_instance.web 308 ` 309 310 const testBuiltinGraphBuilderMultiLevelStr = ` 311 module.foo.module.bar.output.value 312 module.foo.module.bar.var.bar 313 module.foo.var.foo 314 module.foo.module.bar.plan-destroy 315 module.foo.module.bar.var.bar 316 module.foo.var.foo 317 module.foo.plan-destroy 318 module.foo.var.foo 319 root 320 module.foo.module.bar.output.value 321 module.foo.module.bar.plan-destroy 322 module.foo.module.bar.var.bar 323 module.foo.plan-destroy 324 module.foo.var.foo 325 ` 326 327 const testBuiltinGraphBuilderOrphanDepsStr = ` 328 aws_instance.bar (orphan) 329 provider.aws 330 aws_instance.foo (orphan) 331 aws_instance.bar (orphan) 332 provider.aws 333 provider.aws (close) 334 aws_instance.foo (orphan) 335 ` 336 337 /* 338 TODO: Commented out this const as it's likely this needs to 339 be updated when the TestBuiltinGraphBuilder_modules test is 340 enabled again. 341 const testBuiltinGraphBuilderModuleStr = ` 342 aws_instance.web 343 aws_instance.web (destroy) 344 aws_instance.web (destroy) 345 aws_security_group.firewall 346 module.consul (expanded) 347 provider.aws 348 aws_security_group.firewall 349 aws_security_group.firewall (destroy) 350 aws_security_group.firewall (destroy) 351 provider.aws 352 module.consul (expanded) 353 aws_security_group.firewall 354 provider.aws 355 provider.aws 356 ` 357 */