Skip to content

Commit 8497fdb

Browse files
authored
feat: add a test macro (#170)
1 parent 720943b commit 8497fdb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+661
-460
lines changed

.github/workflows/rust.yml

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,53 @@ env:
1111
CARGO_TERM_COLOR: always
1212

1313
jobs:
14-
build:
14+
check-format:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Check format
19+
run: |
20+
cargo fmt --all -- --check
1521
22+
clippy:
1623
runs-on: ubuntu-latest
17-
timeout-minutes: 5
24+
steps:
25+
- uses: actions/checkout@v4
26+
- name: clippy
27+
run: cargo clippy --all-targets --all-features --workspace -- -D warnings
28+
test-multi-thread:
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
- name: Run tests
33+
run: |
34+
./tests/start-server.sh
35+
export SERVER_ENDPOINT=localhost:9000
36+
export ACCESS_KEY=minioadmin
37+
export SECRET_KEY=minioadmin
38+
export ENABLE_HTTPS=1
39+
export MINIO_SSL_CERT_FILE=./tests/public.crt
40+
MINIO_TEST_TOKIO_RUNTIME_FLAVOR="multi_thread" cargo test -- --nocapture
41+
test-current-thread:
42+
runs-on: ubuntu-latest
43+
steps:
44+
- uses: actions/checkout@v4
45+
- name: Run tests
46+
run: |
47+
./tests/start-server.sh
48+
export SERVER_ENDPOINT=localhost:9000
49+
export ACCESS_KEY=minioadmin
50+
export SECRET_KEY=minioadmin
51+
export ENABLE_HTTPS=1
52+
export MINIO_SSL_CERT_FILE=./tests/public.crt
53+
MINIO_TEST_TOKIO_RUNTIME_FLAVOR="current_thread" cargo test -- --nocapture
1854
55+
build:
56+
runs-on: ubuntu-latest
57+
timeout-minutes: 5
1958
steps:
2059
- uses: actions/checkout@v4
2160
- name: Build
2261
run: |
2362
cargo --version
24-
cargo fmt --all -- --check
25-
cargo clippy --all-targets --all-features
2663
cargo build --bins --examples --tests --benches --verbose
27-
28-
- name: Run tests
29-
run: |
30-
./tests/start-server.sh
31-
export SERVER_ENDPOINT=localhost:9000
32-
export ACCESS_KEY=minioadmin
33-
export SECRET_KEY=minioadmin
34-
export ENABLE_HTTPS=1
35-
export SSL_CERT_FILE=./tests/public.crt
36-
cargo test --verbose -- --nocapture

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ async-std = { version = "1.13.1", features = ["attributes", "tokio1"] }
6262
clap = { version = "4.5.40", features = ["derive"] }
6363
quickcheck = "1.0.3"
6464
criterion = "0.6.0"
65+
minio-macros = { path = "./macros" }
6566

6667
[lib]
6768
name = "minio"

benches/s3/api_benchmarks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
15+
#![allow(unused_must_use)]
1516

1617
mod bench_bucket_exists;
1718
mod bench_bucket_lifecycle;

benches/s3/bench_bucket_replication.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub(crate) fn bench_put_bucket_replication(criterion: &mut Criterion) {
4242

4343
let _resp: PutBucketVersioningResponse = ctx
4444
.client
45-
.put_bucket_versioning(&ctx.aux_bucket.clone().unwrap())
45+
.put_bucket_versioning(ctx.aux_bucket.clone().unwrap())
4646
.versioning_status(VersioningStatus::Enabled)
4747
.send()
4848
.await
@@ -77,7 +77,7 @@ pub(crate) fn bench_get_bucket_replication(criterion: &mut Criterion) {
7777

7878
let _resp: PutBucketVersioningResponse = ctx
7979
.client
80-
.put_bucket_versioning(&ctx.aux_bucket.clone().unwrap())
80+
.put_bucket_versioning(ctx.aux_bucket.clone().unwrap())
8181
.versioning_status(VersioningStatus::Enabled)
8282
.send()
8383
.await
@@ -107,7 +107,7 @@ pub(crate) fn bench_delete_bucket_replication(criterion: &mut Criterion) {
107107

108108
let _resp: PutBucketVersioningResponse = ctx
109109
.client
110-
.put_bucket_versioning(&ctx.aux_bucket.clone().unwrap())
110+
.put_bucket_versioning(ctx.aux_bucket.clone().unwrap())
111111
.versioning_status(VersioningStatus::Enabled)
112112
.send()
113113
.await

benches/s3/common_benches.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl Ctx2 {
4040
/// Create a new context with a bucket
4141
pub async fn new() -> Self {
4242
unsafe {
43-
env::set_var("SSL_CERT_FILE", "./tests/public.crt");
43+
env::set_var("MINIO_SSL_CERT_FILE", "./tests/public.crt");
4444
}
4545
let ctx = TestContext::new_from_env();
4646
let (bucket_name, cleanup) = ctx.create_bucket_helper().await;
@@ -57,7 +57,7 @@ impl Ctx2 {
5757
/// Create a new context with a bucket and an object
5858
pub async fn new_with_object(object_lock: bool) -> Self {
5959
unsafe {
60-
env::set_var("SSL_CERT_FILE", "./tests/public.crt");
60+
env::set_var("MINIO_SSL_CERT_FILE", "./tests/public.crt");
6161
}
6262
let ctx = TestContext::new_from_env();
6363
let bucket_name: String = rand_bucket_name();

common/src/cleanup_guard.rs

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16-
use async_std::future::timeout;
1716
use minio::s3::Client;
1817

19-
use std::thread;
20-
2118
/// Cleanup guard that removes the bucket when it is dropped
2219
pub struct CleanupGuard {
2320
client: Client,
@@ -32,41 +29,26 @@ impl CleanupGuard {
3229
bucket_name: bucket_name.into(),
3330
}
3431
}
35-
}
36-
37-
impl Drop for CleanupGuard {
38-
fn drop(&mut self) {
39-
let client = self.client.clone();
40-
let bucket_name = self.bucket_name.clone();
41-
//println!("Going to remove bucket {}", bucket_name);
4232

43-
// Spawn the cleanup task in a way that detaches it from the current runtime
44-
thread::spawn(move || {
45-
// Create a new runtime for this thread
46-
let rt = tokio::runtime::Runtime::new().unwrap();
33+
pub async fn cleanup(&self) {
34+
cleanup(self.client.clone(), &self.bucket_name).await;
35+
}
36+
}
4737

48-
// Execute the async cleanup in this new runtime
49-
rt.block_on(async {
50-
// do the actual removal of the bucket
51-
match timeout(
52-
std::time::Duration::from_secs(60),
53-
client.delete_and_purge_bucket(&bucket_name),
54-
)
55-
.await
56-
{
57-
Ok(result) => match result {
38+
pub async fn cleanup(client: Client, bucket_name: &str) {
39+
tokio::select!(
40+
_ = tokio::time::sleep(std::time::Duration::from_secs(60)) => {
41+
eprintln!("Cleanup timeout after 60s while removing bucket {}", bucket_name);
42+
},
43+
outcome = client.delete_and_purge_bucket(bucket_name) => {
44+
match outcome {
5845
Ok(_) => {
59-
//println!("Bucket {} removed successfully", bucket_name),
46+
eprintln!("Bucket {} removed successfully", bucket_name);
6047
}
61-
Err(_e) => {
62-
//println!("Error removing bucket {}: {:?}", bucket_name, e)
48+
Err(e) => {
49+
eprintln!("Error removing bucket {}: {:?}", bucket_name, e);
6350
}
64-
},
65-
Err(_) => println!("Timeout after 60s while removing bucket {}", bucket_name),
51+
}
6652
}
67-
});
68-
})
69-
.join()
70-
.unwrap(); // This blocks the current thread until cleanup is done
71-
}
53+
);
7254
}

common/src/rand_reader.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16+
use futures::AsyncRead;
1617
use std::io;
18+
use std::pin::Pin;
19+
use std::task::{Context, Poll};
1720

1821
pub struct RandReader {
1922
size: u64,
@@ -28,10 +31,7 @@ impl RandReader {
2831

2932
impl io::Read for RandReader {
3033
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
31-
let bytes_read: usize = match (self.size as usize) > buf.len() {
32-
true => buf.len(),
33-
false => self.size as usize,
34-
};
34+
let bytes_read = buf.len().min(self.size as usize);
3535

3636
if bytes_read > 0 {
3737
let random: &mut dyn rand::RngCore = &mut rand::thread_rng();
@@ -43,3 +43,22 @@ impl io::Read for RandReader {
4343
Ok(bytes_read)
4444
}
4545
}
46+
47+
impl AsyncRead for RandReader {
48+
fn poll_read(
49+
self: Pin<&mut Self>,
50+
_cx: &mut Context<'_>,
51+
buf: &mut [u8],
52+
) -> Poll<io::Result<usize>> {
53+
let bytes_read = buf.len().min(self.size as usize);
54+
55+
if bytes_read > 0 {
56+
let random: &mut dyn rand::RngCore = &mut rand::thread_rng();
57+
random.fill_bytes(&mut buf[0..bytes_read]);
58+
}
59+
60+
self.get_mut().size -= bytes_read as u64;
61+
62+
Poll::Ready(Ok(bytes_read))
63+
}
64+
}

common/src/rand_src.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
// limitations under the License.
1515

1616
use async_std::stream::Stream;
17-
use async_std::task;
1817
use bytes::Bytes;
1918
use futures::io::AsyncRead;
2019
use rand::prelude::SmallRng;
@@ -41,26 +40,21 @@ impl Stream for RandSrc {
4140

4241
fn poll_next(
4342
self: std::pin::Pin<&mut Self>,
44-
_cx: &mut task::Context<'_>,
45-
) -> task::Poll<Option<Self::Item>> {
43+
_cx: &mut Context<'_>,
44+
) -> Poll<Option<Self::Item>> {
4645
if self.size == 0 {
47-
return task::Poll::Ready(None);
46+
return Poll::Ready(None);
4847
}
49-
50-
let bytes_read = match self.size > 64 * 1024 {
51-
true => 64 * 1024,
52-
false => self.size as usize,
53-
};
48+
// Limit to 8 KiB per read
49+
let bytes_read = self.size.min(8 * 1024) as usize;
5450

5551
let this = self.get_mut();
5652

5753
let mut buf = vec![0; bytes_read];
5854
let random: &mut dyn rand::RngCore = &mut this.rng;
5955
random.fill_bytes(&mut buf);
60-
6156
this.size -= bytes_read as u64;
62-
63-
task::Poll::Ready(Some(Ok(Bytes::from(buf))))
57+
Poll::Ready(Some(Ok(Bytes::from(buf))))
6458
}
6559
}
6660

common/src/test_context.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl TestContext {
4242
let access_key = std::env::var("ACCESS_KEY").unwrap();
4343
let secret_key = std::env::var("SECRET_KEY").unwrap();
4444
let secure = std::env::var("ENABLE_HTTPS").is_ok();
45-
let value = std::env::var("SSL_CERT_FILE").unwrap();
45+
let value = std::env::var("MINIO_SSL_CERT_FILE").unwrap();
4646
let mut ssl_cert_file = None;
4747
if !value.is_empty() {
4848
ssl_cert_file = Some(Path::new(&value));
@@ -97,8 +97,8 @@ impl TestContext {
9797
.unwrap_or(false);
9898
log::debug!("ENABLE_HTTPS={}", secure);
9999
let ssl_cert: String =
100-
std::env::var("SSL_CERT_FILE").unwrap_or(DEFAULT_SSL_CERT_FILE.to_string());
101-
log::debug!("SSL_CERT_FILE={}", ssl_cert);
100+
std::env::var("MINIO_SSL_CERT_FILE").unwrap_or(DEFAULT_SSL_CERT_FILE.to_string());
101+
log::debug!("MINIO_SSL_CERT_FILE={}", ssl_cert);
102102
let ssl_cert_file: PathBuf = ssl_cert.into();
103103
let ignore_cert_check: bool = std::env::var("IGNORE_CERT_CHECK")
104104
.unwrap_or(DEFAULT_IGNORE_CERT_CHECK.to_string())

macros/Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "minio-macros"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
[lib]
8+
proc-macro = true
9+
10+
11+
[dependencies]
12+
syn = "2.0.53"
13+
proc-macro2 = "1.0.37"
14+
quote = "1.0.18"
15+
darling = "0.20.8"
16+
darling_core = "0.20.8"
17+
uuid = { version = "1.17.0", features = ["v4"] }
18+
19+
[dev-dependencies]
20+
minio_common = { path = "../common" }

0 commit comments

Comments
 (0)