You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by mm...@apache.org on 2026/06/17 23:45:00 UTC
(pulsar) branch master updated: [fix][test] Fix flaky testPrepareInitPoliciesCacheAsyncThrowExceptionAfterCreateReader (#26049)
This is an automated email from the ASF dual-hosted git repository.
merlimat pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 6f82106ea6c [fix][test] Fix flaky testPrepareInitPoliciesCacheAsyncThrowExceptionAfterCreateReader (#26049)
6f82106ea6c is described below
commit 6f82106ea6c4d508a883ff27875ef279c7c4101c
Author: Lari Hotari <lh...@users.noreply.github.com>
AuthorDate: Thu Jun 18 02:44:55 2026 +0300
[fix][test] Fix flaky testPrepareInitPoliciesCacheAsyncThrowExceptionAfterCreateReader (#26049)
---
.../SystemTopicBasedTopicPoliciesServiceTest.java | 28 +++++++++++++++++-----
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SystemTopicBasedTopicPoliciesServiceTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SystemTopicBasedTopicPoliciesServiceTest.java
index 2523d1bd49c..b6dbffede81 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SystemTopicBasedTopicPoliciesServiceTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SystemTopicBasedTopicPoliciesServiceTest.java
@@ -49,6 +49,7 @@ import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest;
import org.apache.pulsar.broker.systopic.SystemTopicClient;
import org.apache.pulsar.client.admin.PulsarAdminException;
import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.PulsarClientException;
import org.apache.pulsar.client.api.Schema;
import org.apache.pulsar.common.events.PulsarEvent;
import org.apache.pulsar.common.naming.NamespaceName;
@@ -554,13 +555,28 @@ public class SystemTopicBasedTopicPoliciesServiceTest extends MockedPulsarServic
assertTrue(logFound);
});
- // Since cleanPoliciesCacheInitMap() is executed, should add the failed reader into readerCache again.
- // Then in SystemTopicBasedTopicPoliciesService, readerCache has a closed reader,
- // and policyCacheInitMap do not contain a future.
- // To simulate the situation: when getTopicPolicy() execute, it will do prepareInitPoliciesCacheAsync() and
- // use a closed reader to read the __change_event topic. Then throw exception
- spyReaderCaches.put(NamespaceName.get(NAMESPACE5), readerCompletableFuture);
+ // The reader.close() above drives readMorePoliciesAsync() into cleanPoliciesCacheInitMap(), which logs
+ // "Closing the topic policies reader for" and removes the namespace from policyCacheInitMap and readerCaches.
+ // Now exercise a follow-up prepareInitPoliciesCacheAsync() that reuses a closed reader and must fail in
+ // initPolicesCache(). Two timing hazards made this flaky (#25081), so both are pinned deterministically:
+ // 1) A real closed reader's hasMoreEventsAsync() (Reader.hasMessageAvailableAsync()) can answer from cached
+ // state instead of failing with AlreadyClosedException, in which case initPolicesCache() reaches the end
+ // of the topic and completes successfully and the expected exception never happens. Use a spy whose
+ // hasMoreEventsAsync() always fails with AlreadyClosedException.
+ // 2) A background topic load can re-run prepareInitPoliciesCacheAsync() for the namespace and leave a
+ // completed init future behind; the next call would then short-circuit through the existing-future
+ // branch and never re-initialize. Drop any init future right before the call so it re-initializes, and
+ // stub createSystemTopicClient() so every reader created for this namespace is the failing spy — then
+ // whichever initialization wins the race fails in the same (asserted) way.
+ SystemTopicClient.Reader<PulsarEvent> closedReader = Mockito.spy(reader);
+ Mockito.doReturn(CompletableFuture.failedFuture(
+ new PulsarClientException.AlreadyClosedException("Reader is already closed")))
+ .when(closedReader).hasMoreEventsAsync();
+ Mockito.doReturn(CompletableFuture.completedFuture(closedReader))
+ .when(spyService).createSystemTopicClient(NamespaceName.get(NAMESPACE5));
+ spyReaderCaches.put(NamespaceName.get(NAMESPACE5), CompletableFuture.completedFuture(closedReader));
FieldUtils.writeDeclaredField(spyService, "readerCaches", spyReaderCaches, true);
+ spyService.policyCacheInitMap.remove(NamespaceName.get(NAMESPACE5));
CompletableFuture<Boolean> prepareFuture = new CompletableFuture<>();
try {