Removed false starts.

This commit is contained in:
Jeff Baskin 2025-03-26 17:47:36 -04:00
parent c9de11ff61
commit bba615e420
19 changed files with 0 additions and 3218 deletions

View File

@ -1,80 +0,0 @@
use crate::queue::Message;
use std::{
sync::mpsc::{channel, Receiver, Sender},
thread::spawn,
};
#[derive(Clone)]
pub enum BackEndMessage {
Get,
Response(String),
}
struct BackEnd {
tx: Sender<Message>,
rx: Receiver<Message>,
}
impl BackEnd {
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(tx.clone().into()).unwrap();
service.listen();
});
}
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 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(_) => {}
_ => 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"),
}
}
}

View File

@ -1,246 +0,0 @@
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,
sync::mpsc::{channel, Receiver, Sender},
thread::spawn,
};
use uuid::Uuid;
#[derive(Clone)]
pub enum ClientMsg {
OpenSession(Option<String>, Sender<Message>),
}
impl Msg for ClientMsg {
fn to_msgdata(&self) -> MsgData {
MsgData::Client(self.clone())
}
}
pub struct Client {
router_tx: Sender<Message>,
client_rx: Receiver<Message>,
requests: HashMap<Uuid, Sender<Message>>,
}
impl Client {
fn new(router_tx: Sender<Message>, client_rx: Receiver<Message>) -> Self {
Self {
router_tx: router_tx,
client_rx: client_rx,
requests: HashMap::new(),
}
}
pub fn start(router_tx: Sender<Message>) -> Sender<Message> {
let (client_tx, client_rx) = channel();
spawn(move || {
let mut client = Self::new(router_tx, client_rx);
client.listen();
});
client_tx
}
fn listen(&mut self) {
loop {
let msg = self.client_rx.recv().unwrap();
match self.requests.get(&msg.get_id()) {
Some(tx) => match msg.get_message() {
MsgData::Session(sess) => match sess {
SessionMsg::Opened(_) => tx.send(msg).unwrap(),
_ => {}
},
_ => {}
},
None => match msg.get_message() {
MsgData::Client(req) => match req {
ClientMsg::OpenSession(id, tx) => {
let sess = SessionMsg::Get(id.clone());
self.requests.insert(msg.get_id(), tx.clone());
self.router_tx.send(msg.reply(&sess)).unwrap();
}
},
_ => {}
},
}
}
}
}
#[cfg(test)]
mod messages {
use super::{super::SessionData, *};
use std::time::Duration;
use uuid::Uuid;
fn setup_client() -> (Sender<Message>, Receiver<Message>) {
let (tx, rx) = channel();
let client_tx = Client::start(tx);
(client_tx, rx)
}
fn opensession(id: &str) -> (Message, Receiver<Message>) {
let (tx, rx) = channel();
let sess = ClientMsg::OpenSession(Some(id.to_string()), tx);
let msg = Message::new(&sess);
(msg, rx)
}
#[test]
fn open_session() {
let (tx, rx) = setup_client();
let sess_id = Uuid::new_v4().to_string();
let (sess_msg, _) = opensession(&sess_id);
tx.send(sess_msg.clone()).unwrap();
let result1 = rx.recv().unwrap();
assert_eq!(result1.get_id(), sess_msg.get_id());
match result1.get_message() {
MsgData::Session(req) => match req {
SessionMsg::Get(sess_data) => match sess_data {
Some(id) => assert_eq!(id.to_string(), sess_id),
_ => unreachable!("Should have returned some data."),
},
_ => unreachable!("Should have been a get session message."),
},
_ => unreachable!("Should have been a Session message."),
}
}
#[test]
fn respond_session() {
let (tx, _rx) = setup_client();
let (sess_msg, client_rx) = opensession(&Uuid::new_v4().to_string());
tx.send(sess_msg.clone()).unwrap();
let expected = Uuid::new_v4();
let right = SessionData::new(expected.clone());
let exp_msg = SessionMsg::Opened(right);
tx.send(sess_msg.reply(&exp_msg)).unwrap();
let result = client_rx.recv().unwrap();
assert_eq!(sess_msg.get_id(), result.get_id(), "Different message ids.");
match result.get_message() {
MsgData::Session(req) => match req {
SessionMsg::Opened(sess) => assert_eq!(
sess.to_string(),
expected.to_string(),
"Different sesssion ids."
),
_ => unreachable!("Should have been an opened session."),
},
_ => unreachable!("Should have been a session message."),
}
}
#[test]
fn does_not_react_if_not_requested() {
let (tx, rx) = setup_client();
let sess = SessionData::new(Uuid::new_v4());
let exp_msg = SessionMsg::Opened(sess);
tx.send(Message::new(&exp_msg)).unwrap();
match rx.recv_timeout(Duration::from_millis(500)) {
Err(_) => {}
_ => unreachable!("Should not receive anything."),
}
}
#[test]
fn ignores_other_session_messages() {
let (tx, _rx) = setup_client();
let (sess_msg, client_rx) = opensession(&Uuid::new_v4().to_string());
tx.send(sess_msg.clone()).unwrap();
let req = SessionMsg::Get(None);
tx.send(sess_msg.reply(&req)).unwrap();
match client_rx.recv_timeout(Duration::from_millis(500)) {
Err(_) => {}
_ => unreachable!("Should not return anything."),
}
}
}
*/

View File

@ -1,120 +0,0 @@
pub mod database;
pub mod global;
pub mod id;
mod record;
pub mod table;
/*
use std::collections::BTreeMap;
use uuid::Uuid;
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Debug)]
struct IDPath {
path: Vec<Uuid>,
}
impl IDPath {
fn new() -> Self {
let mut path = Vec::new();
path.push(Uuid::nil());
Self { path: path }
}
fn next() -> Uuid {
Uuid::new_v4()
}
fn extend(&self, addition: Uuid) -> Self {
let mut result = self.clone();
result.path.pop();
result.path.push(addition);
result.path.push(Uuid::nil());
result
}
}
#[cfg(test)]
mod ids {
use super::*;
#[test]
fn create_idpath() {
let expected = [Uuid::nil()];
let id = IDPath::new();
assert_eq!(id.path, expected);
}
#[test]
fn next_is_random() {
let mut ids: Vec<Uuid> = Vec::new();
for _ in 0..10 {
let id = IDPath::next();
assert!(!ids.contains(&id), "{} is a duplicate", id);
ids.push(id);
}
}
#[test]
fn extend_idpath() {
let mut path: Vec<Uuid> = Vec::new();
path.push(Uuid::nil());
let mut id = IDPath::new();
for count in 1..5 {
assert_eq!(id.path.len(), count);
let extended = IDPath::next();
id = id.extend(extended.clone());
path.pop();
path.push(extended);
path.push(Uuid::nil());
assert_eq!(id.path, path);
}
}
}
*/
struct Cache {
data: BTreeMap<String, IDPath>,
}
impl Cache {
fn new() -> Self {
Self {
data: BTreeMap::new(),
}
}
fn add_database<S>(&mut self, name: S)
where
S: Into<String>,
{
self.data.insert(name.into(), IDPath::new());
}
fn get_databases(&self) -> Vec<String> {
self.data.keys().cloned().collect()
}
}
#[cfg(test)]
mod caches {
use super::*;
#[test]
fn create_cache() {
let cache = Cache::new();
let dbs = cache.get_databases();
assert!(dbs.is_empty());
}
/*
#[test]
fn add_databases() {
let mut cache = Cache::new();
cache.add_database("zed");
cache.add_database("alpha".to_string());
cache.add_database("beta");
cache.add_database("gamma".to_string());
assert_eq!(cache.get_databases(), ["alpha", "beta", "gamma", "zed"]);
}
*/
}

View File

@ -1,95 +0,0 @@
use crate::{
data::table::Table,
error::{ErrorType, MTTError},
};
use std::{collections::HashMap, fmt, ops::Deref};
#[derive(Debug, Clone)]
pub enum DBError {
DuplicateTable(String),
}
impl fmt::Display for DBError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DBError::DuplicateTable(data) => write!(f, "'{}' already exists", data),
}
}
}
#[cfg(test)]
mod errora {
use super::*;
#[test]
fn duplicate_table() {
let name = "fred";
let err = DBError::DuplicateTable(name.to_string());
assert_eq!(err.to_string(), format!("'{}' already exists", name));
}
}
pub struct Database {
tables: HashMap<String, Table>,
}
impl Database {
pub fn new() -> Self {
Self {
tables: HashMap::new(),
}
}
fn add_table(&mut self, name: &str, table: Table) -> Result<(), MTTError> {
match self.tables.get(name) {
Some(_) => {
let err = DBError::DuplicateTable(name.to_string());
return Err(err.into());
}
None => {}
}
self.tables.insert(name.to_string(), table);
Ok(())
}
}
impl Deref for Database {
type Target = HashMap<String, Table>;
fn deref(&self) -> &Self::Target {
&self.tables
}
}
#[cfg(test)]
mod databases {
use super::*;
#[test]
fn create_new_database() {
let db = Database::new();
assert_eq!(db.len(), 0);
}
#[test]
fn add_table() {
let mut db = Database::new();
let tbl = Table::new();
let name = "Something";
db.add_table(name, tbl).unwrap();
assert_eq!(db.len(), 1);
}
#[test]
fn no_duplicate_names() {
let mut db = Database::new();
let tbl1 = Table::new();
let tbl2 = Table::new();
let name = "Something";
db.add_table(name, tbl1).unwrap();
match db.add_table(name, tbl2) {
Ok(_) => unreachable!("Should have been an error"),
Err(err) => {}
}
}
}

View File

@ -1,95 +0,0 @@
use crate::{data::IDPath, error::MTTError};
use std::{collections::HashMap, fmt, ops::Deref};
#[derive(Debug, Clone)]
pub enum GblError {
DuplicateDB(String),
}
impl fmt::Display for GblError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GblError::DuplicateDB(data) => write!(f, "database '{}' already exists", data),
}
}
}
#[cfg(test)]
mod errors {
use super::*;
#[test]
fn duplicate_database() {
let name = "name";
let err = GblError::DuplicateDB(name.to_string());
assert_eq!(
err.to_string(),
format!("database '{}' already exists", name)
);
}
}
struct Global {
databases: HashMap<String, IDPath>,
}
impl Global {
fn new() -> Self {
Self {
databases: HashMap::new(),
}
}
fn add_database(&mut self, name: &str, db: IDPath) -> Result<(), MTTError> {
match self.databases.get(name) {
Some(_) => {
let err = GblError::DuplicateDB(name.to_string());
Err(err.into())
}
None => {
self.databases.insert(name.to_string(), db);
Ok(())
}
}
}
}
impl Deref for Global {
type Target = HashMap<String, IDPath>;
fn deref(&self) -> &Self::Target {
&self.databases
}
}
#[cfg(test)]
mod gblverses {
use super::*;
#[test]
fn create_gblverse() {
let gbl = Global::new();
assert_eq!(gbl.len(), 0);
}
#[test]
fn add_database() {
let mut gbl = Global::new();
let db = IDPath::new();
gbl.add_database("barney", db).unwrap();
assert_eq!(gbl.len(), 1);
}
#[test]
fn no_duplicate_dbs() {
let mut gbl = Global::new();
let db1 = IDPath::new();
let db2 = IDPath::new();
let name = "duplicate";
gbl.add_database("barney", db2).unwrap();
match gbl.add_database("barney", db1) {
Ok(_) => unreachable!("should have been an error"),
Err(err) => {}
}
}
}

View File

@ -1,125 +0,0 @@
use crate::{
data::record::Field,
error::{ErrorType, MTTError},
};
use std::fmt;
use uuid::Uuid;
#[derive(Clone, Debug)]
pub enum IDError {
InvalidUuid(String),
}
impl fmt::Display for IDError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
IDError::InvalidUuid(data) => write!(f, "'{}' is not a valid uuid", data),
}
}
}
#[cfg(test)]
mod dberrors {
use super::*;
#[test]
fn invalid_uuid() {
let data = "notgood";
let err = IDError::InvalidUuid(data.to_string());
assert_eq!(err.to_string(), format!("'{}' is not a valid uuid", data));
}
}
#[derive(Clone)]
pub struct ID {
data: Uuid,
}
impl ID {
pub fn new(data: Uuid) -> Self {
Self { data: data }
}
pub fn random() -> Self {
Self {
data: Uuid::new_v4(),
}
}
}
impl TryFrom<Uuid> for ID {
type Error = MTTError;
fn try_from(value: Uuid) -> Result<Self, Self::Error> {
Ok(Self::new(value))
}
}
impl TryFrom<&str> for ID {
type Error = MTTError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match Uuid::try_from(value) {
Ok(id) => Ok(ID::new(id)),
Err(_) => Err(IDError::InvalidUuid(value.to_string()).into()),
}
}
}
impl fmt::Display for ID {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.data)
}
}
#[cfg(test)]
mod id {
use super::*;
#[test]
fn try_from_uuid() {
let data = Uuid::new_v4();
let id = ID::try_from(data.clone()).unwrap();
assert_eq!(id.to_string(), data.to_string());
}
#[test]
fn try_from_str() {
let holder = Uuid::new_v4().to_string();
let data = holder.as_str();
let id = ID::try_from(data).unwrap();
assert_eq!(id.to_string(), data);
}
#[test]
fn try_from_bad_str() {
let bad = "BadUuid";
match ID::try_from(bad) {
Ok(_) => unreachable!("Should have failed to create an ID"),
Err(err) => match err.get_code() {
ErrorType::IDErr(id) => match id {
IDError::InvalidUuid(data) => assert_eq!(data, bad),
},
_ => unreachable!("Returned wrong error"),
},
}
}
#[test]
fn create_new() {
let data = Uuid::new_v4();
let id = ID::new(data.clone());
assert_eq!(id.to_string(), data.to_string());
}
#[test]
fn random_is_unique() {
let mut ids: Vec<String> = Vec::new();
for _ in 0..10 {
let id = ID::random();
let holder = id.to_string();
assert!(!ids.contains(&holder), "'{}' is a duplicate entry", id);
ids.push(holder);
}
}
}

View File

@ -1,116 +0,0 @@
pub mod database;
pub mod global;
pub mod id;
mod record;
pub mod table;
use super::Message;
use std::{
collections::BTreeMap,
sync::mpsc::{channel, Receiver, Sender},
thread::spawn,
};
use uuid::Uuid;
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Debug)]
struct IDPath {
path: Vec<Uuid>,
}
impl IDPath {
fn new() -> Self {
let mut path = Vec::new();
path.push(Uuid::nil());
Self { path: path }
}
fn next() -> Uuid {
Uuid::new_v4()
}
fn extend(&self, addition: Uuid) -> Self {
let mut result = self.clone();
result.path.pop();
result.path.push(addition);
result.path.push(Uuid::nil());
result
}
}
#[cfg(test)]
mod idpaths {
use super::*;
#[test]
fn create_idpath() {
let expected = [Uuid::nil()];
let id = IDPath::new();
assert_eq!(id.path, expected);
}
#[test]
fn next_is_random() {
let mut ids: Vec<Uuid> = Vec::new();
for _ in 0..10 {
let id = IDPath::next();
assert!(!ids.contains(&id), "{} is a duplicate", id);
ids.push(id);
}
}
#[test]
fn extend_idpath() {
let mut path: Vec<Uuid> = Vec::new();
path.push(Uuid::nil());
let mut id = IDPath::new();
for count in 1..5 {
assert_eq!(id.path.len(), count);
let extended = IDPath::next();
id = id.extend(extended.clone());
path.pop();
path.push(extended);
path.push(Uuid::nil());
assert_eq!(id.path, path);
}
}
}
struct Data {
router_tx: Sender<Message>,
data_rx: Receiver<Message>,
}
impl Data {
fn new(router_tx: Sender<Message>, data_rx: Receiver<Message>) -> Self {
Self {
router_tx: router_tx,
data_rx: data_rx,
}
}
pub fn start(router_tx: Sender<Message>) -> Sender<Message> {
let (data_tx, data_rx) = channel();
spawn(move || {
let mut req = Data::new(router_tx, data_rx);
req.listen();
});
data_tx
}
fn listen(&mut self) {
loop {
let msg = self.data_rx.recv().unwrap();
}
}
}
#[cfg(test)]
mod requests {
use super::*;
#[test]
fn add_database() {
let (tx, rx) = channel();
let data_tx = Data::start(tx);
}
}

View File

@ -1,116 +0,0 @@
use crate::data::id::ID;
use std::{collections::HashMap, fmt, ops::Deref};
#[derive(Clone)]
pub enum Field {
ID(ID),
}
impl From<ID> for Field {
fn from(value: ID) -> Self {
Field::ID(value)
}
}
impl fmt::Display for Field {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Field::ID(id) => write!(f, "{}", id),
}
}
}
pub struct Record {
data: HashMap<String, Field>,
}
impl Record {
pub fn new() -> Self {
Self {
data: HashMap::new(),
}
}
pub fn add<S, D>(&mut self, name: S, data: D) -> Option<Field>
where
String: From<S>,
Field: From<D>,
{
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 fields {
use super::*;
#[test]
fn from_id() {
let id = ID::random();
let field = Field::from(id.clone());
assert_eq!(field.to_string(), id.to_string());
}
}
#[cfg(test)]
mod records {
use super::*;
#[test]
fn new_record() {
let rec = Record::new();
assert_eq!(rec.len(), 0);
}
#[test]
fn add_field() {
let mut rec = Record::new();
let name = "field_name";
let data = ID::random();
rec.add(name.to_string(), data);
match rec.get(name) {
Some(data) => match data {
Field::ID(result) => assert_eq!(result.to_string(), data.to_string()),
},
None => unreachable!("Should get data back"),
}
}
#[test]
fn add_alternate_field() {
let mut rec = Record::new();
let name = "alternate";
let data = ID::random();
rec.add(name, data.clone());
match rec.get(name) {
Some(data) => match data {
Field::ID(result) => assert_eq!(result.to_string(), data.to_string()),
},
None => unreachable!("Should get data back"),
}
}
#[test]
fn record_iter() {
let mut data: HashMap<String, ID> = HashMap::new();
data.insert("a".to_string(), ID::random());
data.insert("b".to_string(), ID::random());
data.insert("c".to_string(), ID::random());
let mut rec = Record::new();
for (key, value) in data.iter() {
rec.add(key, value.clone());
}
assert_eq!(rec.len(), data.len());
for (key, value) in rec.iter() {
assert_eq!(value.to_string(), data.get(key).unwrap().to_string());
}
}
}

View File

@ -1,216 +0,0 @@
use crate::{
data::{
id::ID,
record::{Field, Record},
},
error::{ErrorType, MTTError},
};
use std::{collections::HashMap, fmt};
#[derive(Clone, Debug)]
pub enum TBLError {
DuplicateField(String),
InvalidField(String),
MissingField(String),
}
impl fmt::Display for TBLError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TBLError::DuplicateField(data) => write!(f, "'{}' already exists", data),
TBLError::InvalidField(data) => write!(f, "'{}' invalid field name", data),
TBLError::MissingField(data) => write!(f, "'{}' field is missing", data),
}
}
}
#[cfg(test)]
mod errors {
use super::*;
#[test]
fn duplicate_field() {
let data = "something";
let err = TBLError::DuplicateField(data.to_string());
assert_eq!(err.to_string(), format!("'{}' already exists", data));
}
#[test]
fn invalid_field() {
let data = "something";
let err = TBLError::InvalidField(data.to_string());
assert_eq!(err.to_string(), format!("'{}' invalid field name", data));
}
#[test]
fn missing_field() {
let data = "something";
let err = TBLError::MissingField(data.to_string());
assert_eq!(err.to_string(), format!("'{}' field is missing", data));
}
}
enum FieldType {
ID,
}
struct FieldDef;
impl FieldDef {
fn new() -> Self {
Self {}
}
fn get_type(&self) -> FieldType {
FieldType::ID
}
}
pub struct Table {
fields: HashMap<String, FieldDef>,
}
impl Table {
pub fn new() -> Self {
Self {
fields: HashMap::new(),
}
}
fn description(&self) -> &HashMap<String, FieldDef> {
&self.fields
}
fn add_field(&mut self, name: &str, field_type: FieldType) -> Result<(), MTTError> {
match self.fields.get(name) {
Some(_) => {
let err = TBLError::DuplicateField(name.to_string());
Err(err.into())
}
None => {
self.fields.insert(name.to_string(), FieldDef::new());
Ok(())
}
}
}
fn add_record(&mut self, rec: Record) -> Result<Record, MTTError> {
let mut holder = rec.clone();
for (key, _) in self.fields.iter() {
match holder.remove(key.into()) {
Some(_) => {}
None => {
let err = TBLError::MissingField(key.to_string());
return Err(err.into());
}
}
}
if holder.len() > 0 {
for (key, _) in holder.iter() {
let err = TBLError::InvalidField(key.to_string());
return Err(err.into());
}
}
Ok(rec)
}
}
#[cfg(test)]
mod table {
use super::*;
#[test]
fn new_table() {
let tbl = Table::new();
let data = tbl.description();
assert_eq!(data.len(), 0);
}
#[test]
fn add_field() {
let mut tbl = Table::new();
let field_name = "something ";
tbl.add_field(field_name, FieldType::ID);
let data = tbl.description();
assert_eq!(data.len(), 1);
match data.get(field_name) {
Some(field_info) => match field_info.get_type() {
FieldType::ID => {}
_ => unreachable!("incorrect field type"),
},
None => unreachable!("should return field definition"),
}
}
#[test]
fn error_on_duplicate_name() {
let mut tbl = Table::new();
let name = "one";
tbl.add_field(name, FieldType::ID);
match tbl.add_field(name, FieldType::ID) {
Ok(_) => unreachable!(" Should not duplicates."),
Err(err) => match err.get_code() {
ErrorType::TBLErr(data) => match data {
TBLError::DuplicateField(fname) => assert_eq!(fname, name),
_ => unreachable!("Should have been a dupluicate field error"),
},
_ => unreachable!("should produce a duplicate name error"),
},
}
}
#[test]
fn add_record() {
let mut tbl = Table::new();
let name = "id";
let field_data = ID::random();
tbl.add_field(name, FieldType::ID).unwrap();
let mut rec = Record::new();
rec.add(name, field_data.clone());
let result = tbl.add_record(rec).unwrap();
assert_eq!(
result.get(name).unwrap().to_string(),
field_data.to_string()
);
}
#[test]
fn add_record_incorrect_field_name() {
let mut tbl = Table::new();
let name = "id";
let field_data = ID::random();
let mut rec = Record::new();
rec.add(name, field_data.clone());
match tbl.add_record(rec) {
Ok(_) => unreachable!("should have produced an error"),
Err(err) => match err.get_code() {
ErrorType::TBLErr(error) => match error {
TBLError::InvalidField(result) => assert_eq!(result, name),
_ => unreachable!("should have been invalid field name"),
},
_ => unreachable!("should have been a table error"),
},
}
}
#[test]
fn add_record_missing_field() {
let mut tbl = Table::new();
let present = "here";
let missing = "not";
tbl.add_field(present, FieldType::ID);
tbl.add_field(missing, FieldType::ID);
let mut rec = Record::new();
rec.add(present, ID::random());
match tbl.add_record(rec) {
Ok(_) => unreachable!("should have produced an error"),
Err(err) => match err.get_code() {
ErrorType::TBLErr(error) => match error {
TBLError::MissingField(result) => assert_eq!(result, missing),
_ => unreachable!("should have been missing field"),
},
_ => unreachable!("should have been a table error"),
},
}
}
}

View File

@ -1,135 +0,0 @@
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();
}
}

View File

@ -1,173 +0,0 @@
use crate::data::{database::DBError, global::GblError, id::IDError, table::TBLError};
use std::{error::Error, fmt};
#[derive(Debug)]
pub enum ErrorType {
DBErr(DBError),
IDErr(IDError),
TBLErr(TBLError),
GblErr(GblError),
}
impl From<DBError> for ErrorType {
fn from(value: DBError) -> Self {
ErrorType::DBErr(value)
}
}
impl From<IDError> for ErrorType {
fn from(value: IDError) -> Self {
ErrorType::IDErr(value)
}
}
impl From<TBLError> for ErrorType {
fn from(value: TBLError) -> Self {
ErrorType::TBLErr(value)
}
}
impl From<GblError> for ErrorType {
fn from(value: GblError) -> Self {
ErrorType::GblErr(value)
}
}
impl fmt::Display for ErrorType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorType::DBErr(data) => write!(f, "database: {}", data),
ErrorType::IDErr(data) => write!(f, "id: {}", data),
ErrorType::TBLErr(data) => write!(f, "table: {}", data),
ErrorType::GblErr(data) => write!(f, "global: {}", data),
}
}
}
#[cfg(test)]
mod errortypes {
use super::*;
#[test]
fn database_error() {
let err = DBError::DuplicateTable("something".to_string());
let result = ErrorType::from(err.clone());
assert_eq!(result.to_string(), format!("database: {}", err));
}
#[test]
fn id_error() {
let err = IDError::InvalidUuid("bad".to_string());
let result = ErrorType::from(err.clone());
assert_eq!(result.to_string(), format!("id: {}", err));
}
#[test]
fn table_error() {
let err = TBLError::InvalidField("bad".to_string());
let result = ErrorType::from(err.clone());
assert_eq!(result.to_string(), format!("table: {}", err));
}
#[test]
fn universal_error() {
let err = GblError::DuplicateDB("bad".to_string());
let result = ErrorType::from(err.clone());
assert_eq!(result.to_string(), format!("global: {}", err));
}
}
#[derive(Debug)]
pub struct MTTError {
err: ErrorType,
}
impl From<ErrorType> for MTTError {
fn from(value: ErrorType) -> Self {
MTTError::new(value)
}
}
impl MTTError {
pub fn new(err: ErrorType) -> Self {
Self { err: err }
}
pub fn get_code(&self) -> &ErrorType {
&self.err
}
}
impl Error for MTTError {}
impl fmt::Display for MTTError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.err.to_string())
}
}
impl From<DBError> for MTTError {
fn from(value: DBError) -> Self {
Self { err: value.into() }
}
}
impl From<IDError> for MTTError {
fn from(value: IDError) -> Self {
Self { err: value.into() }
}
}
impl From<TBLError> for MTTError {
fn from(value: TBLError) -> Self {
Self { err: value.into() }
}
}
impl From<GblError> for MTTError {
fn from(value: GblError) -> Self {
Self { err: value.into() }
}
}
#[cfg(test)]
mod errors {
use super::*;
use rand::{distributions::Alphanumeric, Rng};
fn rand_str() -> String {
rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(5)
.map(char::from)
.collect()
}
#[test]
fn from_id_error() {
let error = IDError::InvalidUuid(rand_str());
let err = MTTError::from(error.clone());
assert_eq!(err.to_string(), ErrorType::IDErr(error).to_string());
}
#[test]
fn from_database_error() {
let error = DBError::DuplicateTable(rand_str());
let err = MTTError::from(error.clone());
assert_eq!(err.to_string(), ErrorType::DBErr(error).to_string());
}
#[test]
fn from_table_error() {
let error = TBLError::InvalidField(rand_str());
let err = MTTError::from(error.clone());
assert_eq!(err.to_string(), ErrorType::TBLErr(error).to_string());
}
#[test]
fn from_global_error() {
let error = GblError::DuplicateDB(rand_str());
let err = MTTError::from(error.clone());
assert_eq!(err.to_string(), ErrorType::GblErr(error).to_string());
}
}

View File

@ -1,106 +0,0 @@
use crate::{backend::BackEndMessage, queue::Message, session2::SessionMessage, Field, Request};
use std::{
sync::mpsc::{channel, Receiver, Sender},
thread::spawn,
};
struct FrontEnd {
tx: Sender<Message>,
rx: Receiver<Message>,
}
impl FrontEnd {
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 frontend = FrontEnd::new(queue_tx.clone(), rx);
queue_tx.send(tx.into()).unwrap();
frontend.listen();
});
}
fn listen(&self) {
loop {
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)]
mod frontends {
use super::*;
use crate::{
create_request::empty_request, session2::create_session_message::create_session_new,
};
use std::time::Duration;
fn run_service() -> (Sender<Message>, Receiver<Message>) {
let (tx, rx) = channel();
let service_tx: Sender<Message>;
FrontEnd::start(tx);
match rx.recv().unwrap() {
Message::Register(result) => service_tx = result,
_ => unreachable!("should register the service"),
}
(service_tx, rx)
}
#[test]
fn gets_registered() {
let (tx, rx) = channel();
FrontEnd::start(tx);
match rx.recv().unwrap() {
Message::Register(_) => {}
_ => unreachable!("should register the service"),
}
}
#[test]
fn handle_request() {
let (tx, rx) = run_service();
let (req, _) = empty_request();
tx.send(req.into()).unwrap();
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
Message::SessMsg(output) => match output {
SessionMessage::Validate(result) => assert!(result.is_none()),
_ => unreachable!("Should have sent a val9idate"),
},
_ => unreachable!("Should have generated a session message"),
}
let (new_sess, sess_id) = create_session_new();
tx.send(new_sess.into()).unwrap();
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
Message::BEMsg(result) => match result {
BackEndMessage::Get => {}
_ => unreachable!("incorrect message type"),
},
_ => unreachable!("incorrect message type"),
}
}
}

View File

@ -1,93 +0,0 @@
use super::{ClientMsg, Msg, SessionMsg};
use uuid::Uuid;
/// Message Types
#[derive(Clone)]
pub enum MsgData {
Client(ClientMsg),
Session(SessionMsg),
Test1,
Test2,
}
/// MoreThanText Message Structure
#[derive(Clone)]
pub struct Message {
id: Uuid,
msg: MsgData,
}
impl Message {
pub fn new<D>(data: &D) -> Self
where
D: Msg,
{
Self {
id: Uuid::new_v4(),
msg: data.to_msgdata(),
}
}
pub fn get_message(&self) -> &MsgData {
&self.msg
}
pub fn get_id(&self) -> Uuid {
self.id.clone()
}
pub fn reply<D>(&self, data: &D) -> Self
where
D: Msg,
{
Self {
id: self.id.clone(),
msg: data.to_msgdata(),
}
}
}
#[cfg(test)]
mod messages {
use super::{super::test_message::Tester, *};
#[test]
fn new_messagees() {
let data = Tester::Test1;
let msg = Message::new(&data);
match msg.get_message() {
MsgData::Test1 => {}
_ => unreachable!("Should have received Test1"),
}
let data = Tester::Test2;
let msg = Message::new(&data);
match msg.get_message() {
MsgData::Test2 => {}
_ => unreachable!("Should have received Test1"),
}
}
#[test]
fn message_ids_are_unique() {
let mut ids: Vec<Uuid> = Vec::new();
let data = Tester::Test1;
for _ in 1..10 {
let msg = Message::new(&data);
assert!(!ids.contains(&msg.get_id()), "Had a duplicate id");
ids.push(msg.get_id());
}
}
#[test]
fn create_replies() {
let data1 = Tester::Test1;
let data2 = Tester::Test2;
let msg = Message::new(&data1);
let reply = msg.reply(&data2);
assert_eq!(reply.get_id(), msg.get_id());
match reply.get_message() {
MsgData::Test2 => {}
_ => unreachable!("Should have been a Test1"),
}
}
}

View File

@ -1,597 +0,0 @@
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());
}
}

View File

@ -1,156 +0,0 @@
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"),
}
}
}
}

View File

@ -1,329 +0,0 @@
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),
}
impl From<Sender<Message>> for Message {
fn from(value: Sender<Message>) -> Self {
Message::Register(value)
}
}
impl From<Request> for Message {
fn from(value: Request) -> Self {
Message::Req(value)
}
}
#[cfg(test)]
mod messages {
use super::*;
use crate::request_test_data::request_root_document;
#[test]
fn from_request() {
let (req, _) = request_root_document();
match req.into() {
Message::Req(_) => {},
_ => unreachable!("should have been s request"),
}
}
#[test]
fn from_sender() {
let (tx, rx) = channel();
match tx.into() {
Message::Register(result) => {
let (req, _) = request_root_document();
result.send(req.into()).unwrap();
match rx.recv().unwrap() {
Message::Req(_) => {}
_ => unreachable!("should have been a request"),
}
}
_ => unreachable!("should have been a register"),
}
}
}
pub 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();
}
}
}
}
}
pub 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::request_test_data::request_root_document;
#[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(tx.clone().into()).unwrap();
}
let (req, _) = request_root_document();
queue_tx.send(req.into()).unwrap();
for (_, rx) in channels.iter() {
match rx.recv().unwrap() {
Message::Req(_) => {}
_ => unreachable!("should have been a request"),
}
}
}
}
*/

View File

@ -1,66 +0,0 @@
use super::Message;
use std::{
sync::mpsc::{Receiver, Sender},
thread::spawn,
};
pub struct Router {
txs: Vec<Sender<Message>>,
rx: Receiver<Message>,
}
impl Router {
fn new(senders: Vec<Sender<Message>>, rx: Receiver<Message>) -> Self {
Self {
txs: senders,
rx: rx,
}
}
pub fn start(senders: Vec<Sender<Message>>, rx: Receiver<Message>) {
spawn(move || {
let router = Router::new(senders, rx);
router.listen();
});
}
fn listen(&self) {
loop {
let msg = self.rx.recv().unwrap();
for tx in self.txs.iter() {
tx.send(msg.clone()).unwrap();
}
}
}
}
#[cfg(test)]
mod messages {
use super::super::MsgData;
use super::{super::test_message::Tester, *};
use std::sync::mpsc::channel;
#[test]
fn forward_messages() {
let (tx, rx) = channel();
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
let senders = vec![tx1, tx2];
Router::start(senders, rx);
let data = Tester::Test1;
let msg = Message::new(&data);
tx.send(msg.clone()).unwrap();
let result1 = rx1.recv().unwrap();
assert_eq!(result1.get_id(), msg.get_id());
match result1.get_message() {
MsgData::Test1 => {}
_ => unreachable!("Should have been test1."),
}
let result2 = rx2.recv().unwrap();
assert_eq!(result2.get_id(), msg.get_id());
match result2.get_message() {
MsgData::Test1 => {}
_ => unreachable!("Should have been test1."),
}
}
}

View File

@ -1,240 +0,0 @@
use super::{Message, Msg, MsgData};
use std::{
fmt,
sync::mpsc::{channel, Receiver, Sender},
thread::spawn,
};
use uuid::Uuid;
#[derive(Clone)]
pub enum SessionMsg {
Get(Option<String>),
Opened(SessionData),
}
impl Msg for SessionMsg {
fn to_msgdata(&self) -> MsgData {
MsgData::Session(self.clone())
}
}
#[derive(Clone)]
pub struct SessionData {
id: Uuid,
}
impl SessionData {
pub fn new(id: Uuid) -> Self {
Self { id: id }
}
}
impl fmt::Display for SessionData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.id)
}
}
pub struct Session {
router_tx: Sender<Message>,
session_rx: Receiver<Message>,
ids: Vec<Uuid>,
}
impl Session {
fn new(router_tx: Sender<Message>, session_rx: Receiver<Message>) -> Self {
Self {
router_tx: router_tx,
session_rx: session_rx,
ids: Vec::new(),
}
}
pub fn start(router_tx: Sender<Message>) -> Sender<Message> {
let (session_tx, session_rx) = channel();
spawn(move || {
let mut session = Session::new(router_tx, session_rx);
session.listen();
});
session_tx
}
fn listen(&mut self) {
loop {
let msg = self.session_rx.recv().unwrap();
match msg.get_message() {
MsgData::Session(data) => match data {
SessionMsg::Get(req_id) => {
let id: Uuid;
match req_id {
Some(req) => match Uuid::try_parse(req) {
Ok(data) => {
if self.ids.contains(&data) {
id = data;
} else {
id = self.create_session();
}
}
Err(_) => id = self.create_session(),
},
None => id = self.create_session(),
}
let data = SessionMsg::Opened(SessionData::new(id));
self.router_tx.send(msg.reply(&data)).unwrap()
}
_ => {}
},
_ => {}
}
}
}
fn create_session(&mut self) -> Uuid {
let id = Uuid::new_v4();
self.ids.push(id.clone());
id
}
}
#[cfg(test)]
mod messages {
use super::{super::test_message::Tester, *};
use std::time::Duration;
fn setup_session() -> (Sender<Message>, Receiver<Message>) {
let (tx, rx) = channel();
let session_tx = Session::start(tx);
(session_tx, rx)
}
#[test]
fn ignore_unwanted_messages() {
let (tx, rx) = setup_session();
let data = Tester::Test1;
let msg = Message::new(&data);
tx.send(msg).unwrap();
match rx.recv_timeout(Duration::from_millis(500)) {
Err(_) => {}
_ => unreachable!("Should not receive anything."),
}
}
#[test]
fn create_new_session() {
let (tx, rx) = setup_session();
let msgdata = SessionMsg::Get(None);
let msg = Message::new(&msgdata);
tx.send(msg.clone()).unwrap();
let result = rx.recv().unwrap();
assert_eq!(result.get_id(), msg.get_id());
match result.get_message() {
MsgData::Session(data) => match data {
SessionMsg::Opened(_) => {}
_ => unreachable!("Should have been an opened response."),
},
_ => unreachable!("Should be a session responsee."),
}
}
#[test]
fn ignore_session_replies() {
let (tx, rx) = setup_session();
let msgdata = SessionMsg::Opened(SessionData::new(Uuid::new_v4()));
let msg = Message::new(&msgdata);
tx.send(msg).unwrap();
match rx.recv_timeout(Duration::from_millis(500)) {
Err(_) => {}
_ => unreachable!("Should not receive anything."),
}
}
#[test]
fn ids_must_be_unique() {
let (tx, rx) = setup_session();
let msgdata = SessionMsg::Get(None);
let mut ids: Vec<String> = Vec::new();
for _ in 0..10 {
let msg = Message::new(&msgdata);
tx.send(msg).unwrap();
match rx.recv().unwrap().get_message() {
MsgData::Session(msg) => match msg {
SessionMsg::Opened(sess) => {
let id = sess.to_string();
assert!(!ids.contains(&id), "duplicated id found.");
ids.push(id);
}
_ => unreachable!("Shouuld have opened a session."),
},
_ => unreachable!("Should be a session message"),
}
}
}
#[test]
fn expired_ids_get_new() {
let (tx, rx) = setup_session();
let old_id = Uuid::new_v4();
let msgdata = SessionMsg::Get(Some(old_id.to_string()));
let msg = Message::new(&msgdata);
tx.send(msg.clone()).unwrap();
let result = rx.recv().unwrap();
assert_eq!(result.get_id(), msg.get_id());
match result.get_message() {
MsgData::Session(msg) => match msg {
SessionMsg::Opened(sess) => assert_ne!(sess.to_string(), old_id.to_string()),
_ => unreachable!("Should habe been an Opened message."),
},
_ => unreachable!("Should have been a session message."),
}
}
#[test]
fn bad_session_ids_get_new() {
let (tx, rx) = setup_session();
let id = "something badA";
let msgdata = SessionMsg::Get(Some(id.to_string()));
let msg = Message::new(&msgdata);
tx.send(msg.clone()).unwrap();
let result = rx.recv().unwrap();
assert_eq!(result.get_id(), msg.get_id());
match result.get_message() {
MsgData::Session(data) => match data {
SessionMsg::Opened(sess) => assert_ne!(sess.to_string(), id),
_ => unreachable!("Should habe been an Opened message."),
},
_ => unreachable!("Should have been a session message."),
}
}
#[test]
fn uses_existing_session() {
let (tx, rx) = setup_session();
let msgdata = SessionMsg::Get(None);
let msg = Message::new(&msgdata);
tx.send(msg).unwrap();
let result = rx.recv().unwrap();
let thesess = match result.get_message() {
MsgData::Session(data) => match data {
SessionMsg::Opened(sess) => sess,
_ => unreachable!("Should habe been an Opened message."),
},
_ => unreachable!("Should have been a session message."),
};
let msgdata = SessionMsg::Get(Some(thesess.to_string()));
let msg = Message::new(&msgdata);
tx.send(msg.clone()).unwrap();
let result = rx.recv().unwrap();
assert_eq!(result.get_id(), msg.get_id());
match result.get_message() {
MsgData::Session(data) => match data {
SessionMsg::Opened(sess) => assert_eq!(
sess.to_string(),
thesess.to_string(),
"Should use existing sesssion."
),
_ => unreachable!("Should habe been an Opened message."),
},
_ => unreachable!("Should have been a session message."),
}
}
}

View File

@ -1,114 +0,0 @@
use crate::{queue::Message, Field};
use std::{
sync::mpsc::{channel, Receiver, Sender},
thread::spawn,
};
use uuid::Uuid;
#[derive(Clone)]
pub enum SessionMessage {
New(Field),
Validate(Option<Field>),
}
impl From<Option<Field>> for SessionMessage {
fn from(value: Option<Field>) -> Self {
SessionMessage::Validate(value)
}
}
#[cfg(test)]
pub mod create_session_message {
use super::*;
pub fn create_session_new() -> (SessionMessage, Uuid) {
let id = Uuid::new_v4();
(SessionMessage::New(id.into()), id)
}
}
#[cfg(test)]
mod sessionmessages {
use super::*;
#[test]
fn from_optional_field() {
let text = "afield";
let id = Some(text.into());
match id.into() {
SessionMessage::Validate(result) => match result {
Some(data) => match data {
Field::Static(output) => assert_eq!(output, text),
_ => unreachable!("should have returned static text"),
},
None => unreachable!("shoulf have returned data"),
},
_ => unreachable!("should have been a vaqlidate"),
}
}
}
struct Session {
tx: Sender<Message>,
rx: Receiver<Message>,
}
impl Session {
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 session = Session::new(queue_tx.clone(), rx);
queue_tx.send(tx.clone().into()).unwrap();
session.listen();
});
}
fn listen(&self) {
loop {
self.rx.recv().unwrap();
let res = Uuid::nil();
self.tx.send(SessionMessage::New(res.into()).into());
}
}
}
#[cfg(test)]
mod sessions {
use super::*;
use std::time::Duration;
#[test]
fn gets_registered() {
let (tx, rx) = channel();
Session::start(tx);
match rx.recv().unwrap() {
Message::Register(_) => {}
_ => unreachable!("should register the service"),
}
}
#[test]
fn validate_none_returns_new_id() {
let (tx, rx) = channel();
let sender: Sender<Message>;
Session::start(tx);
match rx.recv().unwrap() {
Message::Register(result) => sender = result,
_ => unreachable!("should register the service"),
}
let data: Option<Field> = None;
let req: SessionMessage = data.into();
sender.send(req.into()).unwrap();
match rx.recv_timeout(Duration::from_millis(500)).unwrap() {
Message::SessMsg(data) => match data {
SessionMessage::New(_) => {}
_ => unreachable!("should have been a new session"),
},
_ => unreachable!("should have been a session message response"),
}
}
}