mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-29 00:17:11 +00:00
test(rustfs): move manual bench tools to examples, gate Swift suites (#6712)
This commit is contained in:
@@ -44,6 +44,18 @@ name = "rustfs-cli-e2e"
|
|||||||
path = "src/bin/rustfs-cli.rs"
|
path = "src/bin/rustfs-cli.rs"
|
||||||
required-features = ["offline-enrollment-e2e-root"]
|
required-features = ["offline-enrollment-e2e-root"]
|
||||||
|
|
||||||
|
# The Swift protocol suites are manual (#[ignore]) and need a server built with
|
||||||
|
# the `swift` feature; gating the test binaries on the same feature keeps the
|
||||||
|
# default `cargo test` / nextest build from linking two dead test binaries
|
||||||
|
# (backlog#1846 cluster 4).
|
||||||
|
[[test]]
|
||||||
|
name = "swift_container_integration_test"
|
||||||
|
required-features = ["swift"]
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "swift_object_integration_test"
|
||||||
|
required-features = ["swift"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ftps", "webdav"]
|
default = ["ftps", "webdav"]
|
||||||
metrics-gpu = ["rustfs-obs/gpu"]
|
metrics-gpu = ["rustfs-obs/gpu"]
|
||||||
|
|||||||
+5
-5
@@ -1,4 +1,4 @@
|
|||||||
# Concurrent Download Tool (tests)
|
# Concurrent Download Tool (example)
|
||||||
|
|
||||||
This tool downloads multiple URLs concurrently and saves files to a target directory.
|
This tool downloads multiple URLs concurrently and saves files to a target directory.
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ After run, the tool prints:
|
|||||||
- latency p95 ms
|
- latency p95 ms
|
||||||
- failure details (`[index] url => error`) when failures exist
|
- failure details (`[index] url => error`) when failures exist
|
||||||
|
|
||||||
If any task fails, the test returns error after printing the summary.
|
If any task fails, the tool exits with an error after printing the summary.
|
||||||
|
|
||||||
Retry is triggered only for recoverable cases:
|
Retry is triggered only for recoverable cases:
|
||||||
|
|
||||||
@@ -45,13 +45,13 @@ Retry is triggered only for recoverable cases:
|
|||||||
## Compile check
|
## Compile check
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo test -p rustfs --test concurrent_download_tool --no-run
|
cargo build -p rustfs --example concurrent_download_tool
|
||||||
```
|
```
|
||||||
|
|
||||||
## Manual run example
|
## Manual run example
|
||||||
|
|
||||||
The commands below are for manual execution only.
|
The commands below are for manual execution only.
|
||||||
They are not part of automated test runs.
|
The tool is an example binary, so it is built on demand and never runs as part of the test suites.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
DOWNLOAD_URLS="http://127.0.0.1:9001/demo/google-cloud-aiplugin-1.46.1-253.zip?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=HAXVOTZK9MLBJT8KWI4E%2F20260329%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260329T105159Z&X-Amz-Expires=86400&X-Amz-Security-Token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJwYXJlbnQiOiJydXN0ZnNhZG1pbiIsImV4cCI6MTc3NDgyMDgyMX0.tYhQoPRcg0Ysx4KVw9ez7ZpYxsqGgqomtsP_iaeTsKzoii8EVNt74BZm2wbUjXW-FbGXc1pqEYX6wZ5Ncpk9Iw&X-Amz-Signature=15f47b19832f53b34f9e0fe1862d53d71660bbf8f1a512669bb2d041ac8d0697&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject" \
|
DOWNLOAD_URLS="http://127.0.0.1:9001/demo/google-cloud-aiplugin-1.46.1-253.zip?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=HAXVOTZK9MLBJT8KWI4E%2F20260329%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260329T105159Z&X-Amz-Expires=86400&X-Amz-Security-Token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJwYXJlbnQiOiJydXN0ZnNhZG1pbiIsImV4cCI6MTc3NDgyMDgyMX0.tYhQoPRcg0Ysx4KVw9ez7ZpYxsqGgqomtsP_iaeTsKzoii8EVNt74BZm2wbUjXW-FbGXc1pqEYX6wZ5Ncpk9Iw&X-Amz-Signature=15f47b19832f53b34f9e0fe1862d53d71660bbf8f1a512669bb2d041ac8d0697&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject" \
|
||||||
@@ -60,6 +60,6 @@ DOWNLOAD_CONCURRENCY="40" \
|
|||||||
DOWNLOAD_REPEAT="40" \
|
DOWNLOAD_REPEAT="40" \
|
||||||
DOWNLOAD_MAX_RETRIES="2" \
|
DOWNLOAD_MAX_RETRIES="2" \
|
||||||
DOWNLOAD_RETRY_BACKOFF_MS="300" \
|
DOWNLOAD_RETRY_BACKOFF_MS="300" \
|
||||||
cargo test -p rustfs --test concurrent_download_tool -- --ignored --nocapture
|
cargo run -p rustfs --example concurrent_download_tool
|
||||||
```
|
```
|
||||||
|
|
||||||
+6
-3
@@ -12,6 +12,10 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
//! Manual concurrent-download performance tool: requires a running RustFS server
|
||||||
|
//! configured via `DOWNLOAD_*` env vars. Run with
|
||||||
|
//! `cargo run -p rustfs --example concurrent_download_tool`.
|
||||||
|
|
||||||
use anyhow::{Context, Result, anyhow};
|
use anyhow::{Context, Result, anyhow};
|
||||||
use futures::stream::{self, StreamExt};
|
use futures::stream::{self, StreamExt};
|
||||||
use reqwest::{Client, Url};
|
use reqwest::{Client, Url};
|
||||||
@@ -368,9 +372,8 @@ async fn run_concurrent_downloads(settings: DownloadSettings) -> Result<Download
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::main]
|
||||||
#[ignore = "manual performance tool: requires a running RustFS server configured via env vars"]
|
async fn main() -> Result<()> {
|
||||||
async fn concurrent_download_tool() -> Result<()> {
|
|
||||||
let settings = DownloadSettings::from_env()?;
|
let settings = DownloadSettings::from_env()?;
|
||||||
let summary = run_concurrent_downloads(settings).await?;
|
let summary = run_concurrent_downloads(settings).await?;
|
||||||
|
|
||||||
+19
-3
@@ -1,3 +1,20 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
//! Manual >1GiB GET benchmark: requires a running RustFS server configured via
|
||||||
|
//! `GT1G_GET_*` env vars. Run with `cargo run -p rustfs --example gt1g_get_benchmark_tool`.
|
||||||
|
|
||||||
use anyhow::{Context, Result, anyhow};
|
use anyhow::{Context, Result, anyhow};
|
||||||
use aws_config::BehaviorVersion;
|
use aws_config::BehaviorVersion;
|
||||||
use aws_config::meta::region::RegionProviderChain;
|
use aws_config::meta::region::RegionProviderChain;
|
||||||
@@ -511,9 +528,8 @@ async fn run_bench(settings: &ToolSettings, client: &Client) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::main]
|
||||||
#[ignore = "manual >1GiB GET benchmark: requires a running RustFS server configured via env vars"]
|
async fn main() -> Result<()> {
|
||||||
async fn gt1g_get_benchmark_tool() -> Result<()> {
|
|
||||||
let settings = ToolSettings::from_env()?;
|
let settings = ToolSettings::from_env()?;
|
||||||
let client = build_client(&settings).await?;
|
let client = build_client(&settings).await?;
|
||||||
|
|
||||||
@@ -16,14 +16,10 @@ use anyhow::{Context, Result};
|
|||||||
use aws_config::BehaviorVersion;
|
use aws_config::BehaviorVersion;
|
||||||
use aws_sdk_s3::Client;
|
use aws_sdk_s3::Client;
|
||||||
use aws_sdk_s3::config::{Credentials, Region};
|
use aws_sdk_s3::config::{Credentials, Region};
|
||||||
use aws_sdk_s3::presigning::PresigningConfig;
|
|
||||||
use aws_sdk_s3::types::{
|
use aws_sdk_s3::types::{
|
||||||
BucketLifecycleConfiguration, ExpirationStatus, LifecycleExpiration, LifecycleRule, LifecycleRuleFilter,
|
BucketLifecycleConfiguration, ExpirationStatus, LifecycleExpiration, LifecycleRule, LifecycleRuleFilter,
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::time::Duration;
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
oss_endpoint: String,
|
oss_endpoint: String,
|
||||||
@@ -31,8 +27,6 @@ struct Settings {
|
|||||||
oss_secret_key: String,
|
oss_secret_key: String,
|
||||||
oss_bucket_name: String,
|
oss_bucket_name: String,
|
||||||
oss_lifecycle_days: i32,
|
oss_lifecycle_days: i32,
|
||||||
#[allow(dead_code)]
|
|
||||||
oss_secure: bool,
|
|
||||||
oss_region: String,
|
oss_region: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +38,6 @@ impl Settings {
|
|||||||
oss_secret_key: "rustfsadmin".to_string(),
|
oss_secret_key: "rustfsadmin".to_string(),
|
||||||
oss_bucket_name: "mblock99".to_string(),
|
oss_bucket_name: "mblock99".to_string(),
|
||||||
oss_lifecycle_days: 1,
|
oss_lifecycle_days: 1,
|
||||||
oss_secure: false,
|
|
||||||
oss_region: "us-east-1".to_string(),
|
oss_region: "us-east-1".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,10 +69,6 @@ impl Oss {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_uuid(&self) -> String {
|
|
||||||
Uuid::new_v4().to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create_bucket(&self) -> Result<()> {
|
async fn create_bucket(&self) -> Result<()> {
|
||||||
match self.client.head_bucket().bucket(&self.bucket_name).send().await {
|
match self.client.head_bucket().bucket(&self.bucket_name).send().await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
@@ -136,49 +125,9 @@ impl Oss {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
async fn upload_file(&self, filename: &str, content: &[u8]) -> Result<String> {
|
|
||||||
let ext = std::path::Path::new(filename)
|
|
||||||
.extension()
|
|
||||||
.and_then(|s| s.to_str())
|
|
||||||
.unwrap_or("");
|
|
||||||
|
|
||||||
let uuid = self.new_uuid();
|
|
||||||
let object_name = if ext.is_empty() { uuid } else { format!("{}.{}", uuid, ext) };
|
|
||||||
|
|
||||||
self.client
|
|
||||||
.put_object()
|
|
||||||
.bucket(&self.bucket_name)
|
|
||||||
.key(&object_name)
|
|
||||||
.body(content.to_vec().into())
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.context("Failed to upload file")?;
|
|
||||||
|
|
||||||
Ok(object_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
async fn get_presigned_url(&self, filename: &str) -> Result<String> {
|
|
||||||
let expires_in = Duration::from_secs((self.lifecycle_days * 24 * 60 * 60) as u64);
|
|
||||||
let presigning_config = PresigningConfig::expires_in(expires_in)?;
|
|
||||||
|
|
||||||
let presigned_req = self
|
|
||||||
.client
|
|
||||||
.get_object()
|
|
||||||
.bucket(&self.bucket_name)
|
|
||||||
.key(filename)
|
|
||||||
.presigned(presigning_config)
|
|
||||||
.await
|
|
||||||
.context("Failed to get presigned URL")?;
|
|
||||||
|
|
||||||
Ok(presigned_req.uri().to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[serial]
|
|
||||||
#[ignore = "requires a running RustFS server at TEST_RUSTFS_SERVER (default http://localhost:9000)"]
|
#[ignore = "requires a running RustFS server at TEST_RUSTFS_SERVER (default http://localhost:9000)"]
|
||||||
async fn test_lifecycle_minio_sdk() -> Result<()> {
|
async fn test_lifecycle_minio_sdk() -> Result<()> {
|
||||||
let settings = Settings::new();
|
let settings = Settings::new();
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ run_rust_helper_fallback() {
|
|||||||
helper_out_dir="$PWD/$helper_out_dir"
|
helper_out_dir="$PWD/$helper_out_dir"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "mc not found; falling back to rustfs/tests/gt1g_get_benchmark_tool.rs"
|
echo "mc not found; falling back to rustfs/examples/gt1g_get_benchmark_tool.rs"
|
||||||
GT1G_GET_ACTION=prepare \
|
GT1G_GET_ACTION=prepare \
|
||||||
GT1G_GET_ENDPOINT="$ENDPOINT" \
|
GT1G_GET_ENDPOINT="$ENDPOINT" \
|
||||||
GT1G_GET_ACCESS_KEY="$ACCESS_KEY" \
|
GT1G_GET_ACCESS_KEY="$ACCESS_KEY" \
|
||||||
@@ -92,7 +92,7 @@ run_rust_helper_fallback() {
|
|||||||
GT1G_GET_OBJECTS="$objects_arg" \
|
GT1G_GET_OBJECTS="$objects_arg" \
|
||||||
GT1G_GET_OUT_DIR="${helper_out_dir:-$PWD/target/bench/issue713-prepare-helper}" \
|
GT1G_GET_OUT_DIR="${helper_out_dir:-$PWD/target/bench/issue713-prepare-helper}" \
|
||||||
GT1G_GET_FORCE="$([[ "$FORCE" == "true" ]] && echo true || echo false)" \
|
GT1G_GET_FORCE="$([[ "$FORCE" == "true" ]] && echo true || echo false)" \
|
||||||
cargo test -p rustfs --test gt1g_get_benchmark_tool gt1g_get_benchmark_tool -- --ignored --nocapture
|
cargo run -p rustfs --example gt1g_get_benchmark_tool
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_args() {
|
parse_args() {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ run_rust_helper_fallback() {
|
|||||||
helper_out_dir="$PWD/$helper_out_dir"
|
helper_out_dir="$PWD/$helper_out_dir"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "mc not found; falling back to rustfs/tests/gt1g_get_benchmark_tool.rs"
|
echo "mc not found; falling back to rustfs/examples/gt1g_get_benchmark_tool.rs"
|
||||||
|
|
||||||
GT1G_GET_ACTION=bench \
|
GT1G_GET_ACTION=bench \
|
||||||
GT1G_GET_ENDPOINT="$ENDPOINT" \
|
GT1G_GET_ENDPOINT="$ENDPOINT" \
|
||||||
@@ -99,7 +99,7 @@ run_rust_helper_fallback() {
|
|||||||
GT1G_GET_ROUNDS="$ROUNDS" \
|
GT1G_GET_ROUNDS="$ROUNDS" \
|
||||||
GT1G_GET_COOLDOWN_SECS="$COOLDOWN_SECS" \
|
GT1G_GET_COOLDOWN_SECS="$COOLDOWN_SECS" \
|
||||||
GT1G_GET_OUT_DIR="$helper_out_dir" \
|
GT1G_GET_OUT_DIR="$helper_out_dir" \
|
||||||
cargo test -p rustfs --test gt1g_get_benchmark_tool gt1g_get_benchmark_tool -- --ignored --nocapture
|
cargo run -p rustfs --example gt1g_get_benchmark_tool
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_args() {
|
parse_args() {
|
||||||
|
|||||||
Reference in New Issue
Block a user