added benchmarks (#142)

This commit is contained in:
Henk-Jan Lebbink
2025-03-29 23:26:11 +01:00
committed by GitHub
parent 0cccaf1663
commit f23572dce8
60 changed files with 1986 additions and 712 deletions

View File

@@ -1,311 +0,0 @@
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
// Copyright 2025 MinIO, Inc.
//
// 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 async_std::task;
use bytes::Bytes;
use rand::SeedableRng;
use rand::distributions::{Alphanumeric, DistString};
use rand::prelude::SmallRng;
use std::path::{Path, PathBuf};
use std::{io, thread};
use tokio::io::AsyncRead;
use tokio::time::timeout;
use tokio_stream::Stream;
use minio::s3::client::Client;
use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl;
use minio::s3::types::S3Api;
pub struct RandReader {
size: u64,
}
impl RandReader {
#[allow(dead_code)]
pub fn new(size: u64) -> RandReader {
RandReader { size }
}
}
impl io::Read for RandReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
let bytes_read: usize = match (self.size as usize) > buf.len() {
true => buf.len(),
false => self.size as usize,
};
if bytes_read > 0 {
let random: &mut dyn rand::RngCore = &mut rand::thread_rng();
random.fill_bytes(&mut buf[0..bytes_read]);
}
self.size -= bytes_read as u64;
Ok(bytes_read)
}
}
pub struct RandSrc {
size: u64,
rng: SmallRng,
}
impl RandSrc {
#[allow(dead_code)]
pub fn new(size: u64) -> RandSrc {
let rng = SmallRng::from_entropy();
RandSrc { size, rng }
}
}
impl Stream for RandSrc {
type Item = Result<Bytes, io::Error>;
fn poll_next(
self: std::pin::Pin<&mut Self>,
_cx: &mut task::Context<'_>,
) -> task::Poll<Option<Self::Item>> {
if self.size == 0 {
return task::Poll::Ready(None);
}
let bytes_read = match self.size > 64 * 1024 {
true => 64 * 1024,
false => self.size as usize,
};
let this = self.get_mut();
let mut buf = vec![0; bytes_read];
let random: &mut dyn rand::RngCore = &mut this.rng;
random.fill_bytes(&mut buf);
this.size -= bytes_read as u64;
task::Poll::Ready(Some(Ok(Bytes::from(buf))))
}
}
impl AsyncRead for RandSrc {
fn poll_read(
self: std::pin::Pin<&mut Self>,
_cx: &mut task::Context<'_>,
read_buf: &mut tokio::io::ReadBuf<'_>,
) -> task::Poll<io::Result<()>> {
let buf = read_buf.initialize_unfilled();
let bytes_read = match self.size > (buf.len() as u64) {
true => buf.len(),
false => self.size as usize,
};
let this = self.get_mut();
if bytes_read > 0 {
let random: &mut dyn rand::RngCore = &mut this.rng;
random.fill_bytes(&mut buf[0..bytes_read]);
}
this.size -= bytes_read as u64;
read_buf.advance(bytes_read);
task::Poll::Ready(Ok(()))
}
}
pub fn rand_bucket_name() -> String {
Alphanumeric
.sample_string(&mut rand::thread_rng(), 8)
.to_lowercase()
}
#[allow(dead_code)]
pub fn rand_object_name() -> String {
Alphanumeric.sample_string(&mut rand::thread_rng(), 8)
}
#[derive(Clone)]
#[allow(dead_code)]
pub struct TestContext {
pub base_url: BaseUrl,
pub access_key: String,
pub secret_key: String,
pub ignore_cert_check: Option<bool>,
pub ssl_cert_file: Option<PathBuf>,
pub client: Client,
}
impl TestContext {
#[allow(dead_code)]
pub fn new_from_env() -> Self {
let run_on_ci: bool = std::env::var("CI")
.unwrap_or("false".into())
.parse()
.unwrap_or(false);
if run_on_ci {
let host = std::env::var("SERVER_ENDPOINT").unwrap();
let access_key = std::env::var("ACCESS_KEY").unwrap();
let secret_key = std::env::var("SECRET_KEY").unwrap();
let secure = std::env::var("ENABLE_HTTPS").is_ok();
let value = std::env::var("SSL_CERT_FILE").unwrap();
let mut ssl_cert_file = None;
if !value.is_empty() {
ssl_cert_file = Some(Path::new(&value));
}
let ignore_cert_check = std::env::var("IGNORE_CERT_CHECK").is_ok();
let region = std::env::var("SERVER_REGION").ok();
let mut base_url: BaseUrl = host.parse().unwrap();
base_url.https = secure;
if let Some(v) = region {
base_url.region = v;
}
let static_provider = StaticProvider::new(&access_key, &secret_key, None);
let client = Client::new(
base_url.clone(),
Some(Box::new(static_provider)),
ssl_cert_file,
Some(ignore_cert_check),
)
.unwrap();
Self {
base_url,
access_key,
secret_key,
ignore_cert_check: Some(ignore_cert_check),
ssl_cert_file: ssl_cert_file.map(PathBuf::from),
client,
}
} else {
const DEFAULT_SERVER_ENDPOINT: &str = "https://play.min.io/";
const DEFAULT_ACCESS_KEY: &str = "minioadmin";
const DEFAULT_SECRET_KEY: &str = "minioadmin";
const DEFAULT_ENABLE_HTTPS: &str = "true";
const DEFAULT_SSL_CERT_FILE: &str = "./tests/public.crt";
const DEFAULT_IGNORE_CERT_CHECK: &str = "false";
const DEFAULT_SERVER_REGION: &str = "";
let host: String =
std::env::var("SERVER_ENDPOINT").unwrap_or(DEFAULT_SERVER_ENDPOINT.to_string());
log::info!("SERVER_ENDPOINT={}", host);
let access_key: String =
std::env::var("ACCESS_KEY").unwrap_or(DEFAULT_ACCESS_KEY.to_string());
log::info!("ACCESS_KEY={}", access_key);
let secret_key: String =
std::env::var("SECRET_KEY").unwrap_or(DEFAULT_SECRET_KEY.to_string());
log::info!("SECRET_KEY=*****");
let secure: bool = std::env::var("ENABLE_HTTPS")
.unwrap_or(DEFAULT_ENABLE_HTTPS.to_string())
.parse()
.unwrap_or(false);
log::info!("ENABLE_HTTPS={}", secure);
let ssl_cert: String =
std::env::var("SSL_CERT_FILE").unwrap_or(DEFAULT_SSL_CERT_FILE.to_string());
log::info!("SSL_CERT_FILE={}", ssl_cert);
let ssl_cert_file: PathBuf = ssl_cert.into();
let ignore_cert_check: bool = std::env::var("IGNORE_CERT_CHECK")
.unwrap_or(DEFAULT_IGNORE_CERT_CHECK.to_string())
.parse()
.unwrap_or(true);
log::info!("IGNORE_CERT_CHECK={}", ignore_cert_check);
let region: String =
std::env::var("SERVER_REGION").unwrap_or(DEFAULT_SERVER_REGION.to_string());
log::info!("SERVER_REGION={:?}", region);
let mut base_url: BaseUrl = host.parse().unwrap();
base_url.https = secure;
base_url.region = region;
let static_provider = StaticProvider::new(&access_key, &secret_key, None);
let client = Client::new(
base_url.clone(),
Some(Box::new(static_provider)),
Some(&*ssl_cert_file),
Some(ignore_cert_check),
)
.unwrap();
Self {
base_url,
access_key,
secret_key,
ignore_cert_check: Some(ignore_cert_check),
ssl_cert_file: Some(ssl_cert_file),
client,
}
}
}
}
#[allow(dead_code)]
pub async fn create_bucket_helper(ctx: &TestContext) -> (String, CleanupGuard) {
let bucket_name = rand_bucket_name();
let _resp = ctx.client.make_bucket(&bucket_name).send().await.unwrap();
let guard = CleanupGuard::new(ctx, &bucket_name);
(bucket_name, guard)
}
// Cleanup guard that removes the bucket when it is dropped
pub struct CleanupGuard {
ctx: TestContext,
bucket_name: String,
}
impl CleanupGuard {
#[allow(dead_code)]
pub fn new(ctx: &TestContext, bucket_name: &str) -> Self {
Self {
ctx: ctx.clone(),
bucket_name: bucket_name.to_string(),
}
}
}
impl Drop for CleanupGuard {
fn drop(&mut self) {
let ctx = self.ctx.clone();
let bucket_name = self.bucket_name.clone();
//println!("Going to remove bucket {}", bucket_name);
// Spawn the cleanup task in a way that detaches it from the current runtime
thread::spawn(move || {
// Create a new runtime for this thread
let rt = tokio::runtime::Runtime::new().unwrap();
// Execute the async cleanup in this new runtime
rt.block_on(async {
// do the actual removal of the bucket
match timeout(
std::time::Duration::from_secs(60),
ctx.client.remove_and_purge_bucket(&bucket_name),
)
.await
{
Ok(result) => match result {
Ok(_) => {
//println!("Bucket {} removed successfully", bucket_name),
}
Err(e) => println!("Error removing bucket {}: {:?}", bucket_name, e),
},
Err(_) => println!("Timeout after 60s while removing bucket {}", bucket_name),
}
});
})
.join()
.unwrap(); // This blocks the current thread until cleanup is done
}
}

View File

@@ -13,19 +13,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, rand_bucket_name};
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{BucketExistsResponse, RemoveBucketResponse};
use minio::s3::response::{BucketExistsResponse, MakeBucketResponse, RemoveBucketResponse};
use minio::s3::types::S3Api;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_bucket_name;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn create_delete_bucket() {
let ctx = TestContext::new_from_env();
let bucket_name = rand_bucket_name();
ctx.client.make_bucket(&bucket_name).send().await.unwrap();
let resp: MakeBucketResponse = ctx.client.make_bucket(&bucket_name).send().await.unwrap();
assert_eq!(resp.bucket, bucket_name);
let resp: BucketExistsResponse = ctx.client.bucket_exists(&bucket_name).send().await.unwrap();
assert!(resp.exists);

View File

@@ -13,19 +13,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper};
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
DeleteBucketEncryptionResponse, GetBucketEncryptionResponse, SetBucketEncryptionResponse,
};
use minio::s3::types::{S3Api, SseConfig};
use minio_common::test_context::TestContext;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn set_get_delete_bucket_encryption() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let config = SseConfig::default();

View File

@@ -13,17 +13,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper};
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::BucketExistsResponse;
use minio::s3::types::S3Api;
use minio_common::test_context::TestContext;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn bucket_exists() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let resp: BucketExistsResponse = ctx.client.bucket_exists(&bucket_name).send().await.unwrap();

View File

@@ -13,41 +13,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper};
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
DeleteBucketLifecycleResponse, GetBucketLifecycleResponse, SetBucketLifecycleResponse,
};
use minio::s3::types::{Filter, LifecycleConfig, LifecycleRule, S3Api};
use minio::s3::types::{LifecycleConfig, S3Api};
use minio_common::example::create_bucket_lifecycle_config_examples;
use minio_common::test_context::TestContext;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn set_get_delete_bucket_lifecycle() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let config: LifecycleConfig = LifecycleConfig {
rules: vec![LifecycleRule {
abort_incomplete_multipart_upload_days_after_initiation: None,
expiration_date: None,
expiration_days: Some(365),
expiration_expired_object_delete_marker: None,
filter: Filter {
and_operator: None,
prefix: Some(String::from("logs/")),
tag: None,
},
id: String::from("rule1"),
noncurrent_version_expiration_noncurrent_days: None,
noncurrent_version_transition_noncurrent_days: None,
noncurrent_version_transition_storage_class: None,
status: true,
transition_date: None,
transition_days: None,
transition_storage_class: None,
}],
};
let config: LifecycleConfig = create_bucket_lifecycle_config_examples();
let resp: SetBucketLifecycleResponse = ctx
.client

View File

@@ -1,39 +1,34 @@
mod common;
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
// Copyright 2025 MinIO, Inc.
//
// 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::{TestContext, create_bucket_helper};
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
DeleteBucketNotificationResponse, GetBucketNotificationResponse, SetBucketNotificationResponse,
};
use minio::s3::types::{
NotificationConfig, PrefixFilterRule, QueueConfig, S3Api, SuffixFilterRule,
};
use minio::s3::types::{NotificationConfig, S3Api};
use minio_common::example::create_bucket_notification_config_example;
use minio_common::test_context::TestContext;
const SQS_ARN: &str = "arn:minio:sqs::miniojavatest:webhook";
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn set_get_delete_bucket_notification() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let config = NotificationConfig {
cloud_func_config_list: None,
queue_config_list: Some(vec![QueueConfig {
events: vec![
String::from("s3:ObjectCreated:Put"),
String::from("s3:ObjectCreated:Copy"),
],
id: Some("".to_string()), //TODO or should this be NONE??
prefix_filter_rule: Some(PrefixFilterRule {
value: String::from("images"),
}),
suffix_filter_rule: Some(SuffixFilterRule {
value: String::from("pg"),
}),
queue: String::from(SQS_ARN),
}]),
topic_config_list: None,
};
let config: NotificationConfig = create_bucket_notification_config_example();
let resp: SetBucketNotificationResponse = ctx
.client

View File

@@ -1,40 +1,32 @@
use crate::common::{TestContext, create_bucket_helper};
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
// Copyright 2025 MinIO, Inc.
//
// 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 minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
DeleteBucketPolicyResponse, GetBucketPolicyResponse, SetBucketPolicyResponse,
};
use minio::s3::types::S3Api;
mod common;
use minio_common::example::create_bucket_policy_config_example;
use minio_common::test_context::TestContext;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn set_get_delete_bucket_policy() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let config = r#"
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Resource": [
"arn:aws:s3:::<BUCKET>/myobject*"
],
"Sid": ""
}
]
}
"#
.replace("<BUCKET>", &bucket_name);
let config: String = create_bucket_policy_config_example(&bucket_name);
let resp: SetBucketPolicyResponse = ctx
.client

View File

@@ -13,81 +13,82 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper};
use minio::s3::builders::VersioningStatus;
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
DeleteBucketReplicationResponse, GetBucketReplicationResponse, GetBucketVersioningResponse,
SetBucketReplicationResponse, SetBucketVersioningResponse,
SetBucketPolicyResponse, SetBucketReplicationResponse, SetBucketVersioningResponse,
};
use minio::s3::types::{
AndOperator, Destination, Filter, ReplicationConfig, ReplicationRule, S3Api,
use minio::s3::types::{ReplicationConfig, S3Api};
use minio_common::example::{
create_bucket_policy_config_example_for_replication, create_bucket_replication_config_example,
};
use std::collections::HashMap;
use minio_common::test_context::TestContext;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn set_get_delete_bucket_replication() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let mut tags: HashMap<String, String> = HashMap::new();
tags.insert(String::from("key1"), String::from("value1"));
tags.insert(String::from("key2"), String::from("value2"));
let ctx2 = TestContext::new_from_env();
let (bucket_name2, _cleanup2) = ctx2.create_bucket_helper().await;
let config = ReplicationConfig {
role: Some("example1".to_string()),
rules: vec![ReplicationRule {
destination: Destination {
bucket_arn: String::from("REPLACE-WITH-ACTUAL-DESTINATION-BUCKET-ARN"),
access_control_translation: None,
account: None,
encryption_config: None,
metrics: None,
replication_time: None,
storage_class: None,
},
delete_marker_replication_status: None,
existing_object_replication_status: None,
filter: Some(Filter {
and_operator: Some(AndOperator {
prefix: Some(String::from("TaxDocs")),
tags: Some(tags),
}),
prefix: None,
tag: None,
}),
id: Some(String::from("rule1")),
prefix: None,
priority: Some(1),
source_selection_criteria: None,
delete_replication_status: Some(false),
status: true,
}],
};
{
let resp: SetBucketVersioningResponse = ctx
.client
.set_bucket_versioning(&bucket_name)
.versioning_status(VersioningStatus::Enabled)
.send()
.await
.unwrap();
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.region, DEFAULT_REGION);
let resp: SetBucketVersioningResponse = ctx
.client
.set_bucket_versioning(&bucket_name)
.versioning_status(VersioningStatus::Enabled)
.send()
.await
.unwrap();
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.region, DEFAULT_REGION);
let resp: SetBucketVersioningResponse = ctx
.client
.set_bucket_versioning(&bucket_name2)
.versioning_status(VersioningStatus::Enabled)
.send()
.await
.unwrap();
assert_eq!(resp.bucket, bucket_name2);
assert_eq!(resp.region, DEFAULT_REGION);
let resp: GetBucketVersioningResponse = ctx
.client
.get_bucket_versioning(&bucket_name)
.send()
.await
.unwrap();
assert_eq!(resp.status, Some(VersioningStatus::Enabled));
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.region, DEFAULT_REGION);
let resp: GetBucketVersioningResponse = ctx
.client
.get_bucket_versioning(&bucket_name)
.send()
.await
.unwrap();
assert_eq!(resp.status, Some(VersioningStatus::Enabled));
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.region, DEFAULT_REGION);
if false {
//TODO: to allow replication policy needs to be applied, but this fails
let config: String = create_bucket_policy_config_example_for_replication();
let _resp: SetBucketPolicyResponse = ctx
.client
.set_bucket_policy(&bucket_name)
.config(config.clone())
.send()
.await
.unwrap();
let _resp: SetBucketPolicyResponse = ctx
.client
.set_bucket_policy(&bucket_name2)
.config(config.clone())
.send()
.await
.unwrap();
}
}
let config: ReplicationConfig = create_bucket_replication_config_example(&bucket_name2);
if false {
//TODO setup permissions that allow replication
// TODO panic: called `Result::unwrap()` on an `Err` value: S3Error(ErrorResponse { code: "XMinioAdminRemoteTargetNotFoundError", message: "The remote target does not exist",
let resp: SetBucketReplicationResponse = ctx
.client

View File

@@ -13,23 +13,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper};
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{DeleteBucketTagsResponse, GetBucketTagsResponse, SetBucketTagsResponse};
use minio::s3::types::S3Api;
use std::collections::HashMap;
use minio_common::example::create_tags_example;
use minio_common::test_context::TestContext;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn set_get_delete_bucket_tags() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let tags = HashMap::from([
(String::from("Project"), String::from("Project One")),
(String::from("User"), String::from("jsmith")),
]);
let tags = create_tags_example();
let resp: SetBucketTagsResponse = ctx
.client

View File

@@ -13,18 +13,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper};
use minio::s3::builders::VersioningStatus;
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{GetBucketVersioningResponse, SetBucketVersioningResponse};
use minio::s3::types::S3Api;
use minio_common::test_context::TestContext;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn set_get_delete_bucket_versioning() {
async fn set_get_bucket_versioning() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let resp: SetBucketVersioningResponse = ctx
.client

View File

@@ -13,16 +13,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use bytes::Bytes;
use minio::s3::types::S3Api;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn get_object() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let data = Bytes::from("hello, world".to_string().into_bytes());
@@ -39,9 +38,4 @@ async fn get_object() {
.unwrap();
let got = resp.content.to_segmented_bytes().await.unwrap().to_bytes();
assert_eq!(got, data);
ctx.client
.remove_object(&bucket_name, object_name.as_str())
.send()
.await
.unwrap();
}

View File

@@ -13,18 +13,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use http::Method;
use minio::s3::args::GetPresignedObjectUrlArgs;
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::GetPresignedObjectUrlResponse;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn get_presigned_object_url() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let resp: GetPresignedObjectUrlResponse = ctx

View File

@@ -13,26 +13,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use minio::s3::args::PostPolicy;
use minio::s3::utils::utc_now;
use minio_common::example::create_post_policy_example;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
use std::collections::HashMap;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn get_presigned_post_form_data() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let expiration = utc_now() + chrono::Duration::days(5);
let mut policy = PostPolicy::new(&bucket_name, &expiration).unwrap();
policy.add_equals_condition("key", &object_name).unwrap();
policy
.add_content_length_range_condition(1024 * 1024, 4 * 1024 * 1024)
.unwrap();
let policy: PostPolicy = create_post_policy_example(&bucket_name, &object_name);
let form_data: HashMap<String, String> = ctx
.client

View File

@@ -1,5 +1,3 @@
use crate::common::{CleanupGuard, TestContext, create_bucket_helper};
use minio::s3::response::ListBucketsResponse;
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
// Copyright 2025 MinIO, Inc.
//
@@ -15,9 +13,10 @@ use minio::s3::response::ListBucketsResponse;
// See the License for the specific language governing permissions and
// limitations under the License.
use minio::s3::response::ListBucketsResponse;
use minio::s3::types::S3Api;
mod common;
use minio_common::cleanup_guard::CleanupGuard;
use minio_common::test_context::TestContext;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn list_buckets() {
@@ -27,7 +26,7 @@ async fn list_buckets() {
let mut names: Vec<String> = Vec::new();
let mut guards: Vec<CleanupGuard> = Vec::new();
for _ in 1..=N_BUCKETS {
let (bucket_name, guard) = create_bucket_helper(&ctx).await;
let (bucket_name, guard) = ctx.create_bucket_helper().await;
names.push(bucket_name);
guards.push(guard);
}

View File

@@ -13,23 +13,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use minio::s3::builders::ObjectToDelete;
use minio::s3::response::PutObjectContentResponse;
use minio::s3::types::ToStream;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
use tokio_stream::StreamExt;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn list_objects() {
async fn list_objects(use_api_v1: bool, include_versions: bool) {
const N_OBJECTS: usize = 3;
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let mut names: Vec<String> = Vec::new();
for _ in 1..=N_OBJECTS {
let object_name = rand_object_name();
let object_name: String = rand_object_name();
let resp: PutObjectContentResponse = ctx
.client
.put_object_content(&bucket_name, &object_name, "hello world")
@@ -37,10 +34,17 @@ async fn list_objects() {
.await
.unwrap();
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.object, object_name);
names.push(object_name);
}
let mut stream = ctx.client.list_objects(&bucket_name).to_stream().await;
let mut stream = ctx
.client
.list_objects(&bucket_name)
.use_api_v1(use_api_v1)
.include_versions(include_versions)
.to_stream()
.await;
let mut count = 0;
while let Some(items) = stream.next().await {
@@ -51,22 +55,24 @@ async fn list_objects() {
}
}
assert_eq!(count, N_OBJECTS);
let del_items: Vec<ObjectToDelete> = names
.iter()
.map(|v| ObjectToDelete::from(v.as_str()))
.collect();
let mut resp = ctx
.client
.remove_objects(&bucket_name, del_items.into_iter())
.verbose_mode(true)
.to_stream()
.await;
while let Some(item) = resp.next().await {
let res = item.unwrap();
for obj in res.result.iter() {
assert!(obj.is_deleted());
}
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn list_objects_v1_no_versions() {
list_objects(true, false).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn list_objects_v1_with_versions() {
list_objects(true, true).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn list_objects_v2_no_versions() {
list_objects(false, false).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn list_objects_v2_with_versions() {
list_objects(false, true).await;
}

View File

@@ -13,22 +13,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use async_std::task;
use common::RandSrc;
use minio::s3::Client;
use minio::s3::builders::ObjectContent;
use minio::s3::creds::StaticProvider;
use minio::s3::types::{NotificationRecords, S3Api};
use minio_common::rand_src::RandSrc;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
use tokio::sync::mpsc;
use tokio_stream::StreamExt;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn listen_bucket_notification() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let name = object_name.clone();

View File

@@ -13,18 +13,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use common::RandSrc;
use minio::s3::args::{ComposeObjectArgs, ComposeSource, StatObjectArgs};
use minio::s3::builders::ObjectContent;
use minio::s3::types::S3Api;
use minio_common::rand_src::RandSrc;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn compose_object() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let src_object_name = rand_object_name();
let size = 16_u64;
@@ -57,15 +55,4 @@ async fn compose_object() {
.await
.unwrap();
assert_eq!(resp.size, 5);
ctx.client
.remove_object(&bucket_name, object_name.as_str())
.send()
.await
.unwrap();
ctx.client
.remove_object(&bucket_name, src_object_name.as_str())
.send()
.await
.unwrap();
}

View File

@@ -13,22 +13,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use common::RandSrc;
use minio::s3::args::{CopyObjectArgs, CopySource, StatObjectArgs};
use minio::s3::builders::ObjectContent;
use minio::s3::types::S3Api;
use minio_common::rand_src::RandSrc;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn copy_object() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let src_object_name = rand_object_name();
let size = 16_u64;
let content = ObjectContent::new_from_stream(RandSrc::new(size), Some(size));
let n_bytes = 16_u64;
let content = ObjectContent::new_from_stream(RandSrc::new(n_bytes), Some(n_bytes));
ctx.client
.put_object_content(&bucket_name, &src_object_name, content)
.send()
@@ -53,16 +51,5 @@ async fn copy_object() {
.stat_object(&StatObjectArgs::new(&bucket_name, &object_name).unwrap())
.await
.unwrap();
assert_eq!(resp.size as u64, size);
ctx.client
.remove_object(&bucket_name, object_name.as_str())
.send()
.await
.unwrap();
ctx.client
.remove_object(&bucket_name, src_object_name.as_str())
.send()
.await
.unwrap();
assert_eq!(resp.size as u64, n_bytes);
}

View File

@@ -13,9 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{CleanupGuard, TestContext, rand_bucket_name, rand_object_name};
use bytes::Bytes;
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
@@ -23,6 +20,9 @@ use minio::s3::response::{
IsObjectLegalHoldEnabledResponse, MakeBucketResponse, PutObjectContentResponse,
};
use minio::s3::types::S3Api;
use minio_common::cleanup_guard::CleanupGuard;
use minio_common::test_context::TestContext;
use minio_common::utils::{rand_bucket_name, rand_object_name};
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn object_legal_hold() {
@@ -35,7 +35,7 @@ async fn object_legal_hold() {
.send()
.await
.unwrap();
let _cleanup = CleanupGuard::new(&ctx, &bucket_name);
let _cleanup = CleanupGuard::new(&ctx.client, &bucket_name);
let object_name = rand_object_name();
let data = Bytes::from("hello, world".to_string().into_bytes());
@@ -58,7 +58,7 @@ async fn object_legal_hold() {
.await
.unwrap();
//println!("response of setting object legal hold: resp={:?}", resp);
assert_eq!(resp.object_name, object_name);
assert_eq!(resp.object, object_name);
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.region, DEFAULT_REGION);
assert_eq!(resp.version_id, None);
@@ -72,7 +72,7 @@ async fn object_legal_hold() {
.unwrap();
//println!("response of getting object legal hold: resp={:?}", resp);
assert!(!resp.enabled);
assert_eq!(resp.object_name, object_name);
assert_eq!(resp.object, object_name);
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.region, DEFAULT_REGION);
assert_eq!(resp.version_id, None);
@@ -85,7 +85,7 @@ async fn object_legal_hold() {
.await
.unwrap();
//println!("response of setting object legal hold: resp={:?}", resp);
assert_eq!(resp.object_name, object_name);
assert_eq!(resp.object, object_name);
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.region, DEFAULT_REGION);
assert_eq!(resp.version_id, None);
@@ -99,7 +99,7 @@ async fn object_legal_hold() {
.unwrap();
//println!("response of getting object legal hold: resp={:?}", resp);
assert!(resp.enabled);
assert_eq!(resp.object_name, object_name);
assert_eq!(resp.object, object_name);
assert_eq!(resp.bucket, bucket_name);
assert_eq!(resp.region, DEFAULT_REGION);
assert_eq!(resp.version_id, None);

View File

@@ -13,14 +13,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{CleanupGuard, TestContext, rand_bucket_name};
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
DeleteObjectLockConfigResponse, GetObjectLockConfigResponse, SetObjectLockConfigResponse,
};
use minio::s3::types::{ObjectLockConfig, RetentionMode, S3Api};
use minio_common::cleanup_guard::CleanupGuard;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_bucket_name;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn set_get_delete_object_lock_config() {
@@ -32,7 +32,7 @@ async fn set_get_delete_object_lock_config() {
.send()
.await
.unwrap();
let _cleanup = CleanupGuard::new(&ctx, &bucket_name);
let _cleanup = CleanupGuard::new(&ctx.client, &bucket_name);
const DURATION_DAYS: i32 = 7;
let config =

View File

@@ -13,20 +13,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{RandSrc, TestContext, create_bucket_helper, rand_object_name};
use http::header;
use minio::s3::args::StatObjectArgs;
use minio::s3::builders::ObjectContent;
use minio::s3::error::Error;
use minio::s3::response::{PutObjectContentResponse, RemoveObjectResponse, StatObjectResponse};
use minio::s3::types::S3Api;
use minio_common::rand_src::RandSrc;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
use tokio::sync::mpsc;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn put_object() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let size = 16_u64;
@@ -68,7 +69,7 @@ async fn put_object() {
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn put_object_multipart() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let size: u64 = 16 + 5 * 1024 * 1024;
@@ -98,29 +99,27 @@ async fn put_object_multipart() {
}
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn put_object_content() {
async fn put_object_content_1() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let sizes = [16_u64, 5 * 1024 * 1024, 16 + 5 * 1024 * 1024];
for size in sizes.iter() {
let data_src = RandSrc::new(*size);
let rsp = ctx
let resp: PutObjectContentResponse = ctx
.client
.put_object_content(
&bucket_name,
&object_name,
ObjectContent::new_from_stream(data_src, Some(*size)),
ObjectContent::new_from_stream(RandSrc::new(*size), Some(*size)),
)
.content_type(String::from("image/jpeg"))
.send()
.await
.unwrap();
assert_eq!(rsp.object_size, *size);
let etag = rsp.etag;
let resp = ctx
assert_eq!(resp.object_size, *size);
let etag = resp.etag;
let resp: StatObjectResponse = ctx
.client
.stat_object(&StatObjectArgs::new(&bucket_name, &object_name).unwrap())
.await
@@ -131,12 +130,22 @@ async fn put_object_content() {
resp.headers.get(header::CONTENT_TYPE).unwrap(),
"image/jpeg"
);
ctx.client
let resp: RemoveObjectResponse = ctx
.client
.remove_object(&bucket_name, object_name.as_str())
.send()
.await
.unwrap();
assert!(!resp.is_delete_marker);
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn put_object_content_2() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let sizes = [16_u64, 5 * 1024 * 1024, 16 + 5 * 1024 * 1024];
// Repeat test with no size specified in ObjectContent
for size in sizes.iter() {
@@ -169,11 +178,11 @@ async fn put_object_content() {
}
}
/// Test sending ObjectContent across async tasks.
/// Test sending PutObject across async tasks.
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn put_object_content_2() {
async fn put_object_content_3() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let sizes = vec![16_u64, 5 * 1024 * 1024, 16 + 5 * 1024 * 1024];
@@ -201,14 +210,14 @@ async fn put_object_content_2() {
tokio::spawn(async move {
let mut idx = 0;
while let Some(item) = receiver.recv().await {
let rsp = client
let resp: PutObjectContentResponse = client
.put_object_content(&test_bucket, &object_name, item)
.send()
.await
.unwrap();
assert_eq!(rsp.object_size, sizes[idx]);
let etag = rsp.etag;
let resp = client
assert_eq!(resp.object_size, sizes[idx]);
let etag = resp.etag;
let resp: StatObjectResponse = client
.stat_object(&StatObjectArgs::new(&test_bucket, &object_name).unwrap())
.await
.unwrap();

View File

@@ -13,18 +13,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use minio::s3::builders::ObjectToDelete;
use minio::s3::response::PutObjectContentResponse;
use minio::s3::types::ToStream;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
use tokio_stream::StreamExt;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn remove_objects() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let mut names: Vec<String> = Vec::new();
for _ in 1..=3 {

View File

@@ -13,18 +13,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{CleanupGuard, TestContext, rand_bucket_name, rand_object_name};
use common::RandSrc;
use minio::s3::builders::ObjectContent;
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
GetObjectRetentionResponse, MakeBucketResponse, PutObjectContentResponse, RemoveObjectResponse,
GetObjectRetentionResponse, MakeBucketResponse, PutObjectContentResponse,
SetObjectRetentionResponse,
};
use minio::s3::types::{RetentionMode, S3Api};
use minio::s3::utils::{to_iso8601utc, utc_now};
use minio_common::cleanup_guard::CleanupGuard;
use minio_common::rand_src::RandSrc;
use minio_common::test_context::TestContext;
use minio_common::utils::{rand_bucket_name, rand_object_name};
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn object_retention() {
@@ -37,7 +37,7 @@ async fn object_retention() {
.send()
.await
.unwrap();
let _cleanup = CleanupGuard::new(&ctx, &bucket_name);
let _cleanup = CleanupGuard::new(&ctx.client, &bucket_name);
assert_eq!(resp.bucket, bucket_name);
let object_name = rand_object_name();
@@ -57,7 +57,7 @@ async fn object_retention() {
assert_eq!(resp.object, object_name);
assert_eq!(resp.object_size, size);
//assert_eq!(resp.version_id, None);
assert_eq!(resp.location, "");
assert_eq!(resp.region, "");
//assert_eq!(resp.etag, "");
let retain_until_date = utc_now() + chrono::Duration::days(1);
@@ -114,16 +114,4 @@ async fn object_retention() {
assert_eq!(resp.version_id, None);
assert_eq!(resp.region, DEFAULT_REGION);
assert_eq!(resp.object, object_name);
let resp: RemoveObjectResponse = ctx
.client
.remove_object(
&bucket_name,
(object_name.as_str(), obj_resp.version_id.as_deref()),
)
.send()
.await
.unwrap();
//assert_eq!(resp.version_id, None);
assert!(resp.is_delete_marker);
}

View File

@@ -13,23 +13,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use common::RandSrc;
use minio::s3::builders::ObjectContent;
use minio::s3::client::DEFAULT_REGION;
use minio::s3::response::{
DeleteObjectTagsResponse, GetObjectTagsResponse, PutObjectContentResponse,
RemoveObjectResponse, SetObjectTagsResponse,
SetObjectTagsResponse,
};
use minio::s3::types::S3Api;
use minio_common::rand_src::RandSrc;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
use std::collections::HashMap;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn object_tags() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let size = 16_u64;
@@ -47,7 +46,7 @@ async fn object_tags() {
assert_eq!(resp.object, object_name);
assert_eq!(resp.object_size, size);
assert_eq!(resp.version_id, None);
assert_eq!(&resp.location, "");
assert_eq!(&resp.region, "");
let tags = HashMap::from([
(String::from("Project"), String::from("Project One")),
@@ -104,13 +103,4 @@ async fn object_tags() {
assert_eq!(resp.object, object_name);
assert_eq!(resp.version_id, None);
assert_eq!(resp.region, DEFAULT_REGION);
let resp: RemoveObjectResponse = ctx
.client
.remove_object(&bucket_name, object_name.as_str())
.send()
.await
.unwrap();
assert_eq!(resp.version_id, None);
assert!(!resp.is_delete_marker)
}

View File

@@ -13,20 +13,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{TestContext, create_bucket_helper, rand_object_name};
use minio::s3::args::SelectObjectContentArgs;
use minio::s3::response::RemoveObjectResponse;
use minio::s3::types::{
CsvInputSerialization, CsvOutputSerialization, FileHeaderInfo, QuoteFields, S3Api,
SelectRequest,
CsvInputSerialization, CsvOutputSerialization, FileHeaderInfo, QuoteFields, SelectRequest,
};
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn select_object_content() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let mut data = String::new();
@@ -81,11 +78,4 @@ async fn select_object_content() {
got += core::str::from_utf8(&buf[..size]).unwrap();
}
assert_eq!(got, data);
let resp: RemoveObjectResponse = ctx
.client
.remove_object(&bucket_name, object_name.as_str())
.send()
.await
.unwrap();
assert!(!resp.is_delete_marker);
}

View File

@@ -13,12 +13,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
mod common;
use crate::common::{RandReader, TestContext, create_bucket_helper, rand_object_name};
use hex::ToHex;
use minio::s3::response::PutObjectContentResponse;
use minio::s3::types::S3Api;
use minio_common::rand_reader::RandReader;
use minio_common::test_context::TestContext;
use minio_common::utils::rand_object_name;
#[cfg(feature = "ring")]
use ring::digest::{Context, SHA256};
#[cfg(not(feature = "ring"))]
@@ -50,7 +50,7 @@ fn get_hash(filename: &String) -> String {
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
async fn upload_download_object() {
let ctx = TestContext::new_from_env();
let (bucket_name, _cleanup) = create_bucket_helper(&ctx).await;
let (bucket_name, _cleanup) = ctx.create_bucket_helper().await;
let object_name = rand_object_name();
let size = 16_u64;
@@ -128,18 +128,4 @@ async fn upload_download_object() {
.await
.unwrap();
assert_eq!(get_hash(&object_name), get_hash(&filename));
fs::remove_file(&object_name).unwrap();
fs::remove_file(&filename).unwrap();
ctx.client
.remove_object(&bucket_name, object_name.as_str())
.send()
.await
.unwrap();
ctx.client
.remove_object(&bucket_name, object_name.as_str())
.send()
.await
.unwrap();
}