fix(test): allow InstanceContext bucket_metadata_sys reinitialization for tests (#4638)

The OnceLock introduced in 5fbd49a80 for bucket_metadata_sys panics when
multiple test modules initialize their own ECStore against the shared
bootstrap context. Switch to Mutex<Option> so test fixtures can
reinitialize safely.

Extract shared gating test environment to gating_test_env.rs to avoid
duplicate ECStore setup across delete_objects_stat_gating_test and
put_prelookup_gating_test.

Fixes 8 test failures:
- capacity_dirty_scope_test (2 tests)
- delete_objects_stat_gating_test (3 tests)
- put_prelookup_gating_test (3 tests)
This commit is contained in:
Zhengchao An
2026-07-10 04:03:26 +08:00
committed by GitHub
parent 5e80980698
commit cefbe2ccc9
6 changed files with 135 additions and 160 deletions
+23 -8
View File
@@ -146,7 +146,12 @@ pub struct InstanceContext {
/// instance's store; holds the store handle plus the bucket→metadata
/// cache, so it is inherently per-store. Replaces the process-global
/// bucket-metadata static (whose double-init panicked process-wide).
bucket_metadata_sys: OnceLock<Arc<RwLock<BucketMetadataSys>>>,
///
/// Uses `std::sync::Mutex` instead of `OnceLock` so test fixtures that
/// share the bootstrap context can reinitialize the metadata system with
/// their own `ECStore` without panicking. Production startup still sets
/// this exactly once.
bucket_metadata_sys: std::sync::Mutex<Option<Arc<RwLock<BucketMetadataSys>>>>,
/// This instance's background-services cancellation token (Phase 5 Slice 13,
/// backlog#939).
///
@@ -186,7 +191,7 @@ impl InstanceContext {
local_disk_map: Arc::new(RwLock::new(HashMap::new())),
local_disk_id_map: Arc::new(RwLock::new(HashMap::new())),
local_disk_set_drives: Arc::new(RwLock::new(Vec::new())),
bucket_metadata_sys: OnceLock::new(),
bucket_metadata_sys: std::sync::Mutex::new(None),
background_cancel_token: OnceLock::new(),
}
}
@@ -319,16 +324,23 @@ impl InstanceContext {
self.local_disk_set_drives.clone()
}
/// Set this instance's bucket metadata system (once). Returns `false` if
/// it was already initialized — the caller preserves the old fail-fast
/// contract, now scoped to the instance instead of the process.
/// Set this instance's bucket metadata system. Replaces any existing
/// value so test fixtures that share the bootstrap context can
/// reinitialize with their own store. Returns `true` if this is the
/// first initialization (no previous value existed).
pub fn init_bucket_metadata_sys(&self, sys: Arc<RwLock<BucketMetadataSys>>) -> bool {
self.bucket_metadata_sys.set(sys).is_ok()
let mut guard = self.bucket_metadata_sys.lock().expect("bucket_metadata_sys lock poisoned");
let is_first = guard.is_none();
*guard = Some(sys);
is_first
}
/// This instance's bucket metadata system, if initialized.
pub fn bucket_metadata_sys(&self) -> Option<Arc<RwLock<BucketMetadataSys>>> {
self.bucket_metadata_sys.get().cloned()
self.bucket_metadata_sys
.lock()
.expect("bucket_metadata_sys lock poisoned")
.clone()
}
/// Set this instance's background-services cancellation token (once).
@@ -387,7 +399,10 @@ impl std::fmt::Debug for InstanceContext {
.field("expiry_state_set", &self.expiry_state.get().is_some())
.field("transition_state_set", &self.transition_state.get().is_some())
.field("bucket_monitor_set", &self.bucket_monitor.get().is_some())
.field("bucket_metadata_sys_set", &self.bucket_metadata_sys.get().is_some())
.field(
"bucket_metadata_sys_set",
&self.bucket_metadata_sys.lock().map(|g| g.is_some()).unwrap_or(false),
)
.field("replication_stats_set", &self.replication_stats.get().is_some())
.field("replication_pool_set", &self.replication_pool.get().is_some())
.field("background_cancel_token_set", &self.background_cancel_token.get().is_some())