spacedrive/core/tests/job_shutdown_test.rs
2025-10-11 13:14:01 -07:00

127 lines
3.5 KiB
Rust

//! Test for job pausing during shutdown
use sd_core::{
infra::db::entities,
infra::job::types::{JobId, JobStatus},
location::{create_location, IndexMode, LocationCreateArgs},
Core,
};
use sea_orm::ActiveModelTrait;
use std::time::Duration;
use tempfile::TempDir;
use tokio::time::sleep;
#[tokio::test]
async fn test_jobs_paused_on_shutdown() -> Result<(), Box<dyn std::error::Error>> {
// Setup test environment
let temp_dir = TempDir::new()?;
let core_dir = temp_dir.path().join("core");
tokio::fs::create_dir_all(&core_dir).await?;
let core = Core::new(core_dir).await?;
// Create library
let library = core
.libraries
.create_library("Test Shutdown Library", None, core.context.clone())
.await?;
// Create test location with many files to ensure job runs long enough
let test_location_dir = temp_dir.path().join("test_location");
tokio::fs::create_dir_all(&test_location_dir).await?;
// Create enough files to ensure indexing takes some time
for i in 0..200 {
let file_path = test_location_dir.join(format!("test_file_{}.txt", i));
tokio::fs::write(&file_path, format!("Test content {}", i)).await?;
// Create some subdirectories with files
if i % 20 == 0 {
let subdir = test_location_dir.join(format!("subdir_{}", i));
tokio::fs::create_dir_all(&subdir).await?;
for j in 0..10 {
let subfile = subdir.join(format!("subfile_{}.txt", j));
tokio::fs::write(&subfile, format!("Subcontent {} {}", i, j)).await?;
}
}
}
// Register device
let db = library.db();
let device = core.device.to_device()?;
let device_model: entities::device::ActiveModel = device.into();
let device_record = device_model.insert(db.conn()).await?;
// Create location to trigger indexing
let location_args = LocationCreateArgs {
path: test_location_dir.clone(),
name: Some("Test Location".to_string()),
index_mode: IndexMode::Deep,
};
create_location(
library.clone(),
&core.events,
location_args,
device_record.id,
)
.await?;
// Wait for indexing to start
sleep(Duration::from_millis(500)).await;
// Verify we have running jobs
let job_manager = library.jobs();
let running_jobs = job_manager.list_jobs(Some(JobStatus::Running)).await?;
assert!(
!running_jobs.is_empty(),
"Should have at least one running job"
);
let job_ids: Vec<JobId> = running_jobs.iter().map(|j| JobId(j.id)).collect();
println!("Found {} running jobs before shutdown", job_ids.len());
// Shutdown the core, which should pause all jobs
println!("Shutting down core...");
core.shutdown().await?;
// Check that jobs were paused
for job_id in &job_ids {
let job_info = job_manager.get_job_info(job_id.0).await?;
if let Some(info) = job_info {
assert_eq!(
info.status,
JobStatus::Paused,
"Job {} should be paused after shutdown",
job_id.0
);
println!("✓ Job {} was paused during shutdown", job_id.0);
}
}
Ok(())
}
#[tokio::test]
async fn test_shutdown_with_no_running_jobs() -> Result<(), Box<dyn std::error::Error>> {
// This test ensures shutdown works correctly when no jobs are running
let temp_dir = TempDir::new()?;
let core = Core::new(temp_dir.path().to_path_buf()).await?;
let library = core
.libraries
.create_library("Empty Library", None, core.context.clone())
.await?;
// Verify no running jobs
let job_manager = library.jobs();
let running_jobs = job_manager.list_jobs(Some(JobStatus::Running)).await?;
assert!(running_jobs.is_empty());
// Shutdown should complete without errors
core.shutdown().await?;
println!("✓ Shutdown completed successfully with no running jobs");
Ok(())
}