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>
186 lines
5.2 KiB
Rust
186 lines
5.2 KiB
Rust
//! Test Fixtures and Helpers for E2E Tests
|
|
//!
|
|
//! Provides reusable test data, helper functions, and utilities for E2E testing.
|
|
|
|
use std::collections::HashMap;
|
|
use fxt::proto::ml_training::{TrainingJobSummary, TrainingStatus};
|
|
|
|
/// Create a test training job with default values
|
|
pub fn create_test_job(
|
|
job_id: &str,
|
|
model_type: &str,
|
|
status: TrainingStatus,
|
|
) -> TrainingJobSummary {
|
|
create_test_job_with_times(
|
|
job_id,
|
|
model_type,
|
|
status,
|
|
chrono::Utc::now().timestamp(),
|
|
0,
|
|
0,
|
|
)
|
|
}
|
|
|
|
/// Create a test training job with specific timestamps
|
|
pub fn create_test_job_with_times(
|
|
job_id: &str,
|
|
model_type: &str,
|
|
status: TrainingStatus,
|
|
created_at: i64,
|
|
started_at: i64,
|
|
completed_at: i64,
|
|
) -> TrainingJobSummary {
|
|
TrainingJobSummary {
|
|
job_id: job_id.to_string(),
|
|
model_type: model_type.to_string(),
|
|
status: status as i32,
|
|
created_at,
|
|
started_at,
|
|
completed_at,
|
|
description: format!("Test {} job for {}", model_type, job_id),
|
|
final_loss: 0.123,
|
|
best_validation_score: 0.456,
|
|
tags: create_test_tags(),
|
|
}
|
|
}
|
|
|
|
/// Create standard test tags
|
|
pub fn create_test_tags() -> HashMap<String, String> {
|
|
let mut tags = HashMap::new();
|
|
tags.insert("env".to_string(), "test".to_string());
|
|
tags.insert("version".to_string(), "1.0".to_string());
|
|
tags
|
|
}
|
|
|
|
/// Create a batch of test jobs for testing list/filter operations
|
|
pub fn create_test_job_batch() -> Vec<TrainingJobSummary> {
|
|
let base_time = chrono::Utc::now().timestamp();
|
|
vec![
|
|
create_test_job_with_times(
|
|
"train_tft_es_20251022_140000",
|
|
"TFT",
|
|
TrainingStatus::Running,
|
|
base_time,
|
|
base_time + 60,
|
|
0,
|
|
),
|
|
create_test_job_with_times(
|
|
"train_dqn_nq_20251022_133000",
|
|
"DQN",
|
|
TrainingStatus::Completed,
|
|
base_time - 3600,
|
|
base_time - 3540,
|
|
base_time - 3336,
|
|
),
|
|
create_test_job_with_times(
|
|
"train_ppo_es_20251022_130000",
|
|
"PPO",
|
|
TrainingStatus::Completed,
|
|
base_time - 7200,
|
|
base_time - 7140,
|
|
base_time - 7133,
|
|
),
|
|
create_test_job_with_times(
|
|
"train_mamba2_6e_20251022_120000",
|
|
"MAMBA_2",
|
|
TrainingStatus::Failed,
|
|
base_time - 14400,
|
|
base_time - 14340,
|
|
base_time - 14200,
|
|
),
|
|
create_test_job_with_times(
|
|
"train_tft_zn_20251022_110000",
|
|
"TFT",
|
|
TrainingStatus::Stopped,
|
|
base_time - 18000,
|
|
base_time - 17940,
|
|
base_time - 17800,
|
|
),
|
|
]
|
|
}
|
|
|
|
/// Helper function to extract job IDs from job list
|
|
pub fn extract_job_ids(jobs: &[TrainingJobSummary]) -> Vec<String> {
|
|
jobs.iter().map(|j| j.job_id.clone()).collect()
|
|
}
|
|
|
|
/// Helper function to filter jobs by status
|
|
pub fn filter_by_status(jobs: &[TrainingJobSummary], status: TrainingStatus) -> Vec<TrainingJobSummary> {
|
|
jobs.iter()
|
|
.filter(|j| j.status == status as i32)
|
|
.cloned()
|
|
.collect()
|
|
}
|
|
|
|
/// Helper function to filter jobs by model type
|
|
pub fn filter_by_model(jobs: &[TrainingJobSummary], model_type: &str) -> Vec<TrainingJobSummary> {
|
|
jobs.iter()
|
|
.filter(|j| j.model_type == model_type)
|
|
.cloned()
|
|
.collect()
|
|
}
|
|
|
|
/// Validate job structure
|
|
pub fn validate_job_structure(job: &TrainingJobSummary) -> bool {
|
|
!job.job_id.is_empty()
|
|
&& !job.model_type.is_empty()
|
|
&& job.status >= 0
|
|
&& job.created_at > 0
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_create_test_job() {
|
|
let job = create_test_job("test_1", "TFT", TrainingStatus::Pending);
|
|
assert_eq!(job.job_id, "test_1");
|
|
assert_eq!(job.model_type, "TFT");
|
|
assert_eq!(job.status, TrainingStatus::Pending as i32);
|
|
}
|
|
|
|
#[test]
|
|
fn test_create_test_job_batch() {
|
|
let jobs = create_test_job_batch();
|
|
assert_eq!(jobs.len(), 5);
|
|
assert_eq!(jobs[0].model_type, "TFT");
|
|
assert_eq!(jobs[1].model_type, "DQN");
|
|
assert_eq!(jobs[2].model_type, "PPO");
|
|
}
|
|
|
|
#[test]
|
|
fn test_filter_by_status() {
|
|
let jobs = create_test_job_batch();
|
|
let completed = filter_by_status(&jobs, TrainingStatus::Completed);
|
|
assert_eq!(completed.len(), 2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_filter_by_model() {
|
|
let jobs = create_test_job_batch();
|
|
let tft_jobs = filter_by_model(&jobs, "TFT");
|
|
assert_eq!(tft_jobs.len(), 2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_validate_job_structure() {
|
|
let job = create_test_job("test_1", "TFT", TrainingStatus::Pending);
|
|
assert!(validate_job_structure(&job));
|
|
|
|
let invalid_job = TrainingJobSummary {
|
|
job_id: "".to_string(),
|
|
..job
|
|
};
|
|
assert!(!validate_job_structure(&invalid_job));
|
|
}
|
|
|
|
#[test]
|
|
fn test_extract_job_ids() {
|
|
let jobs = create_test_job_batch();
|
|
let ids = extract_job_ids(&jobs);
|
|
assert_eq!(ids.len(), 5);
|
|
assert!(ids.contains(&"train_tft_es_20251022_140000".to_string()));
|
|
}
|
|
}
|