Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bc4af89

Browse files
authoredFeb 14, 2025··
Merge branch 'main' into write_chars_heap_ascii
2 parents 82782ee + 36448cd commit bc4af89

File tree

16 files changed

+412
-188
lines changed

16 files changed

+412
-188
lines changed
 

Diff for: ‎.evergreen/.evg.yml

+57-104
Original file line numberDiff line numberDiff line change
@@ -509,24 +509,6 @@ functions:
509509
mongo --nodb setup.js aws_e2e_ecs.js
510510
cd -
511511
512-
"run atlas data lake test":
513-
- command: shell.exec
514-
type: test
515-
params:
516-
working_dir: "src"
517-
script: |
518-
${PREPARE_SHELL}
519-
JAVA_VERSION=${JAVA_VERSION} .evergreen/run-atlas-data-lake-test.sh
520-
521-
"run atlas search test":
522-
- command: shell.exec
523-
type: test
524-
params:
525-
working_dir: "src"
526-
script: |
527-
${PREPARE_SHELL}
528-
MONGODB_URI="${atlas_search_uri}" .evergreen/run-atlas-search-tests.sh
529-
530512
"run-ocsp-test":
531513
- command: shell.exec
532514
type: test
@@ -627,19 +609,6 @@ functions:
627609
${PREPARE_SHELL}
628610
PROJECT_DIRECTORY=${PROJECT_DIRECTORY} JAVA_VERSION=${JAVA_VERSION} TOPOLOGY=${TOPOLOGY} STORAGE_ENGINE=${STORAGE_ENGINE} MONGODB_URI="${MONGODB_URI}" .evergreen/run-mmapv1-storage-test.sh
629611
630-
"run atlas test":
631-
- command: shell.exec
632-
type: test
633-
params:
634-
silent: true
635-
working_dir: "src"
636-
script: |
637-
# DO NOT ECHO WITH XTRACE (which PREPARE_SHELL does)
638-
# The connection strings are pipe-delimited
639-
JAVA_VERSION="8" \
640-
MONGODB_URIS="${atlas_free_tier_uri}|${atlas_replica_set_uri}|${atlas_sharded_uri}|${atlas_tls_v11_uri}|${atlas_tls_v12_uri}|${atlas_free_tier_uri_srv}|${atlas_replica_set_uri_srv}|${atlas_sharded_uri_srv}|${atlas_tls_v11_uri_srv}|${atlas_tls_v12_uri_srv}|${atlas_serverless_uri}|${atlas_serverless_uri_srv}" \
641-
.evergreen/run-connectivity-tests.sh
642-
643612
run socks5 tests:
644613
- command: shell.exec
645614
type: test
@@ -1454,14 +1423,50 @@ tasks:
14541423
OCSP_MUST_STAPLE: "false"
14551424
OCSP_TLS_SHOULD_SUCCEED: "0"
14561425

1457-
- name: "atlas-data-lake-test"
1426+
- name: "atlas-data-lake-task"
14581427
commands:
14591428
- func: "bootstrap mongohoused"
1460-
- func: "run atlas data lake test"
1429+
- command: shell.exec
1430+
type: test
1431+
params:
1432+
working_dir: "src"
1433+
script: |
1434+
${PREPARE_SHELL}
1435+
JAVA_VERSION=${JAVA_VERSION} .evergreen/run-atlas-data-lake-test.sh
14611436
1462-
- name: "atlas-search-test"
1437+
- name: "atlas-search-task"
14631438
commands:
1464-
- func: "run atlas search test"
1439+
- command: shell.exec
1440+
type: test
1441+
params:
1442+
working_dir: "src"
1443+
script: |
1444+
${PREPARE_SHELL}
1445+
MONGODB_URI="${atlas_search_uri}" .evergreen/run-atlas-search-tests.sh
1446+
1447+
- name: "atlas-connectivity-task"
1448+
commands:
1449+
- command: shell.exec
1450+
type: test
1451+
params:
1452+
silent: true
1453+
working_dir: "src"
1454+
script: |
1455+
# DO NOT ECHO WITH XTRACE (which PREPARE_SHELL does)
1456+
# The connection strings are pipe-delimited
1457+
MONGODB_URIS="${atlas_free_tier_uri}|${atlas_replica_set_uri}|${atlas_sharded_uri}|${atlas_tls_v11_uri}|${atlas_tls_v12_uri}|${atlas_free_tier_uri_srv}|${atlas_replica_set_uri_srv}|${atlas_sharded_uri_srv}|${atlas_tls_v11_uri_srv}|${atlas_tls_v12_uri_srv}|${atlas_serverless_uri}|${atlas_serverless_uri_srv}" \
1458+
JAVA_VERSION="8" \
1459+
.evergreen/run-connectivity-tests.sh
1460+
1461+
- name: "atlas-search-index-management-task"
1462+
commands:
1463+
- command: subprocess.exec
1464+
params:
1465+
working_dir: src
1466+
binary: bash
1467+
add_expansions_to_env: true
1468+
args:
1469+
- .evergreen/run-atlas-search-index-management-tests.sh
14651470

14661471
- name: "gssapi-auth-test"
14671472
commands:
@@ -1482,20 +1487,6 @@ tasks:
14821487
- func: "bootstrap mongo-orchestration"
14831488
- func: "run netty tests"
14841489

1485-
- name: "atlas-test"
1486-
commands:
1487-
- func: "run atlas test"
1488-
1489-
- name: "test-atlas-search-index-helpers"
1490-
commands:
1491-
- command: subprocess.exec
1492-
params:
1493-
working_dir: src
1494-
binary: bash
1495-
add_expansions_to_env: true
1496-
args:
1497-
- .evergreen/run-atlas-search-index-management-tests.sh
1498-
14991490
- name: publish-snapshot
15001491
depends_on:
15011492
- variant: "static-checks"
@@ -1528,7 +1519,7 @@ tasks:
15281519
- func: "run perf tests"
15291520
- func: "send dashboard data"
15301521

1531-
- name: "test-aws-lambda-deployed"
1522+
- name: "aws-lambda-deployed-task"
15321523
commands:
15331524
- command: ec2.assume_role
15341525
params:
@@ -1622,7 +1613,6 @@ tasks:
16221613
echo "Untarring file ... begin"
16231614
GCPKMS_CMD="tar xf mongo-java-driver.tgz" $DRIVERS_TOOLS/.evergreen/csfle/gcpkms/run-command.sh
16241615
echo "Untarring file ... end"
1625-
16261616
- command: shell.exec
16271617
type: test
16281618
params:
@@ -1910,11 +1900,12 @@ axes:
19101900
batchtime: 10080 # 7 days
19111901

19121902
task_groups:
1913-
- name: test_atlas_task_group_search_indexes
1903+
- name: "atlas-deployed-task-group"
19141904
setup_group:
19151905
- func: fetch source
19161906
- func: prepare resources
19171907
- command: subprocess.exec
1908+
type: setup
19181909
params:
19191910
working_dir: src
19201911
binary: bash
@@ -1926,6 +1917,7 @@ task_groups:
19261917
file: src/atlas-expansion.yml
19271918
teardown_group:
19281919
- command: subprocess.exec
1920+
type: setup
19291921
params:
19301922
working_dir: src
19311923
binary: bash
@@ -1935,7 +1927,9 @@ task_groups:
19351927
setup_group_can_fail_task: true
19361928
setup_group_timeout_secs: 1800
19371929
tasks:
1938-
- test-atlas-search-index-helpers
1930+
- "atlas-search-index-management-task"
1931+
- "aws-lambda-deployed-task"
1932+
19391933
- name: testgcpkms_task_group
19401934
setup_group_can_fail_task: true
19411935
setup_group_timeout_secs: 1800 # 30 minutes
@@ -1971,6 +1965,7 @@ task_groups:
19711965
$DRIVERS_TOOLS/.evergreen/csfle/gcpkms/delete-instance.sh
19721966
tasks:
19731967
- testgcpkms-task
1968+
19741969
- name: testazurekms_task_group
19751970
setup_group_can_fail_task: true
19761971
setup_group_timeout_secs: 1800 # 30 minutes
@@ -2015,32 +2010,6 @@ task_groups:
20152010
$DRIVERS_TOOLS/.evergreen/csfle/azurekms/delete-vm.sh
20162011
tasks:
20172012
- testazurekms-task
2018-
- name: test_atlas_task_group
2019-
setup_group:
2020-
- func: fetch source
2021-
- func: prepare resources
2022-
- command: subprocess.exec
2023-
params:
2024-
working_dir: src
2025-
binary: bash
2026-
add_expansions_to_env: true
2027-
args:
2028-
- ${DRIVERS_TOOLS}/.evergreen/atlas/setup-atlas-cluster.sh
2029-
- command: expansions.update
2030-
params:
2031-
file: src/atlas-expansion.yml
2032-
teardown_group:
2033-
- command: subprocess.exec
2034-
params:
2035-
working_dir: src
2036-
binary: bash
2037-
add_expansions_to_env: true
2038-
args:
2039-
- ${DRIVERS_TOOLS}/.evergreen/atlas/teardown-atlas-cluster.sh
2040-
setup_group_can_fail_task: true
2041-
setup_group_timeout_secs: 1800
2042-
tasks:
2043-
- test-aws-lambda-deployed
20442013

20452014
- name: testoidc_task_group
20462015
setup_group:
@@ -2275,24 +2244,12 @@ buildvariants:
22752244
tasks:
22762245
- name: "perf"
22772246

2278-
- name: rhel8-test-atlas
2279-
display_name: Atlas Cluster Tests
2280-
run_on: rhel80-large
2281-
tasks:
2282-
- test_atlas_task_group
2283-
22842247
- name: plain-auth-test
22852248
display_name: "PLAIN (LDAP) Auth test"
22862249
run_on: rhel80-small
22872250
tasks:
22882251
- name: "plain-auth-test"
22892252

2290-
- name: rhel80-test-search-indexes
2291-
display_name: Atlas Search Index Management Tests
2292-
run_on: rhel80-small
2293-
tasks:
2294-
- name: "test_atlas_task_group_search_indexes"
2295-
22962253
- name: "oidc-auth-test"
22972254
display_name: "OIDC Auth"
22982255
run_on: ubuntu2204-small
@@ -2347,23 +2304,19 @@ buildvariants:
23472304
tasks:
23482305
- name: ".ocsp"
23492306

2350-
- name: atlas-data-lake-test
2351-
display_name: "Atlas Data Lake test"
2352-
run_on: ubuntu2004-small
2353-
tasks:
2354-
- name: "atlas-data-lake-test"
2355-
2356-
- name: atlas-test
2357-
display_name: "Atlas test"
2307+
- name: "atlas-search-variant"
2308+
display_name: "Atlas Tests"
23582309
run_on: rhel80-small
23592310
tasks:
2360-
- name: "atlas-test"
2311+
- name: "atlas-deployed-task-group"
2312+
- name: "atlas-search-task"
2313+
- name: "atlas-connectivity-task"
23612314

2362-
- name: atlas-search-test
2363-
display_name: "Atlas Search test"
2364-
run_on: rhel80-small
2315+
- name: atlas-data-lake-test
2316+
display_name: "Atlas Data Lake test"
2317+
run_on: ubuntu2004-small
23652318
tasks:
2366-
- name: "atlas-search-test"
2319+
- name: "atlas-data-lake-task"
23672320

23682321
- name: "reactive-streams-tck-test"
23692322
display_name: "Reactive Streams TCK tests"

Diff for: ‎.evergreen/run-atlas-search-tests.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ echo "Running Atlas Search tests"
1616
./gradlew --stacktrace --info \
1717
-Dorg.mongodb.test.atlas.search=true \
1818
-Dorg.mongodb.test.uri=${MONGODB_URI} \
19-
driver-core:test --tests AggregatesSearchIntegrationTest --tests AggregatesVectorSearchIntegrationTest
19+
driver-core:test --tests AggregatesSearchIntegrationTest \
20+
--tests AggregatesBinaryVectorSearchIntegrationTest \
21+
--tests AggregatesSearchTest \

Diff for: ‎driver-core/src/main/com/mongodb/client/model/search/SearchOperator.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
import com.mongodb.client.model.geojson.Point;
2323
import org.bson.BsonArray;
2424
import org.bson.BsonBinary;
25-
import org.bson.BsonBoolean;
2625
import org.bson.BsonDocument;
2726
import org.bson.BsonNull;
27+
import org.bson.BsonBoolean;
2828
import org.bson.BsonType;
2929
import org.bson.Document;
3030
import org.bson.conversions.Bson;
@@ -573,14 +573,15 @@ static PhraseSearchOperator phrase(final Iterable<? extends SearchPath> paths, f
573573
}
574574

575575
/**
576-
* Returns a {@link SearchOperator} that performs a search using a special characters in the search string that can match any character.
576+
* Returns a {@link SearchOperator} that performs a search using a special
577+
* characters in the search string that can match any character.
577578
*
579+
* @param path The indexed field to be searched.
578580
* @param query The string to search for.
579-
* @param path The indexed field to be searched.
580581
* @return The requested {@link SearchOperator}.
581582
* @mongodb.atlas.manual atlas-search/wildcard/ wildcard operator
582583
*/
583-
static WildcardSearchOperator wildcard(final String query, final SearchPath path) {
584+
static WildcardSearchOperator wildcard(final SearchPath path, final String query) {
584585
return wildcard(singleton(notNull("query", query)), singleton(notNull("path", path)));
585586
}
586587

Diff for: ‎driver-core/src/main/com/mongodb/client/model/search/WildcardSearchOperator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import com.mongodb.annotations.Sealed;
2121

2222
/**
23-
* @see SearchOperator#wildcard(String, SearchPath)
23+
* @see SearchOperator#wildcard(SearchPath, String)
2424
* @see SearchOperator#wildcard(Iterable, Iterable)
2525
* @since 4.7
2626
*/

Diff for: ‎driver-core/src/main/com/mongodb/internal/connection/ClientMetadataHelper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ private enum Orchestrator {
224224
K8S("kubernetes") {
225225
@Override
226226
boolean isCurrentOrchestrator() {
227-
return System.getenv("KUBERNETES_SERVICE_HOST") != null;
227+
return FaasEnvironment.getEnv("KUBERNETES_SERVICE_HOST") != null;
228228
}
229229
},
230230
UNKNOWN(null);

Diff for: ‎driver-core/src/main/com/mongodb/internal/connection/FaasEnvironment.java

+21-9
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020

2121
import java.util.ArrayList;
2222
import java.util.Arrays;
23+
import java.util.HashMap;
2324
import java.util.List;
25+
import java.util.Map;
2426

2527
enum FaasEnvironment {
2628
AWS_LAMBDA("aws.lambda"),
@@ -29,21 +31,23 @@ enum FaasEnvironment {
2931
VERCEL("vercel"),
3032
UNKNOWN(null);
3133

34+
static final Map<String, String> ENV_OVERRIDES_FOR_TESTING = new HashMap<>();
35+
3236
static FaasEnvironment getFaasEnvironment() {
3337
List<FaasEnvironment> result = new ArrayList<>();
34-
String awsExecutionEnv = System.getenv("AWS_EXECUTION_ENV");
38+
String awsExecutionEnv = getEnv("AWS_EXECUTION_ENV");
3539

36-
if (System.getenv("VERCEL") != null) {
40+
if (getEnv("VERCEL") != null) {
3741
result.add(FaasEnvironment.VERCEL);
3842
}
3943
if ((awsExecutionEnv != null && awsExecutionEnv.startsWith("AWS_Lambda_"))
40-
|| System.getenv("AWS_LAMBDA_RUNTIME_API") != null) {
44+
|| getEnv("AWS_LAMBDA_RUNTIME_API") != null) {
4145
result.add(FaasEnvironment.AWS_LAMBDA);
4246
}
43-
if (System.getenv("FUNCTIONS_WORKER_RUNTIME") != null) {
47+
if (getEnv("FUNCTIONS_WORKER_RUNTIME") != null) {
4448
result.add(FaasEnvironment.AZURE_FUNC);
4549
}
46-
if (System.getenv("K_SERVICE") != null || System.getenv("FUNCTION_NAME") != null) {
50+
if (getEnv("K_SERVICE") != null || getEnv("FUNCTION_NAME") != null) {
4751
result.add(FaasEnvironment.GCP_FUNC);
4852
}
4953
// vercel takes precedence over aws.lambda
@@ -56,6 +60,14 @@ static FaasEnvironment getFaasEnvironment() {
5660
return result.get(0);
5761
}
5862

63+
@Nullable
64+
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);
69+
}
70+
5971
@Nullable
6072
private final String name;
6173

@@ -95,11 +107,11 @@ public Integer getMemoryMb() {
95107
public String getRegion() {
96108
switch (this) {
97109
case AWS_LAMBDA:
98-
return System.getenv("AWS_REGION");
110+
return getEnv("AWS_REGION");
99111
case GCP_FUNC:
100-
return System.getenv("FUNCTION_REGION");
112+
return getEnv("FUNCTION_REGION");
101113
case VERCEL:
102-
return System.getenv("VERCEL_REGION");
114+
return getEnv("VERCEL_REGION");
103115
default:
104116
return null;
105117
}
@@ -108,7 +120,7 @@ public String getRegion() {
108120
@Nullable
109121
private static Integer getEnvInteger(final String name) {
110122
try {
111-
String value = System.getenv(name);
123+
String value = getEnv(name);
112124
return Integer.parseInt(value);
113125
} catch (NumberFormatException e) {
114126
return null;

Diff for: ‎driver-core/src/test/functional/com/mongodb/client/WithWrapper.java

+2-16
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,11 @@
1616

1717
package com.mongodb.client;
1818

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

21-
import java.lang.reflect.Field;
2222
import java.util.Map;
2323

24-
import static java.lang.System.getenv;
25-
2624
@FunctionalInterface
2725
public interface WithWrapper {
2826

@@ -34,7 +32,7 @@ static WithWrapper withWrapper() {
3432

3533
default WithWrapper withEnvironmentVariable(final String name, @Nullable final String value) {
3634
return runnable -> {
37-
Map<String, String> innerMap = getEnvInnerMap();
35+
Map<String, String> innerMap = FaasEnvironmentAccessor.getFaasEnvMap();
3836
String original = innerMap.get(name);
3937
if (value == null) {
4038
innerMap.remove(name);
@@ -65,16 +63,4 @@ default WithWrapper withSystemProperty(final String name, final String value) {
6563
};
6664
}
6765

68-
static Map<String, String> getEnvInnerMap() {
69-
try {
70-
Map<String, String> env = getenv();
71-
Field field = env.getClass().getDeclaredField("m");
72-
field.setAccessible(true);
73-
@SuppressWarnings("unchecked")
74-
Map<String, String> result = (Map<String, String>) field.get(env);
75-
return result;
76-
} catch (IllegalAccessException | NoSuchFieldException e) {
77-
throw new RuntimeException(e);
78-
}
79-
}
8066
}

Diff for: ‎driver-core/src/test/functional/com/mongodb/client/model/search/AggregatesBinaryVectorSearchIntegrationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
import com.mongodb.client.model.SearchIndexType;
2323
import com.mongodb.client.test.CollectionHelper;
2424
import com.mongodb.internal.operation.SearchIndexRequest;
25+
import org.bson.BinaryVector;
2526
import org.bson.BsonDocument;
2627
import org.bson.Document;
27-
import org.bson.BinaryVector;
2828
import org.bson.codecs.DocumentCodec;
2929
import org.bson.conversions.Bson;
3030
import org.junit.jupiter.api.AfterAll;

Diff for: ‎driver-core/src/test/functional/com/mongodb/client/model/search/AggregatesSearchIntegrationTest.java

+3
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@
229229
* </tr>
230230
* </tbody>
231231
* </table>
232+
* <p>
233+
* Use this class when needing to test against MFLIX specifically. Otherwise,
234+
* see AggregatesSearchTest.
232235
*/
233236
final class AggregatesSearchIntegrationTest {
234237
private static final MongoNamespace MFLIX_MOVIES_NS = new MongoNamespace("sample_mflix", "movies");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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.connection;
18+
19+
import java.util.Map;
20+
21+
/**
22+
* In the same package as FaasEnvironment, to access package-private
23+
*/
24+
public final class FaasEnvironmentAccessor {
25+
private FaasEnvironmentAccessor() {
26+
}
27+
28+
public static Map<String, String> getFaasEnvMap() {
29+
return FaasEnvironment.ENV_OVERRIDES_FOR_TESTING;
30+
}
31+
}

Diff for: ‎driver-core/src/test/unit/com/mongodb/client/model/search/SearchOperatorTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -833,8 +833,8 @@ void wildcard() {
833833
.append("path", fieldPath("fieldName").toBsonValue())
834834
),
835835
SearchOperator.wildcard(
836-
"term",
837-
fieldPath("fieldName"))
836+
fieldPath("fieldName"), "term"
837+
)
838838
.toBsonDocument()
839839
),
840840
() -> assertEquals(

Diff for: ‎driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/gridfs/GridFSBucketImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ public GridFSUploadPublisher<Void> uploadFromPublisher(final ClientSession clien
208208
final Publisher<ByteBuffer> source,
209209
final GridFSUploadOptions options) {
210210
return createGridFSUploadPublisher(chunkSizeBytes, filesCollection, chunksCollection,
211-
notNull("clientSession", clientSession), new BsonObjectId(), filename, options, source);
211+
notNull("clientSession", clientSession), id, filename, options, source);
212212
}
213213

214214
@Override

Diff for: ‎driver-scala/src/main/scala/org/mongodb/scala/model/search/SearchOperator.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ object SearchOperator {
429429
* @return The requested `SearchOperator`.
430430
* @see [[https://www.mongodb.com/docs/atlas/atlas-search/wildcard/ wildcard operator]]
431431
*/
432-
def wildcard(query: String, path: SearchPath): WildcardSearchOperator = JSearchOperator.wildcard(query, path)
432+
def wildcard(query: String, path: SearchPath): WildcardSearchOperator = JSearchOperator.wildcard(path, query)
433433

434434
/**
435435
* Returns a `SearchOperator` that enables queries which use special characters in the search string that can match any character.

Diff for: ‎driver-sync/src/test/functional/com/mongodb/client/DatabaseTestCase.java

+2-21
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@
1616

1717
package com.mongodb.client;
1818

19-
import com.mongodb.MongoNamespace;
2019
import com.mongodb.client.test.CollectionHelper;
2120
import com.mongodb.internal.connection.ServerHelper;
22-
import org.bson.BsonDocument;
23-
import org.bson.BsonDocumentWrapper;
2421
import org.bson.Document;
2522
import org.bson.codecs.DocumentCodec;
2623
import org.junit.jupiter.api.AfterEach;
@@ -40,7 +37,7 @@ public class DatabaseTestCase {
4037

4138
@BeforeEach
4239
public void setUp() {
43-
client = getMongoClient();
40+
client = getMongoClient();
4441
database = client.getDatabase(getDefaultDatabaseName());
4542
collection = database.getCollection(getClass().getName());
4643
collection.drop();
@@ -58,23 +55,7 @@ public void tearDown() {
5855
}
5956
}
6057

61-
protected String getDatabaseName() {
62-
return database.getName();
63-
}
64-
65-
protected String getCollectionName() {
66-
return collection.getNamespace().getCollectionName();
67-
}
68-
69-
protected MongoNamespace getNamespace() {
70-
return collection.getNamespace();
71-
}
72-
7358
protected CollectionHelper<Document> getCollectionHelper() {
74-
return new CollectionHelper<>(new DocumentCodec(), getNamespace());
75-
}
76-
77-
protected BsonDocument wrap(final Document document) {
78-
return new BsonDocumentWrapper<>(document, new DocumentCodec());
59+
return new CollectionHelper<>(new DocumentCodec(), collection.getNamespace());
7960
}
8061
}

Diff for: ‎driver-sync/src/test/functional/com/mongodb/client/Fixture.java

+19-26
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.mongodb.client;
1818

19+
import com.mongodb.ClusterFixture;
1920
import com.mongodb.ConnectionString;
2021
import com.mongodb.MongoClientSettings;
2122
import com.mongodb.ServerAddress;
@@ -24,7 +25,6 @@
2425
import java.util.List;
2526
import java.util.concurrent.TimeUnit;
2627

27-
import static com.mongodb.ClusterFixture.getConnectionString;
2828
import static com.mongodb.ClusterFixture.getMultiMongosConnectionString;
2929
import static com.mongodb.ClusterFixture.getServerApi;
3030
import static com.mongodb.internal.connection.ClusterDescriptionHelper.getPrimaries;
@@ -34,7 +34,6 @@
3434
* Helper class for the acceptance tests.
3535
*/
3636
public final class Fixture {
37-
private static final String DEFAULT_DATABASE_NAME = "JavaDriverTest";
3837
private static final long MIN_HEARTBEAT_FREQUENCY_MS = 50L;
3938

4039
private static MongoClient mongoClient;
@@ -44,10 +43,23 @@ private Fixture() {
4443
}
4544

4645
public static synchronized MongoClient getMongoClient() {
47-
if (mongoClient == null) {
48-
mongoClient = MongoClients.create(getMongoClientSettings());
49-
Runtime.getRuntime().addShutdownHook(new ShutdownHook());
46+
if (mongoClient != null) {
47+
return mongoClient;
5048
}
49+
MongoClientSettings mongoClientSettings = getMongoClientSettings();
50+
mongoClient = MongoClients.create(mongoClientSettings);
51+
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
52+
synchronized (Fixture.class) {
53+
if (mongoClient == null) {
54+
return;
55+
}
56+
if (defaultDatabase != null) {
57+
defaultDatabase.drop();
58+
}
59+
mongoClient.close();
60+
mongoClient = null;
61+
}
62+
}));
5163
return mongoClient;
5264
}
5365

@@ -59,34 +71,15 @@ public static synchronized MongoDatabase getDefaultDatabase() {
5971
}
6072

6173
public static String getDefaultDatabaseName() {
62-
return DEFAULT_DATABASE_NAME;
63-
}
64-
65-
static class ShutdownHook extends Thread {
66-
@Override
67-
public void run() {
68-
synchronized (Fixture.class) {
69-
if (mongoClient != null) {
70-
if (defaultDatabase != null) {
71-
defaultDatabase.drop();
72-
}
73-
mongoClient.close();
74-
mongoClient = null;
75-
}
76-
}
77-
}
74+
return ClusterFixture.getDefaultDatabaseName();
7875
}
7976

8077
public static MongoClientSettings getMongoClientSettings() {
8178
return getMongoClientSettingsBuilder().build();
8279
}
8380

84-
public static MongoClientSettings getMultiMongosMongoClientSettings() {
85-
return getMultiMongosMongoClientSettingsBuilder().build();
86-
}
87-
8881
public static MongoClientSettings.Builder getMongoClientSettingsBuilder() {
89-
return getMongoClientSettings(getConnectionString());
82+
return getMongoClientSettings(ClusterFixture.getConnectionString());
9083
}
9184

9285
public static MongoClientSettings.Builder getMultiMongosMongoClientSettingsBuilder() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
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.client.model.search;
18+
19+
import com.mongodb.client.AggregateIterable;
20+
import com.mongodb.client.MongoClient;
21+
import com.mongodb.client.MongoCollection;
22+
import com.mongodb.client.MongoDatabase;
23+
import com.mongodb.client.model.SearchIndexModel;
24+
import com.mongodb.internal.connection.ServerHelper;
25+
import org.bson.BsonArray;
26+
import org.bson.BsonDocument;
27+
import org.bson.Document;
28+
import org.bson.codecs.DecoderContext;
29+
import org.bson.conversions.Bson;
30+
import org.junit.jupiter.api.AfterAll;
31+
import org.junit.jupiter.api.BeforeAll;
32+
import org.junit.jupiter.api.Test;
33+
34+
import java.util.ArrayList;
35+
import java.util.Arrays;
36+
import java.util.List;
37+
import java.util.concurrent.TimeUnit;
38+
import java.util.stream.Collectors;
39+
import java.util.stream.StreamSupport;
40+
41+
import static com.mongodb.ClusterFixture.isAtlasSearchTest;
42+
import static com.mongodb.ClusterFixture.serverVersionAtLeast;
43+
import static com.mongodb.MongoClientSettings.getDefaultCodecRegistry;
44+
import static com.mongodb.client.Fixture.getMongoClient;
45+
import static com.mongodb.client.Fixture.getPrimary;
46+
import static com.mongodb.client.model.Aggregates.search;
47+
import static com.mongodb.client.model.Aggregates.sort;
48+
import static com.mongodb.client.model.Sorts.ascending;
49+
import static com.mongodb.client.model.search.SearchOptions.searchOptions;
50+
import static com.mongodb.client.model.search.SearchPath.fieldPath;
51+
import static org.junit.jupiter.api.Assertions.assertEquals;
52+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
53+
54+
public class AggregatesSearchFunctionalTest {
55+
public static final String ATLAS_SEARCH_DATABASE = "javaVectorSearchTest";
56+
private static MongoClient client;
57+
private static MongoDatabase database;
58+
private static MongoCollection<Document> collection;
59+
private static String searchIndexName;
60+
61+
@BeforeAll
62+
public static void beforeAll() {
63+
assumeTrue(isAtlasSearchTest());
64+
assumeTrue(serverVersionAtLeast(8, 0));
65+
66+
client = getMongoClient();
67+
database = client.getDatabase(ATLAS_SEARCH_DATABASE);
68+
String collectionName = AggregatesSearchFunctionalTest.class.getName();
69+
collection = database.getCollection(collectionName);
70+
collection.drop();
71+
72+
// We insert documents first. The ensuing indexing guarantees that all
73+
// data present at the time indexing commences will be indexed before
74+
// the index enters the READY state.
75+
insertDocuments("[\n"
76+
+ " { _id: 1 },\n"
77+
+ " { _id: 2, title: null },\n"
78+
+ " { _id: 3, title: 'test' },\n"
79+
+ " { _id: 4, title: ['test', 'xyz'] },\n"
80+
+ " { _id: 5, title: 'not test' },\n"
81+
+ " { _id: 6, description: 'desc 1' },\n"
82+
+ " { _id: 7, description: 'desc 8' },\n"
83+
+ " { _id: 8, summary: 'summary 1 one five' },\n"
84+
+ " { _id: 9, summary: 'summary 2 one two three four five' },\n"
85+
+ "]");
86+
87+
searchIndexName = "not_default";
88+
// Index creation can take disproportionately long, so we create it once
89+
// for all tests.
90+
// We set dynamic to true to index unspecified fields. Different kinds
91+
// of fields are needed for different tests.
92+
collection.createSearchIndexes(Arrays.asList(new SearchIndexModel(searchIndexName, Document.parse(
93+
"{\n"
94+
+ " \"mappings\": {\n"
95+
+ " \"dynamic\": true,\n"
96+
+ " \"fields\": {\n"
97+
+ " \"title\": {\n"
98+
+ " \"type\": \"token\"\n"
99+
+ " },\n"
100+
+ " \"description\": {\n"
101+
+ " \"analyzer\": \"lucene.keyword\","
102+
+ " \"type\": \"string\"\n"
103+
+ " }\n"
104+
+ " }\n"
105+
+ " }\n"
106+
+ "}"))));
107+
waitForIndex(collection, searchIndexName);
108+
}
109+
110+
@AfterAll
111+
public static void afterAll() {
112+
if (collection != null) {
113+
collection.drop();
114+
}
115+
try {
116+
ServerHelper.checkPool(getPrimary());
117+
} catch (InterruptedException e) {
118+
// ignore
119+
}
120+
}
121+
122+
@Test
123+
public void testExists() {
124+
List<Bson> pipeline = Arrays.asList(
125+
search(SearchOperator.exists(fieldPath("title")),
126+
searchOptions().index(searchIndexName)));
127+
assertResults(pipeline, "[\n"
128+
+ " { _id: 2, title: null },\n"
129+
+ " { _id: 3, title: 'test' },\n"
130+
+ " { _id: 4, title: ['test', 'xyz'] },\n"
131+
+ " { _id: 5, title: 'not test' },\n"
132+
+ "]");
133+
}
134+
135+
@Test
136+
public void testEquals() {
137+
List<Bson> pipeline1 = Arrays.asList(
138+
search(SearchOperator.equals(fieldPath("title"), "test"),
139+
searchOptions().index(searchIndexName)));
140+
assertResults(pipeline1, "[\n"
141+
+ " { _id: 3, title: 'test' }\n"
142+
+ " { _id: 4, title: ['test', 'xyz'] }\n"
143+
+ "]");
144+
145+
// equals null does not match non-existent fields
146+
List<Bson> pipeline2 = Arrays.asList(
147+
search(SearchOperator.equalsNull(fieldPath("title")),
148+
searchOptions().index(searchIndexName)));
149+
assertResults(pipeline2, "[\n"
150+
+ " { _id: 2, title: null }\n"
151+
+ "]");
152+
}
153+
154+
@Test
155+
public void testMoreLikeThis() {
156+
List<Bson> pipeline = Arrays.asList(
157+
search(SearchOperator.moreLikeThis(Document.parse("{ summary: 'summary' }").toBsonDocument()),
158+
searchOptions().index(searchIndexName)));
159+
assertResults(pipeline, "[\n"
160+
+ " { _id: 8, summary: 'summary 1 one five' },\n"
161+
+ " { _id: 9, summary: 'summary 2 one two three four five' },\n"
162+
+ "]");
163+
}
164+
165+
@Test
166+
public void testRegex() {
167+
List<Bson> pipeline = Arrays.asList(
168+
search(SearchOperator.regex(fieldPath("description"), "des[c]+ <1-4>"),
169+
searchOptions().index(searchIndexName)));
170+
assertResults(pipeline, "[\n"
171+
+ " { _id: 6, description: 'desc 1' },\n"
172+
+ "]");
173+
}
174+
175+
@Test
176+
public void testWildcard() {
177+
List<Bson> pipeline = Arrays.asList(
178+
search(SearchOperator.wildcard(fieldPath("description"), "desc*"),
179+
searchOptions().index(searchIndexName)));
180+
assertResults(pipeline, "[\n"
181+
+ " { _id: 6, description: 'desc 1' },\n"
182+
+ " { _id: 7, description: 'desc 8' },\n"
183+
+ "]");
184+
}
185+
186+
@Test
187+
public void testPhrase() {
188+
List<Bson> pipeline = Arrays.asList(
189+
search(SearchOperator.phrase(fieldPath("summary"), "one five").slop(2),
190+
searchOptions().index(searchIndexName)));
191+
assertResults(pipeline, "[\n"
192+
+ " { _id: 8, summary: 'summary 1 one five' },\n"
193+
+ "]");
194+
}
195+
196+
@Test
197+
public void testQueryString() {
198+
List<Bson> pipeline = Arrays.asList(
199+
search(SearchOperator.queryString(fieldPath("summary"), "summary: one AND summary: three"),
200+
searchOptions().index(searchIndexName)));
201+
assertResults(pipeline, "[\n"
202+
+ " { _id: 9, summary: 'summary 2 one two three four five' },\n"
203+
+ "]");
204+
}
205+
206+
private static void insertDocuments(final String s) {
207+
List<Document> documents = BsonArray.parse(s).stream()
208+
.map(v -> new Document(v.asDocument()))
209+
.collect(Collectors.toList());
210+
collection.insertMany(documents);
211+
}
212+
213+
private static void assertResults(final List<Bson> pipeline, final String expectedResultsAsString) {
214+
ArrayList<Bson> pipeline2 = new ArrayList<>(pipeline);
215+
pipeline2.add(sort(ascending("_id")));
216+
217+
List<BsonDocument> expectedResults = parseToList(expectedResultsAsString);
218+
List<BsonDocument> actualResults = aggregate(pipeline2);
219+
assertEquals(expectedResults, actualResults);
220+
}
221+
222+
private static List<BsonDocument> aggregate(final List<Bson> stages) {
223+
AggregateIterable<Document> result = collection.aggregate(stages);
224+
List<BsonDocument> results = new ArrayList<>();
225+
result.forEach(r -> results.add(r.toBsonDocument()));
226+
return results;
227+
}
228+
229+
public static List<BsonDocument> parseToList(final String s) {
230+
return BsonArray.parse(s).stream().map(v -> toBsonDocument(v.asDocument())).collect(Collectors.toList());
231+
}
232+
233+
public static BsonDocument toBsonDocument(final BsonDocument bsonDocument) {
234+
return getDefaultCodecRegistry().get(BsonDocument.class).decode(bsonDocument.asBsonReader(), DecoderContext.builder().build());
235+
}
236+
237+
public static <T> boolean waitForIndex(final MongoCollection<T> collection, final String indexName) {
238+
long startTime = System.nanoTime();
239+
long timeoutNanos = TimeUnit.SECONDS.toNanos(60);
240+
while (System.nanoTime() - startTime < timeoutNanos) {
241+
Document indexRecord = StreamSupport.stream(collection.listSearchIndexes().spliterator(), false)
242+
.filter(index -> indexName.equals(index.getString("name")))
243+
.findAny().orElse(null);
244+
if (indexRecord != null) {
245+
if ("FAILED".equals(indexRecord.getString("status"))) {
246+
throw new RuntimeException("Search index has failed status.");
247+
}
248+
if (indexRecord.getBoolean("queryable")) {
249+
return true;
250+
}
251+
}
252+
try {
253+
Thread.sleep(100); // busy-wait, avoid in production
254+
} catch (InterruptedException e) {
255+
Thread.currentThread().interrupt();
256+
throw new RuntimeException(e);
257+
}
258+
}
259+
return false;
260+
}
261+
262+
}

0 commit comments

Comments
 (0)
Please sign in to comment.