use super::*;
#[test]
fn atomic_progress_hint_default() {
assert_eq!(
ProgressHint::default(),
AtomicProgressHint::default().peek()
);
}
#[test]
fn atomic_progress_hint_sequence() {
let progress_hint = AtomicProgressHint::default();
assert_eq!(ProgressHint::Continue, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Accepted {
previous_state: ProgressHint::Continue,
},
progress_hint.suspend().unwrap()
);
assert_eq!(ProgressHint::Suspend, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Ignored,
progress_hint.suspend().unwrap()
);
assert_eq!(ProgressHint::Suspend, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Accepted {
previous_state: ProgressHint::Suspend,
},
progress_hint.resume().unwrap()
);
assert_eq!(ProgressHint::Continue, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Ignored,
progress_hint.resume().unwrap()
);
assert_eq!(ProgressHint::Continue, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Accepted {
previous_state: ProgressHint::Continue,
},
progress_hint.finish().unwrap()
);
assert_eq!(ProgressHint::Finish, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Ignored,
progress_hint.finish().unwrap()
);
assert_eq!(ProgressHint::Finish, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Accepted {
previous_state: ProgressHint::Finish,
},
progress_hint.reset()
);
assert_eq!(ProgressHint::Continue, progress_hint.load());
assert_eq!(SwitchAtomicStateOk::Ignored, progress_hint.reset());
assert_eq!(ProgressHint::Continue, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Accepted {
previous_state: ProgressHint::Continue,
},
progress_hint.suspend().unwrap()
);
assert_eq!(ProgressHint::Suspend, progress_hint.load());
assert_eq!(
SwitchAtomicStateOk::Accepted {
previous_state: ProgressHint::Suspend,
},
progress_hint.finish().unwrap()
);
assert_eq!(ProgressHint::Finish, progress_hint.load());
assert_eq!(
Err(SwitchAtomicStateErr::Rejected {
current_state: ProgressHint::Finish,
}),
progress_hint.suspend()
);
assert_eq!(ProgressHint::Finish, progress_hint.load());
assert_eq!(
Err(SwitchAtomicStateErr::Rejected {
current_state: ProgressHint::Finish,
}),
progress_hint.resume()
);
assert_eq!(ProgressHint::Finish, progress_hint.load());
}
#[test]
fn progress_hint_sender_receiver_attach_detach() -> anyhow::Result<()> {
let mut rx = ProgressHintReceiver::default();
let tx1 = ProgressHintSender::attach(&rx);
assert!(tx1.is_attached());
assert_eq!(
SwitchProgressHintOk::Accepted {
previous_state: ProgressHint::Continue,
},
tx1.suspend()?
);
assert_eq!(ProgressHint::Suspend, rx.load());
#[allow(clippy::redundant_clone)]
let tx2 = tx1.clone();
assert!(tx2.is_attached());
assert_eq!(
SwitchProgressHintOk::Accepted {
previous_state: ProgressHint::Suspend,
},
tx2.resume()?
);
assert_eq!(ProgressHint::Continue, rx.load());
rx.detach();
assert!(!tx1.is_attached());
assert!(!tx2.is_attached());
assert!(matches!(
tx1.finish(),
Err(SwitchProgressHintError::Detached)
));
assert!(matches!(
tx2.finish(),
Err(SwitchProgressHintError::Detached)
));
Ok(())
}
#[test]
fn progress_hint_handover_temporal_decoupling_of_sender_receiver() -> anyhow::Result<()> {
let rx = ProgressHintReceiver::default();
assert!(!rx.wait_until(Instant::now()));
let tx = ProgressHintSender::attach(&rx);
assert!(tx.is_attached());
assert_eq!(
SwitchProgressHintOk::Accepted {
previous_state: ProgressHint::Continue,
},
tx.finish()?
);
assert_eq!(ProgressHint::Finish, rx.load());
drop(tx);
assert!(rx.wait_until(Instant::now()));
Ok(())
}
#[test]
fn progress_hint_handover_consume_single_update_notification_once() -> anyhow::Result<()> {
let rx = ProgressHintReceiver::default();
let tx = ProgressHintSender::attach(&rx);
assert!(tx.is_attached());
assert!(!rx.wait_until(Instant::now()));
assert_eq!(
SwitchProgressHintOk::Accepted {
previous_state: ProgressHint::Continue,
},
tx.suspend()?
);
assert_eq!(ProgressHint::Suspend, rx.load());
assert!(rx.wait_until(Instant::now()));
assert!(!rx.wait_until(Instant::now()));
assert_eq!(
SwitchProgressHintOk::Accepted {
previous_state: ProgressHint::Suspend,
},
tx.resume()?
);
assert_eq!(ProgressHint::Continue, rx.load());
assert_eq!(
SwitchProgressHintOk::Accepted {
previous_state: ProgressHint::Continue,
},
tx.finish()?
);
assert_eq!(ProgressHint::Finish, rx.load());
assert!(rx.wait_until(Instant::now()));
assert!(!rx.wait_until(Instant::now()));
Ok(())
}
#[test]
fn progress_hint_handover_try_switch_without_update_notification() {
let mut rx = ProgressHintReceiver::default();
assert!(!rx.wait_until(Instant::now()));
assert!(rx.try_suspending());
assert_eq!(ProgressHint::Suspend, rx.load());
assert!(!rx.wait_until(Instant::now()));
assert!(rx.try_finishing());
assert_eq!(ProgressHint::Finish, rx.load());
assert!(!rx.wait_until(Instant::now()));
}