Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion tests/common.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#![cfg(feature = "rust")]
#![cfg(all(feature = "rust", feature = "cpp"))]

use std::io::Cursor;

use fastpfor::rust::{
Composition, FastPFOR, FastPForResult, Integer, JustCopy, VariableByte, BLOCK_SIZE_128,
DEFAULT_PAGE_SIZE,
};
use rand::rngs::StdRng;
use rand::Rng as _;
use rand::SeedableRng as _;

pub enum TestCodec {
VariableByte(VariableByte, String),
Expand Down Expand Up @@ -81,3 +84,47 @@ pub fn get_codecs() -> Vec<TestCodec> {
),
]
}

pub fn test_input_sizes() -> Vec<usize> {
(1..=8).map(|exp| (1usize << exp) * 128).collect()
}

pub fn get_test_cases(n: usize) -> Vec<Vec<u32>> {
let mut rng = StdRng::seed_from_u64(14);

vec![
// Zeroes
vec![0u32; n],
// Same non-zero
vec![14u32; n],
// Ascending values
(0..n).map(|i| i as u32).collect::<Vec<u32>>(),
// Descending values
(0..n).rev().map(|i| i as u32).collect::<Vec<u32>>(),
// Bit-flipping pattern
(0..n)
.map(|i| ((i as u32) * 32) ^ ((i as u32) >> 1))
.collect::<Vec<u32>>(),
// Alternating large and small values
(0..n)
.map(|i| {
let ui = i as u32;
if ui % 2 == 0 {
1 << 30
} else {
3
}
})
.collect::<Vec<u32>>(),
// Random u32 values
(0..n)
.map(|_| rng.random_range(0..(1 << 31)))
.collect::<Vec<u32>>(),
// Spike in the middle
(0..n)
.map(|i| if i == n / 2 { u32::MAX } else { 1 })
.collect::<Vec<u32>>(),
// An empty vector
Vec::new(),
]
}
104 changes: 73 additions & 31 deletions tests/cpp_compat_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,84 @@ use fastpfor::rust::Integer as _;
use fastpfor::{cpp, rust};
use std::io::Cursor;

mod common;
use common::{get_test_cases, test_input_sizes};

#[test]
fn test_rust_decompresses_cpp_encoded_data() {
let input: Vec<u32> = (0..256).map(|i| (i * 32) ^ (i >> 1)).collect();
let codec_cpp = cpp::FastPFor128Codec::new();
let mut codec_rs = rust::FastPFOR::new(rust::DEFAULT_PAGE_SIZE, rust::BLOCK_SIZE_128);

// Buffer for the C++ encoded
let mut compressed_buffer = vec![0; input.len()];
for n in test_input_sizes() {
for input in get_test_cases(n + rust::BLOCK_SIZE_128 as usize) {
// Buffer for the C++ encoded
let mut compressed_buffer = vec![0; input.len()];

// C++ encoding
let codec_cpp = cpp::FastPFor128Codec::new();
let encoded_cpp = codec_cpp.encode32(&input, &mut compressed_buffer).unwrap();
let compressed_len = encoded_cpp.len();
// C++ encoding
let encoded_cpp = codec_cpp.encode32(&input, &mut compressed_buffer).unwrap();
let compressed_len = encoded_cpp.len();

// C++ decoding
let mut decoded_by_cpp = vec![0; input.len()];
let decoded_cpp = codec_cpp
.decode32(encoded_cpp, &mut decoded_by_cpp)
.unwrap();
// C++ decoding
let mut decoded_by_cpp = vec![0; input.len()];
let decoded_cpp = codec_cpp
.decode32(encoded_cpp, &mut decoded_by_cpp)
.unwrap();

// Rust decoding
let mut input_offset = Cursor::new(0u32);
let mut decoded_by_rust = vec![0; input.len()];
codec_rs
.uncompress(
&compressed_buffer,
compressed_len as u32,
&mut input_offset,
&mut decoded_by_rust,
&mut Cursor::new(0u32),
)
.unwrap();

assert_eq!(
decoded_cpp.len(),
decoded_by_rust.len(),
"Mismatched output lengths"
);
assert_eq!(decoded_cpp, decoded_by_rust);
}
}
}

// Rust decoding
let mut input_offset = Cursor::new(0u32);
#[test]
fn test_rust_and_cpp_fastpfor32_compression_matches() {
let codec_cpp = cpp::FastPFor128Codec::new();
let mut codec_rs = rust::FastPFOR::new(rust::DEFAULT_PAGE_SIZE, rust::BLOCK_SIZE_128);
let mut decoded_by_rust = vec![0; input.len()];
codec_rs
.uncompress(
&compressed_buffer,
compressed_len as u32,
&mut input_offset,
&mut decoded_by_rust,
&mut Cursor::new(0u32),
)
.unwrap();

assert_eq!(
decoded_cpp.len(),
decoded_by_rust.len(),
"Mismatched output lengths"
);
assert_eq!(decoded_cpp, decoded_by_rust);

for n in test_input_sizes() {
for input in get_test_cases(n + rust::BLOCK_SIZE_128 as usize) {
// Buffer for the C++ encoded
let mut compressed_buffer = vec![0; input.len()];

// C++ encoding
let encoded_cpp = codec_cpp.encode32(&input, &mut compressed_buffer).unwrap();
let compressed_len = encoded_cpp.len();

// Rust encoding
let mut input_offset_rs = Cursor::new(0u32);
let mut encoded_rs: Vec<u32> = vec![0; input.len()];
let mut output_offset_rs = Cursor::new(0u32);
codec_rs
.compress(
&input,
input.len() as u32,
&mut input_offset_rs,
&mut encoded_rs,
&mut output_offset_rs,
)
.unwrap();

assert_eq!(
&encoded_cpp[..compressed_len],
&encoded_rs[..compressed_len]
);
}
}
}
Loading