|
1 | 1 | #![cfg(test)] |
2 | 2 |
|
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. |
5 | 5 |
|
6 | 6 | use crate::query::Value; |
7 | 7 |
|
| 8 | +/// Verify roundtrip works for all Value variants. |
8 | 9 | #[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() { |
163 | 11 | let values = vec![ |
164 | | - Value::Integer(42), |
165 | | - Value::Text("hello".to_string()), |
166 | | - Value::Real(3.14), |
167 | 12 | 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]), |
168 | 22 | ]; |
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)); |
174 | 28 | } |
175 | 29 | } |
176 | 30 |
|
| 31 | +/// Verify large blobs don't hit size limits. |
177 | 32 | #[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)); |
191 | 38 | } |
192 | 39 |
|
| 40 | +/// Verify postcard errors convert correctly to our error type. |
193 | 41 | #[test] |
194 | | -fn test_error_handling_consistency() { |
195 | | - // Test that errors are consistent |
| 42 | +fn test_postcard_error_conversion() { |
196 | 43 | 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 | + ); |
204 | 51 | } |
205 | 52 | } |
0 commit comments