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
317 changes: 167 additions & 150 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ modelardb_storage = { path = "crates/modelardb_storage"}
modelardb_test = { path = "crates/modelardb_test"}
modelardb_types = { path = "crates/modelardb_types"}
object_store = "0.13.2"
proptest = "1.11.0"
proptest = { version = "1.11.0", features = ["attr-macro"]}
prost = "0.14.3"
prost-build = "0.14.3"
protox = "0.9.1"
Expand Down
15 changes: 9 additions & 6 deletions crates/modelardb_compression/src/models/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl Default for BitVecBuilder {
#[cfg(test)]
mod tests {
use super::*;
use proptest::{bool, collection, prop_assert, prop_assume, proptest};
use proptest::{bool, collection, prop_assert, prop_assume, property_test};

// The largest byte, a random byte, and the smallest byte for testing.
const TEST_BYTES: &[u8] = &[255, 170, 0];
Expand Down Expand Up @@ -311,16 +311,19 @@ mod tests {
));
}

proptest! {
#[test]
fn test_writing_and_reading_random_bits(bits in collection::vec(bool::ANY, 0..50)) {
#[property_test]
fn test_writing_and_reading_random_bits(
#[strategy = collection::vec(bool::ANY, 0..50)] bits: Vec<bool>,
) {
prop_assume!(!bits.is_empty());
let mut bit_vector_builder = BitVecBuilder::new();
for bit in &bits {
write_bool_as_bit(&mut bit_vector_builder, *bit);
}
prop_assert!(bytes_and_bits_are_equal(&bit_vector_builder.finish(), &bits));
}
prop_assert!(bytes_and_bits_are_equal(
&bit_vector_builder.finish(),
&bits
));
}

fn bytes_and_bits_are_equal(bytes: &[u8], bits: &[bool]) -> bool {
Expand Down
47 changes: 24 additions & 23 deletions crates/modelardb_compression/src/models/macaque_v.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ mod tests {

use modelardb_test::ERROR_BOUND_TEN;
use proptest::num::f32 as ProptestValue;
use proptest::{bool, collection, prop_assert, prop_assert_eq, prop_assume, proptest};
use proptest::{bool, collection, prop_assert, prop_assert_eq, prop_assume, property_test};

use crate::models;

Expand All @@ -351,29 +351,33 @@ mod tests {
assert!(MacaqueV::new(ErrorBound::Lossless).model().0.is_empty());
}

proptest! {
#[test]
fn test_append_single_value_with_lossless_error_bound(value in ProptestValue::ANY) {
#[property_test]
fn test_append_single_value_with_lossless_error_bound(value: f32) {
let mut model_type = MacaqueV::new(ErrorBound::Lossless);

model_type.compress_values(&[value]);

prop_assert!(models::equal_or_nan(value as f64, model_type.last_value as f64));
prop_assert!(models::equal_or_nan(
value as f64,
model_type.last_value as f64
));
prop_assert_eq!(model_type.last_leading_zero_bits, u8::MAX);
prop_assert_eq!(model_type.last_trailing_zero_bits, 0);
}

#[test]
fn test_append_repeated_values_with_lossless_error_bound(value in ProptestValue::ANY) {
#[property_test]
fn test_append_repeated_values_with_lossless_error_bound(value: f32) {
let mut model_type = MacaqueV::new(ErrorBound::Lossless);

model_type.compress_values(&[value, value]);

prop_assert!(models::equal_or_nan(value as f64, model_type.last_value as f64));
prop_assert!(models::equal_or_nan(
value as f64,
model_type.last_value as f64
));
prop_assert_eq!(model_type.last_leading_zero_bits, u8::MAX);
prop_assert_eq!(model_type.last_trailing_zero_bits, 0);
}
}

#[test]
fn test_append_different_values_with_leading_zero_bits_with_lossless_error_bound() {
Expand Down Expand Up @@ -433,18 +437,17 @@ mod tests {
}

// Tests for sum().
proptest! {
#[test]
fn test_sum_with_lossless_error_bound(values in collection::vec(ProptestValue::ANY, 0..50)) {
#[property_test]
fn test_sum_with_lossless_error_bound(
#[strategy = collection::vec(ProptestValue::ANY, 0..50)] values: Vec<Value>,
) {
prop_assume!(!values.is_empty());
let expected_sum = values.iter().sum::<f32>();
let compressed_values = compress_values_using_macaque_v(
ErrorBound::Lossless,
&values, None);
let compressed_values =
compress_values_using_macaque_v(ErrorBound::Lossless, &values, None);
let sum = sum(values.len(), &compressed_values, None);
prop_assert!(models::equal_or_nan(expected_sum as f64, sum as f64));
}
}

#[test]
fn test_sum_model_single_value_with_lossless_error_bound() {
Expand All @@ -464,14 +467,12 @@ mod tests {
}

// Tests for grid().
proptest! {
#[test]
fn test_grid_with_lossless_error_bound(values in collection::vec(ProptestValue::ANY, 0..50)) {
#[property_test]
fn test_grid_with_lossless_error_bound(
#[strategy = collection::vec(ProptestValue::ANY, 0..50)] values: Vec<Value>,
) {
prop_assume!(!values.is_empty());
assert_grid_with_error_bound(
ErrorBound::Lossless,
&values);
}
assert_grid_with_error_bound(ErrorBound::Lossless, &values);
}

fn assert_grid_with_error_bound(error_bound: ErrorBound, values: &[Value]) {
Expand Down
138 changes: 86 additions & 52 deletions crates/modelardb_compression/src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,100 +290,136 @@ mod tests {
use modelardb_test::{
ERROR_BOUND_ABSOLUTE_MAX, ERROR_BOUND_ONE, ERROR_BOUND_RELATIVE_MAX, ERROR_BOUND_TEN,
};
use proptest::num;
use proptest::num::f32 as ProptestValue;
use proptest::{prop_assert, prop_assume, proptest};
use proptest::{prop_assert, prop_assume, property_test};

// Tests for is_value_within_error_bound().
proptest! {
#[test]
fn test_same_value_is_always_within_lossless_error_bound(value in ProptestValue::ANY) {
prop_assert!(is_value_within_error_bound(ErrorBound::Lossless, value, value));
#[property_test]
fn test_same_value_is_always_within_lossless_error_bound(value: Value) {
prop_assert!(is_value_within_error_bound(
ErrorBound::Lossless,
value,
value
));
}

#[test]
fn test_other_value_is_never_within_absolute_error_bound_of_positive_infinity(value in ProptestValue::ANY) {
#[property_test]
fn test_other_value_is_never_within_absolute_error_bound_of_positive_infinity(value: Value) {
prop_assume!(value != Value::INFINITY);
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(), Value::INFINITY, value));
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(),
Value::INFINITY,
value
));
}

#[test]
fn test_other_value_is_never_within_relative_error_bound_of_positive_infinity(value in ProptestValue::ANY) {
#[property_test]
fn test_other_value_is_never_within_relative_error_bound_of_positive_infinity(value: Value) {
prop_assume!(value != Value::INFINITY);
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(), Value::INFINITY, value));
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(),
Value::INFINITY,
value
));
}

#[test]
fn test_other_value_is_never_within_absolute_error_bound_of_negative_infinity(value in ProptestValue::ANY) {
#[property_test]
fn test_other_value_is_never_within_absolute_error_bound_of_negative_infinity(value: Value) {
prop_assume!(value != Value::NEG_INFINITY);
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(), Value::NEG_INFINITY, value));
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(),
Value::NEG_INFINITY,
value
));
}

#[test]
fn test_other_value_is_never_within_relative_error_bound_of_negative_infinity(value in ProptestValue::ANY) {
#[property_test]
fn test_other_value_is_never_within_relative_error_bound_of_negative_infinity(value: Value) {
prop_assume!(value != Value::NEG_INFINITY);
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(), Value::NEG_INFINITY, value));
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(),
Value::NEG_INFINITY,
value
));
}

#[test]
fn test_other_value_is_never_within_absolute_error_bound_of_nan(value in ProptestValue::ANY) {
#[property_test]
fn test_other_value_is_never_within_absolute_error_bound_of_nan(value: Value) {
prop_assume!(!value.is_nan());
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(), Value::NAN, value));
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(),
Value::NAN,
value
));
}

#[test]
fn test_other_value_is_never_within_relative_error_bound_of_nan(value in ProptestValue::ANY) {
#[property_test]
fn test_other_value_is_never_within_relative_error_bound_of_nan(value: Value) {
prop_assume!(!value.is_nan());
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(), Value::NAN, value));
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(),
Value::NAN,
value
));
}

#[test]
fn test_positive_infinity_is_never_within_absolute_error_bound_of_other_value(value in ProptestValue::ANY) {
#[property_test]
fn test_positive_infinity_is_never_within_absolute_error_bound_of_other_value(value: Value) {
prop_assume!(value != Value::INFINITY);
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(), value, Value::INFINITY));
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(),
value,
Value::INFINITY
));
}

#[test]
fn test_positive_infinity_is_never_within_relative_error_bound_of_other_value(value in ProptestValue::ANY) {
#[property_test]
fn test_positive_infinity_is_never_within_relative_error_bound_of_other_value(value: Value) {
prop_assume!(value != Value::INFINITY);
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(), value, Value::INFINITY));
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(),
value,
Value::INFINITY
));
}

#[test]
fn test_negative_infinity_is_never_within_absolute_error_bound_of_other_value(value in ProptestValue::ANY) {
#[property_test]
fn test_negative_infinity_is_never_within_absolute_error_bound_of_other_value(value: Value) {
prop_assume!(value != Value::NEG_INFINITY);
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(), value, Value::NEG_INFINITY));
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(),
value,
Value::NEG_INFINITY
));
}

#[test]
fn test_negative_infinity_is_never_within_relative_error_bound_of_other_value(value in ProptestValue::ANY) {
#[property_test]
fn test_negative_infinity_is_never_within_relative_error_bound_of_other_value(value: Value) {
prop_assume!(value != Value::NEG_INFINITY);
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(), value, Value::NEG_INFINITY));
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(),
value,
Value::NEG_INFINITY
));
}

#[test]
fn test_nan_is_never_within_absolute_error_bound_of_other_value(value in ProptestValue::ANY) {
#[property_test]
fn test_nan_is_never_within_absolute_error_bound_of_other_value(value: Value) {
prop_assume!(!value.is_nan());
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(), value, Value::NAN));
ErrorBound::try_new_absolute(ERROR_BOUND_ABSOLUTE_MAX).unwrap(),
value,
Value::NAN
));
}

#[test]
fn test_nan_is_never_within_relative_error_bound_of_other_value(value in ProptestValue::ANY) {
#[property_test]
fn test_nan_is_never_within_relative_error_bound_of_other_value(value: Value) {
prop_assume!(!value.is_nan());
prop_assert!(!is_value_within_error_bound(
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(), value, Value::NAN));
}
ErrorBound::try_new_relative(ERROR_BOUND_RELATIVE_MAX).unwrap(),
value,
Value::NAN
));
}

#[test]
Expand Down Expand Up @@ -416,17 +452,15 @@ mod tests {
}

// Tests for equal_or_nan().
proptest! {
#[test]
fn test_equal_or_nan_equal(value in num::f64::ANY) {
#[property_test]
fn test_equal_or_nan_equal(value: f64) {
assert!(equal_or_nan(value, value));
}

#[test]
fn test_equal_or_nan_not_equal(v1 in num::f64::ANY, v2 in num::f64::ANY) {
prop_assume!(v1 != v2 && !v1.is_nan() && !v2.is_nan());
prop_assert!(!equal_or_nan(v1, v2));
}
#[property_test]
fn test_equal_or_nan_not_equal(value_one: f64, value_two: f64) {
prop_assume!(value_one != value_two && !value_one.is_nan() && !value_two.is_nan());
prop_assert!(!equal_or_nan(value_one, value_two));
}

// Tests for decompress_all_timestamps_and_split_into_models_and_residuals().
Expand Down
Loading
Loading