From eff75af430bb7feca21ea94593bf998ec12b1ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Fri, 19 Jun 2026 10:29:32 +0200 Subject: [PATCH] test: de-flake DynamicGenericEventSourceRegistrationIT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test captured the reconcile execution count while the create-triggered reconcile cascade was still running (the first await only checked that the ConfigMap and Secret existed, not that the system had quiesced), and asserted an exact +2 executions after the external replace. The reconciler re-writes the ConfigMap/Secret on every execution, so the number of self-induced reconciles is timing-dependent, and after the read-after-write filtering rework (#3414) the reconciler's own follow-up write is filtered, so a deterministic +2 no longer holds. Wait for the execution count to stabilize before capturing the baseline, and assert only a lower bound (at least one more execution) after the replace. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Attila Mészáros --- ...namicGenericEventSourceRegistrationIT.java | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationIT.java index e9c7712954..7e15ab8bf5 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationIT.java @@ -16,6 +16,7 @@ package io.javaoperatorsdk.operator.baseapi.dynamicgenericeventsourceregistration; import java.time.Duration; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -62,22 +63,41 @@ void registersEventSourcesDynamically() { var secret = extension.get(Secret.class, TEST_RESOURCE_NAME); assertThat(cm).isNotNull(); assertThat(secret).isNotNull(); + assertThat(reconciler.getNumberOfEventSources()).isEqualTo(2); }); - var executions = reconciler.getNumberOfExecutions(); + + // The reconciler creates/updates the ConfigMap and Secret on every execution, which produces + // further watch events. Wait for that self-induced cascade to settle before capturing the + // execution count, otherwise the captured value (and any delta we assert on it) is racy. + var executions = awaitStableExecutionCount(reconciler); assertThat(reconciler.getNumberOfEventSources()).isEqualTo(2); - assertThat(executions).isLessThanOrEqualTo(3); var cm = extension.get(ConfigMap.class, TEST_RESOURCE_NAME); cm.getData().put("key2", "val2"); extension.replace(cm); // triggers the reconciliation + // The external change triggers at least one reconciliation. We only assert a lower bound: the + // reconciler's own subsequent write of the ConfigMap is filtered by read-after-write + // consistency, so the exact number of follow-up executions is not deterministic. await() + .untilAsserted( + () -> assertThat(reconciler.getNumberOfExecutions()).isGreaterThan(executions)); + assertThat(reconciler.getNumberOfEventSources()).isEqualTo(2); + } + + /** Waits until the execution count stops changing and returns the stable value. */ + private static int awaitStableExecutionCount( + DynamicGenericEventSourceRegistrationReconciler reconciler) { + var previous = new AtomicInteger(-1); + await() + .pollInterval(Duration.ofMillis(300)) .untilAsserted( () -> { - assertThat(reconciler.getNumberOfExecutions() - executions).isEqualTo(2); + var current = reconciler.getNumberOfExecutions(); + assertThat(current).isEqualTo(previous.getAndSet(current)); }); - assertThat(reconciler.getNumberOfEventSources()).isEqualTo(2); + return reconciler.getNumberOfExecutions(); } DynamicGenericEventSourceRegistrationCustomResource testResource() {