aboutsummaryrefslogtreecommitdiff
path: root/tests/test_parse_simple_string.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_parse_simple_string.rs')
-rw-r--r--tests/test_parse_simple_string.rs185
1 files changed, 185 insertions, 0 deletions
diff --git a/tests/test_parse_simple_string.rs b/tests/test_parse_simple_string.rs
new file mode 100644
index 0000000..2e9ed11
--- /dev/null
+++ b/tests/test_parse_simple_string.rs
@@ -0,0 +1,185 @@
+use codecrafters_redis::resp_parser::*;
+
+#[test]
+fn test_valid_simple_strings() {
+ // Basic valid cases
+ assert_eq!(parse_simple_strings(b"+OK\r\n").unwrap().0, "OK");
+ assert_eq!(parse_simple_strings(b"+PONG\r\n").unwrap().0, "PONG");
+ assert_eq!(
+ parse_simple_strings(b"+Hello World\r\n").unwrap().0,
+ "Hello World"
+ );
+
+ // Empty string
+ assert_eq!(parse_simple_strings(b"+\r\n").unwrap().0, "");
+
+ // String with spaces and special characters (but no \r or \n)
+ assert_eq!(
+ parse_simple_strings(b"+Hello, World! 123\r\n").unwrap().0,
+ "Hello, World! 123"
+ );
+
+ // String with various ASCII characters
+ assert_eq!(
+ parse_simple_strings(b"+!@#$%^&*()_+-={}[]|\\:;\"'<>?,./ \r\n")
+ .unwrap()
+ .0,
+ "!@#$%^&*()_+-={}[]|\\:;\"'<>?,./ "
+ );
+
+ // Unicode characters (should work with UTF-8)
+ assert_eq!(
+ parse_simple_strings(b"+\xc3\xa9\xc3\xa1\xc3\xb1\r\n")
+ .unwrap()
+ .0,
+ "éáñ"
+ );
+}
+
+#[test]
+fn test_invalid_prefix() {
+ // Missing '+' prefix
+ assert_eq!(
+ parse_simple_strings(b"OK\r\n").err().unwrap().message(),
+ "WRONGTYPE Operation against a key holding the wrong kind of value"
+ );
+
+ // Wrong prefix
+ assert_eq!(
+ parse_simple_strings(b"-Error\r\n").err().unwrap().message(),
+ "WRONGTYPE Operation against a key holding the wrong kind of value"
+ );
+ assert_eq!(
+ parse_simple_strings(b":123\r\n").err().unwrap().message(),
+ "WRONGTYPE Operation against a key holding the wrong kind of value"
+ );
+ assert_eq!(
+ parse_simple_strings(b"$5\r\nhello\r\n")
+ .err()
+ .unwrap()
+ .message(),
+ "WRONGTYPE Operation against a key holding the wrong kind of value"
+ );
+}
+
+#[test]
+fn test_missing_crlf_terminator() {
+ // No CRLF at all
+ assert_eq!(
+ parse_simple_strings(b"+OK").err().unwrap().message(),
+ "ERR Unexpected end of input"
+ );
+
+ // Only \r
+ assert_eq!(
+ parse_simple_strings(b"+OK\r").err().unwrap().message(),
+ "ERR Unexpected end of input"
+ );
+
+ // Only \n
+ assert_eq!(
+ parse_simple_strings(b"+OK\n").err().unwrap().message(),
+ "ERR Unexpected end of input"
+ );
+
+ // Wrong order (\n\r instead of \r\n)
+ assert_eq!(
+ parse_simple_strings(b"+OK\n\r").err().unwrap().message(),
+ "ERR Unexpected end of input"
+ );
+}
+
+#[test]
+fn test_invalid_characters_in_content() {
+ // Contains \r in content
+ assert_eq!(
+ parse_simple_strings(b"+Hello\rWorld\r\n")
+ .err()
+ .unwrap()
+ .message(),
+ "ERR invalid value"
+ );
+
+ // Contains \n in content
+ assert_eq!(
+ parse_simple_strings(b"+Hello\nWorld\r\n")
+ .err()
+ .unwrap()
+ .message(),
+ "ERR invalid value"
+ );
+}
+
+#[test]
+fn test_empty_input() {
+ assert_eq!(
+ parse_simple_strings(b"").err().unwrap().message(),
+ "ERR Empty data"
+ );
+}
+
+#[test]
+fn test_with_trailing_data() {
+ // RESP simple string with extra data after CRLF (should be ignored)
+ assert_eq!(parse_simple_strings(b"+OK\r\nextra_data").unwrap().0, "OK");
+ assert_eq!(
+ parse_simple_strings(b"+PONG\r\n+another_string\r\n")
+ .unwrap()
+ .0,
+ "PONG"
+ );
+}
+
+#[test]
+fn test_real_world_redis_responses() {
+ // Common Redis simple string responses
+ assert_eq!(parse_simple_strings(b"+OK\r\n").unwrap().0, "OK");
+ assert_eq!(parse_simple_strings(b"+PONG\r\n").unwrap().0, "PONG");
+ assert_eq!(parse_simple_strings(b"+QUEUED\r\n").unwrap().0, "QUEUED");
+
+ // Redis status responses
+ assert_eq!(
+ parse_simple_strings(b"+Background saving started\r\n")
+ .unwrap()
+ .0,
+ "Background saving started"
+ );
+ assert_eq!(
+ parse_simple_strings(b"+Background saving successfully finished\r\n")
+ .unwrap()
+ .0,
+ "Background saving successfully finished"
+ );
+}
+
+#[test]
+fn test_edge_cases() {
+ // Just the prefix and CRLF
+ assert_eq!(parse_simple_strings(b"+\r\n").unwrap().0, "");
+
+ // Long string
+ let long_string = "a".repeat(1000);
+ let mut input = b"+".to_vec();
+ input.extend_from_slice(long_string.as_bytes());
+ input.extend_from_slice(b"\r\n");
+ assert_eq!(parse_simple_strings(&input).unwrap().0, long_string);
+
+ // String with only spaces
+ assert_eq!(parse_simple_strings(b"+ \r\n").unwrap().0, " ");
+
+ // String with tabs and other whitespace
+ assert_eq!(parse_simple_strings(b"+\t \t\r\n").unwrap().0, "\t \t");
+}
+
+#[test]
+fn test_binary_safety_within_limits() {
+ // Non-UTF8 bytes (but no \r or \n)
+ let mut input = b"+".to_vec();
+ input.extend_from_slice(&[0xFF, 0xFE, 0xFD]); // Invalid UTF-8
+ input.extend_from_slice(b"\r\n");
+
+ // Should handle invalid UTF-8 gracefully with replacement characters
+ if let RespType::SimpleString(data) = parse_simple_strings(&input).unwrap().0 {
+ assert!(!data.is_empty()); // Should contain replacement characters
+ }
+}