diff options
author | Alex Auvolat <alex@adnab.me> | 2024-02-13 11:24:56 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2024-02-13 11:36:28 +0100 |
commit | cf2af186fcc0c8f581a966454b6cd4720d3821f0 (patch) | |
tree | 37a978ba9ffb780fc828cff7b8ec93662d50884f /src/garage/tests/s3 | |
parent | db48dd3d6c1f9e86a62e9b8edfce2c1620bcd5f3 (diff) | |
parent | 823078b4cdaf93e09de0847c5eaa75beb7b26b7f (diff) | |
download | garage-cf2af186fcc0c8f581a966454b6cd4720d3821f0.tar.gz garage-cf2af186fcc0c8f581a966454b6cd4720d3821f0.zip |
Merge branch 'main' into next-0.10
Diffstat (limited to 'src/garage/tests/s3')
-rw-r--r-- | src/garage/tests/s3/list.rs | 60 | ||||
-rw-r--r-- | src/garage/tests/s3/multipart.rs | 30 | ||||
-rw-r--r-- | src/garage/tests/s3/objects.rs | 48 | ||||
-rw-r--r-- | src/garage/tests/s3/streaming_signature.rs | 16 | ||||
-rw-r--r-- | src/garage/tests/s3/website.rs | 123 |
5 files changed, 183 insertions, 94 deletions
diff --git a/src/garage/tests/s3/list.rs b/src/garage/tests/s3/list.rs index bb03f250..1b0c006d 100644 --- a/src/garage/tests/s3/list.rs +++ b/src/garage/tests/s3/list.rs @@ -613,3 +613,63 @@ async fn test_listmultipart() { assert!(r.common_prefixes.is_none()); } } + +#[tokio::test] +async fn test_multichar_delimiter() { + // Test case from dpape from issue #692 with reference results from Amazon + + let ctx = common::context(); + let bucket = ctx.create_bucket("multichardelim"); + + for k in [ + "a/", "a/b/", "a/b/c/", "a/b/c/d", "a/c/", "a/c/b/", "a/c/b/e", + ] { + ctx.client + .put_object() + .bucket(&bucket) + .key(k) + .send() + .await + .unwrap(); + } + + // With delimiter / + { + let r = ctx + .client + .list_objects_v2() + .bucket(&bucket) + .delimiter("/") + .send() + .await + .unwrap(); + + assert!(r.contents.is_none()); + + let common_prefixes = r.common_prefixes.unwrap(); + assert_eq!(common_prefixes.len(), 1); + assert_eq!(common_prefixes[0].prefix.as_deref().unwrap(), "a/"); + } + + // With delimiter b/ + { + let r = ctx + .client + .list_objects_v2() + .bucket(&bucket) + .delimiter("b/") + .send() + .await + .unwrap(); + + let contents = r.contents.unwrap(); + assert_eq!(contents.len(), 2); + assert_eq!(contents[0].key.as_deref().unwrap(), "a/"); + assert_eq!(contents[1].key.as_deref().unwrap(), "a/c/"); + + let common_prefixes = r.common_prefixes.unwrap(); + assert_eq!(common_prefixes.len(), 2); + assert_eq!(common_prefixes[0].prefix.as_deref().unwrap(), "a/b/"); + assert_eq!(common_prefixes[1].prefix.as_deref().unwrap(), "a/c/b/"); + } +} diff --git a/src/garage/tests/s3/multipart.rs b/src/garage/tests/s3/multipart.rs index 09ae5e5b..51c9df74 100644 --- a/src/garage/tests/s3/multipart.rs +++ b/src/garage/tests/s3/multipart.rs @@ -154,7 +154,7 @@ async fn test_multipart_upload() { .await .unwrap(); - assert_eq!(r.content_length, (SZ_5MB * 3) as i64); + assert_eq!(r.content_length.unwrap(), (SZ_5MB * 3) as i64); } { @@ -183,7 +183,7 @@ async fn test_multipart_upload() { .unwrap(); eprintln!("get_object with part_number = {}", part_number); - assert_eq!(o.content_length, SZ_5MB as i64); + assert_eq!(o.content_length.unwrap(), SZ_5MB as i64); assert_bytes_eq!(o.body, data); } } @@ -249,14 +249,14 @@ async fn test_uploadlistpart() { let ps = r.parts.unwrap(); assert_eq!(ps.len(), 1); - assert_eq!(ps[0].part_number, 2); + assert_eq!(ps[0].part_number.unwrap(), 2); let fp = &ps[0]; assert!(fp.last_modified.is_some()); assert_eq!( fp.e_tag.as_ref().unwrap(), "\"3366bb9dcf710d6801b5926467d02e19\"" ); - assert_eq!(fp.size, SZ_5MB as i64); + assert_eq!(fp.size.unwrap(), SZ_5MB as i64); } let p2 = ctx @@ -286,23 +286,23 @@ async fn test_uploadlistpart() { let ps = r.parts.unwrap(); assert_eq!(ps.len(), 2); - assert_eq!(ps[0].part_number, 1); + assert_eq!(ps[0].part_number.unwrap(), 1); let fp = &ps[0]; assert!(fp.last_modified.is_some()); assert_eq!( fp.e_tag.as_ref().unwrap(), "\"3c484266f9315485694556e6c693bfa2\"" ); - assert_eq!(fp.size, SZ_5MB as i64); + assert_eq!(fp.size.unwrap(), SZ_5MB as i64); - assert_eq!(ps[1].part_number, 2); + assert_eq!(ps[1].part_number.unwrap(), 2); let sp = &ps[1]; assert!(sp.last_modified.is_some()); assert_eq!( sp.e_tag.as_ref().unwrap(), "\"3366bb9dcf710d6801b5926467d02e19\"" ); - assert_eq!(sp.size, SZ_5MB as i64); + assert_eq!(sp.size.unwrap(), SZ_5MB as i64); } { @@ -320,14 +320,14 @@ async fn test_uploadlistpart() { assert!(r.part_number_marker.is_none()); assert_eq!(r.next_part_number_marker.as_deref(), Some("1")); - assert_eq!(r.max_parts, 1_i32); - assert!(r.is_truncated); + assert_eq!(r.max_parts.unwrap(), 1_i32); + assert!(r.is_truncated.unwrap()); assert_eq!(r.key.unwrap(), "a"); assert_eq!(r.upload_id.unwrap().as_str(), uid.as_str()); let parts = r.parts.unwrap(); assert_eq!(parts.len(), 1); let fp = &parts[0]; - assert_eq!(fp.part_number, 1); + assert_eq!(fp.part_number.unwrap(), 1); assert_eq!( fp.e_tag.as_ref().unwrap(), "\"3c484266f9315485694556e6c693bfa2\"" @@ -349,19 +349,19 @@ async fn test_uploadlistpart() { r2.part_number_marker.as_ref().unwrap(), r.next_part_number_marker.as_ref().unwrap() ); - assert_eq!(r2.max_parts, 1_i32); + assert_eq!(r2.max_parts.unwrap(), 1_i32); assert_eq!(r2.key.unwrap(), "a"); assert_eq!(r2.upload_id.unwrap().as_str(), uid.as_str()); let parts = r2.parts.unwrap(); assert_eq!(parts.len(), 1); let fp = &parts[0]; - assert_eq!(fp.part_number, 2); + assert_eq!(fp.part_number.unwrap(), 2); assert_eq!( fp.e_tag.as_ref().unwrap(), "\"3366bb9dcf710d6801b5926467d02e19\"" ); //assert!(r2.is_truncated); // WHY? (this was the test before) - assert!(!r2.is_truncated); + assert!(!r2.is_truncated.unwrap()); } let cmp = CompletedMultipartUpload::builder() @@ -411,7 +411,7 @@ async fn test_uploadlistpart() { .await .unwrap(); - assert_eq!(r.content_length, (SZ_5MB * 2) as i64); + assert_eq!(r.content_length.unwrap(), (SZ_5MB * 2) as i64); } } diff --git a/src/garage/tests/s3/objects.rs b/src/garage/tests/s3/objects.rs index 27697d45..ad5f63f1 100644 --- a/src/garage/tests/s3/objects.rs +++ b/src/garage/tests/s3/objects.rs @@ -50,9 +50,9 @@ async fn test_putobject() { // assert_eq!(o.version_id.unwrap(), _version); assert_eq!(o.content_type.unwrap(), content_type); assert!(o.last_modified.is_some()); - assert_eq!(o.content_length, 0); - assert_eq!(o.parts_count, 0); - assert_eq!(o.tag_count, 0); + assert_eq!(o.content_length.unwrap(), 0); + assert_eq!(o.parts_count, None); + assert_eq!(o.tag_count, None); } { @@ -86,9 +86,9 @@ async fn test_putobject() { assert_bytes_eq!(o.body, b"hi"); assert_eq!(o.e_tag.unwrap(), etag); assert!(o.last_modified.is_some()); - assert_eq!(o.content_length, 2); - assert_eq!(o.parts_count, 0); - assert_eq!(o.tag_count, 0); + assert_eq!(o.content_length.unwrap(), 2); + assert_eq!(o.parts_count, None); + assert_eq!(o.tag_count, None); } { @@ -119,9 +119,9 @@ async fn test_putobject() { assert_bytes_eq!(o.body, b""); assert_eq!(o.e_tag.unwrap(), etag); assert!(o.last_modified.is_some()); - assert_eq!(o.content_length, 0); - assert_eq!(o.parts_count, 0); - assert_eq!(o.tag_count, 0); + assert_eq!(o.content_length.unwrap(), 0); + assert_eq!(o.parts_count, None); + assert_eq!(o.tag_count, None); } } @@ -185,6 +185,30 @@ async fn test_getobject() { assert_eq!(o.content_range.unwrap().as_str(), "bytes 57-61/62"); assert_bytes_eq!(o.body, &BODY[57..]); } + { + let exp = aws_sdk_s3::primitives::DateTime::from_secs(10000000000); + let o = ctx + .client + .get_object() + .bucket(&bucket) + .key(STD_KEY) + .response_content_type("application/x-dummy-test") + .response_cache_control("ccdummy") + .response_content_disposition("cddummy") + .response_content_encoding("cedummy") + .response_content_language("cldummy") + .response_expires(exp) + .send() + .await + .unwrap(); + assert_eq!(o.content_type.unwrap().as_str(), "application/x-dummy-test"); + assert_eq!(o.cache_control.unwrap().as_str(), "ccdummy"); + assert_eq!(o.content_disposition.unwrap().as_str(), "cddummy"); + assert_eq!(o.content_encoding.unwrap().as_str(), "cedummy"); + assert_eq!(o.content_language.unwrap().as_str(), "cldummy"); + assert_eq!(o.expires.unwrap(), exp); + assert_bytes_eq!(o.body, &BODY[..]); + } } #[tokio::test] @@ -205,7 +229,7 @@ async fn test_deleteobject() { .await .unwrap(); if i > 0 { - to_del = to_del.objects(ObjectIdentifier::builder().key(k).build()); + to_del = to_del.objects(ObjectIdentifier::builder().key(k).build().unwrap()); } } @@ -223,7 +247,7 @@ async fn test_deleteobject() { .unwrap(); if i > 0 { - to_del = to_del.objects(ObjectIdentifier::builder().key(k).build()); + to_del = to_del.objects(ObjectIdentifier::builder().key(k).build().unwrap()); } } @@ -247,7 +271,7 @@ async fn test_deleteobject() { .client .delete_objects() .bucket(&bucket) - .delete(to_del.build()) + .delete(to_del.build().unwrap()) .send() .await .unwrap(); diff --git a/src/garage/tests/s3/streaming_signature.rs b/src/garage/tests/s3/streaming_signature.rs index b7a1acae..224b9ed5 100644 --- a/src/garage/tests/s3/streaming_signature.rs +++ b/src/garage/tests/s3/streaming_signature.rs @@ -57,9 +57,9 @@ async fn test_putobject_streaming() { // assert_eq!(o.version_id.unwrap(), _version); assert_eq!(o.content_type.unwrap(), content_type); assert!(o.last_modified.is_some()); - assert_eq!(o.content_length, 0); - assert_eq!(o.parts_count, 0); - assert_eq!(o.tag_count, 0); + assert_eq!(o.content_length.unwrap(), 0); + assert_eq!(o.parts_count, None); + assert_eq!(o.tag_count, None); } { @@ -95,9 +95,9 @@ async fn test_putobject_streaming() { assert_bytes_eq!(o.body, BODY); assert_eq!(o.e_tag.unwrap(), etag); assert!(o.last_modified.is_some()); - assert_eq!(o.content_length, 62); - assert_eq!(o.parts_count, 0); - assert_eq!(o.tag_count, 0); + assert_eq!(o.content_length.unwrap(), 62); + assert_eq!(o.parts_count, None); + assert_eq!(o.tag_count, None); } } @@ -187,7 +187,7 @@ async fn test_put_website_streaming() { .await .unwrap(); - assert_eq!(o.index_document.unwrap().suffix.unwrap(), "home.html"); - assert_eq!(o.error_document.unwrap().key.unwrap(), "err/error.html"); + assert_eq!(o.index_document.unwrap().suffix, "home.html"); + assert_eq!(o.error_document.unwrap().key, "err/error.html"); } } diff --git a/src/garage/tests/s3/website.rs b/src/garage/tests/s3/website.rs index eeafb5fa..0cadc388 100644 --- a/src/garage/tests/s3/website.rs +++ b/src/garage/tests/s3/website.rs @@ -8,15 +8,18 @@ use aws_sdk_s3::{ types::{CorsConfiguration, CorsRule, ErrorDocument, IndexDocument, WebsiteConfiguration}, }; use http::{Request, StatusCode}; -use hyper::{ - body::{to_bytes, Body}, - Client, -}; +use http_body_util::BodyExt; +use http_body_util::Full as FullBody; +use hyper::body::Bytes; +use hyper_util::client::legacy::Client; +use hyper_util::rt::TokioExecutor; use serde_json::json; const BODY: &[u8; 16] = b"<h1>bonjour</h1>"; const BODY_ERR: &[u8; 6] = b"erreur"; +pub type Body = FullBody<Bytes>; + #[tokio::test] async fn test_website() { const BCKT_NAME: &str = "my-website"; @@ -34,14 +37,14 @@ async fn test_website() { .await .unwrap(); - let client = Client::new(); + let client = Client::builder(TokioExecutor::new()).build_http(); let req = || { Request::builder() .method("GET") .uri(format!("http://127.0.0.1:{}/", ctx.garage.web_port)) .header("Host", format!("{}.web.garage", BCKT_NAME)) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap() }; @@ -49,7 +52,7 @@ async fn test_website() { assert_eq!(resp.status(), StatusCode::NOT_FOUND); assert_ne!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), + BodyExt::collect(resp.into_body()).await.unwrap().to_bytes(), BODY.as_ref() ); /* check that we do not leak body */ @@ -58,10 +61,9 @@ async fn test_website() { .method("GET") .uri(format!( "http://127.0.0.1:{0}/check?domain={1}", - ctx.garage.admin_port, - BCKT_NAME.to_string() + ctx.garage.admin_port, BCKT_NAME )) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap() }; @@ -87,7 +89,7 @@ async fn test_website() { resp = client.request(req()).await.unwrap(); assert_eq!(resp.status(), StatusCode::OK); assert_eq!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), + resp.into_body().collect().await.unwrap().to_bytes(), BODY.as_ref() ); @@ -103,14 +105,14 @@ async fn test_website() { "http://127.0.0.1:{0}/check?domain={1}", ctx.garage.admin_port, bname )) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap() }; - let mut admin_resp = client.request(admin_req()).await.unwrap(); + let admin_resp = client.request(admin_req()).await.unwrap(); assert_eq!(admin_resp.status(), StatusCode::OK); assert_eq!( - to_bytes(admin_resp.body_mut()).await.unwrap().as_ref(), + admin_resp.into_body().collect().await.unwrap().to_bytes(), format!("Domain '{bname}' is managed by Garage").as_bytes() ); } @@ -124,7 +126,7 @@ async fn test_website() { resp = client.request(req()).await.unwrap(); assert_eq!(resp.status(), StatusCode::NOT_FOUND); assert_ne!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), + resp.into_body().collect().await.unwrap().to_bytes(), BODY.as_ref() ); /* check that we do not leak body */ @@ -133,10 +135,9 @@ async fn test_website() { .method("GET") .uri(format!( "http://127.0.0.1:{0}/check?domain={1}", - ctx.garage.admin_port, - BCKT_NAME.to_string() + ctx.garage.admin_port, BCKT_NAME )) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap() }; @@ -181,8 +182,18 @@ async fn test_website_s3_api() { .unwrap(); let conf = WebsiteConfiguration::builder() - .index_document(IndexDocument::builder().suffix("home.html").build()) - .error_document(ErrorDocument::builder().key("err/error.html").build()) + .index_document( + IndexDocument::builder() + .suffix("home.html") + .build() + .unwrap(), + ) + .error_document( + ErrorDocument::builder() + .key("err/error.html") + .build() + .unwrap(), + ) .build(); ctx.client @@ -201,9 +212,11 @@ async fn test_website_s3_api() { .allowed_methods("GET") .allowed_methods("PUT") .allowed_origins("*") - .build(), + .build() + .unwrap(), ) - .build(); + .build() + .unwrap(); ctx.client .put_bucket_cors() @@ -222,24 +235,21 @@ async fn test_website_s3_api() { .await .unwrap(); - let main_rule = cors_res.cors_rules().unwrap().iter().next().unwrap(); + let main_rule = cors_res.cors_rules().iter().next().unwrap(); assert_eq!(main_rule.id.as_ref().unwrap(), "main-rule"); assert_eq!( main_rule.allowed_headers.as_ref().unwrap(), &vec!["*".to_string()] ); + assert_eq!(&main_rule.allowed_origins, &vec!["*".to_string()]); assert_eq!( - main_rule.allowed_origins.as_ref().unwrap(), - &vec!["*".to_string()] - ); - assert_eq!( - main_rule.allowed_methods.as_ref().unwrap(), + &main_rule.allowed_methods, &vec!["GET".to_string(), "PUT".to_string()] ); } - let client = Client::new(); + let client = Client::builder(TokioExecutor::new()).build_http(); // Test direct requests with CORS { @@ -248,10 +258,10 @@ async fn test_website_s3_api() { .uri(format!("http://127.0.0.1:{}/site/", ctx.garage.web_port)) .header("Host", format!("{}.web.garage", BCKT_NAME)) .header("Origin", "https://example.com") - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap(); - let mut resp = client.request(req).await.unwrap(); + let resp = client.request(req).await.unwrap(); assert_eq!(resp.status(), StatusCode::OK); assert_eq!( @@ -259,7 +269,7 @@ async fn test_website_s3_api() { "*" ); assert_eq!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), + resp.into_body().collect().await.unwrap().to_bytes(), BODY.as_ref() ); } @@ -273,14 +283,14 @@ async fn test_website_s3_api() { ctx.garage.web_port )) .header("Host", format!("{}.web.garage", BCKT_NAME)) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap(); - let mut resp = client.request(req).await.unwrap(); + let resp = client.request(req).await.unwrap(); assert_eq!(resp.status(), StatusCode::NOT_FOUND); assert_eq!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), + resp.into_body().collect().await.unwrap().to_bytes(), BODY_ERR.as_ref() ); } @@ -293,10 +303,10 @@ async fn test_website_s3_api() { .header("Host", format!("{}.web.garage", BCKT_NAME)) .header("Origin", "https://example.com") .header("Access-Control-Request-Method", "PUT") - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap(); - let mut resp = client.request(req).await.unwrap(); + let resp = client.request(req).await.unwrap(); assert_eq!(resp.status(), StatusCode::OK); assert_eq!( @@ -304,7 +314,7 @@ async fn test_website_s3_api() { "*" ); assert_ne!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), + resp.into_body().collect().await.unwrap().to_bytes(), BODY.as_ref() ); } @@ -317,14 +327,14 @@ async fn test_website_s3_api() { .header("Host", format!("{}.web.garage", BCKT_NAME)) .header("Origin", "https://example.com") .header("Access-Control-Request-Method", "DELETE") - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap(); - let mut resp = client.request(req).await.unwrap(); + let resp = client.request(req).await.unwrap(); assert_eq!(resp.status(), StatusCode::FORBIDDEN); assert_ne!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), + resp.into_body().collect().await.unwrap().to_bytes(), BODY.as_ref() ); } @@ -358,14 +368,14 @@ async fn test_website_s3_api() { .header("Host", format!("{}.web.garage", BCKT_NAME)) .header("Origin", "https://example.com") .header("Access-Control-Request-Method", "PUT") - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap(); - let mut resp = client.request(req).await.unwrap(); + let resp = client.request(req).await.unwrap(); assert_eq!(resp.status(), StatusCode::FORBIDDEN); assert_ne!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), + resp.into_body().collect().await.unwrap().to_bytes(), BODY.as_ref() ); } @@ -384,20 +394,15 @@ async fn test_website_s3_api() { .method("GET") .uri(format!("http://127.0.0.1:{}/site/", ctx.garage.web_port)) .header("Host", format!("{}.web.garage", BCKT_NAME)) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap(); - let mut resp = client.request(req).await.unwrap(); + let resp = client.request(req).await.unwrap(); assert_eq!(resp.status(), StatusCode::NOT_FOUND); - assert_ne!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), - BODY_ERR.as_ref() - ); - assert_ne!( - to_bytes(resp.body_mut()).await.unwrap().as_ref(), - BODY.as_ref() - ); + let resp_bytes = resp.into_body().collect().await.unwrap().to_bytes(); + assert_ne!(resp_bytes, BODY_ERR.as_ref()); + assert_ne!(resp_bytes, BODY.as_ref()); } } @@ -405,13 +410,13 @@ async fn test_website_s3_api() { async fn test_website_check_domain() { let ctx = common::context(); - let client = Client::new(); + let client = Client::builder(TokioExecutor::new()).build_http(); let admin_req = || { Request::builder() .method("GET") .uri(format!("http://127.0.0.1:{}/check", ctx.garage.admin_port)) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap() }; @@ -435,7 +440,7 @@ async fn test_website_check_domain() { "http://127.0.0.1:{}/check?domain=", ctx.garage.admin_port )) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap() }; @@ -459,7 +464,7 @@ async fn test_website_check_domain() { "http://127.0.0.1:{}/check?domain=foobar", ctx.garage.admin_port )) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap() }; @@ -483,7 +488,7 @@ async fn test_website_check_domain() { "http://127.0.0.1:{}/check?domain=%E2%98%B9", ctx.garage.admin_port )) - .body(Body::empty()) + .body(Body::new(Bytes::new())) .unwrap() }; |