Files
foxhunt/fxt/tests/agent_commands_test.rs
jgrusewski 2da5bafc0e refactor: rename tli→fxt, delete legacy scripts/RunPod/deploy artifacts
- Rename tli/ directory to fxt/, update package + binary name to "fxt"
- Replace all `use tli::` → `use fxt::` across 52 Rust files
- Update build.rs proto paths (tli/proto → fxt/proto) in 6 services
- Update Dockerfiles, CI workflows, deploy.sh for new paths
- Delete ~170 legacy shell scripts (kept 15 essential ones)
- Delete RunPod Python client (runpod/), tests (tests/runpod/)
- Delete foxhunt-deploy crate (RunPod-only deployment tool)
- Delete terraform/runpod/ (moved to Scaleway)
- Delete ML Python hyperopt scripts (replaced by Rust Argmin PSO)
- Delete .gitlab-ci.yml (using GitHub + Gitea)
- Remove foxhunt-deploy from workspace members

504 files changed, -74,355 lines of legacy code removed.
Workspace compiles clean (0 errors, 0 warnings).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:32:21 +01:00

270 lines
8.6 KiB
Rust

//! Agent Commands Integration Tests
//!
//! Test suite for `tli agent` commands including portfolio allocation.
//! Uses TDD approach with tests written before implementation.
// Suppress false-positive unused_crate_dependencies warnings
// dev-dependencies are shared across ALL test targets in the crate
// This test may not use all deps, but they are required by other integration tests
#![allow(unused_crate_dependencies)]
use fxt::commands::agent::{handle_allocate_portfolio, AllocatePortfolioArgs};
#[tokio::test]
async fn test_allocate_portfolio_valid_args() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "ml-optimized".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
// This will fail until Trading Agent Service is running
// For now, test that the function signature is correct
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
// Expected to fail with connection error when service is not running
// But should not panic or have type errors
assert!(result.is_err() || result.is_ok());
}
#[tokio::test]
async fn test_allocate_portfolio_negative_capital() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: -1000.0,
strategy: "ml-optimized".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
assert!(result.is_err());
let error = result.unwrap_err();
eprintln!("Error: {}", error);
assert!(
error.to_string().contains("positive")
|| error
.to_string()
.contains("Invalid portfolio allocation constraints")
);
}
#[tokio::test]
async fn test_allocate_portfolio_zero_capital() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 0.0,
strategy: "ml-optimized".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_allocate_portfolio_invalid_strategy() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "invalid-strategy-xyz".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
assert!(result.is_err());
let error = result.unwrap_err();
assert!(
error.to_string().contains("Unknown allocation strategy")
|| error.to_string().contains("allocation strategy")
);
}
#[tokio::test]
async fn test_allocate_portfolio_min_size_too_small() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "ml-optimized".to_string(),
max_position_size: 0.20,
min_position_size: 0.0,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
assert!(
result.is_err(),
"Expected error for min_position_size = 0.0"
);
}
#[tokio::test]
async fn test_allocate_portfolio_max_size_too_large() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "ml-optimized".to_string(),
max_position_size: 1.5,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
assert!(
result.is_err(),
"Expected error for max_position_size = 1.5"
);
}
#[tokio::test]
async fn test_allocate_portfolio_min_greater_than_max() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "ml-optimized".to_string(),
max_position_size: 0.10,
min_position_size: 0.20,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
assert!(result.is_err(), "Expected error for min > max");
}
#[tokio::test]
async fn test_allocate_portfolio_equal_weight_strategy() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "equal-weight".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
// Should parse strategy correctly (may fail with connection error)
assert!(result.is_err() || result.is_ok());
}
#[tokio::test]
async fn test_allocate_portfolio_risk_parity_strategy() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "risk-parity".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
// Should parse strategy correctly (may fail with connection error)
assert!(result.is_err() || result.is_ok());
}
#[tokio::test]
async fn test_allocate_portfolio_mean_variance_strategy() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "mean-variance".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
// Should parse strategy correctly (may fail with connection error)
assert!(result.is_err() || result.is_ok());
}
#[tokio::test]
async fn test_allocate_portfolio_kelly_strategy() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "kelly".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
// Should parse strategy correctly (may fail with connection error)
assert!(result.is_err() || result.is_ok());
}
#[tokio::test]
async fn test_allocate_portfolio_case_insensitive_strategy() {
let args = AllocatePortfolioArgs {
selection_id: "test-selection-123".to_string(),
total_capital: 100000.0,
strategy: "ML-OPTIMIZED".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let result = handle_allocate_portfolio(args, "http://localhost:50051", "mock-jwt-token").await;
// Should parse strategy correctly (may fail with connection error)
assert!(result.is_err() || result.is_ok());
}
#[test]
fn test_allocate_portfolio_args_struct() {
// Test that AllocatePortfolioArgs can be constructed
let args = AllocatePortfolioArgs {
selection_id: "test-123".to_string(),
total_capital: 100000.0,
strategy: "ml-optimized".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
assert_eq!(args.selection_id, "test-123");
assert_eq!(args.total_capital, 100000.0);
assert_eq!(args.strategy, "ml-optimized");
assert_eq!(args.max_position_size, 0.20);
assert_eq!(args.min_position_size, 0.05);
}
#[test]
fn test_allocate_portfolio_args_clone() {
// Test that AllocatePortfolioArgs implements Clone
let args = AllocatePortfolioArgs {
selection_id: "test-123".to_string(),
total_capital: 100000.0,
strategy: "ml-optimized".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let cloned = args.clone();
assert_eq!(args.selection_id, cloned.selection_id);
assert_eq!(args.total_capital, cloned.total_capital);
}
#[test]
fn test_allocate_portfolio_args_debug() {
// Test that AllocatePortfolioArgs implements Debug
let args = AllocatePortfolioArgs {
selection_id: "test-123".to_string(),
total_capital: 100000.0,
strategy: "ml-optimized".to_string(),
max_position_size: 0.20,
min_position_size: 0.05,
};
let debug_str = format!("{:?}", args);
assert!(debug_str.contains("test-123"));
assert!(debug_str.contains("100000"));
}