use ic_management_canister_types::CanisterId;
use pocket_ic::PocketIc;
use std::sync::Arc;
use std::{path::PathBuf, slice::IterMut};
pub struct FuzzerState {
name: String,
state: Option<Arc<PocketIc>>,
canisters: Vec<CanisterInfo>,
}
pub struct CanisterInfo {
pub id: Option<CanisterId>,
pub name: String,
pub wasm_path: WasmPath,
pub ty: CanisterType,
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum CanisterType {
Coverage,
Support,
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
pub enum WasmPath {
EnvVar(String),
Path(PathBuf),
}
impl FuzzerState {
pub fn new(name: &str, canisters: Vec<CanisterInfo>) -> Self {
assert!(
canisters
.iter()
.filter(|c| c.ty == CanisterType::Coverage)
.count()
== 1,
"Only one coverage canister is allowed"
);
Self {
name: name.to_string(),
state: None,
canisters,
}
}
pub fn init_state(&mut self, state: PocketIc) {
self.state = Some(Arc::new(state));
}
pub fn name(&self) -> &str {
&self.name
}
pub(crate) fn get_coverage_canister_id(&self) -> CanisterId {
self.canisters
.iter()
.find(|c| c.ty == CanisterType::Coverage)
.unwrap()
.id
.unwrap()
}
pub(crate) fn get_state_machine(&self) -> Arc<PocketIc> {
self.state.as_ref().unwrap().clone()
}
pub fn get_canister_id_by_name(&self, name: &str) -> CanisterId {
self.canisters
.iter()
.find(|c| c.name == name)
.unwrap_or_else(|| panic!("Canister {name} not found"))
.id
.unwrap_or_else(|| panic!("CanisterId is not initialized for {name}"))
}
pub fn get_canister_wasm_path_by_name(&self, name: &str) -> WasmPath {
self.canisters
.iter()
.find(|c| c.name == name)
.unwrap_or_else(|| panic!("Canister {name} not found"))
.wasm_path
.clone()
}
pub fn get_canister_names(&self) -> Vec<String> {
self.canisters.iter().map(|c| c.name.clone()).collect()
}
pub fn get_iter_mut_canister_info(&mut self) -> IterMut<'_, CanisterInfo> {
self.canisters.iter_mut()
}
}