use std::env; use std::fs; use std::path::PathBuf; use tempfile::TempDir; use chrono::{NaiveDateTime, Datelike, Timelike}; use livestream_archiver::LivestreamArchiver; #[tokio::test] async fn test_livestream_archiver_creation() { let temp_output = TempDir::new().unwrap(); // Test that we can create a new archiver let archiver = LivestreamArchiver::new(temp_output.path().to_path_buf()); assert_eq!(archiver.get_output_path(), temp_output.path()); } #[tokio::test] async fn test_date_extraction_from_filename() { let temp_output = TempDir::new().unwrap(); let archiver = LivestreamArchiver::new(temp_output.path().to_path_buf()); // Test valid filename let result = archiver.extract_date_from_filename("2024-12-25_14-30-45.mp4").await; assert!(result.is_ok()); let date = result.unwrap(); assert_eq!(date.year(), 2024); assert_eq!(date.month(), 12); assert_eq!(date.day(), 25); assert_eq!(date.hour(), 14); assert_eq!(date.minute(), 30); assert_eq!(date.second(), 45); // Test invalid filename let result = archiver.extract_date_from_filename("invalid-filename.mp4").await; assert!(result.is_err()); // Test non-mp4 file let result = archiver.extract_date_from_filename("2024-12-25_14-30-45.avi").await; assert!(result.is_err()); } #[tokio::test] async fn test_file_already_processed_detection() { let temp_output = TempDir::new().unwrap(); // Set up environment variables for program names env::set_var("DIVINE_WORSHIP_NAME", "Test Divine Worship"); env::set_var("AFTERNOON_PROGRAM_NAME", "Test Afternoon Program"); let archiver = LivestreamArchiver::new(temp_output.path().to_path_buf()); let test_date = NaiveDateTime::parse_from_str("2024-12-25_14-30-45", "%Y-%m-%d_%H-%M-%S").unwrap(); // Initially no files should exist assert!(!archiver.check_if_file_already_processed("2024-12-25_14-30-45.mp4", &test_date)); // Create the expected output directory structure let year_dir = temp_output.path().join("2024"); let month_dir = year_dir.join("12-December"); fs::create_dir_all(&month_dir).unwrap(); // Create a divine worship file let divine_worship_file = month_dir.join("Test Divine Worship (December 25 2024).mp4"); fs::write(&divine_worship_file, "test content").unwrap(); // Now it should detect the file as processed assert!(archiver.check_if_file_already_processed("2024-12-25_14-30-45.mp4", &test_date)); // Clean up environment variables env::remove_var("DIVINE_WORSHIP_NAME"); env::remove_var("AFTERNOON_PROGRAM_NAME"); } #[tokio::test] async fn test_environment_variable_configuration() { // Test with custom environment variables env::set_var("DIVINE_WORSHIP_NAME", "Custom Divine Service"); env::set_var("AFTERNOON_PROGRAM_NAME", "Custom Afternoon Show"); env::set_var("SHOW_TITLE", "Custom Livestreams"); let temp_output = TempDir::new().unwrap(); let archiver = LivestreamArchiver::new(temp_output.path().to_path_buf()); // These are internal fields, so we test them indirectly through the file processing logic let test_date = NaiveDateTime::parse_from_str("2024-12-25_14-30-45", "%Y-%m-%d_%H-%M-%S").unwrap(); // The archiver should use the custom names when checking for existing files assert!(!archiver.check_if_file_already_processed("test.mp4", &test_date)); // Create expected directory structure let year_dir = temp_output.path().join("2024"); let month_dir = year_dir.join("12-December"); fs::create_dir_all(&month_dir).unwrap(); // Create file with custom name let custom_file = month_dir.join("Custom Divine Service (December 25 2024).mp4"); fs::write(&custom_file, "test content").unwrap(); // Should now detect as processed assert!(archiver.check_if_file_already_processed("test.mp4", &test_date)); // Clean up env::remove_var("DIVINE_WORSHIP_NAME"); env::remove_var("AFTERNOON_PROGRAM_NAME"); env::remove_var("SHOW_TITLE"); } #[tokio::test] async fn test_stability_tracking_integration() { let temp_output = TempDir::new().unwrap(); let archiver = LivestreamArchiver::new(temp_output.path().to_path_buf()); let temp_input = TempDir::new().unwrap(); let test_file = temp_input.path().join("2024-12-25_14-30-45.mp4"); // Create initial file fs::write(&test_file, "initial content").unwrap(); // Test that stability tracking starts let result = archiver.on_file_event(&test_file); assert!(result.is_ok()); assert!(!result.unwrap(), "New file should not be immediately stable"); // File should be tracked let tracked_files = archiver.get_tracked_files(); assert_eq!(tracked_files.len(), 1); assert_eq!(tracked_files[0], test_file); // Remove tracking archiver.remove_file_tracker(&test_file); assert_eq!(archiver.get_tracked_files().len(), 0); } #[tokio::test] async fn test_directory_structure_creation() { let temp_output = TempDir::new().unwrap(); // Test date parsing and directory structure let test_cases = vec![ ("2024-01-15_10-30-00.mp4", "2024", "01-January"), ("2024-12-31_23-59-59.mp4", "2024", "12-December"), ("2023-07-04_12-00-00.mp4", "2023", "07-July"), ]; for (filename, expected_year, expected_month) in test_cases { let archiver = LivestreamArchiver::new(temp_output.path().to_path_buf()); let date = archiver.extract_date_from_filename(filename).await.unwrap(); // The directory structure should match what the archiver expects let year_dir = temp_output.path().join(expected_year); let month_dir = year_dir.join(expected_month); // Create the directory structure as the archiver would fs::create_dir_all(&month_dir).unwrap(); // Verify structure exists assert!(year_dir.exists()); assert!(month_dir.exists()); // Test file detection logic assert!(!archiver.check_if_file_already_processed(filename, &date)); } } // Helper function to create mock video files for testing fn create_mock_mp4_file(path: &PathBuf, size_mb: usize) -> std::io::Result<()> { let content = vec![0u8; size_mb * 1024 * 1024]; // Create file of specified size in MB fs::write(path, content) }