From 85477775c4d88169d3814102cf25b3f4a8526219 Mon Sep 17 00:00:00 2001 From: Jeff Baskin Date: Sat, 18 Oct 2025 13:03:36 -0400 Subject: [PATCH] Finished readding the commented tests. --- src/message.rs | 798 ++++++++++++++++--------------------------------- 1 file changed, 250 insertions(+), 548 deletions(-) diff --git a/src/message.rs b/src/message.rs index 3b1dc81..b153e61 100644 --- a/src/message.rs +++ b/src/message.rs @@ -27,7 +27,7 @@ enum MTTError { DocumentFieldNotFound(String), DocumentFieldWrongDataType(FieldType, FieldType), DocumentNotFound(String), - FieldDuplicate(String, Field), + FieldDuplicate, FieldMissingData, InvalidNone, RecordMismatch, @@ -304,10 +304,7 @@ mod messages { #[test] fn can_the_document_be_a_stringi_reference() { - let dts = [ - Name::english("one"), - Name::english("two"), - ]; + let dts = [Name::english("one"), Name::english("two")]; for document in dts.into_iter() { let msg = Message::new( document.clone(), @@ -552,14 +549,20 @@ impl Name { &self.lang } - fn english(name: S) -> Self where S: Into { + fn english(name: S) -> Self + where + S: Into, + { Self { name: name.into(), lang: Language::from_639_1("en").unwrap(), } } - fn japanese(name: S) -> Self where S: Into { + fn japanese(name: S) -> Self + where + S: Into, + { Self { name: name.into(), lang: Language::from_639_1("ja").unwrap(), @@ -1132,305 +1135,6 @@ impl RouteRequest { } } -/* -struct QueueData { - senders: HashMap>, - names: HashMap, - routes: HashMap>, -} - -impl QueueData { - fn new() -> Self { - Self { - senders: HashMap::new(), - names: HashMap::new(), - routes: HashMap::new(), - } - } - - fn get_doc_id(&self, nameid: N) -> Result - where - N: Into, - { - let sender_id = match nameid.into() { - NameID::Name(name) => match self.names.get(&name) { - Some(id) => id.clone(), - None => return Err(MTTError::DocumentNotFound(name.clone())), - }, - NameID::ID(id) => id.clone(), - NameID::None => unreachable!("should never be none"), - }; - if self.senders.contains_key(&sender_id) { - Ok(sender_id) - } else { - Err(MTTError::DocumentNotFound(sender_id.to_string())) - } - } - - fn register( - &mut self, - tx: Sender, - name: String, - routes: Vec, - ) -> Result<(), MTTError> { - let mut id = Uuid::new_v4(); - while self.senders.contains_key(&id) { - id = Uuid::new_v4(); - } - match self.get_doc_id(name.clone()) { - Ok(_) => return Err(MTTError::DocumentAlreadyExists(name)), - Err(_) => {} - } - let mut holder: HashMap> = HashMap::new(); - for route in routes.iter() { - let doc_type = match &route.doc_name { - Include::Some(doc_name) => { - if doc_name == &name { - Include::Some(id.clone()) - } else { - match self.get_doc_id(doc_name.to_string()) { - Ok(doc_id) => Include::Some(doc_id), - Err(err) => return Err(err), - } - } - } - Include::All => Include::All, - }; - let route_id: RouteID = - Route::new(route.msg_id.clone(), doc_type, route.action.clone()).into(); - match self.routes.get(&route_id) { - Some(senders) => { - let mut addition = senders.clone(); - addition.push(id.clone()); - holder.insert(route_id, addition); - } - None => { - let senders = [id.clone()].to_vec(); - holder.insert(route_id, senders); - } - } - } - self.senders.insert(id.clone(), tx); - self.names.insert(name.clone(), id.clone()); - for (route_id, senders) in holder.iter() { - self.routes.insert(route_id.clone(), senders.clone()); - } - Ok(()) - } - - fn send(&self, msg: Message) -> Result<(), MTTError> { - let doc_id: Include = match self.get_doc_id(msg.get_document_id()) { - Ok(id) => Include::Some(id.clone()), - Err(err) => { - let action: Action = msg.get_action().into(); - if action == Action::Create { - Include::Some(Uuid::nil()) - } else { - return Err(err); - } - } - }; - let route = Route::new( - Include::Some(msg.get_message_id().clone()), - doc_id, - Include::Some(msg.get_action().into()), - ); - for (send_route, send_ids) in self.routes.iter() { - if route == send_route.into() { - for send_id in send_ids { - let tx = self.senders.get(&send_id).unwrap(); - tx.send(msg.clone()).unwrap(); - } - } - } - Ok(()) - } -} - -#[cfg(test)] -mod queuedatas { - use super::support_test::TIMEOUT; - use super::*; - use std::sync::mpsc::RecvTimeoutError; - - #[test] - fn can_document_be_registered() { - let mut queuedata = QueueData::new(); - let (tx, rx) = channel(); - let name = Uuid::new_v4().to_string(); - let routes = [ - RouteRequest::new( - Include::All, - Include::Some(name.clone()), - Include::Some(Action::Query), - ), - RouteRequest::new( - Include::All, - Include::Some(name.clone()), - Include::Some(Action::Reply), - ), - ] - .to_vec(); - queuedata.register(tx, name.clone(), routes).unwrap(); - let msg1 = Message::new(name.clone(), MsgAction::Query(Query::new())); - let msg2 = Message::new(name.clone(), MsgAction::Reply(Reply::new())); - let msg3 = Message::new(name.clone(), MsgAction::Create(DocDef::new())); - queuedata.send(msg1.clone()).unwrap(); - queuedata.send(msg2.clone()).unwrap(); - queuedata.send(msg3.clone()).unwrap(); - let result1 = rx.recv_timeout(TIMEOUT).unwrap(); - let result2 = rx.recv_timeout(TIMEOUT).unwrap(); - match rx.recv_timeout(TIMEOUT) { - Ok(_) => unreachable!("should have timed out"), - Err(err) => match err { - RecvTimeoutError::Timeout => {} - _ => unreachable!("should have timed out"), - }, - } - assert_eq!(result1.get_message_id(), msg1.get_message_id()); - assert_eq!(result2.get_message_id(), msg2.get_message_id()); - match result1.get_action() { - MsgAction::Query(_) => {} - _ => unreachable!("should have been a query"), - } - match result2.get_action() { - MsgAction::Reply(_) => {} - _ => unreachable!("should have been a query"), - } - } - - #[test] - fn does_register_fail_on_duplicate_documents() { - let mut queuedata = QueueData::new(); - let (tx1, _) = channel(); - let (tx2, _) = channel(); - let name = Uuid::new_v4().to_string(); - queuedata - .register(tx1, name.to_string(), Vec::new()) - .unwrap(); - match queuedata.register(tx2, name.to_string(), Vec::new()) { - Ok(_) => unreachable!("duplicates should create an error"), - Err(err) => match err { - MTTError::DocumentAlreadyExists(result) => assert_eq!(result, name), - _ => unreachable!("should have been document does not exists"), - }, - } - } - - #[test] - fn does_bad_route_prevent_registration() { - let mut queuedata = QueueData::new(); - let (tx, rx) = channel(); - let good = "good"; - let bad = Uuid::new_v4().to_string(); - let routes = [ - RouteRequest::new( - Include::All, - Include::Some(good.to_string()), - Include::Some(Action::Query), - ), - RouteRequest::new( - Include::All, - Include::Some(bad.clone()), - Include::Some(Action::Reply), - ), - ] - .to_vec(); - match queuedata.register(tx, good.to_string(), routes) { - Ok(_) => unreachable!("should produce an error"), - Err(err) => match err { - MTTError::DocumentNotFound(result) => assert_eq!(result, bad), - _ => unreachable!("Shouuld be document not found"), - }, - } - assert_eq!(queuedata.senders.len(), 0, "should not add to senders"); - assert_eq!(queuedata.names.len(), 0, "should not add to names"); - assert_eq!(queuedata.routes.len(), 0, "should nor add to routes"); - } - - #[test] - fn is_sender_only_added_once_to_routes() { - let mut queuedata = QueueData::new(); - let (tx, rx) = channel(); - let name = "project"; - let routes = [ - RouteRequest::new( - Include::All, - Include::Some(name.to_string()), - Include::Some(Action::Query), - ), - RouteRequest::new( - Include::All, - Include::Some(name.to_string()), - Include::Some(Action::Query), - ), - ] - .to_vec(); - queuedata.register(tx, name.to_string(), routes).unwrap(); - for senders in queuedata.routes.values() { - assert_eq!(senders.len(), 1, "should be no double entries"); - } - } - - #[test] - fn does_a_bad_document_name_fail() { - let docname = Uuid::new_v4().to_string(); - let queuedata = QueueData::new(); - let msg = Message::new(docname.clone(), MsgAction::Query(Query::new())); - match queuedata.send(msg) { - Ok(_) => unreachable!("should have been an error"), - Err(data) => match data { - MTTError::DocumentNotFound(doc) => assert_eq!(doc, docname), - _ => unreachable!("should have been a not found error"), - }, - } - } - - #[test] - fn is_send_okay_if_no_one_is_listening() { - let mut queuedata = QueueData::new(); - let name = "something"; - let (tx, _) = channel(); - queuedata - .register(tx, name.to_string(), Vec::new()) - .unwrap(); - let msg = Message::new("something", MsgAction::Create(DocDef::new())); - match queuedata.send(msg) { - Ok(_) => {} - Err(err) => unreachable!("got {:?}: should not error", err), - } - } - - #[test] - fn can_more_than_one_document_respond() { - let mut queuedata = QueueData::new(); - let name1 = "task"; - let name2 = "work"; - let action = MsgAction::Query(Query::new()); - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - let routes = [RouteRequest::new( - Include::All, - Include::Some(name1.to_string()), - Include::All, - )] - .to_vec(); - queuedata - .register(tx1, name1.to_string(), routes.clone()) - .unwrap(); - queuedata - .register(tx2, name2.to_string(), routes.clone()) - .unwrap(); - let msg = Message::new(name1, action.clone()); - queuedata.send(msg.clone()).unwrap(); - let result1 = rx1.recv_timeout(TIMEOUT).unwrap(); - let result2 = rx2.recv_timeout(TIMEOUT).unwrap(); - assert_eq!(result1.get_message_id(), msg.get_message_id()); - assert_eq!(result1.get_message_id(), result2.get_message_id()); - } -} -*/ - struct DocRegistry { doc_names: Names, queue: Queue, @@ -1755,10 +1459,7 @@ mod queues { fn can_register_routes() { let mut tester = TestQueue::new(); let mut queue = tester.get_queue(); - let names = [ - Name::english("task"), - Name::english("recipe"), - ]; + let names = [Name::english("task"), Name::english("recipe")]; for name in names.iter() { tester.add_document(name.clone()); } @@ -1785,10 +1486,7 @@ mod queues { fn can_multiple_register_for_the_same_route() { let mut tester = TestQueue::new(); let mut queue = tester.get_queue(); - let names = [ - Name::english("task"), - Name::english("recipe"), - ]; + let names = [Name::english("task"), Name::english("recipe")]; let route_req = Path::new(Include::All, Include::All, Include::All); let reg_msg = RegMsg::AddRoute(route_req); for name in names.iter() { @@ -1844,10 +1542,7 @@ mod queues { fn can_routing_be_based_on_message_id() { let mut tester = TestQueue::new(); let mut queue = tester.get_queue(); - let names = [ - Name::english("one"), - Name::english("two"), - ]; + let names = [Name::english("one"), Name::english("two")]; let mut inputs: HashMap = HashMap::new(); for name in names.iter() { tester.add_document(name.clone()); @@ -1885,10 +1580,7 @@ mod queues { fn can_routing_be_based_on_document_name() { let mut tester = TestQueue::new(); let mut queue = tester.get_queue(); - let names = [ - Name::english("one"), - Name::english("two"), - ]; + let names = [Name::english("one"), Name::english("two")]; let mut inputs: HashMap = HashMap::new(); for name in names.iter() { tester.add_document(name.clone()); @@ -1926,10 +1618,7 @@ mod queues { fn can_routing_be_based_on_action() { let mut tester = TestQueue::new(); let mut queue = tester.get_queue(); - let names = [ - Name::english("one"), - Name::english("two"), - ]; + let names = [Name::english("one"), Name::english("two")]; let paths = [ Path::new(Include::All, Include::All, Include::Some(Action::Reply)), Path::new(Include::All, Include::All, Include::Some(Action::Error)), @@ -2285,7 +1974,7 @@ mod fieldsettings { match fset.validate(None) { Ok(data) => unreachable!("got {:?}: should have gotten an error", data), Err(err) => match err { - MTTError::InvalidNone => {}, + MTTError::InvalidNone => {} _ => unreachable!("got {:?}: should have gotten a invalid none", err), }, } @@ -2525,17 +2214,6 @@ impl DocDef { Ok(_) => Ok(()), Err(err) => Err(err), } - - /* - let setting = match self.get_field_mut(field_name) { - Ok(data) => data, - Err(err) => return Err(err), - }; - match setting.set_default(value) { - Ok(_) => Ok(()), - Err(err) => Err(err), - } - */ } fn add_index(&mut self, field_name: &Name, index_type: IndexType) -> Result<(), MTTError> { @@ -2545,15 +2223,6 @@ impl DocDef { }; self.indexes.insert(id.clone(), index_type); Ok(()) - - /* - let setting = match self.get_field(&field_name) { - Ok(_) => {} - Err(err) => return Err(err), - }; - self.indexes.insert(field_name, index_type); - Ok(()) - */ } fn create_indexes(&self) -> Indexes { @@ -2683,27 +2352,6 @@ mod docdefs { }, } } - - /* - #[test] - fn returns_field_ids() { - let count = 5; - let mut ids: HashSet = HashSet::new(); - while ids.len() < count { - ids.insert(Name::english(Uuid::new_v4().to_string())); - } - let docname = Name::english("something".to_string()); - let mut docdef = DocDef::new(docname); - for id in ids.iter() { - docdef.add_field(id.clone(), FieldType::Uuid); - } - let result = docdef.field_ids(); - assert_eq!(result.len(), ids.len()); - for id in result.iter() { - assert!(ids.contains(id.clone())); - } - } - */ } #[derive(Clone, Debug)] @@ -3289,30 +2937,6 @@ mod queries { }, } } - - /* - #[test] - fn returns_set_of_fields() { - let count = 5; - let mut field_ids: HashSet = HashSet::new(); - while field_ids.len() < count { - field_ids.insert(Name::english(Uuid::new_v4().to_string())); - } - let mut query = Query::new(); - for field_id in field_ids.iter() { - query.add(field_id.clone(), Calculation::new(Operand::Equal)); - } - let result = query.field_ids(); - assert_eq!(result.len(), field_ids.len()); - for field_id in result.iter() { - assert!( - field_ids.contains(field_id), - "field id {:?} not found", - field_id - ); - } - } - */ } #[derive(Clone, Debug)] @@ -3398,7 +3022,10 @@ impl InternalRecord { } } - fn insert(&mut self, id: Uuid, data: F) -> Option where F: Into { + fn insert(&mut self, id: Uuid, data: F) -> Option + where + F: Into, + { self.data.insert(id, data.into()) } @@ -3889,13 +3516,27 @@ impl Index { } }; if self.unique && oids.len() > 0 { - return Err(MTTError::FieldDuplicate("".to_string(), field)); + return Err(MTTError::FieldDuplicate); } else { oids.insert(oid); } Ok(()) } + fn append(&mut self, index: &Self) { + for (value, oids) in index.data.iter() { + match self.data.get(value) { + Some(data) => { + let holder = data.union(oids).cloned().collect(); + self.data.insert(value.clone(), holder); + } + None => { + self.data.insert(value.clone(), oids.clone()); + } + } + } + } + fn get(&self, spec: &Operation) -> Vec { let mut output = Vec::new(); for (field, oids) in self.data.iter() { @@ -3913,7 +3554,7 @@ impl Index { for (key, value) in self.data.iter() { let mut op = calc.clone(); match op.add_value(key.clone()) { - Ok(_) => {}, + Ok(_) => {} Err(err) => return Err(err), } if op.calculate() == true.into() { @@ -3938,7 +3579,7 @@ impl Index { fn validate(&self, field: &Field) -> Result<(), MTTError> { if self.unique { match self.data.get(field) { - Some(_) => return Err(MTTError::FieldDuplicate("".to_string(), field.clone())), + Some(_) => return Err(MTTError::FieldDuplicate), None => {} } } @@ -3967,16 +3608,26 @@ impl Indexes { self.data.get(field_id).unwrap() } + fn get_index_mut(&mut self, field_id: &Uuid) -> &mut Index { + self.data.get_mut(field_id).unwrap() + } + + fn append(&mut self, indexes: &Self) { + for (field_id, index) in indexes.iter() { + self.data.get_mut(field_id).unwrap().append(index); + } + } + fn pull(&self, field_id: &Uuid, calc: &Calculation) -> Result, MTTError> { self.data.get(field_id).unwrap().pull(calc) } - fn add_to_index(&mut self, field_name: &Uuid, field: Field, oid: Oid) { + fn add_to_index(&mut self, field_name: &Uuid, field: Field, oid: Oid) -> Result<(), MTTError> { let index = match self.data.get_mut(field_name) { Some(data) => data, - None => return, + None => return Ok(()), }; - index.add(field, oid); + index.add(field, oid) } fn remove_from_index(&mut self, field_name: &Uuid, field: &Field, oid: &Oid) { @@ -3998,6 +3649,10 @@ impl Indexes { Ok(()) } + fn iter(&self) -> impl Iterator { + self.data.iter() + } + fn iter_mut(&mut self) -> impl Iterator { self.data.iter_mut() } @@ -4098,10 +3753,7 @@ mod indexes { match index.add(field.clone(), oids[0].clone()) { Ok(_) => unreachable!("should have been an error"), Err(err) => match err { - MTTError::FieldDuplicate(field_name, value) => { - assert_eq!(field_name, ""); - assert_eq!(value, field); - } + MTTError::FieldDuplicate => {} _ => unreachable!("got {:?}: should have been duplicate field", err), }, } @@ -4128,10 +3780,7 @@ mod indexes { match index.validate(&field) { Ok(_) => unreachable!("should have gotten a duplication error"), Err(err) => match err { - MTTError::FieldDuplicate(field_name, value) => { - assert_eq!(field_name, ""); - assert_eq!(value, field); - } + MTTError::FieldDuplicate => {} _ => unreachable!("got {:?}: should have been duplicate field", err), }, } @@ -4229,12 +3878,6 @@ impl DocumentFile { &self.docdef } - /* - fn get_documents<'a>(&self) -> impl Iterator { - self.docs.iter() - } - */ - fn validate(&self, field_name: NT, value: Option) -> Result<(Uuid, Field), MTTError> where NT: Into, @@ -4257,7 +3900,6 @@ impl DocumentFile { fn add_field_to_error(key: String, err: MTTError) -> MTTError { match err { MTTError::DocumentFieldMissing(_) => MTTError::DocumentFieldMissing(key), - MTTError::FieldDuplicate(_, field) => MTTError::FieldDuplicate(key, field.clone()), _ => err.clone(), } } @@ -4267,7 +3909,7 @@ impl DocumentFile { NT: Into, { let field_id = self.docdef.get_field_id(field_name).unwrap(); - self.indexes.add_to_index(&field_id, field, oid) + self.indexes.add_to_index(&field_id, field, oid).unwrap(); } fn remove_from_index(&mut self, field_name: NT, field: &Field, oid: &Oid) @@ -4316,15 +3958,16 @@ impl DocumentFile { } fn delete(&mut self, delete: &Delete) -> MsgAction { - let mut reply = Reply::new(); - /* - let oids = self.run_query(delete.get_query()).unwrap(); + let oids = match self.run_query(delete.get_query()) { + Ok(data) => data, + Err(err) => return err.into(), + }; + let mut records = RecordIter::with_names(self.docdef.get_field_names().clone()); for oid in oids.iter() { - reply.add(self.docs.get(oid).unwrap().clone()); + records.insert(self.docs.get(oid).unwrap().clone()); self.docs.remove(oid); } - */ - reply.into() + records.into() } fn run_query(&self, query: &Query) -> Result, MTTError> { @@ -4355,7 +3998,7 @@ impl DocumentFile { let doc = self.docs.get(oid).unwrap(); let mut calc = calculation.clone(); match calc.add_value(doc.get(field_id).unwrap().clone()) { - Ok(_) => {}, + Ok(_) => {} Err(err) => return Err(err), } if calc.calculate() == false.into() { @@ -4391,13 +4034,34 @@ impl DocumentFile { Ok(result) => result, Err(err) => return err.into(), }; - let mut output = RecordIter::with_names(self.docdef.get_field_names().clone()); + let mut holder: HashMap = HashMap::new(); for oid in oids.iter() { - let rec = self.docs.get_mut(oid).unwrap(); + holder.insert(oid.clone(), self.docs.get(oid).unwrap().clone()); + } + let mut removes: Vec<(Uuid, Field, Oid)> = Vec::new(); + let mut indexes = self.docdef.create_indexes(); + for (oid, rec) in holder.iter_mut() { for (field_id, value) in changes.iter() { + removes.push(( + field_id.clone(), + rec.get(field_id).unwrap().clone(), + oid.clone(), + )); + match indexes.add_to_index(&field_id, value.clone(), oid.clone()) { + Ok(_) => {} + Err(err) => return err.into(), + } rec.insert(field_id.clone(), value.clone()); } - output.insert(rec.clone()); + } + let mut output = RecordIter::with_names(self.docdef.get_field_names().clone()); + for (field_id, value, oid) in removes.iter() { + self.indexes.remove_from_index(field_id, value, oid); + } + self.indexes.append(&indexes); + for (oid, record) in holder.iter() { + self.docs.insert(oid.clone(), record.clone()); + output.insert(record.clone()); } output.into() } @@ -4413,7 +4077,8 @@ mod document_files { Path::new(Include::All, Include::All, Include::Some(Action::Records)), Path::new(Include::All, Include::All, Include::Some(Action::Reply)), Path::new(Include::All, Include::All, Include::Some(Action::Error)), - ].to_vec() + ] + .to_vec() } struct TestDocument { @@ -4670,14 +4335,23 @@ mod document_files { match action { MsgAction::Records(output) => { let entry_count: usize = count.try_into().unwrap(); - assert_eq!(output.len(), entry_count, "should have the same number of entries"); + assert_eq!( + output.len(), + entry_count, + "should have the same number of entries" + ); for record in output.clone() { let holder = record.get(&name).unwrap(); let data = match holder { Field::Integer(item) => item.clone(), _ => unreachable!("got {:?}, should have been integer", holder), }; - assert!(entries.contains(&data), "did not find {:?} in {:?}", data, entries); + assert!( + entries.contains(&data), + "did not find {:?} in {:?}", + data, + entries + ); entries.remove(&data); } } @@ -4694,7 +4368,12 @@ mod document_files { let name = Name::english("bad"); let mut addition = Addition::new(); addition.add_field(name.clone(), "doesn't matter"); - queue.send(Message::new(test_doc.get_docdef().get_document_name(), addition)).unwrap(); + queue + .send(Message::new( + test_doc.get_docdef().get_document_name(), + addition, + )) + .unwrap(); let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); match result.get_action() { MsgAction::Error(err) => match err { @@ -4712,7 +4391,10 @@ mod document_files { let queue = test_doc.get_queue(); let mut addition = Addition::new(); addition.add_field(Name::english("field0"), "string"); - queue.send(Message::new(test_doc.get_docdef().get_document_name(), addition)); + queue.send(Message::new( + test_doc.get_docdef().get_document_name(), + addition, + )); let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); match result.get_action() { MsgAction::Error(err) => match err { @@ -4736,11 +4418,14 @@ mod document_files { let queue = test_doc.get_queue(); let mut addition = Addition::new(); addition.add_field(Name::english("field0"), 1); - queue.send(Message::new(test_doc.get_docdef().get_document_name(), addition)); + queue.send(Message::new( + test_doc.get_docdef().get_document_name(), + addition, + )); let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); match result.get_action() { MsgAction::Error(err) => match err { - MTTError::InvalidNone => {}, + MTTError::InvalidNone => {} _ => unreachable!("got {:?}: should have been document field missing", err), }, _ => unreachable!("got {:?}: should have been an error", result.get_action()), @@ -4762,7 +4447,10 @@ mod document_files { calc.add_value(expected.clone()); let mut query = Query::new(); query.add(Name::english("field0"), calc); - queue.send(Message::new(test_doc.get_docdef().get_document_name(), query)); + queue.send(Message::new( + test_doc.get_docdef().get_document_name(), + query, + )); let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { @@ -4798,7 +4486,10 @@ mod document_files { calc.add_value(data.clone()); let mut query = Query::new(); query.add(Name::english("field0"), calc); - queue.send(Message::new(test_doc.get_docdef().get_document_name(), query)); + queue.send(Message::new( + test_doc.get_docdef().get_document_name(), + query, + )); let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { @@ -4989,7 +4680,8 @@ mod document_files { #[test] fn errors_on_bad_field_type_with_index() { let mut doc = TestDocument::new([FieldType::Uuid].to_vec()); - doc.get_docdef_mut().add_index(&Name::english("field0"), IndexType::Index); + doc.get_docdef_mut() + .add_index(&Name::english("field0"), IndexType::Index); doc.start(); doc.populate([Uuid::nil().into()].to_vec()); let mut calc = Calculation::new(Operand::Equal); @@ -5144,10 +4836,10 @@ mod document_files { let mut update = Update::new(); let mut calc = Calculation::new(Operand::Equal); calc.add_value(id.clone()); + update.get_query_mut().add(Name::english("field0"), calc); update - .get_query_mut() - .add(Name::english("field0"), calc); - update.get_values_mut().add_field(Name::english("field1"), new); + .get_values_mut() + .add_field(Name::english("field1"), new); let mut testing = |msg: Message| { doc.get_queue().send(msg.clone()).unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); @@ -5184,11 +4876,16 @@ mod document_files { let mut calc = Calculation::new(Operand::Equal); calc.add_value(picked.clone()); update.get_query_mut().add(Name::english("field0"), calc); - update.get_values_mut().add_field(Name::english("field1"), new); - doc.get_queue().send(Message::new(doc_name.clone(), update)).unwrap(); + update + .get_values_mut() + .add_field(Name::english("field1"), new); + doc.get_queue() + .send(Message::new(doc_name.clone(), update)) + .unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); - match action {MsgAction::Records(docs) => { + match action { + MsgAction::Records(docs) => { assert_eq!(docs.len(), 1, "should have one entry"); for doc in docs.clone() { assert_eq!(doc.get(Name::english("field0")).unwrap(), picked.into()); @@ -5197,10 +4894,13 @@ mod document_files { } _ => unreachable!("got {:?}: should have gotten a reply", action), } - doc.get_queue().send(Message::new(doc_name.clone(), Query::new())).unwrap(); + doc.get_queue() + .send(Message::new(doc_name.clone(), Query::new())) + .unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); - match action {MsgAction::Records(docs) => { + match action { + MsgAction::Records(docs) => { assert_eq!(docs.len(), 5, "should have one entry"); for doc in docs.clone() { if doc.get(Name::english("field0")).unwrap() == picked.into() { @@ -5230,12 +4930,15 @@ mod document_files { let mut calc = Calculation::new(Operand::Equal); calc.add_value(picked.clone()); update.get_query_mut().add(Name::english("field0"), calc); - update.get_values_mut().add_field(Name::english("field1"), new); + update + .get_values_mut() + .add_field(Name::english("field1"), new); let mut testing = |msg: Message| { doc.get_queue().send(msg).unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); - match action {MsgAction::Records(docs) => { + match action { + MsgAction::Records(docs) => { assert_eq!(docs.len(), 5, "should have one entry"); for doc in docs.clone() { assert_eq!(doc.get(Name::english("field0")).unwrap(), picked.into()); @@ -5287,7 +4990,9 @@ mod document_files { let mut calc = Calculation::new(Operand::Equal); calc.add_value(id.clone()); update.get_query_mut().add(Name::english("field0"), calc); - update.get_values_mut().add_field(Name::english("field1"), new); + update + .get_values_mut() + .add_field(Name::english("field1"), new); doc.send(update).unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); @@ -5303,30 +5008,47 @@ mod document_files { } } - /* #[test] fn does_update_maintain_unique_fields() { - let (mut docdef, doc_name) = create_docdef([FieldType::Uuid].to_vec()); - docdef.add_index("field0".to_string(), IndexType::Unique); - let (queue, rx) = test_doc(doc_name.as_str(), docdef, standard_routes()); - let field0 = Uuid::new_v4(); - let mut addition = Addition::new(); - addition.add_field("field0".to_string(), field0.clone()); - let msg = Message::new(doc_name.clone(), addition.clone()); - queue.send(msg).unwrap(); - rx.recv_timeout(TIMEOUT).unwrap(); - let msg2 = Message::new(doc_name.clone(), addition); - queue.send(msg2).unwrap(); - let result = rx.recv_timeout(TIMEOUT).unwrap(); + let mut test_doc = TestDocument::new([FieldType::Integer].to_vec()); + test_doc + .get_docdef_mut() + .add_index(&Name::english("field0"), IndexType::Unique); + test_doc.start(); + let fname = Name::english("field0"); + let old = 3; + let new = 5; + test_doc.populate([old.into()].to_vec()); + let mut update = Update::new(); + let mut calc = Calculation::new(Operand::Equal); + calc.add_value(old); + update.get_query_mut().add(fname.clone(), calc); + update.get_values_mut().add_field(&fname, new); + test_doc.send(update).unwrap(); + test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); + let mut should_clear = Addition::new(); + should_clear.add_field(fname.clone(), old); + let mut should_error = Addition::new(); + should_error.add_field(fname.clone(), new); + test_doc.send(should_clear).unwrap(); + let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); + let action = result.get_action(); + match action { + MsgAction::Records(docs) => { + assert_eq!(docs.len(), 1, "should have one entry"); + for doc in docs.clone() { + assert_eq!(doc.get(&fname).unwrap(), old.into()); + } + } + _ => unreachable!("got {:?}: should have gotten records", action), + } + test_doc.send(should_error).unwrap(); + let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { MsgAction::Error(err) => match err { - MTTError::FieldDuplicate(key, field) => { - let expected: Field = field0.into(); - assert_eq!(key, "field0"); - assert_eq!(field, &expected); - } - _ => unreachable!("got {:?}: should have gotten an missing field", err), + MTTError::FieldDuplicate => {} + _ => unreachable!("got {:?}: should have gotten incorrect file type", err), }, _ => unreachable!("got {:?}: should have gotten an error", action), } @@ -5334,34 +5056,44 @@ mod document_files { #[test] fn unique_value_remains_available_if_failure_occurs() { - let (mut docdef, doc_name) = create_docdef([FieldType::Uuid, FieldType::Uuid].to_vec()); - docdef.add_index("field0".to_string(), IndexType::Unique); - let (queue, rx) = test_doc(doc_name.as_str(), docdef, standard_routes()); - let field0 = Uuid::new_v4(); + let f0name = Name::english("field0"); + let f1name = Name::english("field1"); + let mut test_doc = TestDocument::new([FieldType::Uuid, FieldType::Uuid].to_vec()); + test_doc + .get_docdef_mut() + .add_index(&f0name, IndexType::Unique); + test_doc.start(); + let f0data = Uuid::new_v4(); + let f1bad_data = "NotUuid"; + let f1good_data = Uuid::nil(); let mut bad_addition = Addition::new(); - bad_addition.add_field("field0".to_string(), field0.clone()); - bad_addition.add_field("field1".to_string(), ""); - let msg = Message::new(doc_name.clone(), bad_addition.clone()); - queue.send(msg).unwrap(); - rx.recv_timeout(TIMEOUT).unwrap(); + bad_addition.add_field(&f0name, f0data.clone()); + bad_addition.add_field(&f1name, f1bad_data); let mut good_addition = Addition::new(); - good_addition.add_field("field0".to_string(), field0.clone()); - good_addition.add_field("field1".to_string(), field0.clone()); - let msg = Message::new(doc_name.clone(), good_addition.clone()); - queue.send(msg).unwrap(); - let result = rx.recv_timeout(TIMEOUT).unwrap(); + good_addition.add_field(&f0name, f0data.clone()); + good_addition.add_field(&f1name, f1good_data.clone()); + test_doc.send(bad_addition).unwrap(); + test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); + test_doc.send(good_addition).unwrap(); + let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { - MsgAction::Reply(_) => {} - _ => unreachable!("got {:?}: should have gotten a reply", action), + MsgAction::Records(docs) => { + assert_eq!(docs.len(), 1, "should have one entry"); + for doc in docs.clone() { + assert_eq!(doc.get(&f0name).unwrap(), f0data.into()); + assert_eq!(doc.get(&f1name).unwrap(), f1good_data.into()); + } + } + _ => unreachable!("got {:?}: should have gotten records", action), } } #[test] fn updating_unique_updates_index_entries() { + let fname = Name::english("field0"); let mut doc = TestDocument::new([FieldType::StaticString].to_vec()); - doc.get_docdef_mut() - .add_index("field0".to_string(), IndexType::Unique); + doc.get_docdef_mut().add_index(&fname, IndexType::Unique); doc.start(); let old = "old"; let new = "new"; @@ -5371,36 +5103,32 @@ mod document_files { let mut update = Update::new(); let mut calc = Calculation::new(Operand::Equal); calc.add_value(old); - update.get_query_mut().add("field0".to_string(), calc); - update.get_values_mut().add_field("field0".to_string(), new); + update.get_query_mut().add(fname.clone(), calc); + update.get_values_mut().add_field(fname.clone(), new); doc.send(update).unwrap(); doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let mut old_addition = Addition::new(); - old_addition.add_field("field0".to_string(), old); + old_addition.add_field(&fname, old); doc.send(old_addition).unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { - MsgAction::Reply(data) => { + MsgAction::Records(data) => { assert_eq!(data.len(), 1); - for doc in data.iter() { - assert_eq!(doc.get_field("field0").unwrap(), fold); + for doc in data.clone() { + assert_eq!(doc.get(&fname).unwrap(), fold); } } _ => unreachable!("got {:?}: should have gotten a reply", action), } let mut new_addition = Addition::new(); - new_addition.add_field("field0".to_string(), new); + new_addition.add_field(fname.clone(), new); doc.send(new_addition).unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { MsgAction::Error(err) => match err { - MTTError::FieldDuplicate(key, field) => { - let expected: Field = new.into(); - assert_eq!(key, "field0"); - assert_eq!(field, &expected); - } + MTTError::FieldDuplicate => {} _ => unreachable!("got {:?}: should have gotten an missing field", err), }, _ => unreachable!("got {:?}: should have gotten an error", action), @@ -5408,10 +5136,11 @@ mod document_files { } #[test] - fn unique_available_after_bad_change() { + fn update_does_not_override_unique_index() { + let f0name = Name::english("field0"); + let f1name = Name::english("field1"); let mut doc = TestDocument::new([FieldType::Uuid, FieldType::StaticString].to_vec()); - doc.get_docdef_mut() - .add_index("field0".to_string(), IndexType::Unique); + doc.get_docdef_mut().add_index(&f0name, IndexType::Unique); doc.start(); let count = 5; let data = "data"; @@ -5428,19 +5157,14 @@ mod document_files { let mut update = Update::new(); let mut calc = Calculation::new(Operand::Equal); calc.add_value(data); - update.get_query_mut().add("field1".to_string(), calc); - update - .get_values_mut() - .add_field("field0".to_string(), holder.clone()); + update.get_query_mut().add(&f1name, calc); + update.get_values_mut().add_field(&f0name, holder.clone()); doc.send(update).unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { MsgAction::Error(err) => match err { - MTTError::FieldDuplicate(key, field) => { - assert_eq!(key, "field0"); - assert_eq!(field, &fholder); - } + MTTError::FieldDuplicate => {} _ => unreachable!("got {:?}: should have gotten an missing field", err), }, _ => unreachable!("got {:?}: should have gotten an error", action), @@ -5450,21 +5174,26 @@ mod document_files { let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { - MsgAction::Reply(data) => { + MsgAction::Records(data) => { assert_eq!(data.len(), ids.len()); - for doc in data.iter() { - match doc.get_field("field0").unwrap() { - Field::Uuid(id) => assert!(ids.contains(&id)), + for doc in data.clone() { + match doc.get(&f0name).unwrap() { + Field::Uuid(id) => { + assert!(ids.contains(&id)); + ids.remove(&id); + } _ => unreachable!("did not get uuid"), } } } _ => unreachable!("got {:?}: should have gotten reply", action), } + assert!(ids.is_empty(), "did not find {:?}", ids); } #[test] fn can_calculate_field_values() { + let fname = Name::english("field0"); let mut doc = TestDocument::new([FieldType::DateTime].to_vec()); doc.start(); let duration = Duration::from_secs(300); @@ -5472,17 +5201,17 @@ mod document_files { calc.add_value(FieldType::DateTime).unwrap(); calc.add_value(duration.clone()).unwrap(); let mut addition = Addition::new(); - addition.add_field("field0".to_string(), calc); + addition.add_field(&fname, calc); let start = Utc::now() + duration; doc.send(addition).unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let stop = Utc::now() + duration; let action = result.get_action(); match action { - MsgAction::Reply(data) => { + MsgAction::Records(data) => { assert_eq!(data.len(), 1); - for doc in data.iter() { - match doc.get_field("field0").unwrap() { + for doc in data.clone() { + match doc.get(&fname).unwrap() { Field::DateTime(datetime) => assert!(datetime > start && datetime < stop), _ => unreachable!("did not get uuid"), } @@ -5494,23 +5223,24 @@ mod document_files { #[test] fn can_delete() { + let fname = Name::english("field0"); let mut doc = TestDocument::new([FieldType::Integer].to_vec()); doc.start(); doc.populate([1.into()].to_vec()); let mut calc = Calculation::new(Operand::Equal); calc.add_value(1); let mut query = Query::new(); - query.add("field0".to_string(), calc); + query.add(&fname, calc); let mut delete = Delete::new(); *delete.get_query_mut() = query.clone(); doc.send(delete).unwrap(); let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { - MsgAction::Reply(data) => { + MsgAction::Records(data) => { assert_eq!(data.len(), 1); - for doc in data.iter() { - match doc.get_field("field0").unwrap() { + for doc in data.clone() { + match doc.get(&fname).unwrap() { Field::Integer(num) => assert_eq!(num, 1), _ => unreachable!("did not get uuid"), } @@ -5522,38 +5252,10 @@ mod document_files { let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { - MsgAction::Reply(data) => assert_eq!(data.len(), 0), - _ => unreachable!("did not get uuid"), + MsgAction::Records(data) => assert_eq!(data.len(), 0), + _ => unreachable!("got {:?}, should have been empty", action), } } - - #[test] - fn delete_should_only_respond_to_its_own() { - let mut doc = TestDocument::new([FieldType::Integer].to_vec()); - doc.start(); - doc.populate([1.into()].to_vec()); - let mut calc = Calculation::new(Operand::Equal); - calc.add_value(1); - let mut query = Query::new(); - query.add("field0".to_string(), calc); - let mut delete = Delete::new(); - *delete.get_query_mut() = query.clone(); - doc.send(delete).unwrap(); - let name = "other"; - let msg = Message::new(name.to_string(), MsgAction::Show); - let (tx, _) = channel(); - let mut queue = doc.get_queue(); - queue.register(tx, name.to_string(), Vec::new()).unwrap(); - queue.send(msg).unwrap(); - match doc.get_receiver().recv_timeout(TIMEOUT) { - Ok(msg) => unreachable!("should not receive: {:?}", msg), - Err(err) => match err { - RecvTimeoutError::Timeout => {} - _ => unreachable!("should have timed out"), - }, - } - } - */ } #[cfg(test)]