use bson::{bson, doc, Bson, Document};
use crate::{
cmap::{CommandResponse, StreamDescription},
concern::WriteConcern,
error::{BulkWriteError, ErrorKind, WriteConcernError},
operation::{Insert, Operation},
options::InsertManyOptions,
Namespace,
};
struct TestFixtures {
op: Insert,
documents: Vec<Document>,
options: InsertManyOptions,
}
fn fixtures() -> TestFixtures {
let documents = vec![
Document::new(),
doc! {"_id": 1234, "a": 1},
doc! {"a": 123, "b": "hello world" },
];
let options = InsertManyOptions {
ordered: Some(true),
write_concern: Some(WriteConcern::builder().journal(true).build()),
..Default::default()
};
let op = Insert::new(
Namespace {
db: "test_db".to_string(),
coll: "test_coll".to_string(),
},
documents.clone(),
Some(options.clone()),
);
TestFixtures {
op,
documents,
options,
}
}
#[test]
fn build() {
let fixtures = fixtures();
let description = StreamDescription::new_testing();
let cmd = fixtures.op.build(&description).unwrap();
assert_eq!(cmd.name.as_str(), "insert");
assert_eq!(cmd.target_db.as_str(), "test_db");
assert_eq!(cmd.read_pref.as_ref(), None);
assert_eq!(
cmd.body.get("insert").unwrap(),
&Bson::String("test_coll".to_string())
);
let mut cmd_docs: Vec<Document> = cmd
.body
.get("documents")
.unwrap()
.as_array()
.unwrap()
.iter()
.map(|b| b.as_document().unwrap().clone())
.collect();
assert_eq!(cmd_docs.len(), fixtures.documents.len());
for (original_doc, cmd_doc) in fixtures.documents.iter().zip(cmd_docs.iter_mut()) {
assert!(cmd_doc.get("_id").is_some());
if original_doc.get("_id").is_some() {
assert_eq!(original_doc, cmd_doc);
} else {
cmd_doc.remove("_id");
assert_eq!(original_doc, cmd_doc);
};
}
assert_eq!(
cmd.body.get("ordered"),
fixtures.options.ordered.map(Bson::Boolean).as_ref()
);
assert_eq!(
cmd.body.get("bypassDocumentValidation"),
fixtures
.options
.bypass_document_validation
.map(Bson::Boolean)
.as_ref()
);
assert_eq!(
cmd.body.get("writeConcern"),
fixtures
.options
.write_concern
.as_ref()
.map(|wc| bson::to_bson(wc).unwrap())
.as_ref()
);
}
#[test]
fn build_ordered() {
let insert = Insert::new(Namespace::empty(), Vec::new(), None);
let cmd = insert
.build(&StreamDescription::new_testing())
.expect("should succeed");
assert_eq!(cmd.body.get("ordered"), Some(&Bson::Boolean(true)));
let insert = Insert::new(
Namespace::empty(),
Vec::new(),
Some(InsertManyOptions::builder().ordered(false).build()),
);
let cmd = insert
.build(&StreamDescription::new_testing())
.expect("should succeed");
assert_eq!(cmd.body.get("ordered"), Some(&Bson::Boolean(false)));
let insert = Insert::new(
Namespace::empty(),
Vec::new(),
Some(InsertManyOptions::builder().ordered(true).build()),
);
let cmd = insert
.build(&StreamDescription::new_testing())
.expect("should succeed");
assert_eq!(cmd.body.get("ordered"), Some(&Bson::Boolean(true)));
}
#[test]
fn handle_success() {
let fixtures = fixtures();
let ok_response = CommandResponse::with_document(doc! { "ok": 1.0, "n": 3 });
let ok_result = fixtures.op.handle_response(ok_response);
assert!(ok_result.is_ok());
let inserted_ids = ok_result.unwrap().inserted_ids;
assert_eq!(inserted_ids.len(), 3); assert_eq!(
inserted_ids.get(&1).unwrap(),
fixtures.documents[1].get("_id").unwrap()
);
}
#[test]
fn handle_invalid_response() {
let fixtures = fixtures();
let invalid_response = CommandResponse::with_document(doc! { "ok": 1.0, "asdfadsf": 123123 });
assert!(fixtures.op.handle_response(invalid_response).is_err());
}
#[test]
fn handle_write_failure() {
let fixtures = fixtures();
let write_error_response = CommandResponse::with_document(doc! {
"ok": 1.0,
"n": 1,
"writeErrors": [
{
"index": 1,
"code": 11000,
"errmsg": "duplicate key"
}
],
"writeConcernError": {
"code": 123,
"codeName": "woohoo",
"errmsg": "error message"
}
});
let write_error_result = fixtures.op.handle_response(write_error_response);
assert!(write_error_result.is_err());
match *write_error_result.unwrap_err().kind {
ErrorKind::BulkWriteError(ref error) => {
let write_errors = error.write_errors.clone().unwrap();
assert_eq!(write_errors.len(), 1);
let expected_err = BulkWriteError {
index: 1,
code: 11000,
code_name: None,
message: "duplicate key".to_string(),
};
assert_eq!(write_errors.first().unwrap(), &expected_err);
let write_concern_error = error.write_concern_error.clone().unwrap();
let expected_wc_err = WriteConcernError {
code: 123,
code_name: "woohoo".to_string(),
message: "error message".to_string(),
};
assert_eq!(write_concern_error, expected_wc_err);
}
ref e => panic!("expected bulk write error, got {:?}", e),
};
}