Skip to content

Commit 2edae49

Browse files
authored
test: fix flaky controller-manager tests (#1445)
Go Testing doesn't handle panics in goroutines well. So test fatals need to happen from the main thread. But errors can still happen in goroutines. So change the controller-manager stopping to assert instead of require no errors.
1 parent bbae3d9 commit 2edae49

File tree

2 files changed

+18
-49
lines changed

2 files changed

+18
-49
lines changed

pkg/reconcilermanager/controllers/reposync_controller_manager_test.go

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,7 @@ func TestRepoSyncReconcilerDeploymentLifecycle(t *testing.T) {
6464
errCh := startControllerManager(ctx, t, fakeClient, testReconciler)
6565

6666
// Wait for manager to exit before returning
67-
defer func() {
68-
cancel()
69-
t.Log("waiting for controller-manager to stop")
70-
for err := range errCh {
71-
require.NoError(t, err)
72-
}
73-
}()
67+
defer stopControllerManager(t, cancel, errCh)
7468

7569
watchCtx, watchCancel := context.WithTimeout(ctx, 10*time.Second)
7670
defer watchCancel()
@@ -187,13 +181,7 @@ func TestReconcileInvalidRepoSyncLifecycle(t *testing.T) {
187181
errCh := startControllerManager(ctx, t, fakeClient, testReconciler)
188182

189183
// Wait for manager to exit before returning
190-
defer func() {
191-
cancel()
192-
t.Log("waiting for controller-manager to stop")
193-
for err := range errCh {
194-
require.NoError(t, err)
195-
}
196-
}()
184+
defer stopControllerManager(t, cancel, errCh)
197185

198186
t.Log("watching for RepoSync status update")
199187
watchCtx, watchCancel := context.WithTimeout(ctx, 10*time.Second)
@@ -260,13 +248,7 @@ func TestReconcileRepoSyncLifecycleValidToInvalid(t *testing.T) {
260248
errCh := startControllerManager(ctx, t, fakeClient, testReconciler)
261249

262250
// Wait for manager to exit before returning
263-
defer func() {
264-
cancel()
265-
t.Log("waiting for controller-manager to stop")
266-
for err := range errCh {
267-
require.NoError(t, err)
268-
}
269-
}()
251+
defer stopControllerManager(t, cancel, errCh)
270252

271253
reconcilerKey := core.NsReconcilerObjectKey(rs.Namespace, rs.Name)
272254

pkg/reconcilermanager/controllers/rootsync_controller_manager_test.go

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"time"
2525

2626
"github.com/go-logr/logr/testr"
27+
"github.com/stretchr/testify/assert"
2728
"github.com/stretchr/testify/require"
2829
appsv1 "k8s.io/api/apps/v1"
2930
corev1 "k8s.io/api/core/v1"
@@ -78,13 +79,7 @@ func TestRootSyncReconcilerDeploymentLifecycle(t *testing.T) {
7879
errCh := startControllerManager(ctx, t, fakeClient, testReconciler)
7980

8081
// Wait for manager to exit before returning
81-
defer func() {
82-
cancel()
83-
t.Log("waiting for controller-manager to stop")
84-
for err := range errCh {
85-
require.NoError(t, err)
86-
}
87-
}()
82+
defer stopControllerManager(t, cancel, errCh)
8883

8984
watchCtx, watchCancel := context.WithTimeout(ctx, 10*time.Second)
9085
defer watchCancel()
@@ -201,13 +196,7 @@ func TestReconcileInvalidRootSyncLifecycle(t *testing.T) {
201196
errCh := startControllerManager(ctx, t, fakeClient, testReconciler)
202197

203198
// Wait for manager to exit before returning
204-
defer func() {
205-
cancel()
206-
t.Log("waiting for controller-manager to stop")
207-
for err := range errCh {
208-
require.NoError(t, err)
209-
}
210-
}()
199+
defer stopControllerManager(t, cancel, errCh)
211200

212201
t.Log("watching for RootSync status update")
213202
watchCtx, watchCancel := context.WithTimeout(ctx, 10*time.Second)
@@ -274,13 +263,7 @@ func TestReconcileRootSyncLifecycleValidToInvalid1(t *testing.T) {
274263
errCh := startControllerManager(ctx, t, fakeClient, testReconciler)
275264

276265
// Wait for manager to exit before returning
277-
defer func() {
278-
cancel()
279-
t.Log("waiting for controller-manager to stop")
280-
for err := range errCh {
281-
require.NoError(t, err)
282-
}
283-
}()
266+
defer stopControllerManager(t, cancel, errCh)
284267

285268
reconcilerKey := core.RootReconcilerObjectKey(rs.Name)
286269

@@ -517,13 +500,7 @@ func testDriftProtection(t *testing.T, fakeClient *syncerFake.Client, testReconc
517500
errCh := startControllerManager(ctx, t, fakeClient, testReconciler)
518501

519502
// Wait for manager to exit before returning
520-
defer func() {
521-
cancel()
522-
t.Log("waiting for controller-manager to stop")
523-
for err := range errCh {
524-
require.NoError(t, err)
525-
}
526-
}()
503+
defer stopControllerManager(t, cancel, errCh)
527504

528505
key := objKeyFunc(client.ObjectKeyFromObject(syncObj))
529506

@@ -650,6 +627,16 @@ func startControllerManager(ctx context.Context, t *testing.T, fakeClient *synce
650627
return errCh
651628
}
652629

630+
func stopControllerManager(t *testing.T, cancel context.CancelFunc, errCh <-chan error) {
631+
cancel()
632+
t.Log("waiting for controller-manager to stop")
633+
for err := range errCh {
634+
// Error/Assert instead of Fatal/Require, to avoid panic when called async.
635+
// Go tests that panic in a defer can be flakey.
636+
assert.NoError(t, err)
637+
}
638+
}
639+
653640
func logObjectYAMLIfFailed(t *testing.T, fakeClient *syncerFake.Client, obj client.Object) {
654641
if t.Failed() {
655642
err := fakeClient.Get(context.Background(), client.ObjectKeyFromObject(obj), obj)

0 commit comments

Comments
 (0)