Skip to content

Commit

Permalink
Add tests for parser (#18)
Browse files Browse the repository at this point in the history
* first tests

* remove grpc and improve protocol test
  • Loading branch information
cospectrum authored Jan 18, 2024
1 parent dd06ef2 commit bd66500
Show file tree
Hide file tree
Showing 25 changed files with 129 additions and 750 deletions.
3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ resolver = "2"
members = [
"memcrab",
"memcrab-cache",
"memcrab-server",
"memcrab-protocol",
"memcrab-cli",
]
exclude = ["examples"]

[workspace.dependencies]
anyhow = "1.0.79"
prost = "0.12.3"
thiserror = "1.0.56"
tonic = "0.10.2"
tokio = { version = "1.35.1", default-features = false }
2 changes: 0 additions & 2 deletions examples/protogen/.gitignore

This file was deleted.

9 changes: 0 additions & 9 deletions examples/protogen/Cargo.toml

This file was deleted.

19 changes: 0 additions & 19 deletions examples/protogen/Makefile.toml

This file was deleted.

11 changes: 0 additions & 11 deletions examples/protogen/README.md

This file was deleted.

23 changes: 0 additions & 23 deletions examples/protogen/proto/cache_grpc.proto

This file was deleted.

32 changes: 0 additions & 32 deletions examples/protogen/src/main.rs

This file was deleted.

2 changes: 0 additions & 2 deletions memcrab-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,5 @@ anyhow = "1.0.79"
clap = { version = "4.4.12", features = ["derive"] }
memcrab = { version = "0.1.0", path = "../memcrab" }
memcrab-cache = { version = "0.1.0", path = "../memcrab-cache" }
memcrab-server = { version = "0.1.0", path = "../memcrab-server" }
rustyline = "13.0.0"
tokio = { version = "1.35.1", features = ["full"] }
tonic.workspace = true
7 changes: 4 additions & 3 deletions memcrab-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use clap::Parser;
use core::num::NonZeroUsize;
use memcrab::RawClient;
use memcrab_cache::Cache;
use memcrab_server::start_grpc_server;
use rustyline::error::ReadlineError;
use rustyline::DefaultEditor;

Expand All @@ -21,7 +20,8 @@ struct Cli {
}

async fn eval_lines(addr: String) -> anyhow::Result<()> {
let mut client = RawClient::connect(format!("http://{}", addr)).await?;
let addr = addr.parse()?;
let mut client = RawClient::connect(addr).await?;
let mut editor = DefaultEditor::new()?;
loop {
let line = editor.readline("memcrab> ");
Expand Down Expand Up @@ -82,12 +82,13 @@ async fn eval_line(client: &mut RawClient, line: String) -> anyhow::Result<()> {
Ok(())
}

#[allow(unused)]
async fn serve(addr: String) -> anyhow::Result<()> {
let maxbytes = 100_000;
let maxlen = NonZeroUsize::new(110).unwrap();
let cache = Cache::new(maxlen, maxbytes);

start_grpc_server(addr.parse()?, cache).await.unwrap();
todo!("server is not implemented");
Ok(())
}

Expand Down
6 changes: 3 additions & 3 deletions memcrab-protocol/src/transport/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ where
pub fn new(stream: S) -> Self {
Self { stream }
}
pub async fn make_request(&mut self, request: &Request) -> Result<Response, ClientSideError> {
pub async fn make_request(&mut self, request: Request) -> Result<Response, ClientSideError> {
let req_bytes = self.encode_request(request);
self.stream.write_all(&req_bytes).await?;

Expand Down Expand Up @@ -62,7 +62,7 @@ where
}
}
}
fn encode_request(&self, request: &Request) -> Vec<u8> {
fn encode_request(&self, request: Request) -> Vec<u8> {
let mut bytes = vec![0; RequestHeader::SIZE];
match request {
Request::Ping => {
Expand Down Expand Up @@ -119,7 +119,7 @@ where
*dst = src;
}
bytes.extend_from_slice(key);
bytes.extend_from_slice(value);
bytes.extend_from_slice(&value);
}
}
bytes
Expand Down
6 changes: 3 additions & 3 deletions memcrab-protocol/src/transport/schemas.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::mapping::alias::{Expiration, Version};
use thiserror::Error;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Request {
Version(Version),
Get(String),
Expand All @@ -15,7 +15,7 @@ pub enum Request {
Ping,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Response {
Value(Vec<u8>),
Ok,
Expand All @@ -24,7 +24,7 @@ pub enum Response {
Pong,
}

#[derive(Error, Debug, Clone)]
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum ErrorResponse {
#[error("validation error")]
Validation(String),
Expand Down
105 changes: 105 additions & 0 deletions memcrab-protocol/tests/test_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use std::net::SocketAddr;
use std::time::Duration;
use tokio::net::{TcpListener, TcpStream};
use tokio::sync::mpsc::{self, Receiver, Sender};

use memcrab_protocol::io::{AsyncReader, AsyncWriter};
use memcrab_protocol::{ClientSocket, ErrorResponse, Request, Response, ServerSocket};

#[tokio::test]
async fn test_commands() {
let addr = "127.0.0.1:9008".parse().unwrap();
let (echo_sender, echo_receiver) = mpsc::channel::<Request>(1);

let cache = |req: Request| -> Response {
match req {
Request::Ping => Response::Pong,
Request::Clear => Response::Ok,
Request::Version(_) => {
let inner = ErrorResponse::Internal("..".to_owned());
Response::Error(inner)
}
Request::Get(_) => Response::Value(vec![1, 2]),
Request::Delete(_) => Response::KeyNotFound,
Request::Set { .. } => Response::Ok,
}
};

tokio::spawn(start_server_socket(addr, echo_sender, cache));

let stream = connect(addr).await;
let socket = ClientSocket::new(stream);
let mut client = TestClient::new(socket, echo_receiver);

let resp = client.make_request(Request::Ping).await;
assert_eq!(resp, Response::Pong);

let resp = client.make_request(Request::Delete("abc".to_owned())).await;
assert_eq!(resp, Response::KeyNotFound);

client.make_request(Request::Version(1)).await;
client.make_request(Request::Clear).await;
client.make_request(Request::Get("123".to_owned())).await;
client
.make_request(Request::Set {
key: "alex".to_owned(),
value: vec![11, 2],
expiration: 2,
})
.await;
}

async fn connect(addr: SocketAddr) -> TcpStream {
for _ in 0..30 {
match TcpStream::connect(addr).await {
Ok(stream) => return stream,
Err(_) => {
tokio::time::sleep(Duration::from_secs_f32(0.1)).await;
}
}
}
unreachable!("could not connect to {:?}", addr)
}

async fn start_server_socket(
addr: SocketAddr,
echo_channel: Sender<Request>,
mut cache: impl FnMut(Request) -> Response,
) {
let listener = TcpListener::bind(addr).await.unwrap();

let (stream, _) = listener.accept().await.unwrap();
let mut server = ServerSocket::new(stream);
loop {
let req = server.recv_request().await.unwrap();
let resp = cache(req.clone());
server.send_response(&resp).await.unwrap();
echo_channel.send(req.clone()).await.unwrap();
}
}

struct TestClient<S>
where
S: AsyncReader + AsyncWriter + Send,
{
socket: ClientSocket<S>,
echo_channel: Receiver<Request>,
}

impl<S> TestClient<S>
where
S: AsyncReader + AsyncWriter + Send,
{
fn new(socket: ClientSocket<S>, echo_channel: Receiver<Request>) -> Self {
Self {
socket,
echo_channel,
}
}
async fn make_request(&mut self, request: Request) -> Response {
let resp = self.socket.make_request(request.clone()).await.unwrap();
let echo = self.echo_channel.recv().await.unwrap();
assert_eq!(echo, request);
resp
}
}
14 changes: 0 additions & 14 deletions memcrab-server/Cargo.toml

This file was deleted.

18 changes: 0 additions & 18 deletions memcrab-server/README.md

This file was deleted.

21 changes: 0 additions & 21 deletions memcrab-server/src/lib.rs

This file was deleted.

Loading

0 comments on commit bd66500

Please sign in to comment.