Skip to content

Commit 38a3099

Browse files
authored
RUST-662 Expose errInfo as details in WriteError (#375)
* RUST-662 Expose errInfo as details in WriteError * Add a rountrip test for write error details
1 parent 3312975 commit 38a3099

File tree

6 files changed

+70
-1
lines changed

6 files changed

+70
-1
lines changed

src/error.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,11 @@ pub struct WriteError {
472472
/// A description of the error that occurred.
473473
#[serde(rename = "errmsg")]
474474
pub message: String,
475+
476+
/// A document providing more information about the write error (e.g. details
477+
/// pertaining to document validation).
478+
#[serde(rename = "errInfo")]
479+
pub details: Option<Document>,
475480
}
476481

477482
/// An error that occurred during a write operation consisting of multiple writes that wasn't due to
@@ -496,6 +501,11 @@ pub struct BulkWriteError {
496501
/// A description of the error that occurred.
497502
#[serde(rename = "errmsg")]
498503
pub message: String,
504+
505+
/// A document providing more information about the write error (e.g. details
506+
/// pertaining to document validation).
507+
#[serde(rename = "errInfo")]
508+
pub details: Option<Document>,
499509
}
500510

501511
/// The set of errors that occurred during a write operation.
@@ -542,6 +552,7 @@ impl WriteFailure {
542552
code: bulk_write_error.code,
543553
code_name: bulk_write_error.code_name,
544554
message: bulk_write_error.message,
555+
details: bulk_write_error.details,
545556
};
546557
Ok(WriteFailure::WriteError(write_error))
547558
} else if let Some(wc_error) = bulk.write_concern_error {

src/operation/delete/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ async fn handle_write_failure() {
149149
code: 1234,
150150
code_name: None,
151151
message: "my error string".to_string(),
152+
details: None,
152153
};
153154
assert_eq!(error, &expected_err);
154155
}

src/operation/insert/test.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,10 @@ async fn handle_write_failure() {
187187
{
188188
"index": 1,
189189
"code": 11000,
190-
"errmsg": "duplicate key"
190+
"errmsg": "duplicate key",
191+
"errInfo": {
192+
"test key": "test value",
193+
}
191194
}
192195
],
193196
"writeConcernError": {
@@ -218,6 +221,7 @@ async fn handle_write_failure() {
218221
code: 11000,
219222
code_name: None,
220223
message: "duplicate key".to_string(),
224+
details: Some(doc! { "test key": "test value" }),
221225
};
222226
assert_eq!(write_errors.first().unwrap(), &expected_err);
223227

src/operation/update/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ async fn handle_write_failure() {
232232
code: 1234,
233233
code_name: None,
234234
message: "my error string".to_string(),
235+
details: None,
235236
};
236237
assert_eq!(error, &expected_err);
237238
}

src/test/spec/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod transactions;
1717
mod unified_runner;
1818
mod v2_runner;
1919
mod versioned_api;
20+
mod write_error;
2021

2122
use std::{
2223
convert::TryFrom,

src/test/spec/write_error.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use crate::{
2+
bson::{doc, Document},
3+
error::{ErrorKind, WriteFailure},
4+
options::CreateCollectionOptions,
5+
test::{EventClient, LOCK},
6+
Collection,
7+
};
8+
9+
#[cfg_attr(feature = "tokio-runtime", tokio::test)]
10+
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
11+
async fn details() {
12+
let _guard = LOCK.run_concurrently().await;
13+
let client = EventClient::new().await;
14+
if client.server_version_lt(5, 0) {
15+
return;
16+
}
17+
18+
let db = client.database("write_error_details");
19+
db.drop(None).await.unwrap();
20+
db.create_collection(
21+
"test",
22+
CreateCollectionOptions::builder()
23+
.validator(doc! {
24+
"x": { "$type": "string" }
25+
})
26+
.build(),
27+
)
28+
.await
29+
.unwrap();
30+
let coll: Collection<Document> = db.collection("test");
31+
let err = coll.insert_one(doc! { "x": 1 }, None).await.unwrap_err();
32+
let write_err = match *err.kind {
33+
ErrorKind::Write(WriteFailure::WriteError(e)) => e,
34+
_ => panic!("expected WriteError, got {:?}", err.kind),
35+
};
36+
let (_, event) = client.get_successful_command_execution("insert");
37+
assert_eq!(write_err.code, 121 /* DocumentValidationFailure */);
38+
assert_eq!(
39+
&write_err.details.unwrap(),
40+
event
41+
.reply
42+
.get_array("writeErrors")
43+
.unwrap()
44+
.get(0)
45+
.unwrap()
46+
.as_document()
47+
.unwrap()
48+
.get_document("errInfo")
49+
.unwrap()
50+
);
51+
}

0 commit comments

Comments
 (0)