Skip to content

Commit 05f0fd2

Browse files
RUST-1077 Update read/write concern document tests (#567)
1 parent 1bf3b4b commit 05f0fd2

File tree

2 files changed

+94
-61
lines changed

2 files changed

+94
-61
lines changed

src/concern/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,14 @@ pub struct WriteConcern {
208208
/// Note that an error being returned due to a write concern error does not imply that the
209209
/// write would not have finished propagating if allowed more time to finish, and the
210210
/// server will not roll back the writes that occurred before the timeout was reached.
211-
#[serde(rename = "wtimeout")]
211+
#[serde(rename = "wtimeout", alias = "wtimeoutMS")]
212212
#[serde(serialize_with = "bson_util::serialize_duration_option_as_int_millis")]
213213
#[serde(deserialize_with = "bson_util::deserialize_duration_option_from_u64_millis")]
214214
#[serde(default)]
215215
pub w_timeout: Option<Duration>,
216216

217217
/// Requests acknowledgement that the operation has propagated to the on-disk journal.
218-
#[serde(rename = "j")]
218+
#[serde(rename = "j", alias = "journal")]
219219
pub journal: Option<bool>,
220220
}
221221

@@ -285,11 +285,12 @@ impl From<String> for Acknowledgment {
285285
}
286286

287287
impl WriteConcern {
288-
#[allow(dead_code)]
289288
pub(crate) fn is_acknowledged(&self) -> bool {
290289
self.w != Some(Acknowledgment::Nodes(0)) || self.journal == Some(true)
291290
}
292291

292+
/// Whether the write concern was created with no values specified. If true, the write concern
293+
/// should be considered the server's default.
293294
pub(crate) fn is_empty(&self) -> bool {
294295
self.w == None && self.w_timeout == None && self.journal == None
295296
}

src/test/spec/read_write_concern/document.rs

Lines changed: 90 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
use std::time::Duration;
2-
31
use serde::Deserialize;
42

53
use crate::{
6-
bson::{Bson, Document},
4+
bson::Document,
75
error::Error,
8-
options::{Acknowledgment, WriteConcern},
6+
options::{ReadConcern, WriteConcern},
97
test::run_spec_test,
108
};
119

@@ -15,80 +13,114 @@ struct TestFile {
1513
}
1614

1715
#[derive(Debug, Deserialize)]
18-
// TODO RUST-1077: remove the #[allow(dead_code)] tag and add #[serde(deny_unknown_fields)] to
19-
// ensure these tests are being fully run
20-
#[allow(dead_code)]
21-
#[serde(rename_all = "camelCase")]
16+
#[serde(rename_all = "camelCase", deny_unknown_fields)]
2217
struct TestCase {
2318
pub description: String,
2419
pub valid: bool,
2520
pub write_concern: Option<Document>,
2621
pub write_concern_document: Option<Document>,
2722
pub read_concern: Option<Document>,
2823
pub read_concern_document: Option<Document>,
24+
pub is_server_default: Option<bool>,
2925
pub is_acknowledged: Option<bool>,
3026
}
3127

32-
fn write_concern_from_document(write_concern_doc: Document) -> Option<WriteConcern> {
33-
let mut write_concern = WriteConcern::default();
28+
async fn run_document_test(test_file: TestFile) {
29+
for test_case in test_file.tests {
30+
let description = test_case.description.as_str();
3431

35-
for (key, value) in write_concern_doc {
36-
match (&key[..], value) {
37-
("w", Bson::Int32(i)) => {
38-
write_concern.w = Some(Acknowledgment::from(i as u32));
39-
}
40-
("w", Bson::String(s)) => {
41-
write_concern.w = Some(Acknowledgment::from(s));
42-
}
43-
("journal", Bson::Boolean(b)) => {
44-
write_concern.journal = Some(b);
45-
}
46-
("wtimeoutMS", Bson::Int32(i)) if i > 0 => {
47-
write_concern.w_timeout = Some(Duration::from_millis(i as u64));
32+
if let Some(specified_write_concern_document) = test_case.write_concern {
33+
let specified_write_concern =
34+
match bson::from_document::<WriteConcern>(specified_write_concern_document)
35+
.map_err(Error::from)
36+
.and_then(|wc| wc.validate().map(|_| wc))
37+
{
38+
Ok(write_concern) => {
39+
assert!(
40+
test_case.valid,
41+
"Write concern deserialization/validation should fail: {}",
42+
description
43+
);
44+
write_concern
45+
}
46+
Err(err) => {
47+
assert!(
48+
!test_case.valid,
49+
"Write concern deserialization/validation should succeed but got \
50+
{:?}: {}",
51+
err, description,
52+
);
53+
continue;
54+
}
55+
};
56+
57+
if let Some(is_server_default) = test_case.is_server_default {
58+
assert_eq!(
59+
specified_write_concern.is_empty(),
60+
is_server_default,
61+
"is_server_default is {} but write concern is {:?}: {}",
62+
is_server_default,
63+
&specified_write_concern,
64+
description
65+
);
4866
}
49-
("wtimeoutMS", Bson::Int32(_)) => {
50-
// WriteConcern has an unsigned integer for the wtimeout field, so this is
51-
// impossible to test.
52-
return None;
67+
68+
if let Some(is_acknowledged) = test_case.is_acknowledged {
69+
assert_eq!(
70+
specified_write_concern.is_acknowledged(),
71+
is_acknowledged,
72+
"is_acknowledged is {} but write concern is {:?}: {}",
73+
is_acknowledged,
74+
&specified_write_concern,
75+
description
76+
);
5377
}
54-
_ => {}
55-
};
56-
}
5778

58-
Some(write_concern)
59-
}
79+
let actual_write_concern_document = bson::to_document(&specified_write_concern)
80+
.unwrap_or_else(|err| {
81+
panic!(
82+
"Write concern serialization should succeed but got {:?}: {}",
83+
err, description
84+
)
85+
});
6086

61-
async fn run_document_test(test_file: TestFile) {
62-
for test_case in test_file.tests {
63-
if let Some(specified_write_concern) = test_case.write_concern {
64-
let wc = write_concern_from_document(specified_write_concern).map(|write_concern| {
65-
write_concern.validate().map_err(Error::from).and_then(|_| {
66-
let doc = bson::to_bson(&write_concern)?;
87+
if let Some(expected_write_concern_document) = test_case.write_concern_document {
88+
assert_eq!(
89+
actual_write_concern_document, expected_write_concern_document,
90+
"{}",
91+
description
92+
);
93+
}
94+
}
95+
96+
if let Some(specified_read_concern_document) = test_case.read_concern {
97+
// It's impossible to construct an empty `ReadConcern` (i.e. the server's default) in
98+
// the Rust driver so we skip this test.
99+
if test_case.description == "Default" {
100+
continue;
101+
}
67102

68-
Ok(doc)
69-
})
70-
});
103+
let specified_read_concern: ReadConcern =
104+
bson::from_document(specified_read_concern_document).unwrap_or_else(|err| {
105+
panic!(
106+
"Read concern deserialization should succeed but got {:?}: {}",
107+
err, description,
108+
)
109+
});
71110

72-
let actual_write_concern = match wc {
73-
Some(Ok(Bson::Document(write_concern))) => {
74-
assert!(test_case.valid, "{}", &test_case.description);
75-
write_concern
76-
}
77-
Some(Ok(x)) => panic!("wat: {:?}", x),
78-
Some(Err(_)) => {
79-
assert!(!test_case.valid, "{}", &test_case.description);
80-
continue;
81-
}
82-
None => {
83-
continue;
84-
}
85-
};
111+
let actual_read_concern_document = bson::to_document(&specified_read_concern)
112+
.unwrap_or_else(|err| {
113+
panic!(
114+
"Read concern serialization should succeed but got: {:?}: {}",
115+
err, description
116+
)
117+
});
86118

87-
if let Some(expected_write_concern) = test_case.write_concern_document {
119+
if let Some(expected_read_concern_document) = test_case.read_concern_document {
88120
assert_eq!(
89-
actual_write_concern, expected_write_concern,
121+
actual_read_concern_document, expected_read_concern_document,
90122
"{}",
91-
&test_case.description
123+
description
92124
);
93125
}
94126
}

0 commit comments

Comments
 (0)