test: 加入 status 方法的单元测试
This commit is contained in:
@@ -7,6 +7,7 @@ static STATUS_OK: u32 = 0b111;
|
||||
/// 从低位开始,固定每三位表示一种数据的状态,从 0b000 开始,每失败一次加一,最多 0b100(即重试 4 次),
|
||||
/// 如果成功,将对应的三位设置为 0b111。
|
||||
/// 当所有任务都成功或者由于尝试次数过多失败,为 status 最高位打上标记 1,将来不再继续尝试。
|
||||
#[derive(Clone)]
|
||||
pub struct Status(u32);
|
||||
|
||||
impl Status {
|
||||
@@ -20,13 +21,7 @@ impl Status {
|
||||
Self(status)
|
||||
}
|
||||
|
||||
/// 从低到高检查状态,如果该位置的任务应该继续尝试执行,则返回 true,否则返回 false
|
||||
fn should_run(&self, size: usize) -> Vec<bool> {
|
||||
assert!(size < 10, "u32 can only store 10 status");
|
||||
(0..size).map(|x| self.check_continue(x)).collect()
|
||||
}
|
||||
|
||||
/// 一般仅需要被内部调用
|
||||
/// 一般仅需要被内部调用,用来设置最高位的标记
|
||||
fn set_flag(&mut self, handled: bool) {
|
||||
if handled {
|
||||
self.0 |= 1 << 31;
|
||||
@@ -35,6 +30,19 @@ impl Status {
|
||||
}
|
||||
}
|
||||
|
||||
/// 从低到高检查状态,如果该位置的任务应该继续尝试执行,则返回 true,否则返回 false
|
||||
fn should_run(&self, size: usize) -> Vec<bool> {
|
||||
assert!(size < 10, "u32 can only store 10 status");
|
||||
(0..size).map(|x| self.check_continue(x)).collect()
|
||||
}
|
||||
|
||||
/// 如果任务的执行次数小于 STATUS_MAX_RETRY,说明可以继续运行
|
||||
fn check_continue(&self, offset: usize) -> bool {
|
||||
assert!(offset < 10, "u32 can only store 10 status");
|
||||
self.get_status(offset) < STATUS_MAX_RETRY
|
||||
}
|
||||
|
||||
/// 根据任务结果更新状态,如果任务成功,设置为 STATUS_OK,否则加一
|
||||
fn update_status(&mut self, result: &[Result<()>]) {
|
||||
assert!(result.len() < 10, "u32 can only store 10 status");
|
||||
for (i, res) in result.iter().enumerate() {
|
||||
@@ -46,16 +54,12 @@ impl Status {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_continue(&self, offset: usize) -> bool {
|
||||
assert!(offset < 10, "u32 can only store 10 status");
|
||||
let helper = !0u32;
|
||||
let sub_status = self.0 & (helper << (offset * 3)) & (helper >> (32 - 3 * offset - 3));
|
||||
sub_status < STATUS_MAX_RETRY
|
||||
}
|
||||
|
||||
fn set_result(&mut self, result: &Result<()>, offset: usize) {
|
||||
if result.is_ok() {
|
||||
self.set_ok(offset);
|
||||
// 如果任务已经执行到最大次数,那么此时 Result 也是 Ok,此时不应该更新状态
|
||||
if self.get_status(offset) < STATUS_MAX_RETRY {
|
||||
self.set_ok(offset);
|
||||
}
|
||||
} else {
|
||||
self.plus_one(offset);
|
||||
}
|
||||
@@ -68,6 +72,11 @@ impl Status {
|
||||
fn set_ok(&mut self, offset: usize) {
|
||||
self.0 |= STATUS_OK << (3 * offset);
|
||||
}
|
||||
|
||||
fn get_status(&self, offset: usize) -> u32 {
|
||||
let helper = !0u32;
|
||||
self.0 & (helper << (offset * 3)) & (helper >> (32 - 3 * offset - 3))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Status> for u32 {
|
||||
@@ -77,6 +86,7 @@ impl From<Status> for u32 {
|
||||
}
|
||||
|
||||
/// 从前到后分别表示:视频封面、分页下载、视频信息
|
||||
#[derive(Clone)]
|
||||
pub struct VideoStatus(Status);
|
||||
|
||||
impl VideoStatus {
|
||||
@@ -101,6 +111,7 @@ impl From<VideoStatus> for u32 {
|
||||
}
|
||||
|
||||
/// 从前到后分别表示:视频封面、视频内容、视频信息
|
||||
#[derive(Clone)]
|
||||
pub struct PageStatus(Status);
|
||||
|
||||
impl PageStatus {
|
||||
@@ -123,3 +134,22 @@ impl From<PageStatus> for u32 {
|
||||
status.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_status() {
|
||||
let mut status = Status::new(0);
|
||||
assert_eq!(status.should_run(3), vec![true, true, true]);
|
||||
for count in 1..=3 {
|
||||
status.update_status(&[Err("".into()), Ok(()), Ok(())]);
|
||||
assert_eq!(status.should_run(3), vec![true, false, false]);
|
||||
assert_eq!(u32::from(status.clone()), 0b111_111_000 + count);
|
||||
}
|
||||
status.update_status(&[Err("".into()), Ok(()), Ok(())]);
|
||||
assert_eq!(status.should_run(3), vec![false, false, false]);
|
||||
assert_eq!(u32::from(status), 0b111_111_100 | Status::handled());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user