use crate::key_encoder::{
decode_date, decode_decimal, decode_integer, decode_real, decode_smallint, decode_time,
decode_tinyint, decode_uuid, encode_date, encode_decimal, encode_integer, encode_key,
encode_real, encode_smallint, encode_time, encode_tinyint, encode_uuid,
};
use crate::value::Value;
#[test]
fn test_tinyint_encoding_preserves_order() {
let values = [i8::MIN, i8::MIN + 1, -1, 0, 1, i8::MAX - 1, i8::MAX];
let encoded: Vec<_> = values.iter().map(|&v| encode_tinyint(v)).collect();
let mut sorted = encoded.clone();
sorted.sort_unstable();
assert_eq!(encoded, sorted, "TinyInt encoding should preserve ordering");
for &v in &values {
assert_eq!(decode_tinyint(encode_tinyint(v)), v);
}
}
#[test]
fn test_smallint_encoding_preserves_order() {
let values = [
i16::MIN,
i16::MIN + 1,
-1000,
-1,
0,
1,
1000,
i16::MAX - 1,
i16::MAX,
];
let encoded: Vec<_> = values.iter().map(|&v| encode_smallint(v)).collect();
let mut sorted = encoded.clone();
sorted.sort_unstable();
assert_eq!(
encoded, sorted,
"SmallInt encoding should preserve ordering"
);
for &v in &values {
assert_eq!(decode_smallint(encode_smallint(v)), v);
}
}
#[test]
fn test_integer_encoding_preserves_order() {
let values = [
i32::MIN,
i32::MIN + 1,
-1000000,
-1,
0,
1,
1000000,
i32::MAX - 1,
i32::MAX,
];
let encoded: Vec<_> = values.iter().map(|&v| encode_integer(v)).collect();
let mut sorted = encoded.clone();
sorted.sort_unstable();
assert_eq!(encoded, sorted, "Integer encoding should preserve ordering");
for &v in &values {
assert_eq!(decode_integer(encode_integer(v)), v);
}
}
#[test]
fn test_real_total_ordering() {
let values = [
f64::NEG_INFINITY,
-1000.0,
-1.0,
-0.0,
0.0,
1.0,
1000.0,
f64::INFINITY,
];
let encoded: Vec<_> = values.iter().map(|&v| encode_real(v)).collect();
let mut sorted = encoded.clone();
sorted.sort_unstable();
assert_eq!(
encoded, sorted,
"Real encoding should preserve total ordering for non-NaN values"
);
for &v in &values {
let decoded = decode_real(encode_real(v));
assert_eq!(decoded, v, "Value should round-trip");
}
let nan = f64::NAN;
let decoded_nan = decode_real(encode_real(nan));
assert!(decoded_nan.is_nan(), "NaN should decode to NaN");
}
#[test]
fn test_real_negative_zero_vs_positive_zero() {
let neg_zero = -0.0f64;
let pos_zero = 0.0f64;
let encoded_neg = encode_real(neg_zero);
let encoded_pos = encode_real(pos_zero);
assert!(
encoded_neg < encoded_pos,
"Negative zero should sort before positive zero"
);
}
#[test]
fn test_decimal_encoding_preserves_order() {
let scale = 2;
let values = [
(i128::MIN, scale),
(-1000000, scale),
(-100, scale),
(0, scale),
(100, scale),
(1000000, scale),
(i128::MAX, scale),
];
let encoded: Vec<_> = values.iter().map(|&(v, s)| encode_decimal(v, s)).collect();
let mut sorted = encoded.clone();
sorted.sort_unstable();
assert_eq!(encoded, sorted, "Decimal encoding should preserve ordering");
for &(v, s) in &values {
assert_eq!(decode_decimal(encode_decimal(v, s)), (v, s));
}
}
#[test]
fn test_date_encoding_preserves_order() {
let values = [i32::MIN, -365, -1, 0, 1, 365, 10000, i32::MAX];
let encoded: Vec<_> = values.iter().map(|&v| encode_date(v)).collect();
let mut sorted = encoded.clone();
sorted.sort_unstable();
assert_eq!(encoded, sorted, "Date encoding should preserve ordering");
for &v in &values {
assert_eq!(decode_date(encode_date(v)), v);
}
}
#[test]
fn test_time_encoding_preserves_order() {
let values = [
0i64,
1_000_000_000, 3_600_000_000_000, 86_400_000_000_000 - 1, ];
let encoded: Vec<_> = values.iter().map(|&v| encode_time(v)).collect();
let mut sorted = encoded.clone();
sorted.sort_unstable();
assert_eq!(encoded, sorted, "Time encoding should preserve ordering");
for &v in &values {
assert_eq!(decode_time(encode_time(v)), v);
}
}
#[test]
fn test_uuid_encoding_round_trip() {
let uuids = [
[0u8; 16],
[255u8; 16],
[
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
0x32, 0x10,
],
];
for uuid in &uuids {
assert_eq!(decode_uuid(encode_uuid(*uuid)), *uuid);
}
}
#[test]
fn test_composite_key_with_new_types() {
let values = vec![
Value::TinyInt(42),
Value::SmallInt(1000),
Value::Integer(100000),
Value::Real(3.14159),
Value::Decimal(12345, 2), Value::Uuid([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
Value::Date(19000), Value::Time(43200_000_000_000), ];
let key = encode_key(&values);
assert!(!key.as_bytes().is_empty());
assert!(
key.as_bytes().len() >= 64,
"Key should be at least 64 bytes"
);
}
#[test]
fn test_value_compare_tinyint() {
assert_eq!(
Value::TinyInt(-1).compare(&Value::TinyInt(0)),
Some(std::cmp::Ordering::Less)
);
assert_eq!(
Value::TinyInt(0).compare(&Value::TinyInt(0)),
Some(std::cmp::Ordering::Equal)
);
assert_eq!(
Value::TinyInt(1).compare(&Value::TinyInt(0)),
Some(std::cmp::Ordering::Greater)
);
}
#[test]
fn test_value_compare_real_with_special_values() {
let neg_inf = Value::Real(f64::NEG_INFINITY);
let zero = Value::Real(0.0);
let inf = Value::Real(f64::INFINITY);
assert_eq!(neg_inf.compare(&zero), Some(std::cmp::Ordering::Less));
assert_eq!(zero.compare(&inf), Some(std::cmp::Ordering::Less));
assert_eq!(neg_inf.compare(&inf), Some(std::cmp::Ordering::Less));
let nan = Value::Real(f64::NAN);
assert_eq!(nan.compare(&nan), Some(std::cmp::Ordering::Equal));
}
#[test]
fn test_value_compare_decimal_same_scale() {
let a = Value::Decimal(12345, 2); let b = Value::Decimal(12346, 2);
assert_eq!(a.compare(&b), Some(std::cmp::Ordering::Less));
}
#[test]
fn test_value_compare_decimal_different_scale() {
let a = Value::Decimal(12345, 2); let b = Value::Decimal(12345, 3);
assert_eq!(a.compare(&b), None);
}
#[test]
fn test_value_compare_different_types() {
let a = Value::Integer(42);
let b = Value::BigInt(42);
assert_eq!(a.compare(&b), None);
}
#[test]
fn test_value_to_json_all_types() {
use serde_json::json;
assert_eq!(Value::TinyInt(42).to_json(), json!(42));
assert_eq!(Value::SmallInt(1000).to_json(), json!(1000));
assert_eq!(Value::Integer(100000).to_json(), json!(100000));
assert_eq!(Value::Real(3.14).to_json(), json!(3.14));
assert_eq!(Value::Decimal(12345, 2).to_json(), json!("123.45"));
let uuid_str = Value::Uuid([
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32,
0x10,
])
.to_json();
assert_eq!(uuid_str, json!("01234567-89ab-cdef-fedc-ba9876543210"));
assert_eq!(Value::Date(19000).to_json(), json!(19000));
assert_eq!(
Value::Time(43200_000_000_000).to_json(),
json!(43200000000000i64)
);
let json_val = Value::Json(json!({"key": "value"}));
assert_eq!(json_val.to_json(), json!({"key": "value"}));
}
#[test]
fn test_value_display() {
assert_eq!(format!("{}", Value::TinyInt(42)), "42");
assert_eq!(format!("{}", Value::SmallInt(1000)), "1000");
assert_eq!(format!("{}", Value::Integer(100000)), "100000");
assert_eq!(format!("{}", Value::Real(3.14)), "3.14");
assert_eq!(format!("{}", Value::Decimal(12345, 2)), "123.45");
assert_eq!(
format!(
"{}",
Value::Uuid([
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
0x32, 0x10
])
),
"01234567-89ab-cdef-fedc-ba9876543210"
);
assert_eq!(format!("{}", Value::Date(19000)), "DATE(19000)");
assert_eq!(
format!("{}", Value::Time(43200_000_000_000)),
"TIME(43200000000000)"
);
}
#[test]
fn test_null_comparison_with_all_types() {
assert_eq!(
Value::Null.compare(&Value::TinyInt(0)),
Some(std::cmp::Ordering::Less)
);
assert_eq!(
Value::Null.compare(&Value::Real(0.0)),
Some(std::cmp::Ordering::Less)
);
assert_eq!(
Value::Null.compare(&Value::Uuid([0; 16])),
Some(std::cmp::Ordering::Less)
);
assert_eq!(
Value::Null.compare(&Value::Null),
Some(std::cmp::Ordering::Equal)
);
}
#[test]
fn test_value_equality() {
assert_eq!(Value::Integer(42), Value::Integer(42));
assert_ne!(Value::Integer(42), Value::Integer(43));
assert_ne!(Value::Integer(42), Value::BigInt(42));
assert_eq!(Value::Real(3.14), Value::Real(3.14));
assert_eq!(Value::Real(f64::NAN), Value::Real(f64::NAN)); }
#[test]
#[should_panic(expected = "JSON values cannot be used in primary keys")]
fn test_json_cannot_be_encoded_as_key() {
let values = vec![Value::Json(serde_json::json!({"key": "value"}))];
encode_key(&values);
}
#[test]
fn test_all_integer_types_distinct() {
let tiny = Value::TinyInt(42);
let small = Value::SmallInt(42);
let int = Value::Integer(42);
let big = Value::BigInt(42);
assert_eq!(tiny.compare(&small), None);
assert_eq!(tiny.compare(&int), None);
assert_eq!(tiny.compare(&big), None);
assert_eq!(small.compare(&int), None);
assert_eq!(small.compare(&big), None);
assert_eq!(int.compare(&big), None);
}