sorting-race 0.2.0

Terminal-based sorting algorithm race visualization tool with real-time metrics
Documentation
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};

#[cfg(test)]
mod multi_session_tests {
    use super::*;
    
    /// Integration test for multi-session capability
    /// 
    /// From quickstart.md scenarios 9-10:
    /// 9. Test Multi-Session Capability
    /// 10. Verify session statistics and history tracking
    #[test]
    fn test_multi_session_capability() {
        // Test running multiple sorting races in single execution
        
        // TODO: Uncomment when interactive system is implemented
        // let mut interactive_app = InteractiveApplication::new();
        // 
        // // Session 1: Array size 50, Shuffled distribution
        // interactive_app.set_array_size_interactive(50);
        // interactive_app.set_distribution_interactive(DistributionType::Shuffled);
        // interactive_app.set_fairness_mode_interactive(FairnessMode::Walltime);
        // 
        // // Start first race
        // let space_key = KeyEvent {
        //     code: KeyCode::Char(' '),
        //     modifiers: KeyModifiers::NONE,
        //     kind: crossterm::event::KeyEventKind::Press,
        //     state: crossterm::event::KeyEventState::NONE,
        // };
        // interactive_app.handle_key_event(space_key);
        // assert_eq!(interactive_app.get_current_mode(), ApplicationMode::Racing);
        // 
        // // Simulate race completion
        // interactive_app.simulate_race_completion();
        // assert_eq!(interactive_app.get_current_mode(), ApplicationMode::Complete);
        // 
        // // Verify first race in history
        // let session_state = interactive_app.get_session_state();
        // assert_eq!(session_state.total_races_run, 1);
        // assert_eq!(session_state.run_history.len(), 1);
        // assert_eq!(session_state.run_history[0].array_size, 50);
        // assert_eq!(session_state.run_history[0].distribution, DistributionType::Shuffled);
        // 
        // // Session 2: Different parameters (array size 100, Reversed)
        // let k_key = KeyEvent {
        //     code: KeyCode::Char('k'),
        //     modifiers: KeyModifiers::NONE,
        //     kind: crossterm::event::KeyEventKind::Press,
        //     state: crossterm::event::KeyEventState::NONE,
        // };
        // interactive_app.handle_key_event(k_key); // Return to configuration mode
        // assert_eq!(interactive_app.get_current_mode(), ApplicationMode::Configuration);
        // 
        // // Change configuration for second race
        // interactive_app.set_array_size_interactive(100);
        // interactive_app.set_distribution_interactive(DistributionType::Reversed);
        // interactive_app.set_fairness_mode_interactive(FairnessMode::Comparison);
        // interactive_app.set_budget_parameter(16);
        // 
        // // Start second race
        // interactive_app.handle_key_event(space_key);
        // assert_eq!(interactive_app.get_current_mode(), ApplicationMode::Racing);
        // 
        // // Simulate second race completion
        // interactive_app.simulate_race_completion();
        // assert_eq!(interactive_app.get_current_mode(), ApplicationMode::Complete);
        // 
        // // Verify session statistics updated
        // let updated_session = interactive_app.get_session_state();
        // assert_eq!(updated_session.total_races_run, 2);
        // assert_eq!(updated_session.run_history.len(), 2);
        // 
        // // Verify second race details
        // let second_race = &updated_session.run_history[1];
        // assert_eq!(second_race.array_size, 100);
        // assert_eq!(second_race.distribution, DistributionType::Reversed);
        // assert_eq!(second_race.fairness_mode, FairnessMode::Comparison);
        // 
        // // Configuration should show updated values for potential third race
        // let current_config = interactive_app.get_current_config();
        // assert_eq!(current_config.array_size, 100);
        // assert_eq!(current_config.distribution, DistributionType::Reversed);
        // assert_eq!(current_config.budget, Some(16));
        
        // For TDD: This test must fail until implementation exists
        panic!("InteractiveApplication and multi-session support not yet implemented - this test should fail until T040-T042 are complete");
    }
    
    #[test]
    fn test_session_history_tracking() {
        // Test that race results are properly tracked in session history
        
        // TODO: Uncomment when interactive system is implemented
        // let mut interactive_app = InteractiveApplication::new();
        // 
        // // Initial session should be empty
        // let initial_session = interactive_app.get_session_state();
        // assert_eq!(initial_session.total_races_run, 0);
        // assert!(initial_session.run_history.is_empty());
        // assert!(initial_session.session_start_time.elapsed().as_secs() < 1); // Recently started
        // 
        // // Run a race with specific configuration
        // interactive_app.configure_and_run_race(RaceConfig {
        //     array_size: 200,
        //     distribution: DistributionType::FewUnique,
        //     fairness_mode: FairnessMode::Weighted,
        //     alpha: Some(2.0),
        //     beta: Some(0.5),
        //     budget: None,
        //     learning_rate: None,
        // });
        // 
        // // Verify race result added to history
        // let session_after_race = interactive_app.get_session_state();
        // assert_eq!(session_after_race.total_races_run, 1);
        // assert_eq!(session_after_race.run_history.len(), 1);
        // 
        // let race_result = &session_after_race.run_history[0];
        // assert_eq!(race_result.array_size, 200);
        // assert_eq!(race_result.distribution, DistributionType::FewUnique);
        // assert_eq!(race_result.fairness_mode, FairnessMode::Weighted);
        // assert!(race_result.completion_times.len() >= 1); // At least one algorithm completed
        // assert!(race_result.memory_usage.len() >= 1); // Memory metrics recorded
        // assert!(race_result.winner.is_some()); // Winner determined
        
        // For TDD: This test must fail until implementation exists
        panic!("InteractiveApplication and session history not yet implemented - this test should fail until T025 and T042 are complete");
    }
    
    #[test]
    fn test_configuration_persistence_between_races() {
        // Test that configuration persists between races within the same session
        
        // TODO: Uncomment when interactive system is implemented
        // let mut interactive_app = InteractiveApplication::new();
        // 
        // // Set specific configuration
        // let initial_config = ConfigurationState {
        //     array_size: 500,
        //     distribution: DistributionType::NearlySorted,
        //     fairness_mode: FairnessMode::Adaptive,
        //     budget: None,
        //     alpha: None,
        //     beta: None,
        //     learning_rate: Some(0.8),
        // };
        // interactive_app.set_configuration(initial_config.clone());
        // 
        // // Run first race
        // interactive_app.start_race();
        // interactive_app.simulate_race_completion();
        // 
        // // Configuration should be preserved after race completion
        // let config_after_first = interactive_app.get_current_config();
        // assert_eq!(config_after_first.array_size, initial_config.array_size);
        // assert_eq!(config_after_first.distribution, initial_config.distribution);
        // assert_eq!(config_after_first.fairness_mode, initial_config.fairness_mode);
        // assert_eq!(config_after_first.learning_rate, initial_config.learning_rate);
        // 
        // // Return to configuration mode and verify config is still there
        // interactive_app.return_to_configuration();
        // let config_in_config_mode = interactive_app.get_current_config();
        // assert_eq!(config_in_config_mode, config_after_first);
        // 
        // // Make a small change and run second race
        // interactive_app.set_array_size_interactive(1000);
        // interactive_app.start_race();
        // interactive_app.simulate_race_completion();
        // 
        // // Updated configuration should persist
        // let final_config = interactive_app.get_current_config();
        // assert_eq!(final_config.array_size, 1000); // Changed
        // assert_eq!(final_config.distribution, initial_config.distribution); // Unchanged
        // assert_eq!(final_config.fairness_mode, initial_config.fairness_mode); // Unchanged
        
        // For TDD: This test must fail until implementation exists
        panic!("InteractiveApplication and configuration persistence not yet implemented - this test should fail until T023 and T041 are complete");
    }
    
    #[test]
    fn test_session_statistics_accuracy() {
        // Test that session statistics are accurate across multiple races
        
        // TODO: Uncomment when interactive system is implemented
        // let mut interactive_app = InteractiveApplication::new();
        // let session_start = std::time::Instant::now();
        // 
        // // Run 3 races with different outcomes
        // let race_configs = vec![
        //     (50, DistributionType::Shuffled, FairnessMode::Walltime),
        //     (100, DistributionType::Reversed, FairnessMode::Comparison),
        //     (200, DistributionType::FewUnique, FairnessMode::Weighted),
        // ];
        // 
        // for (i, (size, dist, fairness)) in race_configs.iter().enumerate() {
        //     interactive_app.set_array_size_interactive(*size);
        //     interactive_app.set_distribution_interactive(*dist);
        //     interactive_app.set_fairness_mode_interactive(*fairness);
        //     
        //     interactive_app.start_race();
        //     interactive_app.simulate_race_completion();
        //     
        //     // Check statistics after each race
        //     let session_state = interactive_app.get_session_state();
        //     assert_eq!(session_state.total_races_run, i + 1);
        //     assert_eq!(session_state.run_history.len(), i + 1);
        // }
        // 
        // // Final verification of session statistics
        // let final_session = interactive_app.get_session_state();
        // assert_eq!(final_session.total_races_run, 3);
        // assert_eq!(final_session.run_history.len(), 3);
        // 
        // // Session duration should be reasonable
        // let session_duration = final_session.session_start_time.elapsed();
        // assert!(session_duration >= session_start.elapsed());
        // assert!(session_duration.as_secs() < 60); // Should complete quickly in test
        // 
        // // Verify each race result is distinct
        // for i in 0..3 {
        //     let race = &final_session.run_history[i];
        //     let expected = &race_configs[i];
        //     assert_eq!(race.array_size, expected.0);
        //     assert_eq!(race.distribution, expected.1);
        //     assert_eq!(race.fairness_mode, expected.2);
        // }
        
        // For TDD: This test must fail until implementation exists
        panic!("InteractiveApplication and session statistics not yet implemented - this test should fail until T025 and T042 are complete");
    }
    
    #[test]
    fn test_memory_cleanup_between_sessions() {
        // Test that memory is properly cleaned up between race sessions
        
        // TODO: Uncomment when interactive system is implemented
        // let mut interactive_app = InteractiveApplication::new();
        // 
        // // Run first race
        // interactive_app.set_array_size_interactive(100);
        // interactive_app.start_race();
        // interactive_app.simulate_race_completion();
        // 
        // // Verify memory metrics exist after first race
        // let memory_after_first = interactive_app.get_memory_metrics();
        // assert!(!memory_after_first.is_empty());
        // assert!(memory_after_first.iter().any(|m| m.current_usage_bytes > 0));
        // 
        // // Return to configuration mode (should trigger cleanup)
        // interactive_app.return_to_configuration();
        // 
        // // Memory metrics should be cleared
        // let memory_after_cleanup = interactive_app.get_memory_metrics();
        // assert!(memory_after_cleanup.is_empty() || 
        //         memory_after_cleanup.iter().all(|m| m.current_usage_bytes == 0));
        // 
        // // Run second race
        // interactive_app.set_array_size_interactive(200);
        // interactive_app.start_race();
        // 
        // // New memory tracking should start fresh
        // let memory_second_race = interactive_app.get_memory_metrics();
        // assert!(!memory_second_race.is_empty());
        // // Memory usage should be independent of previous race
        // for metric in memory_second_race {
        //     assert!(metric.current_usage_bytes >= 0);
        //     assert!(metric.peak_usage_bytes >= metric.current_usage_bytes);
        // }
        
        // For TDD: This test must fail until implementation exists
        panic!("InteractiveApplication and memory cleanup not yet implemented - this test should fail until T027 and T041 are complete");
    }
}