package terraform import ( "sync" "testing" ) func TestEvalRequireState(t *testing.T) { ctx := new(MockEvalContext) cases := []struct { State *InstanceState Exit bool }{ { nil, true, }, { &InstanceState{}, true, }, { &InstanceState{ID: "foo"}, false, }, } var exitVal EvalEarlyExitError for _, tc := range cases { node := &EvalRequireState{State: &tc.State} _, err := node.Eval(ctx) if tc.Exit { if err != exitVal { t.Fatalf("should've exited: %#v", tc.State) } continue } if !tc.Exit && err != nil { t.Fatalf("shouldn't exit: %#v", tc.State) } if err != nil { t.Fatalf("err: %s", err) } } } func TestEvalUpdateStateHook(t *testing.T) { mockHook := new(MockHook) ctx := new(MockEvalContext) ctx.HookHook = mockHook ctx.StateState = &State{Serial: 42} ctx.StateLock = new(sync.RWMutex) node := &EvalUpdateStateHook{} if _, err := node.Eval(ctx); err != nil { t.Fatalf("err: %s", err) } if !mockHook.PostStateUpdateCalled { t.Fatal("should call PostStateUpdate") } if mockHook.PostStateUpdateState.Serial != 42 { t.Fatalf("bad: %#v", mockHook.PostStateUpdateState) } } func TestEvalReadState(t *testing.T) { var output *InstanceState cases := map[string]struct { Resources map[string]*ResourceState Node EvalNode ExpectedInstanceId string }{ "ReadState gets primary instance state": { Resources: map[string]*ResourceState{ "aws_instance.bar": &ResourceState{ Primary: &InstanceState{ ID: "i-abc123", }, }, }, Node: &EvalReadState{ Name: "aws_instance.bar", Output: &output, }, ExpectedInstanceId: "i-abc123", }, "ReadStateDeposed gets deposed instance": { Resources: map[string]*ResourceState{ "aws_instance.bar": &ResourceState{ Deposed: []*InstanceState{ &InstanceState{ID: "i-abc123"}, }, }, }, Node: &EvalReadStateDeposed{ Name: "aws_instance.bar", Output: &output, Index: 0, }, ExpectedInstanceId: "i-abc123", }, } for k, c := range cases { ctx := new(MockEvalContext) ctx.StateState = &State{ Modules: []*ModuleState{ &ModuleState{ Path: rootModulePath, Resources: c.Resources, }, }, } ctx.StateLock = new(sync.RWMutex) ctx.PathPath = rootModulePath result, err := c.Node.Eval(ctx) if err != nil { t.Fatalf("[%s] Got err: %#v", k, err) } expected := c.ExpectedInstanceId if !(result != nil && result.(*InstanceState).ID == expected) { t.Fatalf("[%s] Expected return with ID %#v, got: %#v", k, expected, result) } if !(output != nil && output.ID == expected) { t.Fatalf("[%s] Expected output with ID %#v, got: %#v", k, expected, output) } output = nil } } func TestEvalWriteState(t *testing.T) { state := &State{} ctx := new(MockEvalContext) ctx.StateState = state ctx.StateLock = new(sync.RWMutex) ctx.PathPath = rootModulePath is := &InstanceState{ID: "i-abc123"} node := &EvalWriteState{ Name: "restype.resname", ResourceType: "restype", State: &is, } _, err := node.Eval(ctx) if err != nil { t.Fatalf("Got err: %#v", err) } checkStateString(t, state, ` restype.resname: ID = i-abc123 `) } func TestEvalWriteStateDeposed(t *testing.T) { state := &State{} ctx := new(MockEvalContext) ctx.StateState = state ctx.StateLock = new(sync.RWMutex) ctx.PathPath = rootModulePath is := &InstanceState{ID: "i-abc123"} node := &EvalWriteStateDeposed{ Name: "restype.resname", ResourceType: "restype", State: &is, Index: -1, } _, err := node.Eval(ctx) if err != nil { t.Fatalf("Got err: %#v", err) } checkStateString(t, state, ` restype.resname: (1 deposed) ID = Deposed ID 1 = i-abc123 `) }