use crate::protocal::parser::{ParseError, Parser};
use crate::protocal::resp::RespValue;
use std::borrow::Cow;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simple_string() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"+OK\r\n");
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(result, RespValue::SimpleString(Cow::Borrowed("OK")));
parser.read_buf(b"+Hello World\r\n"); let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(
result,
RespValue::SimpleString(Cow::Borrowed("Hello World"))
);
parser.read_buf(b"+Hello@#$%^&*()\r\n");
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(
result,
RespValue::SimpleString(Cow::Borrowed("Hello@#$%^&*()"))
);
}
#[test]
fn test_error() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"-Error message\r\n");
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(result, RespValue::Error(Cow::Borrowed("Error message")));
parser.read_buf(b"-\r\n");
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(result, RespValue::Error(Cow::Borrowed("")));
parser.read_buf(b"-ERR unknown command 'foobar'\r\n");
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(
result,
RespValue::Error(Cow::Borrowed("ERR unknown command 'foobar'"))
);
}
#[test]
fn test_integer() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b":1234\r\n");
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(result, RespValue::Integer(1234));
parser.read_buf(b":-1234\r\n");
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(result, RespValue::Integer(-1234));
parser.read_buf(b":0\r\n");
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(result, RespValue::Integer(0));
parser.read_buf(format!(":{}\r\n", i64::MAX).as_bytes());
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(result, RespValue::Integer(i64::MAX));
parser.read_buf(format!(":{}\r\n", i64::MIN).as_bytes());
let result = match parser.try_parse() {
Ok(Some(val)) => val,
Ok(None) => panic!("Expected complete value"),
Err(e) => panic!("Parse error: {:?}", e),
};
assert_eq!(result, RespValue::Integer(i64::MIN));
}
#[test]
fn test_invalid_type_marker() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"x1234");
match parser.try_parse() {
Err(ParseError::InvalidFormat(_)) => (), other => panic!("Expected InvalidFormat error, got {:?}", other),
}
}
#[test]
fn test_invalid_length() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"$-2");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None for incomplete data, got {:?}", other),
}
parser.read_buf(b"\r\n");
match parser.try_parse() {
Ok(Some(RespValue::Null)) => (), other => panic!("Expected InvalidLength error, got {:?}", other),
}
}
#[test]
fn test_array_length_mismatch() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"*2\r\n+OK\r\n");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None for incomplete array, got {:?}", other),
}
}
#[test]
fn test_invalid_integer_format() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b":12.34");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None for incomplete data, got {:?}", other),
}
parser.read_buf(b"\r\n");
match parser.try_parse() {
Err(ParseError::InvalidFormat(_)) => (), other => panic!("Expected InvalidFormat error, got {:?}", other),
}
}
#[test]
fn test_missing_crlf() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"+OK\n");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected InvalidFormat error, got {:?}", other),
}
}
#[test]
fn test_exceeding_maximum_depth() {
let mut shallow_parser = Parser::new(1, 1000);
shallow_parser.read_buf(b"*1\r\n");
match shallow_parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None for incomplete data, got {:?}", other),
}
shallow_parser.read_buf(b"*1\r\n");
match shallow_parser.try_parse() {
Err(ParseError::InvalidDepth) => (), other => panic!("Expected None for incomplete data, got {:?}", other),
}
shallow_parser.read_buf(b"+OK\r\n");
match shallow_parser.try_parse() {
Err(ParseError::InvalidDepth) => (), other => panic!(
"Expected InvalidFormat error for exceeding maximum depth, got {:?}",
other
),
}
}
#[test]
fn test_incomplete_messages() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"+OK");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!(
"Expected None for incomplete simple string, got {:?}",
other
),
}
parser = Parser::new(100, 1000);
parser.read_buf(b"-ERR");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!(
"Expected None for incomplete error message, got {:?}",
other
),
}
parser = Parser::new(100, 1000);
parser.read_buf(b":123");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None for incomplete integer, got {:?}", other),
}
parser = Parser::new(100, 1000);
parser.read_buf(b"$5");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!(
"Expected None for incomplete bulk string length, got {:?}",
other
),
}
parser = Parser::new(100, 1000);
parser.read_buf(b"*3");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None for incomplete array length, got {:?}", other),
}
}
#[test]
fn test_large_messages() {
let mut parser = Parser::new(100, 10000);
let large_string = "x".repeat(1000);
let message = format!("${}\r\n{}\r\n", large_string.len(), large_string);
parser.read_buf(format!("${}\r\n", large_string.len()).as_bytes());
match parser.try_parse() {
Err(ParseError::NotEnoughData) => (), other => panic!("Expected None, got {:?}", other),
}
let chunks = large_string.as_bytes().chunks(100);
for chunk in chunks {
parser.read_buf(chunk);
match parser.try_parse() {
Err(ParseError::NotEnoughData) => (), other => panic!("Expected None, got {:?}", other),
}
}
parser.read_buf(b"\r\n");
match parser.try_parse() {
Ok(Some(RespValue::BulkString(Some(msg)))) => {
assert_eq!(msg, large_string);
}
other => panic!("Expected BulkString, got {:?}", other),
}
let mut large_array = String::from("*1000\r\n");
parser.read_buf(large_array.as_bytes());
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None, got {:?}", other),
}
for _ in 0..999 {
parser.read_buf(b":1\r\n");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None, got {:?}", other),
}
}
parser.read_buf(b":1\r\n");
match parser.try_parse() {
Ok(Some(RespValue::Array(Some(arr)))) => {
assert_eq!(arr.len(), 1000);
assert!(arr.iter().all(|x| *x == RespValue::Integer(1)));
}
other => panic!("Expected Array, got {:?}", other),
}
}
#[test]
fn test_error_message_chunks() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"-ERR unknow");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None, got {:?}", other),
}
parser.read_buf(b"n command");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None, got {:?}", other),
}
parser.read_buf(b"\r\n");
match parser.try_parse() {
Ok(Some(RespValue::Error(msg))) => {
assert_eq!(msg, "ERR unknown command");
}
other => panic!("Expected Error message, got {:?}", other),
}
}
#[test]
fn test_bulk_string_chunks() {
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"$0\r\n\r\n");
let result = parser.try_parse();
assert_eq!(result, Ok(Some(RespValue::Null)));
}
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"$0\r\n");
let result = parser.try_parse();
assert_eq!(result, Ok(Some(RespValue::Null)));
parser.read_buf(b"\r\n");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::UnexpectedEof));
}
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"$5");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::UnexpectedEof));
parser.read_buf(b"\r\nhello");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::NotEnoughData));
parser.read_buf(b"\r\n");
let result = parser.try_parse();
assert_eq!(
result,
Ok(Some(RespValue::BulkString(Some(Cow::Borrowed("hello")))))
);
}
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"$12\r\n");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::NotEnoughData));
parser.read_buf(b"Hello ");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::NotEnoughData));
parser.read_buf(b"World!");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::NotEnoughData));
parser.read_buf(b"\r\n");
let result = parser.try_parse();
assert_eq!(
result,
Ok(Some(RespValue::BulkString(Some(Cow::Borrowed(
"Hello World!"
)))))
);
}
}
#[test]
fn test_array_chunks() {
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"*2");
_ = parser.try_parse();
parser.read_buf(b"\r\n:1");
_ = parser.try_parse();
parser.read_buf(b"\r\n");
_ = parser.try_parse();
parser.read_buf(b":2\r\n");
let result = parser.try_parse();
assert_eq!(
result,
Ok(Some(RespValue::Array(Some(vec![
RespValue::Integer(1),
RespValue::Integer(2)
]))))
);
}
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"*0\r\n");
let result = parser.try_parse();
assert_eq!(result, Ok(Some(RespValue::Array(None))));
}
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"*-1\r\n");
let result = parser.try_parse();
assert_eq!(result, Ok(Some(RespValue::Array(None))));
}
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"*3\r\n:123\r\n");
_ = parser.try_parse();
parser.read_buf(b"+hello\r\n");
_ = parser.try_parse();
parser.read_buf(b"$5\r\nworld\r\n");
let result = parser.try_parse();
assert_eq!(
result,
Ok(Some(RespValue::Array(Some(vec![
RespValue::Integer(123),
RespValue::SimpleString("hello".into()),
RespValue::BulkString(Some("world".into()))
]))))
);
}
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"*2\r\n");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::UnexpectedEof));
parser.read_buf(b"*2\r\n+a\r\n+b\r\n");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::UnexpectedEof));
parser.read_buf(b"*2\r\n+c\r\n+d\r\n");
let result = parser.try_parse();
assert_eq!(
result,
Ok(Some(RespValue::Array(Some(vec![
RespValue::Array(Some(vec![
RespValue::SimpleString(Cow::Borrowed("a")),
RespValue::SimpleString(Cow::Borrowed("b"))
])),
RespValue::Array(Some(vec![
RespValue::SimpleString(Cow::Borrowed("c")),
RespValue::SimpleString(Cow::Borrowed("d"))
]))
]))))
);
}
{
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"*-2\r\n");
let result = parser.try_parse();
assert_eq!(result, Ok(Some(RespValue::Array(None))));
parser = Parser::new(100, 1000);
parser.read_buf(b"*2\r\n:1\r\n");
let result = parser.try_parse();
assert_eq!(result, Err(ParseError::UnexpectedEof)); }
let mut parser = Parser::new(100, 1000);
parser.read_buf(b"*0\r\n");
assert_eq!(parser.try_parse(), Ok(Some(RespValue::Array(None))));
parser.read_buf(b"*-1\r\n");
assert_eq!(parser.try_parse(), Ok(Some(RespValue::Array(None))));
parser.read_buf(b"*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n");
assert_eq!(
parser.try_parse(),
Ok(Some(RespValue::Array(Some(vec![
RespValue::BulkString(Some(Cow::Borrowed("hello"))),
RespValue::BulkString(Some(Cow::Borrowed("world")))
]))))
);
parser.read_buf(b"*5\r\n:1\r\n:2\r\n:3\r\n:4\r\n$5\r\nhello\r\n");
assert_eq!(
parser.try_parse(),
Ok(Some(RespValue::Array(Some(vec![
RespValue::Integer(1),
RespValue::Integer(2),
RespValue::Integer(3),
RespValue::Integer(4),
RespValue::BulkString(Some(Cow::Borrowed("hello")))
]))))
);
parser.read_buf(b"*2\r\n*2\r\n+a\r\n+b\r\n*2\r\n+c\r\n+d\r\n");
assert_eq!(
parser.try_parse(),
Ok(Some(RespValue::Array(Some(vec![
RespValue::Array(Some(vec![
RespValue::SimpleString(Cow::Borrowed("a")),
RespValue::SimpleString(Cow::Borrowed("b"))
])),
RespValue::Array(Some(vec![
RespValue::SimpleString(Cow::Borrowed("c")),
RespValue::SimpleString(Cow::Borrowed("d"))
]))
]))))
);
}
#[test]
fn test_integer_chunks() {
let mut parser = Parser::new(100, 1000);
parser.read_buf(b":123");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None, got {:?}", other),
}
parser.read_buf(b"45");
match parser.try_parse() {
Err(ParseError::UnexpectedEof) => (), other => panic!("Expected None, got {:?}", other),
}
parser.read_buf(b"\r\n");
match parser.try_parse() {
Ok(Some(RespValue::Integer(num))) => {
assert_eq!(num, 12345);
}
other => panic!("Expected Integer, got {:?}", other),
}
}
#[test]
fn test_large_bulk_string_chunks() {
let mut parser = Parser::new(100, 10000);
let large_string = "x".repeat(1000);
parser.read_buf(format!("${}\r\n", large_string.len()).as_bytes());
match parser.try_parse() {
Err(ParseError::NotEnoughData) => (), other => panic!("Expected None, got {:?}", other),
}
let chunk_size = 100;
for chunk in large_string.as_bytes().chunks(chunk_size) {
parser.read_buf(chunk);
match parser.try_parse() {
Err(ParseError::NotEnoughData) => (), other => panic!("Expected None while processing chunks, got {:?}", other),
}
}
parser.read_buf(b"\r\n");
match parser.try_parse() {
Ok(Some(RespValue::BulkString(Some(msg)))) => {
assert_eq!(msg, large_string);
}
other => panic!("Expected BulkString, got {:?}", other),
}
}
}