Skip to content

Commit dc87145

Browse files
committed
test: ensure rust and cpp compression matches
1 parent 765eff1 commit dc87145

File tree

2 files changed

+114
-31
lines changed

2 files changed

+114
-31
lines changed

tests/cpp_compat_tests.rs

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,80 @@ use fastpfor::rust::Integer as _;
55
use fastpfor::{cpp, rust};
66
use std::io::Cursor;
77

8+
mod test_data;
9+
use test_data::get_test_cases;
10+
811
#[test]
912
fn test_rust_decompresses_cpp_encoded_data() {
10-
let input: Vec<u32> = (0..256).map(|i| (i * 32) ^ (i >> 1)).collect();
13+
let codec_cpp = cpp::FastPFor128Codec::new();
14+
let mut codec_rs = rust::FastPFOR::new(rust::DEFAULT_PAGE_SIZE, rust::BLOCK_SIZE_128);
1115

12-
// Buffer for the C++ encoded
13-
let mut compressed_buffer = vec![0; input.len()];
16+
for input in get_test_cases(512 + rust::BLOCK_SIZE_128 as usize) {
17+
// Buffer for the C++ encoded
18+
let mut compressed_buffer = vec![0; input.len()];
1419

15-
// C++ encoding
16-
let codec_cpp = cpp::FastPFor128Codec::new();
17-
let encoded_cpp = codec_cpp.encode32(&input, &mut compressed_buffer).unwrap();
18-
let compressed_len = encoded_cpp.len();
20+
// C++ encoding
21+
let encoded_cpp = codec_cpp.encode32(&input, &mut compressed_buffer).unwrap();
22+
let compressed_len = encoded_cpp.len();
1923

20-
// C++ decoding
21-
let mut decoded_by_cpp = vec![0; input.len()];
22-
let decoded_cpp = codec_cpp
23-
.decode32(encoded_cpp, &mut decoded_by_cpp)
24-
.unwrap();
24+
// C++ decoding
25+
let mut decoded_by_cpp = vec![0; input.len()];
26+
let decoded_cpp = codec_cpp
27+
.decode32(encoded_cpp, &mut decoded_by_cpp)
28+
.unwrap();
29+
30+
// Rust decoding
31+
let mut input_offset = Cursor::new(0u32);
32+
let mut decoded_by_rust = vec![0; input.len()];
33+
codec_rs
34+
.uncompress(
35+
&compressed_buffer,
36+
compressed_len as u32,
37+
&mut input_offset,
38+
&mut decoded_by_rust,
39+
&mut Cursor::new(0u32),
40+
)
41+
.unwrap();
42+
43+
assert_eq!(
44+
decoded_cpp.len(),
45+
decoded_by_rust.len(),
46+
"Mismatched output lengths"
47+
);
48+
assert_eq!(decoded_cpp, decoded_by_rust);
49+
}
50+
}
2551

26-
// Rust decoding
27-
let mut input_offset = Cursor::new(0u32);
52+
#[test]
53+
fn test_rust_and_cpp_fastpfor32_compression_matches() {
54+
let codec_cpp = cpp::FastPFor128Codec::new();
2855
let mut codec_rs = rust::FastPFOR::new(rust::DEFAULT_PAGE_SIZE, rust::BLOCK_SIZE_128);
29-
let mut decoded_by_rust = vec![0; input.len()];
30-
codec_rs
31-
.uncompress(
32-
&compressed_buffer,
33-
compressed_len as u32,
34-
&mut input_offset,
35-
&mut decoded_by_rust,
36-
&mut Cursor::new(0u32),
37-
)
38-
.unwrap();
39-
40-
assert_eq!(
41-
decoded_cpp.len(),
42-
decoded_by_rust.len(),
43-
"Mismatched output lengths"
44-
);
45-
assert_eq!(decoded_cpp, decoded_by_rust);
56+
57+
for input in get_test_cases(512 + rust::BLOCK_SIZE_128 as usize) {
58+
// Buffer for the C++ encoded
59+
let mut compressed_buffer = vec![0; input.len()];
60+
61+
// C++ encoding
62+
let encoded_cpp = codec_cpp.encode32(&input, &mut compressed_buffer).unwrap();
63+
let compressed_len = encoded_cpp.len();
64+
65+
// Rust encoding
66+
let mut input_offset_rs = Cursor::new(0u32);
67+
let mut encoded_rs: Vec<u32> = vec![0; input.len()];
68+
let mut output_offset_rs = Cursor::new(0u32);
69+
codec_rs
70+
.compress(
71+
&input,
72+
input.len() as u32,
73+
&mut input_offset_rs,
74+
&mut encoded_rs,
75+
&mut output_offset_rs,
76+
)
77+
.unwrap();
78+
79+
assert_eq!(
80+
&encoded_cpp[..compressed_len],
81+
&encoded_rs[..compressed_len]
82+
);
83+
}
4684
}

tests/test_data.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#![cfg(all(feature = "rust", feature = "cpp"))]
2+
3+
use rand::rngs::StdRng;
4+
use rand::Rng as _;
5+
use rand::SeedableRng as _;
6+
7+
pub fn get_test_cases(n: usize) -> Vec<Vec<u32>> {
8+
let mut rng = StdRng::seed_from_u64(14);
9+
10+
vec![
11+
// Zeroes
12+
vec![0u32; n],
13+
// Same non-zero
14+
vec![14u32; n],
15+
// Ascending values
16+
(0..n).map(|i| i as u32).collect::<Vec<u32>>(),
17+
// Descending values
18+
(0..n).rev().map(|i| i as u32).collect::<Vec<u32>>(),
19+
// Bit-flipping pattern
20+
(0..n)
21+
.map(|i| ((i as u32) * 32) ^ ((i as u32) >> 1))
22+
.collect::<Vec<u32>>(),
23+
// Alternating large and small values
24+
(0..n)
25+
.map(|i| {
26+
let ui = i as u32;
27+
if ui % 2 == 0 {
28+
1 << 30
29+
} else {
30+
3
31+
}
32+
})
33+
.collect::<Vec<u32>>(),
34+
// Random u32 values
35+
(0..n)
36+
.map(|_| rng.random_range(0..(1 << 31)))
37+
.collect::<Vec<u32>>(),
38+
// Spike in the middle
39+
(0..n)
40+
.map(|i| if i == n / 2 { u32::MAX } else { 1 })
41+
.collect::<Vec<u32>>(),
42+
// An empty vector
43+
Vec::new(),
44+
]
45+
}

0 commit comments

Comments
 (0)