From 4ff2a0ea77cb89fdf7de5fb95d6f7cc205fa0aa8 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Mon, 6 May 2024 14:50:22 -0700 Subject: [PATCH 01/14] Re-enable tests. JAVA-5104 --- ...sessions-override-operation-timeoutMS.json | 8 +-- .../ClientSideOperationTimeoutTest.java | 18 ++++--- ...tClientSideOperationsTimeoutProseTest.java | 50 +++++++++++++++++++ .../ClientSideOperationTimeoutTest.java | 46 +++-------------- 4 files changed, 72 insertions(+), 50 deletions(-) diff --git a/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/sessions-override-operation-timeoutMS.json b/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/sessions-override-operation-timeoutMS.json index 441c698328c..2839d0a33b7 100644 --- a/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/sessions-override-operation-timeoutMS.json +++ b/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/sessions-override-operation-timeoutMS.json @@ -82,7 +82,10 @@ }, { "name": "startTransaction", - "object": "session" + "object": "session", + "arguments": { + "timeoutMS": 500 + } }, { "name": "insertOne", @@ -97,9 +100,6 @@ { "name": "commitTransaction", "object": "session", - "arguments": { - "timeoutMS": 500 - }, "expectError": { "isTimeoutError": true } diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java index 50edc0edcfd..7ac88243437 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java @@ -33,13 +33,14 @@ import java.io.IOException; import java.net.URISyntaxException; import java.util.Collection; +import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import static com.mongodb.client.ClientSideOperationTimeoutTest.checkSkipCSOTTest; -import static com.mongodb.client.ClientSideOperationTimeoutTest.racyTestAssertion; +import static com.mongodb.client.ClientSideOperationTimeoutTest.skipOperationTimeoutTests; import static com.mongodb.reactivestreams.client.syncadapter.SyncMongoClient.disableSleep; import static com.mongodb.reactivestreams.client.syncadapter.SyncMongoClient.enableSleepAfterCursorError; import static java.lang.String.format; +import static java.util.Arrays.asList; import static org.junit.Assume.assumeFalse; // See https://github.com/mongodb/specifications/tree/master/source/client-side-operation-timeout/tests @@ -54,6 +55,7 @@ public ClientSideOperationTimeoutTest(final String fileDescription, final String super(schemaVersion, runOnRequirements, entities, initialData, definition); this.testDescription = testDescription; // Time sensitive - cannot just create a cursor with publishers + skipOperationTimeoutTests(fileDescription, testDescription); assumeFalse("No iterateOnce support. There is alternative prose test for it.", testDescription.equals("timeoutMS is refreshed for getMore if maxAwaitTimeMS is not set")); @@ -74,14 +76,10 @@ The Reactive Streams specification prevents us from allowing a subsequent next c assumeFalse(testDescription.endsWith("createChangeStream on client")); assumeFalse(testDescription.endsWith("createChangeStream on database")); assumeFalse(testDescription.endsWith("createChangeStream on collection")); - assumeFalse("TODO (CSOT) - JAVA-5104", fileDescription.equals("timeoutMS behaves correctly during command execution") - && testDescription.equals("command is not sent if RTT is greater than timeoutMS")); // No withTransaction support assumeFalse(fileDescription.contains("withTransaction") || testDescription.contains("withTransaction")); - checkSkipCSOTTest(fileDescription, testDescription); - if (testDescription.equals("timeoutMS is refreshed for close")) { enableSleepAfterCursorError(256); } @@ -128,6 +126,14 @@ public void cleanUp() { Hooks.resetOnErrorDropped(); } + public static boolean racyTestAssertion(final String testDescription, final AssertionError e) { + return RACY_GET_MORE_TESTS.contains(testDescription) && e.getMessage().startsWith("Number of events must be the same"); + } + + private static final List RACY_GET_MORE_TESTS = asList( + "remaining timeoutMS applied to getMore if timeoutMode is cursor_lifetime", + "remaining timeoutMS applied to getMore if timeoutMode is unset"); + private void assertNoDroppedError(final String message) { Throwable droppedError = atomicReferenceThrowable.get(); if (droppedError != null) { diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index c2bc6c59411..8ccad14d158 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -746,6 +746,56 @@ public void shouldIgnoreWtimeoutMsOfWriteConcernToInitialAndSubsequentCommitTran }}); } + /** + * Not a prose spec test. However, it is additional test case for better coverage. + */ + @Tag("setsFailPoint") + @Test + @DisplayName("Should refresh timeout for commit transaction") + public void shouldRefreshTimeoutForCommitTransaction() { + assumeTrue(serverVersionAtLeast(4, 4)); + assumeFalse(isStandalone()); + + collectionHelper.runAdminCommand("{" + + " configureFailPoint: \"failCommand\"," + + " mode: { times: 1 }," + + " data: {" + + " failCommands: [\"abortTransaction\"]," + + " blockConnection: true," + + " blockTimeMS: " + 600 + + " }" + + "}"); + + try (MongoClient mongoClient = createMongoClient(getMongoClientSettingsBuilder())) { + MongoCollection collection = mongoClient.getDatabase(namespace.getDatabaseName()) + .getCollection(namespace.getCollectionName()); + + try (ClientSession session = mongoClient.startSession(ClientSessionOptions.builder() + .defaultTimeout(200, TimeUnit.MILLISECONDS) + .build())) { + session.startTransaction(TransactionOptions.builder() + .writeConcern(WriteConcern.ACKNOWLEDGED.withWTimeout(100, TimeUnit.MILLISECONDS)) + .build()); + collection.insertOne(session, new Document("x", 1)); + sleep(200); + + assertDoesNotThrow(session::commitTransaction); + //repeat commit. + assertDoesNotThrow(session::commitTransaction); + } + } + List commandStartedEvents = commandListener.getCommandStartedEvents("commitTransaction"); + assertEquals(2, commandStartedEvents.size()); + + commandStartedEvents.forEach(e -> { + BsonDocument command = e.getCommand(); + if (command.containsKey("writeConcern")) { + BsonDocument writeConcern = command.getDocument("writeConcern"); + assertFalse(writeConcern.isEmpty()); + assertFalse(writeConcern.containsKey("wTimeoutMS")); + }}); + } + private static Stream test8ServerSelectionArguments() { return Stream.of( Arguments.of(Named.of("serverSelectionTimeoutMS honored if timeoutMS is not set", diff --git a/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java b/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java index 77caabfdbbb..3ed61ea082a 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java @@ -27,24 +27,18 @@ import java.io.IOException; import java.net.URISyntaxException; import java.util.Collection; -import java.util.List; -import static java.util.Arrays.asList; import static org.junit.Assume.assumeFalse; // See https://github.com/mongodb/specifications/tree/master/source/client-side-operation-timeout/tests @RunWith(Parameterized.class) public class ClientSideOperationTimeoutTest extends UnifiedSyncTest { - private final String testDescription; + public ClientSideOperationTimeoutTest(final String fileDescription, final String testDescription, final String schemaVersion, @Nullable final BsonArray runOnRequirements, final BsonArray entities, final BsonArray initialData, final BsonDocument definition) { super(schemaVersion, runOnRequirements, entities, initialData, definition); - this.testDescription = testDescription; - checkSkipCSOTTest(fileDescription, testDescription); - - assumeFalse("TODO (CSOT) - JAVA-5104", fileDescription.equals("timeoutMS behaves correctly for non-tailable cursors") - && testDescription.equals("timeoutMS applied to find if timeoutMode is iteration")); + skipOperationTimeoutTests(fileDescription, testDescription); } @Parameterized.Parameters(name = "{0}: {1}") @@ -55,48 +49,20 @@ public static Collection data() throws URISyntaxException, IOException @Test @Override public void shouldPassAllOutcomes() { - try { - super.shouldPassAllOutcomes(); - } catch (AssertionError e) { - if (racyTestAssertion(testDescription, e)) { - // Ignore failure - racy test often no time to do the getMore - return; - } - throw e; - } + super.shouldPassAllOutcomes(); } - public static boolean racyTestAssertion(final String testDescription, final AssertionError e) { - return RACY_GET_MORE_TESTS.contains(testDescription) && e.getMessage().startsWith("Number of events must be the same"); - } - - public static void checkSkipCSOTTest(final String fileDescription, final String testDescription) { + public static void skipOperationTimeoutTests(final String fileDescription, final String testDescription) { assumeFalse("No maxTimeMS parameter for createIndex() method", testDescription.contains("maxTimeMS is ignored if timeoutMS is set - createIndex on collection")); - assumeFalse("TODO (CSOT) CRUD Failure", - testDescription.contains("socketTimeoutMS is ignored if timeoutMS is set - deleteMany on collection")); - assumeFalse("No run cursor command", fileDescription.startsWith("runCursorCommand")); assumeFalse("No special handling of runCommand", testDescription.contains("runCommand on database")); - assumeFalse("No count command helper", testDescription.endsWith("count on collection")); - assumeFalse("No operation based overrides", fileDescription.equals("timeoutMS can be overridden for an operation")); assumeFalse("No operation session based overrides", - fileDescription.equals("timeoutMS can be overridden for individual session operations")); - assumeFalse("No operation session based overrides", - fileDescription.equals("operations ignore deprected timeout options if timeoutMS is set") - && (testDescription.equals("abortTransaction ignores socketTimeoutMS if timeoutMS is set") - || testDescription.equals("commitTransaction ignores socketTimeoutMS if timeoutMS is set") - || testDescription.equals("commitTransaction ignores maxCommitTimeMS if timeoutMS is set") - )); + testDescription.equals("timeoutMS can be overridden for commitTransaction") + || testDescription.equals("timeoutMS applied to abortTransaction")); assumeFalse("No operation based overrides", fileDescription.equals("timeoutMS behaves correctly when closing cursors") && testDescription.equals("timeoutMS can be overridden for close")); - - assumeFalse("TODO (CSOT) - JAVA-5259 No client.withTimeout", testDescription.endsWith("on client")); } - - private static final List RACY_GET_MORE_TESTS = asList( - "remaining timeoutMS applied to getMore if timeoutMode is cursor_lifetime", - "remaining timeoutMS applied to getMore if timeoutMode is unset"); } From 250a85ad1c5fc6fb4f74af60fe08657015106dfa Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Mon, 6 May 2024 17:33:07 -0700 Subject: [PATCH 02/14] Add additional assertions. Rename tests for better clarity. JAVA-5104 --- .../ClientSideOperationTimeoutProseTest.java | 4 +++- ...stractClientSideOperationsTimeoutProseTest.java | 14 +++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java index 8dc6716080e..f894ed6312c 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java @@ -420,7 +420,8 @@ public void testTimeoutMsRefreshedForGetMoreWhenMaxAwaitTimeMsSet() { .timeout(rtt + 300, TimeUnit.MILLISECONDS))) { MongoCollection collection = client.getDatabase(namespace.getDatabaseName()) - .getCollection(namespace.getCollectionName()).withReadPreference(ReadPreference.primary()); + .getCollection(namespace.getCollectionName()) + .withReadPreference(ReadPreference.primary()); collectionHelper.runAdminCommand("{" + " configureFailPoint: \"failCommand\"," @@ -449,6 +450,7 @@ public void testTimeoutMsRefreshedForGetMoreWhenMaxAwaitTimeMsSet() { .expectNextCount(2) .thenAwait(Duration.ofMillis(600)) .thenRequest(2) + .expectNextCount(2) .thenCancel() .verify(); diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index 8ccad14d158..11aae966f65 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -86,6 +86,7 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -468,7 +469,7 @@ public void test8ServerSelectionHandshake(final String ignoredTestName, final in @Tag("setsFailPoint") @SuppressWarnings("try") - @DisplayName("9. End Session 1 / 2") + @DisplayName("9. End Session. The timeout specified via the MongoClient timeoutMS option") @Test public void test9EndSessionClientTimeout() { assumeTrue(serverVersionAtLeast(4, 4)); @@ -498,12 +499,14 @@ public void test9EndSessionClientTimeout() { assertTrue(elapsed <= 150, "Took too long to time out, elapsedMS: " + elapsed); } } - assertDoesNotThrow(() -> commandListener.getCommandFailedEvent("abortTransaction")); + CommandFailedEvent abortTransactionEvent = assertDoesNotThrow(() -> + commandListener.getCommandFailedEvent("abortTransaction")); + assertInstanceOf(MongoOperationTimeoutException.class, abortTransactionEvent.getThrowable()); } @Tag("setsFailPoint") @SuppressWarnings("try") - @DisplayName("9. End Session 2 / 2") + @DisplayName("9. End Session. The timeout specified via the ClientSession defaultTimeoutMS option") @Test public void test9EndSessionSessionTimeout() { assumeTrue(serverVersionAtLeast(4, 4)); @@ -533,8 +536,9 @@ public void test9EndSessionSessionTimeout() { assertTrue(elapsed <= 150, "Took too long to time out, elapsedMS: " + elapsed); } } - - assertDoesNotThrow(() -> commandListener.getCommandFailedEvent("abortTransaction")); + CommandFailedEvent abortTransactionEvent = assertDoesNotThrow(() -> + commandListener.getCommandFailedEvent("abortTransaction")); + assertInstanceOf(MongoOperationTimeoutException.class, abortTransactionEvent.getThrowable()); } @Tag("setsFailPoint") From 6676260327de12f782ee270db1d03a34a37e122a Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Mon, 6 May 2024 19:56:19 -0700 Subject: [PATCH 03/14] Add ignoreExtraEvents override to avoid flakiness in racy tests. JAVA-5104 --- .../unified/ClientSideOperationTimeoutTest.java | 6 ++++++ .../com/mongodb/client/unified/UnifiedTest.java | 17 +++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java index 7ac88243437..1e112fad91f 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java @@ -84,6 +84,12 @@ The Reactive Streams specification prevents us from allowing a subsequent next c enableSleepAfterCursorError(256); } + /* + * The test is occasionally racy. The "killCursors" command may appear as an additional event. This is unexpected in unified tests, + * but anticipated in reactive streams because an operation timeout error triggers the closure of the stream/publisher. + */ + ignoreExtraCommandEvents(testDescription.contains("timeoutMS is refreshed for getMore - failure")); + Hooks.onOperatorDebug(); Hooks.onErrorDropped(atomicReferenceThrowable::set); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java index 76bc928f507..590b36274b2 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java @@ -21,9 +21,6 @@ import com.mongodb.MongoNamespace; import com.mongodb.ReadPreference; import com.mongodb.UnixServerAddress; -import com.mongodb.event.TestServerMonitorListener; -import com.mongodb.internal.logging.LogMessage; -import com.mongodb.logging.TestLoggingInterceptor; import com.mongodb.WriteConcern; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoClient; @@ -37,10 +34,13 @@ import com.mongodb.connection.ServerDescription; import com.mongodb.event.CommandEvent; import com.mongodb.event.CommandStartedEvent; +import com.mongodb.event.TestServerMonitorListener; import com.mongodb.internal.connection.TestCommandListener; import com.mongodb.internal.connection.TestConnectionPoolListener; +import com.mongodb.internal.logging.LogMessage; import com.mongodb.lang.NonNull; import com.mongodb.lang.Nullable; +import com.mongodb.logging.TestLoggingInterceptor; import org.bson.BsonArray; import org.bson.BsonBoolean; import org.bson.BsonDocument; @@ -110,6 +110,7 @@ public abstract class UnifiedTest { private final List failPoints = new ArrayList<>(); private final UnifiedTestContext rootContext = new UnifiedTestContext(); private BsonDocument startingClusterTime; + private boolean ignoreExtraCommandEventsOverride = false; private class UnifiedTestContext { private final AssertionContext context = new AssertionContext(); @@ -258,7 +259,7 @@ public void shouldPassAllOutcomes() { } if (definition.containsKey("expectEvents")) { - compareEvents(rootContext, definition); + compareEvents(rootContext, definition, ignoreExtraCommandEventsOverride); } if (definition.containsKey("expectLogMessages")) { @@ -273,11 +274,11 @@ public void shouldPassAllOutcomes() { } } - private void compareEvents(final UnifiedTestContext context, final BsonDocument definition) { + private void compareEvents(final UnifiedTestContext context, final BsonDocument definition, final boolean ignoreExtraEventsOverride) { for (BsonValue cur : definition.getArray("expectEvents")) { BsonDocument curClientEvents = cur.asDocument(); String client = curClientEvents.getString("client").getValue(); - boolean ignoreExtraEvents = curClientEvents.getBoolean("ignoreExtraEvents", BsonBoolean.FALSE).getValue(); + boolean ignoreExtraEvents = curClientEvents.getBoolean("ignoreExtraEvents", BsonBoolean.FALSE).getValue() || ignoreExtraEventsOverride; String eventType = curClientEvents.getString("eventType", new BsonString("command")).getValue(); BsonArray expectedEvents = curClientEvents.getArray("events"); if (eventType.equals("command")) { @@ -972,4 +973,8 @@ private BsonDocument addInitialDataAndGetClusterTime() { } return getCurrentClusterTime(); } + + protected void ignoreExtraCommandEvents(final boolean ignoreExtraCommandEventsOverride) { + this.ignoreExtraCommandEventsOverride = ignoreExtraCommandEventsOverride; + } } From ce83e5838060318ded608247560f5184959a4fc3 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Tue, 7 May 2024 15:54:45 -0700 Subject: [PATCH 04/14] Start using JUnit extension to disable failpoint instead of Tags. Use unified terminiogy for timeout messages. JAVA-5104 --- .../com/mongodb/internal/TimeoutContext.java | 6 ++-- .../internal/async/function/RetryState.java | 2 +- .../internal/connection/SocketStream.java | 2 +- .../connection/netty/NettyStream.java | 14 +++++--- .../gridfs/GridFSUploadPublisherImpl.java | 2 +- .../ClientSideOperationTimeoutProseTest.java | 11 ++---- .../ClientSideOperationTimeoutTest.java | 1 - .../client/gridfs/GridFSBucketImpl.java | 2 +- .../gridfs/GridFSDownloadStreamImpl.java | 2 +- .../client/gridfs/GridFSUploadStreamImpl.java | 2 +- .../client/internal/KeyManagementService.java | 2 +- ...tClientSideOperationsTimeoutProseTest.java | 33 +++++------------ .../client/FailPointTestExtension.java | 35 +++++++++++++++++++ ...eOperationsEncryptionTimeoutProseTest.java | 21 ++++++----- 14 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 driver-sync/src/test/functional/com/mongodb/client/FailPointTestExtension.java diff --git a/driver-core/src/main/com/mongodb/internal/TimeoutContext.java b/driver-core/src/main/com/mongodb/internal/TimeoutContext.java index 6a67ee52859..937e8c83b20 100644 --- a/driver-core/src/main/com/mongodb/internal/TimeoutContext.java +++ b/driver-core/src/main/com/mongodb/internal/TimeoutContext.java @@ -65,7 +65,7 @@ public static T throwMongoTimeoutException(final String message) { } public static MongoOperationTimeoutException createMongoTimeoutException(final Throwable cause) { - return createMongoTimeoutException("Operation timed out: " + cause.getMessage(), cause); + return createMongoTimeoutException("Operation exceeded the timeout limit: " + cause.getMessage(), cause); } public static MongoOperationTimeoutException createMongoTimeoutException(final String message, final Throwable cause) { @@ -173,7 +173,7 @@ public long timeoutOrAlternative(final long alternativeTimeoutMS) { return timeout.call(MILLISECONDS, () -> 0L, (ms) -> ms, - () -> throwMongoTimeoutException("The operation timeout has expired.")); + () -> throwMongoTimeoutException("The operation exceeded the timeout limit.")); } } @@ -252,7 +252,7 @@ public int getConnectTimeoutMs() { return Math.toIntExact(Timeout.nullAsInfinite(timeout).call(MILLISECONDS, () -> connectTimeoutMS, (ms) -> connectTimeoutMS == 0 ? ms : Math.min(ms, connectTimeoutMS), - () -> throwMongoTimeoutException("The operation timeout has expired."))); + () -> throwMongoTimeoutException("The operation exceeded the timeout limit."))); } public void resetTimeout() { diff --git a/driver-core/src/main/com/mongodb/internal/async/function/RetryState.java b/driver-core/src/main/com/mongodb/internal/async/function/RetryState.java index 3f8707a237f..2144e269ba4 100644 --- a/driver-core/src/main/com/mongodb/internal/async/function/RetryState.java +++ b/driver-core/src/main/com/mongodb/internal/async/function/RetryState.java @@ -207,7 +207,7 @@ private void doAdvanceOrThrow(final Throwable attemptException, */ if (hasTimeoutMs() && !loopState.isLastIteration()) { previouslyChosenException = createMongoTimeoutException( - "Retry attempt timed out.", + "Retry attempt exceeded the timeout limit.", previouslyChosenException); } throw previouslyChosenException; diff --git a/driver-core/src/main/com/mongodb/internal/connection/SocketStream.java b/driver-core/src/main/com/mongodb/internal/connection/SocketStream.java index 8f11c610a06..e0a0dd6aa15 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/SocketStream.java +++ b/driver-core/src/main/com/mongodb/internal/connection/SocketStream.java @@ -164,7 +164,7 @@ public void write(final List buffers, final OperationContext operationC for (final ByteBuf cur : buffers) { outputStream.write(cur.array(), 0, cur.limit()); if (operationContext.getTimeoutContext().hasExpired()) { - throwMongoTimeoutException("Timeout occurred during socket write."); + throwMongoTimeoutException("Socket write exceeded the timeout limit."); } } } diff --git a/driver-core/src/main/com/mongodb/internal/connection/netty/NettyStream.java b/driver-core/src/main/com/mongodb/internal/connection/netty/NettyStream.java index 04989451596..b28054e7d3d 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/netty/NettyStream.java +++ b/driver-core/src/main/com/mongodb/internal/connection/netty/NettyStream.java @@ -253,10 +253,7 @@ public void writeAsync(final List buffers, final OperationContext opera } long writeTimeoutMS = operationContext.getTimeoutContext().getWriteTimeoutMS(); - Optional writeTimeoutHandler = writeTimeoutMS != NO_SCHEDULE_TIME - ? Optional.of(new WriteTimeoutHandler(writeTimeoutMS, MILLISECONDS)) : Optional.empty(); - writeTimeoutHandler.map(w -> channel.pipeline().addBefore("ChannelInboundHandlerAdapter", "WriteTimeoutHandler", w)); - + final Optional writeTimeoutHandler = addWriteTimeoutHandler(writeTimeoutMS); channel.writeAndFlush(composite).addListener((ChannelFutureListener) future -> { writeTimeoutHandler.map(w -> channel.pipeline().remove(w)); if (!future.isSuccess()) { @@ -267,6 +264,15 @@ public void writeAsync(final List buffers, final OperationContext opera }); } + private Optional addWriteTimeoutHandler(final long writeTimeoutMS) { + if (writeTimeoutMS != NO_SCHEDULE_TIME) { + WriteTimeoutHandler writeTimeoutHandler = new WriteTimeoutHandler(writeTimeoutMS, MILLISECONDS); + channel.pipeline().addBefore("ChannelInboundHandlerAdapter", "WriteTimeoutHandler", writeTimeoutHandler); + return Optional.of(writeTimeoutHandler); + } + return Optional.empty(); + } + @Override public void readAsync(final int numBytes, final OperationContext operationContext, final AsyncCompletionHandler handler) { readAsync(numBytes, handler, operationContext.getTimeoutContext().getReadTimeoutMS()); diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/gridfs/GridFSUploadPublisherImpl.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/gridfs/GridFSUploadPublisherImpl.java index c44a55ee2e4..a45d369c676 100644 --- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/gridfs/GridFSUploadPublisherImpl.java +++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/gridfs/GridFSUploadPublisherImpl.java @@ -279,7 +279,7 @@ private static Mono createMonoTimer(final @Nulla private static Mono createTimeoutMonoError() { return Mono.error(TimeoutContext.createMongoTimeoutException( - "GridFS timed out waiting for data from provided source Publisher")); + "GridFS waiting for data from the source Publisher exceeded the timeout limit.")); } private Mono createSaveFileDataMono(final AtomicBoolean terminated, diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java index f894ed6312c..e70354af449 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java @@ -107,7 +107,6 @@ protected boolean isAsync() { return true; } - @Tag("setsFailPoint") @DisplayName("6. GridFS Upload - uploads via openUploadStream can be timed out") @Test @Override @@ -117,7 +116,7 @@ public void testGridFSUploadViaOpenUploadStreamTimeout() { //given collectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: { times: 1 }," + " data: {" + " failCommands: [\"insert\"]," @@ -164,7 +163,6 @@ public void testGridFSUploadViaOpenUploadStreamTimeout() { } } - @Tag("setsFailPoint") @DisplayName("6. GridFS Upload - Aborting an upload stream can be timed out") @Test @Override @@ -177,7 +175,7 @@ public void testAbortingGridFsUploadStreamTimeout() throws ExecutionException, I Hooks.onErrorDropped(droppedErrorFuture::complete); collectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: { times: 1 }," + " data: {" + " failCommands: [\"delete\"]," @@ -227,7 +225,6 @@ public void testAbortingGridFsUploadStreamTimeout() throws ExecutionException, I /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Tag("setsFailPoint") @DisplayName("TimeoutMS applies to full resume attempt in a next call") @Test public void testTimeoutMSAppliesToFullResumeAttemptInNextCall() { @@ -283,7 +280,6 @@ public void testTimeoutMSAppliesToFullResumeAttemptInNextCall() { /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Tag("setsFailPoint") @DisplayName("TimeoutMS applied to initial aggregate") @Test public void testTimeoutMSAppliedToInitialAggregate() { @@ -332,7 +328,6 @@ public void testTimeoutMSAppliedToInitialAggregate() { /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Tag("setsFailPoint") @DisplayName("TimeoutMS is refreshed for getMore if maxAwaitTimeMS is not set") @Test public void testTimeoutMsRefreshedForGetMoreWhenMaxAwaitTimeMsNotSet() { @@ -402,7 +397,6 @@ public void testTimeoutMsRefreshedForGetMoreWhenMaxAwaitTimeMsNotSet() { /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Tag("setsFailPoint") @DisplayName("TimeoutMS is refreshed for getMore if maxAwaitTimeMS is set") @Test public void testTimeoutMsRefreshedForGetMoreWhenMaxAwaitTimeMsSet() { @@ -465,7 +459,6 @@ public void testTimeoutMsRefreshedForGetMoreWhenMaxAwaitTimeMsSet() { /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Tag("setsFailPoint") @DisplayName("TimeoutMS is honored for next operation when several getMore executed internally") @Test public void testTimeoutMsISHonoredForNnextOperationWhenSeveralGetMoreExecutedInternally() { diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java index 1e112fad91f..4c9a1dbb7c6 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/unified/ClientSideOperationTimeoutTest.java @@ -54,7 +54,6 @@ public ClientSideOperationTimeoutTest(final String fileDescription, final String final BsonArray initialData, final BsonDocument definition) { super(schemaVersion, runOnRequirements, entities, initialData, definition); this.testDescription = testDescription; - // Time sensitive - cannot just create a cursor with publishers skipOperationTimeoutTests(fileDescription, testDescription); assumeFalse("No iterateOnce support. There is alternative prose test for it.", diff --git a/driver-sync/src/main/com/mongodb/client/gridfs/GridFSBucketImpl.java b/driver-sync/src/main/com/mongodb/client/gridfs/GridFSBucketImpl.java index c2ff6fb8c35..731e9c55846 100644 --- a/driver-sync/src/main/com/mongodb/client/gridfs/GridFSBucketImpl.java +++ b/driver-sync/src/main/com/mongodb/client/gridfs/GridFSBucketImpl.java @@ -62,7 +62,7 @@ final class GridFSBucketImpl implements GridFSBucket { private static final int DEFAULT_CHUNKSIZE_BYTES = 255 * 1024; - private static final String TIMEOUT_MESSAGE = "GridFS operation timed out"; + private static final String TIMEOUT_MESSAGE = "GridFS operation exceeded the timeout limit."; private final String bucketName; private final int chunkSizeBytes; private final MongoCollection filesCollection; diff --git a/driver-sync/src/main/com/mongodb/client/gridfs/GridFSDownloadStreamImpl.java b/driver-sync/src/main/com/mongodb/client/gridfs/GridFSDownloadStreamImpl.java index 460241edd2d..16f50baf7dd 100644 --- a/driver-sync/src/main/com/mongodb/client/gridfs/GridFSDownloadStreamImpl.java +++ b/driver-sync/src/main/com/mongodb/client/gridfs/GridFSDownloadStreamImpl.java @@ -39,7 +39,7 @@ import static java.lang.String.format; class GridFSDownloadStreamImpl extends GridFSDownloadStream { - private static final String TIMEOUT_MESSAGE = "The GridFS download stream has timed out"; + private static final String TIMEOUT_MESSAGE = "The GridFS download stream exceeded the timeout limit."; private final ClientSession clientSession; private final GridFSFile fileInfo; private final MongoCollection chunksCollection; diff --git a/driver-sync/src/main/com/mongodb/client/gridfs/GridFSUploadStreamImpl.java b/driver-sync/src/main/com/mongodb/client/gridfs/GridFSUploadStreamImpl.java index ec8e2a69f16..74a3046fbba 100644 --- a/driver-sync/src/main/com/mongodb/client/gridfs/GridFSUploadStreamImpl.java +++ b/driver-sync/src/main/com/mongodb/client/gridfs/GridFSUploadStreamImpl.java @@ -36,7 +36,7 @@ import static com.mongodb.internal.Locks.withInterruptibleLock; final class GridFSUploadStreamImpl extends GridFSUploadStream { - public static final String TIMEOUT_MESSAGE = "The GridFS upload stream has timed out"; + public static final String TIMEOUT_MESSAGE = "The GridFS upload stream exceeded the timeout limit."; private final ClientSession clientSession; private final MongoCollection filesCollection; private final MongoCollection chunksCollection; diff --git a/driver-sync/src/main/com/mongodb/client/internal/KeyManagementService.java b/driver-sync/src/main/com/mongodb/client/internal/KeyManagementService.java index 16f6df10f21..fee5ddac729 100644 --- a/driver-sync/src/main/com/mongodb/client/internal/KeyManagementService.java +++ b/driver-sync/src/main/com/mongodb/client/internal/KeyManagementService.java @@ -139,7 +139,7 @@ private void setSocketSoTimeoutToOperationTimeout() throws SocketException { throw new AssertionError("operationTimeout cannot be infinite"); }, (ms) -> socket.setSoTimeout(Math.toIntExact(ms)), - () -> TimeoutContext.throwMongoTimeoutException("Timeout has expired while reading from KMS server")); + () -> TimeoutContext.throwMongoTimeoutException("Reading from KMS server exceeded the timeout limit.")); } @Override diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index 11aae966f65..b4cc03f5e71 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -58,9 +58,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Named; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -101,6 +101,10 @@ @SuppressWarnings("checkstyle:VisibilityModifier") public abstract class AbstractClientSideOperationsTimeoutProseTest { + protected static final String FAIL_COMMAND_NAME = "failCommand"; + @RegisterExtension + protected static final FailPointTestExtension FAILPOINT_TEST_EXTENSION = new FailPointTestExtension(FAIL_COMMAND_NAME); + protected static final String GRID_FS_BUCKET_NAME = "db.fs"; private static final AtomicInteger COUNTER = new AtomicInteger(); @@ -124,7 +128,6 @@ protected int postSessionCloseSleep() { return 0; } - @Tag("setsFailPoint") @SuppressWarnings("try") @FlakyTest(maxAttempts = 3) @DisplayName("4. Background Connection Pooling - timeoutMS used for handshake commands") @@ -134,7 +137,7 @@ public void testBackgroundConnectionPoolingTimeoutMSUsedForHandshakeCommands() { assumeFalse(isServerlessTest()); collectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: {" + " times: 1" + " }," @@ -162,7 +165,6 @@ public void testBackgroundConnectionPoolingTimeoutMSUsedForHandshakeCommands() { } } - @Tag("setsFailPoint") @SuppressWarnings("try") @FlakyTest(maxAttempts = 3) @DisplayName("4. Background Connection Pooling - timeoutMS is refreshed for each handshake command") @@ -172,7 +174,7 @@ public void testBackgroundConnectionPoolingTimeoutMSIsRefreshedForEachHandshakeC assumeFalse(isServerlessTest()); collectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: \"alwaysOn\"," + " data: {" + " failCommands: [\"hello\", \"isMaster\", \"saslContinue\"]," @@ -198,7 +200,6 @@ public void testBackgroundConnectionPoolingTimeoutMSIsRefreshedForEachHandshakeC } } - @Tag("setsFailPoint") @FlakyTest(maxAttempts = 3) @DisplayName("5. Blocking Iteration Methods - Tailable cursors") public void testBlockingIterationMethodsTailableCursor() { @@ -236,7 +237,6 @@ public void testBlockingIterationMethodsTailableCursor() { } } - @Tag("setsFailPoint") @FlakyTest(maxAttempts = 3) @DisplayName("5. Blocking Iteration Methods - Change Streams") public void testBlockingIterationMethodsChangeStream() { @@ -284,8 +284,6 @@ public void testBlockingIterationMethodsChangeStream() { } } - - @Tag("setsFailPoint") @DisplayName("6. GridFS Upload - uploads via openUploadStream can be timed out") @Test public void testGridFSUploadViaOpenUploadStreamTimeout() { @@ -317,7 +315,6 @@ public void testGridFSUploadViaOpenUploadStreamTimeout() { } } - @Tag("setsFailPoint") @DisplayName("6. GridFS Upload - Aborting an upload stream can be timed out") @Test public void testAbortingGridFsUploadStreamTimeout() throws Throwable { @@ -349,7 +346,6 @@ public void testAbortingGridFsUploadStreamTimeout() throws Throwable { } } - @Tag("setsFailPoint") @DisplayName("6. GridFS Download") @Test public void testGridFsDownloadStreamTimeout() { @@ -426,7 +422,6 @@ public void test8ServerSelection(final String connectionString) { } } - @Tag("setsFailPoint") @DisplayName("8. Server Selection 2 / 2") @ParameterizedTest(name = "[{index}] {0}") @MethodSource("test8ServerSelectionHandshakeArguments") @@ -467,7 +462,6 @@ public void test8ServerSelectionHandshake(final String ignoredTestName, final in } } - @Tag("setsFailPoint") @SuppressWarnings("try") @DisplayName("9. End Session. The timeout specified via the MongoClient timeoutMS option") @Test @@ -504,7 +498,6 @@ public void test9EndSessionClientTimeout() { assertInstanceOf(MongoOperationTimeoutException.class, abortTransactionEvent.getThrowable()); } - @Tag("setsFailPoint") @SuppressWarnings("try") @DisplayName("9. End Session. The timeout specified via the ClientSession defaultTimeoutMS option") @Test @@ -541,7 +534,6 @@ public void test9EndSessionSessionTimeout() { assertInstanceOf(MongoOperationTimeoutException.class, abortTransactionEvent.getThrowable()); } - @Tag("setsFailPoint") @DisplayName("9. End Session - Custom Test: Each operation has its own timeout with commit") @Test public void test9EndSessionCustomTesEachOperationHasItsOwnTimeoutWithCommit() { @@ -573,7 +565,6 @@ public void test9EndSessionCustomTesEachOperationHasItsOwnTimeoutWithCommit() { assertDoesNotThrow(() -> commandListener.getCommandSucceededEvent("commitTransaction")); } - @Tag("setsFailPoint") @DisplayName("9. End Session - Custom Test: Each operation has its own timeout with abort") @Test public void test9EndSessionCustomTesEachOperationHasItsOwnTimeoutWithAbort() { @@ -605,7 +596,6 @@ public void test9EndSessionCustomTesEachOperationHasItsOwnTimeoutWithAbort() { assertDoesNotThrow(() -> commandListener.getCommandSucceededEvent("abortTransaction")); } - @Tag("setsFailPoint") @DisplayName("10. Convenient Transactions") @Test public void test10ConvenientTransactions() { @@ -640,7 +630,6 @@ public void test10ConvenientTransactions() { } } - @Tag("setsFailPoint") @DisplayName("10. Convenient Transactions - Custom Test: with transaction uses a single timeout") @Test public void test10CustomTestWithTransactionUsesASingleTimeout() { @@ -674,7 +663,6 @@ public void test10CustomTestWithTransactionUsesASingleTimeout() { } } - @Tag("setsFailPoint") @DisplayName("10. Convenient Transactions - Custom Test: with transaction uses a single timeout - lock") @Test public void test10CustomTestWithTransactionUsesASingleTimeoutWithLock() { @@ -713,7 +701,7 @@ public void test10CustomTestWithTransactionUsesASingleTimeoutWithLock() { /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Tag("setsFailPoint") + @Test @DisplayName("Should ignore wTimeoutMS of WriteConcern to initial and subsequent commitTransaction operations") public void shouldIgnoreWtimeoutMsOfWriteConcernToInitialAndSubsequentCommitTransactionOperations() { @@ -753,7 +741,7 @@ public void shouldIgnoreWtimeoutMsOfWriteConcernToInitialAndSubsequentCommitTran /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Tag("setsFailPoint") + @Test @DisplayName("Should refresh timeout for commit transaction") public void shouldRefreshTimeoutForCommitTransaction() { @@ -850,9 +838,6 @@ public void setUp() { @AfterEach public void tearDown(final TestInfo info) { if (collectionHelper != null) { - if (info.getTags().contains("setsFailPoint") && serverVersionAtLeast(4, 4)) { - collectionHelper.runAdminCommand("{configureFailPoint: \"failCommand\", mode: \"off\"}"); - } collectionHelper.drop(); filesCollectionHelper.drop(); chunksCollectionHelper.drop(); diff --git a/driver-sync/src/test/functional/com/mongodb/client/FailPointTestExtension.java b/driver-sync/src/test/functional/com/mongodb/client/FailPointTestExtension.java new file mode 100644 index 00000000000..05a9444c8a9 --- /dev/null +++ b/driver-sync/src/test/functional/com/mongodb/client/FailPointTestExtension.java @@ -0,0 +1,35 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mongodb.client; + +import com.mongodb.ClusterFixture; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +public class FailPointTestExtension implements AfterEachCallback { + + private final String failPointName; + + public FailPointTestExtension(final String failPointName) { + this.failPointName = failPointName; + } + + @Override + public void afterEach(ExtensionContext context) { + ClusterFixture.disableFailPoint(failPointName); + } +} \ No newline at end of file diff --git a/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java index 636fd302824..49186dfa32b 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java @@ -26,6 +26,7 @@ import com.mongodb.ReadConcern; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; +import com.mongodb.client.FailPointTestExtension; import com.mongodb.client.Fixture; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; @@ -46,9 +47,9 @@ import org.bson.codecs.BsonDocumentCodec; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -76,6 +77,9 @@ */ public abstract class AbstractClientSideOperationsEncryptionTimeoutProseTest { + protected static final String FAIL_COMMAND_NAME = "failCommand"; + @RegisterExtension + protected static final FailPointTestExtension FAILPOINT_TEST_EXTENSION = new FailPointTestExtension(FAIL_COMMAND_NAME); private static final Map> KMS_PROVIDERS = new HashMap<>(); private final MongoNamespace keyVaultNamespace = new MongoNamespace("keyvault", "datakeys"); @@ -92,7 +96,6 @@ public abstract class AbstractClientSideOperationsEncryptionTimeoutProseTest { protected abstract MongoClient createMongoClient(MongoClientSettings.Builder builder); @Test - @Tag("setsFailPoint") void shouldThrowOperationTimeoutExceptionWhenCreateDataKey() { assumeTrue(serverVersionAtLeast(4, 4)); long rtt = ClusterFixture.getPrimaryRTT(); @@ -105,7 +108,7 @@ void shouldThrowOperationTimeoutExceptionWhenCreateDataKey() { try (ClientEncryption clientEncryption = createClientEncryption(getClientEncryptionSettingsBuilder(rtt + 100))) { keyVaultCollectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: { times: 1 }," + " data: {" + " failCommands: [\"insert\"]," @@ -126,7 +129,6 @@ void shouldThrowOperationTimeoutExceptionWhenCreateDataKey() { } @Test - @Tag("setsFailPoint") void shouldThrowOperationTimeoutExceptionWhenEncryptData() { assumeTrue(serverVersionAtLeast(4, 4)); long rtt = ClusterFixture.getPrimaryRTT(); @@ -136,7 +138,7 @@ void shouldThrowOperationTimeoutExceptionWhenEncryptData() { clientEncryption.createDataKey("local"); keyVaultCollectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: { times: 1 }," + " data: {" + " failCommands: [\"find\"]," @@ -161,7 +163,6 @@ void shouldThrowOperationTimeoutExceptionWhenEncryptData() { } @Test - @Tag("setsFailPoint") void shouldThrowOperationTimeoutExceptionWhenDecryptData() { assumeTrue(serverVersionAtLeast(4, 4)); long rtt = ClusterFixture.getPrimaryRTT(); @@ -177,7 +178,7 @@ void shouldThrowOperationTimeoutExceptionWhenDecryptData() { try (ClientEncryption clientEncryption = createClientEncryption(getClientEncryptionSettingsBuilder(rtt + 100))) { keyVaultCollectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: { times: 1 }," + " data: {" + " failCommands: [\"find\"]," @@ -199,14 +200,13 @@ void shouldThrowOperationTimeoutExceptionWhenDecryptData() { * Not a prose spec test. However, it is additional test case for better coverage. */ @Test - @Tag("setsFailPoint") void shouldDecreaseOperationTimeoutForSubsequentOperations() { assumeTrue(serverVersionAtLeast(4, 4)); long rtt = ClusterFixture.getPrimaryRTT(); long initialTimeoutMS = rtt + 2500; keyVaultCollectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: \"alwaysOn\"," + " data: {" + " failCommands: [\"insert\", \"find\", \"listCollections\"]," @@ -274,7 +274,6 @@ void shouldDecreaseOperationTimeoutForSubsequentOperations() { */ @ParameterizedTest @ValueSource(strings = {"insert", "create"}) - @Tag("setsFailPoint") void shouldThrowTimeoutExceptionWhenCreateEncryptedCollection(final String commandToTimeout) { assumeTrue(serverVersionAtLeast(7, 0)); //given @@ -298,7 +297,7 @@ void shouldThrowTimeoutExceptionWhenCreateEncryptedCollection(final String comma + "}")); keyVaultCollectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," + + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: { times: 1 }," + " data: {" + " failCommands: [\"" + commandToTimeout + "\"]," From ee08fa008cb96e1dff4bd66e7f8c108376b6a80d Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Tue, 7 May 2024 16:30:12 -0700 Subject: [PATCH 05/14] Update tests. JAVA-5104 --- .../connection/TestCommandListener.java | 6 +++ ...tClientSideOperationsTimeoutProseTest.java | 39 ++++++++----------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java b/driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java index 497cd3e7247..9c55183cf56 100644 --- a/driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java +++ b/driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java @@ -149,6 +149,12 @@ public List getCommandFailedEvents() { return getEvents(CommandFailedEvent.class, Integer.MAX_VALUE); } + public List getCommandFailedEvents(String commandName) { + return getEvents(CommandFailedEvent.class, + commandEvent -> commandEvent.getCommandName().equals(commandName), + Integer.MAX_VALUE); + } + public List getCommandStartedEvents() { return getEvents(CommandStartedEvent.class, Integer.MAX_VALUE); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index b4cc03f5e71..bf2e03dc3de 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -741,23 +741,12 @@ public void shouldIgnoreWtimeoutMsOfWriteConcernToInitialAndSubsequentCommitTran /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Test @DisplayName("Should refresh timeout for commit transaction") - public void shouldRefreshTimeoutForCommitTransaction() { + public void shouldThrowTimeoutExceptionForSubsequentCommitTransaction() { assumeTrue(serverVersionAtLeast(4, 4)); assumeFalse(isStandalone()); - collectionHelper.runAdminCommand("{" - + " configureFailPoint: \"failCommand\"," - + " mode: { times: 1 }," - + " data: {" - + " failCommands: [\"abortTransaction\"]," - + " blockConnection: true," - + " blockTimeMS: " + 600 - + " }" - + "}"); - try (MongoClient mongoClient = createMongoClient(getMongoClientSettingsBuilder())) { MongoCollection collection = mongoClient.getDatabase(namespace.getDatabaseName()) .getCollection(namespace.getCollectionName()); @@ -765,27 +754,31 @@ public void shouldRefreshTimeoutForCommitTransaction() { try (ClientSession session = mongoClient.startSession(ClientSessionOptions.builder() .defaultTimeout(200, TimeUnit.MILLISECONDS) .build())) { - session.startTransaction(TransactionOptions.builder() - .writeConcern(WriteConcern.ACKNOWLEDGED.withWTimeout(100, TimeUnit.MILLISECONDS)) - .build()); + session.startTransaction(TransactionOptions.builder().build()); collection.insertOne(session, new Document("x", 1)); sleep(200); assertDoesNotThrow(session::commitTransaction); + + collectionHelper.runAdminCommand("{" + + " configureFailPoint: \"failCommand\"," + + " mode: { times: 1 }," + + " data: {" + + " failCommands: [\"commitTransaction\"]," + + " blockConnection: true," + + " blockTimeMS: " + 500 + + " }" + + "}"); + //repeat commit. - assertDoesNotThrow(session::commitTransaction); + assertThrows(MongoOperationTimeoutException.class, session::commitTransaction); } } List commandStartedEvents = commandListener.getCommandStartedEvents("commitTransaction"); assertEquals(2, commandStartedEvents.size()); - commandStartedEvents.forEach(e -> { - BsonDocument command = e.getCommand(); - if (command.containsKey("writeConcern")) { - BsonDocument writeConcern = command.getDocument("writeConcern"); - assertFalse(writeConcern.isEmpty()); - assertFalse(writeConcern.containsKey("wTimeoutMS")); - }}); + List failedEvents = commandListener.getCommandFailedEvents("commitTransaction"); + assertEquals(1, failedEvents.size()); } private static Stream test8ServerSelectionArguments() { From cd170a5124014d7af064147c78ad3b2fbf2040ad Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Tue, 7 May 2024 16:35:50 -0700 Subject: [PATCH 06/14] Remove FailPoint test extension. JAVA-5104 --- .../ClientSideOperationTimeoutProseTest.java | 4 +-- ...tClientSideOperationsTimeoutProseTest.java | 8 ++--- .../client/FailPointTestExtension.java | 35 ------------------- ...eOperationsEncryptionTimeoutProseTest.java | 11 ++---- 4 files changed, 6 insertions(+), 52 deletions(-) delete mode 100644 driver-sync/src/test/functional/com/mongodb/client/FailPointTestExtension.java diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java index e70354af449..9f591e38221 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java @@ -523,8 +523,8 @@ public void setUp() { @Override @AfterEach - public void tearDown(final TestInfo info) { - super.tearDown(info); + public void tearDown() { + super.tearDown(); SyncMongoClient.disableSleep(); } diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index bf2e03dc3de..3e3b9be1f42 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -59,8 +59,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Named; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -102,9 +100,6 @@ public abstract class AbstractClientSideOperationsTimeoutProseTest { protected static final String FAIL_COMMAND_NAME = "failCommand"; - @RegisterExtension - protected static final FailPointTestExtension FAILPOINT_TEST_EXTENSION = new FailPointTestExtension(FAIL_COMMAND_NAME); - protected static final String GRID_FS_BUCKET_NAME = "db.fs"; private static final AtomicInteger COUNTER = new AtomicInteger(); @@ -829,7 +824,8 @@ public void setUp() { } @AfterEach - public void tearDown(final TestInfo info) { + public void tearDown() { + ClusterFixture.disableFailPoint(FAIL_COMMAND_NAME); if (collectionHelper != null) { collectionHelper.drop(); filesCollectionHelper.drop(); diff --git a/driver-sync/src/test/functional/com/mongodb/client/FailPointTestExtension.java b/driver-sync/src/test/functional/com/mongodb/client/FailPointTestExtension.java deleted file mode 100644 index 05a9444c8a9..00000000000 --- a/driver-sync/src/test/functional/com/mongodb/client/FailPointTestExtension.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.mongodb.client; - -import com.mongodb.ClusterFixture; -import org.junit.jupiter.api.extension.AfterEachCallback; -import org.junit.jupiter.api.extension.ExtensionContext; - -public class FailPointTestExtension implements AfterEachCallback { - - private final String failPointName; - - public FailPointTestExtension(final String failPointName) { - this.failPointName = failPointName; - } - - @Override - public void afterEach(ExtensionContext context) { - ClusterFixture.disableFailPoint(failPointName); - } -} \ No newline at end of file diff --git a/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java index 49186dfa32b..bc8ae8bbff7 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java @@ -26,7 +26,6 @@ import com.mongodb.ReadConcern; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; -import com.mongodb.client.FailPointTestExtension; import com.mongodb.client.Fixture; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; @@ -48,8 +47,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -78,8 +75,6 @@ public abstract class AbstractClientSideOperationsEncryptionTimeoutProseTest { protected static final String FAIL_COMMAND_NAME = "failCommand"; - @RegisterExtension - protected static final FailPointTestExtension FAILPOINT_TEST_EXTENSION = new FailPointTestExtension(FAIL_COMMAND_NAME); private static final Map> KMS_PROVIDERS = new HashMap<>(); private final MongoNamespace keyVaultNamespace = new MongoNamespace("keyvault", "datakeys"); @@ -383,11 +378,9 @@ public void setUp() { } @AfterEach - public void tearDown(final TestInfo info) { + public void tearDown() { + ClusterFixture.disableFailPoint(FAIL_COMMAND_NAME); if (keyVaultCollectionHelper != null) { - if (info.getTags().contains("setsFailPoint") && serverVersionAtLeast(4, 4)) { - keyVaultCollectionHelper.runAdminCommand("{configureFailPoint: \"failCommand\", mode: \"off\"}"); - } keyVaultCollectionHelper.drop(); } } From 0a7d145fc341f4ebcb943e49aba3ece1f4ac2e94 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Tue, 7 May 2024 22:30:36 -0700 Subject: [PATCH 07/14] Fix retry tests. JAVA-5104 --- .../com/mongodb/internal/async/function/RetryStateTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/driver-core/src/test/unit/com/mongodb/internal/async/function/RetryStateTest.java b/driver-core/src/test/unit/com/mongodb/internal/async/function/RetryStateTest.java index ecc8dda3592..f14cb3e18a1 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/async/function/RetryStateTest.java +++ b/driver-core/src/test/unit/com/mongodb/internal/async/function/RetryStateTest.java @@ -51,7 +51,7 @@ final class RetryStateTest { private static final TimeoutContext TIMEOUT_CONTEXT_INFINITE_GLOBAL_TIMEOUT = new TimeoutContext(new TimeoutSettings(0L, 0L, 0L, 0L, 0L)); - private static final String EXPECTED_TIMEOUT_MESSAGE = "Retry attempt timed out."; + private static final String EXPECTED_TIMEOUT_MESSAGE = "Retry attempt exceeded the timeout limit."; static Stream infiniteTimeout() { return Stream.of( @@ -302,7 +302,7 @@ void advanceThrowTimeoutExceptionWhenTransformerSwallowOriginalTimeoutException( (rs, e) -> false)); Assertions.assertNotEquals(actualTimeoutException, expectedTimeoutException); - Assertions.assertEquals("Retry attempt timed out.", actualTimeoutException.getMessage()); + Assertions.assertEquals(EXPECTED_TIMEOUT_MESSAGE, actualTimeoutException.getMessage()); Assertions.assertEquals(previousAttemptException, actualTimeoutException.getCause(), "Retry timeout exception should have a cause if transformer returned non-timeout exception."); } From d3841b5ec49c174bca2f310344ec71d87002b724 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Thu, 9 May 2024 18:00:50 -0700 Subject: [PATCH 08/14] Fix test assertion. JAVA-5104 --- .../client/internal/gridfs/GridFSUploadPublisherImplTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/gridfs/GridFSUploadPublisherImplTest.java b/driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/gridfs/GridFSUploadPublisherImplTest.java index aa628cc6dc8..38d19647fd7 100644 --- a/driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/gridfs/GridFSUploadPublisherImplTest.java +++ b/driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/gridfs/GridFSUploadPublisherImplTest.java @@ -93,7 +93,7 @@ void shouldTimeoutWhenSourcePublisherCompletionExceedsOverallOperationTimeout() Throwable throwable = onErrorEvents.get(0); assertEquals(MongoOperationTimeoutException.class, throwable.getClass()); - assertEquals("GridFS timed out waiting for data from provided source Publisher", throwable.getMessage()); + assertEquals("GridFS waiting for data from the source Publisher exceeded the timeout limit.", throwable.getMessage()); //assert no chunk has been inserted as we have not sent any data from source publisher. for (CommandEvent event : commandListener.getEvents()) { From cac9f36cba083e8615963a084033af5dffff9373 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Thu, 9 May 2024 19:54:56 -0700 Subject: [PATCH 09/14] - Fix timeoutContext being null for subsequent commmit transaction issue. - Adress static check issues. JAVA-5104 --- .../com/mongodb/internal/connection/TestCommandListener.java | 2 +- .../client/internal/ClientSessionPublisherImpl.java | 1 - .../client/ClientSideOperationTimeoutProseTest.java | 2 -- .../client/AbstractClientSideOperationsTimeoutProseTest.java | 3 +-- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java b/driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java index 9c55183cf56..d9033481612 100644 --- a/driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java +++ b/driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java @@ -149,7 +149,7 @@ public List getCommandFailedEvents() { return getEvents(CommandFailedEvent.class, Integer.MAX_VALUE); } - public List getCommandFailedEvents(String commandName) { + public List getCommandFailedEvents(final String commandName) { return getEvents(CommandFailedEvent.class, commandEvent -> commandEvent.getCommandName().equals(commandName), Integer.MAX_VALUE); diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java index fceee433ef6..62314c7e141 100644 --- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java +++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/ClientSessionPublisherImpl.java @@ -166,7 +166,6 @@ public Publisher commitTransaction() { .execute( new CommitTransactionOperation(writeConcern, alreadyCommitted) .recoveryToken(getRecoveryToken()), readConcern, this) - .doOnSuccess(ignored -> setTimeoutContext(null)) .doOnTerminate(() -> { commitInProgress = false; transactionState = TransactionState.COMMITTED; diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java index 9f591e38221..e4d8971872f 100644 --- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java +++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ClientSideOperationTimeoutProseTest.java @@ -41,9 +41,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; import reactor.core.publisher.Flux; import reactor.core.publisher.Hooks; import reactor.test.StepVerifier; diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index 3e3b9be1f42..a0723eaf9b6 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -696,7 +696,6 @@ public void test10CustomTestWithTransactionUsesASingleTimeoutWithLock() { /** * Not a prose spec test. However, it is additional test case for better coverage. */ - @Test @DisplayName("Should ignore wTimeoutMS of WriteConcern to initial and subsequent commitTransaction operations") public void shouldIgnoreWtimeoutMsOfWriteConcernToInitialAndSubsequentCommitTransactionOperations() { @@ -729,7 +728,7 @@ public void shouldIgnoreWtimeoutMsOfWriteConcernToInitialAndSubsequentCommitTran if (command.containsKey("writeConcern")) { BsonDocument writeConcern = command.getDocument("writeConcern"); assertFalse(writeConcern.isEmpty()); - assertFalse(writeConcern.containsKey("wTimeoutMS")); + assertFalse(writeConcern.containsKey("wtimeout")); }}); } From 306b7d8b137036cf916fa3e04ed0579b0d03746d Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Fri, 10 May 2024 21:14:53 -0700 Subject: [PATCH 10/14] - Skip cursor tests that require collection to be capped on serverless instances. JAVA-5104 --- .../AbstractClientSideOperationsTimeoutProseTest.java | 4 ++++ .../com/mongodb/client/ClientSideOperationTimeoutTest.java | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index a0723eaf9b6..759e4ca508d 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -463,6 +463,8 @@ public void test8ServerSelectionHandshake(final String ignoredTestName, final in public void test9EndSessionClientTimeout() { assumeTrue(serverVersionAtLeast(4, 4)); assumeFalse(isStandalone()); + assumeFalse(isServerlessTest()); + collectionHelper.runAdminCommand("{" + " configureFailPoint: \"failCommand\"," + " mode: { times: 1 }," @@ -499,6 +501,8 @@ public void test9EndSessionClientTimeout() { public void test9EndSessionSessionTimeout() { assumeTrue(serverVersionAtLeast(4, 4)); assumeFalse(isStandalone()); + assumeFalse(isServerlessTest()); + collectionHelper.runAdminCommand("{" + " configureFailPoint: \"failCommand\"," + " mode: { times: 1 }," diff --git a/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java b/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java index 3ed61ea082a..0c8b849a644 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java @@ -16,6 +16,7 @@ package com.mongodb.client; +import com.mongodb.ClusterFixture; import com.mongodb.client.unified.UnifiedSyncTest; import com.mongodb.lang.Nullable; import org.bson.BsonArray; @@ -53,6 +54,12 @@ public void shouldPassAllOutcomes() { } public static void skipOperationTimeoutTests(final String fileDescription, final String testDescription) { + + if (ClusterFixture.isServerlessTest()) { + // It is not possible to create capped collections on serverless instances. + assumeFalse(fileDescription.equals("timeoutMS behaves correctly for tailable awaitData cursors")); + assumeFalse(fileDescription.equals("timeoutMS behaves correctly for tailable non-awaitData cursors")); + } assumeFalse("No maxTimeMS parameter for createIndex() method", testDescription.contains("maxTimeMS is ignored if timeoutMS is set - createIndex on collection")); assumeFalse("No run cursor command", fileDescription.startsWith("runCursorCommand")); From 323ade21e3d56e00adc0186e290f4128e1ead6d6 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Wed, 15 May 2024 15:07:21 -0700 Subject: [PATCH 11/14] Reduce timeouts for serverless tests to pass. JAVA-5104 --- .../non-tailable-cursors.json | 7 ++++--- .../com/mongodb/client/ClientSideOperationTimeoutTest.java | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/non-tailable-cursors.json b/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/non-tailable-cursors.json index 291c6e72aa1..dd22ac3996f 100644 --- a/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/non-tailable-cursors.json +++ b/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/non-tailable-cursors.json @@ -1,5 +1,6 @@ { "description": "timeoutMS behaves correctly for non-tailable cursors", + "comment": "Manually reduced blockTimeMS for tests to pass in serverless", "schemaVersion": "1.9", "runOnRequirements": [ { @@ -143,7 +144,7 @@ "getMore" ], "blockConnection": true, - "blockTimeMS": 125 + "blockTimeMS": 101 } } } @@ -221,7 +222,7 @@ "getMore" ], "blockConnection": true, - "blockTimeMS": 150 + "blockTimeMS": 101 } } } @@ -355,7 +356,7 @@ "getMore" ], "blockConnection": true, - "blockTimeMS": 125 + "blockTimeMS": 101 } } } diff --git a/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java b/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java index 0c8b849a644..c1a995fef9e 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/ClientSideOperationTimeoutTest.java @@ -56,9 +56,13 @@ public void shouldPassAllOutcomes() { public static void skipOperationTimeoutTests(final String fileDescription, final String testDescription) { if (ClusterFixture.isServerlessTest()) { + // It is not possible to create capped collections on serverless instances. assumeFalse(fileDescription.equals("timeoutMS behaves correctly for tailable awaitData cursors")); assumeFalse(fileDescription.equals("timeoutMS behaves correctly for tailable non-awaitData cursors")); + + /* Drivers MUST NOT execute a killCursors command because the pinned connection is no longer under a load balancer. */ + assumeFalse(testDescription.equals("timeoutMS is refreshed for close")); } assumeFalse("No maxTimeMS parameter for createIndex() method", testDescription.contains("maxTimeMS is ignored if timeoutMS is set - createIndex on collection")); From c4ac3a3fa6f013d29e8d7cfce6feec848263cee8 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Sun, 26 May 2024 20:55:05 -0700 Subject: [PATCH 12/14] - Revert change in unified tests. - Rename test name. --- .../sessions-override-operation-timeoutMS.json | 8 ++++---- .../AbstractClientSideOperationsTimeoutProseTest.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/sessions-override-operation-timeoutMS.json b/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/sessions-override-operation-timeoutMS.json index 2839d0a33b7..441c698328c 100644 --- a/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/sessions-override-operation-timeoutMS.json +++ b/driver-core/src/test/resources/unified-test-format/client-side-operation-timeout/sessions-override-operation-timeoutMS.json @@ -82,10 +82,7 @@ }, { "name": "startTransaction", - "object": "session", - "arguments": { - "timeoutMS": 500 - } + "object": "session" }, { "name": "insertOne", @@ -100,6 +97,9 @@ { "name": "commitTransaction", "object": "session", + "arguments": { + "timeoutMS": 500 + }, "expectError": { "isTimeoutError": true } diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java index 759e4ca508d..9264caad5e4 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractClientSideOperationsTimeoutProseTest.java @@ -740,7 +740,7 @@ public void shouldIgnoreWtimeoutMsOfWriteConcernToInitialAndSubsequentCommitTran * Not a prose spec test. However, it is additional test case for better coverage. */ @Test - @DisplayName("Should refresh timeout for commit transaction") + @DisplayName("Should throw timeout exception for subsequent commit transaction") public void shouldThrowTimeoutExceptionForSubsequentCommitTransaction() { assumeTrue(serverVersionAtLeast(4, 4)); assumeFalse(isStandalone()); From 9013da838b05a8d639a4d7d9ac4a6f1f4841aed2 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Tue, 4 Jun 2024 04:43:41 -0700 Subject: [PATCH 13/14] Remove unused imports. --- .../src/test/functional/com/mongodb/client/unified/Entities.java | 1 - 1 file changed, 1 deletion(-) diff --git a/driver-sync/src/test/functional/com/mongodb/client/unified/Entities.java b/driver-sync/src/test/functional/com/mongodb/client/unified/Entities.java index bd89ccc2cbc..746a7704c1d 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/unified/Entities.java +++ b/driver-sync/src/test/functional/com/mongodb/client/unified/Entities.java @@ -26,7 +26,6 @@ import com.mongodb.ServerApi; import com.mongodb.ServerApiVersion; import com.mongodb.TransactionOptions; -import com.mongodb.WriteConcern; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCluster; From 9bbf8407033117e7cf29907ccf12a54fd6d93d11 Mon Sep 17 00:00:00 2001 From: "slav.babanin" Date: Tue, 4 Jun 2024 07:29:41 -0700 Subject: [PATCH 14/14] Increase timeouts. --- ...tractClientSideOperationsEncryptionTimeoutProseTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java index bc8ae8bbff7..6d3d134e2fc 100644 --- a/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java +++ b/driver-sync/src/test/functional/com/mongodb/client/csot/AbstractClientSideOperationsEncryptionTimeoutProseTest.java @@ -163,7 +163,7 @@ void shouldThrowOperationTimeoutExceptionWhenDecryptData() { long rtt = ClusterFixture.getPrimaryRTT(); BsonBinary encrypted; - try (ClientEncryption clientEncryption = createClientEncryption(getClientEncryptionSettingsBuilder(rtt + 100))) { + try (ClientEncryption clientEncryption = createClientEncryption(getClientEncryptionSettingsBuilder(rtt + 400))) { clientEncryption.createDataKey("local"); BsonBinary dataKey = clientEncryption.createDataKey("local"); EncryptOptions encryptOptions = new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"); @@ -171,14 +171,14 @@ void shouldThrowOperationTimeoutExceptionWhenDecryptData() { encrypted = clientEncryption.encrypt(new BsonString("hello"), encryptOptions); } - try (ClientEncryption clientEncryption = createClientEncryption(getClientEncryptionSettingsBuilder(rtt + 100))) { + try (ClientEncryption clientEncryption = createClientEncryption(getClientEncryptionSettingsBuilder(rtt + 400))) { keyVaultCollectionHelper.runAdminCommand("{" + " configureFailPoint: \"" + FAIL_COMMAND_NAME + "\"," + " mode: { times: 1 }," + " data: {" + " failCommands: [\"find\"]," + " blockConnection: true," - + " blockTimeMS: " + (rtt + 100) + + " blockTimeMS: " + (rtt + 500) + " }" + "}"); commandListener.reset();