test(s3): complete snowball auto-extract compatibility (#2324)

This commit is contained in:
安正超
2026-03-29 19:19:45 +08:00
committed by GitHub
parent 3366bd2464
commit 939a69f9c2
3 changed files with 234 additions and 16 deletions
@@ -107,6 +107,97 @@ mod tests {
Ok(())
}
#[tokio::test]
#[serial]
async fn snowball_auto_extract_supports_standard_headers_with_combined_extract_options()
-> Result<(), Box<dyn Error + Send + Sync>> {
init_logging();
let mut env = RustFSTestEnvironment::new().await?;
env.start_rustfs_server(vec![]).await?;
let client = env.create_s3_client();
let bucket = "snowball-standard-options";
let extracted_prefix = "/tenant-standard/";
client.create_bucket().bucket(bucket).send().await?;
let mut builder = tokio_tar::Builder::new(Cursor::new(Vec::new()));
let mut dir_header = tokio_tar::Header::new_gnu();
dir_header.set_entry_type(tokio_tar::EntryType::Directory);
dir_header.set_size(0);
dir_header.set_mode(0o755);
dir_header.set_cksum();
builder
.append_data(&mut dir_header, "ignored-dir/", Cursor::new(Vec::new()))
.await?;
let mut valid_header = tokio_tar::Header::new_gnu();
valid_header.set_size(b"standard-body".len() as u64);
valid_header.set_mode(0o644);
valid_header.set_cksum();
builder
.append_data(&mut valid_header, "valid.txt", Cursor::new(b"standard-body".as_slice()))
.await?;
let long_name = format!("{}.txt", "a".repeat(1100));
let mut invalid_header = tokio_tar::Header::new_gnu();
invalid_header.set_size(b"ignored-body".len() as u64);
invalid_header.set_mode(0o644);
invalid_header.set_cksum();
builder
.append_data(&mut invalid_header, long_name, Cursor::new(b"ignored-body".as_slice()))
.await?;
let archive = builder.into_inner().await?.into_inner();
client
.put_object()
.bucket(bucket)
.key("fixture.tar")
.body(ByteStream::from(archive))
.customize()
.mutate_request(move |req| {
req.headers_mut().insert("x-amz-meta-snowball-auto-extract", "true");
req.headers_mut().insert("x-amz-meta-snowball-prefix", extracted_prefix);
req.headers_mut().insert("x-amz-meta-snowball-ignore-dirs", "true");
req.headers_mut().insert("x-amz-meta-snowball-ignore-errors", "true");
})
.send()
.await?;
let valid = client
.get_object()
.bucket(bucket)
.key("tenant-standard/valid.txt")
.send()
.await?;
assert_eq!(valid.body.collect().await?.into_bytes().as_ref(), b"standard-body");
let dir_err = client
.head_object()
.bucket(bucket)
.key("tenant-standard/ignored-dir/")
.send()
.await
.expect_err("directory marker should be skipped when standard ignore-dirs=true");
let dir_service_err = dir_err.into_service_error();
assert_eq!(dir_service_err.code(), Some("NotFound"));
let listed = client
.list_objects_v2()
.bucket(bucket)
.prefix("tenant-standard/")
.send()
.await?;
let keys: Vec<_> = listed.contents().iter().filter_map(|entry| entry.key()).collect();
assert_eq!(keys, vec!["tenant-standard/valid.txt"]);
env.stop_server();
Ok(())
}
#[tokio::test]
#[serial]
async fn snowball_auto_extract_ignores_directories_when_requested() -> Result<(), Box<dyn Error + Send + Sync>> {
@@ -181,4 +272,50 @@ mod tests {
env.stop_server();
Ok(())
}
#[tokio::test]
#[serial]
async fn snowball_auto_extract_prefers_exact_minio_prefix_over_suffix_fallback() -> Result<(), Box<dyn Error + Send + Sync>> {
init_logging();
let mut env = RustFSTestEnvironment::new().await?;
env.start_rustfs_server(vec![]).await?;
let client = env.create_s3_client();
let bucket = "snowball-prefix-precedence";
let archive = build_test_archive().await?;
client.create_bucket().bucket(bucket).send().await?;
client
.put_object()
.bucket(bucket)
.key("fixture.tar")
.body(ByteStream::from(archive))
.customize()
.mutate_request(|req| {
req.headers_mut().insert("x-amz-meta-snowball-auto-extract", "true");
req.headers_mut()
.insert("x-amz-meta-acme-snowball-prefix", "/tenant-fallback/");
req.headers_mut().insert("x-amz-meta-minio-snowball-prefix", "/tenant-exact/");
})
.send()
.await?;
let exact = client.get_object().bucket(bucket).key("tenant-exact/root.txt").send().await?;
assert_eq!(exact.body.collect().await?.into_bytes().as_ref(), b"root payload\n");
let fallback_err = client
.head_object()
.bucket(bucket)
.key("tenant-fallback/root.txt")
.send()
.await
.expect_err("fallback suffix header should not override exact MinIO prefix");
let fallback_service_err = fallback_err.into_service_error();
assert_eq!(fallback_service_err.code(), Some("NotFound"));
env.stop_server();
Ok(())
}
}