Fix flapping JSON output test
This test would previously fail randomly due to the use of multiple resource instances. Instance keys are iterated over as a map for presentation, which has intentionally inconsistent ordering. To fix this, I changed the test to use different resource addresses for the three drift cases. I also extracted them to a separate test, and tweaked the test helper functions to reduce the number of fatal exit points, to make failed test debugging easier.
This commit is contained in:
parent
3e5bfa7364
commit
c51112a30c
|
@ -303,12 +303,16 @@ func testJSONViewOutputEqualsFull(t *testing.T, output string, want []map[string
|
|||
gotLines := strings.Split(output, "\n")
|
||||
|
||||
if len(gotLines) != len(want) {
|
||||
t.Fatalf("unexpected number of messages. got %d, want %d", len(gotLines), len(want))
|
||||
t.Errorf("unexpected number of messages. got %d, want %d", len(gotLines), len(want))
|
||||
}
|
||||
|
||||
// Unmarshal each line and compare to the expected value
|
||||
for i := range gotLines {
|
||||
var gotStruct map[string]interface{}
|
||||
if i >= len(want) {
|
||||
t.Error("reached end of want messages too soon")
|
||||
break
|
||||
}
|
||||
wantStruct := want[i]
|
||||
|
||||
if err := json.Unmarshal([]byte(gotLines[i]), &gotStruct); err != nil {
|
||||
|
@ -323,12 +327,12 @@ func testJSONViewOutputEqualsFull(t *testing.T, output string, want []map[string
|
|||
|
||||
// Verify the timestamp format
|
||||
if _, err := time.Parse("2006-01-02T15:04:05.000000Z07:00", timestamp.(string)); err != nil {
|
||||
t.Fatalf("error parsing timestamp: %s", err)
|
||||
t.Errorf("error parsing timestamp on line %d: %s", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !cmp.Equal(wantStruct, gotStruct) {
|
||||
t.Fatalf("unexpected output on line %d:\n%s", i, cmp.Diff(wantStruct, gotStruct))
|
||||
t.Errorf("unexpected output on line %d:\n%s", i, cmp.Diff(wantStruct, gotStruct))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -517,103 +517,10 @@ func TestOperationJSON_plan(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
PrevRunState: states.BuildState(func(state *states.SyncState) {
|
||||
// Update
|
||||
state.SetResourceInstanceCurrent(
|
||||
boop.Instance(addrs.IntKey(0)).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"bar"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
// Delete
|
||||
state.SetResourceInstanceCurrent(
|
||||
boop.Instance(addrs.IntKey(1)).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"boop"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
// No-op
|
||||
state.SetResourceInstanceCurrent(
|
||||
beep.Instance(addrs.NoKey).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"boop"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
}),
|
||||
PriorState: states.BuildState(func(state *states.SyncState) {
|
||||
// Update
|
||||
state.SetResourceInstanceCurrent(
|
||||
boop.Instance(addrs.IntKey(0)).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"baz"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
// Delete
|
||||
state.SetResourceInstanceCurrent(
|
||||
boop.Instance(addrs.IntKey(1)).Absolute(root),
|
||||
nil,
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
// No-op
|
||||
state.SetResourceInstanceCurrent(
|
||||
beep.Instance(addrs.NoKey).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"boop"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
}),
|
||||
}
|
||||
v.Plan(plan, testSchemas())
|
||||
|
||||
want := []map[string]interface{}{
|
||||
// Drift detected: update
|
||||
{
|
||||
"@level": "info",
|
||||
"@message": "test_resource.boop[0]: Drift detected (update)",
|
||||
"@module": "terraform.ui",
|
||||
"type": "resource_drift",
|
||||
"change": map[string]interface{}{
|
||||
"action": "update",
|
||||
"resource": map[string]interface{}{
|
||||
"addr": "test_resource.boop[0]",
|
||||
"implied_provider": "test",
|
||||
"module": "",
|
||||
"resource": "test_resource.boop[0]",
|
||||
"resource_key": float64(0),
|
||||
"resource_name": "boop",
|
||||
"resource_type": "test_resource",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Drift detected: delete
|
||||
{
|
||||
"@level": "info",
|
||||
"@message": "test_resource.boop[1]: Drift detected (delete)",
|
||||
"@module": "terraform.ui",
|
||||
"type": "resource_drift",
|
||||
"change": map[string]interface{}{
|
||||
"action": "delete",
|
||||
"resource": map[string]interface{}{
|
||||
"addr": "test_resource.boop[1]",
|
||||
"implied_provider": "test",
|
||||
"module": "",
|
||||
"resource": "test_resource.boop[1]",
|
||||
"resource_key": float64(1),
|
||||
"resource_name": "boop",
|
||||
"resource_type": "test_resource",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Create-then-delete should result in replace
|
||||
{
|
||||
"@level": "info",
|
||||
|
@ -728,6 +635,134 @@ func TestOperationJSON_plan(t *testing.T) {
|
|||
testJSONViewOutputEquals(t, done(t).Stdout(), want)
|
||||
}
|
||||
|
||||
func TestOperationJSON_planDrift(t *testing.T) {
|
||||
streams, done := terminal.StreamsForTesting(t)
|
||||
v := &OperationJSON{view: NewJSONView(NewView(streams))}
|
||||
|
||||
root := addrs.RootModuleInstance
|
||||
boop := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_resource", Name: "boop"}
|
||||
beep := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_resource", Name: "beep"}
|
||||
derp := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_resource", Name: "derp"}
|
||||
|
||||
plan := &plans.Plan{
|
||||
Changes: &plans.Changes{
|
||||
Resources: []*plans.ResourceInstanceChangeSrc{},
|
||||
},
|
||||
PrevRunState: states.BuildState(func(state *states.SyncState) {
|
||||
// Update
|
||||
state.SetResourceInstanceCurrent(
|
||||
boop.Instance(addrs.NoKey).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"bar"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
// Delete
|
||||
state.SetResourceInstanceCurrent(
|
||||
beep.Instance(addrs.NoKey).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"boop"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
// No-op
|
||||
state.SetResourceInstanceCurrent(
|
||||
derp.Instance(addrs.NoKey).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"boop"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
}),
|
||||
PriorState: states.BuildState(func(state *states.SyncState) {
|
||||
// Update
|
||||
state.SetResourceInstanceCurrent(
|
||||
boop.Instance(addrs.NoKey).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"baz"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
// Delete
|
||||
state.SetResourceInstanceCurrent(
|
||||
beep.Instance(addrs.NoKey).Absolute(root),
|
||||
nil,
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
// No-op
|
||||
state.SetResourceInstanceCurrent(
|
||||
derp.Instance(addrs.NoKey).Absolute(root),
|
||||
&states.ResourceInstanceObjectSrc{
|
||||
Status: states.ObjectReady,
|
||||
AttrsJSON: []byte(`{"foo":"boop"}`),
|
||||
},
|
||||
root.ProviderConfigDefault(addrs.NewDefaultProvider("test")),
|
||||
)
|
||||
}),
|
||||
}
|
||||
v.Plan(plan, testSchemas())
|
||||
|
||||
want := []map[string]interface{}{
|
||||
// Drift detected: update
|
||||
{
|
||||
"@level": "info",
|
||||
"@message": "test_resource.boop: Drift detected (update)",
|
||||
"@module": "terraform.ui",
|
||||
"type": "resource_drift",
|
||||
"change": map[string]interface{}{
|
||||
"action": "update",
|
||||
"resource": map[string]interface{}{
|
||||
"addr": "test_resource.boop",
|
||||
"implied_provider": "test",
|
||||
"module": "",
|
||||
"resource": "test_resource.boop",
|
||||
"resource_key": nil,
|
||||
"resource_name": "boop",
|
||||
"resource_type": "test_resource",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Drift detected: delete
|
||||
{
|
||||
"@level": "info",
|
||||
"@message": "test_resource.beep: Drift detected (delete)",
|
||||
"@module": "terraform.ui",
|
||||
"type": "resource_drift",
|
||||
"change": map[string]interface{}{
|
||||
"action": "delete",
|
||||
"resource": map[string]interface{}{
|
||||
"addr": "test_resource.beep",
|
||||
"implied_provider": "test",
|
||||
"module": "",
|
||||
"resource": "test_resource.beep",
|
||||
"resource_key": nil,
|
||||
"resource_name": "beep",
|
||||
"resource_type": "test_resource",
|
||||
},
|
||||
},
|
||||
},
|
||||
// No changes
|
||||
{
|
||||
"@level": "info",
|
||||
"@message": "Plan: 0 to add, 0 to change, 0 to destroy.",
|
||||
"@module": "terraform.ui",
|
||||
"type": "change_summary",
|
||||
"changes": map[string]interface{}{
|
||||
"operation": "plan",
|
||||
"add": float64(0),
|
||||
"change": float64(0),
|
||||
"remove": float64(0),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testJSONViewOutputEquals(t, done(t).Stdout(), want)
|
||||
}
|
||||
|
||||
func TestOperationJSON_plannedChange(t *testing.T) {
|
||||
streams, done := terminal.StreamsForTesting(t)
|
||||
v := &OperationJSON{view: NewJSONView(NewView(streams))}
|
||||
|
|
Loading…
Reference in New Issue