remote: Fix flaky ByteStreamUploaderTest.
Running locally, I noticed that the multipleBlobsUploadShouldWork() test
is flaky (~1% of all runs).
The flakiness exists due to Future.get() being notified about completion
before the future's listeners are executed. We make use of future
listeners to remove an upload digest from an internal hashmap, after the
upload completed. Thus, checking for this map to be empty immediately
after uploadBlob (aka Future.get()) returned, could sometimes fail due
to the listeners not having executed yet.
The fix is to periodically poll the hashmap until all listeners have
executed.
RELNOTES: None.
PiperOrigin-RevId: 161507486
diff --git a/src/test/java/com/google/devtools/build/lib/remote/ByteStreamUploaderTest.java b/src/test/java/com/google/devtools/build/lib/remote/ByteStreamUploaderTest.java
index d9b5d3e..596b5a6 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/ByteStreamUploaderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/ByteStreamUploaderTest.java
@@ -163,7 +163,7 @@
// This test should not have triggered any retries.
Mockito.verifyZeroInteractions(mockBackoff);
- assertThat(uploader.uploadsInProgress()).isFalse();
+ blockUntilInternalStateConsistent(uploader);
}
@Test(timeout = 20000)
@@ -251,7 +251,7 @@
uploader.uploadBlobs(builders);
- assertThat(uploader.uploadsInProgress()).isFalse();
+ blockUntilInternalStateConsistent(uploader);
}
@Test(timeout = 10000)
@@ -383,7 +383,7 @@
assertThat(f1.isCancelled()).isTrue();
assertThat(f2.isCancelled()).isTrue();
- assertThat(uploader.uploadsInProgress()).isFalse();
+ blockUntilInternalStateConsistent(uploader);
}
@Test(timeout = 10000)
@@ -521,4 +521,12 @@
return retries;
}
}
+
+ private void blockUntilInternalStateConsistent(ByteStreamUploader uploader) throws Exception {
+ // Poll until all upload futures have been removed from the internal hash map. The polling is
+ // necessary, as listeners are executed after Future.get() calls are notified about completion.
+ while (uploader.uploadsInProgress()) {
+ Thread.sleep(1);
+ }
+ }
}