From 9bc633ad9adb6e124757e6ff355f7adcdf50e42f Mon Sep 17 00:00:00 2001 From: Gaius Date: Fri, 20 Dec 2024 12:25:32 +0800 Subject: [PATCH] test: add tests for calculate_piece_range Signed-off-by: Gaius --- dragonfly-client-storage/src/content.rs | 115 ++++++++++++++++++---- dragonfly-client/src/proxy/cache.rs | 123 +++++++++++++++++++----- dragonfly-client/src/proxy/mod.rs | 2 + 3 files changed, 196 insertions(+), 44 deletions(-) diff --git a/dragonfly-client-storage/src/content.rs b/dragonfly-client-storage/src/content.rs index 63c34f35..d6bc74e8 100644 --- a/dragonfly-client-storage/src/content.rs +++ b/dragonfly-client-storage/src/content.rs @@ -252,22 +252,16 @@ impl Content { range: Option, ) -> Result { let task_path = self.get_task_path(task_id); + + // Calculate the target offset and length based on the range. + let (target_offset, target_length) = calculate_piece_range(offset, length, range); + let f = File::open(task_path.as_path()).await.map_err(|err| { error!("open {:?} failed: {}", task_path, err); err })?; let mut f_reader = BufReader::with_capacity(self.config.storage.read_buffer_size, f); - // Calculate the target offset and length based on the range. - let (target_offset, target_length) = if let Some(range) = range { - let target_offset = max(offset, range.start); - let target_length = - min(offset + length - 1, range.start + range.length - 1) - target_offset + 1; - (target_offset, target_length) - } else { - (offset, length) - }; - f_reader .seek(SeekFrom::Start(target_offset)) .await @@ -292,14 +286,7 @@ impl Content { let task_path = self.get_task_path(task_id); // Calculate the target offset and length based on the range. - let (target_offset, target_length) = if let Some(range) = range { - let target_offset = max(offset, range.start); - let target_length = - min(offset + length - 1, range.start + range.length - 1) - target_offset + 1; - (target_offset, target_length) - } else { - (offset, length) - }; + let (target_offset, target_length) = calculate_piece_range(offset, length, range); let f = File::open(task_path.as_path()).await.map_err(|err| { error!("open {:?} failed: {}", task_path, err); @@ -605,3 +592,95 @@ impl Content { Ok(task_dir.join(task_id)) } } + +/// calculate_piece_range calculates the target offset and length based on the piece range and +/// request range. +pub fn calculate_piece_range(offset: u64, length: u64, range: Option) -> (u64, u64) { + if let Some(range) = range { + let target_offset = max(offset, range.start); + let target_length = + min(offset + length - 1, range.start + range.length - 1) - target_offset + 1; + (target_offset, target_length) + } else { + (offset, length) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn should_calculate_piece_range() { + let test_cases = vec![ + (1, 4, None, 1, 4), + ( + 1, + 4, + Some(Range { + start: 1, + length: 4, + }), + 1, + 4, + ), + ( + 1, + 4, + Some(Range { + start: 2, + length: 1, + }), + 2, + 1, + ), + ( + 1, + 4, + Some(Range { + start: 1, + length: 1, + }), + 1, + 1, + ), + ( + 1, + 4, + Some(Range { + start: 4, + length: 1, + }), + 4, + 1, + ), + ( + 1, + 4, + Some(Range { + start: 0, + length: 2, + }), + 1, + 1, + ), + ( + 1, + 4, + Some(Range { + start: 4, + length: 3, + }), + 4, + 1, + ), + ]; + + for (piece_offset, piece_length, range, expected_offset, expected_length) in test_cases { + let (target_offset, target_length) = + calculate_piece_range(piece_offset, piece_length, range); + assert_eq!(target_offset, expected_offset); + assert_eq!(target_length, expected_length); + } + } +} diff --git a/dragonfly-client/src/proxy/cache.rs b/dragonfly-client/src/proxy/cache.rs index bb32365d..1d12588d 100644 --- a/dragonfly-client/src/proxy/cache.rs +++ b/dragonfly-client/src/proxy/cache.rs @@ -93,11 +93,11 @@ impl Cache { }; // Calculate the target offset and length based on the range. - let (target_offset, target_length) = - self.calculate_piece_range(interested_piece.offset, interested_piece.length, range); + let (piece_target_offset, piece_target_length) = + calculate_piece_range(interested_piece.offset, interested_piece.length, range); - let begin = target_offset; - let end = target_offset + target_length; + let begin = piece_target_offset; + let end = piece_target_offset + piece_target_length; if begin >= piece_content.len() || end > piece_content.len() { return Err(Error::InvalidParameter); } @@ -109,28 +109,6 @@ impl Cache { Ok(Some(content.freeze())) } - /// calculate_piece_range calculates the target offset and length based on the piece range and - /// request range. - fn calculate_piece_range( - &self, - piece_offset: u64, - piece_length: u64, - range: Option, - ) -> (usize, usize) { - if let Some(range) = range { - let target_offset = max(piece_offset, range.start) - piece_offset; - - let interested_piece_end = piece_offset + piece_length - 1; - let range_end = range.start + range.length - 1; - let target_length = - min(interested_piece_end, range_end) - target_offset - piece_offset + 1; - - (target_offset as usize, target_length as usize) - } else { - (0, piece_length as usize) - } - } - /// get_piece gets the piece content from the cache. pub fn get_piece(&self, id: &str) -> Option { let mut pieces = self.pieces.lock().unwrap(); @@ -154,3 +132,96 @@ impl Cache { pieces.contains(id) } } + +/// calculate_piece_range calculates the target offset and length based on the piece range and +/// request range. +pub fn calculate_piece_range(offset: u64, length: u64, range: Option) -> (usize, usize) { + if let Some(range) = range { + let target_offset = max(offset, range.start) - offset; + let target_length = + min(offset + length - 1, range.start + range.length - 1) - target_offset - offset + 1; + + (target_offset as usize, target_length as usize) + } else { + (0, length as usize) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn should_calculate_piece_range() { + let test_cases = vec![ + (1, 4, None, 0, 4), + ( + 1, + 4, + Some(Range { + start: 1, + length: 4, + }), + 0, + 4, + ), + ( + 1, + 4, + Some(Range { + start: 2, + length: 1, + }), + 1, + 1, + ), + ( + 1, + 4, + Some(Range { + start: 1, + length: 1, + }), + 0, + 1, + ), + ( + 1, + 4, + Some(Range { + start: 4, + length: 1, + }), + 3, + 1, + ), + ( + 1, + 4, + Some(Range { + start: 0, + length: 2, + }), + 0, + 1, + ), + ( + 1, + 4, + Some(Range { + start: 4, + length: 3, + }), + 3, + 1, + ), + ]; + + for (piece_offset, piece_length, range, expected_offset, expected_length) in test_cases { + let (target_offset, target_length) = + calculate_piece_range(piece_offset, piece_length, range); + assert_eq!(target_offset, expected_offset); + assert_eq!(target_length, expected_length); + } + } +} diff --git a/dragonfly-client/src/proxy/mod.rs b/dragonfly-client/src/proxy/mod.rs index 04e70562..9292d2ce 100644 --- a/dragonfly-client/src/proxy/mod.rs +++ b/dragonfly-client/src/proxy/mod.rs @@ -887,6 +887,8 @@ async fn proxy_via_dfdaemon( } }; + // When the piece reader reads to the end, add the piece + // to the cache. if n == 0 { cache.add_piece(&piece_id, content.freeze()); break;