This is an automated email from the ASF dual-hosted git repository.
yhu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push:
new 79fcfc6fcb5 Fix flakiness for BeamFnLoggingClientTest (#27308)
79fcfc6fcb5 is described below
commit 79fcfc6fcb502b1bc9c2b60bfbfc321586d6db99
Author: Sam Whittle <[email protected]>
AuthorDate: Wed Jul 5 23:22:06 2023 +0200
Fix flakiness for BeamFnLoggingClientTest (#27308)
---
.../harness/logging/BeamFnLoggingClientTest.java | 50 +++++++++++++++-------
1 file changed, 34 insertions(+), 16 deletions(-)
diff --git
a/sdks/java/harness/src/test/java/org/apache/beam/fn/harness/logging/BeamFnLoggingClientTest.java
b/sdks/java/harness/src/test/java/org/apache/beam/fn/harness/logging/BeamFnLoggingClientTest.java
index 1fd8e249dd0..d93762c06c9 100644
---
a/sdks/java/harness/src/test/java/org/apache/beam/fn/harness/logging/BeamFnLoggingClientTest.java
+++
b/sdks/java/harness/src/test/java/org/apache/beam/fn/harness/logging/BeamFnLoggingClientTest.java
@@ -27,9 +27,10 @@ import static org.junit.Assert.assertTrue;
import java.util.Collection;
import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.Phaser;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Handler;
import java.util.logging.Level;
@@ -234,7 +235,7 @@ public class BeamFnLoggingClientTest {
// removes the only reference and the logger may get GC'd before the
assertions (BEAM-4136).
Logger rootLogger = null;
Logger configuredLogger = null;
- Phaser streamBlocker = new Phaser(1);
+ CompletableFuture<Object> streamBlocker = new CompletableFuture<Object>();
Endpoints.ApiServiceDescriptor apiServiceDescriptor =
Endpoints.ApiServiceDescriptor.newBuilder()
@@ -249,7 +250,7 @@ public class BeamFnLoggingClientTest {
StreamObserver<BeamFnApi.LogControl> outboundObserver) {
// Block before returning an error on the stream so that
we can observe the
// loggers before they are reset.
- streamBlocker.awaitAdvance(1);
+ streamBlocker.join();
outboundServerObserver.set(outboundObserver);
outboundObserver.onError(
Status.INTERNAL.withDescription("TEST
ERROR").asException());
@@ -275,7 +276,7 @@ public class BeamFnLoggingClientTest {
rootLogger = LogManager.getLogManager().getLogger("");
configuredLogger =
LogManager.getLogManager().getLogger("ConfiguredLogger");
// Allow the stream to return with an error.
- assertEquals(0, streamBlocker.arrive());
+ streamBlocker.complete(new Object());
thrown.expectMessage("TEST ERROR");
client.close();
} finally {
@@ -356,15 +357,22 @@ public class BeamFnLoggingClientTest {
@Test
public void testClosableWhenBlockingForOnReady() throws Exception {
BeamFnLoggingMDC.setInstructionId("instruction-1");
- Collection<BeamFnApi.LogEntry> values = new ConcurrentLinkedQueue<>();
+ AtomicInteger testEntriesObserved = new AtomicInteger();
+ AtomicBoolean onReadyBlocking = new AtomicBoolean();
AtomicReference<StreamObserver<BeamFnApi.LogControl>>
outboundServerObserver =
new AtomicReference<>();
final AtomicBoolean elementsAllowed = new AtomicBoolean(true);
CallStreamObserver<BeamFnApi.LogEntry.List> inboundServerObserver =
TestStreams.withOnNext(
- (BeamFnApi.LogEntry.List logEntries) ->
- values.addAll(logEntries.getLogEntriesList()))
+ (BeamFnApi.LogEntry.List logEntries) -> {
+ for (BeamFnApi.LogEntry entry :
logEntries.getLogEntriesList()) {
+ if
(entry.toBuilder().clearCustomData().build().equals(TEST_ENTRY)) {
+ testEntriesObserved.addAndGet(1);
+ }
+ }
+ })
+ .withOnCompleted(() -> outboundServerObserver.get().onCompleted())
.build();
Endpoints.ApiServiceDescriptor apiServiceDescriptor =
@@ -397,6 +405,10 @@ public class BeamFnLoggingClientTest {
delegate) {
@Override
public boolean isReady() {
+ if (elementsAllowed.get()) {
+ return true;
+ }
+ onReadyBlocking.set(true);
return elementsAllowed.get();
}
};
@@ -430,20 +442,28 @@ public class BeamFnLoggingClientTest {
}
// Measure how long it takes all the logs to appear.
int sleepTime = 0;
- while (values.size() < numEntries) {
+ while (testEntriesObserved.get() < numEntries) {
++sleepTime;
Thread.sleep(1);
}
// Attempt to enter the blocking state by pushing back on the stream,
publishing records and
// then giving them time for it to block.
elementsAllowed.set(false);
- for (int i = 0; i < numEntries; ++i) {
+ int postAllowedLogs = 0;
+ while (!onReadyBlocking.get()) {
+ ++postAllowedLogs;
configuredLogger.log(TEST_RECORD);
+ Thread.sleep(1);
}
+
+ // Even with sleeping to give some additional time for the logs that
were sent by the client
+ // to be observed by the server we should not observe all the client
logs, indicating we're
+ // blocking as intended.
Thread.sleep(sleepTime * 3);
- // At this point, the background thread is either blocking as intended
or the background
- // thread hasn't yet observed all the input. In either case the test
should pass.
- assertTrue(values.size() < numEntries * 2);
+ assertTrue(testEntriesObserved.get() < numEntries + postAllowedLogs);
+
+ // Allow entries to drain to speed up close.
+ elementsAllowed.set(true);
client.close();
@@ -463,13 +483,11 @@ public class BeamFnLoggingClientTest {
@Test
public void testServerCloseNotifiesTermination() throws Exception {
BeamFnLoggingMDC.setInstructionId("instruction-1");
- Collection<BeamFnApi.LogEntry> values = new ConcurrentLinkedQueue<>();
AtomicReference<StreamObserver<BeamFnApi.LogControl>>
outboundServerObserver =
new AtomicReference<>();
CallStreamObserver<BeamFnApi.LogEntry.List> inboundServerObserver =
- TestStreams.withOnNext(
- (BeamFnApi.LogEntry.List logEntries) ->
- values.addAll(logEntries.getLogEntriesList()))
+ TestStreams.withOnNext((BeamFnApi.LogEntry.List logEntries) -> {})
+ .withOnCompleted(() -> outboundServerObserver.get().onCompleted())
.build();
Endpoints.ApiServiceDescriptor apiServiceDescriptor =