Skip to content

Commit 67e297a

Browse files
author
Drew Robinson
committed
Add wincode binary compatibility tests
These tests verify that wincode produces byte-for-byte identical output to bincode 1.3.3, ensuring wire protocol compatibility with existing clients.
1 parent 352f2db commit 67e297a

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

libsql-server/src/rpc/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub mod replica_proxy;
2323
pub mod replication;
2424
pub mod streaming_exec;
2525

26+
#[cfg(test)]
27+
mod wincode_compat_test;
28+
2629
pub async fn run_rpc_server<A: crate::net::Accept>(
2730
proxy_service: ProxyService,
2831
acceptor: A,
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#![cfg(test)]
2+
3+
//! Tests to verify wincode binary compatibility with bincode 1.3.3.
4+
//!
5+
//! These tests ensure that the migration from bincode to wincode maintains
6+
//! wire protocol compatibility with existing clients (particularly the Go client).
7+
8+
use crate::query::Value;
9+
10+
#[test]
11+
fn test_wincode_produces_same_bytes_as_bincode() {
12+
// Test that wincode produces identical bytes to what bincode 1.3.3 would produce.
13+
// This is critical for maintaining wire protocol compatibility.
14+
15+
let test_cases = vec![
16+
("Null", Value::Null, vec![0, 0, 0, 0]),
17+
(
18+
"Integer(42)",
19+
Value::Integer(42),
20+
vec![1, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0],
21+
),
22+
(
23+
"Integer(i64::MAX)",
24+
Value::Integer(i64::MAX),
25+
vec![1, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 127],
26+
),
27+
(
28+
"Real(3.14159)",
29+
Value::Real(3.14159),
30+
vec![2, 0, 0, 0, 110, 134, 27, 240, 249, 33, 9, 64],
31+
),
32+
(
33+
"Text(empty)",
34+
Value::Text(String::new()),
35+
vec![3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
36+
),
37+
(
38+
"Text(Hello)",
39+
Value::Text("Hello".to_string()),
40+
vec![3, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 72, 101, 108, 108, 111],
41+
),
42+
(
43+
"Blob([1,2,3])",
44+
Value::Blob(vec![1, 2, 3]),
45+
vec![4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3],
46+
),
47+
];
48+
49+
for (name, value, expected_bytes) in test_cases {
50+
let serialised = wincode::serialize(&value).expect("wincode serialisation failed");
51+
52+
assert_eq!(
53+
serialised, expected_bytes,
54+
"{}: wincode output differs from expected bincode output",
55+
name
56+
);
57+
58+
// Also verify roundtrip
59+
let deserialised: Value = wincode::deserialize(&serialised)
60+
.expect("wincode deserialisation failed");
61+
62+
assert_eq!(
63+
format!("{:?}", value),
64+
format!("{:?}", deserialised),
65+
"{}: roundtrip failed",
66+
name
67+
);
68+
}
69+
}
70+
71+
#[test]
72+
fn test_wincode_roundtrip_all_variants() {
73+
// Verify that all Value variants can be serialised and deserialised correctly.
74+
let values = vec![
75+
Value::Null,
76+
Value::Integer(0),
77+
Value::Integer(i64::MIN),
78+
Value::Integer(i64::MAX),
79+
Value::Real(0.0),
80+
Value::Real(std::f64::consts::PI),
81+
Value::Real(f64::MIN),
82+
Value::Real(f64::MAX),
83+
Value::Text(String::new()),
84+
Value::Text("test".to_string()),
85+
Value::Text("unicode: 🦀🚀".to_string()),
86+
Value::Blob(vec![]),
87+
Value::Blob(vec![0u8, 255u8]),
88+
Value::Blob(vec![1, 2, 3, 4, 5]),
89+
];
90+
91+
for value in &values {
92+
let encoded = wincode::serialize(value).expect("encode failed");
93+
let decoded: Value = wincode::deserialize(&encoded).expect("decode failed");
94+
assert_eq!(
95+
format!("{:?}", value),
96+
format!("{:?}", decoded),
97+
"roundtrip failed for {:?}",
98+
value
99+
);
100+
}
101+
}

0 commit comments

Comments
 (0)