Files
foxhunt/tli/tests/property_tests.rs
jgrusewski c0be3ca530 🔧 Major compilation fixes across entire workspace - Significant progress achieved
## Summary of Compilation Fixes

### Core Infrastructure Improvements
- **Fixed import system**: Established canonical type imports from common::types
- **Resolved syntax errors**: Fixed malformed use statements with embedded comments
- **Import consolidation**: Eliminated duplicate and conflicting type imports
- **Type visibility**: Improved public/private type access patterns

### Major Areas Fixed

#### Trading Engine (trading_engine/)
-  Fixed syntax errors in types/basic.rs with clean re-exports
-  Resolved OrderSide/Side naming conflicts
-  Fixed type_registry.rs malformed imports
-  Consolidated canonical type imports from common::types
-  Fixed broker_client.rs duplicate OrderStatus imports
- 🔄 Remaining: 41 type visibility errors (down from 286+ errors)

#### Common Types (common/)
-  Established as single source of truth for all types
-  Clean type definitions with proper visibility
-  Consistent error handling patterns

#### Data Pipeline (data/)
-  Updated imports to use canonical common::types
-  Fixed provider trait implementations
-  Resolved database integration issues

#### ML Components (ml/)
-  Fixed model interface imports
-  Updated feature extraction systems
-  Resolved training pipeline dependencies

#### Risk Management (risk/)
-  Fixed safety module imports
-  Updated VaR calculator dependencies
-  Consolidated compliance types

#### Services
-  Trading Service: Fixed repository implementations
-  Backtesting Service: Updated strategy engines
-  TLI: Fixed dashboard and UI components

#### Test Infrastructure
-  Updated integration test imports
-  Fixed performance benchmark dependencies
-  Resolved mock implementations

### Technical Achievements

#### Import System Overhaul
- Established common::types as canonical source
- Eliminated circular dependencies
- Fixed visibility modifiers (pub use vs use)
- Resolved naming conflicts (Side → OrderSide)

#### Type System Cleanup
- Consolidated duplicate type definitions
- Fixed malformed syntax (comments in use statements)
- Standardized error handling patterns
- Improved module structure

#### Configuration Management
- Enhanced config crate integration
- Fixed database configuration patterns
- Improved hot-reload mechanisms

### Error Reduction Progress
- **Before**: 371+ compilation errors across workspace
- **After**: ~202 errors remaining (46% reduction achieved)
- **Major**: Fixed critical syntax errors preventing any compilation
- **Infrastructure**: Resolved fundamental import and type system issues

### Files Modified: 347
- Core types and infrastructure
- Service implementations
- Test suites and benchmarks
- Configuration systems
- Database integrations

### Next Steps
- Complete remaining type visibility fixes in trading_engine
- Finalize import resolution in remaining modules
- Validate cross-crate dependencies
- Run comprehensive test suite

This represents a major milestone in achieving zero compilation errors across
the entire Foxhunt HFT trading system workspace. The foundational type system
and import structure has been successfully established and standardized.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 20:56:22 +02:00

784 lines
27 KiB
Rust

//! Property-based tests for TLI system
//!
//! This module provides comprehensive property-based testing using the proptest
//! framework to validate system behavior across a wide range of inputs and
//! edge cases. Property tests help ensure the system behaves correctly under
//! all possible scenarios, not just specific test cases.
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use uuid::Uuid;
use tli::client::{
ConnectionConfig, ConnectionManager, MarketDataSnapshot, OrderContext, OrderValidationConfig,
RiskManagementConfig, TradingClient, TradingClientConfig,
};
// Database imports removed - TLI is pure client
use tli::error::{TliError, TliResult};
use tli::prelude::*;
use tli::types::*;
use proptest::prelude::*;
use proptest::test_runner::TestCaseResult;
use proptest::{prop_assert, prop_assert_eq, prop_assume};
use tempfile::TempDir;
use tracing_test::traced_test;
#[cfg(test)]
mod order_validation_properties {
use super::*;
/// Property: Valid symbols should always pass validation
proptest! {
#[test]
fn prop_valid_symbols_pass_validation(
symbol in "[A-Z]{1,5}(\\.[A-Z]{1,3})?"
) {
prop_assert!(validate_symbol(&symbol).is_ok());
}
}
/// Property: Invalid symbols should always fail validation
proptest! {
#[test]
fn prop_invalid_symbols_fail_validation(
symbol in ".*[^A-Z0-9._-].*|^$|.{21,}"
) {
prop_assume!(!symbol.is_empty() || symbol.len() > 20 || symbol.chars().any(|c| !"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-".contains(c)));
prop_assert!(validate_symbol(&symbol).is_err());
}
}
/// Property: Positive quantities should pass validation
proptest! {
#[test]
fn prop_positive_quantities_valid(
quantity in 0.000001f64..1000000.0
) {
prop_assert!(validate_quantity(quantity).is_ok());
}
}
/// Property: Non-positive or invalid quantities should fail
proptest! {
#[test]
fn prop_invalid_quantities_fail(
quantity in prop::num::f64::ANY
) {
prop_assume!(quantity <= 0.0 || !quantity.is_finite());
prop_assert!(validate_quantity(quantity).is_err());
}
}
/// Property: Positive finite prices should pass validation
proptest! {
#[test]
fn prop_positive_prices_valid(
price in 0.0001f64..100000.0
) {
prop_assert!(validate_price(price).is_ok());
}
}
/// Property: Order validation should be consistent
proptest! {
#[test]
fn prop_order_validation_consistency(
symbol in "[A-Z]{1,5}",
quantity in 1.0f64..10000.0,
price in 1.0f64..1000.0,
side in prop::sample::select(vec![OrderSide::Buy, OrderSide::Sell]),
order_type in prop::sample::select(vec![OrderType::Market, OrderType::Limit, OrderType::Stop])
) {
let order = SubmitOrderRequest {
symbol: symbol.clone(),
side: side as i32,
order_type: order_type as i32,
quantity,
price: Some(price),
client_order_id: Uuid::new_v4().to_string(),
..Default::default()
};
// Basic validation should be consistent
let result1 = validate_symbol(&symbol);
let result2 = validate_symbol(&symbol);
prop_assert_eq!(result1.is_ok(), result2.is_ok());
let qty_result1 = validate_quantity(quantity);
let qty_result2 = validate_quantity(quantity);
prop_assert_eq!(qty_result1.is_ok(), qty_result2.is_ok());
// Order should have consistent fields
prop_assert_eq!(order.symbol, symbol);
prop_assert_eq!(order.quantity, quantity);
}
}
/// Property: Client order IDs should be unique when generated
proptest! {
#[test]
fn prop_unique_client_order_ids(
count in 1usize..1000
) {
let mut order_ids = std::collections::HashSet::new();
for _ in 0..count {
let order_id = Uuid::new_v4().to_string();
prop_assert!(order_ids.insert(order_id), "Duplicate order ID generated");
}
prop_assert_eq!(order_ids.len(), count);
}
}
}
#[cfg(test)]
mod timestamp_properties {
use super::*;
/// Property: Timestamp conversion should be reversible
proptest! {
#[test]
fn prop_timestamp_conversion_reversible(
timestamp_nanos in 0i64..i64::MAX/2
) {
let system_time = unix_nanos_to_system_time(timestamp_nanos);
let converted_back = system_time_to_unix_nanos(system_time);
// Allow small rounding errors (< 1 microsecond)
let diff = (converted_back - timestamp_nanos).abs();
prop_assert!(diff < 1000, "Timestamp conversion error: {} ns", diff);
}
}
/// Property: Current timestamp should always increase
proptest! {
#[test]
fn prop_current_timestamp_increases(
iterations in 1usize..100
) {
let mut last_timestamp = 0i64;
for _ in 0..iterations {
let current = current_unix_nanos();
prop_assert!(current >= last_timestamp, "Timestamp went backwards");
last_timestamp = current;
// Small delay to ensure time progression
std::thread::sleep(Duration::from_nanos(1));
}
}
}
/// Property: System time should convert to reasonable nanoseconds
proptest! {
#[test]
fn prop_system_time_reasonable_nanos(
seconds_since_epoch in 0u64..2_000_000_000u64 // ~year 2033
) {
let system_time = UNIX_EPOCH + Duration::from_secs(seconds_since_epoch);
let nanos = system_time_to_unix_nanos(system_time);
prop_assert!(nanos > 0, "Negative timestamp");
prop_assert!(nanos < i64::MAX, "Timestamp overflow");
// Should be approximately correct (within 1 second)
let expected_nanos = seconds_since_epoch as i64 * 1_000_000_000;
let diff = (nanos - expected_nanos).abs();
prop_assert!(diff < 1_000_000_000, "Timestamp conversion error too large");
}
}
}
#[cfg(test)]
mod type_conversion_properties {
use super::*;
/// Property: Order side string conversion should be reversible
proptest! {
#[test]
fn prop_order_side_conversion_reversible(
side in prop::sample::select(vec![OrderSide::Buy, OrderSide::Sell])
) {
let side_string = order_side_to_string(side);
let converted_back = string_to_order_side(&side_string);
prop_assert!(converted_back.is_ok());
prop_assert_eq!(converted_back.unwrap(), side);
}
}
/// Property: Order type string conversion should be reversible
proptest! {
#[test]
fn prop_order_type_conversion_reversible(
order_type in prop::sample::select(vec![
OrderType::Market, OrderType::Limit, OrderType::Stop, OrderType::StopLimit
])
) {
let type_string = order_type_to_string(order_type);
let converted_back = string_to_order_type(&type_string);
prop_assert!(converted_back.is_ok());
prop_assert_eq!(converted_back.unwrap(), order_type);
}
}
/// Property: Order status string conversion should be reversible
proptest! {
#[test]
fn prop_order_status_conversion_reversible(
status in prop::sample::select(vec![
OrderStatus::New, OrderStatus::PartiallyFilled, OrderStatus::Filled,
OrderStatus::Cancelled, OrderStatus::Rejected, OrderStatus::PendingCancel
])
) {
let status_string = order_status_to_string(status);
let converted_back = string_to_order_status(&status_string);
prop_assert!(converted_back.is_ok());
prop_assert_eq!(converted_back.unwrap(), status);
}
}
/// Property: Case insensitive conversions should work
proptest! {
#[test]
fn prop_case_insensitive_conversions(
side_str in "(BUY|SELL)",
case_variation in prop::sample::select(vec!["lower", "upper", "mixed"])
) {
let test_string = match case_variation {
"lower" => side_str.to_lowercase(),
"upper" => side_str.to_uppercase(),
"mixed" => {
let mut chars: Vec<char> = side_str.chars().collect();
for (i, c) in chars.iter_mut().enumerate() {
if i % 2 == 0 {
*c = c.to_ascii_lowercase();
} else {
*c = c.to_ascii_uppercase();
}
}
chars.into_iter().collect()
}
_ => side_str.to_string(),
};
let result = string_to_order_side(&test_string);
prop_assert!(result.is_ok(), "Failed to parse: {}", test_string);
}
}
}
#[cfg(test)]
mod position_calculation_properties {
use super::*;
/// Property: Position market value calculation should be correct
proptest! {
#[test]
fn prop_position_market_value_calculation(
symbol in "[A-Z]{1,5}",
quantity in -10000.0f64..10000.0,
market_price in 0.01f64..10000.0,
average_cost in 0.01f64..10000.0
) {
let position = create_proto_position(
symbol.clone(),
quantity,
market_price,
average_cost
);
prop_assert_eq!(position.symbol, symbol);
prop_assert_eq!(position.quantity, quantity);
prop_assert_eq!(position.market_price, market_price);
prop_assert_eq!(position.average_cost, average_cost);
// Market value should equal quantity * market_price
let expected_market_value = quantity * market_price;
prop_assert!((position.market_value - expected_market_value).abs() < 0.001);
// Unrealized PnL should equal (market_price - average_cost) * quantity
let expected_pnl = (market_price - average_cost) * quantity;
prop_assert!((position.unrealized_pnl - expected_pnl).abs() < 0.001);
// Realized PnL should be zero for new positions
prop_assert_eq!(position.realized_pnl, 0.0);
}
}
/// Property: Long positions should have positive quantity
proptest! {
#[test]
fn prop_long_position_properties(
symbol in "[A-Z]{1,5}",
quantity in 0.01f64..10000.0,
market_price in 0.01f64..1000.0,
average_cost in 0.01f64..1000.0
) {
let position = create_proto_position(symbol, quantity, market_price, average_cost);
prop_assert!(position.quantity > 0.0);
prop_assert!(position.market_value > 0.0);
// If market price > average cost, should have profit
if market_price > average_cost {
prop_assert!(position.unrealized_pnl > 0.0);
} else if market_price < average_cost {
prop_assert!(position.unrealized_pnl < 0.0);
} else {
prop_assert_eq!(position.unrealized_pnl, 0.0);
}
}
}
/// Property: Short positions should have negative quantity
proptest! {
#[test]
fn prop_short_position_properties(
symbol in "[A-Z]{1,5}",
quantity in -10000.0f64..-0.01,
market_price in 0.01f64..1000.0,
average_cost in 0.01f64..1000.0
) {
let position = create_proto_position(symbol, quantity, market_price, average_cost);
prop_assert!(position.quantity < 0.0);
prop_assert!(position.market_value < 0.0); // Negative for short positions
// For short positions, profit when market price < average cost
if market_price < average_cost {
prop_assert!(position.unrealized_pnl > 0.0);
} else if market_price > average_cost {
prop_assert!(position.unrealized_pnl < 0.0);
}
}
}
}
#[cfg(test)]
mod metric_creation_properties {
use super::*;
/// Property: Metrics should have consistent timestamps
proptest! {
#[test]
fn prop_metric_timestamps_consistent(
name in "[a-z_]{1,20}",
value in -1000000.0f64..1000000.0,
unit in "[a-z]{1,10}",
label_count in 0usize..10
) {
let mut labels = HashMap::new();
for i in 0..label_count {
labels.insert(format!("label_{}", i), format!("value_{}", i));
}
let before = current_unix_nanos();
let metric = create_metric(name.clone(), value, unit.clone(), labels.clone());
let after = current_unix_nanos();
prop_assert_eq!(metric.name, name);
prop_assert_eq!(metric.value, value);
prop_assert_eq!(metric.unit, unit);
prop_assert_eq!(metric.labels, labels);
// Timestamp should be within reasonable range
prop_assert!(metric.timestamp_unix_nanos >= before);
prop_assert!(metric.timestamp_unix_nanos <= after);
}
}
/// Property: Metric values should handle all finite numbers
proptest! {
#[test]
fn prop_metric_values_finite(
value in prop::num::f64::POSITIVE | prop::num::f64::NEGATIVE
) {
prop_assume!(value.is_finite());
let metric = create_metric(
"test_metric".to_string(),
value,
"units".to_string(),
HashMap::new()
);
prop_assert_eq!(metric.value, value);
prop_assert!(metric.value.is_finite());
}
}
}
#[cfg(test)]
// Database and encryption property tests removed - TLI is pure client
#[cfg(test)]
mod event_properties {
use super::*;
/// Property: Event IDs should be unique
proptest! {
#[test]
fn prop_event_ids_unique(
count in 1usize..1000
) {
let mut event_ids = std::collections::HashSet::new();
for i in 0..count {
let event = TliEvent {
event_id: Uuid::new_v4().to_string(),
event_type: EventType::MarketData,
source_service: "test_service".to_string(),
timestamp: current_unix_nanos() + i as i64,
data: serde_json::json!({"index": i}),
metadata: HashMap::new(),
};
prop_assert!(event_ids.insert(event.event_id.clone()), "Duplicate event ID");
}
prop_assert_eq!(event_ids.len(), count);
}
}
/// Property: Event timestamps should be reasonable
proptest! {
#[test]
fn prop_event_timestamps_reasonable(
event_type in prop::sample::select(vec![
EventType::MarketData, EventType::OrderUpdate, EventType::RiskAlert
]),
source_service in "[a-z_]{1,20}",
timestamp_offset in -3600i64..3600i64 // +/- 1 hour
) {
let base_timestamp = current_unix_nanos();
let event_timestamp = base_timestamp + (timestamp_offset * 1_000_000_000); // Convert to nanos
let event = TliEvent {
event_id: Uuid::new_v4().to_string(),
event_type,
source_service,
timestamp: event_timestamp,
data: serde_json::json!({}),
metadata: HashMap::new(),
};
// Timestamp should be within reasonable range
let now = current_unix_nanos();
let diff = (event.timestamp - now).abs();
prop_assert!(diff < 7200 * 1_000_000_000, "Timestamp too far from current time"); // 2 hours
}
}
/// Property: Event serialization should be reversible
proptest! {
#[test]
fn prop_event_serialization_reversible(
event_type in prop::sample::select(vec![
EventType::MarketData, EventType::OrderUpdate, EventType::RiskAlert,
EventType::SystemStatus, EventType::ConfigChange, EventType::Metrics
]),
source_service in "[a-z_]{1,20}",
symbol in "[A-Z]{1,5}",
price in 0.01f64..10000.0
) {
let event = TliEvent {
event_id: Uuid::new_v4().to_string(),
event_type,
source_service,
timestamp: current_unix_nanos(),
data: serde_json::json!({
"symbol": symbol,
"price": price
}),
metadata: HashMap::from([
("test_key".to_string(), "test_value".to_string())
]),
};
// Serialize to JSON
let serialized = serde_json::to_string(&event)?;
// Deserialize back
let deserialized: TliEvent = serde_json::from_str(&serialized)?;
prop_assert_eq!(event.event_id, deserialized.event_id);
prop_assert_eq!(event.source_service, deserialized.source_service);
prop_assert_eq!(event.timestamp, deserialized.timestamp);
prop_assert_eq!(event.data, deserialized.data);
prop_assert_eq!(event.metadata, deserialized.metadata);
Ok(()) as TliResult<()>
}
}
}
#[cfg(test)]
mod client_configuration_properties {
use super::*;
/// Property: Trading client config should validate properly
proptest! {
#[test]
fn prop_trading_config_validation(
request_timeout_ms in 100u64..30000,
max_order_size in 1.0f64..10000000.0,
min_order_size in 0.001f64..1.0,
var_confidence in 0.9f64..0.999
) {
let config = TradingClientConfig {
service_name: "test_service".to_string(),
request_timeout: Duration::from_millis(request_timeout_ms),
order_validation: OrderValidationConfig {
enable_pre_validation: true,
max_order_size,
min_order_size,
validate_symbols: true,
validate_market_hours: true,
},
risk_management: RiskManagementConfig {
enable_risk_monitoring: true,
max_position_exposure: 1000000.0,
var_confidence_level: var_confidence,
alert_thresholds: Default::default(),
enable_position_limits: true,
},
market_data: Default::default(),
monitoring: Default::default(),
event_streaming: Default::default(),
};
// Config should be internally consistent
prop_assert!(config.order_validation.max_order_size >= config.order_validation.min_order_size);
prop_assert!(config.request_timeout.as_millis() >= 100);
prop_assert!(config.risk_management.var_confidence_level >= 0.9);
prop_assert!(config.risk_management.var_confidence_level < 1.0);
}
}
/// Property: Connection config should have reasonable timeouts
proptest! {
#[test]
fn prop_connection_config_timeouts(
timeout_ms in 100u64..60000,
max_retries in 0u32..10,
retry_delay_ms in 10u64..5000
) {
let config = ConnectionConfig {
endpoint: "http://localhost:50051".to_string(),
timeout: Duration::from_millis(timeout_ms),
max_retries,
retry_delay: Duration::from_millis(retry_delay_ms),
enable_tls: false,
enable_health_check: true,
health_check_interval: Duration::from_secs(30),
pool_size: 5,
idle_timeout: Duration::from_secs(300),
..Default::default()
};
// Timeouts should be reasonable
prop_assert!(config.timeout.as_millis() >= 100);
prop_assert!(config.timeout.as_millis() <= 60000);
prop_assert!(config.retry_delay.as_millis() >= 10);
prop_assert!(config.retry_delay.as_millis() <= 5000);
prop_assert!(config.max_retries <= 10);
}
}
}
#[cfg(test)]
mod market_data_properties {
use super::*;
/// Property: Market data snapshots should have consistent bid/ask spreads
proptest! {
#[test]
fn prop_market_data_spread_consistency(
symbol in "[A-Z]{1,5}",
mid_price in 1.0f64..1000.0,
spread in 0.01f64..10.0,
volume in 1u64..1000000
) {
let bid_price = mid_price - (spread / 2.0);
let ask_price = mid_price + (spread / 2.0);
let snapshot = MarketDataSnapshot {
symbol: symbol.clone(),
last_price: Some(mid_price),
bid_price: Some(bid_price),
ask_price: Some(ask_price),
bid_size: Some(volume),
ask_size: Some(volume),
volume: Some(volume),
timestamp: std::time::Instant::now(),
};
prop_assert_eq!(snapshot.symbol, symbol);
prop_assert!(snapshot.bid_price.unwrap() < snapshot.ask_price.unwrap());
let actual_spread = snapshot.ask_price.unwrap() - snapshot.bid_price.unwrap();
prop_assert!((actual_spread - spread).abs() < 0.001);
// Last price should be within bid/ask range (approximately)
let last = snapshot.last_price.unwrap();
prop_assert!(last >= bid_price - 0.01);
prop_assert!(last <= ask_price + 0.01);
}
}
/// Property: Market data should have reasonable volumes
proptest! {
#[test]
fn prop_market_data_volume_reasonable(
bid_size in 1u64..100000,
ask_size in 1u64..100000,
volume in 0u64..10000000
) {
let snapshot = MarketDataSnapshot {
symbol: "TEST".to_string(),
last_price: Some(100.0),
bid_price: Some(99.95),
ask_price: Some(100.05),
bid_size: Some(bid_size),
ask_size: Some(ask_size),
volume: Some(volume),
timestamp: std::time::Instant::now(),
};
prop_assert!(snapshot.bid_size.unwrap() > 0);
prop_assert!(snapshot.ask_size.unwrap() > 0);
prop_assert!(snapshot.volume.unwrap() >= 0);
}
}
}
// Property test configuration and utilities
#[cfg(test)]
mod property_test_config {
use super::*;
use proptest::test_runner::{Config, TestCaseResult, TestRunner};
/// Custom property test configuration for performance-critical tests
pub fn high_performance_config() -> Config {
Config {
cases: 10000, // More test cases for critical paths
max_shrink_iters: 1000,
timeout: 30000, // 30 second timeout
..Config::default()
}
}
/// Custom property test configuration for database tests
pub fn database_config() -> Config {
Config {
cases: 1000, // Fewer cases due to I/O overhead
max_shrink_iters: 100,
timeout: 60000, // 60 second timeout for I/O
..Config::default()
}
}
/// Property test for stress testing with custom config
#[test]
fn stress_test_order_validation() {
let mut runner = TestRunner::new(high_performance_config());
runner
.run(
&("[A-Z]{1,5}", 0.01f64..1000000.0, 0.01f64..10000.0),
|(symbol, quantity, price)| {
// Validate order components
validate_symbol(&symbol)?;
validate_quantity(quantity)?;
validate_price(price)?;
Ok(())
},
)
.unwrap();
}
/// Property test for database operations with custom config
#[test]
fn stress_test_database_operations() {
// Database stress tests removed - TLI is pure client
let mut runner = TestRunner::new(database_config());
// Use runner for other non-database tests if needed
}
}
// Performance-oriented property tests
#[cfg(test)]
mod performance_properties {
use super::*;
use std::time::Instant;
/// Property: Order validation should complete within time bounds
proptest! {
#[test]
fn prop_order_validation_performance(
symbol in "[A-Z]{1,5}",
quantity in 1.0f64..1000.0,
price in 1.0f64..500.0
) {
let start = Instant::now();
let _symbol_valid = validate_symbol(&symbol);
let _quantity_valid = validate_quantity(quantity);
let _price_valid = validate_price(price);
let duration = start.elapsed();
// Should complete in under 10 microseconds
prop_assert!(duration.as_micros() < 10, "Validation too slow: {:?}", duration);
}
}
/// Property: Type conversions should be fast
proptest! {
#[test]
fn prop_type_conversion_performance(
side in prop::sample::select(vec![OrderSide::Buy, OrderSide::Sell]),
order_type in prop::sample::select(vec![OrderType::Market, OrderType::Limit])
) {
let start = Instant::now();
let side_str = order_side_to_string(side);
let _side_back = string_to_order_side(&side_str);
let type_str = order_type_to_string(order_type);
let _type_back = string_to_order_type(&type_str);
let duration = start.elapsed();
// Should complete in under 1 microsecond
prop_assert!(duration.as_nanos() < 1000, "Type conversion too slow: {:?}", duration);
}
}
/// Property: Timestamp operations should be extremely fast
#[test]
fn prop_timestamp_performance() {
let start = Instant::now();
let _timestamp = current_unix_nanos();
let system_time = unix_nanos_to_system_time(1_000_000_000);
let _converted = system_time_to_unix_nanos(system_time);
let duration = start.elapsed();
// Should complete in under 500 nanoseconds
assert!(
duration.as_nanos() < 500,
"Timestamp ops too slow: {:?}",
duration
);
}
}