Moved client requests into lib testing.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s

This commit is contained in:
Jeff Baskin 2026-02-22 00:21:57 -05:00
parent f334bfa9f1
commit 7e067fde8c
6 changed files with 95 additions and 127 deletions

View File

@ -5,7 +5,7 @@ pub enum Action {
Addition,
Create,
Delete,
DocumentCreated,
DocumentCreated,
Error,
OnAddition,
OnDelete,

View File

@ -102,6 +102,7 @@ impl From<UserAction> for MsgAction {
fn from(value: UserAction) -> Self {
match value {
UserAction::Addition(data) => Self::Addition(data),
UserAction::Delete(data) => Self::Delete(data),
UserAction::Query(data) => Self::Query(data),
UserAction::Update(data) => Self::Update(data),
}

View File

@ -1,9 +1,10 @@
use super::{Addition, DocDef, FieldType, Query, Update};
use super::{Addition, Delete, DocDef, FieldType, Query, Update};
use crate::{message::MessageAction, name::NameType};
#[derive(Clone, Debug)]
pub enum UserAction {
Addition(Addition),
Delete(Delete),
Query(Query),
Update(Update),
}
@ -14,6 +15,12 @@ impl From<Addition> for UserAction {
}
}
impl From<Delete> for UserAction {
fn from(value: Delete) -> Self {
Self::Delete(value)
}
}
impl From<Query> for UserAction {
fn from(value: Query) -> Self {
Self::Query(value)
@ -30,6 +37,7 @@ impl MessageAction for UserAction {
fn doc_name(&self) -> &NameType {
match self {
Self::Addition(data) => data.doc_name(),
Self::Delete(data) => data.doc_name(),
Self::Query(data) => data.doc_name(),
Self::Update(data) => data.doc_name(),
}

View File

@ -866,110 +866,6 @@ mod document_files {
}
}
#[test]
fn does_not_respond_to_create() {
let name = Name::english("quiet");
let docdef = DocDef::new(name.clone());
let mut test_doc: TestDocument = docdef.into();
let alt = Name::english("alternate");
test_doc.start(standard_paths());
let docdef = DocDef::new(alt);
let msg = Message::new(docdef);
test_doc.get_queue().send(msg);
match test_doc.get_receiver().recv_timeout(TIMEOUT) {
Ok(msg) => unreachable!("should not receive: {:?}", msg),
Err(err) => match err {
RecvTimeoutError::Timeout => {}
_ => unreachable!("should have timed out"),
},
}
}
#[test]
fn does_document_respond_to_requests() {
let name = Name::english("listen");
let docdef = DocDef::new(name.clone());
let mut test_doc: TestDocument = docdef.into();
test_doc.start(standard_paths());
let queue = test_doc.get_queue();
let msg_actions = [
MsgAction::Addition(Addition::new(name.clone())),
MsgAction::Delete(Delete::new(name.clone())),
MsgAction::Query(Query::new(name.clone())),
MsgAction::Show(Show::new(name.clone())),
MsgAction::Update(Update::new(name.clone())),
];
for msg_action in msg_actions.iter() {
let msg = Message::new(msg_action.clone());
queue.send(msg.clone());
let result = match test_doc.get_receiver().recv_timeout(TIMEOUT) {
Ok(data) => data.clone(),
Err(err) => unreachable!("for {:?} got {:?}", msg_action, err),
};
assert_eq!(
result.get_message_id(),
msg.get_message_id(),
"for {:?} response and reply ids should equal",
msg_action
);
match result.get_action() {
MsgAction::Reply(data) => {
assert_eq!(data.len(), 0, "for {:?} got {:?}", msg_action, result)
}
MsgAction::Records(data) => {
assert_eq!(data.len(), 0, "for {:?} got {:?}", msg_action, result)
}
_ => unreachable!(
"for {:?} got {:?}: should have received a reply",
msg_action,
result.get_action()
),
}
}
}
#[test]
fn does_not_respond_to_other_document_requests() {
let name = Name::english("quiet");
let alt = Name::english("alternate");
let docdef = DocDef::new(name.clone());
let mut test_doc: TestDocument = docdef.into();
test_doc.start(standard_paths());
let queue = test_doc.get_queue();
let reg_msg = Register::new(
test_doc.get_sender_id(),
RegMsg::AddDocName([alt.clone()].to_vec()),
);
let setup = Message::new(reg_msg.clone());
queue.send(setup);
test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap();
let msg_actions = [
MsgAction::Addition(Addition::new(alt.clone())),
MsgAction::Create(DocDef::new(alt.clone())),
MsgAction::Delete(Delete::new(alt.clone())),
MsgAction::Query(Query::new(alt.clone())),
MsgAction::Show(Show::new(alt.clone())),
MsgAction::Update(Update::new(alt.clone())),
];
let mut msgs: HashMap<Uuid, MsgAction> = HashMap::new();
for msg_action in msg_actions.iter() {
let msg = Message::new(msg_action.clone());
msgs.insert(msg.get_message_id().clone(), msg_action.clone());
queue.send(msg);
}
match test_doc.get_receiver().recv_timeout(TIMEOUT) {
Ok(msg) => unreachable!(
"for {:?} should not receive: {:?}",
msgs.get(msg.get_message_id()).unwrap(),
msg
),
Err(err) => match err {
RecvTimeoutError::Timeout => {}
_ => unreachable!("got {:?}, should have timed out", err),
},
}
}
#[test]
fn query_sends_on_query_message() {
let count = 5;

View File

@ -9,17 +9,18 @@ pub use action::*;
use document::{Clock, CreateDoc, Session};
use message::{wrapper::Message, MessageAction};
use queue::{
data_director::{Include, Path, RegMsg, Register},
data_director::{RegMsg, Register},
router::Queue,
};
use std::{
sync::mpsc::{channel, Receiver},
sync::mpsc::{channel, Receiver, Sender},
time::Duration,
};
use uuid::Uuid;
pub use mtterror::{ErrorID, MTTError};
pub use name::{Name, NameType};
pub use queue::data_director::{Include, Path};
#[cfg(test)]
mod support_tests {
@ -38,10 +39,14 @@ pub struct MoreThanText {
impl MoreThanText {
pub fn new() -> Self {
let queue = Queue::new();
let mut output = Self { queue: queue.clone()};
let mut output = Self {
queue: queue.clone(),
};
Clock::start(queue.clone());
CreateDoc::start(queue.clone());
output.create_document(Session::document_definition()).unwrap();
output
.create_document(Session::document_definition())
.unwrap();
output
}
@ -120,8 +125,8 @@ impl MoreThanText {
Ok(data) => match data.get_action() {
MsgAction::Records(data) => Ok(data.clone()),
MsgAction::Error(err) => Err(err.clone()),
_ => unreachable!("should only receive records or errors")
}
_ => unreachable!("should only receive records or errors"),
},
Err(_) => Err(MTTError::new(NameType::None, ErrorID::TimeOut)),
};
self.queue.remove_sender(&sender_id);
@ -155,8 +160,8 @@ impl MoreThanText {
Ok(data) => match data.get_action() {
MsgAction::DocumentCreated => Ok(()),
MsgAction::Error(err) => Err(err.clone()),
_ => unreachable!("should only receive records or errors")
}
_ => unreachable!("should only receive records or errors"),
},
Err(_) => Err(MTTError::new(NameType::None, ErrorID::TimeOut)),
};
self.queue.remove_sender(&sender_id);
@ -198,6 +203,10 @@ impl TestMoreThanText {
self.mtt.records(request)
}
pub fn create_document(&mut self, docdef: DocDef) -> Result<(), MTTError> {
self.mtt.create_document(docdef)
}
pub fn send_time_pulse(&self) {
let msg = Clock::gen_message();
self.queue.send(msg);
@ -206,4 +215,16 @@ impl TestMoreThanText {
pub fn random_name() -> Name {
Name::english(Uuid::new_v4().to_string().as_str())
}
pub fn register_channel(&self, paths: Vec<Path>) -> Receiver<Message> {
let mut queue = self.mtt.queue.clone();
let (tx, rx) = channel();
let sender_id = queue.add_sender(tx);
for path in paths.iter() {
let reg_msg = Register::new(sender_id.clone(), RegMsg::AddRoute(path.clone()));
queue.send(Message::new(reg_msg));
rx.recv().unwrap(); // Wait for completion.
}
rx
}
}

View File

@ -1,16 +1,11 @@
use morethantext::{action::*, ErrorID, Name, MoreThanText, TestMoreThanText};
use morethantext::{action::*, ErrorID, Include, MoreThanText, Name, Path, TestMoreThanText};
use std::{
sync::mpsc::{channel, RecvTimeoutError},
time::Duration,
};
use uuid::Uuid;
#[test]
fn is_document_created() {
let mut mtt = MoreThanText::new();
let doc_name = TestMoreThanText::random_name();
let docdef = DocDef::new(doc_name.clone());
mtt.create_document(docdef).unwrap();
let qry = Query::new(doc_name);
let result = mtt.records(qry).unwrap();
assert_eq!(result.len(), 0);
}
pub static TIMEOUT: Duration = Duration::from_millis(500);
#[test]
fn are_errors_produced_for_duplicate_names() {
@ -20,8 +15,55 @@ fn are_errors_produced_for_duplicate_names() {
match mtt.create_document(docdef) {
Ok(_) => assert!(false, "should have failed"),
Err(err) => match err.error_id() {
ErrorID::NameAlreadyExists => {},
ErrorID::NameAlreadyExists => {}
_ => unreachable!("got {:?}, should be name already exists", err),
}
},
}
}
#[test]
fn does_document_respond_to() {
let mut mtt = MoreThanText::new();
let doc_name = TestMoreThanText::random_name();
let mut requests: Vec<UserAction> = Vec::new();
requests.push(Addition::new(doc_name.clone()).into());
requests.push(Delete::new(doc_name.clone()).into());
requests.push(Query::new(doc_name.clone()).into());
requests.push(Update::new(doc_name.clone()).into());
let docdef = DocDef::new(doc_name.clone());
mtt.create_document(docdef).unwrap();
for req in requests.iter() {
let result = mtt.records(req.clone()).unwrap();
assert_eq!(result.len(), 0, "from {:?}", req);
}
}
#[test]
fn does_document_ignore_other_document_requests() {
let mut mtt = TestMoreThanText::new();
let quiet = Name::english("quiet");
let alt = Name::english("alt");
mtt.create_document(DocDef::new(quiet.clone())).unwrap();
mtt.create_document(DocDef::new(alt.clone())).unwrap();
let paths = vec![Path::new(
Include::All,
Include::Just(quiet.clone().into()),
Include::All,
)];
let rx = mtt.register_channel(paths);
let mut requests: Vec<UserAction> = Vec::new();
requests.push(Addition::new(alt.clone()).into());
requests.push(Delete::new(alt.clone()).into());
requests.push(Query::new(alt.clone()).into());
requests.push(Update::new(alt.clone()).into());
for req in requests.iter() {
mtt.records(req.clone()).unwrap();
}
match rx.recv_timeout(TIMEOUT) {
Ok(msg) => unreachable!("got {:?} should have timed out", msg),
Err(err) => match err {
RecvTimeoutError::Timeout => {}
_ => unreachable!("got {:?}, should have timed out", err),
},
}
}