Move 17 library crates into crates/, CLI binary into bin/fxt, consolidate 10 test crates into testing/, split config crate from deployment config files. Root directory reduced from 38+ to ~17 directories. All Cargo.toml paths and build.rs proto refs updated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
133 lines
4.0 KiB
Rust
133 lines
4.0 KiB
Rust
//! Market Data Helper for E2E Tests
|
|
//!
|
|
//! Provides utilities to publish test market data events that can be streamed
|
|
//! through the Trading Service's `stream_market_data` endpoint.
|
|
|
|
use anyhow::Result;
|
|
use tokio::time::{interval, Duration};
|
|
use tracing::info;
|
|
|
|
/// Start a background task that publishes test market data events
|
|
///
|
|
/// This helper publishes periodic market data events to enable E2E tests
|
|
/// that depend on market data streaming. Events are published at 10 Hz (100ms intervals).
|
|
///
|
|
/// # Arguments
|
|
/// * `symbols` - List of symbols to generate market data for
|
|
/// * `duration_secs` - How long to run the generator (0 = run indefinitely)
|
|
///
|
|
/// # Returns
|
|
/// A handle that can be used to stop the generator
|
|
pub fn start_test_market_data_publisher(
|
|
symbols: Vec<String>,
|
|
duration_secs: u64,
|
|
) -> tokio::task::JoinHandle<()> {
|
|
info!(
|
|
"🎲 Starting test market data publisher for symbols: {:?}",
|
|
symbols
|
|
);
|
|
|
|
tokio::spawn(async move {
|
|
let mut tick = interval(Duration::from_millis(100)); // 10 Hz
|
|
let mut sequence = 0u64;
|
|
let start_time = tokio::time::Instant::now();
|
|
|
|
loop {
|
|
// Check if we should stop (duration_secs == 0 means run forever)
|
|
if duration_secs > 0 && start_time.elapsed().as_secs() >= duration_secs {
|
|
info!("⏱️ Test market data publisher stopped after {} seconds", duration_secs);
|
|
break;
|
|
}
|
|
|
|
tick.tick().await;
|
|
|
|
for symbol in &symbols {
|
|
let base_price = match symbol.as_str() {
|
|
"AAPL" => 150.0,
|
|
"GOOGL" => 2800.0,
|
|
"MSFT" => 300.0,
|
|
"AMZN" => 3300.0,
|
|
_ => 100.0,
|
|
};
|
|
|
|
let price = base_price + (sequence as f64 * 0.01) % 10.0;
|
|
let volume = 100.0 + (sequence as f64 * 10.0) % 1000.0;
|
|
|
|
// Note: In production, this would publish to an event bus or message queue
|
|
// For E2E tests, the Trading Service will generate synthetic market data
|
|
// when stream_market_data is called with no real data provider
|
|
|
|
// Log at DEBUG level to avoid flooding test output
|
|
tracing::debug!(
|
|
symbol = %symbol,
|
|
price = price,
|
|
volume = volume,
|
|
sequence = sequence,
|
|
"Published test market data"
|
|
);
|
|
}
|
|
|
|
sequence += 1;
|
|
}
|
|
})
|
|
}
|
|
|
|
/// Publish a single burst of market data events for testing
|
|
///
|
|
/// Useful for tests that need a specific number of market data events.
|
|
///
|
|
/// # Arguments
|
|
/// * `symbol` - Symbol to generate data for
|
|
/// * `count` - Number of events to generate
|
|
/// * `base_price` - Starting price
|
|
pub async fn publish_market_data_burst(
|
|
symbol: &str,
|
|
count: usize,
|
|
base_price: f64,
|
|
) -> Result<()> {
|
|
info!(
|
|
"📊 Publishing {} test market data events for {}",
|
|
count, symbol
|
|
);
|
|
|
|
for i in 0..count {
|
|
let price = base_price + (i as f64 * 0.01);
|
|
let volume = 100.0 + (i as f64);
|
|
|
|
tracing::debug!(
|
|
symbol = %symbol,
|
|
price = price,
|
|
volume = volume,
|
|
sequence = i,
|
|
"Published test market data burst event"
|
|
);
|
|
|
|
// In E2E tests, the Trading Service generates synthetic data
|
|
// This function mainly serves to document the expected data format
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[tokio::test]
|
|
async fn test_market_data_publisher_lifecycle() {
|
|
let handle = start_test_market_data_publisher(
|
|
vec!["TEST".to_string()],
|
|
1, // Run for 1 second
|
|
);
|
|
|
|
// Wait for publisher to finish
|
|
let _ = tokio::time::timeout(Duration::from_secs(2), handle).await;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_market_data_burst() {
|
|
let result = publish_market_data_burst("TEST", 10, 100.0).await;
|
|
assert!(result.is_ok());
|
|
}
|
|
}
|