Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .evergreen/setup-env.bash
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Java configurations for evergreen

# On Windows Evergreen hosts `OS` is a native environment variable set to
# "Windows_NT". It is not set on other platforms, so default it from `uname`
# to avoid an unbound variable error under `set -u`.
if [ -z "${OS:-}" ]; then
case "$(uname -s)" in
CYGWIN*|MINGW*|MSYS*|Windows_NT) OS="Windows_NT" ;;
*) OS="$(uname -s)" ;;
esac
fi

if [ "Windows_NT" == "$OS" ]; then
export JDK8="/cygdrive/c/java/jdk8"
export JDK11="/cygdrive/c/java/jdk11"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1003,8 +1003,14 @@ private static void rethrowIfError(final Throwable t) {

private void throwTranslatedWriteException(final Throwable e, final OperationContext operationContext) {
rethrowIfError(e);
if (e instanceof MongoSocketWriteTimeoutException && operationContext.getTimeoutContext().hasTimeoutMS()) {
throw createMongoTimeoutException(e);
if (operationContext.getTimeoutContext().hasTimeoutMS()) {
if (e instanceof MongoSocketWriteTimeoutException) {
throw createMongoTimeoutException(e);
} else if (e instanceof SocketTimeoutException) {
// A blocking (SSL) write can surface the socket read-timeout as a bare SocketTimeoutException;
// mirror translateReadException so it is reported as a timeout rather than a generic write error.
throw createMongoTimeoutException(createWriteTimeoutException((SocketTimeoutException) e));
}
}

if (e instanceof MongoException) {
Expand Down Expand Up @@ -1032,6 +1038,10 @@ private Throwable translateReadFailure(final Throwable e, final OperationContext
return translateReadException(e, operationContext);
}

private MongoSocketWriteTimeoutException createWriteTimeoutException(final SocketTimeoutException e) {
return new MongoSocketWriteTimeoutException("Timeout while sending message", getServerAddress(), e);
}

private MongoException translateReadException(final Throwable e, final OperationContext operationContext) {
if (operationContext.getTimeoutContext().hasTimeoutMS()) {
if (e instanceof SocketTimeoutException) {
Expand Down
16 changes: 16 additions & 0 deletions driver-core/src/test/functional/com/mongodb/ClusterFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;

Expand Down Expand Up @@ -837,4 +838,19 @@ private static OperationContext applySessionContext(final OperationContext opera
public static OperationContext getOperationContext(final ReadPreference readPreference) {
return applySessionContext(OPERATION_CONTEXT, readPreference);
}

/** Factor by which CSOT timeout/block values are widened on Windows, whose slower TLS setup eats tight budgets. */
public static final int WINDOWS_CSOT_TIMEOUT_MULTIPLIER = 10;

public static boolean isWindows() {
return System.getProperty("os.name", "").toLowerCase(Locale.ROOT).startsWith("windows");
}

/**
* Scales a CSOT timeout / failpoint-block value by {@link #WINDOWS_CSOT_TIMEOUT_MULTIPLIER} on Windows (unchanged
* elsewhere). Scale a test's timeout and its blockTimeMS together to preserve which command times out.
*/
public static int scaleForWindows(final int millis) {
return isWindows() ? millis * WINDOWS_CSOT_TIMEOUT_MULTIPLIER : millis;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ public void asStringTest() {
}

@Test
public void asStringTestNestedPre82() {
assumeTrue(serverVersionLessThan(8, 2));
public void asStringTestNestedPre83() {
assumeTrue(serverVersionLessThan(8, 3));

// Arrays and documents are not (yet) supported:
assertThrows(MongoCommandException.class, () ->
Expand All @@ -202,7 +202,7 @@ public void asStringTestNestedPre82() {

@Test
public void asStringTestNested() {
assumeTrue(serverVersionAtLeast(8, 2));
assumeTrue(serverVersionAtLeast(8, 3));

assertExpression("[1,2]", ofIntegerArray(1, 2).asString());
assertExpression("{\"a\":1}", of(Document.parse("{a: 1}")).asString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.mongodb.MongoSocketException
import com.mongodb.MongoSocketReadException
import com.mongodb.MongoSocketReadTimeoutException
import com.mongodb.MongoSocketWriteException
import com.mongodb.MongoSocketWriteTimeoutException
import com.mongodb.ReadConcern
import com.mongodb.ServerAddress
import com.mongodb.async.FutureResultCallback
Expand Down Expand Up @@ -476,6 +477,25 @@ class InternalStreamConnectionSpecification extends Specification {
connection.isClosed()
}

def 'Should throw timeout exception with underlying socket exception as a cause when Stream.write throws SocketTimeoutException'() {
given:
stream.write(_, _) >> { throw new SocketTimeoutException() }
def connection = getOpenedConnection()
def (buffers, messageId) = helper.hello()

when:
connection.sendMessage(buffers, messageId, OPERATION_CONTEXT.withTimeoutContext(
new TimeoutContext(TIMEOUT_SETTINGS_WITH_INFINITE_TIMEOUT)))

then:
def timeoutException = thrown(MongoOperationTimeoutException)
def mongoSocketWriteTimeoutException = timeoutException.getCause()
mongoSocketWriteTimeoutException instanceof MongoSocketWriteTimeoutException
mongoSocketWriteTimeoutException.getCause() instanceof SocketTimeoutException

connection.isClosed()
}

def 'Should wrap MongoSocketReadTimeoutException with MongoOperationTimeoutException'() {
given:
stream.read(_, _) >> { throw new MongoSocketReadTimeoutException("test", new ServerAddress(), null) }
Expand Down
Loading