This is an automated email from the ASF dual-hosted git repository. suyanhanx pushed a commit to branch test-for-read-if-none-match in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
commit c084c60f1794138c23031a43c5d5008e8e3a8552 Author: suyanhanx <[email protected]> AuthorDate: Thu Apr 27 14:25:20 2023 +0800 add test for read_with_if_none_match Signed-off-by: suyanhanx <[email protected]> --- core/src/services/gcs/backend.rs | 2 ++ core/src/services/http/backend.rs | 2 ++ core/src/services/obs/backend.rs | 2 ++ core/src/services/oss/backend.rs | 2 ++ core/tests/behavior/read_only.rs | 71 +++++++++++++++++++++++++++++++++++++++ core/tests/behavior/write.rs | 49 +++++++++++++++++++++++---- 6 files changed, 122 insertions(+), 6 deletions(-) diff --git a/core/src/services/gcs/backend.rs b/core/src/services/gcs/backend.rs index a53a20ab..28ba61e1 100644 --- a/core/src/services/gcs/backend.rs +++ b/core/src/services/gcs/backend.rs @@ -381,6 +381,8 @@ impl Accessor for GcsBackend { read: true, read_can_next: true, + read_with_if_match: true, + read_with_if_none_match: true, write: true, write_with_content_type: true, diff --git a/core/src/services/http/backend.rs b/core/src/services/http/backend.rs index 8a4d3fb6..a39b645c 100644 --- a/core/src/services/http/backend.rs +++ b/core/src/services/http/backend.rs @@ -265,6 +265,8 @@ impl Accessor for HttpBackend { read: true, read_can_next: true, + read_with_if_match: true, + read_with_if_none_match: true, ..Default::default() }); diff --git a/core/src/services/obs/backend.rs b/core/src/services/obs/backend.rs index 4eaf9c01..e67492c3 100644 --- a/core/src/services/obs/backend.rs +++ b/core/src/services/obs/backend.rs @@ -312,6 +312,8 @@ impl Accessor for ObsBackend { read: true, read_can_next: true, + read_with_if_match: true, + read_with_if_none_match: true, write: true, write_with_content_type: true, diff --git a/core/src/services/oss/backend.rs b/core/src/services/oss/backend.rs index 1388c25a..47bed953 100644 --- a/core/src/services/oss/backend.rs +++ b/core/src/services/oss/backend.rs @@ -430,6 +430,8 @@ impl Accessor for OssBackend { read: true, read_can_next: true, + read_with_if_match: true, + read_with_if_none_match: true, write: true, write_with_cache_control: true, diff --git a/core/tests/behavior/read_only.rs b/core/tests/behavior/read_only.rs index fdaf939e..5fe41660 100644 --- a/core/tests/behavior/read_only.rs +++ b/core/tests/behavior/read_only.rs @@ -17,6 +17,7 @@ use anyhow::Result; use futures::AsyncReadExt; +use opendal::ops::OpRead; use opendal::ops::OpStat; use opendal::EntryMode; use opendal::ErrorKind; @@ -76,6 +77,8 @@ macro_rules! behavior_read_tests { test_reader_tail, test_read_not_exist, test_read_with_dir_path, + test_read_with_if_match, + test_read_with_if_none_match, ); )* }; @@ -304,3 +307,71 @@ pub async fn test_read_with_dir_path(op: Operator) -> Result<()> { Ok(()) } + +/// Read with if_match should match, else get a ConditionNotMatch error. +pub async fn test_read_with_if_match(op: Operator) -> Result<()> { + if !op.info().capability().read_with_if_match { + return Ok(()); + } + + let path = "normal_file"; + + let meta = op.stat(path).await?; + + let mut op_read = OpRead::default(); + op_read = op_read.with_if_match("invalid_etag"); + + let res = op.read_with(path, op_read).await; + assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch); + + let mut op_read = OpRead::default(); + op_read = op_read.with_if_match(meta.etag().expect("etag must exist")); + + let bs = op + .read_with(path, op_read) + .await + .expect("read must succeed"); + assert_eq!(bs.len(), 262144, "read size"); + assert_eq!( + format!("{:x}", Sha256::digest(&bs)), + "e7541d0f50d2d5c79dc41f28ccba8e0cdfbbc8c4b1aa1a0110184ef0ef67689f", + "read content" + ); + + Ok(()) +} + +/// Read with if_none_match should match, else get a ConditionNotMatch error. +pub async fn test_read_with_if_none_match(op: Operator) -> Result<()> { + if !op.info().capability().read_with_if_none_match { + return Ok(()); + } + + let path = "normal_file"; + + let meta = op.stat(path).await?; + + let mut op_read = OpRead::default(); + op_read = op_read.with_if_none_match(meta.etag().expect("etag must exist")); + + let res = op.read_with(path, op_read).await; + assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch); + + let mut op_read = OpRead::default(); + op_read = op_read.with_if_none_match("invalid_etag"); + + let bs = op + .read_with(path, op_read) + .await + .expect("read must succeed"); + assert_eq!(bs.len(), 262144, "read size"); + assert_eq!( + format!("{:x}", Sha256::digest(&bs)), + "e7541d0f50d2d5c79dc41f28ccba8e0cdfbbc8c4b1aa1a0110184ef0ef67689f", + "read content" + ); + + Ok(()) +} diff --git a/core/tests/behavior/write.rs b/core/tests/behavior/write.rs index c1212cfb..d15b8b25 100644 --- a/core/tests/behavior/write.rs +++ b/core/tests/behavior/write.rs @@ -95,6 +95,7 @@ macro_rules! behavior_write_tests { test_reader_tail, test_read_not_exist, test_read_with_if_match, + test_read_with_if_none_match, test_fuzz_range_reader, test_fuzz_offset_reader, test_fuzz_part_reader, @@ -585,18 +586,54 @@ pub async fn test_read_with_if_match(op: Operator) -> Result<()> { let meta = op.stat(&path).await?; - let mut op_if_match = OpRead::default(); - op_if_match = op_if_match.with_if_match("invalid_etag"); + let mut op_read = OpRead::default(); + op_read = op_read.with_if_match("invalid_etag"); - let res = op.read_with(&path, op_if_match).await; + let res = op.read_with(&path, op_read).await; assert!(res.is_err()); assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch); - let mut op_if_match = OpRead::default(); - op_if_match = op_if_match.with_if_match(meta.etag().expect("etag must exist")); + let mut op_read = OpRead::default(); + op_read = op_read.with_if_match(meta.etag().expect("etag must exist")); + + let bs = op + .read_with(&path, op_read) + .await + .expect("read must succeed"); + assert_eq!(bs, content); + + op.delete(&path).await.expect("delete must succeed"); + Ok(()) +} + +/// Read with if_none_match should match, else get a ConditionNotMatch error. +pub async fn test_read_with_if_none_match(op: Operator) -> Result<()> { + if !op.info().capability().read_with_if_none_match { + return Ok(()); + } + + let path = uuid::Uuid::new_v4().to_string(); + debug!("Generate a random file: {}", &path); + let (content, _) = gen_bytes(); + + op.write(&path, content.clone()) + .await + .expect("write must succeed"); + + let meta = op.stat(&path).await?; + + let mut op_read = OpRead::default(); + op_read = op_read.with_if_none_match(meta.etag().expect("etag must exist")); + + let res = op.read_with(&path, op_read).await; + assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch); + + let mut op_read = OpRead::default(); + op_read = op_read.with_if_none_match("invalid_etag"); let bs = op - .read_with(&path, op_if_match) + .read_with(&path, op_read) .await .expect("read must succeed"); assert_eq!(bs, content);
