Skip to content

Commit 037058e

Browse files
authored
RUST-1202 Sync latest initial DNS seedlist discovery tests (#595)
1 parent 7d25033 commit 037058e

40 files changed

+583
-114
lines changed

src/test/spec/initial_dns_seedlist_discovery.rs

Lines changed: 95 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ use crate::{
1515
#[serde(deny_unknown_fields)]
1616
struct TestFile {
1717
uri: String,
18-
seeds: Vec<String>,
19-
hosts: Vec<String>,
18+
seeds: Option<Vec<String>>,
19+
hosts: Option<Vec<String>>,
2020
options: Option<ResolvedOptions>,
2121
parsed_options: Option<ParsedOptions>,
2222
error: Option<bool>,
2323
comment: Option<String>,
24+
#[serde(rename = "numSeeds")]
25+
num_seeds: Option<usize>,
26+
#[serde(rename = "numHosts")]
27+
num_hosts: Option<usize>,
2428
}
2529

2630
#[derive(Debug, Deserialize, PartialEq)]
@@ -31,6 +35,8 @@ struct ResolvedOptions {
3135
ssl: bool,
3236
load_balanced: Option<bool>,
3337
direct_connection: Option<bool>,
38+
srv_max_hosts: Option<u32>,
39+
srv_service_name: Option<String>,
3440
}
3541

3642
impl ResolvedOptions {
@@ -56,26 +62,25 @@ struct ParsedOptions {
5662
}
5763

5864
async fn run_test(mut test_file: TestFile) {
59-
// TODO DRIVERS-796: unskip this test
60-
if test_file.uri == "mongodb+srv://test5.test.build.10gen.cc/?authSource=otherDB" {
61-
log_uncaptured(
62-
"skipping initial_dns_seedlist_discovery due to authSource being specified without \
63-
credentials",
64-
);
65-
return;
66-
}
65+
if let Some(ref options) = test_file.options {
66+
// TODO RUST-933: Remove this skip.
67+
let skip = if options.srv_max_hosts.is_some() {
68+
Some("srvMaxHosts")
69+
// TODO RUST-911: Remove this skip.
70+
} else if options.srv_service_name.is_some() {
71+
Some("srvServiceName")
72+
} else {
73+
None
74+
};
6775

68-
// TODO RUST-980 unskip these tests
69-
if test_file
70-
.options
71-
.as_ref()
72-
.and_then(|o| o.load_balanced)
73-
.unwrap_or(false)
74-
{
75-
log_uncaptured(
76-
"skipping initial_dns_seedlist_discovery due to load-balanced test configuration",
77-
);
78-
return;
76+
if let Some(skip) = skip {
77+
log_uncaptured(format!(
78+
"skipping initial_dns_seedlist_discovery test case due to unsupported connection \
79+
string option: {}",
80+
skip,
81+
));
82+
return;
83+
}
7984
}
8085

8186
// "encoded-userinfo-and-db.json" specifies a database name with a question mark which is
@@ -104,38 +109,32 @@ async fn run_test(mut test_file: TestFile) {
104109

105110
let options = result.unwrap();
106111

107-
let mut expected_seeds = test_file.seeds.split_off(0);
108-
let mut actual_seeds = options
109-
.hosts
110-
.iter()
111-
.map(|address| address.to_string())
112-
.collect::<Vec<_>>();
112+
if let Some(ref mut expected_seeds) = test_file.seeds {
113+
let mut actual_seeds = options
114+
.hosts
115+
.iter()
116+
.map(|address| address.to_string())
117+
.collect::<Vec<_>>();
113118

114-
expected_seeds.sort();
115-
actual_seeds.sort();
119+
expected_seeds.sort();
120+
actual_seeds.sort();
116121

117-
assert_eq!(expected_seeds, actual_seeds,);
122+
assert_eq!(*expected_seeds, actual_seeds);
123+
if let Some(expected_seed_count) = test_file.num_seeds {
124+
assert_eq!(actual_seeds.len(), expected_seed_count)
125+
}
126+
}
118127

119128
// "txt-record-with-overridden-ssl-option.json" requires SSL be disabled; see DRIVERS-1324.
120129
let requires_tls = match test_file.options {
121130
Some(ref options) => options.ssl,
122131
None => true,
123132
};
124133
let client = TestClient::new().await;
125-
let skip = if !client.is_replica_set() {
126-
Some("not replica set")
127-
} else if client.options.repl_set_name.as_deref() != Some("repl0") {
128-
Some("repl_set_name != repl0")
129-
} else if requires_tls != client.options.tls_options().is_some() {
130-
Some("tls requirement mismatch")
131-
} else {
132-
None
133-
};
134-
if let Some(skip) = skip {
135-
log_uncaptured(format!(
136-
"skipping initial_dns_seedlist_discovery due to topology ({})",
137-
skip
138-
))
134+
if requires_tls != client.options.tls_options().is_some() {
135+
log_uncaptured(
136+
"skipping initial_dns_seedlist_discovery test case due to TLS requirement mismatch",
137+
)
139138
} else {
140139
// If the connection URI provides authentication information, manually create the user
141140
// before connecting.
@@ -169,7 +168,9 @@ async fn run_test(mut test_file: TestFile) {
169168
.await
170169
.unwrap();
171170

172-
test_file.hosts.sort();
171+
if let Some(ref mut hosts) = test_file.hosts {
172+
hosts.sort();
173+
}
173174

174175
// This loop allows for some time to allow SDAM to discover the desired topology
175176
// TODO: RUST-232 or RUST-585: use SDAM monitoring / channels / timeouts to improve
@@ -179,8 +180,14 @@ async fn run_test(mut test_file: TestFile) {
179180
let mut actual_hosts = client.get_hosts().await;
180181
actual_hosts.sort();
181182

182-
if actual_hosts == test_file.hosts {
183-
break;
183+
if let Some(ref expected_hosts) = test_file.hosts {
184+
if actual_hosts == *expected_hosts {
185+
break;
186+
}
187+
} else if let Some(expected_host_count) = test_file.num_hosts {
188+
if actual_hosts.len() == expected_host_count {
189+
break;
190+
}
184191
} else if start.elapsed() > Duration::from_secs(5) {
185192
panic!(
186193
"expected to eventually discover {:?}, instead found {:?}",
@@ -219,16 +226,57 @@ async fn run_test(mut test_file: TestFile) {
219226
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
220227
async fn replica_set() {
221228
let _guard: RwLockReadGuard<()> = LOCK.run_concurrently().await;
229+
let client = TestClient::new().await;
230+
let skip =
231+
if client.is_replica_set() && client.options.repl_set_name.as_deref() != Some("repl0") {
232+
Some("repl_set_name != repl0")
233+
} else if !client.is_replica_set() {
234+
Some("not a replica set")
235+
} else {
236+
None
237+
};
238+
if let Some(skip) = skip {
239+
log_uncaptured(format!(
240+
"skipping initial_dns_seedlist_discovery::replica_set due to unmet topology \
241+
requirement ({})",
242+
skip
243+
));
244+
return;
245+
}
246+
222247
run_spec_test(&["initial-dns-seedlist-discovery", "replica-set"], run_test).await;
223248
}
224249

225250
#[cfg_attr(feature = "tokio-runtime", tokio::test)]
226251
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
227252
async fn load_balanced() {
228253
let _guard: RwLockReadGuard<()> = LOCK.run_concurrently().await;
254+
let client = TestClient::new().await;
255+
if !client.is_load_balanced() {
256+
log_uncaptured(
257+
"skipping initial_dns_seedlist_discovery::load_balanced due to unmet topology \
258+
requirement (not a load balanced cluster)",
259+
);
260+
return;
261+
}
229262
run_spec_test(
230263
&["initial-dns-seedlist-discovery", "load-balanced"],
231264
run_test,
232265
)
233266
.await;
234267
}
268+
269+
#[cfg_attr(feature = "tokio-runtime", tokio::test)]
270+
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
271+
async fn sharded() {
272+
let _guard: RwLockReadGuard<()> = LOCK.run_concurrently().await;
273+
let client = TestClient::new().await;
274+
if !client.is_sharded() {
275+
log_uncaptured(
276+
"skipping initial_dns_seedlist_discovery::sharded due to unmet topology requirement \
277+
(not a sharded cluster)",
278+
);
279+
return;
280+
}
281+
run_spec_test(&["initial-dns-seedlist-discovery", "sharded"], run_test).await;
282+
}

src/test/spec/json/initial-dns-seedlist-discovery/README.rst

Lines changed: 90 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,21 @@ Test Setup
1010

1111
The tests in the ``replica-set`` directory MUST be executed against a
1212
three-node replica set on localhost ports 27017, 27018, and 27019 with
13-
replica set name ``repl0``. The tests in ``load-balanced`` MUST be executed
14-
against a load-balanced sharded cluster with the mongos servers running on
15-
localhost ports 27017 and 27018 and load balancers, shard servers, and config
16-
servers running on any open ports. In both cases, the clusters MUST be
17-
started with SSL enabled.
13+
replica set name ``repl0``.
14+
15+
The tests in the ``load-balanced`` directory MUST be executed against a
16+
load-balanced sharded cluster with the mongos servers running on localhost ports
17+
27017 and 27018 and ``--loadBalancerPort`` 27050 and 27051, respectively
18+
(corresponding to the script in `drivers-evergreen-tools`_). The load balancers,
19+
shard servers, and config servers may run on any open ports.
20+
21+
.. _`drivers-evergreen-tools`: https://github.com/mongodb-labs/drivers-evergreen-tools/blob/master/.evergreen/run-load-balancer.sh
22+
23+
The tests in the ``sharded`` directory MUST be executed against a sharded
24+
cluster with the mongos servers running on localhost ports 27017 and 27018.
25+
Shard servers and config servers may run on any open ports.
26+
27+
In all cases, the clusters MUST be started with SSL enabled.
1828

1929
To run the tests that accompany this spec, you need to configure the SRV and
2030
TXT records with a real name server. The following records are required for
@@ -24,29 +34,32 @@ these tests::
2434
localhost.test.build.10gen.cc. 86400 IN A 127.0.0.1
2535
localhost.sub.test.build.10gen.cc. 86400 IN A 127.0.0.1
2636

27-
Record TTL Class Port Target
28-
_mongodb._tcp.test1.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
29-
_mongodb._tcp.test1.test.build.10gen.cc. 86400 IN SRV 27018 localhost.test.build.10gen.cc.
30-
_mongodb._tcp.test2.test.build.10gen.cc. 86400 IN SRV 27018 localhost.test.build.10gen.cc.
31-
_mongodb._tcp.test2.test.build.10gen.cc. 86400 IN SRV 27019 localhost.test.build.10gen.cc.
32-
_mongodb._tcp.test3.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
33-
_mongodb._tcp.test5.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
34-
_mongodb._tcp.test6.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
35-
_mongodb._tcp.test7.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
36-
_mongodb._tcp.test8.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
37-
_mongodb._tcp.test10.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
38-
_mongodb._tcp.test11.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
39-
_mongodb._tcp.test12.test.build.10gen.cc. 86400 IN SRV 27017 localhost.build.10gen.cc.
40-
_mongodb._tcp.test13.test.build.10gen.cc. 86400 IN SRV 27017 test.build.10gen.cc.
41-
_mongodb._tcp.test14.test.build.10gen.cc. 86400 IN SRV 27017 localhost.not-test.build.10gen.cc.
42-
_mongodb._tcp.test15.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.not-build.10gen.cc.
43-
_mongodb._tcp.test16.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.not-10gen.cc.
44-
_mongodb._tcp.test17.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.not-cc.
45-
_mongodb._tcp.test18.test.build.10gen.cc. 86400 IN SRV 27017 localhost.sub.test.build.10gen.cc.
46-
_mongodb._tcp.test19.test.build.10gen.cc. 86400 IN SRV 27017 localhost.evil.build.10gen.cc.
47-
_mongodb._tcp.test19.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
48-
_mongodb._tcp.test20.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
49-
_mongodb._tcp.test21.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
37+
Record TTL Class Port Target
38+
_mongodb._tcp.test1.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
39+
_mongodb._tcp.test1.test.build.10gen.cc. 86400 IN SRV 27018 localhost.test.build.10gen.cc.
40+
_mongodb._tcp.test2.test.build.10gen.cc. 86400 IN SRV 27018 localhost.test.build.10gen.cc.
41+
_mongodb._tcp.test2.test.build.10gen.cc. 86400 IN SRV 27019 localhost.test.build.10gen.cc.
42+
_mongodb._tcp.test3.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
43+
_mongodb._tcp.test5.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
44+
_mongodb._tcp.test6.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
45+
_mongodb._tcp.test7.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
46+
_mongodb._tcp.test8.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
47+
_mongodb._tcp.test10.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
48+
_mongodb._tcp.test11.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
49+
_mongodb._tcp.test12.test.build.10gen.cc. 86400 IN SRV 27017 localhost.build.10gen.cc.
50+
_mongodb._tcp.test13.test.build.10gen.cc. 86400 IN SRV 27017 test.build.10gen.cc.
51+
_mongodb._tcp.test14.test.build.10gen.cc. 86400 IN SRV 27017 localhost.not-test.build.10gen.cc.
52+
_mongodb._tcp.test15.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.not-build.10gen.cc.
53+
_mongodb._tcp.test16.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.not-10gen.cc.
54+
_mongodb._tcp.test17.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.not-cc.
55+
_mongodb._tcp.test18.test.build.10gen.cc. 86400 IN SRV 27017 localhost.sub.test.build.10gen.cc.
56+
_mongodb._tcp.test19.test.build.10gen.cc. 86400 IN SRV 27017 localhost.evil.build.10gen.cc.
57+
_mongodb._tcp.test19.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
58+
_mongodb._tcp.test20.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
59+
_mongodb._tcp.test21.test.build.10gen.cc. 86400 IN SRV 27017 localhost.test.build.10gen.cc.
60+
_customname._tcp.test22.test.build.10gen.cc 86400 IN SRV 27017 localhost.test.build.10gen.cc.
61+
_mongodb._tcp.test23.test.build.10gen.cc. 86400 IN SRV 8000 localhost.test.build.10gen.cc.
62+
_mongodb._tcp.test24.test.build.10gen.cc. 86400 IN SRV 8000 localhost.test.build.10gen.cc.
5063

5164
Record TTL Class Text
5265
test5.test.build.10gen.cc. 86400 IN TXT "replicaSet=repl0&authSource=thisDB"
@@ -58,11 +71,18 @@ these tests::
5871
test11.test.build.10gen.cc. 86400 IN TXT "replicaS" "et=rep" "l0"
5972
test20.test.build.10gen.cc. 86400 IN TXT "loadBalanced=true"
6073
test21.test.build.10gen.cc. 86400 IN TXT "loadBalanced=false"
74+
test24.test.build.10gen.cc. 86400 IN TXT "loadBalanced=true"
75+
76+
Notes:
6177

62-
Note that ``test4`` is omitted deliberately to test what happens with no SRV
63-
record. ``test9`` is missing because it was deleted during the development of
64-
the tests. The missing ``test.`` sub-domain in the SRV record target for
65-
``test12`` is deliberate.
78+
- ``test4`` is omitted deliberately to test what happens with no SRV record.
79+
- ``test9`` is missing because it was deleted during the development of the
80+
tests.
81+
- The missing ``test.`` sub-domain in the SRV record target for ``test12`` is
82+
deliberate.
83+
- ``test22`` is used to test a custom service name (``customname``).
84+
- ``test23`` and ``test24`` point to port 8000 (HAProxy) and are used for
85+
load-balanced tests.
6686

6787
In our tests we have used ``localhost.test.build.10gen.cc`` as the domain, and
6888
then configured ``localhost.test.build.10gen.cc`` to resolve to 127.0.0.1.
@@ -76,28 +96,49 @@ Test Format and Use
7696

7797
These YAML and JSON files contain the following fields:
7898

79-
- ``uri``: a mongodb+srv connection string
99+
- ``uri``: a ``mongodb+srv`` connection string
80100
- ``seeds``: the expected set of initial seeds discovered from the SRV record
101+
- ``numSeeds``: the expected number of initial seeds discovered from the SRV
102+
record. This is mainly used to test ``srvMaxHosts``, since randomly selected
103+
hosts cannot be deterministically asserted.
81104
- ``hosts``: the discovered topology's list of hosts once SDAM completes a scan
82-
- ``options``: the parsed connection string options as discovered from URI and
83-
TXT records
84-
- ``parsed_options``: additional options present in the `Connection String`_
85-
URI such as ``Userinfo`` (as ``user`` and ``password``), and ``Auth
86-
database`` (as ``auth_database``).
105+
- ``numHosts``: the expected number of hosts discovered once SDAM completes a
106+
scan. This is mainly used to test ``srvMaxHosts``, since randomly selected
107+
hosts cannot be deterministically asserted.
108+
- ``options``: the parsed `URI options`_ as discovered from the
109+
`Connection String`_'s "Connection Options" component and SRV resolution
110+
(e.g. TXT records, implicit ``tls`` default).
111+
- ``parsed_options``: additional, parsed options from other `Connection String`_
112+
components. This is mainly used for asserting ``UserInfo`` (as ``user`` and
113+
``password``) and ``Auth database`` (as ``auth_database``).
87114
- ``error``: indicates that the parsing of the URI, or the resolving or
88115
contents of the SRV or TXT records included errors.
89116
- ``comment``: a comment to indicate why a test would fail.
90117

91118
.. _`Connection String`: ../../connection-string/connection-string-spec.rst
119+
.. _`URI options`: ../../uri-options/uri-options.rst
120+
121+
For each file, create a MongoClient initialized with the ``mongodb+srv``
122+
connection string.
123+
124+
If ``seeds`` is specified, drivers SHOULD verify that the set of hosts in the
125+
client's initial seedlist matches the list in ``seeds``. If ``numSeeds`` is
126+
specified, drivers SHOULD verify that the size of that set matches ``numSeeds``.
127+
128+
If ``hosts`` is specified, drivers MUST verify that the set of
129+
ServerDescriptions in the client's TopologyDescription eventually matches the
130+
list in ``hosts``. If ``numHosts`` is specified, drivers MUST verify that the
131+
size of that set matches ``numHosts``.
132+
133+
If ``options`` is specified, drivers MUST verify each of the values under
134+
``options`` match the MongoClient's parsed value for that option. There may be
135+
other options parsed by the MongoClient as well, which a test does not verify.
136+
137+
If ``parsed_options`` is specified, drivers MUST verify that each of the values
138+
under ``parsed_options`` match the MongoClient's parsed value for that option.
139+
Supported values include, but are not limited to, ``user`` and ``password``
140+
(parsed from ``UserInfo``) and ``auth_database`` (parsed from
141+
``Auth database``).
92142

93-
For each file, create MongoClient initialized with the mongodb+srv connection
94-
string. You SHOULD verify that the client's initial seed list matches the list of
95-
seeds. You MUST verify that the set of ServerDescriptions in the client's
96-
TopologyDescription eventually matches the list of hosts. You MUST verify that
97-
each of the values of the Connection String Options under ``options`` match the
98-
Client's parsed value for that option. There may be other options parsed by
99-
the Client as well, which a test does not verify. In ``uri-with-auth`` the URI
100-
contains a user/password set and additional options are provided in
101-
``parsed_options`` so that tests can verify authentication is maintained when
102-
evaluating URIs. You MUST verify that an error has been thrown if ``error`` is
103-
present.
143+
If ``error`` is specified and ``true``, drivers MUST verify that an error has
144+
been thrown.

0 commit comments

Comments
 (0)