Skip to content

Commit ce12734

Browse files
committed
Add Windows CI testing
- Add Windows 2022 Evergreen build variants for server 8.2 across all topologies to enable Windows CI coverage - Add EnvironmentProvider class to centralize all System.getenv() calls, replacing the reflection-based env var override hack that fails on Windows due to JDK's ProcessEnvironment dual-map architecture - Fix SSL keystore/truststore paths in Evergreen scripts to use native Windows paths via cygpath - Fix JSON test file path separator handling and mongocryptd temp directory for Windows compatibility - Skip Unix-domain-socket test on Windows JAVA-6057
1 parent 8731b19 commit ce12734

18 files changed

Lines changed: 252 additions & 116 deletions

File tree

.evergreen/.evg.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,12 @@ axes:
17401740
display_name: "8.0"
17411741
variables:
17421742
VERSION: "8.0"
1743+
# 8.2 is used solely for Windows testing. MongoDB 8.0 binaries are affected by SERVER-116018 on Windows,
1744+
# and the fix is only available starting from 8.2.
1745+
- id: "8.2"
1746+
display_name: "8.2"
1747+
variables:
1748+
VERSION: "8.2"
17431749
- id: "7.0"
17441750
display_name: "7.0"
17451751
variables:
@@ -1770,6 +1776,9 @@ axes:
17701776
- id: "ubuntu"
17711777
display_name: "Ubuntu"
17721778
run_on: "ubuntu2004-small"
1779+
- id: "windows"
1780+
display_name: "Windows"
1781+
run_on: "windows-2022-latest-small"
17731782

17741783
- id: "topology"
17751784
display_name: "Topology"
@@ -2403,6 +2412,22 @@ buildvariants:
24032412
- name: "test-core-task"
24042413
- name: "test-legacy-task"
24052414

2415+
- matrix_name: "tests-jdk-secure-windows"
2416+
matrix_spec: { auth: "auth", ssl: "ssl", jdk: "jdk17",
2417+
version: [ "8.2" ],
2418+
topology: "*", os: "windows" }
2419+
display_name: "${os}: ${version} ${topology} ${auth} ${ssl} ${jdk}"
2420+
tags: [ "tests-variant" ]
2421+
tasks:
2422+
- name: "test-sync-task"
2423+
exec_timeout_secs: 7200
2424+
- name: "test-reactive-task"
2425+
exec_timeout_secs: 7200
2426+
- name: "test-core-task"
2427+
exec_timeout_secs: 7200
2428+
- name: "test-legacy-task"
2429+
exec_timeout_secs: 7200
2430+
24062431
- matrix_name: "tests-require-api-version"
24072432
matrix_spec: { api-version: "required", auth: "auth", ssl: "nossl", jdk: [ "jdk21" ], version: [ "5.0", "6.0", "7.0", "8.0", "latest" ],
24082433
topology: "standalone", os: "linux" }
@@ -2540,6 +2565,15 @@ buildvariants:
25402565
tasks:
25412566
- name: "csfle-tests-with-mongocryptd-task"
25422567

2568+
- matrix_name: "csfle-tests-with-mongocryptd-windows"
2569+
matrix_spec: { os: "windows",
2570+
version: [ "8.0", "latest" ],
2571+
topology: [ "replicaset" ] }
2572+
display_name: "${os} CSFLE with mongocryptd: ${version}"
2573+
tasks:
2574+
- name: "csfle-tests-with-mongocryptd-task"
2575+
exec_timeout_secs: 7200
2576+
25432577
- matrix_name: "socks5-tests"
25442578
matrix_spec: { os: "linux", ssl: [ "nossl", "ssl" ], version: [ "latest" ], topology: [ "replicaset" ], socks-auth: [ "auth", "noauth" ] }
25452579
display_name: "SOCKS5 proxy ${socks-auth} : ${version} ${topology} ${ssl} ${jdk} ${os}"

.evergreen/run-csfle-tests-with-mongocryptd.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,16 @@ provision_ssl () {
3939
cp ${JAVA_HOME}/lib/security/cacerts mongo-truststore
4040
${JAVA_HOME}/bin/keytool -importcert -trustcacerts -file ${DRIVERS_TOOLS}/.evergreen/x509gen/ca.pem -keystore mongo-truststore -storepass changeit -storetype JKS -noprompt
4141

42+
# Use native paths on Windows (cygwin paths like /cygdrive/c/... are not understood by the JDK)
43+
local CURRENT_DIR
44+
if [ "Windows_NT" == "$OS" ]; then
45+
CURRENT_DIR=$(cygpath -m "$(pwd)")
46+
else
47+
CURRENT_DIR=$(pwd)
48+
fi
49+
4250
# We add extra gradle arguments for SSL
43-
export GRADLE_EXTRA_VARS="-Pssl.enabled=true -Pssl.keyStoreType=pkcs12 -Pssl.keyStore=`pwd`/client.pkc -Pssl.keyStorePassword=bithere -Pssl.trustStoreType=jks -Pssl.trustStore=`pwd`/mongo-truststore -Pssl.trustStorePassword=changeit"
51+
export GRADLE_EXTRA_VARS="-Pssl.enabled=true -Pssl.keyStoreType=pkcs12 -Pssl.keyStore=${CURRENT_DIR}/client.pkc -Pssl.keyStorePassword=bithere -Pssl.trustStoreType=jks -Pssl.trustStore=${CURRENT_DIR}/mongo-truststore -Pssl.trustStorePassword=changeit"
4452
}
4553

4654
############################################

.evergreen/run-tests.sh

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,16 @@ provision_ssl () {
6262
cp ${JAVA_HOME}/lib/security/cacerts mongo-truststore
6363
${JAVA_HOME}/bin/keytool -importcert -trustcacerts -file ${DRIVERS_TOOLS}/.evergreen/x509gen/ca.pem -keystore mongo-truststore -storepass changeit -storetype JKS -noprompt
6464

65+
# Use native paths on Windows (cygwin paths like /cygdrive/c/... are not understood by the JDK)
66+
local CURRENT_DIR
67+
if [ "Windows_NT" == "$OS" ]; then
68+
CURRENT_DIR=$(cygpath -m "$(pwd)")
69+
else
70+
CURRENT_DIR=$(pwd)
71+
fi
72+
6573
# We add extra gradle arguments for SSL
66-
export GRADLE_EXTRA_VARS="-Pssl.enabled=true -Pssl.keyStoreType=pkcs12 -Pssl.keyStore=`pwd`/client.pkc -Pssl.keyStorePassword=bithere -Pssl.trustStoreType=jks -Pssl.trustStore=`pwd`/mongo-truststore -Pssl.trustStorePassword=changeit"
74+
export GRADLE_EXTRA_VARS="-Pssl.enabled=true -Pssl.keyStoreType=pkcs12 -Pssl.keyStore=${CURRENT_DIR}/client.pkc -Pssl.keyStorePassword=bithere -Pssl.trustStoreType=jks -Pssl.trustStore=${CURRENT_DIR}/mongo-truststore -Pssl.trustStorePassword=changeit"
6775
}
6876

6977
provision_multi_mongos_uri_for_ssl () {
@@ -124,6 +132,12 @@ if [ ! -z "$REQUIRE_API_VERSION" ]; then
124132
export API_VERSION="-Dorg.mongodb.test.api.version=1"
125133
fi
126134

135+
# Log Windows version info for diagnostics
136+
if [ "Windows_NT" == "$OS" ]; then
137+
echo "Windows build info:"
138+
cmd /c ver
139+
fi
140+
127141
echo "Running $AUTH tests over $SSL for $TOPOLOGY and connecting to $MONGODB_URI"
128142

129143
echo "Running tests with Java ${JAVA_VERSION}"

.evergreen/setup-env.bash

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
# Java configurations for evergreen
22

3-
export JDK8="/opt/java/jdk8"
4-
export JDK11="/opt/java/jdk11"
5-
export JDK17="/opt/java/jdk17"
6-
export JDK21="/opt/java/jdk21"
3+
if [ "Windows_NT" == "$OS" ]; then
4+
export JDK8="/cygdrive/c/java/jdk8"
5+
export JDK11="/cygdrive/c/java/jdk11"
6+
export JDK17="/cygdrive/c/java/jdk17"
7+
export JDK21="/cygdrive/c/java/jdk21"
8+
else
9+
export JDK8="/opt/java/jdk8"
10+
export JDK11="/opt/java/jdk11"
11+
export JDK17="/opt/java/jdk17"
12+
export JDK21="/opt/java/jdk21"
13+
fi
714
# note that `JDK21_GRAALVM` is used in `run-graalvm-native-image-app.sh`
815
# by dynamically constructing the variable name
916
export JDK21_GRAALVM="/opt/java/jdk21-graalce"

bson/src/test/unit/util/JsonPoweredTestHelper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ public static List<BsonDocument> getTestDocuments(final String resourcePath) {
8686
public FileVisitResult visitFile(final Path filePath, final BasicFileAttributes attrs) throws IOException {
8787
if (filePath.toString().endsWith(".json")) {
8888
if (fileSystem == null) {
89-
files.add(getTestDocumentWithMetaData(filePath.toString().substring(filePath.toString().lastIndexOf(resourcePath))));
89+
String filePathStr = filePath.toString().replace('\\', '/');
90+
files.add(getTestDocumentWithMetaData(filePathStr.substring(filePathStr.lastIndexOf(resourcePath))));
9091
} else {
9192
files.add(getTestDocumentWithMetaData(filePath.toString()));
9293
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.internal;
18+
19+
import com.mongodb.lang.Nullable;
20+
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
import java.util.function.UnaryOperator;
24+
25+
/**
26+
* Centralized access to environment variables. All production code should use
27+
* this class instead of calling {@link System#getenv(String)} directly.
28+
*
29+
* <p>Tests can override values via {@link #envOverride()}.</p>
30+
*/
31+
public final class EnvironmentProvider {
32+
private static UnaryOperator<String> envLookup = System::getenv;
33+
34+
private EnvironmentProvider() {
35+
}
36+
37+
@Nullable
38+
public static String getEnv(final String key) {
39+
return envLookup.apply(key);
40+
}
41+
42+
/** Exists only for testing **/
43+
public static EnvironmentOverride envOverride() {
44+
return new EnvironmentOverride();
45+
}
46+
47+
public static final class EnvironmentOverride implements AutoCloseable {
48+
private final Map<String, String> overrides = new HashMap<>();
49+
private final UnaryOperator<String> original;
50+
51+
private EnvironmentOverride() {
52+
original = envLookup;
53+
envLookup = key -> overrides.containsKey(key)
54+
? overrides.get(key)
55+
: original.apply(key);
56+
}
57+
58+
public EnvironmentOverride set(final String key, @Nullable final String value) {
59+
overrides.put(key, value);
60+
return this;
61+
}
62+
63+
@Override
64+
public void close() {
65+
envLookup = original;
66+
}
67+
}
68+
}

driver-core/src/main/com/mongodb/internal/authentication/BuiltInAwsCredentialSupplier.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.mongodb.internal.authentication;
1818

1919
import com.mongodb.AwsCredential;
20+
import com.mongodb.internal.EnvironmentProvider;
2021
import org.bson.BsonDocument;
2122

2223
import java.util.HashMap;
@@ -29,7 +30,7 @@ class BuiltInAwsCredentialSupplier implements Supplier<AwsCredential> {
2930

3031
@Override
3132
public AwsCredential get() {
32-
if (System.getenv("AWS_ACCESS_KEY_ID") != null) {
33+
if (EnvironmentProvider.getEnv("AWS_ACCESS_KEY_ID") != null) {
3334
return obtainFromEnvironmentVariables();
3435
} else {
3536
return obtainFromEc2OrEcsResponse();
@@ -38,13 +39,13 @@ public AwsCredential get() {
3839

3940
private static AwsCredential obtainFromEnvironmentVariables() {
4041
return new AwsCredential(
41-
System.getenv("AWS_ACCESS_KEY_ID"),
42-
System.getenv("AWS_SECRET_ACCESS_KEY"),
43-
System.getenv("AWS_SESSION_TOKEN"));
42+
EnvironmentProvider.getEnv("AWS_ACCESS_KEY_ID"),
43+
EnvironmentProvider.getEnv("AWS_SECRET_ACCESS_KEY"),
44+
EnvironmentProvider.getEnv("AWS_SESSION_TOKEN"));
4445
}
4546

4647
private static AwsCredential obtainFromEc2OrEcsResponse() {
47-
String path = System.getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI");
48+
String path = EnvironmentProvider.getEnv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI");
4849
BsonDocument ec2OrEcsResponse = path == null ? BsonDocument.parse(getEc2Response()) : BsonDocument.parse(getEcsResponse(path));
4950

5051
return new AwsCredential(

driver-core/src/main/com/mongodb/internal/connection/FaasEnvironment.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,12 @@
1616

1717
package com.mongodb.internal.connection;
1818

19+
import com.mongodb.internal.EnvironmentProvider;
1920
import com.mongodb.lang.Nullable;
2021

2122
import java.util.ArrayList;
2223
import java.util.Arrays;
23-
import java.util.HashMap;
2424
import java.util.List;
25-
import java.util.Map;
2625

2726
enum FaasEnvironment {
2827
AWS_LAMBDA("aws.lambda"),
@@ -31,8 +30,6 @@ enum FaasEnvironment {
3130
VERCEL("vercel"),
3231
UNKNOWN(null);
3332

34-
static final Map<String, String> ENV_OVERRIDES_FOR_TESTING = new HashMap<>();
35-
3633
static FaasEnvironment getFaasEnvironment() {
3734
List<FaasEnvironment> result = new ArrayList<>();
3835
String awsExecutionEnv = getEnv("AWS_EXECUTION_ENV");
@@ -62,10 +59,7 @@ static FaasEnvironment getFaasEnvironment() {
6259

6360
@Nullable
6461
public static String getEnv(final String key) {
65-
if (ENV_OVERRIDES_FOR_TESTING.containsKey(key)) {
66-
return ENV_OVERRIDES_FOR_TESTING.get(key);
67-
}
68-
return System.getenv(key);
62+
return EnvironmentProvider.getEnv(key);
6963
}
7064

7165
@Nullable

driver-core/src/main/com/mongodb/internal/connection/OidcAuthenticator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.mongodb.internal.connection;
1818

1919
import com.mongodb.AuthenticationMechanism;
20+
import com.mongodb.internal.EnvironmentProvider;
2021
import com.mongodb.MongoClientException;
2122
import com.mongodb.MongoCommandException;
2223
import com.mongodb.MongoConfigurationException;
@@ -235,8 +236,8 @@ private static OidcCallback getTestCallback() {
235236
@VisibleForTesting(otherwise = VisibleForTesting.AccessModifier.PRIVATE)
236237
static OidcCallback getK8sCallback() {
237238
return (context) -> {
238-
String azure = System.getenv(K8S_AZURE_FILE);
239-
String aws = System.getenv(K8S_AWS_FILE);
239+
String azure = EnvironmentProvider.getEnv(K8S_AZURE_FILE);
240+
String aws = EnvironmentProvider.getEnv(K8S_AWS_FILE);
240241
String path;
241242
if (azure != null) {
242243
path = azure;
@@ -542,7 +543,7 @@ public boolean isComplete() {
542543
}
543544

544545
private static String readTokenFromFile() {
545-
String path = System.getenv(OIDC_TOKEN_FILE);
546+
String path = EnvironmentProvider.getEnv(OIDC_TOKEN_FILE);
546547
if (path == null) {
547548
throw new MongoClientException(
548549
format("Environment variable must be specified: %s", OIDC_TOKEN_FILE));

driver-core/src/main/com/mongodb/internal/observability/micrometer/MicrometerTracer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import static com.mongodb.internal.observability.micrometer.MongodbObservation.LowCardinalityKeyNames.EXCEPTION_TYPE;
3939
import static com.mongodb.internal.observability.micrometer.MongodbObservation.MONGODB_OBSERVATION;
4040
import static com.mongodb.internal.observability.micrometer.TracingManager.ENV_OBSERVABILITY_QUERY_TEXT_MAX_LENGTH;
41-
import static java.lang.System.getenv;
41+
import static com.mongodb.internal.EnvironmentProvider.getEnv;
4242
import static java.util.Optional.ofNullable;
4343

4444

@@ -75,7 +75,7 @@ public MicrometerTracer(final ObservationRegistry observationRegistry) {
7575
public MicrometerTracer(final ObservationRegistry observationRegistry, final boolean allowCommandPayload, final int textMaxLength) {
7676
this.allowCommandPayload = allowCommandPayload;
7777
this.observationRegistry = observationRegistry;
78-
this.textMaxLength = ofNullable(getenv(ENV_OBSERVABILITY_QUERY_TEXT_MAX_LENGTH))
78+
this.textMaxLength = ofNullable(getEnv(ENV_OBSERVABILITY_QUERY_TEXT_MAX_LENGTH))
7979
.map(Integer::parseInt)
8080
.orElse(textMaxLength);
8181
}

0 commit comments

Comments
 (0)