Abandoned path. Senders can only be moved oncde.
This commit is contained in:
@ -4,6 +4,12 @@ use std::{
|
||||
thread::spawn,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum BackEndMessage {
|
||||
Get,
|
||||
Response(String),
|
||||
}
|
||||
|
||||
struct BackEnd {
|
||||
tx: Sender<Message>,
|
||||
rx: Receiver<Message>,
|
||||
@ -11,10 +17,7 @@ struct BackEnd {
|
||||
|
||||
impl BackEnd {
|
||||
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self {
|
||||
Self {
|
||||
tx: tx,
|
||||
rx: rx,
|
||||
}
|
||||
Self { tx: tx, rx: rx }
|
||||
}
|
||||
|
||||
fn start(queue_tx: Sender<Message>) {
|
||||
@ -29,22 +32,49 @@ impl BackEnd {
|
||||
fn listen(&self) {
|
||||
loop {
|
||||
self.rx.recv().unwrap();
|
||||
self.tx
|
||||
.send(BackEndMessage::Response("Something goes here".to_string()).into())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod backends {
|
||||
use std::time::Duration;
|
||||
use super::*;
|
||||
use std::time::Duration;
|
||||
|
||||
fn run_service() -> (Sender<Message>, Receiver<Message>) {
|
||||
let (tx, rx) = channel();
|
||||
let service_tx: Sender<Message>;
|
||||
BackEnd::start(tx);
|
||||
match rx.recv().unwrap() {
|
||||
Message::Register(result) => service_tx = result,
|
||||
_ => unreachable!("should register the service"),
|
||||
}
|
||||
(service_tx, rx)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_registered() {
|
||||
let (tx, rx) = channel();
|
||||
BackEnd::start(tx);
|
||||
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
|
||||
Message::Register(_) => {},
|
||||
Message::Register(_) => {}
|
||||
_ => unreachable!("should register the service"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_home_page() {
|
||||
let (tx, rx) = run_service();
|
||||
tx.send(BackEndMessage::Get.into()).unwrap();
|
||||
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
|
||||
Message::BEMsg(result) => match result {
|
||||
BackEndMessage::Response(_) => {}
|
||||
_ => unreachable!("wrong message type"),
|
||||
},
|
||||
_ => unreachable!("wrong message type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,91 @@
|
||||
use crate::{
|
||||
queue::{Message, MessageData},
|
||||
ClientMessage,
|
||||
};
|
||||
use std::{
|
||||
sync::mpsc::{channel, Receiver, Sender},
|
||||
thread::spawn,
|
||||
};
|
||||
|
||||
pub struct Reply;
|
||||
|
||||
impl Reply {
|
||||
pub fn get_session(&self) -> String {
|
||||
"id".to_string()
|
||||
}
|
||||
|
||||
pub fn get_content(&self) -> String {
|
||||
"Something goes here.".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
struct Client {
|
||||
tx: Sender<Message>,
|
||||
rx: Receiver<Message>
|
||||
}
|
||||
|
||||
impl Client {
|
||||
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self {
|
||||
Self {
|
||||
tx: tx,
|
||||
rx: rx,
|
||||
}
|
||||
}
|
||||
|
||||
fn start(queue_tx: Sender<Message>) {
|
||||
spawn(move || {
|
||||
let (tx, rx) = channel();
|
||||
let service = Self::new(queue_tx.clone(), rx);
|
||||
queue_tx.send(Message::new(tx.into())).unwrap();
|
||||
service.listen();
|
||||
});
|
||||
}
|
||||
|
||||
fn listen(&self) {
|
||||
loop {
|
||||
let msg = self.rx.recv().unwrap();
|
||||
match msg.get_data() {
|
||||
MessageData::ClientMsg(output) => {
|
||||
match output {
|
||||
ClientMessage::Req(data) => {
|
||||
let result = crate::client::Reply {};
|
||||
data.tx.send(result).unwrap();
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod clients {
|
||||
use crate::create_requests::root_doc_no_sess;
|
||||
use super::*;
|
||||
|
||||
fn setup_client() -> (Sender<Message>, Receiver<Message>) {
|
||||
let (tx, rx) = channel();
|
||||
Client::start(tx);
|
||||
let client_tx = match rx.recv().unwrap().get_data() {
|
||||
MessageData::Register(result) => result.clone(),
|
||||
_ => unreachable!("Register service first"),
|
||||
};
|
||||
(client_tx, rx)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_root_doc_request() {
|
||||
let (tx, rx) = setup_client();
|
||||
let (req, client_rx) = root_doc_no_sess();
|
||||
tx.send(Message::new(req.into())).unwrap();
|
||||
client_rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
use super::{Message, Msg, MsgData, SessionMsg};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@ -155,3 +243,4 @@ mod messages {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
135
src/docbuilder.rs
Normal file
135
src/docbuilder.rs
Normal file
@ -0,0 +1,135 @@
|
||||
use crate::{
|
||||
field::Field,
|
||||
queue::{Message, QueueClient},
|
||||
};
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Document {
|
||||
session: Field,
|
||||
content: Field,
|
||||
}
|
||||
|
||||
impl Document {
|
||||
pub fn new(session: Field, content: Field) -> Self {
|
||||
Self {
|
||||
session: session,
|
||||
content: content,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the session id information.
|
||||
pub fn get_session(&self) -> String {
|
||||
self.session.to_string()
|
||||
}
|
||||
|
||||
/// Get the requested content.
|
||||
pub fn get_content(&self) -> String {
|
||||
self.content.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod documeents {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn create_response() {
|
||||
let id = "something";
|
||||
let txt = "stuff";
|
||||
let res = Document::new(id.into(), txt.into());
|
||||
match res.session {
|
||||
Field::Static(data) => assert_eq!(data, id),
|
||||
_ => unreachable!("wrong field type"),
|
||||
}
|
||||
match res.content {
|
||||
Field::Static(data) => assert_eq!(data, txt),
|
||||
_ => unreachable!("wrong field type"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_id_string() {
|
||||
let id = "id";
|
||||
let doc = "content";
|
||||
let reply = Document::new(id.into(), doc.into());
|
||||
assert_eq!(reply.get_session(), id);
|
||||
assert_eq!(reply.get_content(), doc);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_id_content() {
|
||||
let id = "session";
|
||||
let doc = "stuff";
|
||||
let reply = Document::new(id.into(), doc.into());
|
||||
assert_eq!(reply.get_session(), id);
|
||||
assert_eq!(reply.get_content(), doc);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DocumentBuilder {
|
||||
_tx: Sender<Message>,
|
||||
rx: Receiver<Message>,
|
||||
}
|
||||
|
||||
impl QueueClient for DocumentBuilder {
|
||||
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self {
|
||||
Self {
|
||||
_tx: tx,
|
||||
rx: rx,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_receiver(&self) -> &Receiver<Message> {
|
||||
&self.rx
|
||||
}
|
||||
|
||||
fn listen(&self) {
|
||||
let rx = self.get_receiver();
|
||||
loop {
|
||||
match rx.recv().unwrap() {
|
||||
Message::Req(data) => {
|
||||
//data.get_sender().send(Document::new("id".into(), "stuff".into())).unwrap();
|
||||
let doc = Document::new("id".into(), "stuff".into());
|
||||
data.send(doc);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod builders {
|
||||
use crate::request_test_data::request_root_document;
|
||||
use std::sync::mpsc::{channel, TryRecvError};
|
||||
use super::*;
|
||||
|
||||
fn run_service() -> (Sender<Message>, Receiver<Message>) {
|
||||
let (tx, rx) = channel();
|
||||
let service_tx: Sender<Message>;
|
||||
DocumentBuilder::start(tx);
|
||||
match rx.recv().unwrap() {
|
||||
Message::Register(result) => service_tx = result,
|
||||
_ => unreachable!("should register the service"),
|
||||
}
|
||||
(service_tx, rx)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_document() {
|
||||
let (tx, rx) = run_service();
|
||||
let (msg, msg_rx) = request_root_document();
|
||||
tx.send(msg.into()).unwrap();
|
||||
match rx.try_recv() {
|
||||
Ok(_) => unreachable!("nothing should go back to the queue"),
|
||||
Err(err) => {
|
||||
match err {
|
||||
TryRecvError::Empty => {},
|
||||
_ => unreachable!("channel should still be open"),
|
||||
}
|
||||
},
|
||||
}
|
||||
msg_rx.recv().unwrap();
|
||||
}
|
||||
}
|
122
src/field.rs
Normal file
122
src/field.rs
Normal file
@ -0,0 +1,122 @@
|
||||
use std::fmt;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Field {
|
||||
Static(String),
|
||||
Uuid(Uuid),
|
||||
}
|
||||
|
||||
impl From<String> for Field {
|
||||
fn from(value: String) -> Self {
|
||||
match Uuid::try_from(value.as_str()) {
|
||||
Ok(data) => return Field::Uuid(data),
|
||||
Err(_) => {}
|
||||
}
|
||||
Field::Static(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Field {
|
||||
fn from(value: &str) -> Self {
|
||||
match Uuid::try_from(value) {
|
||||
Ok(data) => return Field::Uuid(data),
|
||||
Err(_) => {}
|
||||
}
|
||||
Field::Static(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uuid> for Field {
|
||||
fn from(value: Uuid) -> Self {
|
||||
Field::Uuid(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Field {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Field::Uuid(data) => write!(f, "{}", data),
|
||||
Field::Static(data) => write!(f, "{}", data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod fields {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn string_to_field() {
|
||||
let entries = ["test1".to_string(), "test2".to_string()];
|
||||
for data in entries {
|
||||
match data.clone().into() {
|
||||
Field::Static(result) => assert_eq!(result, data),
|
||||
_ => unreachable!("shouuld have been a static field"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_to_field() {
|
||||
let entries = ["test1", "test2"];
|
||||
for data in entries {
|
||||
match data.into() {
|
||||
Field::Static(result) => assert_eq!(result, data),
|
||||
_ => unreachable!("shouuld have been a static field"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
match id.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_string_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
let id_string = id.to_string();
|
||||
match id_string.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_str_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
let id_string = id.to_string();
|
||||
let id_str = id_string.as_str();
|
||||
match id_str.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_field_to_string() {
|
||||
let id = Uuid::new_v4();
|
||||
let result = id.to_string();
|
||||
let input = Field::Uuid(id);
|
||||
assert_eq!(input.to_string(), result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_field_to_string() {
|
||||
let result = "Something goes here";
|
||||
let input: Field = result.into();
|
||||
assert_eq!(input.to_string(), result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_field_to_string() {
|
||||
let result = "Another string".to_string();
|
||||
let input: Field = result.clone().into();
|
||||
assert_eq!(input.to_string(), result);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::{queue::Message, session2::SessionMessage, Field, Request};
|
||||
use crate::{backend::BackEndMessage, queue::Message, session2::SessionMessage, Field, Request};
|
||||
use std::{
|
||||
sync::mpsc::{channel, Receiver, Sender},
|
||||
thread::spawn,
|
||||
@ -25,12 +25,31 @@ impl FrontEnd {
|
||||
|
||||
fn listen(&self) {
|
||||
loop {
|
||||
self.rx.recv().unwrap();
|
||||
match self.rx.recv().unwrap() {
|
||||
Message::Req(output) => self.validate_session(output),
|
||||
Message::SessMsg(output) => match output {
|
||||
SessionMessage::New(data) => {
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let id: Option<Field> = None;
|
||||
let msg: SessionMessage = id.into();
|
||||
self.tx.send(msg.into()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn forward_request(&self, sess_id: Field) {
|
||||
self.tx.send(BackEndMessage::Get.into()).unwrap();
|
||||
}
|
||||
|
||||
fn validate_session(&self, req: Request) {
|
||||
let id: Option<Field> = None;
|
||||
let msg: SessionMessage = id.into();
|
||||
self.tx.send(msg.into()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -76,6 +95,12 @@ mod frontends {
|
||||
}
|
||||
let (new_sess, sess_id) = create_session_new();
|
||||
tx.send(new_sess.into()).unwrap();
|
||||
// generate backend request.
|
||||
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
|
||||
Message::BEMsg(result) => match result {
|
||||
BackEndMessage::Get => {}
|
||||
_ => unreachable!("incorrect message type"),
|
||||
},
|
||||
_ => unreachable!("incorrect message type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
571
src/lib.rs
571
src/lib.rs
@ -1,572 +1,31 @@
|
||||
mod backend;
|
||||
mod client;
|
||||
mod data;
|
||||
mod error;
|
||||
mod frontend;
|
||||
mod message;
|
||||
mod queue;
|
||||
mod router;
|
||||
mod session;
|
||||
mod session2;
|
||||
mod field;
|
||||
|
||||
use client::{Client, ClientMsg};
|
||||
use message::{Message, MsgData};
|
||||
use router::Router;
|
||||
use session::{Session, SessionData, SessionMsg};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::Deref,
|
||||
sync::mpsc::{channel, Receiver, Sender},
|
||||
};
|
||||
use uuid::Uuid;
|
||||
use field::Field;
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Field {
|
||||
Static(String),
|
||||
Uuid(Uuid),
|
||||
}
|
||||
pub struct Reply;
|
||||
|
||||
impl From<String> for Field {
|
||||
fn from(value: String) -> Self {
|
||||
match Uuid::try_from(value.as_str()) {
|
||||
Ok(data) => return Field::Uuid(data),
|
||||
Err(_) => {}
|
||||
}
|
||||
Field::Static(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Field {
|
||||
fn from(value: &str) -> Self {
|
||||
match Uuid::try_from(value) {
|
||||
Ok(data) => return Field::Uuid(data),
|
||||
Err(_) => {}
|
||||
}
|
||||
Field::Static(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uuid> for Field {
|
||||
fn from(value: Uuid) -> Self {
|
||||
Field::Uuid(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod fields {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn string_to_field() {
|
||||
let entries = ["test1".to_string(), "test2".to_string()];
|
||||
for data in entries {
|
||||
match data.clone().into() {
|
||||
Field::Static(result) => assert_eq!(result, data),
|
||||
_ => unreachable!("shouuld have been a static field"),
|
||||
}
|
||||
}
|
||||
impl Reply {
|
||||
pub fn get_session(&self) -> String {
|
||||
"id".to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_to_field() {
|
||||
let entries = ["test1", "test2"];
|
||||
for data in entries {
|
||||
match data.into() {
|
||||
Field::Static(result) => assert_eq!(result, data),
|
||||
_ => unreachable!("shouuld have been a static field"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
match id.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_string_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
let id_string = id.to_string();
|
||||
match id_string.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_str_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
let id_string = id.to_string();
|
||||
let id_str = id_string.as_str();
|
||||
match id_str.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
pub fn get_content(&self) -> String {
|
||||
"Something goes here.".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Request {
|
||||
id: Option<Field>,
|
||||
tx: Sender<Response>,
|
||||
}
|
||||
|
||||
impl Request {
|
||||
fn new<F>(id: Option<F>) -> (Self, Receiver<Response>)
|
||||
where
|
||||
F: Into<Field>,
|
||||
{
|
||||
let result: Option<Field>;
|
||||
match id {
|
||||
Some(data) => {
|
||||
result = Some(data.into());
|
||||
}
|
||||
None => result = None,
|
||||
}
|
||||
let (tx, rx) = channel();
|
||||
(Self { id: result, tx: tx }, rx)
|
||||
}
|
||||
|
||||
fn get_session(&self) -> &Option<Field> {
|
||||
return &self.id;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod create_request {
|
||||
use super::*;
|
||||
|
||||
pub fn empty_request() -> (Request, Receiver<Response>) {
|
||||
let id: Option<String> = None;
|
||||
Request::new(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod requests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn create_request_no_id() {
|
||||
let input: Option<String> = None;
|
||||
let (req, _) = Request::new(input);
|
||||
assert!(req.id.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_request_with_uuid() {
|
||||
let id = Uuid::new_v4();
|
||||
let (req, _) = Request::new(Some(id));
|
||||
match req.id {
|
||||
Some(field) => match (field) {
|
||||
Field::Uuid(data) => assert_eq!(data, id),
|
||||
_ => unreachable!("Should have been a uuid"),
|
||||
},
|
||||
None => unreachable!("Should producer data"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_session() {
|
||||
let id = Uuid::new_v4();
|
||||
let (req, _) = Request::new(Some(id));
|
||||
match req.get_session() {
|
||||
Some(result) => {
|
||||
match result {
|
||||
Field::Uuid(data) => assert_eq!(data, &id),
|
||||
_ => unreachable!("should have returned a uuid field"),
|
||||
};
|
||||
}
|
||||
None => unreachable!("should have returned a uuid"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Record {
|
||||
data: HashMap<String, Field>,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
data: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add<S, F>(&mut self, name: S, data: F)
|
||||
where
|
||||
S: Into<String>,
|
||||
F: Into<Field>,
|
||||
{
|
||||
self.data.insert(name.into(), data.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Record {
|
||||
type Target = HashMap<String, Field>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod records {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn initialize() {
|
||||
let rec = Record::new();
|
||||
assert!(rec.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_get_return() {
|
||||
let rec = Record::new();
|
||||
match rec.get("empty") {
|
||||
Some(_) => unreachable!("Should_have returned a None"),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_data() {
|
||||
let name = "name1x";
|
||||
let data = "data1";
|
||||
let mut rec = Record::new();
|
||||
rec.add(name, data);
|
||||
match rec.get(name) {
|
||||
None => unreachable!("Should return data"),
|
||||
Some(result) => match result {
|
||||
Field::Static(txt) => assert_eq!(txt, data),
|
||||
_ => unreachable!("Should have been static"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_data_strings() {
|
||||
let name = "field".to_string();
|
||||
let data = "info".to_string();
|
||||
let mut rec = Record::new();
|
||||
rec.add(name.clone(), data.clone());
|
||||
match rec.get(&name) {
|
||||
None => unreachable!("Should return data"),
|
||||
Some(result) => match result {
|
||||
Field::Static(txt) => assert_eq!(txt, &data),
|
||||
_ => unreachable!("should have been statis"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ResponseError {
|
||||
ColumnNumberMisMatch,
|
||||
MissionColumn(String),
|
||||
}
|
||||
|
||||
struct Response {
|
||||
data: HashMap<String, Vec<Field>>,
|
||||
counter: usize,
|
||||
}
|
||||
|
||||
impl Response {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
data: HashMap::new(),
|
||||
counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, rec: Record) -> Result<(), ResponseError> {
|
||||
if self.data.is_empty() {
|
||||
for (key, value) in rec.iter() {
|
||||
let mut store = Vec::new();
|
||||
store.push(value.clone());
|
||||
self.data.insert(key.to_string(), store);
|
||||
}
|
||||
} else {
|
||||
if rec.len() != self.data.len() {
|
||||
return Err(ResponseError::ColumnNumberMisMatch);
|
||||
}
|
||||
for (key, value) in rec.iter() {
|
||||
match self.data.get_mut(key) {
|
||||
Some(data) => data.push(value.clone()),
|
||||
None => return Err(ResponseError::MissionColumn(key.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Response {
|
||||
type Item = Record;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.data.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut rec = Record::new();
|
||||
for (key, value) in self.data.iter() {
|
||||
if self.counter >= value.len() {
|
||||
return None;
|
||||
}
|
||||
rec.add(key, value[self.counter].clone());
|
||||
}
|
||||
self.counter += 1;
|
||||
Some(rec)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod responses {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn create_response() {
|
||||
let mut res = Response::new();
|
||||
assert!(res.data.is_empty());
|
||||
assert!(res.next().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_records() {
|
||||
let mut res = Response::new();
|
||||
let columns = ["col1", "col2"];
|
||||
let count = 3;
|
||||
let field_cnt = &count * columns.len();
|
||||
let mut fields = 0..field_cnt;
|
||||
for _ in 0..count {
|
||||
let mut rec = Record::new();
|
||||
for col in columns {
|
||||
rec.add(col, fields.next().unwrap().to_string());
|
||||
}
|
||||
res.add(rec);
|
||||
}
|
||||
fields = 0..field_cnt;
|
||||
for _ in 0..count {
|
||||
match res.next() {
|
||||
Some(rec) => {
|
||||
assert_eq!(rec.len(), columns.len());
|
||||
for col in columns {
|
||||
match rec.get(col).unwrap() {
|
||||
Field::Static(txt) => {
|
||||
assert_eq!(txt.clone(), fields.next().unwrap().to_string())
|
||||
}
|
||||
_ => unreachable!("should have been static"),
|
||||
}
|
||||
}
|
||||
}
|
||||
None => unreachable!("Should have returned data"),
|
||||
}
|
||||
}
|
||||
assert!(res.next().is_none(), "exceeded the correct of records");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_of_columns_mismatch() {
|
||||
let mut res = Response::new();
|
||||
let mut rec1 = Record::new();
|
||||
let mut rec2 = Record::new();
|
||||
rec1.add("one", "one");
|
||||
rec2.add("one", "one");
|
||||
rec2.add("two", "two");
|
||||
res.add(rec1).unwrap();
|
||||
match res.add(rec2) {
|
||||
Ok(_) => unreachable!("Should not accept additional value"),
|
||||
Err(err) => match err {
|
||||
ResponseError::ColumnNumberMisMatch => {}
|
||||
_ => unreachable!("should havee been a mismatch error"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_field_error() {
|
||||
let mut res = Response::new();
|
||||
let mut rec1 = Record::new();
|
||||
let mut rec2 = Record::new();
|
||||
rec1.add("one", "one");
|
||||
rec2.add("one", "one");
|
||||
rec2.add("two", "two");
|
||||
res.add(rec2).unwrap();
|
||||
match res.add(rec1) {
|
||||
Ok(_) => unreachable!("Should not accept additional value"),
|
||||
Err(err) => match err {
|
||||
ResponseError::ColumnNumberMisMatch => {}
|
||||
_ => unreachable!("should havee been a mismatch error"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_column_name() {
|
||||
let mut res = Response::new();
|
||||
let mut rec1 = Record::new();
|
||||
let mut rec2 = Record::new();
|
||||
rec1.add("one", "one");
|
||||
rec2.add("two", "two");
|
||||
res.add(rec1).unwrap();
|
||||
match res.add(rec2) {
|
||||
Ok(_) => unreachable!("Should not accept additional value"),
|
||||
Err(err) => match err {
|
||||
ResponseError::MissionColumn(txt) => assert_eq!(txt, "two"),
|
||||
_ => unreachable!("should have been missing cloumn"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Support functions for Messages.
|
||||
pub trait Msg {
|
||||
fn to_msgdata(&self) -> MsgData;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_message {
|
||||
use super::*;
|
||||
|
||||
pub enum Tester {
|
||||
Test1,
|
||||
Test2,
|
||||
}
|
||||
|
||||
impl Msg for Tester {
|
||||
fn to_msgdata(&self) -> MsgData {
|
||||
match self {
|
||||
Tester::Test1 => MsgData::Test1,
|
||||
Tester::Test2 => MsgData::Test2,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Application client to MoreThanText
|
||||
pub struct MoreThanText {
|
||||
// tx: Sender<Message>,
|
||||
session: Option<SessionData>,
|
||||
tx: Sender<Message>,
|
||||
}
|
||||
pub struct MoreThanText;
|
||||
|
||||
impl MoreThanText {
|
||||
/// Create a MoreThanText database.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use morethantext::MoreThanText;
|
||||
///
|
||||
/// MoreThanText::new();
|
||||
/// ```
|
||||
pub fn new() -> Self {
|
||||
/* Future code.
|
||||
* tx = Queue::start();
|
||||
* tx.send(Session::start().into()).unwrap();
|
||||
* Self { tx: tx }
|
||||
*/
|
||||
let (tx, rx) = channel();
|
||||
let mut senders = Vec::new();
|
||||
senders.push(Client::start(tx.clone()));
|
||||
senders.push(Session::start(tx.clone()));
|
||||
Router::start(senders, rx);
|
||||
Self {
|
||||
session: None,
|
||||
tx: tx,
|
||||
}
|
||||
Self {}
|
||||
}
|
||||
|
||||
/// Opens an existing or new session with the database.
|
||||
///
|
||||
/// If the string is None, incorrect, or expired,
|
||||
/// a new session will be created.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use morethantext::MoreThanText;
|
||||
///
|
||||
/// let mut mtt = MoreThanText::new();
|
||||
/// mtt.open_session(None);
|
||||
/// mtt.open_session(Some("7b1ff340-7dfa-4f29-b144-601384e54423".to_string()));
|
||||
/// ```
|
||||
pub fn open_session(&mut self, id: Option<String>) {
|
||||
let (tx, rx) = channel();
|
||||
let req = ClientMsg::OpenSession(id, tx);
|
||||
let msg = Message::new(&req);
|
||||
self.tx.send(msg).unwrap();
|
||||
match rx.recv().unwrap().get_message() {
|
||||
MsgData::Session(data) => match data {
|
||||
SessionMsg::Opened(sess) => self.session = Some(sess.clone()),
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
/// Get the session id
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use morethantext::MoreThanText;
|
||||
///
|
||||
/// let mut mtt = MoreThanText::new();
|
||||
/// let id = mtt.get_id();
|
||||
/// ```
|
||||
pub fn get_id(&self) -> String {
|
||||
match &self.session {
|
||||
Some(id) => id.to_string(),
|
||||
None => "".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for MoreThanText {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
session: None,
|
||||
tx: self.tx.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod mtt_client {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn default_values() {
|
||||
let mtt = MoreThanText::new();
|
||||
assert!(mtt.session.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_session() {
|
||||
let mut mtt = MoreThanText::new();
|
||||
mtt.open_session(None);
|
||||
assert!(mtt.session.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_ids_are_unique() {
|
||||
let mut mtt = MoreThanText::new();
|
||||
mtt.open_session(None);
|
||||
let id1 = mtt.get_id();
|
||||
mtt.open_session(None);
|
||||
assert_ne!(mtt.get_id(), id1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cloned_clients_have_no_session() {
|
||||
let mut mtt = MoreThanText::new();
|
||||
mtt.open_session(None);
|
||||
let result = mtt.clone();
|
||||
assert!(result.session.is_none());
|
||||
pub fn request<F>(&self, _session: Option<F>) -> Reply
|
||||
where
|
||||
F: Into<Field>,
|
||||
{
|
||||
Reply {}
|
||||
}
|
||||
}
|
||||
|
77
src/main.rs
77
src/main.rs
@ -1,8 +1,8 @@
|
||||
use axum::{extract::State, response::IntoResponse, routing::get, Router};
|
||||
use axum::{extract::State, handler::Handler, response::IntoResponse};
|
||||
use axum_extra::extract::cookie::{Cookie, CookieJar};
|
||||
use clap::Parser;
|
||||
//use morethantext::{MoreThanText, Session};
|
||||
use morethantext::MoreThanText;
|
||||
use tokio::{spawn, sync::mpsc::channel};
|
||||
|
||||
const LOCALHOST: &str = "127.0.0.1";
|
||||
const SESSION_KEY: &str = "sessionid";
|
||||
@ -21,28 +21,32 @@ struct Args {
|
||||
node: Vec<String>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod http_session {
|
||||
#[tokio::test]
|
||||
async fn my_test() {
|
||||
assert!(true);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let args = Args::parse();
|
||||
let addr = format!("{}:{}", args.address, args.port);
|
||||
let state = MoreThanText::new();
|
||||
let app = Router::new().route("/", get(handler)).with_state(state);
|
||||
let app = mtt_conn.with_state(state);
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||
axum::serve(listener, app.into_make_service())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn handler(jar: CookieJar, mut state: State<MoreThanText>) -> impl IntoResponse {
|
||||
let mut cookies = jar.clone();
|
||||
async fn mtt_conn(jar: CookieJar, state: State<MoreThanText>) -> impl IntoResponse {
|
||||
let sid = match jar.get(SESSION_KEY) {
|
||||
Some(cookie) => Some(cookie.value().to_string()),
|
||||
None => None,
|
||||
};
|
||||
let (tx, mut rx) = channel(5);
|
||||
spawn(async move {
|
||||
tx.send(state.request(sid)).await.unwrap();
|
||||
});
|
||||
let reply = rx.recv().await.unwrap();
|
||||
let cookie = Cookie::build((SESSION_KEY, reply.get_session()));
|
||||
let cookies = jar.add(cookie);
|
||||
|
||||
/*
|
||||
let sid = match jar.get(SESSION_KEY) {
|
||||
Some(cookie) => Some(cookie.value().to_string()),
|
||||
None => None,
|
||||
@ -52,5 +56,50 @@ async fn handler(jar: CookieJar, mut state: State<MoreThanText>) -> impl IntoRes
|
||||
let cookie = Cookie::build((SESSION_KEY, state.get_id()));
|
||||
cookies = jar.add(cookie);
|
||||
}
|
||||
(cookies, "Something goes here.")
|
||||
*/
|
||||
(cookies, reply.get_content())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod servers {
|
||||
use super::*;
|
||||
use axum::{
|
||||
body::Body,
|
||||
http::{Request, StatusCode},
|
||||
};
|
||||
use tower::ServiceExt;
|
||||
|
||||
#[tokio::test]
|
||||
async fn get_home_page() {
|
||||
let app = mtt_conn.with_state(MoreThanText::new());
|
||||
let response = app
|
||||
.oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let sessid = format!("{:?}", response.headers().get("set-cookie").unwrap());
|
||||
assert!(sessid.contains(SESSION_KEY), "did not set session id");
|
||||
}
|
||||
|
||||
/*
|
||||
#[tokio::test]
|
||||
async fn session_ids_are_unique() {
|
||||
let app = mtt_conn.with_state(MoreThanText::new());
|
||||
let mut holder: Vec<String> = Vec::new();
|
||||
for _ in 0..5 {
|
||||
let response = app
|
||||
.clone()
|
||||
.oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
let sessid = format!("{:?}", response.headers().get("set-cookie").unwrap());
|
||||
assert!(
|
||||
!holder.contains(&sessid),
|
||||
"found duplicate entry: {:?}",
|
||||
holder
|
||||
);
|
||||
holder.push(sessid);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
597
src/old-lib.rs
Normal file
597
src/old-lib.rs
Normal file
@ -0,0 +1,597 @@
|
||||
mod backend;
|
||||
mod client;
|
||||
mod data;
|
||||
mod error;
|
||||
mod frontend;
|
||||
mod message;
|
||||
mod queue;
|
||||
mod router;
|
||||
mod session;
|
||||
mod session2;
|
||||
|
||||
use client::{Client, ClientMsg};
|
||||
use message::{Message, MsgData};
|
||||
use router::Router;
|
||||
use session::{Session, SessionData, SessionMsg};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::Deref,
|
||||
sync::mpsc::{channel, Receiver, Sender},
|
||||
thread::spawn,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
/*
|
||||
* This is code to finish once sessions have been ransfered,
|
||||
* and the dead code is removed.
|
||||
*
|
||||
trait MessageService: Sized {
|
||||
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self;
|
||||
|
||||
fn start(queue_tx: Sender<Message>) {
|
||||
spawn(move || {
|
||||
let (tx, rx) = channel();
|
||||
let service = Self::new(queue_tx.clone(), rx);
|
||||
queue_tx.send(tx.clone().into()).unwrap();
|
||||
service.listen();
|
||||
});
|
||||
}
|
||||
|
||||
fn listen(&self) {
|
||||
loop {
|
||||
self.rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Field {
|
||||
Static(String),
|
||||
Uuid(Uuid),
|
||||
}
|
||||
|
||||
impl From<String> for Field {
|
||||
fn from(value: String) -> Self {
|
||||
match Uuid::try_from(value.as_str()) {
|
||||
Ok(data) => return Field::Uuid(data),
|
||||
Err(_) => {}
|
||||
}
|
||||
Field::Static(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Field {
|
||||
fn from(value: &str) -> Self {
|
||||
match Uuid::try_from(value) {
|
||||
Ok(data) => return Field::Uuid(data),
|
||||
Err(_) => {}
|
||||
}
|
||||
Field::Static(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uuid> for Field {
|
||||
fn from(value: Uuid) -> Self {
|
||||
Field::Uuid(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod fields {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn string_to_field() {
|
||||
let entries = ["test1".to_string(), "test2".to_string()];
|
||||
for data in entries {
|
||||
match data.clone().into() {
|
||||
Field::Static(result) => assert_eq!(result, data),
|
||||
_ => unreachable!("shouuld have been a static field"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_to_field() {
|
||||
let entries = ["test1", "test2"];
|
||||
for data in entries {
|
||||
match data.into() {
|
||||
Field::Static(result) => assert_eq!(result, data),
|
||||
_ => unreachable!("shouuld have been a static field"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
match id.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_string_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
let id_string = id.to_string();
|
||||
match id_string.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid_str_to_field() {
|
||||
let id = Uuid::new_v4();
|
||||
let id_string = id.to_string();
|
||||
let id_str = id_string.as_str();
|
||||
match id_str.into() {
|
||||
Field::Uuid(result) => assert_eq!(result, id),
|
||||
_ => unreachable!("should have been a uuid field"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Request {
|
||||
id: Option<Field>,
|
||||
tx: Sender<Response>,
|
||||
}
|
||||
|
||||
impl Request {
|
||||
fn new<F>(id: Option<F>) -> (Self, Receiver<Response>)
|
||||
where
|
||||
F: Into<Field>,
|
||||
{
|
||||
let result: Option<Field>;
|
||||
match id {
|
||||
Some(data) => {
|
||||
result = Some(data.into());
|
||||
}
|
||||
None => result = None,
|
||||
}
|
||||
let (tx, rx) = channel();
|
||||
(Self { id: result, tx: tx }, rx)
|
||||
}
|
||||
|
||||
fn get_session(&self) -> &Option<Field> {
|
||||
return &self.id;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod create_request {
|
||||
use super::*;
|
||||
|
||||
pub fn empty_request() -> (Request, Receiver<Response>) {
|
||||
let id: Option<String> = None;
|
||||
Request::new(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod requests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn create_request_no_id() {
|
||||
let input: Option<String> = None;
|
||||
let (req, _) = Request::new(input);
|
||||
assert!(req.id.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_request_with_uuid() {
|
||||
let id = Uuid::new_v4();
|
||||
let (req, _) = Request::new(Some(id));
|
||||
match req.id {
|
||||
Some(field) => match (field) {
|
||||
Field::Uuid(data) => assert_eq!(data, id),
|
||||
_ => unreachable!("Should have been a uuid"),
|
||||
},
|
||||
None => unreachable!("Should producer data"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_session() {
|
||||
let id = Uuid::new_v4();
|
||||
let (req, _) = Request::new(Some(id));
|
||||
match req.get_session() {
|
||||
Some(result) => {
|
||||
match result {
|
||||
Field::Uuid(data) => assert_eq!(data, &id),
|
||||
_ => unreachable!("should have returned a uuid field"),
|
||||
};
|
||||
}
|
||||
None => unreachable!("should have returned a uuid"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Record {
|
||||
data: HashMap<String, Field>,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
data: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add<S, F>(&mut self, name: S, data: F)
|
||||
where
|
||||
S: Into<String>,
|
||||
F: Into<Field>,
|
||||
{
|
||||
self.data.insert(name.into(), data.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Record {
|
||||
type Target = HashMap<String, Field>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod records {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn initialize() {
|
||||
let rec = Record::new();
|
||||
assert!(rec.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_get_return() {
|
||||
let rec = Record::new();
|
||||
match rec.get("empty") {
|
||||
Some(_) => unreachable!("Should_have returned a None"),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_data() {
|
||||
let name = "name1x";
|
||||
let data = "data1";
|
||||
let mut rec = Record::new();
|
||||
rec.add(name, data);
|
||||
match rec.get(name) {
|
||||
None => unreachable!("Should return data"),
|
||||
Some(result) => match result {
|
||||
Field::Static(txt) => assert_eq!(txt, data),
|
||||
_ => unreachable!("Should have been static"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_data_strings() {
|
||||
let name = "field".to_string();
|
||||
let data = "info".to_string();
|
||||
let mut rec = Record::new();
|
||||
rec.add(name.clone(), data.clone());
|
||||
match rec.get(&name) {
|
||||
None => unreachable!("Should return data"),
|
||||
Some(result) => match result {
|
||||
Field::Static(txt) => assert_eq!(txt, &data),
|
||||
_ => unreachable!("should have been statis"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ResponseError {
|
||||
ColumnNumberMisMatch,
|
||||
MissionColumn(String),
|
||||
}
|
||||
|
||||
struct Response {
|
||||
data: HashMap<String, Vec<Field>>,
|
||||
counter: usize,
|
||||
}
|
||||
|
||||
impl Response {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
data: HashMap::new(),
|
||||
counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, rec: Record) -> Result<(), ResponseError> {
|
||||
if self.data.is_empty() {
|
||||
for (key, value) in rec.iter() {
|
||||
let mut store = Vec::new();
|
||||
store.push(value.clone());
|
||||
self.data.insert(key.to_string(), store);
|
||||
}
|
||||
} else {
|
||||
if rec.len() != self.data.len() {
|
||||
return Err(ResponseError::ColumnNumberMisMatch);
|
||||
}
|
||||
for (key, value) in rec.iter() {
|
||||
match self.data.get_mut(key) {
|
||||
Some(data) => data.push(value.clone()),
|
||||
None => return Err(ResponseError::MissionColumn(key.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Response {
|
||||
type Item = Record;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.data.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut rec = Record::new();
|
||||
for (key, value) in self.data.iter() {
|
||||
if self.counter >= value.len() {
|
||||
return None;
|
||||
}
|
||||
rec.add(key, value[self.counter].clone());
|
||||
}
|
||||
self.counter += 1;
|
||||
Some(rec)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod responses {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn create_response() {
|
||||
let mut res = Response::new();
|
||||
assert!(res.data.is_empty());
|
||||
assert!(res.next().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_records() {
|
||||
let mut res = Response::new();
|
||||
let columns = ["col1", "col2"];
|
||||
let count = 3;
|
||||
let field_cnt = &count * columns.len();
|
||||
let mut fields = 0..field_cnt;
|
||||
for _ in 0..count {
|
||||
let mut rec = Record::new();
|
||||
for col in columns {
|
||||
rec.add(col, fields.next().unwrap().to_string());
|
||||
}
|
||||
res.add(rec);
|
||||
}
|
||||
fields = 0..field_cnt;
|
||||
for _ in 0..count {
|
||||
match res.next() {
|
||||
Some(rec) => {
|
||||
assert_eq!(rec.len(), columns.len());
|
||||
for col in columns {
|
||||
match rec.get(col).unwrap() {
|
||||
Field::Static(txt) => {
|
||||
assert_eq!(txt.clone(), fields.next().unwrap().to_string())
|
||||
}
|
||||
_ => unreachable!("should have been static"),
|
||||
}
|
||||
}
|
||||
}
|
||||
None => unreachable!("Should have returned data"),
|
||||
}
|
||||
}
|
||||
assert!(res.next().is_none(), "exceeded the correct of records");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_of_columns_mismatch() {
|
||||
let mut res = Response::new();
|
||||
let mut rec1 = Record::new();
|
||||
let mut rec2 = Record::new();
|
||||
rec1.add("one", "one");
|
||||
rec2.add("one", "one");
|
||||
rec2.add("two", "two");
|
||||
res.add(rec1).unwrap();
|
||||
match res.add(rec2) {
|
||||
Ok(_) => unreachable!("Should not accept additional value"),
|
||||
Err(err) => match err {
|
||||
ResponseError::ColumnNumberMisMatch => {}
|
||||
_ => unreachable!("should havee been a mismatch error"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_field_error() {
|
||||
let mut res = Response::new();
|
||||
let mut rec1 = Record::new();
|
||||
let mut rec2 = Record::new();
|
||||
rec1.add("one", "one");
|
||||
rec2.add("one", "one");
|
||||
rec2.add("two", "two");
|
||||
res.add(rec2).unwrap();
|
||||
match res.add(rec1) {
|
||||
Ok(_) => unreachable!("Should not accept additional value"),
|
||||
Err(err) => match err {
|
||||
ResponseError::ColumnNumberMisMatch => {}
|
||||
_ => unreachable!("should havee been a mismatch error"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_column_name() {
|
||||
let mut res = Response::new();
|
||||
let mut rec1 = Record::new();
|
||||
let mut rec2 = Record::new();
|
||||
rec1.add("one", "one");
|
||||
rec2.add("two", "two");
|
||||
res.add(rec1).unwrap();
|
||||
match res.add(rec2) {
|
||||
Ok(_) => unreachable!("Should not accept additional value"),
|
||||
Err(err) => match err {
|
||||
ResponseError::MissionColumn(txt) => assert_eq!(txt, "two"),
|
||||
_ => unreachable!("should have been missing cloumn"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Support functions for Messages.
|
||||
pub trait Msg {
|
||||
fn to_msgdata(&self) -> MsgData;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_message {
|
||||
use super::*;
|
||||
|
||||
pub enum Tester {
|
||||
Test1,
|
||||
Test2,
|
||||
}
|
||||
|
||||
impl Msg for Tester {
|
||||
fn to_msgdata(&self) -> MsgData {
|
||||
match self {
|
||||
Tester::Test1 => MsgData::Test1,
|
||||
Tester::Test2 => MsgData::Test2,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Application client to MoreThanText
|
||||
pub struct MoreThanText {
|
||||
// tx: Sender<Message>,
|
||||
session: Option<SessionData>,
|
||||
tx: Sender<Message>,
|
||||
}
|
||||
|
||||
impl MoreThanText {
|
||||
/// Create a MoreThanText database.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use morethantext::MoreThanText;
|
||||
///
|
||||
/// MoreThanText::new();
|
||||
/// ```
|
||||
pub fn new() -> Self {
|
||||
/* Future code.
|
||||
* tx = Queue::start();
|
||||
* tx.send(Session::start().into()).unwrap();
|
||||
* Self { tx: tx }
|
||||
*/
|
||||
let (tx, rx) = channel();
|
||||
let mut senders = Vec::new();
|
||||
senders.push(Client::start(tx.clone()));
|
||||
senders.push(Session::start(tx.clone()));
|
||||
Router::start(senders, rx);
|
||||
Self {
|
||||
session: None,
|
||||
tx: tx,
|
||||
}
|
||||
}
|
||||
|
||||
/// Opens an existing or new session with the database.
|
||||
///
|
||||
/// If the string is None, incorrect, or expired,
|
||||
/// a new session will be created.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use morethantext::MoreThanText;
|
||||
///
|
||||
/// let mut mtt = MoreThanText::new();
|
||||
/// mtt.open_session(None);
|
||||
/// mtt.open_session(Some("7b1ff340-7dfa-4f29-b144-601384e54423".to_string()));
|
||||
/// ```
|
||||
pub fn open_session(&mut self, id: Option<String>) {
|
||||
let (tx, rx) = channel();
|
||||
let req = ClientMsg::OpenSession(id, tx);
|
||||
let msg = Message::new(&req);
|
||||
self.tx.send(msg).unwrap();
|
||||
match rx.recv().unwrap().get_message() {
|
||||
MsgData::Session(data) => match data {
|
||||
SessionMsg::Opened(sess) => self.session = Some(sess.clone()),
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
/// Get the session id
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use morethantext::MoreThanText;
|
||||
///
|
||||
/// let mut mtt = MoreThanText::new();
|
||||
/// let id = mtt.get_id();
|
||||
/// ```
|
||||
pub fn get_id(&self) -> String {
|
||||
match &self.session {
|
||||
Some(id) => id.to_string(),
|
||||
None => "".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for MoreThanText {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
session: None,
|
||||
tx: self.tx.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod mtt_client {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn default_values() {
|
||||
let mtt = MoreThanText::new();
|
||||
assert!(mtt.session.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_session() {
|
||||
let mut mtt = MoreThanText::new();
|
||||
mtt.open_session(None);
|
||||
assert!(mtt.session.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_ids_are_unique() {
|
||||
let mut mtt = MoreThanText::new();
|
||||
mtt.open_session(None);
|
||||
let id1 = mtt.get_id();
|
||||
mtt.open_session(None);
|
||||
assert_ne!(mtt.get_id(), id1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cloned_clients_have_no_session() {
|
||||
let mut mtt = MoreThanText::new();
|
||||
mtt.open_session(None);
|
||||
let result = mtt.clone();
|
||||
assert!(result.session.is_none());
|
||||
}
|
||||
}
|
156
src/old-queue.rs
Normal file
156
src/old-queue.rs
Normal file
@ -0,0 +1,156 @@
|
||||
use crate::{backend::BackEndMessage, session2::SessionMessage, Request};
|
||||
use std::{
|
||||
sync::mpsc::{channel, Receiver, Sender},
|
||||
thread::spawn,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Message {
|
||||
BEMsg(BackEndMessage),
|
||||
Register(Sender<Message>),
|
||||
Req(Request),
|
||||
SessMsg(SessionMessage),
|
||||
}
|
||||
|
||||
impl From<Request> for Message {
|
||||
fn from(value: Request) -> Self {
|
||||
Message::Req(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sender<Message>> for Message {
|
||||
fn from(value: Sender<Message>) -> Self {
|
||||
Message::Register(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SessionMessage> for Message {
|
||||
fn from(value: SessionMessage) -> Self {
|
||||
Message::SessMsg(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BackEndMessage> for Message {
|
||||
fn from(value: BackEndMessage) -> Self {
|
||||
Message::BEMsg(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod messages {
|
||||
use super::*;
|
||||
use crate::{create_request::empty_request, Field};
|
||||
|
||||
#[test]
|
||||
fn from_request() {
|
||||
let (req, _) = empty_request();
|
||||
match req.into() {
|
||||
Message::Req(result) => assert!(result.get_session().is_none()),
|
||||
_ => unreachable!("should have been s request"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_sender() {
|
||||
let (tx, rx) = channel();
|
||||
match tx.into() {
|
||||
Message::Register(result) => {
|
||||
let (req, _) = empty_request();
|
||||
result.send(req.into()).unwrap();
|
||||
match rx.recv().unwrap() {
|
||||
Message::Req(_) => {}
|
||||
_ => unreachable!("should have been a request"),
|
||||
}
|
||||
}
|
||||
_ => unreachable!("should have been a register"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_sessionmessage() {
|
||||
let id: Option<Field> = None;
|
||||
let sess_msg: SessionMessage = id.into();
|
||||
match sess_msg.into() {
|
||||
Message::SessMsg(result) => match result {
|
||||
SessionMessage::Validate(data) => assert!(data.is_none()),
|
||||
_ => unreachable!("should have been a validate"),
|
||||
},
|
||||
_ => unreachable!("should have been a session message"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_backend_message() {
|
||||
let data = BackEndMessage::Get;
|
||||
match data.into() {
|
||||
Message::BEMsg(result) => match result {
|
||||
BackEndMessage::Get => {}
|
||||
_ => unreachable!("should have been a validate"),
|
||||
},
|
||||
_ => unreachable!("should have been a session message"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Queue {
|
||||
channels: Vec<Sender<Message>>,
|
||||
rx: Receiver<Message>,
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
fn new(rx: Receiver<Message>) -> Self {
|
||||
Self {
|
||||
channels: Vec::new(),
|
||||
rx: rx,
|
||||
}
|
||||
}
|
||||
|
||||
fn listen(&mut self) {
|
||||
loop {
|
||||
let msg = self.rx.recv().unwrap();
|
||||
match msg {
|
||||
Message::Register(tx) => self.channels.push(tx),
|
||||
_ => {
|
||||
for tx in self.channels.iter() {
|
||||
tx.send(msg.clone()).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn start() -> Sender<Message> {
|
||||
let (tx, rx) = channel();
|
||||
spawn(move || {
|
||||
let mut queue = Queue::new(rx);
|
||||
queue.listen();
|
||||
});
|
||||
tx
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod queues {
|
||||
use super::*;
|
||||
use crate::create_request::empty_request;
|
||||
|
||||
#[test]
|
||||
fn create_queue() {
|
||||
let mut channels = Vec::new();
|
||||
for _ in 0..5 {
|
||||
channels.push(channel());
|
||||
}
|
||||
let mut queue_tx = Queue::start();
|
||||
for (tx, _) in channels.iter() {
|
||||
queue_tx.send(tx.clone().into()).unwrap();
|
||||
}
|
||||
let (req, _) = empty_request();
|
||||
queue_tx.send(req.into()).unwrap();
|
||||
for (_, rx) in channels.iter() {
|
||||
match rx.recv().unwrap() {
|
||||
Message::Req(_) => {}
|
||||
_ => unreachable!("should have been a request"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
258
src/queue.rs
258
src/queue.rs
@ -1,20 +1,224 @@
|
||||
use crate::{session2::SessionMessage, Request};
|
||||
use crate::{client::Reply, ClientMessage, Request};
|
||||
use std::{
|
||||
sync::mpsc::{channel, Receiver, Sender},
|
||||
thread::spawn,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum MessageData {
|
||||
ClientMsg(ClientMessage),
|
||||
Register(Sender<Message>),
|
||||
}
|
||||
|
||||
impl From<ClientMessage> for MessageData {
|
||||
fn from(value: ClientMessage) -> Self {
|
||||
MessageData::ClientMsg(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Request> for MessageData {
|
||||
fn from(value: Request) -> Self {
|
||||
let data: ClientMessage = value.into();
|
||||
MessageData::ClientMsg(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sender<Message>> for MessageData {
|
||||
fn from(value: Sender<Message>) -> Self {
|
||||
MessageData::Register(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod messagedatas {
|
||||
use crate::create_requests::root_doc_no_sess;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_client_message() {
|
||||
let (req, _) = root_doc_no_sess();
|
||||
let data: ClientMessage = req.into();
|
||||
match data.into() {
|
||||
MessageData::ClientMsg(_) => {},
|
||||
_ => unreachable!("should have been a client messsage"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_request() {
|
||||
let (req, _) = root_doc_no_sess();
|
||||
match req.into() {
|
||||
MessageData::ClientMsg(_) => {},
|
||||
_ => unreachable!("should be a client message"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_sender() {
|
||||
let (tx, rx) = channel();
|
||||
match tx.into() {
|
||||
MessageData::Register(result) => {
|
||||
let (req, _) = root_doc_no_sess();
|
||||
result.send(Message::new(req.into())).unwrap();
|
||||
match rx.recv().unwrap().data {
|
||||
MessageData::ClientMsg(_) => {}
|
||||
_ => unreachable!("should have been a request"),
|
||||
}
|
||||
}
|
||||
_ => unreachable!("should have been a register"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Message {
|
||||
data: MessageData,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn new(data: MessageData) -> Self {
|
||||
Self {
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_data(&self) -> &MessageData {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod messages {
|
||||
use crate::create_requests::root_doc_no_sess;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn create_msg() {
|
||||
let (req, _) = root_doc_no_sess();
|
||||
let msg = Message::new(req.into());
|
||||
match msg.data {
|
||||
MessageData::ClientMsg(_) => {},
|
||||
_ => unreachable!("should have been a client message"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Queue {
|
||||
channels: Vec<Sender<Message>>,
|
||||
rx: Receiver<Message>,
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
fn new(rx: Receiver<Message>) -> Self {
|
||||
Self {
|
||||
channels: Vec::new(),
|
||||
rx: rx,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start() -> Sender<Message> {
|
||||
let (tx, rx) = channel();
|
||||
spawn(move || {
|
||||
let mut queue = Queue::new(rx);
|
||||
queue.listen();
|
||||
});
|
||||
tx
|
||||
}
|
||||
|
||||
fn listen(&mut self) {
|
||||
loop {
|
||||
let msg = self.rx.recv().unwrap();
|
||||
match msg.get_data() {
|
||||
MessageData::Register(sender) => self.channels.push(sender.clone()),
|
||||
_ => {
|
||||
for tx in self.channels.iter() {
|
||||
tx.send(msg.clone()).unwrap();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod queues {
|
||||
use crate::{
|
||||
create_requests::root_doc_no_sess,
|
||||
Request,
|
||||
};
|
||||
use std::time::Duration;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn create_queue() {
|
||||
let mut channels = Vec::new();
|
||||
for _ in 0..5 {
|
||||
channels.push(channel());
|
||||
}
|
||||
let queue_tx = Queue::start();
|
||||
for (tx, _) in channels.iter() {
|
||||
queue_tx.send(Message::new(tx.clone().into())).unwrap();
|
||||
}
|
||||
let (req, _) = root_doc_no_sess();
|
||||
queue_tx.send(Message::new(req.into())).unwrap();
|
||||
for (_, rx) in channels.iter() {
|
||||
match rx.recv_timeout(Duration::from_millis(500)).unwrap().get_data() {
|
||||
MessageData::ClientMsg(_) => {}
|
||||
_ => unreachable!("should have been a request"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn get_root_doc() {
|
||||
let (client_tx, client_rx) = channel();
|
||||
let sess = None;
|
||||
let req = Request {
|
||||
tx: client_tx,
|
||||
session: sess,
|
||||
};
|
||||
let tx = Queue::start();
|
||||
tx.send(Message::new(req.into())).unwrap();
|
||||
client_rx.recv().unwrap();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
use crate::Request;
|
||||
use std::{
|
||||
sync::mpsc::{channel, Receiver, Sender},
|
||||
thread::spawn,
|
||||
};
|
||||
|
||||
pub trait QueueClient: Sized {
|
||||
fn new(tx: Sender<Message>, rx: Receiver<Message>) -> Self;
|
||||
|
||||
fn start(queue_tx: Sender<Message>) {
|
||||
spawn(move || {
|
||||
let (tx, rx) = channel();
|
||||
let service = Self::new(queue_tx.clone(), rx);
|
||||
queue_tx.send(tx.into()).unwrap();
|
||||
service.listen();
|
||||
});
|
||||
}
|
||||
|
||||
fn get_receiver(&self) -> &Receiver<Message>;
|
||||
|
||||
fn listen(&self) {
|
||||
let rx = self.get_receiver();
|
||||
loop {
|
||||
rx.recv().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Message {
|
||||
Register(Sender<Message>),
|
||||
Req(Request),
|
||||
SessMsg(SessionMessage),
|
||||
}
|
||||
|
||||
impl From<Request> for Message {
|
||||
fn from(value: Request) -> Self {
|
||||
Message::Req(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sender<Message>> for Message {
|
||||
@ -23,22 +227,22 @@ impl From<Sender<Message>> for Message {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SessionMessage> for Message {
|
||||
fn from(value: SessionMessage) -> Self {
|
||||
Message::SessMsg(value)
|
||||
impl From<Request> for Message {
|
||||
fn from(value: Request) -> Self {
|
||||
Message::Req(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod messages {
|
||||
use super::*;
|
||||
use crate::{create_request::empty_request, Field};
|
||||
use crate::request_test_data::request_root_document;
|
||||
|
||||
#[test]
|
||||
fn from_request() {
|
||||
let (req, _) = empty_request();
|
||||
let (req, _) = request_root_document();
|
||||
match req.into() {
|
||||
Message::Req(result) => assert!(result.get_session().is_none()),
|
||||
Message::Req(_) => {},
|
||||
_ => unreachable!("should have been s request"),
|
||||
}
|
||||
}
|
||||
@ -48,7 +252,7 @@ mod messages {
|
||||
let (tx, rx) = channel();
|
||||
match tx.into() {
|
||||
Message::Register(result) => {
|
||||
let (req, _) = empty_request();
|
||||
let (req, _) = request_root_document();
|
||||
result.send(req.into()).unwrap();
|
||||
match rx.recv().unwrap() {
|
||||
Message::Req(_) => {}
|
||||
@ -58,22 +262,9 @@ mod messages {
|
||||
_ => unreachable!("should have been a register"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_sessionmessage() {
|
||||
let id: Option<Field> = None;
|
||||
let sess_msg: SessionMessage = id.into();
|
||||
match sess_msg.into() {
|
||||
Message::SessMsg(result) => match result {
|
||||
SessionMessage::Validate(data) => assert!(data.is_none()),
|
||||
_ => unreachable!("should have been a validate"),
|
||||
},
|
||||
_ => unreachable!("should have been a session message"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Queue {
|
||||
pub struct Queue {
|
||||
channels: Vec<Sender<Message>>,
|
||||
rx: Receiver<Message>,
|
||||
}
|
||||
@ -100,7 +291,7 @@ impl Queue {
|
||||
}
|
||||
}
|
||||
|
||||
fn start() -> Sender<Message> {
|
||||
pub fn start() -> Sender<Message> {
|
||||
let (tx, rx) = channel();
|
||||
spawn(move || {
|
||||
let mut queue = Queue::new(rx);
|
||||
@ -113,7 +304,7 @@ impl Queue {
|
||||
#[cfg(test)]
|
||||
mod queues {
|
||||
use super::*;
|
||||
use crate::create_request::empty_request;
|
||||
use crate::request_test_data::request_root_document;
|
||||
|
||||
#[test]
|
||||
fn create_queue() {
|
||||
@ -121,11 +312,11 @@ mod queues {
|
||||
for _ in 0..5 {
|
||||
channels.push(channel());
|
||||
}
|
||||
let mut queue_tx = Queue::start();
|
||||
let queue_tx = Queue::start();
|
||||
for (tx, _) in channels.iter() {
|
||||
queue_tx.send(tx.clone().into()).unwrap();
|
||||
}
|
||||
let (req, _) = empty_request();
|
||||
let (req, _) = request_root_document();
|
||||
queue_tx.send(req.into()).unwrap();
|
||||
for (_, rx) in channels.iter() {
|
||||
match rx.recv().unwrap() {
|
||||
@ -135,3 +326,4 @@ mod queues {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
Reference in New Issue
Block a user