Skip to content

Commit

Permalink
add tests for invalid range
Browse files Browse the repository at this point in the history
  • Loading branch information
meteorgan committed Jan 12, 2025
1 parent 3d5a5a5 commit d5d8dc0
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 111 deletions.
35 changes: 16 additions & 19 deletions integrations/object_store/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,28 +281,25 @@ impl ObjectStore for OpendalStore {
.map_err(|err| format_object_store_error(err, location.as_ref()))?
};

let mut read_range = 0..meta.size;
if let Some(range) = options.range {
match range {
GetRange::Bounded(r) => {
read_range = r;
let read_range = match options.range {
Some(GetRange::Bounded(r)) => {
if r.start >= r.end || r.start >= meta.size {
0..0
} else {
let end = r.end.min(meta.size);
r.start..end
}
GetRange::Offset(r) => {
if r >= meta.size {
read_range = 0..0;
} else {
read_range = r..meta.size;
}
}
GetRange::Suffix(r) => {
if r >= meta.size {
read_range = 0..meta.size;
} else {
read_range = (meta.size - r)..meta.size;
}
}
Some(GetRange::Offset(r)) => {
if r < meta.size {
r..meta.size
} else {
0..0
}
}
}
Some(GetRange::Suffix(r)) if r < meta.size => (meta.size - r)..meta.size,
_ => 0..meta.size,
};

let stream = reader
.into_bytes_stream(read_range.start as u64..read_range.end as u64)
Expand Down
198 changes: 106 additions & 92 deletions integrations/object_store/tests/behavior/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ pub fn tests(store: &OpendalStore, tests: &mut Vec<Trial>) {
store,
test_get_opts_with_range,
));
tests.push(build_trail(
"test_get_opts_with_invalid_range",
store,
test_get_opts_with_invalid_range,
));
tests.push(build_trail(
"test_get_opts_with_version",
store,
Expand Down Expand Up @@ -143,6 +148,50 @@ pub async fn test_get_opts_with_range(store: OpendalStore) -> Result<()> {
Ok(())
}

pub async fn test_get_opts_with_invalid_range(store: OpendalStore) -> Result<()> {
let location = new_file_path("data").into();
let value = Bytes::from_static(b"Hello, world!");

store.put(&location, value.clone().into()).await?;

// the end of the range is greater than the size of the object
let opts = GetOptions {
range: Some((0..100).into()),
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
assert_eq!(ret.range, 0..value.len());
assert_eq!(ret.bytes().await?, value);

// the start of the range is greater than the end of the range
let opts = GetOptions {
range: Some((2..0).into()),
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
assert_eq!(ret.range, 0..0);

// the offset of the range is greater than the size of the object
let opts = GetOptions {
range: Some(GetRange::Offset(100)),
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
assert_eq!(ret.range, 0..0);

// the suffix of the range is greater than the size of the object
let opts = GetOptions {
range: Some(GetRange::Suffix(100)),
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
assert_eq!(ret.range, 0..value.len());
assert_eq!(ret.bytes().await?, value);

store.delete(&location).await?;
Ok(())
}

pub async fn test_get_opts_with_version(store: OpendalStore) -> Result<()> {
if !store.info().full_capability().read_with_version {
return Ok(());
Expand All @@ -152,15 +201,12 @@ pub async fn test_get_opts_with_version(store: OpendalStore) -> Result<()> {
let value = Bytes::from_static(b"Hello, world!");
store.put(&location, value.clone().into()).await?;
let meta = store.head(&location).await?;
let ret = store
.get_opts(
&location,
GetOptions {
version: meta.version,
..Default::default()
},
)
.await?;

let opts = GetOptions {
version: meta.version,
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
let data = ret.bytes().await?;
assert_eq!(value, data);

Expand All @@ -171,17 +217,13 @@ pub async fn test_get_opts_with_version(store: OpendalStore) -> Result<()> {
Bytes::from_static(b"Hello, world!").into(),
)
.await?;
let version = store.head(&another_location).await?.version;

let ret = store
.get_opts(
&location,
GetOptions {
version,
..Default::default()
},
)
.await;
let another_version = store.head(&another_location).await?.version;

let opts = GetOptions {
version: another_version,
..Default::default()
};
let ret = store.get_opts(&location, opts).await;
assert!(ret.is_err());
assert!(matches!(
ret.err().unwrap(),
Expand All @@ -202,27 +244,20 @@ async fn test_get_ops_with_if_match(store: OpendalStore) -> Result<()> {
let value = Bytes::from_static(b"Hello, world!");
store.put(&location, value.clone().into()).await?;
let meta = store.head(&location).await?;
let ret = store
.get_opts(
&location,
GetOptions {
if_match: Some(meta.e_tag.unwrap()),
..Default::default()
},
)
.await?;

let opts = GetOptions {
if_match: Some(meta.e_tag.unwrap()),
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
let data = ret.bytes().await?;
assert_eq!(value, data);

let ret = store
.get_opts(
&location,
GetOptions {
if_match: Some("invalid etag".to_string()),
..Default::default()
},
)
.await;
let opts = GetOptions {
if_match: Some("invalid etag".to_string()),
..Default::default()
};
let ret = store.get_opts(&location, opts).await;
assert!(ret.is_err());
assert!(matches!(
ret.err().unwrap(),
Expand All @@ -242,27 +277,20 @@ async fn test_get_ops_with_if_none_match(store: OpendalStore) -> Result<()> {
let value = Bytes::from_static(b"Hello, world!");
store.put(&location, value.clone().into()).await?;
let meta = store.head(&location).await?;
let ret = store
.get_opts(
&location,
GetOptions {
if_none_match: Some("invalid etag".to_string()),
..Default::default()
},
)
.await?;

let opts = GetOptions {
if_none_match: Some("invalid etag".to_string()),
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
let data = ret.bytes().await?;
assert_eq!(value, data);

let ret = store
.get_opts(
&location,
GetOptions {
if_none_match: Some(meta.e_tag.unwrap()),
..Default::default()
},
)
.await;
let opts = GetOptions {
if_none_match: Some(meta.e_tag.unwrap()),
..Default::default()
};
let ret = store.get_opts(&location, opts).await;
assert!(ret.is_err());
assert!(matches!(
ret.err().unwrap(),
Expand All @@ -282,27 +310,20 @@ async fn test_get_opts_with_if_modified_since(store: OpendalStore) -> Result<()>
let value = Bytes::from_static(b"Hello, world!");
store.put(&location, value.clone().into()).await?;
let meta = store.head(&location).await?;
let ret = store
.get_opts(
&location,
GetOptions {
if_modified_since: Some(meta.last_modified - std::time::Duration::from_secs(1)),
..Default::default()
},
)
.await?;

let opts = GetOptions {
if_modified_since: Some(meta.last_modified - std::time::Duration::from_secs(1)),
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
let data = ret.bytes().await?;
assert_eq!(value, data);

let ret = store
.get_opts(
&location,
GetOptions {
if_modified_since: Some(meta.last_modified + std::time::Duration::from_secs(1)),
..Default::default()
},
)
.await;
let opts = GetOptions {
if_modified_since: Some(meta.last_modified + std::time::Duration::from_secs(1)),
..Default::default()
};
let ret = store.get_opts(&location, opts).await;
assert!(ret.is_err());
assert!(matches!(
ret.err().unwrap(),
Expand All @@ -322,27 +343,20 @@ async fn test_get_opts_with_if_unmodified_since(store: OpendalStore) -> Result<(
let value = Bytes::from_static(b"Hello, world!");
store.put(&location, value.clone().into()).await?;
let meta = store.head(&location).await?;
let ret = store
.get_opts(
&location,
GetOptions {
if_unmodified_since: Some(meta.last_modified + std::time::Duration::from_secs(1)),
..Default::default()
},
)
.await?;

let opts = GetOptions {
if_unmodified_since: Some(meta.last_modified + std::time::Duration::from_secs(1)),
..Default::default()
};
let ret = store.get_opts(&location, opts).await?;
let data = ret.bytes().await?;
assert_eq!(value, data);

let ret = store
.get_opts(
&location,
GetOptions {
if_unmodified_since: Some(meta.last_modified - std::time::Duration::from_secs(1)),
..Default::default()
},
)
.await;
let opts = GetOptions {
if_unmodified_since: Some(meta.last_modified - std::time::Duration::from_secs(1)),
..Default::default()
};
let ret = store.get_opts(&location, opts).await;
assert!(ret.is_err());
assert!(matches!(
ret.err().unwrap(),
Expand Down

0 comments on commit d5d8dc0

Please sign in to comment.