mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-25 13:36:50 +00:00
test(ecstore): guard replication facade boundary (#4035)
This commit is contained in:
@@ -47,3 +47,7 @@ and lifecycle/heal scheduling paths.
|
|||||||
Start with `ReplicationRuntime` or `ReplicationEventSink`. Both can be added as
|
Start with `ReplicationRuntime` or `ReplicationEventSink`. Both can be added as
|
||||||
narrow internal contracts while keeping current queue, MRF, resync, and target
|
narrow internal contracts while keeping current queue, MRF, resync, and target
|
||||||
behavior unchanged. Do not start with a crate move.
|
behavior unchanged. Do not start with a crate move.
|
||||||
|
|
||||||
|
Current compatibility guard: `crates/ecstore/tests/replication_facade_compat_test.rs`
|
||||||
|
keeps the ECStore replication facade types covered while architecture rules
|
||||||
|
keep direct imports behind local `storage_api` boundaries.
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright 2024 RustFS Team
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
mod storage_api;
|
||||||
|
|
||||||
|
use s3s::dto::ReplicationConfiguration;
|
||||||
|
use storage_api::replication_compat::{
|
||||||
|
BucketStats, DeletedObjectReplicationInfo, DynReplicationPool, ObjectOpts, ReplicationConfigurationExt, ReplicationStats,
|
||||||
|
ResyncStatusType,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn type_name<T>() -> &'static str {
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_name_unsized<T: ?Sized>() -> &'static str {
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_replication_config_ext<T: ReplicationConfigurationExt>() {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn replication_facade_exports_config_extension_contract() {
|
||||||
|
assert_replication_config_ext::<ReplicationConfiguration>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn replication_facade_exports_runtime_and_dto_types() {
|
||||||
|
assert_eq!(ResyncStatusType::default(), ResyncStatusType::NoResync);
|
||||||
|
assert!(!ResyncStatusType::default().is_valid());
|
||||||
|
|
||||||
|
let object_opts = ObjectOpts::default();
|
||||||
|
assert!(object_opts.name.is_empty());
|
||||||
|
|
||||||
|
let deleted = DeletedObjectReplicationInfo::default();
|
||||||
|
assert!(deleted.bucket.is_empty());
|
||||||
|
|
||||||
|
let _stats = ReplicationStats::new();
|
||||||
|
let _bucket_stats = BucketStats::default();
|
||||||
|
|
||||||
|
assert!(type_name::<ReplicationStats>().contains("ReplicationStats"));
|
||||||
|
assert!(type_name::<BucketStats>().contains("BucketStats"));
|
||||||
|
assert!(type_name::<DeletedObjectReplicationInfo>().contains("DeletedObjectReplicationInfo"));
|
||||||
|
assert!(type_name_unsized::<DynReplicationPool>().contains("ReplicationPoolTrait"));
|
||||||
|
}
|
||||||
@@ -20,6 +20,13 @@ pub(crate) mod contract_compat {
|
|||||||
pub(crate) use super::{DiskStore, ECStore, Error, GetObjectReader, ObjectInfo, ObjectOptions, PutObjReader, SetDisks};
|
pub(crate) use super::{DiskStore, ECStore, Error, GetObjectReader, ObjectInfo, ObjectOptions, PutObjReader, SetDisks};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) mod replication_compat {
|
||||||
|
pub(crate) use rustfs_ecstore::api::bucket::replication::{
|
||||||
|
BucketStats, DeletedObjectReplicationInfo, DynReplicationPool, ObjectOpts, ReplicationConfigurationExt, ReplicationStats,
|
||||||
|
ResyncStatusType,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) mod legacy_bitrot_read {
|
pub(crate) mod legacy_bitrot_read {
|
||||||
pub(crate) use super::{DiskOption, Endpoint, STORAGE_FORMAT_FILE, create_bitrot_reader, new_disk};
|
pub(crate) use super::{DiskOption, Endpoint, STORAGE_FORMAT_FILE, create_bitrot_reader, new_disk};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ RUSTFS_APP_ADMIN_STORAGE_HELPER_ROOT_REEXPORT_HITS_FILE="${TMP_DIR}/rustfs_app_a
|
|||||||
EXTERNAL_TEST_ECSTORE_COMPAT_BYPASS_HITS_FILE="${TMP_DIR}/external_test_ecstore_compat_bypass_hits.txt"
|
EXTERNAL_TEST_ECSTORE_COMPAT_BYPASS_HITS_FILE="${TMP_DIR}/external_test_ecstore_compat_bypass_hits.txt"
|
||||||
FUZZ_ECSTORE_COMPAT_BYPASS_HITS_FILE="${TMP_DIR}/fuzz_ecstore_compat_bypass_hits.txt"
|
FUZZ_ECSTORE_COMPAT_BYPASS_HITS_FILE="${TMP_DIR}/fuzz_ecstore_compat_bypass_hits.txt"
|
||||||
EXTERNAL_ECSTORE_API_BOUNDARY_HITS_FILE="${TMP_DIR}/external_ecstore_api_boundary_hits.txt"
|
EXTERNAL_ECSTORE_API_BOUNDARY_HITS_FILE="${TMP_DIR}/external_ecstore_api_boundary_hits.txt"
|
||||||
|
REPLICATION_FACADE_BYPASS_HITS_FILE="${TMP_DIR}/replication_facade_bypass_hits.txt"
|
||||||
LEGACY_ECSTORE_CONFIG_MODEL_HITS_FILE="${TMP_DIR}/legacy_ecstore_config_model_hits.txt"
|
LEGACY_ECSTORE_CONFIG_MODEL_HITS_FILE="${TMP_DIR}/legacy_ecstore_config_model_hits.txt"
|
||||||
ECSTORE_ROOT_STORE_SET_DISK_MODULE_HITS_FILE="${TMP_DIR}/ecstore_root_store_set_disk_module_hits.txt"
|
ECSTORE_ROOT_STORE_SET_DISK_MODULE_HITS_FILE="${TMP_DIR}/ecstore_root_store_set_disk_module_hits.txt"
|
||||||
ECSTORE_ROOT_STORE_SUPPORT_MODULE_HITS_FILE="${TMP_DIR}/ecstore_root_store_support_module_hits.txt"
|
ECSTORE_ROOT_STORE_SUPPORT_MODULE_HITS_FILE="${TMP_DIR}/ecstore_root_store_support_module_hits.txt"
|
||||||
@@ -2277,6 +2278,18 @@ if [[ -s "$EXTERNAL_ECSTORE_API_BOUNDARY_HITS_FILE" ]]; then
|
|||||||
report_failure "external ECStore API facade imports must stay in local storage_api boundary files: $(paste -sd '; ' "$EXTERNAL_ECSTORE_API_BOUNDARY_HITS_FILE")"
|
report_failure "external ECStore API facade imports must stay in local storage_api boundary files: $(paste -sd '; ' "$EXTERNAL_ECSTORE_API_BOUNDARY_HITS_FILE")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
rg -n --with-filename 'rustfs_ecstore::api::bucket::replication' \
|
||||||
|
rustfs/src crates/*/src crates/*/tests crates/ecstore/tests fuzz/fuzz_targets \
|
||||||
|
--glob '*.rs' |
|
||||||
|
rg -v '^(rustfs/src/(admin/storage_api|app/storage_api|storage/storage_api)\.rs|crates/ecstore/tests/storage_api\.rs|crates/obs/src/metrics/storage_api\.rs|crates/scanner/src/storage_api\.rs|crates/scanner/tests/storage_api/mod\.rs|fuzz/fuzz_targets/(bucket_validation_storage_api|path_containment_storage_api)\.rs):' || true
|
||||||
|
) >"$REPLICATION_FACADE_BYPASS_HITS_FILE"
|
||||||
|
|
||||||
|
if [[ -s "$REPLICATION_FACADE_BYPASS_HITS_FILE" ]]; then
|
||||||
|
report_failure "replication facade imports must stay in local storage_api boundaries: $(paste -sd '; ' "$REPLICATION_FACADE_BYPASS_HITS_FILE")"
|
||||||
|
fi
|
||||||
|
|
||||||
(
|
(
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user