TestAgentController unit test is flaky, try to add workaround

TestAgentController really runs the controller and evaluates multiple
calls to the controller's Sync with real informers caching updates.
There is a large amount of non-determinism in this unit test, and it
does not always behave the same way. Because it makes assertions about
the specific errors that should be returned by Sync, it was not
accounting for some errors that are only returned by Sync once in a
while depending on the exact (unpredictable) order of operations.

This commit doesn't fix the non-determinism in the test, but rather
tries to work around it by also allowing other (undesired but
inevitable) error messages to appear in the list of actual error
messages returned by the calls to the Sync function.

Signed-off-by: Margo Crawford <margaretc@vmware.com>
This commit is contained in:
Ryan Richard 2021-07-15 13:41:31 -07:00 committed by Margo Crawford
parent dc567d0d1f
commit 2bba39d723

View File

@ -207,16 +207,17 @@ func TestAgentController(t *testing.T) {
} }
tests := []struct { tests := []struct {
name string name string
discoveryURLOverride *string discoveryURLOverride *string
pinnipedObjects []runtime.Object pinnipedObjects []runtime.Object
kubeObjects []runtime.Object kubeObjects []runtime.Object
addKubeReactions func(*kubefake.Clientset) addKubeReactions func(*kubefake.Clientset)
mocks func(*testing.T, *mocks.MockPodCommandExecutorMockRecorder, *mocks.MockDynamicCertPrivateMockRecorder, *cache.Expiring) mocks func(*testing.T, *mocks.MockPodCommandExecutorMockRecorder, *mocks.MockDynamicCertPrivateMockRecorder, *cache.Expiring)
wantDistinctErrors []string wantDistinctErrors []string
wantDistinctLogs []string alsoAllowUndesiredDistinctErrors []string
wantAgentDeployment *appsv1.Deployment wantDistinctLogs []string
wantStrategy *configv1alpha1.CredentialIssuerStrategy wantAgentDeployment *appsv1.Deployment
wantStrategy *configv1alpha1.CredentialIssuerStrategy
}{ }{
{ {
name: "no CredentialIssuer found", name: "no CredentialIssuer found",
@ -351,6 +352,10 @@ func TestAgentController(t *testing.T) {
wantDistinctErrors: []string{ wantDistinctErrors: []string{
"could not find a healthy agent pod (1 candidate)", "could not find a healthy agent pod (1 candidate)",
}, },
alsoAllowUndesiredDistinctErrors: []string{
// due to the high amount of nondeterminism in this test, this error will sometimes also happen, but is not required to happen
`could not ensure agent deployment: deployments.apps "pinniped-concierge-kube-cert-agent" already exists`,
},
wantDistinctLogs: []string{ wantDistinctLogs: []string{
`kube-cert-agent-controller "level"=0 "msg"="creating new deployment" "deployment"={"name":"pinniped-concierge-kube-cert-agent","namespace":"concierge"} "templatePod"={"name":"kube-controller-manager-1","namespace":"kube-system"}`, `kube-cert-agent-controller "level"=0 "msg"="creating new deployment" "deployment"={"name":"pinniped-concierge-kube-cert-agent","namespace":"concierge"} "templatePod"={"name":"kube-controller-manager-1","namespace":"kube-system"}`,
}, },
@ -395,6 +400,10 @@ func TestAgentController(t *testing.T) {
wantDistinctErrors: []string{ wantDistinctErrors: []string{
"could not find a healthy agent pod (1 candidate)", "could not find a healthy agent pod (1 candidate)",
}, },
alsoAllowUndesiredDistinctErrors: []string{
// due to the high amount of nondeterminism in this test, this error will sometimes also happen, but is not required to happen
`could not ensure agent deployment: deployments.apps "pinniped-concierge-kube-cert-agent" already exists`,
},
wantDistinctLogs: []string{ wantDistinctLogs: []string{
`kube-cert-agent-controller "level"=0 "msg"="creating new deployment" "deployment"={"name":"pinniped-concierge-kube-cert-agent","namespace":"concierge"} "templatePod"={"name":"kube-controller-manager-1","namespace":"kube-system"}`, `kube-cert-agent-controller "level"=0 "msg"="creating new deployment" "deployment"={"name":"pinniped-concierge-kube-cert-agent","namespace":"concierge"} "templatePod"={"name":"kube-controller-manager-1","namespace":"kube-system"}`,
}, },
@ -756,7 +765,14 @@ func TestAgentController(t *testing.T) {
defer cancel() defer cancel()
errorMessages := runControllerUntilQuiet(ctx, t, controller, kubeInformers, conciergeInformers) errorMessages := runControllerUntilQuiet(ctx, t, controller, kubeInformers, conciergeInformers)
assert.Equal(t, tt.wantDistinctErrors, deduplicate(errorMessages), "unexpected errors")
actualErrors := deduplicate(errorMessages)
require.Subsetf(t, actualErrors, tt.wantDistinctErrors, "required error(s) were not found in the actual errors")
allAllowedErrors := append([]string{}, tt.wantDistinctErrors...)
allAllowedErrors = append(allAllowedErrors, tt.alsoAllowUndesiredDistinctErrors...)
require.Subsetf(t, allAllowedErrors, actualErrors, "actual errors contained additional error(s) which is not expected by the test")
assert.Equal(t, tt.wantDistinctLogs, deduplicate(log.Lines()), "unexpected logs") assert.Equal(t, tt.wantDistinctLogs, deduplicate(log.Lines()), "unexpected logs")
// Assert that the agent deployment is in the expected final state. // Assert that the agent deployment is in the expected final state.