Skip to content

Commit 0488f64

Browse files
author
Drew Robinson
committed
tests: Make sure postcard works with some verification tests.
1 parent 5342a6f commit 0488f64

File tree

3 files changed

+33
-461
lines changed

3 files changed

+33
-461
lines changed
Lines changed: 33 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -1,205 +1,52 @@
11
#![cfg(test)]
22

3-
//! RPC-specific tests for postcard serialization
4-
//! These tests verify postcard works correctly in the actual RPC layer
3+
//! Minimal smoke tests for postcard serialisation.
4+
//! These verify the bincode → postcard migration works correctly.
55
66
use crate::query::Value;
77

8+
/// Verify roundtrip works for all Value variants.
89
#[test]
9-
fn test_value_roundtrip_null() {
10-
let value = Value::Null;
11-
let encoded = postcard::to_stdvec(&value).unwrap();
12-
let decoded: Value = postcard::from_bytes(&encoded).unwrap();
13-
14-
match (value, decoded) {
15-
(Value::Null, Value::Null) => {},
16-
_ => panic!("roundtrip failed"),
17-
}
18-
}
19-
20-
#[test]
21-
fn test_value_roundtrip_integer() {
22-
let test_cases = vec![0i64, 1, -1, i64::MAX, i64::MIN];
23-
24-
for i in test_cases {
25-
let value = Value::Integer(i);
26-
let encoded = postcard::to_stdvec(&value).unwrap();
27-
let decoded: Value = postcard::from_bytes(&encoded).unwrap();
28-
29-
match decoded {
30-
Value::Integer(decoded_i) if decoded_i == i => {},
31-
_ => panic!("roundtrip failed for {}", i),
32-
}
33-
}
34-
}
35-
36-
#[test]
37-
fn test_value_roundtrip_real() {
38-
let test_cases = vec![0.0f64, 1.0, -1.0, 3.14159, f64::MAX, f64::MIN];
39-
40-
for f in test_cases {
41-
let value = Value::Real(f);
42-
let encoded = postcard::to_stdvec(&value).unwrap();
43-
let decoded: Value = postcard::from_bytes(&encoded).unwrap();
44-
45-
match decoded {
46-
Value::Real(decoded_f) if (decoded_f - f).abs() < 1e-10 => {},
47-
_ => panic!("roundtrip failed for {}", f),
48-
}
49-
}
50-
}
51-
52-
#[test]
53-
fn test_value_roundtrip_text() {
54-
let test_cases = vec![
55-
String::new(),
56-
"hello".to_string(),
57-
"🦀 Rust".to_string(),
58-
"a".repeat(10_000),
59-
];
60-
61-
for s in test_cases {
62-
let value = Value::Text(s.clone());
63-
let encoded = postcard::to_stdvec(&value).unwrap();
64-
let decoded: Value = postcard::from_bytes(&encoded).unwrap();
65-
66-
match decoded {
67-
Value::Text(decoded_s) if decoded_s == s => {},
68-
_ => panic!("roundtrip failed for text"),
69-
}
70-
}
71-
}
72-
73-
#[test]
74-
fn test_value_roundtrip_blob() {
75-
let test_cases = vec![
76-
vec![],
77-
vec![0u8],
78-
vec![255u8],
79-
(0..256).map(|i| (i % 256) as u8).collect::<Vec<_>>(),
80-
vec![0u8; 10000],
81-
];
82-
83-
for b in test_cases {
84-
let value = Value::Blob(b.clone());
85-
let encoded = postcard::to_stdvec(&value).unwrap();
86-
let decoded: Value = postcard::from_bytes(&encoded).unwrap();
87-
88-
match decoded {
89-
Value::Blob(decoded_b) if decoded_b == b => {},
90-
_ => panic!("roundtrip failed for blob"),
91-
}
92-
}
93-
}
94-
95-
#[test]
96-
fn test_large_blob_roundtrip() {
97-
let large_blob = vec![42u8; 1_000_000];
98-
let value = Value::Blob(large_blob.clone());
99-
let encoded = postcard::to_stdvec(&value).unwrap();
100-
let decoded: Value = postcard::from_bytes(&encoded).unwrap();
101-
102-
match decoded {
103-
Value::Blob(decoded_b) if decoded_b == large_blob => {},
104-
_ => panic!("large blob roundtrip failed"),
105-
}
106-
}
107-
108-
#[test]
109-
fn test_binary_safe_roundtrip() {
110-
// Verify that binary data with null bytes is preserved
111-
let binary_data = vec![0u8, 1, 2, 255, 254, 0, 0, 1];
112-
let value = Value::Blob(binary_data.clone());
113-
let encoded = postcard::to_stdvec(&value).unwrap();
114-
let decoded: Value = postcard::from_bytes(&encoded).unwrap();
115-
116-
match decoded {
117-
Value::Blob(decoded_b) if decoded_b == binary_data => {
118-
// Verify no null terminators were added
119-
assert!(!decoded_b.ends_with(&[0]));
120-
},
121-
_ => panic!("binary roundtrip failed"),
122-
}
123-
}
124-
125-
#[test]
126-
fn test_deterministic_encoding() {
127-
// Same value should always encode to same bytes
128-
let value = Value::Text("test".to_string());
129-
let encoded1 = postcard::to_stdvec(&value).unwrap();
130-
let encoded2 = postcard::to_stdvec(&value).unwrap();
131-
let encoded3 = postcard::to_stdvec(&value).unwrap();
132-
133-
assert_eq!(encoded1, encoded2, "encoding not deterministic");
134-
assert_eq!(encoded2, encoded3, "encoding not deterministic");
135-
}
136-
137-
#[test]
138-
fn test_different_values_different_encoding() {
139-
let value1 = Value::Integer(42);
140-
let value2 = Value::Integer(43);
141-
142-
let encoded1 = postcard::to_stdvec(&value1).unwrap();
143-
let encoded2 = postcard::to_stdvec(&value2).unwrap();
144-
145-
assert_ne!(encoded1, encoded2, "different values should encode differently");
146-
}
147-
148-
#[test]
149-
fn test_malformed_data_handling() {
150-
// Empty data should fail
151-
let result: Result<Value, _> = postcard::from_bytes(&[]);
152-
assert!(result.is_err(), "should fail on empty data");
153-
154-
// Garbage data should fail
155-
let garbage = vec![0xff, 0xfe, 0xfd, 0xfc];
156-
let result: Result<Value, _> = postcard::from_bytes(&garbage);
157-
// Either fails or returns something - both acceptable
158-
let _ = result;
159-
}
160-
161-
#[test]
162-
fn test_positional_params_serialization() {
10+
fn test_value_roundtrip_all_variants() {
16311
let values = vec![
164-
Value::Integer(42),
165-
Value::Text("hello".to_string()),
166-
Value::Real(3.14),
16712
Value::Null,
13+
Value::Integer(0),
14+
Value::Integer(i64::MAX),
15+
Value::Integer(i64::MIN),
16+
Value::Real(std::f64::consts::PI),
17+
Value::Real(f64::MAX),
18+
Value::Text(String::new()),
19+
Value::Text("hello 🦀".to_string()),
20+
Value::Blob(vec![]),
21+
Value::Blob(vec![0u8, 255u8]),
16822
];
169-
170-
for value in values {
171-
let encoded = postcard::to_stdvec(&value).unwrap();
172-
let _decoded: Value = postcard::from_bytes(&encoded).unwrap();
173-
// If we get here, roundtrip succeeded
23+
24+
for value in &values {
25+
let encoded = postcard::to_stdvec(value).expect("encode failed");
26+
let decoded: Value = postcard::from_bytes(&encoded).expect("decode failed");
27+
assert_eq!(format!("{:?}", value), format!("{:?}", decoded));
17428
}
17529
}
17630

31+
/// Verify large blobs don't hit size limits.
17732
#[test]
178-
fn test_size_efficiency() {
179-
// Verify encoded sizes are reasonable
180-
let int_value = Value::Integer(42);
181-
let encoded = postcard::to_stdvec(&int_value).unwrap();
182-
assert!(encoded.len() < 20, "integer encoding too large");
183-
184-
let text_value = Value::Text("hello world".to_string());
185-
let encoded = postcard::to_stdvec(&text_value).unwrap();
186-
assert!(encoded.len() < 25, "short text encoding too large");
187-
188-
let blob_value = Value::Blob(vec![0u8; 100]);
189-
let encoded = postcard::to_stdvec(&blob_value).unwrap();
190-
assert!(encoded.len() < 120, "blob encoding too large");
33+
fn test_large_blob_roundtrip() {
34+
let value = Value::Blob(vec![42u8; 1_000_000]);
35+
let encoded = postcard::to_stdvec(&value).expect("encode failed");
36+
let decoded: Value = postcard::from_bytes(&encoded).expect("decode failed");
37+
assert!(matches!(decoded, Value::Blob(b) if b.len() == 1_000_000));
19138
}
19239

40+
/// Verify postcard errors convert correctly to our error type.
19341
#[test]
194-
fn test_error_handling_consistency() {
195-
// Test that errors are consistent
42+
fn test_postcard_error_conversion() {
19643
let garbage = vec![0xff, 0xfe];
197-
let result1: Result<Value, _> = postcard::from_bytes(&garbage);
198-
let result2: Result<Value, _> = postcard::from_bytes(&garbage);
199-
200-
// Both should fail or both should succeed (deterministic behavior)
201-
match (result1, result2) {
202-
(Ok(_), Ok(_)) | (Err(_), Err(_)) => {}, // Both same - good
203-
_ => panic!("error handling not deterministic"),
44+
let result: Result<Value, postcard::Error> = postcard::from_bytes(&garbage);
45+
46+
if let Err(e) = result {
47+
let crate_error = crate::error::Error::from(e);
48+
assert!(
49+
matches!(crate_error, crate::error::Error::Internal(msg) if msg.contains("Unexpected"))
50+
);
20451
}
20552
}

libsql/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,6 @@ mod value;
172172
#[cfg(feature = "serde")]
173173
pub mod de;
174174

175-
#[cfg(all(test, feature = "replication"))]
176-
mod postcard_migration_tests;
177-
178175
pub use value::{Value, ValueRef, ValueType};
179176

180177
cfg_hrana! {

0 commit comments

Comments
 (0)