summaryrefslogtreecommitdiff
path: root/src/mongo/client
diff options
context:
space:
mode:
authorjannaerin <golden.janna@gmail.com>2020-04-21 13:51:15 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-04-24 16:10:48 +0000
commit76823e76d597b52e66539580474c93be02fe2c6e (patch)
treebf95197be18b9b677adda6aa4c79bbe851a17511 /src/mongo/client
parent9ccfe0715fd23452c285471322529da8adec86e2 (diff)
downloadmongo-76823e76d597b52e66539580474c93be02fe2c6e.tar.gz
SERVER-43333 Ingest drivers server selection tests
Diffstat (limited to 'src/mongo/client')
-rw-r--r--src/mongo/client/sdam/SConscript33
-rw-r--r--src/mongo/client/sdam/json_test_arg_parser.cpp99
-rw-r--r--src/mongo/client/sdam/json_test_arg_parser.h90
-rw-r--r--src/mongo/client/sdam/json_test_runner_cli_options.idl (renamed from src/mongo/client/sdam/sdam_json_test_runner_cli_options.idl)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/README.rst (renamed from src/mongo/client/sdam/json_tests/README.rst)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/compatible.json (renamed from src/mongo/client/sdam/json_tests/rs/compatible.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/compatible_unknown.json (renamed from src/mongo/client/sdam/json_tests/rs/compatible_unknown.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_arbiters.json (renamed from src/mongo/client/sdam/json_tests/rs/discover_arbiters.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_passives.json (renamed from src/mongo/client/sdam/json_tests/rs/discover_passives.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_primary.json (renamed from src/mongo/client/sdam/json_tests/rs/discover_primary.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_secondary.json (renamed from src/mongo/client/sdam/json_tests/rs/discover_secondary.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/discovery.json (renamed from src/mongo/client/sdam/json_tests/rs/discovery.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/discovery.json.notused (renamed from src/mongo/client/sdam/json_tests/rs/discovery.json.notused)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/equal_electionids.json (renamed from src/mongo/client/sdam/json_tests/rs/equal_electionids.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/ghost_discovered.json (renamed from src/mongo/client/sdam/json_tests/rs/ghost_discovered.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/hosts_differ_from_seeds.json (renamed from src/mongo/client/sdam/json_tests/rs/hosts_differ_from_seeds.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_arbiter.json (renamed from src/mongo/client/sdam/json_tests/rs/incompatible_arbiter.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_ghost.json (renamed from src/mongo/client/sdam/json_tests/rs/incompatible_ghost.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_other.json (renamed from src/mongo/client/sdam/json_tests/rs/incompatible_other.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/ls_timeout.json (renamed from src/mongo/client/sdam/json_tests/rs/ls_timeout.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/member_reconfig.json (renamed from src/mongo/client/sdam/json_tests/rs/member_reconfig.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/member_standalone.json (renamed from src/mongo/client/sdam/json_tests/rs/member_standalone.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary.json (renamed from src/mongo/client/sdam/json_tests/rs/new_primary.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_new_electionid.json (renamed from src/mongo/client/sdam/json_tests/rs/new_primary_new_electionid.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_new_setversion.json (renamed from src/mongo/client/sdam/json_tests/rs/new_primary_new_setversion.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_wrong_set_name.json (renamed from src/mongo/client/sdam/json_tests/rs/new_primary_wrong_set_name.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/non_rs_member.json (renamed from src/mongo/client/sdam/json_tests/rs/non_rs_member.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/normalize_case.json.disabled (renamed from src/mongo/client/sdam/json_tests/rs/normalize_case.json.disabled)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/normalize_case_me.json.disabled (renamed from src/mongo/client/sdam/json_tests/rs/normalize_case_me.json.disabled)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/null_election_id.json (renamed from src/mongo/client/sdam/json_tests/rs/null_election_id.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_ghost.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_becomes_ghost.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_mongos.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_becomes_mongos.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_standalone.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_becomes_standalone.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_changes_set_name.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_changes_set_name.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_disconnect.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect_electionid.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_disconnect_electionid.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect_setversion.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_disconnect_setversion.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_hint_from_secondary_with_mismatched_me.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_hint_from_secondary_with_mismatched_me.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_mismatched_me.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_mismatched_me.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_reports_new_member.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_reports_new_member.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_to_no_primary_mismatched_me.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_to_no_primary_mismatched_me.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_wrong_set_name.json (renamed from src/mongo/client/sdam/json_tests/rs/primary_wrong_set_name.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/response_from_removed.json (renamed from src/mongo/client/sdam/json_tests/rs/response_from_removed.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/rsother_discovered.json (renamed from src/mongo/client/sdam/json_tests/rs/rsother_discovered.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/sec_not_auth.json (renamed from src/mongo/client/sdam/json_tests/rs/sec_not_auth.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_ignore_ok_0.json (renamed from src/mongo/client/sdam/json_tests/rs/secondary_ignore_ok_0.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_mismatched_me.json (renamed from src/mongo/client/sdam/json_tests/rs/secondary_mismatched_me.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_wrong_set_name.json (renamed from src/mongo/client/sdam/json_tests/rs/secondary_wrong_set_name.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_wrong_set_name_with_primary.json (renamed from src/mongo/client/sdam/json_tests/rs/secondary_wrong_set_name_with_primary.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/setversion_without_electionid.json (renamed from src/mongo/client/sdam/json_tests/rs/setversion_without_electionid.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/stepdown_change_set_name.json (renamed from src/mongo/client/sdam/json_tests/rs/stepdown_change_set_name.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/too_new.json (renamed from src/mongo/client/sdam/json_tests/rs/too_new.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/too_old.json (renamed from src/mongo/client/sdam/json_tests/rs/too_old.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/unexpected_mongos.json (renamed from src/mongo/client/sdam/json_tests/rs/unexpected_mongos.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/use_setversion_without_electionid.json (renamed from src/mongo/client/sdam/json_tests/rs/use_setversion_without_electionid.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/rs/wrong_set_name.json (renamed from src/mongo/client/sdam/json_tests/rs/wrong_set_name.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/sharded/compatible.json (renamed from src/mongo/client/sdam/json_tests/sharded/compatible.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/sharded/ls_timeout_mongos.json (renamed from src/mongo/client/sdam/json_tests/sharded/ls_timeout_mongos.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/sharded/mongos_disconnect.json (renamed from src/mongo/client/sdam/json_tests/sharded/mongos_disconnect.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/sharded/multiple_mongoses.json (renamed from src/mongo/client/sdam/json_tests/sharded/multiple_mongoses.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/sharded/non_mongos_removed.json (renamed from src/mongo/client/sdam/json_tests/sharded/non_mongos_removed.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/sharded/normalize_uri_case.json.disabled (renamed from src/mongo/client/sdam/json_tests/sharded/normalize_uri_case.json.disabled)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/sharded/too_new.json (renamed from src/mongo/client/sdam/json_tests/sharded/too_new.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/sharded/too_old.json (renamed from src/mongo/client/sdam/json_tests/sharded/too_old.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/compatible.json (renamed from src/mongo/client/sdam/json_tests/single/compatible.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_external_ip.json (renamed from src/mongo/client/sdam/json_tests/single/direct_connection_external_ip.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_mongos.json (renamed from src/mongo/client/sdam/json_tests/single/direct_connection_mongos.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rsarbiter.json (renamed from src/mongo/client/sdam/json_tests/single/direct_connection_rsarbiter.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rsprimary.json (renamed from src/mongo/client/sdam/json_tests/single/direct_connection_rsprimary.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rssecondary.json (renamed from src/mongo/client/sdam/json_tests/single/direct_connection_rssecondary.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_slave.json (renamed from src/mongo/client/sdam/json_tests/single/direct_connection_slave.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_standalone.json (renamed from src/mongo/client/sdam/json_tests/single/direct_connection_standalone.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/ls_timeout_standalone.json (renamed from src/mongo/client/sdam/json_tests/single/ls_timeout_standalone.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/not_ok_response.json (renamed from src/mongo/client/sdam/json_tests/single/not_ok_response.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/standalone_removed.json (renamed from src/mongo/client/sdam/json_tests/single/standalone_removed.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/too_new.json (renamed from src/mongo/client/sdam/json_tests/single/too_new.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/too_old.json (renamed from src/mongo/client/sdam/json_tests/single/too_old.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/sdam_tests/single/unavailable_seed.json (renamed from src/mongo/client/sdam/json_tests/single/unavailable_seed.json)0
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/README.rst67
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/rtt/first_value.json5
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/rtt/first_value_zero.json5
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_1.json5
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_2.json5
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_3.json5
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_4.json5
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_5.json5
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest.json60
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest_multiple.json68
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest_non_matching.json34
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PossiblePrimary.json21
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PossiblePrimaryNearest.json21
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Primary.json29
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PrimaryPreferred.json58
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.json34
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary.json60
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/SecondaryPreferred.json60
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.json34
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_multi_tags.json60
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_multi_tags2.json60
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_non_matching.json34
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest.json76
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest_multiple.json84
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest_non_matching.json42
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Primary.json55
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/PrimaryPreferred.json58
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.json60
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Secondary.json68
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred.json68
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred_non_matching.json60
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred_tags.json52
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Secondary_non_matching.json42
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/Single/read/SecondaryPreferred.json44
-rw-r--r--src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/Unknown/read/SecondaryPreferred.json17
-rw-r--r--src/mongo/client/sdam/sdam_datatypes.cpp18
-rw-r--r--src/mongo/client/sdam/sdam_datatypes.h1
-rw-r--r--src/mongo/client/sdam/sdam_json_test_runner.cpp110
-rw-r--r--src/mongo/client/sdam/server_selection_json_test_runner.cpp506
-rw-r--r--src/mongo/client/sdam/topology_description.cpp4
118 files changed, 2210 insertions, 112 deletions
diff --git a/src/mongo/client/sdam/SConscript b/src/mongo/client/sdam/SConscript
index 4d7c01ac4b9..ff9f92e6166 100644
--- a/src/mongo/client/sdam/SConscript
+++ b/src/mongo/client/sdam/SConscript
@@ -31,17 +31,42 @@ env.Library(
sdam_json_test = env.Program(
target='sdam_json_test',
source=[
- 'sdam_json_test_runner.cpp',
- env.Idlc('sdam_json_test_runner_cli_options.idl')[0]],
+ 'sdam_json_test_runner.cpp'],
AIB_COMPONENT="sdam-json-test",
LIBDEPS=[
'sdam',
'sdam_test',
+ 'json_test',
'$BUILD_DIR/mongo/util/clock_source_mock',
- '$BUILD_DIR/mongo/client/connection_string',
- '$BUILD_DIR/mongo/util/options_parser/options_parser'],
+ '$BUILD_DIR/mongo/client/connection_string'],
)[0]
+server_selection_json_test = env.Program(
+ target='server_selection_json_test',
+ source=[
+ 'server_selection_json_test_runner.cpp'],
+ AIB_COMPONENT="server-selection-json-test",
+ LIBDEPS=[
+ 'sdam',
+ 'sdam_test',
+ 'json_test',
+ '$BUILD_DIR/mongo/util/clock_source_mock',
+ '$BUILD_DIR/mongo/client/connection_string'],
+)[0]
+
+env.Library(
+ target='json_test',
+ source=[
+ 'json_test_arg_parser.cpp',
+ env.Idlc('json_test_runner_cli_options.idl')[0],
+ ],
+ LIBDEPS=[
+ 'sdam',
+ '$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/util/options_parser/options_parser',
+ ],
+)
+
env.Library(
target='sdam_test',
source=[
diff --git a/src/mongo/client/sdam/json_test_arg_parser.cpp b/src/mongo/client/sdam/json_test_arg_parser.cpp
new file mode 100644
index 00000000000..d29f550ea25
--- /dev/null
+++ b/src/mongo/client/sdam/json_test_arg_parser.cpp
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2020-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault
+
+#include "mongo/client/sdam/json_test_arg_parser.h"
+
+#include "mongo/logger/logger.h"
+#include "mongo/logv2/log.h"
+#include "mongo/util/options_parser/environment.h"
+#include "mongo/util/options_parser/option_section.h"
+#include "mongo/util/options_parser/options_parser.h"
+
+namespace moe = mongo::optionenvironment;
+
+namespace mongo::sdam {
+
+ArgParser::ArgParser(int argc, char* argv[]) {
+ moe::OptionsParser parser;
+ moe::Environment environment;
+ moe::OptionSection options;
+
+ Status ret = addCliOptions(&options);
+ if (!ret.isOK()) {
+ std::cerr << "Unexpected error adding cli options: " << ret.toString() << std::endl;
+ MONGO_UNREACHABLE;
+ }
+
+ ret = parser.run(options, toStringVector(argc, argv), {}, &environment);
+ if (argc <= 1 || !ret.isOK() || environment.count("help")) {
+ if (!ret.isOK()) {
+ std::cerr << "An error occurred: " << ret.toString() << std::endl;
+ }
+ printHelpAndExit(argv[0], options.helpString());
+ }
+
+ const auto exitIfError = [](Status status) {
+ if (!status.isOK()) {
+ std::cerr << "An error occurred: " << status.toString() << std::endl;
+ std::exit(kArgParseExitCode);
+ }
+ };
+
+ if (environment.count(kSourceDirOption)) {
+ ret = environment.get(kSourceDirOption, &_sourceDirectory);
+ exitIfError(ret);
+ }
+
+ if (environment.count(moe::Key(kFilterOption))) {
+ ret = environment.get(moe::Key(kFilterOption), &_testFilters);
+ exitIfError(ret);
+ }
+
+ if (environment.count(moe::Key(kVerbose))) {
+ std::string value;
+ ret = environment.get(moe::Key(kVerbose), &value);
+ if (!ret.isOK())
+ exitIfError(ret);
+ _verbose = value.size() + 1;
+ }
+}
+
+void ArgParser::LogParams() const {
+ LOGV2(20199, "Verbosity: {verbose}", "verbose"_attr = _verbose);
+ LOGV2(20200, "Source Directory: {sourceDirectory}", "sourceDirectory"_attr = _sourceDirectory);
+ if (_testFilters.size()) {
+ LOGV2(20201,
+ "Filters: {boost_join_testFilters}",
+ "boost_join_testFilters"_attr = boost::join(_testFilters, ", "));
+ }
+}
+
+
+}; // namespace mongo::sdam
diff --git a/src/mongo/client/sdam/json_test_arg_parser.h b/src/mongo/client/sdam/json_test_arg_parser.h
new file mode 100644
index 00000000000..c621434fec4
--- /dev/null
+++ b/src/mongo/client/sdam/json_test_arg_parser.h
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2020-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include <fstream>
+#include <iostream>
+#include <memory>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/format.hpp>
+#include <boost/optional/optional_io.hpp>
+
+#include "mongo/client/sdam/json_test_runner_cli_options_gen.h"
+
+
+namespace mongo::sdam {
+
+class ArgParser {
+public:
+ ArgParser(int argc, char* argv[]);
+
+ void LogParams() const;
+
+ const std::string& SourceDirectory() const {
+ return _sourceDirectory;
+ }
+
+ const std::vector<std::string>& TestFilters() const {
+ return _testFilters;
+ }
+
+ int Verbose() const {
+ return _verbose;
+ }
+
+private:
+ constexpr static auto kSourceDirOption = "source-dir";
+ constexpr static auto kSourceDirDefault = ".";
+
+ constexpr static auto kFilterOption = "filter";
+
+ constexpr static int kHelpExitCode = 0;
+ constexpr static int kArgParseExitCode = 1024;
+
+ constexpr static auto kVerbose = "verbose";
+
+ std::string _sourceDirectory = kSourceDirDefault;
+ std::vector<std::string> _testFilters;
+ int _verbose = 0;
+
+ void printHelpAndExit(char* programName, const std::string desc) {
+ std::cout << programName << ":" << std::endl << desc << std::endl;
+ std::exit(kHelpExitCode);
+ }
+
+ std::vector<std::string> toStringVector(int n, char** array) {
+ std::vector<std::string> result;
+ for (int i = 0; i < n; ++i)
+ result.push_back(array[i]);
+ return result;
+ }
+};
+}; // namespace mongo::sdam
diff --git a/src/mongo/client/sdam/sdam_json_test_runner_cli_options.idl b/src/mongo/client/sdam/json_test_runner_cli_options.idl
index 3b1a643ae03..3b1a643ae03 100644
--- a/src/mongo/client/sdam/sdam_json_test_runner_cli_options.idl
+++ b/src/mongo/client/sdam/json_test_runner_cli_options.idl
diff --git a/src/mongo/client/sdam/json_tests/README.rst b/src/mongo/client/sdam/json_tests/sdam_tests/README.rst
index f8bd43f8d4d..f8bd43f8d4d 100644
--- a/src/mongo/client/sdam/json_tests/README.rst
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/README.rst
diff --git a/src/mongo/client/sdam/json_tests/rs/compatible.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/compatible.json
index d670770f6d1..d670770f6d1 100644
--- a/src/mongo/client/sdam/json_tests/rs/compatible.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/compatible.json
diff --git a/src/mongo/client/sdam/json_tests/rs/compatible_unknown.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/compatible_unknown.json
index 1105da8764a..1105da8764a 100644
--- a/src/mongo/client/sdam/json_tests/rs/compatible_unknown.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/compatible_unknown.json
diff --git a/src/mongo/client/sdam/json_tests/rs/discover_arbiters.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_arbiters.json
index ced7baeb653..ced7baeb653 100644
--- a/src/mongo/client/sdam/json_tests/rs/discover_arbiters.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_arbiters.json
diff --git a/src/mongo/client/sdam/json_tests/rs/discover_passives.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_passives.json
index e46249d6686..e46249d6686 100644
--- a/src/mongo/client/sdam/json_tests/rs/discover_passives.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_passives.json
diff --git a/src/mongo/client/sdam/json_tests/rs/discover_primary.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_primary.json
index ea2cce9b72b..ea2cce9b72b 100644
--- a/src/mongo/client/sdam/json_tests/rs/discover_primary.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_primary.json
diff --git a/src/mongo/client/sdam/json_tests/rs/discover_secondary.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_secondary.json
index 7210b3845c7..7210b3845c7 100644
--- a/src/mongo/client/sdam/json_tests/rs/discover_secondary.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discover_secondary.json
diff --git a/src/mongo/client/sdam/json_tests/rs/discovery.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discovery.json
index 57ed568e3b0..57ed568e3b0 100644
--- a/src/mongo/client/sdam/json_tests/rs/discovery.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discovery.json
diff --git a/src/mongo/client/sdam/json_tests/rs/discovery.json.notused b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discovery.json.notused
index 57ed568e3b0..57ed568e3b0 100644
--- a/src/mongo/client/sdam/json_tests/rs/discovery.json.notused
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/discovery.json.notused
diff --git a/src/mongo/client/sdam/json_tests/rs/equal_electionids.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/equal_electionids.json
index f8d20b350df..f8d20b350df 100644
--- a/src/mongo/client/sdam/json_tests/rs/equal_electionids.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/equal_electionids.json
diff --git a/src/mongo/client/sdam/json_tests/rs/ghost_discovered.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/ghost_discovered.json
index bf22cbb0eb5..bf22cbb0eb5 100644
--- a/src/mongo/client/sdam/json_tests/rs/ghost_discovered.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/ghost_discovered.json
diff --git a/src/mongo/client/sdam/json_tests/rs/hosts_differ_from_seeds.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/hosts_differ_from_seeds.json
index a67db57d0cb..a67db57d0cb 100644
--- a/src/mongo/client/sdam/json_tests/rs/hosts_differ_from_seeds.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/hosts_differ_from_seeds.json
diff --git a/src/mongo/client/sdam/json_tests/rs/incompatible_arbiter.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_arbiter.json
index aa582208d6b..aa582208d6b 100644
--- a/src/mongo/client/sdam/json_tests/rs/incompatible_arbiter.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_arbiter.json
diff --git a/src/mongo/client/sdam/json_tests/rs/incompatible_ghost.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_ghost.json
index 088159c3aba..088159c3aba 100644
--- a/src/mongo/client/sdam/json_tests/rs/incompatible_ghost.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_ghost.json
diff --git a/src/mongo/client/sdam/json_tests/rs/incompatible_other.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_other.json
index b65d674b42b..b65d674b42b 100644
--- a/src/mongo/client/sdam/json_tests/rs/incompatible_other.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/incompatible_other.json
diff --git a/src/mongo/client/sdam/json_tests/rs/ls_timeout.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/ls_timeout.json
index 6860742c9e9..6860742c9e9 100644
--- a/src/mongo/client/sdam/json_tests/rs/ls_timeout.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/ls_timeout.json
diff --git a/src/mongo/client/sdam/json_tests/rs/member_reconfig.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/member_reconfig.json
index 336acff0236..336acff0236 100644
--- a/src/mongo/client/sdam/json_tests/rs/member_reconfig.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/member_reconfig.json
diff --git a/src/mongo/client/sdam/json_tests/rs/member_standalone.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/member_standalone.json
index a97dfabf52e..a97dfabf52e 100644
--- a/src/mongo/client/sdam/json_tests/rs/member_standalone.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/member_standalone.json
diff --git a/src/mongo/client/sdam/json_tests/rs/new_primary.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary.json
index eb73b304bd9..eb73b304bd9 100644
--- a/src/mongo/client/sdam/json_tests/rs/new_primary.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary.json
diff --git a/src/mongo/client/sdam/json_tests/rs/new_primary_new_electionid.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_new_electionid.json
index 67f314b1edc..67f314b1edc 100644
--- a/src/mongo/client/sdam/json_tests/rs/new_primary_new_electionid.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_new_electionid.json
diff --git a/src/mongo/client/sdam/json_tests/rs/new_primary_new_setversion.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_new_setversion.json
index c1ec50c845c..c1ec50c845c 100644
--- a/src/mongo/client/sdam/json_tests/rs/new_primary_new_setversion.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_new_setversion.json
diff --git a/src/mongo/client/sdam/json_tests/rs/new_primary_wrong_set_name.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_wrong_set_name.json
index 7be79d2d3c9..7be79d2d3c9 100644
--- a/src/mongo/client/sdam/json_tests/rs/new_primary_wrong_set_name.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/new_primary_wrong_set_name.json
diff --git a/src/mongo/client/sdam/json_tests/rs/non_rs_member.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/non_rs_member.json
index 907c1651e02..907c1651e02 100644
--- a/src/mongo/client/sdam/json_tests/rs/non_rs_member.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/non_rs_member.json
diff --git a/src/mongo/client/sdam/json_tests/rs/normalize_case.json.disabled b/src/mongo/client/sdam/json_tests/sdam_tests/rs/normalize_case.json.disabled
index 4d0b0ae629b..4d0b0ae629b 100644
--- a/src/mongo/client/sdam/json_tests/rs/normalize_case.json.disabled
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/normalize_case.json.disabled
diff --git a/src/mongo/client/sdam/json_tests/rs/normalize_case_me.json.disabled b/src/mongo/client/sdam/json_tests/sdam_tests/rs/normalize_case_me.json.disabled
index e854e7fb432..e854e7fb432 100644
--- a/src/mongo/client/sdam/json_tests/rs/normalize_case_me.json.disabled
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/normalize_case_me.json.disabled
diff --git a/src/mongo/client/sdam/json_tests/rs/null_election_id.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/null_election_id.json
index 3de0a74e413..3de0a74e413 100644
--- a/src/mongo/client/sdam/json_tests/rs/null_election_id.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/null_election_id.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_becomes_ghost.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_ghost.json
index 897120f1fbc..897120f1fbc 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_becomes_ghost.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_ghost.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_becomes_mongos.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_mongos.json
index 8d4967b7ddb..8d4967b7ddb 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_becomes_mongos.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_mongos.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_becomes_standalone.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_standalone.json
index e35c75f4bc0..e35c75f4bc0 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_becomes_standalone.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_becomes_standalone.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_changes_set_name.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_changes_set_name.json
index d008326123b..d008326123b 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_changes_set_name.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_changes_set_name.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_disconnect.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect.json
index 271ca5874e5..271ca5874e5 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_disconnect.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_disconnect_electionid.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect_electionid.json
index 59c8faf1805..59c8faf1805 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_disconnect_electionid.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect_electionid.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_disconnect_setversion.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect_setversion.json
index beb023e4f41..beb023e4f41 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_disconnect_setversion.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_disconnect_setversion.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_hint_from_secondary_with_mismatched_me.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_hint_from_secondary_with_mismatched_me.json
index 806fda37c3b..806fda37c3b 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_hint_from_secondary_with_mismatched_me.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_hint_from_secondary_with_mismatched_me.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_mismatched_me.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_mismatched_me.json
index 8d18a6971f5..8d18a6971f5 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_mismatched_me.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_mismatched_me.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_reports_new_member.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_reports_new_member.json
index 6ed55ab3d19..6ed55ab3d19 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_reports_new_member.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_reports_new_member.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_to_no_primary_mismatched_me.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_to_no_primary_mismatched_me.json
index fdb250ffef4..fdb250ffef4 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_to_no_primary_mismatched_me.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_to_no_primary_mismatched_me.json
diff --git a/src/mongo/client/sdam/json_tests/rs/primary_wrong_set_name.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_wrong_set_name.json
index eda47871730..eda47871730 100644
--- a/src/mongo/client/sdam/json_tests/rs/primary_wrong_set_name.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/primary_wrong_set_name.json
diff --git a/src/mongo/client/sdam/json_tests/rs/response_from_removed.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/response_from_removed.json
index dd3562d7fc9..dd3562d7fc9 100644
--- a/src/mongo/client/sdam/json_tests/rs/response_from_removed.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/response_from_removed.json
diff --git a/src/mongo/client/sdam/json_tests/rs/rsother_discovered.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/rsother_discovered.json
index c575501d803..c575501d803 100644
--- a/src/mongo/client/sdam/json_tests/rs/rsother_discovered.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/rsother_discovered.json
diff --git a/src/mongo/client/sdam/json_tests/rs/sec_not_auth.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/sec_not_auth.json
index 7d5e7000357..7d5e7000357 100644
--- a/src/mongo/client/sdam/json_tests/rs/sec_not_auth.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/sec_not_auth.json
diff --git a/src/mongo/client/sdam/json_tests/rs/secondary_ignore_ok_0.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_ignore_ok_0.json
index 6d3033eeeee..6d3033eeeee 100644
--- a/src/mongo/client/sdam/json_tests/rs/secondary_ignore_ok_0.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_ignore_ok_0.json
diff --git a/src/mongo/client/sdam/json_tests/rs/secondary_mismatched_me.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_mismatched_me.json
index d2a70f67889..d2a70f67889 100644
--- a/src/mongo/client/sdam/json_tests/rs/secondary_mismatched_me.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_mismatched_me.json
diff --git a/src/mongo/client/sdam/json_tests/rs/secondary_wrong_set_name.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_wrong_set_name.json
index 4c132b633e1..4c132b633e1 100644
--- a/src/mongo/client/sdam/json_tests/rs/secondary_wrong_set_name.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_wrong_set_name.json
diff --git a/src/mongo/client/sdam/json_tests/rs/secondary_wrong_set_name_with_primary.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_wrong_set_name_with_primary.json
index 73cbab7c5d5..73cbab7c5d5 100644
--- a/src/mongo/client/sdam/json_tests/rs/secondary_wrong_set_name_with_primary.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/secondary_wrong_set_name_with_primary.json
diff --git a/src/mongo/client/sdam/json_tests/rs/setversion_without_electionid.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/setversion_without_electionid.json
index 0500c6d1575..0500c6d1575 100644
--- a/src/mongo/client/sdam/json_tests/rs/setversion_without_electionid.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/setversion_without_electionid.json
diff --git a/src/mongo/client/sdam/json_tests/rs/stepdown_change_set_name.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/stepdown_change_set_name.json
index 39a4f532ddb..39a4f532ddb 100644
--- a/src/mongo/client/sdam/json_tests/rs/stepdown_change_set_name.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/stepdown_change_set_name.json
diff --git a/src/mongo/client/sdam/json_tests/rs/too_new.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/too_new.json
index 945145af885..945145af885 100644
--- a/src/mongo/client/sdam/json_tests/rs/too_new.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/too_new.json
diff --git a/src/mongo/client/sdam/json_tests/rs/too_old.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/too_old.json
index 3f9eadc4bca..3f9eadc4bca 100644
--- a/src/mongo/client/sdam/json_tests/rs/too_old.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/too_old.json
diff --git a/src/mongo/client/sdam/json_tests/rs/unexpected_mongos.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/unexpected_mongos.json
index 95c7aa9dce2..95c7aa9dce2 100644
--- a/src/mongo/client/sdam/json_tests/rs/unexpected_mongos.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/unexpected_mongos.json
diff --git a/src/mongo/client/sdam/json_tests/rs/use_setversion_without_electionid.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/use_setversion_without_electionid.json
index 16225d6b83f..16225d6b83f 100644
--- a/src/mongo/client/sdam/json_tests/rs/use_setversion_without_electionid.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/use_setversion_without_electionid.json
diff --git a/src/mongo/client/sdam/json_tests/rs/wrong_set_name.json b/src/mongo/client/sdam/json_tests/sdam_tests/rs/wrong_set_name.json
index 45be2f502b2..45be2f502b2 100644
--- a/src/mongo/client/sdam/json_tests/rs/wrong_set_name.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/rs/wrong_set_name.json
diff --git a/src/mongo/client/sdam/json_tests/sharded/compatible.json b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/compatible.json
index 3dae1f7ea1e..3dae1f7ea1e 100644
--- a/src/mongo/client/sdam/json_tests/sharded/compatible.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/compatible.json
diff --git a/src/mongo/client/sdam/json_tests/sharded/ls_timeout_mongos.json b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/ls_timeout_mongos.json
index 96f8dec17ac..96f8dec17ac 100644
--- a/src/mongo/client/sdam/json_tests/sharded/ls_timeout_mongos.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/ls_timeout_mongos.json
diff --git a/src/mongo/client/sdam/json_tests/sharded/mongos_disconnect.json b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/mongos_disconnect.json
index 04015694a8d..04015694a8d 100644
--- a/src/mongo/client/sdam/json_tests/sharded/mongos_disconnect.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/mongos_disconnect.json
diff --git a/src/mongo/client/sdam/json_tests/sharded/multiple_mongoses.json b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/multiple_mongoses.json
index 6e60fd05c7d..6e60fd05c7d 100644
--- a/src/mongo/client/sdam/json_tests/sharded/multiple_mongoses.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/multiple_mongoses.json
diff --git a/src/mongo/client/sdam/json_tests/sharded/non_mongos_removed.json b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/non_mongos_removed.json
index 58cf7c07d78..58cf7c07d78 100644
--- a/src/mongo/client/sdam/json_tests/sharded/non_mongos_removed.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/non_mongos_removed.json
diff --git a/src/mongo/client/sdam/json_tests/sharded/normalize_uri_case.json.disabled b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/normalize_uri_case.json.disabled
index 4aa7cb08b61..4aa7cb08b61 100644
--- a/src/mongo/client/sdam/json_tests/sharded/normalize_uri_case.json.disabled
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/normalize_uri_case.json.disabled
diff --git a/src/mongo/client/sdam/json_tests/sharded/too_new.json b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/too_new.json
index 9521e117899..9521e117899 100644
--- a/src/mongo/client/sdam/json_tests/sharded/too_new.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/too_new.json
diff --git a/src/mongo/client/sdam/json_tests/sharded/too_old.json b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/too_old.json
index 6bd187f61db..6bd187f61db 100644
--- a/src/mongo/client/sdam/json_tests/sharded/too_old.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/sharded/too_old.json
diff --git a/src/mongo/client/sdam/json_tests/single/compatible.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/compatible.json
index ee6b847ade7..ee6b847ade7 100644
--- a/src/mongo/client/sdam/json_tests/single/compatible.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/compatible.json
diff --git a/src/mongo/client/sdam/json_tests/single/direct_connection_external_ip.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_external_ip.json
index 44581501862..44581501862 100644
--- a/src/mongo/client/sdam/json_tests/single/direct_connection_external_ip.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_external_ip.json
diff --git a/src/mongo/client/sdam/json_tests/single/direct_connection_mongos.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_mongos.json
index a7fa0794901..a7fa0794901 100644
--- a/src/mongo/client/sdam/json_tests/single/direct_connection_mongos.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_mongos.json
diff --git a/src/mongo/client/sdam/json_tests/single/direct_connection_rsarbiter.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rsarbiter.json
index 3ef374d6f1e..3ef374d6f1e 100644
--- a/src/mongo/client/sdam/json_tests/single/direct_connection_rsarbiter.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rsarbiter.json
diff --git a/src/mongo/client/sdam/json_tests/single/direct_connection_rsprimary.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rsprimary.json
index bd5aaf7f044..bd5aaf7f044 100644
--- a/src/mongo/client/sdam/json_tests/single/direct_connection_rsprimary.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rsprimary.json
diff --git a/src/mongo/client/sdam/json_tests/single/direct_connection_rssecondary.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rssecondary.json
index 3b4f3c8c5ad..3b4f3c8c5ad 100644
--- a/src/mongo/client/sdam/json_tests/single/direct_connection_rssecondary.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_rssecondary.json
diff --git a/src/mongo/client/sdam/json_tests/single/direct_connection_slave.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_slave.json
index a40debd1838..a40debd1838 100644
--- a/src/mongo/client/sdam/json_tests/single/direct_connection_slave.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_slave.json
diff --git a/src/mongo/client/sdam/json_tests/single/direct_connection_standalone.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_standalone.json
index 2ecff9b9ae2..2ecff9b9ae2 100644
--- a/src/mongo/client/sdam/json_tests/single/direct_connection_standalone.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/direct_connection_standalone.json
diff --git a/src/mongo/client/sdam/json_tests/single/ls_timeout_standalone.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/ls_timeout_standalone.json
index ae6c8ba11be..ae6c8ba11be 100644
--- a/src/mongo/client/sdam/json_tests/single/ls_timeout_standalone.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/ls_timeout_standalone.json
diff --git a/src/mongo/client/sdam/json_tests/single/not_ok_response.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/not_ok_response.json
index 06f71305dc0..06f71305dc0 100644
--- a/src/mongo/client/sdam/json_tests/single/not_ok_response.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/not_ok_response.json
diff --git a/src/mongo/client/sdam/json_tests/single/standalone_removed.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/standalone_removed.json
index 4c363ffffb8..4c363ffffb8 100644
--- a/src/mongo/client/sdam/json_tests/single/standalone_removed.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/standalone_removed.json
diff --git a/src/mongo/client/sdam/json_tests/single/too_new.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/too_new.json
index 38e4621d60f..38e4621d60f 100644
--- a/src/mongo/client/sdam/json_tests/single/too_new.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/too_new.json
diff --git a/src/mongo/client/sdam/json_tests/single/too_old.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/too_old.json
index fbf68262c02..fbf68262c02 100644
--- a/src/mongo/client/sdam/json_tests/single/too_old.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/too_old.json
diff --git a/src/mongo/client/sdam/json_tests/single/unavailable_seed.json b/src/mongo/client/sdam/json_tests/sdam_tests/single/unavailable_seed.json
index e9cce02ebfd..e9cce02ebfd 100644
--- a/src/mongo/client/sdam/json_tests/single/unavailable_seed.json
+++ b/src/mongo/client/sdam/json_tests/sdam_tests/single/unavailable_seed.json
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/README.rst b/src/mongo/client/sdam/json_tests/server_selection_tests/README.rst
new file mode 100644
index 00000000000..2c9550a2268
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/README.rst
@@ -0,0 +1,67 @@
+======================
+Server Selection Tests
+======================
+
+This directory contains platform-independent tests that drivers can use
+to prove their conformance to the Server Selection spec. The tests
+are provided in both YAML and JSON formats, and drivers may test against
+whichever format is more convenient for them.
+
+Version
+-------
+
+Files in the "specifications" repository have no version scheme. They are not
+tied to a MongoDB server version.
+
+Test Format and Use
+-------------------
+
+There are two types of tests for the server selection spec, tests for
+round trip time (RTT) calculation, and tests for server selection logic.
+
+Drivers should be able to test their server selection logic
+without any network I/O, by parsing topology descriptions and read preference
+documents from the test files and passing them into driver code. Parts of the
+server selection code may need to be mocked or subclassed to achieve this.
+
+RTT Calculation Tests
+>>>>>>>>>>>>>>>>>>>>>
+
+These YAML files contain the following keys:
+
+- ``avg_rtt_ms``: a server's previous average RTT, in milliseconds
+- ``new_rtt_ms``: a new RTT value for this server, in milliseconds
+- ``new_avg_rtt``: this server's newly-calculated average RTT, in milliseconds
+
+For each file, create a server description object initialized with ``avg_rtt_ms``.
+Parse ``new_rtt_ms``, and ensure that the new RTT value for the mocked server
+description is equal to ``new_avg_rtt``.
+
+If driver architecture doesn't easily allow construction of server description
+objects in isolation, unit testing the EWMA algorithm using these inputs
+and expected outputs is acceptable.
+
+Server Selection Logic Tests
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+These YAML files contain the following setup for each test:
+
+- ``topology_description``: the state of a mocked cluster
+- ``operation``: the kind of operation to perform, either read or write
+- ``read_preference``: a read preference document
+
+For each file, create a new TopologyDescription object initialized with the values
+from ``topology_description``. Create a ReadPreference object initialized with the
+values from ``read_preference``.
+
+Together with "operation", pass the newly-created TopologyDescription and ReadPreference
+to server selection, and ensure that it selects the correct subset of servers from
+the TopologyDescription. Each YAML file contains a key for these stages of server selection:
+
+- ``suitable_servers``: the set of servers in topology_description that are suitable, as
+ per the Server Selection spec, given operation and read_preference
+- ``in_latency_window``: the set of suitable_servers that fall within the latency window
+
+Drivers implementing server selection MUST test that their implementation
+correctly returns the set of servers in ``in_latency_window``. Drivers SHOULD also test
+against ``suitable_servers`` if possible.
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/first_value.json b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/first_value.json
new file mode 100644
index 00000000000..421944da366
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/first_value.json
@@ -0,0 +1,5 @@
+{
+ "avg_rtt_ms": "NULL",
+ "new_rtt_ms": 10,
+ "new_avg_rtt": 10
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/first_value_zero.json b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/first_value_zero.json
new file mode 100644
index 00000000000..d5bfc41b25d
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/first_value_zero.json
@@ -0,0 +1,5 @@
+{
+ "avg_rtt_ms": "NULL",
+ "new_rtt_ms": 0,
+ "new_avg_rtt": 0
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_1.json b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_1.json
new file mode 100644
index 00000000000..ed6a80ce29b
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_1.json
@@ -0,0 +1,5 @@
+{
+ "avg_rtt_ms": 0,
+ "new_rtt_ms": 5,
+ "new_avg_rtt": 1
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_2.json b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_2.json
new file mode 100644
index 00000000000..ccb5a0173b6
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_2.json
@@ -0,0 +1,5 @@
+{
+ "avg_rtt_ms": 3.1,
+ "new_rtt_ms": 36,
+ "new_avg_rtt": 9.68
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_3.json b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_3.json
new file mode 100644
index 00000000000..6921c94d36c
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_3.json
@@ -0,0 +1,5 @@
+{
+ "avg_rtt_ms": 9.12,
+ "new_rtt_ms": 9.12,
+ "new_avg_rtt": 9.12
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_4.json b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_4.json
new file mode 100644
index 00000000000..d9ce3800b82
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_4.json
@@ -0,0 +1,5 @@
+{
+ "avg_rtt_ms": 1,
+ "new_rtt_ms": 1000,
+ "new_avg_rtt": 200.8
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_5.json b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_5.json
new file mode 100644
index 00000000000..9ae33bc1434
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/rtt/value_test_5.json
@@ -0,0 +1,5 @@
+{
+ "avg_rtt_ms": 0,
+ "new_rtt_ms": 0.25,
+ "new_avg_rtt": 0.05
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest.json
new file mode 100644
index 00000000000..aa48679e866
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest.json
@@ -0,0 +1,60 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Nearest",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest_multiple.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest_multiple.json
new file mode 100644
index 00000000000..1fcfd52a477
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest_multiple.json
@@ -0,0 +1,68 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 10,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 20,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Nearest",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 10,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 20,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 10,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 20,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest_non_matching.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest_non_matching.json
new file mode 100644
index 00000000000..b72895d8a83
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Nearest_non_matching.json
@@ -0,0 +1,34 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Nearest",
+ "tag_sets": [
+ {
+ "data_center": "sf"
+ }
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PossiblePrimary.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PossiblePrimary.json
new file mode 100644
index 00000000000..4d286af830f
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PossiblePrimary.json
@@ -0,0 +1,21 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "PossiblePrimary"
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Primary",
+ "tag_sets": [
+ {}
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PossiblePrimaryNearest.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PossiblePrimaryNearest.json
new file mode 100644
index 00000000000..bf9c70b420e
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PossiblePrimaryNearest.json
@@ -0,0 +1,21 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "PossiblePrimary"
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Nearest",
+ "tag_sets": [
+ {}
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Primary.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Primary.json
new file mode 100644
index 00000000000..f0f3fa9ea15
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Primary.json
@@ -0,0 +1,29 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Primary"
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PrimaryPreferred.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PrimaryPreferred.json
new file mode 100644
index 00000000000..f87ef4f6170
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PrimaryPreferred.json
@@ -0,0 +1,58 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "PrimaryPreferred",
+ "tag_sets": [
+ {}
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.json
new file mode 100644
index 00000000000..ee962299270
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.json
@@ -0,0 +1,34 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "PrimaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "sf"
+ }
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary.json
new file mode 100644
index 00000000000..3b8f1e97cd6
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary.json
@@ -0,0 +1,60 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Secondary",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/SecondaryPreferred.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/SecondaryPreferred.json
new file mode 100644
index 00000000000..c3142ec1154
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/SecondaryPreferred.json
@@ -0,0 +1,60 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "SecondaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.json
new file mode 100644
index 00000000000..a2c18bb7d22
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.json
@@ -0,0 +1,34 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "SecondaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "sf"
+ }
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_multi_tags.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_multi_tags.json
new file mode 100644
index 00000000000..b319918e926
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_multi_tags.json
@@ -0,0 +1,60 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "rack": "one",
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "rack": "two",
+ "data_center": "sf"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Secondary",
+ "tag_sets": [
+ {
+ "data_center": "nyc",
+ "rack": "one"
+ },
+ {
+ "other_tag": "doesntexist"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "rack": "one",
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "rack": "one",
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_multi_tags2.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_multi_tags2.json
new file mode 100644
index 00000000000..8f64d95ecb8
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_multi_tags2.json
@@ -0,0 +1,60 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "rack": "one",
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "rack": "two",
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Secondary",
+ "tag_sets": [
+ {
+ "data_center": "nyc",
+ "rack": "one"
+ },
+ {
+ "other_tag": "doesntexist"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "rack": "one",
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "rack": "one",
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_non_matching.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_non_matching.json
new file mode 100644
index 00000000000..4931e1019a4
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetNoPrimary/read/Secondary_non_matching.json
@@ -0,0 +1,34 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetNoPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Secondary",
+ "tag_sets": [
+ {
+ "data_center": "sf"
+ }
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest.json
new file mode 100644
index 00000000000..cfe4965938d
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest.json
@@ -0,0 +1,76 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Nearest",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest_multiple.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest_multiple.json
new file mode 100644
index 00000000000..67296d434fe
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest_multiple.json
@@ -0,0 +1,84 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 10,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 20,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Nearest",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 10,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 20,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 10,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 20,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest_non_matching.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest_non_matching.json
new file mode 100644
index 00000000000..a3a85c9a83e
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Nearest_non_matching.json
@@ -0,0 +1,42 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Nearest",
+ "tag_sets": [
+ {
+ "data_center": "sf"
+ }
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Primary.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Primary.json
new file mode 100644
index 00000000000..8da1482e967
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Primary.json
@@ -0,0 +1,55 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Primary"
+ },
+ "suitable_servers": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/PrimaryPreferred.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/PrimaryPreferred.json
new file mode 100644
index 00000000000..306171f3a20
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/PrimaryPreferred.json
@@ -0,0 +1,58 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "PrimaryPreferred",
+ "tag_sets": [
+ {}
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.json
new file mode 100644
index 00000000000..722f1cfb1a9
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.json
@@ -0,0 +1,60 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "PrimaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "sf"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Secondary.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Secondary.json
new file mode 100644
index 00000000000..23864a278c4
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Secondary.json
@@ -0,0 +1,68 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Secondary",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred.json
new file mode 100644
index 00000000000..d07c24218d3
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred.json
@@ -0,0 +1,68 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "SecondaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred_non_matching.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred_non_matching.json
new file mode 100644
index 00000000000..f893cc9f828
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred_non_matching.json
@@ -0,0 +1,60 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "SecondaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "sf"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred_tags.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred_tags.json
new file mode 100644
index 00000000000..a74a2dbf33b
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/SecondaryPreferred_tags.json
@@ -0,0 +1,52 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "sf"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "SecondaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Secondary_non_matching.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Secondary_non_matching.json
new file mode 100644
index 00000000000..12721806665
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/ReplicaSetWithPrimary/read/Secondary_non_matching.json
@@ -0,0 +1,42 @@
+{
+ "topology_description": {
+ "type": "ReplicaSetWithPrimary",
+ "servers": [
+ {
+ "address": "b:27017",
+ "avg_rtt_ms": 5,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "c:27017",
+ "avg_rtt_ms": 100,
+ "type": "RSSecondary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ },
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 26,
+ "type": "RSPrimary",
+ "tags": {
+ "data_center": "nyc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "Secondary",
+ "tag_sets": [
+ {
+ "data_center": "sf"
+ }
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/Single/read/SecondaryPreferred.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/Single/read/SecondaryPreferred.json
new file mode 100644
index 00000000000..e60496dfdfe
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/Single/read/SecondaryPreferred.json
@@ -0,0 +1,44 @@
+{
+ "topology_description": {
+ "type": "Single",
+ "servers": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 5,
+ "type": "Standalone",
+ "tags": {
+ "data_center": "dc"
+ }
+ }
+ ]
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "SecondaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 5,
+ "type": "Standalone",
+ "tags": {
+ "data_center": "dc"
+ }
+ }
+ ],
+ "in_latency_window": [
+ {
+ "address": "a:27017",
+ "avg_rtt_ms": 5,
+ "type": "Standalone",
+ "tags": {
+ "data_center": "dc"
+ }
+ }
+ ]
+}
diff --git a/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/Unknown/read/SecondaryPreferred.json b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/Unknown/read/SecondaryPreferred.json
new file mode 100644
index 00000000000..0ae8075fba3
--- /dev/null
+++ b/src/mongo/client/sdam/json_tests/server_selection_tests/server_selection/Unknown/read/SecondaryPreferred.json
@@ -0,0 +1,17 @@
+{
+ "topology_description": {
+ "type": "Unknown",
+ "servers": []
+ },
+ "operation": "read",
+ "read_preference": {
+ "mode": "SecondaryPreferred",
+ "tag_sets": [
+ {
+ "data_center": "nyc"
+ }
+ ]
+ },
+ "suitable_servers": [],
+ "in_latency_window": []
+}
diff --git a/src/mongo/client/sdam/sdam_datatypes.cpp b/src/mongo/client/sdam/sdam_datatypes.cpp
index 2faf7acd361..b8b9926077d 100644
--- a/src/mongo/client/sdam/sdam_datatypes.cpp
+++ b/src/mongo/client/sdam/sdam_datatypes.cpp
@@ -113,6 +113,24 @@ std::string toString(const TopologyType topologyType) {
}
}
+StatusWith<TopologyType> parseTopologyType(StringData strTopologyType) {
+ if (strTopologyType == "ReplicaSetNoPrimary") {
+ return TopologyType::kReplicaSetNoPrimary;
+ } else if (strTopologyType == "ReplicaSetWithPrimary") {
+ return TopologyType::kReplicaSetWithPrimary;
+ } else if (strTopologyType == "Sharded") {
+ return TopologyType::kSharded;
+ } else if (strTopologyType == "Unknown") {
+ return TopologyType::kUnknown;
+ } else if (strTopologyType == "Single") {
+ return TopologyType::kSingle;
+ } else {
+ std::stringstream errorMessage;
+ errorMessage << strTopologyType << " is an invalid TopologyType.";
+ return StatusWith<TopologyType>(ErrorCodes::InvalidTopologyType, errorMessage.str());
+ }
+}
+
std::ostream& operator<<(std::ostream& os, const TopologyType topologyType) {
os << toString(topologyType);
return os;
diff --git a/src/mongo/client/sdam/sdam_datatypes.h b/src/mongo/client/sdam/sdam_datatypes.h
index 3ec5363965c..71fdd1e10ed 100644
--- a/src/mongo/client/sdam/sdam_datatypes.h
+++ b/src/mongo/client/sdam/sdam_datatypes.h
@@ -54,6 +54,7 @@ enum class TopologyType {
};
const std::vector<TopologyType> allTopologyTypes();
std::string toString(const TopologyType topologyType);
+StatusWith<TopologyType> parseTopologyType(StringData strTopologyType);
std::ostream& operator<<(std::ostream& os, const TopologyType topologyType);
enum class ServerType {
diff --git a/src/mongo/client/sdam/sdam_json_test_runner.cpp b/src/mongo/client/sdam/sdam_json_test_runner.cpp
index b2a6cd0b011..4da3e7d60b8 100644
--- a/src/mongo/client/sdam/sdam_json_test_runner.cpp
+++ b/src/mongo/client/sdam/sdam_json_test_runner.cpp
@@ -40,7 +40,7 @@
#include "mongo/bson/json.h"
#include "mongo/client/mongo_uri.h"
-#include "mongo/client/sdam/sdam_json_test_runner_cli_options_gen.h"
+#include "mongo/client/sdam/json_test_arg_parser.h"
#include "mongo/client/sdam/topology_manager.h"
#include "mongo/logger/logger.h"
#include "mongo/logv2/log.h"
@@ -52,17 +52,18 @@
/**
* This program runs the Server Discover and Monitoring JSON test files located in
- * the src/monogo/client/sdam/json_tests sub-directory.
+ * the src/monogo/client/sdam/json_tests/sdam_tests sub-directory.
*
* The process return code conforms to the UNIX idiom of 0 to indicate success and non-zero to
* indicate failure. In the case of test failure, the process will return the number of test cases
* that failed.
*
* Example invocation to run all tests:
- * sdam_json_test --source-dir src/monogo/client/sdam/json_tests
+ * sdam_json_test --source-dir src/monogo/client/sdam/json_tests/sdam_tests
*
* Example invocation to run a single test:
- * sdam_json_test --source-dir src/monogo/client/sdam/json_tests --filter normalize_uri_case
+ * sdam_json_test --source-dir src/monogo/client/sdam/json_tests/sdam_tests --filter
+ * normalize_uri_case
*/
namespace fs = boost::filesystem;
@@ -78,105 +79,6 @@ std::string emphasize(const std::string text) {
return output.str();
}
-class ArgParser {
-public:
- ArgParser(int argc, char* argv[]) {
- moe::OptionsParser parser;
- moe::Environment environment;
- moe::OptionSection options;
-
- Status ret = addCliOptions(&options);
- if (!ret.isOK()) {
- std::cerr << "Unexpected error adding cli options: " << ret.toString() << std::endl;
- MONGO_UNREACHABLE;
- }
-
- ret = parser.run(options, toStringVector(argc, argv), {}, &environment);
- if (argc <= 1 || !ret.isOK() || environment.count("help")) {
- if (!ret.isOK()) {
- std::cerr << "An error occurred: " << ret.toString() << std::endl;
- }
- printHelpAndExit(argv[0], options.helpString());
- }
-
- const auto exitIfError = [](Status status) {
- if (!status.isOK()) {
- std::cerr << "An error occurred: " << status.toString() << std::endl;
- std::exit(kArgParseExitCode);
- }
- };
-
- if (environment.count(kSourceDirOption)) {
- ret = environment.get(kSourceDirOption, &_sourceDirectory);
- exitIfError(ret);
- }
-
- if (environment.count(moe::Key(kFilterOption))) {
- ret = environment.get(moe::Key(kFilterOption), &_testFilters);
- exitIfError(ret);
- }
-
- if (environment.count(moe::Key(kVerbose))) {
- std::string value;
- ret = environment.get(moe::Key(kVerbose), &value);
- if (!ret.isOK())
- exitIfError(ret);
- _verbose = value.size() + 1;
- }
- }
-
- void LogParams() const {
- LOGV2(20199, "Verbosity: {verbose}", "verbose"_attr = _verbose);
- LOGV2(20200,
- "Source Directory: {sourceDirectory}",
- "sourceDirectory"_attr = _sourceDirectory);
- if (_testFilters.size()) {
- LOGV2(20201,
- "Filters: {boost_join_testFilters}",
- "boost_join_testFilters"_attr = boost::join(_testFilters, ", "));
- }
- }
-
- const std::string& SourceDirectory() const {
- return _sourceDirectory;
- }
-
- const std::vector<std::string>& TestFilters() const {
- return _testFilters;
- }
-
- int Verbose() const {
- return _verbose;
- }
-
-private:
- constexpr static auto kSourceDirOption = "source-dir";
- constexpr static auto kSourceDirDefault = ".";
-
- constexpr static auto kFilterOption = "filter";
-
- constexpr static int kHelpExitCode = 0;
- constexpr static int kArgParseExitCode = 1024;
-
- constexpr static auto kVerbose = "verbose";
-
- std::string _sourceDirectory = kSourceDirDefault;
- std::vector<std::string> _testFilters;
- int _verbose = 0;
-
- void printHelpAndExit(char* programName, const std::string desc) {
- std::cout << programName << ":" << std::endl << desc << std::endl;
- std::exit(kHelpExitCode);
- }
-
- std::vector<std::string> toStringVector(int n, char** array) {
- std::vector<std::string> result;
- for (int i = 0; i < n; ++i)
- result.push_back(array[i]);
- return result;
- }
-};
-
/**
* This class is responsible for parsing and executing a single 'phase' of the json test
*/
@@ -609,7 +511,7 @@ private:
} else {
// We can technically choose either kUnknown or kSharded and be compliant,
// but it seems that some of the json tests assume kUnknown as the initial state.
- // see: json_tests/sharded/normalize_uri_case.json
+ // see: json_tests/sdam_tests/sharded/normalize_uri_case.json
_initialType = TopologyType::kUnknown;
}
} else {
diff --git a/src/mongo/client/sdam/server_selection_json_test_runner.cpp b/src/mongo/client/sdam/server_selection_json_test_runner.cpp
new file mode 100644
index 00000000000..fa17b0e6424
--- /dev/null
+++ b/src/mongo/client/sdam/server_selection_json_test_runner.cpp
@@ -0,0 +1,506 @@
+/**
+ * Copyright (C) 2020-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault
+
+#include <fstream>
+#include <iostream>
+#include <memory>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/format.hpp>
+#include <boost/optional/optional_io.hpp>
+
+#include "mongo/bson/json.h"
+#include "mongo/client/sdam/json_test_arg_parser.h"
+#include "mongo/client/sdam/server_description_builder.h"
+#include "mongo/client/sdam/server_selector.h"
+#include "mongo/client/sdam/topology_manager.h"
+#include "mongo/logger/logger.h"
+#include "mongo/logv2/log.h"
+#include "mongo/stdx/unordered_set.h"
+#include "mongo/util/clock_source_mock.h"
+#include "mongo/util/options_parser/environment.h"
+#include "mongo/util/options_parser/option_section.h"
+#include "mongo/util/options_parser/options_parser.h"
+
+/**
+ * This program runs the Server Discover and Monitoring JSON test files located in
+ * the src/monogo/client/sdam/json_tests/server_selection_tests sub-directory.
+ *
+ * The process return code conforms to the UNIX idiom of 0 to indicate success and non-zero to
+ * indicate failure. In the case of test failure, the process will return the number of test cases
+ * that failed.
+ *
+ * Example invocation to run all tests:
+ * sdam_json_test --source-dir src/monogo/client/sdam/json_tests/server_selection_tests
+ *
+ * Example invocation to run a single test:
+ * sdam_json_test --source-dir src/monogo/client/sdam/json_tests/server_selection_tests --filter
+ * Nearest_multiple
+ */
+
+namespace fs = boost::filesystem;
+namespace moe = mongo::optionenvironment;
+using namespace mongo::sdam;
+
+namespace mongo::sdam {
+
+std::string emphasize(const std::string text) {
+ std::stringstream output;
+ const auto border = std::string(3, '#');
+ output << border << " " << text << " " << border << std::endl;
+ return output.str();
+}
+
+std::ostream& operator<<(std::ostream& os, const std::vector<std::string>& input) {
+ for (auto const& i : input) {
+ os << i << " ";
+ }
+ return os;
+}
+
+class JsonTestCase {
+public:
+ virtual ~JsonTestCase() = default;
+
+ // pair of error subject & error description
+ using TestErrors = std::pair<std::string, std::string>;
+ struct TestCaseResult {
+ std::vector<TestErrors> errorDescriptions;
+ std::string file;
+
+ bool Success() const {
+ return errorDescriptions.size() == 0;
+ }
+ };
+
+ virtual TestCaseResult execute() = 0;
+
+ virtual const std::string& FilePath() const = 0;
+};
+
+/**
+ * This class is responsible for parsing and executing a single json test file in the rtt directory.
+ */
+class JsonRttTestCase : public JsonTestCase {
+public:
+ JsonRttTestCase(fs::path testFilePath) {
+ parseTest(testFilePath);
+ }
+
+ ~JsonRttTestCase() = default;
+
+ TestCaseResult execute() {
+ LOGV2(
+ 4333500, "{testFilePath}", "testFilePath"_attr = emphasize("Running " + _testFilePath));
+
+ ServerDescriptionPtr updatedServerDescription;
+ if (_serverDescription) {
+ updatedServerDescription = (*_serverDescription)->cloneWithRTT(Milliseconds(_newRtt));
+ } else {
+ // This is mocking the first ServerDescription being created during the handshake
+ auto clockSource = std::make_unique<ClockSourceMock>();
+ updatedServerDescription = std::make_shared<ServerDescription>(
+ ServerDescription(clockSource.get(),
+ IsMasterOutcome(ServerAddress("dummy"),
+ BSON("ok" << 1 << "setname"
+ << "replSet"
+ << "ismaster" << true),
+ IsMasterRTT(Milliseconds(_newRtt)))));
+ }
+
+ TestCaseResult result{{}, _testFilePath};
+ validateNewAvgRtt(&result, updatedServerDescription);
+
+ if (!result.Success()) {
+ LOGV2(4333501, "Test {testFilePath} failed.", "testFilePath"_attr = _testFilePath);
+ }
+
+ return result;
+ }
+
+ const std::string& FilePath() const {
+ return _testFilePath;
+ }
+
+private:
+ void parseTest(fs::path testFilePath) {
+ _testFilePath = testFilePath.string();
+ LOGV2(4333502, "");
+ LOGV2(4333503,
+ "{testFilePath}",
+ "testFilePath"_attr = emphasize("Parsing " + testFilePath.string()));
+ {
+ std::ifstream testFile(_testFilePath);
+ std::ostringstream json;
+ json << testFile.rdbuf();
+ _jsonTest = fromjson(json.str());
+ }
+
+ // Only create the initial server description if the original avg rtt is not "NULL". If it
+ // is, the test case is meant to mimic creating the first ServerDescription which we will do
+ // above.
+ std::string origRttAsString = _jsonTest.getStringField("avg_rtt_ms");
+ if (origRttAsString.compare("NULL") != 0) {
+ auto serverDescription = ServerDescriptionBuilder()
+ .withAddress("dummy")
+ .withType(ServerType::kRSPrimary)
+ .instance();
+ auto origAvgRtt = Milliseconds(_jsonTest["avg_rtt_ms"].numberInt());
+
+ _serverDescription = serverDescription->cloneWithRTT(origAvgRtt);
+ }
+
+ _newRtt = _jsonTest["new_rtt_ms"].numberInt();
+ _newAvgRtt = _jsonTest["new_avg_rtt"].numberInt();
+ }
+
+ void validateNewAvgRtt(TestCaseResult* result, ServerDescriptionPtr newServerDescription) {
+ if (!newServerDescription->getRtt()) {
+ std::stringstream errorMessage;
+ errorMessage << "new server description does not have an RTT value but expected '"
+ << Milliseconds(_newAvgRtt) << "'ms";
+ auto errorDescription = std::make_pair("RTT", errorMessage.str());
+ result->errorDescriptions.push_back(errorDescription);
+ return;
+ }
+
+ auto newAvgRtt = duration_cast<Milliseconds>(newServerDescription->getRtt().get());
+ if (newAvgRtt.compare(duration_cast<Milliseconds>(Milliseconds(_newAvgRtt))) != 0) {
+ std::stringstream errorMessage;
+ errorMessage << "new average RTT is incorrect, got '" << newAvgRtt
+ << "'ms but expected '" << Milliseconds(_newAvgRtt) << "'ms";
+ auto errorDescription = std::make_pair("RTT", errorMessage.str());
+ result->errorDescriptions.push_back(errorDescription);
+ }
+ }
+
+ std::string _testFilePath;
+ BSONObj _jsonTest;
+ boost::optional<ServerDescriptionPtr> _serverDescription;
+ int _newRtt;
+ int _newAvgRtt;
+};
+
+/**
+ * This class is responsible for parsing and executing a single json test file in the
+ * server_selection directory.
+ */
+class JsonServerSelectionTestCase : public JsonTestCase {
+public:
+ JsonServerSelectionTestCase(fs::path testFilePath) {
+ parseTest(testFilePath);
+ }
+ ~JsonServerSelectionTestCase() = default;
+
+ TestCaseResult execute() {
+ LOGV2(
+ 4333504, "{testFilePath}", "testFilePath"_attr = emphasize("Running " + _testFilePath));
+
+ SdamServerSelector serverSelector(
+ sdam::ServerSelectionConfiguration::defaultConfiguration());
+ auto selectedServers = serverSelector.selectServers(_topologyDescription, _readPreference);
+
+ TestCaseResult result{{}, _testFilePath};
+ validateServersInLatencyWindow(&result, selectedServers);
+
+ if (!result.Success()) {
+ LOGV2(4333505, "Test {testFilePath} failed.", "testFilePath"_attr = _testFilePath);
+ }
+
+ return result;
+ }
+
+ const std::string& FilePath() const {
+ return _testFilePath;
+ }
+
+private:
+ void parseTest(fs::path testFilePath) {
+ _testFilePath = testFilePath.string();
+ LOGV2(4333506, "");
+ LOGV2(4333507,
+ "{testFilePath}",
+ "testFilePath"_attr = emphasize("Parsing " + testFilePath.string()));
+ {
+ std::ifstream testFile(_testFilePath);
+ std::ostringstream json;
+ json << testFile.rdbuf();
+ _jsonTest = fromjson(json.str());
+ }
+
+ // The json tests pass in capitalized keywords for mode, but the server only accepts
+ // lowercased keywords. Also, change the key "tags_set" to "tags".
+ auto readPrefObj = _jsonTest.getObjectField("read_preference");
+ std::string mode = readPrefObj.getStringField("mode");
+ mode[0] = std::tolower(mode[0]);
+ auto tagSetsObj = readPrefObj["tag_sets"];
+ auto tags = tagSetsObj ? BSONArray(readPrefObj["tag_sets"].Obj()) : BSONArray();
+
+ BSONObj readPref = BSON("mode" << mode << "tags" << tags);
+ _readPreference = uassertStatusOK(ReadPreferenceSetting::fromInnerBSON(readPref));
+
+ // Parse the TopologyDescription and inLatencyWindow objects
+ auto topologyDescriptionObj = _jsonTest.getObjectField("topology_description");
+
+ std::vector<ServerDescriptionPtr> serverDescriptions;
+ std::vector<ServerAddress> serverAddresses;
+ const std::vector<BSONElement>& bsonServers = topologyDescriptionObj["servers"].Array();
+ for (auto bsonServer : bsonServers) {
+ auto server = bsonServer.Obj();
+
+ auto serverType = uassertStatusOK(parseServerType(server.getStringField("type")));
+ auto serverDescription = ServerDescriptionBuilder()
+ .withAddress(server.getStringField("address"))
+ .withType(serverType)
+ .withRtt(Milliseconds(server["avg_rtt_ms"].numberInt()))
+ .withMinWireVersion(8)
+ .withMaxWireVersion(9);
+
+ auto tagsObj = server.getObjectField("tags");
+ const auto keys = tagsObj.getFieldNames<std::set<std::string>>();
+ for (const auto key : keys) {
+ serverDescription.withTag(key, tagsObj.getStringField(key));
+ }
+
+ serverDescriptions.push_back(serverDescription.instance());
+ serverAddresses.push_back(server.getStringField("address"));
+ }
+
+ TopologyType initType =
+ uassertStatusOK(parseTopologyType(topologyDescriptionObj.getStringField("type")));
+ boost::optional<std::string> setName = boost::none;
+ if (initType == TopologyType::kReplicaSetNoPrimary || initType == TopologyType::kSingle)
+ setName = "replset";
+
+ boost::optional<std::vector<ServerAddress>> seedList = boost::none;
+ if (serverAddresses.size() > 0)
+ seedList = serverAddresses;
+
+ auto config = SdamConfiguration(
+ seedList, initType, SdamConfiguration::kDefaultHeartbeatFrequencyMs, setName);
+ _topologyDescription = std::make_shared<TopologyDescription>(config);
+
+ const std::vector<BSONElement>& bsonLatencyWindow = _jsonTest["in_latency_window"].Array();
+ for (const auto& serverDescription : serverDescriptions) {
+ _topologyDescription->installServerDescription(serverDescription);
+
+ for (auto bsonServer : bsonLatencyWindow) {
+ auto server = bsonServer.Obj();
+ if (serverDescription->getAddress() ==
+ ServerAddress(server.getStringField("address"))) {
+ _inLatencyWindow.push_back(serverDescription);
+ }
+ }
+ }
+ }
+
+ void validateServersInLatencyWindow(
+ TestCaseResult* result,
+ boost::optional<std::vector<ServerDescriptionPtr>> selectedServers) {
+ if (!selectedServers && _inLatencyWindow.size() > 0) {
+ std::stringstream errorMessage;
+ errorMessage << "did not select any servers, but expected '" << _inLatencyWindow.size()
+ << "' to be selected.";
+ auto errorDescription = std::make_pair("servers in latency window", errorMessage.str());
+ result->errorDescriptions.push_back(errorDescription);
+ } else if (selectedServers && selectedServers->size() != _inLatencyWindow.size()) {
+ std::stringstream errorMessage;
+ errorMessage << "selected '" << selectedServers->size() << "' server(s), but expected '"
+ << _inLatencyWindow.size() << "' to be selected.";
+ auto errorDescription = std::make_pair("servers in latency window", errorMessage.str());
+ result->errorDescriptions.push_back(errorDescription);
+ } else {
+ // Compare the server addresses of each server in the selectedServers and
+ // _inLatencyWindow vectors. We do not need to compare the entire server description
+ // because we only need to make sure that the correct server was chosen and are not
+ // manipulating the ServerDescriptions at all.
+ std::vector<std::string> selectedServerAddresses;
+ std::vector<std::string> expectedServerAddresses;
+
+ auto selectedServersIt = selectedServers->begin();
+ for (auto expectedServersIt = _inLatencyWindow.begin();
+ expectedServersIt != _inLatencyWindow.end();
+ ++expectedServersIt) {
+ selectedServerAddresses.push_back((*selectedServersIt)->getAddress());
+ expectedServerAddresses.push_back((*expectedServersIt)->getAddress());
+
+ selectedServersIt++;
+ }
+
+ std::sort(selectedServerAddresses.begin(), selectedServerAddresses.end());
+ std::sort(expectedServerAddresses.begin(), expectedServerAddresses.end());
+ if (!std::equal(selectedServerAddresses.begin(),
+ selectedServerAddresses.end(),
+ expectedServerAddresses.begin())) {
+ std::stringstream errorMessage;
+ errorMessage << "selected servers with addresses '" << selectedServerAddresses
+ << "' server(s), but expected '" << expectedServerAddresses
+ << "' to be selected.";
+ auto errorDescription =
+ std::make_pair("servers in latency window", errorMessage.str());
+ result->errorDescriptions.push_back(errorDescription);
+ return;
+ }
+ }
+ }
+
+ std::string _testFilePath;
+ BSONObj _jsonTest;
+ TopologyDescriptionPtr _topologyDescription;
+ ReadPreferenceSetting _readPreference;
+ std::vector<ServerDescriptionPtr> _inLatencyWindow;
+};
+
+/**
+ * This class runs (potentially) multiple json tests and reports their results.
+ */
+class ServerSelectionJsonTestRunner {
+public:
+ ServerSelectionJsonTestRunner(std::string testDirectory, std::vector<std::string> testFilters)
+ : _testFiles(scanTestFiles(testDirectory, testFilters)) {}
+
+ std::vector<JsonTestCase::TestCaseResult> runTests() {
+ std::vector<JsonTestCase::TestCaseResult> results;
+ const auto testFiles = getTestFiles();
+ for (auto jsonTest : testFiles) {
+ auto testCase = [jsonTest]() -> std::unique_ptr<JsonTestCase> {
+ if (jsonTest.string().find("/rtt/")) {
+ return std::make_unique<JsonRttTestCase>(jsonTest);
+ }
+ return std::make_unique<JsonServerSelectionTestCase>(jsonTest);
+ }();
+
+ try {
+ LOGV2(4333508,
+ "{testFilePath}",
+ "testFilePath"_attr = emphasize("Executing " + testCase->FilePath()));
+ results.push_back(testCase->execute());
+ } catch (const DBException& ex) {
+ std::stringstream error;
+ error << "Exception while executing " << jsonTest.string() << ": " << ex.toString();
+ std::string errorStr = error.str();
+ results.push_back(JsonTestCase::TestCaseResult{
+ {std::make_pair("exception", errorStr)}, jsonTest.string()});
+ std::cerr << errorStr;
+ }
+ }
+ return results;
+ }
+
+ int report(std::vector<JsonTestCase::TestCaseResult> results) {
+ int numTestCases = results.size();
+ int numSuccess = 0;
+ int numFailed = 0;
+
+ if (std::any_of(
+ results.begin(), results.end(), [](const JsonTestCase::TestCaseResult& result) {
+ return !result.Success();
+ })) {
+ LOGV2(4333509,
+ "{Failed_Test_Results}",
+ "Failed_Test_Results"_attr = emphasize("Failed Test Results"));
+ }
+
+ for (const auto result : results) {
+ auto file = result.file;
+ if (result.Success()) {
+ ++numSuccess;
+ } else {
+ LOGV2(4333510, "{testFilePath}", "testFilePath"_attr = emphasize(file));
+ LOGV2(4333511, "error in file: {file}", "file"_attr = file);
+ ++numFailed;
+ LOGV2(4333512, "");
+ }
+ }
+ LOGV2(4333513,
+ "{numTestCases} test cases; {numSuccess} success; {numFailed} failed.",
+ "numTestCases"_attr = numTestCases,
+ "numSuccess"_attr = numSuccess,
+ "numFailed"_attr = numFailed);
+
+ return numFailed;
+ }
+
+ const std::vector<fs::path>& getTestFiles() const {
+ return _testFiles;
+ }
+
+private:
+ std::vector<fs::path> scanTestFiles(std::string testDirectory,
+ std::vector<std::string> filters) {
+ std::vector<fs::path> results;
+ for (const auto& entry : fs::recursive_directory_iterator(testDirectory)) {
+ if (!fs::is_directory(entry) && matchesFilter(entry, filters)) {
+ results.push_back(entry.path());
+ }
+ }
+ return results;
+ }
+
+ bool matchesFilter(const fs::directory_entry& entry, std::vector<std::string> filters) {
+ const auto filePath = entry.path();
+ if (filePath.extension() != ".json") {
+ return false;
+ }
+
+ if (filters.size() == 0) {
+ return true;
+ }
+
+ for (const auto& filter : filters) {
+ if (filePath.string().find(filter) != std::string::npos) {
+ return true;
+ } else {
+ LOGV2_DEBUG(4333514,
+ 2,
+ "'{filePath}' skipped due to filter configuration.",
+ "filePath"_attr = filePath.string());
+ }
+ }
+
+ return false;
+ }
+
+ std::vector<fs::path> _testFiles;
+};
+}; // namespace mongo::sdam
+
+int main(int argc, char* argv[]) {
+ ArgParser args(argc, argv);
+
+ ::mongo::logger::globalLogDomain()->setMinimumLoggedSeverity(
+ ::mongo::logger::LogSeverity::Debug(args.Verbose()));
+ args.LogParams();
+
+ ServerSelectionJsonTestRunner testRunner(args.SourceDirectory(), args.TestFilters());
+ return testRunner.report(testRunner.runTests());
+}
diff --git a/src/mongo/client/sdam/topology_description.cpp b/src/mongo/client/sdam/topology_description.cpp
index cd89535e1bc..b3ccc6f6c8d 100644
--- a/src/mongo/client/sdam/topology_description.cpp
+++ b/src/mongo/client/sdam/topology_description.cpp
@@ -129,7 +129,6 @@ boost::optional<ServerDescriptionPtr> TopologyDescription::installServerDescript
const auto& currentDescription = *it;
if (currentDescription->getAddress() == newServerDescription->getAddress()) {
previousDescription = *it;
-
*it = std::shared_ptr<ServerDescription>(newServerDescription);
break;
}
@@ -139,14 +138,11 @@ boost::optional<ServerDescriptionPtr> TopologyDescription::installServerDescript
_servers.push_back(std::shared_ptr<ServerDescription>(newServerDescription));
}
}
-
newServerDescription->_topologyDescription = shared_from_this();
-
checkWireCompatibilityVersions();
calculateLogicalSessionTimeout();
topologyDescriptionInstallServerDescription.shouldFail();
-
return previousDescription;
}