#[cfg(test)]
mod tests {
use crate::price_level::entry::OrderBookEntry;
use crate::price_level::level::PriceLevel;
use crate::utils::{Price, Quantity, TimestampMs};
use crate::{Hash32, Id, OrderType, Side, TimeInForce};
use std::str::FromStr;
use std::sync::Arc;
use tracing::info;
#[test]
fn test_display() {
let level = Arc::new(PriceLevel::new(1000));
let entry = OrderBookEntry::new(level.clone(), 5);
let display_str = entry.to_string();
info!("Display string: {}", display_str);
assert!(display_str.starts_with("OrderBookEntry:"));
assert!(display_str.contains("price=1000"));
assert!(display_str.contains("index=5"));
}
#[test]
fn test_from_str() {
let input = "OrderBookEntry:price=1000;index=5";
let entry = OrderBookEntry::from_str(input).unwrap();
assert_eq!(entry.price(), 1000);
assert_eq!(entry.index, 5);
}
#[test]
fn test_roundtrip_display_parse() {
let level = Arc::new(PriceLevel::new(1000));
let original = OrderBookEntry::new(level.clone(), 5);
let string_rep = original.to_string();
let parsed = OrderBookEntry::from_str(&string_rep).unwrap();
assert_eq!(original.price(), parsed.price());
assert_eq!(original.index, parsed.index);
}
#[test]
fn test_serialization() {
use serde_json;
let level = Arc::new(PriceLevel::new(1000));
let entry = OrderBookEntry::new(level.clone(), 5);
let serialized = serde_json::to_string(&entry).unwrap();
info!("Serialized: {}", serialized);
assert!(serialized.contains("\"price\":1000"));
assert!(serialized.contains("\"index\":5"));
}
#[test]
fn test_deserialization() {
use serde_json;
let json = r#"{"price":1000,"index":5}"#;
let entry: OrderBookEntry = serde_json::from_str(json).unwrap();
assert_eq!(entry.price(), 1000);
assert_eq!(entry.index, 5);
}
#[test]
fn test_order_book_entry_json_serialization() {
let level = Arc::new(PriceLevel::new(10000));
let entry = OrderBookEntry::new(level, 5);
let json = serde_json::to_string(&entry).unwrap();
assert!(json.contains("\"price\":10000"));
assert!(json.contains("\"index\":5"));
assert!(json.contains("\"visible_quantity\":0"));
assert!(json.contains("\"total_quantity\":0"));
}
#[test]
fn test_order_book_entry_wrapper_struct() {
#[derive(serde::Deserialize)]
struct Wrapper {
price: u64,
index: usize,
}
let json = r#"{"price":10000,"index":5}"#;
let wrapper: Wrapper = serde_json::from_str(json).unwrap();
assert_eq!(wrapper.price, 10000);
assert_eq!(wrapper.index, 5);
}
#[test]
fn test_order_book_entry_equality_hash() {
let level1 = Arc::new(PriceLevel::new(1000));
let level2 = Arc::new(PriceLevel::new(1000));
let entry1 = OrderBookEntry::new(level1.clone(), 1);
let entry2 = OrderBookEntry::new(level2.clone(), 2);
assert_eq!(entry1, entry2);
let mut set = std::collections::HashSet::new();
set.insert(entry1.price());
assert!(set.contains(&entry2.price()));
}
#[test]
fn test_order_book_entry_serialization() {
let level = Arc::new(PriceLevel::new(1000));
let entry = OrderBookEntry::new(level.clone(), 5);
let order = OrderType::Standard {
id: Id::from_u64(1),
price: Price::new(1000),
quantity: Quantity::new(10),
side: Side::Buy,
user_id: Hash32::zero(),
timestamp: TimestampMs::new(1616823000000),
time_in_force: TimeInForce::Gtc,
extra_fields: (),
};
level.add_order(order);
let json = serde_json::to_string(&entry).unwrap();
assert!(json.contains("\"price\":1000"));
assert!(json.contains("\"visible_quantity\":10"));
assert!(json.contains("\"total_quantity\":10"));
assert!(json.contains("\"index\":5"));
}
#[test]
fn test_order_book_entry_deserialization() {
let json = r#"{"price":1500,"index":10,"visible_quantity":50,"total_quantity":150}"#;
let entry: OrderBookEntry = serde_json::from_str(json).unwrap();
assert_eq!(entry.price(), 1500);
assert_eq!(entry.index, 10);
}
#[test]
fn test_order_book_entry_from_str_with_invalid_input() {
let invalid_input = "NotAnOrderBookEntry:price=1000;index=5";
let result = OrderBookEntry::from_str(invalid_input);
assert!(result.is_err());
let missing_index = "OrderBookEntry:price=1000";
let result = OrderBookEntry::from_str(missing_index);
assert!(result.is_err());
let invalid_price = "OrderBookEntry:price=invalid;index=5";
let result = OrderBookEntry::from_str(invalid_price);
assert!(result.is_err());
let invalid_index = "OrderBookEntry:price=1000;index=invalid";
let result = OrderBookEntry::from_str(invalid_index);
assert!(result.is_err());
}
}
#[cfg(test)]
mod tests_order_book_entry {
use crate::orders::Hash32;
use crate::price_level::entry::OrderBookEntry;
use crate::price_level::level::PriceLevel;
use crate::utils::{Price, Quantity, TimestampMs};
use std::cmp::Ordering;
use std::sync::Arc;
fn create_test_entry(price: u128, index: usize) -> OrderBookEntry {
let level = Arc::new(PriceLevel::new(price));
OrderBookEntry::new(level, index)
}
#[test]
fn test_order_count() {
let level1 = Arc::new(PriceLevel::new(1000));
let entry1 = OrderBookEntry::new(level1.clone(), 5);
assert_eq!(entry1.order_count(), 0);
let order_type = crate::orders::OrderType::Standard {
id: crate::orders::Id::from_u64(1),
price: Price::new(1000),
quantity: Quantity::new(10),
side: crate::orders::Side::Buy,
user_id: Hash32::zero(),
timestamp: TimestampMs::new(1616823000000),
time_in_force: crate::orders::TimeInForce::Gtc,
extra_fields: (),
};
level1.add_order(order_type);
assert_eq!(entry1.order_count(), 1);
let order_type2 = crate::orders::OrderType::Standard {
id: crate::orders::Id::from_u64(2),
price: Price::new(1000),
quantity: Quantity::new(20),
side: crate::orders::Side::Buy,
user_id: Hash32::zero(),
timestamp: TimestampMs::new(1616823000001),
time_in_force: crate::orders::TimeInForce::Gtc,
extra_fields: (),
};
level1.add_order(order_type2);
assert_eq!(entry1.order_count(), 2);
}
#[test]
fn test_partial_eq() {
let entry1 = create_test_entry(1000, 5);
let entry2 = create_test_entry(1000, 10);
assert_eq!(entry1, entry2);
let entry3 = create_test_entry(2000, 5);
assert_ne!(entry1, entry3);
}
#[test]
fn test_eq() {
let entry1 = create_test_entry(1000, 5);
let entry2 = create_test_entry(1000, 10);
let mut entries = std::collections::HashSet::new();
entries.insert(entry1.price());
entries.insert(entry2.price());
assert_eq!(entries.len(), 1);
}
#[test]
fn test_partial_ord() {
let entry1 = create_test_entry(1000, 5);
let entry2 = create_test_entry(2000, 10);
assert!(entry1.partial_cmp(&entry2) == Some(Ordering::Less));
assert!(entry2.partial_cmp(&entry1) == Some(Ordering::Greater));
assert!(entry1.partial_cmp(&entry1) == Some(Ordering::Equal));
}
#[test]
fn test_ord() {
let entry1 = create_test_entry(1000, 5);
let entry2 = create_test_entry(2000, 10);
let entry3 = create_test_entry(500, 15);
assert!(entry1 < entry2);
assert!(entry2 > entry1);
assert!(entry3 < entry1);
let mut entries = [entry2, entry1, entry3];
entries.sort();
assert_eq!(entries[0].price(), 500);
assert_eq!(entries[1].price(), 1000);
assert_eq!(entries[2].price(), 2000);
}
#[test]
fn test_binary_search() {
let entries = [
create_test_entry(500, 1),
create_test_entry(1000, 2),
create_test_entry(1500, 3),
create_test_entry(2000, 4),
create_test_entry(2500, 5),
];
let search_entry = create_test_entry(1500, 100); let result = entries.binary_search(&search_entry);
assert_eq!(result, Ok(2));
let search_entry = create_test_entry(1800, 100);
let result = entries.binary_search(&search_entry);
assert_eq!(result, Err(3)); }
#[test]
fn test_price() {
let entry = create_test_entry(1234, 5);
assert_eq!(entry.price(), 1234);
}
#[test]
fn test_index() {
let entry = create_test_entry(1000, 42);
assert_eq!(entry.index, 42);
}
#[test]
fn test_quantity_methods() {
let level = Arc::new(PriceLevel::new(1000));
let entry = OrderBookEntry::new(level.clone(), 5);
assert_eq!(entry.visible_quantity(), 0);
assert!(matches!(entry.total_quantity(), Ok(0)));
let standard_order = crate::orders::OrderType::Standard {
id: crate::orders::Id::from_u64(1),
price: Price::new(1000),
quantity: Quantity::new(10),
side: crate::orders::Side::Buy,
user_id: Hash32::zero(),
timestamp: TimestampMs::new(1616823000000),
time_in_force: crate::orders::TimeInForce::Gtc,
extra_fields: (),
};
level.add_order(standard_order);
assert_eq!(entry.visible_quantity(), 10);
assert!(matches!(entry.total_quantity(), Ok(10)));
let iceberg_order = crate::orders::OrderType::IcebergOrder {
id: crate::orders::Id::from_u64(2),
price: Price::new(1000),
visible_quantity: Quantity::new(5),
hidden_quantity: Quantity::new(15),
side: crate::orders::Side::Buy,
user_id: Hash32::zero(),
timestamp: TimestampMs::new(1616823000001),
time_in_force: crate::orders::TimeInForce::Gtc,
extra_fields: (),
};
level.add_order(iceberg_order);
assert_eq!(entry.visible_quantity(), 15); assert!(matches!(entry.total_quantity(), Ok(30))); }
}
#[cfg(test)]
mod tests_order_book_entry_deserialize {
use crate::price_level::entry::OrderBookEntry;
use crate::price_level::level::PriceLevel;
use std::sync::Arc;
#[test]
fn test_deserialize_from_json_basic() {
let json = r#"{"price":1000,"index":5}"#;
let entry: OrderBookEntry = serde_json::from_str(json).unwrap();
assert_eq!(entry.price(), 1000);
assert_eq!(entry.index, 5);
assert_eq!(entry.order_count(), 0); }
#[test]
fn test_deserialize_with_extra_fields() {
let json = r#"{
"price": 1500,
"index": 10,
"visible_quantity": 100,
"total_quantity": 200,
"unknown_field": "value"
}"#;
let entry: OrderBookEntry = serde_json::from_str(json).unwrap();
assert_eq!(entry.price(), 1500);
assert_eq!(entry.index, 10);
}
#[test]
fn test_deserialize_missing_fields() {
let json_missing_price = r#"{"index": 5}"#;
let result = serde_json::from_str::<OrderBookEntry>(json_missing_price);
assert!(result.is_err());
let json_missing_index = r#"{"price": 1000}"#;
let result = serde_json::from_str::<OrderBookEntry>(json_missing_index);
assert!(result.is_err());
}
#[test]
fn test_deserialize_invalid_types() {
let json_invalid_price = r#"{"price":"invalid","index":5}"#;
let result = serde_json::from_str::<OrderBookEntry>(json_invalid_price);
assert!(result.is_err());
let json_invalid_index = r#"{"price":1000,"index":"invalid"}"#;
let result = serde_json::from_str::<OrderBookEntry>(json_invalid_index);
assert!(result.is_err());
}
#[test]
fn test_deserialize_different_formats() {
let json_int = r#"{"price":1000,"index":5}"#;
let entry: OrderBookEntry = serde_json::from_str(json_int).unwrap();
assert_eq!(entry.index, 5);
let json_large_values = r#"{"price":18446744073709551615,"index":4294967295}"#; let entry: OrderBookEntry = serde_json::from_str(json_large_values).unwrap();
assert_eq!(entry.price(), 18446744073709551615);
assert_eq!(entry.index, 4294967295);
}
#[test]
fn test_deserialize_wrapper_struct() {
#[derive(serde::Deserialize)]
struct Wrapper {
price: u128,
index: usize,
}
let json = r#"{"price":1000,"index":5}"#;
let wrapper: Wrapper = serde_json::from_str(json).unwrap();
assert_eq!(wrapper.price, 1000);
assert_eq!(wrapper.index, 5);
let level = Arc::new(PriceLevel::new(wrapper.price));
let entry = OrderBookEntry::new(level, wrapper.index);
assert_eq!(entry.price(), 1000);
assert_eq!(entry.index, 5);
}
#[test]
fn test_deserialize_from_complete_json() {
let json = r#"{
"price": 1000,
"index": 5,
"level_data": {
"visible_quantity": 10,
"hidden_quantity": 20,
"order_count": 2
}
}"#;
let entry: OrderBookEntry = serde_json::from_str(json).unwrap();
assert_eq!(entry.price(), 1000);
assert_eq!(entry.index, 5);
}
#[test]
fn test_serde_round_trip() {
let original_level = Arc::new(PriceLevel::new(1500));
let original_entry = OrderBookEntry::new(original_level, 25);
let serialized = serde_json::to_string(&original_entry).unwrap();
let deserialized: OrderBookEntry = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized.price(), original_entry.price());
assert_eq!(deserialized.index, original_entry.index);
}
}