//! # GUI Component Tests //! //! Comprehensive tests for all GUI components including initialization, //! state management, user interactions, and display functionality. #![cfg(test)] use eframe::egui; use rusty_emu::gui::components::*; use rusty_emu::gui::state::*; use std::sync::{Arc, Mutex}; /// Test utilities for GUI testing mod gui_test_utils { use super::*; use eframe::egui::{Context, Ui}; /// Create a test GUI context for component testing pub fn create_test_context() -> Context { let ctx = Context::default(); // Configure for testing ctx.set_pixels_per_point(1.0); ctx } /// Create a test UI instance for component rendering pub fn create_test_ui(ctx: &Context) -> Ui { let mut ui = Ui::new( ctx.clone(), egui::LayerId::new(egui::Order::Middle, egui::Id::new("test")), egui::Id::new("test_ui"), egui::Rect::from_min_size(egui::Pos2::ZERO, egui::Vec2::new(800.0, 600.0)), egui::Rect::from_min_size(egui::Pos2::ZERO, egui::Vec2::new(800.0, 600.0)), ); ui } /// Create a test GUI state with known values for testing pub fn create_test_gui_state() -> GuiState { let mut state = GuiState::new(); state.system_loaded = true; state.system_running = true; state.cycle_count = 12345; // Set up test memory data state.memory_state.ram_contents = vec![ [0x12, 0x34, 0x56, 0x78], [0x9A, 0xBC, 0xDE, 0xF0], [0x11, 0x22, 0x33, 0x44], [0x55, 0x66, 0x77, 0x88], ]; // Set up test register data state.register_state.accumulator = 0x0F; state.register_state.carry_flag = true; state.register_state.program_counter = 0x123; state.register_state.index_registers[0] = 0x2A; state.register_state.stack_pointer = 0x08; // Set up component states state.component_states.cpu_running = true; state.component_states.ram_running = true; state.component_states.rom_running = false; state.component_states.clock_running = true; state } /// Create a test system info pub fn create_test_system_info() -> rusty_emu::system_config::SystemInfo { rusty_emu::system_config::SystemInfo { name: "Test System".to_string(), description: "Test system for GUI testing".to_string(), component_count: 4, cpu_speed: 750_000.0, rom_size: 4096, ram_size: 1024, } } } #[cfg(test)] mod gui_components_tests { use super::*; use gui_test_utils::*; #[test] fn test_gui_components_creation() { let components = GuiComponents::new(); // Test that all components are properly initialized // Since the struct is mostly private, we test through the public interface assert!(true); // Placeholder - in real implementation, test component state } #[test] fn test_control_panel_creation() { let control_panel = ControlPanel::new(); // Test initial state assert_eq!(control_panel.start_button_text, "Start System"); assert!(!control_panel.stop_button_enabled); assert!(!control_panel.reset_button_enabled); } #[test] fn test_control_panel_start_system() { let mut control_panel = ControlPanel::new(); let mut state = GuiState::new(); control_panel.start_system(&mut state); assert!(state.system_running); assert_eq!(control_panel.start_button_text, "System Running..."); assert!(control_panel.stop_button_enabled); assert!(control_panel.reset_button_enabled); assert!(state.last_error.is_none()); } #[test] fn test_control_panel_stop_system() { let mut control_panel = ControlPanel::new(); let mut state = GuiState::new(); // First start the system control_panel.start_system(&mut state); // Then stop it control_panel.stop_system(&mut state); assert!(!state.system_running); assert_eq!(control_panel.start_button_text, "Start System"); assert!(!control_panel.stop_button_enabled); assert!(state.last_error.is_none()); } #[test] fn test_control_panel_reset_system() { let mut control_panel = ControlPanel::new(); let mut state = GuiState::new(); // First start the system control_panel.start_system(&mut state); state.cycle_count = 1000; // Then reset it control_panel.reset_system(&mut state); assert!(!state.system_running); assert_eq!(state.cycle_count, 0); assert_eq!(control_panel.start_button_text, "Start System"); assert!(!control_panel.stop_button_enabled); assert!(!control_panel.reset_button_enabled); assert!(state.last_error.is_none()); } #[test] fn test_memory_viewer_creation() { let memory_viewer = MemoryViewer::new(); assert!(memory_viewer.show_hex); assert_eq!(memory_viewer.bytes_per_row, 16); } #[test] fn test_memory_viewer_display_modes() { let memory_viewer = MemoryViewer::new(); let state = create_test_gui_state(); let ctx = create_test_context(); // Test hex display mode // Note: In a real implementation, we would test the actual rendering // For now, we verify the component can be created and holds state assert!(memory_viewer.show_hex); // Test that memory data is accessible assert_eq!(state.memory_state.ram_contents.len(), 4); for bank in &state.memory_state.ram_contents { assert_eq!(bank.len(), 4); } } #[test] fn test_register_viewer_creation() { let register_viewer = RegisterViewer::new(); assert_eq!(register_viewer.selected_register, 0); } #[test] fn test_register_viewer_selection() { let mut register_viewer = RegisterViewer::new(); let state = create_test_gui_state(); // Test register selection bounds register_viewer.selected_register = 15; assert_eq!(register_viewer.selected_register, 15); // Test register data access assert_eq!(state.register_state.accumulator, 0x0F); assert!(state.register_state.carry_flag); assert_eq!(state.register_state.program_counter, 0x123); assert_eq!(state.register_state.index_registers[0], 0x2A); assert_eq!(state.register_state.stack_pointer, 0x08); } #[test] fn test_rom_loader_creation() { let rom_loader = RomLoader::new(); assert!(!rom_loader.show_file_dialog); assert!(rom_loader.selected_file.is_none()); } #[test] fn test_rom_loader_file_dialog() { let mut rom_loader = RomLoader::new(); // Test opening file dialog rom_loader.show_file_dialog = true; assert!(rom_loader.show_file_dialog); // Test canceling file dialog rom_loader.show_file_dialog = false; assert!(!rom_loader.show_file_dialog); } #[test] fn test_status_bar_creation() { let status_bar = StatusBar::new(); // StatusBar is a zero-sized type, just verify it can be created assert!(true); } #[test] fn test_status_bar_state_display() { let status_bar = StatusBar::new(); let state = create_test_gui_state(); // Test that status information is accessible assert!(state.system_running); assert_eq!(state.cycle_count, 12345); assert!(state.component_states.cpu_running); assert!(state.component_states.ram_running); assert!(!state.component_states.rom_running); assert!(state.component_states.clock_running); } } #[cfg(test)] mod gui_state_tests { use super::*; use gui_test_utils::*; #[test] fn test_gui_state_creation() { let state = GuiState::new(); assert!(!state.system_loaded); assert!(!state.system_running); assert_eq!(state.cycle_count, 0); assert!(state.system_info.is_none()); assert!(state.last_error.is_none()); // Test component states assert!(!state.component_states.cpu_running); assert!(!state.component_states.ram_running); assert!(!state.component_states.rom_running); assert!(!state.component_states.clock_running); // Test memory state assert_eq!(state.memory_state.ram_contents.len(), 4); assert_eq!(state.memory_state.selected_bank, 0); assert_eq!(state.memory_state.selected_address, 0); // Test register state assert_eq!(state.register_state.accumulator, 0); assert!(!state.register_state.carry_flag); assert_eq!(state.register_state.program_counter, 0); assert_eq!(state.register_state.index_registers.iter().sum::(), 0); assert_eq!(state.register_state.stack_pointer, 0); } #[test] fn test_gui_state_error_handling() { let mut state = GuiState::new(); // Test setting error let error_msg = "Test error message".to_string(); state.set_error(error_msg.clone()); assert_eq!(state.get_error(), Some(error_msg.as_str())); // Test clearing error state.clear_error(); assert!(state.get_error().is_none()); } #[test] fn test_gui_state_system_integration() { let mut state = GuiState::new(); let test_info = create_test_system_info(); // Test system info conversion let gui_info: super::SystemInfo = test_info.into(); assert_eq!(gui_info.name, "Test System"); assert_eq!(gui_info.component_count, 4); assert_eq!(gui_info.cpu_speed, 750_000.0); } #[test] fn test_memory_state_initialization() { let state = GuiState::new(); // Verify memory banks are properly initialized assert_eq!(state.memory_state.ram_contents.len(), 4); for (bank_idx, bank) in state.memory_state.ram_contents.iter().enumerate() { assert_eq!(bank.len(), 4, "Bank {} should have 4 bytes", bank_idx); // All bytes should be initialized to 0 for (addr, &value) in bank.iter().enumerate() { assert_eq!(value, 0, "Bank {}, address {} should be 0", bank_idx, addr); } } } #[test] fn test_register_state_initialization() { let state = GuiState::new(); // Verify all registers are properly initialized assert_eq!(state.register_state.accumulator, 0); assert!(!state.register_state.carry_flag); assert_eq!(state.register_state.program_counter, 0); assert_eq!(state.register_state.stack_pointer, 0); // All index registers should be 0 assert_eq!(state.register_state.index_registers.iter().sum::(), 0); for (i, ®) in state.register_state.index_registers.iter().enumerate() { assert_eq!(reg, 0, "Index register R{} should be 0", i); } } } #[cfg(test)] mod gui_integration_tests { use super::*; use gui_test_utils::*; #[test] fn test_gui_app_creation() { use rusty_emu::gui::GuiApp; let app = GuiApp::new(&eframe::CreationContext { egui_ctx: Default::default(), integration_info: Default::default(), storage: None, build_info: Default::default(), }); // Test initial state assert!(app.system.is_none()); assert!(!app.gui_state.system_loaded); assert!(!app.gui_state.system_running); } #[test] fn test_gui_app_system_integration() { use rusty_emu::gui::GuiApp; use rusty_emu::system_config::{ConfigurableSystem, SystemFactory}; // Create a test system let factory = SystemFactory::new(); let system = Arc::new(Mutex::new( factory.create_from_json("configs/mcs4_basic.json").unwrap(), )); let mut app = GuiApp::new(&eframe::CreationContext { egui_ctx: Default::default(), integration_info: Default::default(), storage: None, build_info: Default::default(), }); // Set the system app.set_system(system); // Verify system is set assert!(app.system.is_some()); assert!(app.gui_state.system_loaded); } #[test] fn test_gui_app_system_access() { use rusty_emu::gui::GuiApp; use rusty_emu::system_config::{ConfigurableSystem, SystemFactory}; let factory = SystemFactory::new(); let system = Arc::new(Mutex::new( factory.create_from_json("configs/mcs4_basic.json").unwrap(), )); let mut app = GuiApp::new(&eframe::CreationContext { egui_ctx: Default::default(), integration_info: Default::default(), storage: None, build_info: Default::default(), }); app.set_system(system); // Test system access let retrieved_system = app.get_system(); assert!(retrieved_system.is_some()); } #[test] fn test_gui_components_integration() { let mut components = GuiComponents::new(); let mut state = create_test_gui_state(); let ctx = create_test_context(); // Test that all components can be rendered together // In a real implementation, this would test the actual rendering // For now, we verify the components exist and have valid state // Test control panel rendering (would panic if component is invalid) components.render_control_panel(&mut create_test_ui(&ctx), &mut state); // Test memory viewer rendering components.render_memory_viewer(&mut create_test_ui(&ctx), &state); // Test register viewer rendering components.render_register_viewer(&mut create_test_ui(&ctx), &state); // Test status bar rendering components.render_status_bar(&mut create_test_ui(&ctx), &state); // If we get here without panicking, the integration is working assert!(true); } }