mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-20 19:42:17 +00:00
898aa4db95
* chore: adjudicate the last 18 bare dead_code allows in the library crates Finishes backlog#1823 step 10 outside `rustfs/src` and `protocols`: config, s3select-query, common, madmin, heal, ecstore, signer and notify. Stripped first, then clippy asked which the compiler actually missed — 8 of the 18 were inert. Seven items are deleted, each checked by grep as well as by clippy: - `common/last_minute.rs`'s private `TimedAction` (with its impl) and `SizeCategory` (with its `Display` impl). The file's public surface — `AccElem`, `LastMinuteLatency` — stays; ecstore consumes it. - `s3select-query`'s three `with_*` builders. `DefaultLogicalOptimizer::with_optimizer_rules` looks used, but the call in the same file is `SessionStateBuilder::with_optimizer_rules` from DataFusion; the local methods have no callers. - `heal/manager.rs`'s `contains_key`. Its six apparent references are all `HashMap::contains_key`. Three keep their code: - `heal/storage.rs`'s `Test` variant is constructed by the `#[cfg(test)] test()` helper, which the lib target cannot see, so it takes a reasoned allow. - `signer`'s `STREAMING_PAYLOAD_HDR` and `try_build_chunk_string_to_sign` gain the `_` prefix instead. That file already marks deliberately-unheld code that way — `_STREAMING_TRAILER_HDR`, `_PAYLOAD_CHUNK_SIZE`, and `_try_build_chunk_signature`, which is the only caller of that function. Following the existing convention removes the allow without an attribute. `protocols` keeps its four; that crate needs `--features swift,sftp` to compile fully and is verified differently. The four `#![allow(dead_code)]` in `e2e_test` are module-root blankets in test-support files, which belong to steps 1-5 rather than step 10. Refs backlog#1823 * chore(e2e_test): adjudicate the two dead_code allows the lib test target still needs `cargo clippy --all-targets` compiles e2e_test's lib test target, which the earlier pass did not cover, so these two removals only surfaced in CI. test_large_multipart_upload's allow was load-bearing: its call site in test_local_kms_multipart_upload is commented out behind "TODO: Re-enable after fixing streaming encryption issues with large files". The allow comes back with the reason string this batch uses everywhere else, so the next reader sees why it is parked instead of deleting a test we intend to run again. TestDefinition.category was the opposite: written at all six definitions, read nowhere, and its enum's impl block is empty. The live copy of that type is crates/e2e_test/src/kms/test_runner.rs, which has an as_str; the policy copy is a vestige of it. Dropping the field, the enum, and the constructor parameter leaves the runner unchanged — it dispatches on name and filters on is_critical. Verification: cargo clippy --all-targets -- -D warnings (workspace, the CI command) and cargo fmt --all --check both pass. --------- Co-authored-by: houseme <housemecn@gmail.com>
233 lines
7.6 KiB
Rust
233 lines
7.6 KiB
Rust
// 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.
|
|
|
|
use crate::common::init_logging;
|
|
use crate::policy::test_env::PolicyTestEnvironment;
|
|
use serial_test::serial;
|
|
use std::time::Instant;
|
|
use tokio::time::{Duration, sleep};
|
|
use tracing::{error, info};
|
|
|
|
/// Test case definition
|
|
#[derive(Debug, Clone)]
|
|
pub struct TestDefinition {
|
|
pub name: String,
|
|
pub is_critical: bool,
|
|
}
|
|
|
|
impl TestDefinition {
|
|
pub fn new(name: impl Into<String>, is_critical: bool) -> Self {
|
|
Self {
|
|
name: name.into(),
|
|
is_critical,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Test result
|
|
#[derive(Debug, Clone)]
|
|
pub struct TestResult {
|
|
pub test_name: String,
|
|
pub success: bool,
|
|
pub error_message: Option<String>,
|
|
}
|
|
|
|
impl TestResult {
|
|
pub fn success(test_name: String) -> Self {
|
|
Self {
|
|
test_name,
|
|
success: true,
|
|
error_message: None,
|
|
}
|
|
}
|
|
|
|
pub fn failure(test_name: String, error: String) -> Self {
|
|
Self {
|
|
test_name,
|
|
success: false,
|
|
error_message: Some(error),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Test suite configuration
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct TestSuiteConfig {
|
|
pub include_critical_only: bool,
|
|
}
|
|
|
|
/// Policy test suite
|
|
pub struct PolicyTestSuite {
|
|
tests: Vec<TestDefinition>,
|
|
config: TestSuiteConfig,
|
|
}
|
|
|
|
impl PolicyTestSuite {
|
|
/// Create default test suite
|
|
pub fn new() -> Self {
|
|
let tests = vec![
|
|
TestDefinition::new("test_aws_policy_variables_single_value", true),
|
|
TestDefinition::new("test_aws_policy_variables_multi_value", true),
|
|
TestDefinition::new("test_aws_policy_variables_concatenation", true),
|
|
TestDefinition::new("test_aws_policy_variables_nested", true),
|
|
TestDefinition::new("test_aws_policy_variables_deny", true),
|
|
TestDefinition::new("test_aws_policy_variables_sts", true),
|
|
];
|
|
|
|
Self {
|
|
tests,
|
|
config: TestSuiteConfig::default(),
|
|
}
|
|
}
|
|
|
|
/// Configure test suite
|
|
pub fn with_config(mut self, config: TestSuiteConfig) -> Self {
|
|
self.config = config;
|
|
self
|
|
}
|
|
|
|
/// Run test suite
|
|
pub async fn run_test_suite(&self) -> Vec<TestResult> {
|
|
init_logging();
|
|
info!("Starting Policy Variables test suite");
|
|
|
|
let start_time = Instant::now();
|
|
let mut results = Vec::new();
|
|
|
|
// Create test environment
|
|
let env = match PolicyTestEnvironment::with_address("127.0.0.1:9000").await {
|
|
Ok(env) => env,
|
|
Err(e) => {
|
|
error!("Failed to create test environment: {}", e);
|
|
return vec![TestResult::failure("env_creation".into(), e.to_string())];
|
|
}
|
|
};
|
|
|
|
// Wait for server to be ready
|
|
if env.wait_for_server_ready().await.is_err() {
|
|
error!("Server is not ready");
|
|
return vec![TestResult::failure("server_check".into(), "Server not ready".into())];
|
|
}
|
|
|
|
// Filter tests
|
|
let tests_to_run: Vec<&TestDefinition> = self
|
|
.tests
|
|
.iter()
|
|
.filter(|test| !self.config.include_critical_only || test.is_critical)
|
|
.collect();
|
|
|
|
info!("Scheduled {} tests", tests_to_run.len());
|
|
|
|
// Run tests
|
|
for (i, test_def) in tests_to_run.iter().enumerate() {
|
|
info!("Running test {}/{}: {}", i + 1, tests_to_run.len(), test_def.name);
|
|
let test_start = Instant::now();
|
|
|
|
let result = self.run_single_test(test_def, &env).await;
|
|
let test_duration = test_start.elapsed();
|
|
|
|
match result {
|
|
Ok(_) => {
|
|
info!("Test passed: {} ({:.2}s)", test_def.name, test_duration.as_secs_f64());
|
|
results.push(TestResult::success(test_def.name.clone()));
|
|
}
|
|
Err(e) => {
|
|
error!("Test failed: {} ({:.2}s): {}", test_def.name, test_duration.as_secs_f64(), e);
|
|
results.push(TestResult::failure(test_def.name.clone(), e.to_string()));
|
|
}
|
|
}
|
|
|
|
// Delay between tests to avoid resource conflicts
|
|
if i < tests_to_run.len() - 1 {
|
|
sleep(Duration::from_secs(2)).await;
|
|
}
|
|
}
|
|
|
|
// Print summary
|
|
self.print_summary(&results, start_time.elapsed());
|
|
|
|
results
|
|
}
|
|
|
|
/// Run a single test
|
|
async fn run_single_test(
|
|
&self,
|
|
test_def: &TestDefinition,
|
|
env: &PolicyTestEnvironment,
|
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
match test_def.name.as_str() {
|
|
"test_aws_policy_variables_single_value" => {
|
|
super::policy_variables_test::test_aws_policy_variables_single_value_impl_with_env(env).await
|
|
}
|
|
"test_aws_policy_variables_multi_value" => {
|
|
super::policy_variables_test::test_aws_policy_variables_multi_value_impl_with_env(env).await
|
|
}
|
|
"test_aws_policy_variables_concatenation" => {
|
|
super::policy_variables_test::test_aws_policy_variables_concatenation_impl_with_env(env).await
|
|
}
|
|
"test_aws_policy_variables_nested" => {
|
|
super::policy_variables_test::test_aws_policy_variables_nested_impl_with_env(env).await
|
|
}
|
|
"test_aws_policy_variables_deny" => {
|
|
super::policy_variables_test::test_aws_policy_variables_deny_impl_with_env(env).await
|
|
}
|
|
"test_aws_policy_variables_sts" => {
|
|
super::policy_variables_test::test_aws_policy_variables_sts_impl_with_env(env).await
|
|
}
|
|
_ => Err(format!("Test {} not implemented", test_def.name).into()),
|
|
}
|
|
}
|
|
|
|
/// Print test summary
|
|
fn print_summary(&self, results: &[TestResult], total_duration: Duration) {
|
|
info!("=== Test Suite Summary ===");
|
|
info!("Total duration: {:.2}s", total_duration.as_secs_f64());
|
|
info!("Total tests: {}", results.len());
|
|
|
|
let passed = results.iter().filter(|r| r.success).count();
|
|
let failed = results.len() - passed;
|
|
let success_rate = (passed as f64 / results.len() as f64) * 100.0;
|
|
|
|
info!("Passed: {} | Failed: {}", passed, failed);
|
|
info!("Success rate: {:.1}%", success_rate);
|
|
|
|
if failed > 0 {
|
|
error!("Failed tests:");
|
|
for result in results.iter().filter(|r| !r.success) {
|
|
error!(" - {}: {}", result.test_name, result.error_message.as_ref().unwrap());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Test suite
|
|
#[tokio::test]
|
|
#[serial]
|
|
#[ignore = "Connects to existing rustfs server"]
|
|
async fn test_policy_critical_suite() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
let config = TestSuiteConfig {
|
|
include_critical_only: true,
|
|
};
|
|
let suite = PolicyTestSuite::new().with_config(config);
|
|
let results = suite.run_test_suite().await;
|
|
|
|
let failed = results.iter().filter(|r| !r.success).count();
|
|
if failed > 0 {
|
|
return Err(format!("Critical tests failed: {failed} failures").into());
|
|
}
|
|
|
|
info!("All critical tests passed");
|
|
Ok(())
|
|
}
|