Skip to content

Commit 4147ba9

Browse files
separate tests between different modes
1 parent e8a8921 commit 4147ba9

File tree

1 file changed

+207
-45
lines changed

1 file changed

+207
-45
lines changed

internal/rpcapi/stacks_test.go

Lines changed: 207 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,8 @@ func TestStacksPlanStackChanges(t *testing.T) {
488488
}
489489
}
490490

491-
func TestStackChangeProgressDuringPlan(t *testing.T) {
491+
func TestStackChangeProgressDuringPlanNormal(t *testing.T) {
492492
tcs := map[string]struct {
493-
mode stacks.PlanMode
494493
source string
495494
store *stacks_testing_provider.ResourceStore
496495
state []stackstate.AppliedChange
@@ -499,7 +498,6 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
499498
diagnostics []*terraform1.Diagnostic
500499
}{
501500
"deferred_changes": {
502-
mode: stacks.PlanMode_NORMAL,
503501
source: "git::https://example.com/bar.git",
504502
want: []*stacks.StackChangeProgress{
505503
{
@@ -569,7 +567,6 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
569567
},
570568
},
571569
"moved": {
572-
mode: stacks.PlanMode_NORMAL,
573570
source: "git::https://example.com/moved.git",
574571
store: stacks_testing_provider.NewResourceStoreBuilder().
575572
AddResource("before", cty.ObjectVal(map[string]cty.Value{
@@ -631,7 +628,6 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
631628
},
632629
},
633630
"import": {
634-
mode: stacks.PlanMode_NORMAL,
635631
source: "git::https://example.com/import.git",
636632
store: stacks_testing_provider.NewResourceStoreBuilder().
637633
AddResource("self", cty.ObjectVal(map[string]cty.Value{
@@ -753,7 +749,6 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
753749
},
754750
},
755751
"removed": {
756-
mode: stacks.PlanMode_NORMAL,
757752
source: "git::https://example.com/removed.git",
758753
store: stacks_testing_provider.NewResourceStoreBuilder().
759754
AddResource("resource", cty.ObjectVal(map[string]cty.Value{
@@ -816,7 +811,6 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
816811
},
817812
},
818813
"invalid - update": {
819-
mode: stacks.PlanMode_NORMAL,
820814
source: "git::https://example.com/invalid.git",
821815
store: stacks_testing_provider.NewResourceStoreBuilder().
822816
AddResource("resource", cty.ObjectVal(map[string]cty.Value{
@@ -881,7 +875,6 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
881875
},
882876
},
883877
"invalid - create": {
884-
mode: stacks.PlanMode_NORMAL,
885878
source: "git::https://example.com/invalid.git",
886879
store: stacks_testing_provider.NewResourceStoreBuilder().
887880
AddResource("resource", cty.ObjectVal(map[string]cty.Value{
@@ -927,8 +920,7 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
927920
},
928921
},
929922
},
930-
"destroy plan": {
931-
mode: stacks.PlanMode_DESTROY,
923+
"no-op plan": {
932924
source: "git::https://example.com/simple.git",
933925
store: stacks_testing_provider.NewResourceStoreBuilder().
934926
AddResource("resource", cty.ObjectVal(map[string]cty.Value{
@@ -956,35 +948,213 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
956948
},
957949
want: []*stacks.StackChangeProgress{
958950
{
959-
Event: &stacks.StackChangeProgress_ResourceInstancePlannedChange_{
960-
ResourceInstancePlannedChange: &stacks.StackChangeProgress_ResourceInstancePlannedChange{
961-
Addr: &stacks.ResourceInstanceObjectInStackAddr{
951+
Event: &stacks.StackChangeProgress_ComponentInstanceStatus_{
952+
ComponentInstanceStatus: &stacks.StackChangeProgress_ComponentInstanceStatus{
953+
Addr: &stacks.ComponentInstanceInStackAddr{
954+
ComponentAddr: "component.self",
962955
ComponentInstanceAddr: "component.self",
963-
ResourceInstanceAddr: "testing_resource.resource",
964-
},
965-
Actions: []stacks.ChangeType{
966-
stacks.ChangeType_DELETE,
967956
},
968-
ProviderAddr: "registry.terraform.io/hashicorp/testing",
957+
Status: stacks.StackChangeProgress_ComponentInstanceStatus_PLANNED,
969958
},
970959
},
971960
},
961+
},
962+
},
963+
"empty plan": {
964+
source: "git::https://example.com/empty.git",
965+
state: []stackstate.AppliedChange{
966+
&stackstate.AppliedChangeComponentInstance{
967+
ComponentAddr: mustAbsComponent(t, "component.self"),
968+
ComponentInstanceAddr: mustAbsComponentInstance(t, "component.self"),
969+
},
970+
},
971+
want: []*stacks.StackChangeProgress{
972972
{
973-
Event: &stacks.StackChangeProgress_ComponentInstanceChanges_{
974-
ComponentInstanceChanges: &stacks.StackChangeProgress_ComponentInstanceChanges{
973+
Event: &stacks.StackChangeProgress_ComponentInstanceStatus_{
974+
ComponentInstanceStatus: &stacks.StackChangeProgress_ComponentInstanceStatus{
975975
Addr: &stacks.ComponentInstanceInStackAddr{
976976
ComponentAddr: "component.self",
977977
ComponentInstanceAddr: "component.self",
978978
},
979-
Total: 1,
980-
Remove: 1,
979+
Status: stacks.StackChangeProgress_ComponentInstanceStatus_PLANNED,
981980
},
982981
},
983982
},
984983
},
985984
},
986-
"no-op plan": {
987-
mode: stacks.PlanMode_NORMAL,
985+
}
986+
987+
for name, tc := range tcs {
988+
t.Run(name, func(t *testing.T) {
989+
ctx := context.Background()
990+
handles := newHandleTable()
991+
stacksServer := newStacksServer(newStopper(), handles, disco.New(), &serviceOpts{})
992+
993+
// For this test, we do actually want to use a "real" provider. We'll
994+
// use the providerCacheOverride to side-load the testing provider.
995+
stacksServer.providerCacheOverride = make(map[addrs.Provider]providers.Factory)
996+
stacksServer.providerCacheOverride[addrs.NewDefaultProvider("testing")] = func() (providers.Interface, error) {
997+
return stacks_testing_provider.NewProviderWithData(t, tc.store), nil
998+
}
999+
lock := depsfile.NewLocks()
1000+
lock.SetProvider(
1001+
addrs.NewDefaultProvider("testing"),
1002+
providerreqs.MustParseVersion("0.0.0"),
1003+
providerreqs.MustParseVersionConstraints("=0.0.0"),
1004+
providerreqs.PreferredHashes([]providerreqs.Hash{}),
1005+
)
1006+
stacksServer.providerDependencyLockOverride = lock
1007+
1008+
sb, err := sourcebundle.OpenDir("testdata/sourcebundle")
1009+
if err != nil {
1010+
t.Fatal(err)
1011+
}
1012+
hnd := handles.NewSourceBundle(sb)
1013+
1014+
client, close := grpcClientForTesting(ctx, t, func(srv *grpc.Server) {
1015+
stacks.RegisterStacksServer(srv, stacksServer)
1016+
})
1017+
defer close()
1018+
1019+
stacksClient := stacks.NewStacksClient(client)
1020+
1021+
open, err := stacksClient.OpenStackConfiguration(ctx, &stacks.OpenStackConfiguration_Request{
1022+
SourceBundleHandle: hnd.ForProtobuf(),
1023+
SourceAddress: &terraform1.SourceAddress{
1024+
Source: tc.source,
1025+
},
1026+
})
1027+
if err != nil {
1028+
t.Fatalf("unexpected error: %s", err)
1029+
}
1030+
defer stacksClient.CloseStackConfiguration(ctx, &stacks.CloseStackConfiguration_Request{
1031+
StackConfigHandle: open.StackConfigHandle,
1032+
})
1033+
1034+
resp, err := stacksClient.PlanStackChanges(ctx, &stacks.PlanStackChanges_Request{
1035+
PlanMode: stacks.PlanMode_NORMAL,
1036+
StackConfigHandle: open.StackConfigHandle,
1037+
PreviousState: appliedChangeToRawState(t, tc.state),
1038+
InputValues: func() map[string]*stacks.DynamicValueWithSource {
1039+
values := make(map[string]*stacks.DynamicValueWithSource)
1040+
for name, value := range tc.inputs {
1041+
values[name] = &stacks.DynamicValueWithSource{
1042+
Value: &stacks.DynamicValue{
1043+
Msgpack: mustMsgpack(t, value, value.Type()),
1044+
},
1045+
SourceRange: &terraform1.SourceRange{
1046+
Start: &terraform1.SourcePos{},
1047+
End: &terraform1.SourcePos{},
1048+
},
1049+
}
1050+
}
1051+
return values
1052+
}(),
1053+
})
1054+
if err != nil {
1055+
t.Fatalf("unexpected error: %s", err)
1056+
}
1057+
1058+
wantEvents := splitStackOperationEvents(func() []*stacks.PlanStackChanges_Event {
1059+
events := make([]*stacks.PlanStackChanges_Event, 0, len(tc.want))
1060+
for _, want := range tc.want {
1061+
events = append(events, &stacks.PlanStackChanges_Event{
1062+
Event: &stacks.PlanStackChanges_Event_Progress{
1063+
Progress: want,
1064+
},
1065+
})
1066+
}
1067+
return events
1068+
}())
1069+
1070+
gotEvents := splitStackOperationEvents(func() []*stacks.PlanStackChanges_Event {
1071+
var events []*stacks.PlanStackChanges_Event
1072+
for {
1073+
event, err := resp.Recv()
1074+
if err == io.EOF {
1075+
break
1076+
}
1077+
if err != nil {
1078+
t.Fatalf("unexpected error: %s", err)
1079+
}
1080+
events = append(events, event)
1081+
}
1082+
return events
1083+
}())
1084+
1085+
// First, validate the diagnostics. Most of the tests are either
1086+
// expecting a specific single diagnostic so we do actually check
1087+
// everything.
1088+
// We don't care about the ordering since it's not guaranteed.
1089+
1090+
if len(tc.diagnostics) != len(gotEvents.Diagnostics) {
1091+
t.Fatalf("expected %d diagnostics, got %d", len(tc.diagnostics), len(gotEvents.Diagnostics))
1092+
}
1093+
1094+
DIAGS:
1095+
for _, expectedDiag := range tc.diagnostics {
1096+
for _, gotDiagEvent := range gotEvents.Diagnostics {
1097+
gotDiag := gotDiagEvent.Event.(*stacks.PlanStackChanges_Event_Diagnostic).Diagnostic
1098+
1099+
if diff := cmp.Diff(expectedDiag, gotDiag, protocmp.Transform()); diff == "" {
1100+
continue DIAGS // Found it
1101+
}
1102+
}
1103+
1104+
// If we reach this point we did not find the diag
1105+
t.Errorf("missing expected diagnostic: %v, got %v", expectedDiag, gotEvents.Diagnostics)
1106+
}
1107+
1108+
// Now we're going to manually verify the existence of some key events.
1109+
// We're not looking for every event because (a) the exact ordering of
1110+
// events is not guaranteed and (b) we don't want to start failing every
1111+
// time a new event is added.
1112+
1113+
WantPlannedChange:
1114+
for _, want := range wantEvents.PlannedChanges {
1115+
for _, got := range gotEvents.PlannedChanges {
1116+
if len(cmp.Diff(want, got, protocmp.Transform())) == 0 {
1117+
continue WantPlannedChange
1118+
}
1119+
}
1120+
t.Errorf("missing expected planned change: %v", want)
1121+
}
1122+
1123+
WantMiscHook:
1124+
for _, want := range wantEvents.MiscHooks {
1125+
for _, got := range gotEvents.MiscHooks {
1126+
if len(cmp.Diff(want, got, protocmp.Transform())) == 0 {
1127+
continue WantMiscHook
1128+
}
1129+
}
1130+
t.Errorf("missing expected event: %v", want)
1131+
}
1132+
1133+
if t.Failed() {
1134+
// if the test failed, let's print out all the events we got to help
1135+
// with debugging.
1136+
for _, evt := range gotEvents.MiscHooks {
1137+
t.Logf(" returned event: %s", evt.String())
1138+
}
1139+
1140+
for _, evt := range gotEvents.PlannedChanges {
1141+
t.Logf(" returned event: %s", evt.String())
1142+
}
1143+
}
1144+
})
1145+
}
1146+
}
1147+
1148+
func TestStackChangeProgressDuringPlanDestroy(t *testing.T) {
1149+
tcs := map[string]struct {
1150+
source string
1151+
store *stacks_testing_provider.ResourceStore
1152+
state []stackstate.AppliedChange
1153+
inputs map[string]cty.Value
1154+
want []*stacks.StackChangeProgress
1155+
diagnostics []*terraform1.Diagnostic
1156+
}{
1157+
"destroy plan": {
9881158
source: "git::https://example.com/simple.git",
9891159
store: stacks_testing_provider.NewResourceStoreBuilder().
9901160
AddResource("resource", cty.ObjectVal(map[string]cty.Value{
@@ -1012,36 +1182,28 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
10121182
},
10131183
want: []*stacks.StackChangeProgress{
10141184
{
1015-
Event: &stacks.StackChangeProgress_ComponentInstanceStatus_{
1016-
ComponentInstanceStatus: &stacks.StackChangeProgress_ComponentInstanceStatus{
1017-
Addr: &stacks.ComponentInstanceInStackAddr{
1018-
ComponentAddr: "component.self",
1185+
Event: &stacks.StackChangeProgress_ResourceInstancePlannedChange_{
1186+
ResourceInstancePlannedChange: &stacks.StackChangeProgress_ResourceInstancePlannedChange{
1187+
Addr: &stacks.ResourceInstanceObjectInStackAddr{
10191188
ComponentInstanceAddr: "component.self",
1189+
ResourceInstanceAddr: "testing_resource.resource",
10201190
},
1021-
Status: stacks.StackChangeProgress_ComponentInstanceStatus_PLANNED,
1191+
Actions: []stacks.ChangeType{
1192+
stacks.ChangeType_DELETE,
1193+
},
1194+
ProviderAddr: "registry.terraform.io/hashicorp/testing",
10221195
},
10231196
},
10241197
},
1025-
},
1026-
},
1027-
"empty plan": {
1028-
mode: stacks.PlanMode_NORMAL,
1029-
source: "git::https://example.com/empty.git",
1030-
state: []stackstate.AppliedChange{
1031-
&stackstate.AppliedChangeComponentInstance{
1032-
ComponentAddr: mustAbsComponent(t, "component.self"),
1033-
ComponentInstanceAddr: mustAbsComponentInstance(t, "component.self"),
1034-
},
1035-
},
1036-
want: []*stacks.StackChangeProgress{
10371198
{
1038-
Event: &stacks.StackChangeProgress_ComponentInstanceStatus_{
1039-
ComponentInstanceStatus: &stacks.StackChangeProgress_ComponentInstanceStatus{
1199+
Event: &stacks.StackChangeProgress_ComponentInstanceChanges_{
1200+
ComponentInstanceChanges: &stacks.StackChangeProgress_ComponentInstanceChanges{
10401201
Addr: &stacks.ComponentInstanceInStackAddr{
10411202
ComponentAddr: "component.self",
10421203
ComponentInstanceAddr: "component.self",
10431204
},
1044-
Status: stacks.StackChangeProgress_ComponentInstanceStatus_PLANNED,
1205+
Total: 1,
1206+
Remove: 1,
10451207
},
10461208
},
10471209
},
@@ -1097,7 +1259,7 @@ func TestStackChangeProgressDuringPlan(t *testing.T) {
10971259
})
10981260

10991261
resp, err := stacksClient.PlanStackChanges(ctx, &stacks.PlanStackChanges_Request{
1100-
PlanMode: tc.mode,
1262+
PlanMode: stacks.PlanMode_DESTROY,
11011263
StackConfigHandle: open.StackConfigHandle,
11021264
PreviousState: appliedChangeToRawState(t, tc.state),
11031265
InputValues: func() map[string]*stacks.DynamicValueWithSource {

0 commit comments

Comments
 (0)