use std::{collections::HashSet, marker::PhantomData, sync::Arc};
use anyhow::Result;
use async_trait::async_trait;
use hotshot_task_impls::events::HotShotEvent;
use hotshot_types::traits::node_implementation::{NodeType, TestableNodeImplementation};
use thiserror::Error;
use crate::test_task::{TestResult, TestTaskState};
#[derive(Error, Debug, Clone)]
pub enum ViewSyncTaskError {
#[error("{} nodes hit view sync", hit_view_sync.len())]
HitViewSync { hit_view_sync: HashSet<usize> },
}
pub struct ViewSyncTask<TYPES: NodeType, I: TestableNodeImplementation<TYPES>> {
pub(crate) hit_view_sync: HashSet<usize>,
pub(crate) description: ViewSyncTaskDescription,
pub(crate) _pd: PhantomData<(TYPES, I)>,
}
#[async_trait]
impl<TYPES: NodeType, I: TestableNodeImplementation<TYPES>> TestTaskState
for ViewSyncTask<TYPES, I>
{
type Event = Arc<HotShotEvent<TYPES>>;
async fn handle_event(&mut self, (event, id): (Self::Event, usize)) -> Result<()> {
match event.as_ref() {
HotShotEvent::ViewSyncTimeout(_, _, _)
| HotShotEvent::ViewSyncPreCommitVoteRecv(_)
| HotShotEvent::ViewSyncCommitVoteRecv(_)
| HotShotEvent::ViewSyncFinalizeVoteRecv(_)
| HotShotEvent::ViewSyncPreCommitVoteSend(_)
| HotShotEvent::ViewSyncCommitVoteSend(_)
| HotShotEvent::ViewSyncFinalizeVoteSend(_)
| HotShotEvent::ViewSyncPreCommitCertificate2Recv(_)
| HotShotEvent::ViewSyncCommitCertificate2Recv(_)
| HotShotEvent::ViewSyncFinalizeCertificate2Recv(_)
| HotShotEvent::ViewSyncPreCommitCertificate2Send(_, _)
| HotShotEvent::ViewSyncCommitCertificate2Send(_, _)
| HotShotEvent::ViewSyncFinalizeCertificate2Send(_, _)
| HotShotEvent::ViewSyncTrigger(_) => {
self.hit_view_sync.insert(id);
}
_ => (),
}
Ok(())
}
async fn check(&self) -> TestResult {
match self.description.clone() {
ViewSyncTaskDescription::Threshold(min, max) => {
let num_hits = self.hit_view_sync.len();
if min <= num_hits && num_hits <= max {
TestResult::Pass
} else {
TestResult::Fail(Box::new(ViewSyncTaskError::HitViewSync {
hit_view_sync: self.hit_view_sync.clone(),
}))
}
}
}
}
}
#[derive(Clone, Debug, Copy)]
pub enum ShouldHitViewSync {
Yes,
No,
Ignore,
}
#[derive(Clone, Debug)]
pub enum ViewSyncTaskDescription {
Threshold(usize, usize),
}