- Refactor new_listing from single file to modular structure - Add handler factory pattern for state management - Improve keyboard utilities and validations - Update database models for bid, listing, and user systems - Add new types: listing_duration, user_row_id - Remove deprecated user_id type - Update Docker configuration - Enhance test utilities and message handling
215 lines
6.8 KiB
Rust
215 lines
6.8 KiB
Rust
//! Test utilities including timestamp comparison macros
|
|
|
|
/// Assert that two timestamps are approximately equal within a given epsilon tolerance.
|
|
///
|
|
/// This macro is useful for testing timestamps that may have small variations due to
|
|
/// execution timing. The epsilon is specified as a `Duration`.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// use chrono::{Utc, Duration};
|
|
/// use crate::test_utils::assert_timestamps_approx_eq;
|
|
///
|
|
/// let now = Utc::now();
|
|
/// let nearly_now = now + Duration::milliseconds(50);
|
|
///
|
|
/// // This will pass - 50ms difference is within 100ms epsilon
|
|
/// assert_timestamps_approx_eq!(now, nearly_now, Duration::milliseconds(100));
|
|
///
|
|
/// // This will fail - 150ms difference exceeds 100ms epsilon
|
|
/// // assert_timestamps_approx_eq!(now, nearly_now, Duration::milliseconds(100));
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! assert_timestamps_approx_eq {
|
|
($left:expr, $right:expr, $epsilon:expr) => {{
|
|
let left_val = $left;
|
|
let right_val = $right;
|
|
let epsilon_val = $epsilon;
|
|
|
|
let diff = if left_val > right_val {
|
|
left_val - right_val
|
|
} else {
|
|
right_val - left_val
|
|
};
|
|
|
|
if diff > epsilon_val {
|
|
panic!(
|
|
"Timestamp assertion failed: timestamps differ by {:?}, which exceeds epsilon {:?}\n left: {:?}\n right: {:?}",
|
|
diff, epsilon_val, left_val, right_val
|
|
);
|
|
}
|
|
}};
|
|
($left:expr, $right:expr, $epsilon:expr, $($arg:tt)+) => {{
|
|
let left_val = $left;
|
|
let right_val = $right;
|
|
let epsilon_val = $epsilon;
|
|
|
|
let diff = if left_val > right_val {
|
|
left_val - right_val
|
|
} else {
|
|
right_val - left_val
|
|
};
|
|
|
|
if diff > epsilon_val {
|
|
panic!(
|
|
"Timestamp assertion failed: timestamps differ by {:?}, which exceeds epsilon {:?}\n left: {:?}\n right: {:?}\n{}",
|
|
diff, epsilon_val, left_val, right_val, format_args!($($arg)+)
|
|
);
|
|
}
|
|
}};
|
|
}
|
|
|
|
/// Assert that two timestamps are approximately equal within a default epsilon of 1 second.
|
|
///
|
|
/// This is a convenience macro for common cases where a 1-second tolerance is sufficient.
|
|
/// For more control over the epsilon, use `assert_timestamps_approx_eq!`.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// use chrono::Utc;
|
|
/// use crate::test_utils::assert_timestamps_approx_eq_default;
|
|
///
|
|
/// let now = Utc::now();
|
|
/// let nearly_now = now + chrono::Duration::milliseconds(500);
|
|
///
|
|
/// // This will pass - 500ms difference is within default 1s epsilon
|
|
/// assert_timestamps_approx_eq_default!(now, nearly_now);
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! assert_timestamps_approx_eq_default {
|
|
($left:expr, $right:expr) => {
|
|
$crate::assert_timestamps_approx_eq!($left, $right, chrono::Duration::seconds(1))
|
|
};
|
|
($left:expr, $right:expr, $($arg:tt)+) => {
|
|
$crate::assert_timestamps_approx_eq!($left, $right, chrono::Duration::seconds(1), $($arg)+)
|
|
};
|
|
}
|
|
|
|
/// Assert that the `starts_at` and `ends_at` fields of two structs are approximately equal.
|
|
///
|
|
/// This macro is specifically designed for comparing listing timestamps where small
|
|
/// variations in timing are expected. Uses a default epsilon of 1 second.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// use chrono::Utc;
|
|
/// use crate::test_utils::assert_listing_timestamps_approx_eq;
|
|
///
|
|
/// let original_listing = /* some listing */;
|
|
/// let reconstructed_listing = /* reconstructed from DB */;
|
|
///
|
|
/// // Compare both starts_at and ends_at with default 1s epsilon
|
|
/// assert_listing_timestamps_approx_eq!(
|
|
/// original_listing.base,
|
|
/// reconstructed_listing.base
|
|
/// );
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! assert_listing_timestamps_approx_eq {
|
|
($left:expr, $right:expr) => {
|
|
$crate::assert_timestamps_approx_eq_default!(
|
|
$left.starts_at,
|
|
$right.starts_at,
|
|
"starts_at timestamps don't match"
|
|
);
|
|
$crate::assert_timestamps_approx_eq_default!(
|
|
$left.ends_at,
|
|
$right.ends_at,
|
|
"ends_at timestamps don't match"
|
|
);
|
|
};
|
|
($left:expr, $right:expr, $epsilon:expr) => {
|
|
$crate::assert_timestamps_approx_eq!(
|
|
$left.starts_at,
|
|
$right.starts_at,
|
|
$epsilon,
|
|
"starts_at timestamps don't match"
|
|
);
|
|
$crate::assert_timestamps_approx_eq!(
|
|
$left.ends_at,
|
|
$right.ends_at,
|
|
$epsilon,
|
|
"ends_at timestamps don't match"
|
|
);
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use chrono::{Duration, Utc};
|
|
|
|
#[test]
|
|
fn test_assert_timestamps_approx_eq_success() {
|
|
let now = Utc::now();
|
|
let nearly_now = now + Duration::milliseconds(50);
|
|
|
|
// Should not panic - within epsilon
|
|
assert_timestamps_approx_eq!(now, nearly_now, Duration::milliseconds(100));
|
|
assert_timestamps_approx_eq!(nearly_now, now, Duration::milliseconds(100));
|
|
}
|
|
|
|
#[test]
|
|
fn test_assert_timestamps_approx_eq_exact() {
|
|
let now = Utc::now();
|
|
|
|
// Should not panic - exact match
|
|
assert_timestamps_approx_eq!(now, now, Duration::milliseconds(1));
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Timestamp assertion failed")]
|
|
fn test_assert_timestamps_approx_eq_failure() {
|
|
let now = Utc::now();
|
|
let much_later = now + Duration::seconds(2);
|
|
|
|
// Should panic - exceeds epsilon
|
|
assert_timestamps_approx_eq!(now, much_later, Duration::milliseconds(100));
|
|
}
|
|
|
|
#[test]
|
|
fn test_assert_timestamps_approx_eq_default_success() {
|
|
let now = Utc::now();
|
|
let nearly_now = now + Duration::milliseconds(500);
|
|
|
|
// Should not panic - within default 1s epsilon
|
|
assert_timestamps_approx_eq_default!(now, nearly_now);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "Timestamp assertion failed")]
|
|
fn test_assert_timestamps_approx_eq_default_failure() {
|
|
let now = Utc::now();
|
|
let much_later = now + Duration::seconds(2);
|
|
|
|
// Should panic - exceeds default 1s epsilon
|
|
assert_timestamps_approx_eq_default!(now, much_later);
|
|
}
|
|
|
|
#[test]
|
|
fn test_custom_error_message() {
|
|
let now = Utc::now();
|
|
let nearly_now = now + Duration::milliseconds(50);
|
|
|
|
// Should not panic - within epsilon, but test custom message format
|
|
assert_timestamps_approx_eq!(
|
|
now,
|
|
nearly_now,
|
|
Duration::milliseconds(100),
|
|
"Custom error message"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_negative_duration() {
|
|
let now = Utc::now();
|
|
let earlier = now - Duration::milliseconds(50);
|
|
|
|
// Should not panic - absolute difference is within epsilon
|
|
assert_timestamps_approx_eq!(now, earlier, Duration::milliseconds(100));
|
|
assert_timestamps_approx_eq!(earlier, now, Duration::milliseconds(100));
|
|
}
|
|
}
|