diff --git a/crates/audit/tests/pipeline_layer_test.rs b/crates/audit/tests/pipeline_layer_test.rs index 3b28b5863..5d5608db2 100644 --- a/crates/audit/tests/pipeline_layer_test.rs +++ b/crates/audit/tests/pipeline_layer_test.rs @@ -236,12 +236,19 @@ async fn audit_pipeline_reports_empty_runtime_snapshots() { } #[tokio::test] -async fn audit_runtime_facade_stops_empty_replay_workers() { +async fn stopping_audit_replay_workers_is_a_no_op_when_there_are_none() { let registry = Arc::new(Mutex::new(AuditRegistry::new())); let replay_workers = Arc::new(RwLock::new(rustfs_targets::ReplayWorkerManager::new())); - let facade = AuditRuntimeFacade::new(registry, replay_workers); + let facade = AuditRuntimeFacade::new(registry, Arc::clone(&replay_workers)); facade.stop_replay_workers().await; + + // The stop path takes the manager's workers and hands them to the adapter, + // so an empty facade must leave it empty rather than wedge it, and a second + // call — which shutdown paths make — must stay harmless (rustfs/backlog#1836). + assert!(replay_workers.read().await.is_empty()); + facade.stop_replay_workers().await; + assert!(replay_workers.read().await.is_empty()); } #[tokio::test] diff --git a/crates/heal/tests/heal_bug_fixes_test.rs b/crates/heal/tests/heal_bug_fixes_test.rs index ba59142fd..dc5addef2 100644 --- a/crates/heal/tests/heal_bug_fixes_test.rs +++ b/crates/heal/tests/heal_bug_fixes_test.rs @@ -117,13 +117,16 @@ fn test_format_set_disk_id_from_i32_valid() { assert_eq!(result.unwrap(), "pool_0_set_1"); } +/// A wall-clock lower bound for "the timestamp was actually read from the +/// clock": 2020-01-01. `unwrap_or_default()` on a pre-epoch clock yields 0, and +/// the old versions of these tests bound the fields to `_` and so could not tell +/// that apart from a real reading (rustfs/backlog#1836). +const SANE_EPOCH_SECS: u64 = 1_577_836_800; + #[test] fn test_resume_state_timestamp_handling() { use rustfs_heal::heal::resume::ResumeState; - // Test that ResumeState creation doesn't panic even if system time is before epoch - // This is a theoretical test - in practice, system time should never be before epoch - // But we want to ensure unwrap_or_default handles edge cases let state = ResumeState::new( "test-task".to_string(), "test-type".to_string(), @@ -131,22 +134,30 @@ fn test_resume_state_timestamp_handling() { vec!["bucket1".to_string()], ); - // Verify fields are initialized (u64 is always >= 0) - // The important thing is that unwrap_or_default prevents panic - let _ = state.start_time; - let _ = state.last_update; + assert!( + state.start_time > SANE_EPOCH_SECS, + "start_time fell back to the default instead of reading the clock: {}", + state.start_time + ); + assert!( + state.last_update >= state.start_time, + "last_update {} must not predate start_time {}", + state.last_update, + state.start_time + ); } #[test] fn test_resume_checkpoint_timestamp_handling() { use rustfs_heal::heal::resume::ResumeCheckpoint; - // Test that ResumeCheckpoint creation doesn't panic let checkpoint = ResumeCheckpoint::new("test-task".to_string()); - // Verify field is initialized (u64 is always >= 0) - // The important thing is that unwrap_or_default prevents panic - let _ = checkpoint.checkpoint_time; + assert!( + checkpoint.checkpoint_time > SANE_EPOCH_SECS, + "checkpoint_time fell back to the default instead of reading the clock: {}", + checkpoint.checkpoint_time + ); } #[test]