Event as trait

This commit is contained in:
Andrea Fioraldi 2020-12-15 11:28:15 +01:00
parent 39229e1013
commit a739b91e2a
3 changed files with 502 additions and 277 deletions

View File

@ -6,7 +6,7 @@ use core::marker::PhantomData;
use hashbrown::HashMap;
use crate::corpus::{Corpus, Testcase};
use crate::events::{Event, EventManager};
use crate::events::EventManager;
use crate::executors::{Executor, ExecutorsTuple, HasObservers};
use crate::feedbacks::FeedbacksTuple;
use crate::generators::Generator;
@ -211,15 +211,11 @@ where
if !self.add_if_interesting(corpus, input, fitness)?.is_none() {
added += 1;
}
manager.fire(Event::LoadInitial {
sender_id: 0,
phantom: PhantomData,
})?;
}
manager.fire(Event::log(
manager.log(
0,
format!("Loaded {} over {} initial testcases", added, num),
))?;
)?;
manager.process(self, corpus)?;
Ok(())
}
@ -339,10 +335,7 @@ where
let cur = current_milliseconds();
if cur - last > 60 * 100 {
last = cur;
manager.fire(Event::update_stats(
state.executions(),
state.executions_over_seconds(),
))?;
manager.update_stats(state.executions(), state.executions_over_seconds())?;
}
}
}

View File

@ -19,7 +19,7 @@ use crate::executors::Executor;
use crate::feedbacks::FeedbacksTuple;
use crate::inputs::Input;
use crate::observers::ObserversTuple;
use crate::serde_anymap::SerdeAny;
use crate::serde_anymap::Ptr;
use crate::utils::Rand;
use crate::AflError;
use crate::{engines::State, utils};
@ -42,8 +42,9 @@ pub struct ClientStats {
executions: u64,
}
/*
/// A custom event, for own messages, with own handler.
pub trait CustomEvent<I, OT>: SerdeAny + Serialize
pub trait CustomEvent<I>: SerdeAny
where
I: Input,
{
@ -54,135 +55,32 @@ where
/// This method will be called in the clients after handle_in_broker (unless BrokerEventResult::Handled) was returned in handle_in_broker
fn handle_in_client(&self) -> Result<(), AflError>;
}
*/
/// Events sent around in the library
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub enum Event<I>
pub trait Event<I>
where
I: Input,
{
LoadInitial {
sender_id: u64,
phantom: PhantomData<I>,
},
NewTestcase {
sender_id: u64,
input: I,
observers_buf: Vec<u8>,
client_config: String,
},
UpdateStats {
sender_id: u64,
executions: usize,
execs_over_sec: u64,
phantom: PhantomData<I>,
},
Crash {
sender_id: u64,
input: I,
phantom: PhantomData<I>,
},
Timeout {
sender_id: u64,
input: I,
phantom: PhantomData<I>,
},
Log {
sender_id: u64,
severity_level: u8,
message: String,
phantom: PhantomData<I>,
},
None {
phantom: PhantomData<I>,
},
Custom {
sender_id: u64,
// TODO: Allow custom events
// custom_event: Box<dyn CustomEvent<I, OT>>,
},
}
impl<I> Event<I>
where
I: Input,
{
pub fn name(&self) -> &str {
match self {
Event::LoadInitial {
sender_id: _,
phantom: _,
} => "Initial",
Event::NewTestcase {
sender_id: _,
input: _,
client_config: _,
observers_buf: _,
} => "New Testcase",
Event::UpdateStats {
sender_id: _,
executions: _,
execs_over_sec: _,
phantom: _,
} => "Stats",
Event::Crash {
sender_id: _,
input: _,
phantom: _,
} => "Crash",
Event::Timeout {
sender_id: _,
input: _,
phantom: _,
} => "Timeout",
Event::Log {
sender_id: _,
severity_level: _,
message: _,
phantom: _,
} => "Log",
Event::None { phantom: _ } => "None",
Event::Custom {
sender_id: _, /*custom_event} => custom_event.name()*/
} => "todo",
}
}
pub fn log(severity_level: u8, message: String) -> Self {
Event::Log {
sender_id: 0,
severity_level: severity_level,
message: message,
phantom: PhantomData,
}
}
pub fn new_testcase<OT>(config: String, input: I, observers: &OT) -> Result<Self, AflError>
/// Returns the name of this event
fn name(&self) -> &str;
/// This method will be called in the broker
fn handle_in_broker(&self, stats: &mut Stats) -> Result<BrokerEventResult, AflError>;
/// This method will be called in the clients after handle_in_broker (unless BrokerEventResult::Handled) was returned in handle_in_broker
fn handle_in_client<C, OT, FT, R>(
self,
state: &mut State<I, R, FT, OT>,
corpus: &mut C,
) -> Result<(), AflError>
where
C: Corpus<I, R>,
OT: ObserversTuple,
{
let observers_buf = postcard::to_allocvec(observers)?;
Ok(Self::NewTestcase {
sender_id: 0,
input: input,
client_config: config,
observers_buf: observers_buf,
})
}
pub fn update_stats(executions: usize, execs_over_sec: u64) -> Self {
Event::UpdateStats {
sender_id: 0,
executions: executions,
execs_over_sec: execs_over_sec,
phantom: PhantomData,
}
}
FT: FeedbacksTuple<I>,
R: Rand;
}
#[derive(Debug, Clone, Default)]
struct Stats {
pub struct Stats {
start_time: Duration,
corpus_size: usize,
client_stats: Vec<ClientStats>,
@ -240,114 +138,6 @@ impl Stats {
}
&mut self.client_stats_mut()[client_id as usize]
}
/// Broker fun
#[inline]
fn handle_in_broker<I>(&mut self, event: &Event<I>) -> Result<BrokerEventResult, AflError>
where
I: Input,
{
match event {
Event::LoadInitial {
sender_id,
phantom: _,
} => {
let client = self.client_stats_mut_for(*sender_id);
client.corpus_size += 1;
Ok(BrokerEventResult::Handled)
}
Event::NewTestcase {
sender_id,
input: _,
observers_buf: _,
client_config: _,
} => {
let client = self.client_stats_mut_for(*sender_id);
client.corpus_size += 1;
println!("[NEW] client {}: corpus: {}", sender_id, self.corpus_size(),);
Ok(BrokerEventResult::Forward)
}
Event::UpdateStats {
sender_id,
executions,
execs_over_sec: _,
phantom: _,
} => {
// TODO: The stats buffer should be added on client add.
let client = self.client_stats_mut_for(*sender_id);
client.executions += *executions as u64;
println!(
"[UPDATE] from client {}, corpus: {} execs: {} execs/s: {}",
sender_id,
self.corpus_size(),
self.total_execs(),
self.execs_per_sec()
);
Ok(BrokerEventResult::Handled)
}
Event::Crash {
sender_id: _,
input: _,
phantom: _,
} => {
panic!("LoggerEventManager cannot handle Event::Crash");
}
Event::Timeout {
sender_id: _,
input: _,
phantom: _,
} => {
panic!("LoggerEventManager cannot handle Event::Timeout");
}
Event::Log {
sender_id: _,
severity_level,
message,
phantom: _,
} => {
println!("[LOG {}]: {}", severity_level, message);
Ok(BrokerEventResult::Handled)
}
_ => Ok(BrokerEventResult::Forward),
}
}
}
/// Client fun
#[inline]
fn handle_in_client<C, OT, FT, I, R>(
event: Event<I>,
state: &mut State<I, R, FT, OT>,
corpus: &mut C,
) -> Result<(), AflError>
where
C: Corpus<I, R>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
I: Input,
R: Rand,
{
match event {
Event::NewTestcase {
sender_id: _,
input,
observers_buf,
client_config: _,
} => {
// TODO: here u should match client_config, if equal to the current one do not re-execute
// we need to pass engine to process() too, TODO
#[cfg(feature = "std")]
println!("Received new Testcase");
let observers = postcard::from_bytes(&observers_buf)?;
let interestingness = state.is_interesting(&input, &observers)?;
state.add_if_interesting(corpus, input, interestingness)?;
Ok(())
}
_ => Err(AflError::Unknown(format!(
"Received illegal message that message should not have arrived: {:?}.",
event
))),
}
}
pub trait EventManager<C, E, OT, FT, I, R>
@ -360,7 +150,7 @@ where
R: Rand,
{
/// Fire an Event
fn fire<'a>(&mut self, event: Event<I>) -> Result<(), AflError>;
//fn fire<'a>(&mut self, event: Event<I>) -> Result<(), AflError>;
/// Lookup for incoming events and process them.
/// Return the number of processes events or an error
@ -377,9 +167,160 @@ where
fn deserialize_observers(&mut self, observers_buf: &[u8]) -> Result<OT, AflError> {
Ok(postcard::from_bytes(observers_buf)?)
}
fn new_testcase(
&mut self,
_input: &I,
_observers: &OT,
_corpus_size: usize,
_config: String,
) -> Result<(), AflError> {
Ok(())
}
fn update_stats(&mut self, _executions: usize, _execs_over_sec: u64) -> Result<(), AflError> {
Ok(())
}
fn crash(&mut self, _input: &I) -> Result<(), AflError> {
Ok(())
}
fn timeout(&mut self, _input: &I) -> Result<(), AflError> {
Ok(())
}
fn log(&mut self, _severity_level: u8, _message: String) -> Result<(), AflError> {
Ok(())
}
// TODO Custom event fire (dyn CustomEvent or similar)
}
#[derive(Debug)]
pub enum LoggerEvent<I>
where
I: Input,
{
NewTestcase {
corpus_size: usize,
phantom: PhantomData<I>,
},
UpdateStats {
executions: usize,
execs_over_sec: u64,
phantom: PhantomData<I>,
},
Crash {
input: I,
},
Timeout {
input: I,
},
Log {
severity_level: u8,
message: String,
phantom: PhantomData<I>,
},
/*Custom {
// TODO: Allow custom events
// custom_event: Box<dyn CustomEvent<I, OT>>,
},*/
}
impl<I> Event<I> for LoggerEvent<I>
where
I: Input,
{
#[inline]
fn name(&self) -> &str {
match self {
LoggerEvent::NewTestcase {
corpus_size: _,
phantom: _,
} => "New Testcase",
LoggerEvent::UpdateStats {
executions: _,
execs_over_sec: _,
phantom: _,
} => "Stats",
LoggerEvent::Crash { input: _ } => "Crash",
LoggerEvent::Timeout { input: _ } => "Timeout",
LoggerEvent::Log {
severity_level: _,
message: _,
phantom: _,
} => "Log",
/*Event::Custom => custom_event.name()
} => "todo",*/
}
}
/// Broker fun
#[inline]
fn handle_in_broker(&self, stats: &mut Stats) -> Result<BrokerEventResult, AflError> {
match self {
LoggerEvent::NewTestcase {
corpus_size,
phantom: _,
} => {
stats.client_stats_mut()[0].corpus_size = *corpus_size as u64;
println!("[NEW] corpus: {}", stats.corpus_size());
Ok(BrokerEventResult::Handled)
}
LoggerEvent::UpdateStats {
executions,
execs_over_sec: _,
phantom: _,
} => {
// TODO: The stats buffer should be added on client add.
stats.client_stats_mut()[0].executions = *executions as u64;
println!(
"[UPDATE] corpus: {} execs: {} execs/s: {}",
stats.corpus_size(),
stats.total_execs(),
stats.execs_per_sec()
);
Ok(BrokerEventResult::Handled)
}
LoggerEvent::Crash { input: _ } => {
panic!("LoggerEventManager cannot handle Event::Crash");
}
LoggerEvent::Timeout { input: _ } => {
panic!("LoggerEventManager cannot handle Event::Timeout");
}
LoggerEvent::Log {
severity_level,
message,
phantom: _,
} => {
println!("[LOG {}]: {}", severity_level, message);
Ok(BrokerEventResult::Handled)
} //_ => Ok(BrokerEventResult::Forward),
}
}
#[inline]
fn handle_in_client<C, OT, FT, R>(
self,
_state: &mut State<I, R, FT, OT>,
_corpus: &mut C,
) -> Result<(), AflError>
where
C: Corpus<I, R>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
R: Rand,
{
match self {
_ => Err(AflError::Unknown(format!(
"Received illegal message that message should not have arrived: {:?}.",
self
))),
}
}
}
#[cfg(feature = "std")]
pub struct LoggerEventManager<C, E, OT, FT, I, R, W>
where
C: Corpus<I, R>,
@ -394,12 +335,11 @@ where
writer: W,
stats: Stats,
events: Vec<Event<I>>,
events: Vec<LoggerEvent<I>>,
// stats (maybe we need a separated struct?)
phantom: PhantomData<(C, E, I, R, OT, FT)>,
}
#[cfg(feature = "std")]
impl<C, E, OT, FT, I, R, W> EventManager<C, E, OT, FT, I, R>
for LoggerEventManager<C, E, OT, FT, I, R, W>
where
@ -412,16 +352,6 @@ where
W: Write,
//CE: CustomEvent<I, OT>,
{
#[inline]
fn fire<'a>(&mut self, event: Event<I>) -> Result<(), AflError> {
match self.stats.handle_in_broker(&event)? {
BrokerEventResult::Forward => self.events.push(event),
// Ignore broker-only events
BrokerEventResult::Handled => (),
}
Ok(())
}
fn process(
&mut self,
state: &mut State<I, R, FT, OT>,
@ -430,12 +360,77 @@ where
let count = self.events.len();
self.events
.drain(..)
.try_for_each(|event| handle_in_client(event, state, corpus))?;
.try_for_each(|event| event.handle_in_client(state, corpus))?;
Ok(count)
}
fn new_testcase(
&mut self,
_input: &I,
_observers: &OT,
corpus_size: usize,
_config: String,
) -> Result<(), AflError> {
let event = LoggerEvent::NewTestcase {
corpus_size: corpus_size,
phantom: PhantomData,
};
match event.handle_in_broker(&mut self.stats)? {
BrokerEventResult::Forward => self.events.push(event),
_ => (),
};
Ok(())
}
fn update_stats(&mut self, executions: usize, execs_over_sec: u64) -> Result<(), AflError> {
let event = LoggerEvent::UpdateStats {
executions: executions,
execs_over_sec: execs_over_sec,
phantom: PhantomData,
};
match event.handle_in_broker(&mut self.stats)? {
BrokerEventResult::Forward => self.events.push(event),
_ => (),
};
Ok(())
}
fn crash(&mut self, input: &I) -> Result<(), AflError> {
let event = LoggerEvent::Crash {
input: input.clone(),
};
match event.handle_in_broker(&mut self.stats)? {
BrokerEventResult::Forward => self.events.push(event),
_ => (),
};
Ok(())
}
fn timeout(&mut self, input: &I) -> Result<(), AflError> {
let event = LoggerEvent::Timeout {
input: input.clone(),
};
match event.handle_in_broker(&mut self.stats)? {
BrokerEventResult::Forward => self.events.push(event),
_ => (),
};
Ok(())
}
fn log(&mut self, severity_level: u8, message: String) -> Result<(), AflError> {
let event = LoggerEvent::Log {
severity_level: severity_level,
message: message,
phantom: PhantomData,
};
match event.handle_in_broker(&mut self.stats)? {
BrokerEventResult::Forward => self.events.push(event),
_ => (),
};
Ok(())
}
}
#[cfg(feature = "std")]
impl<C, E, OT, FT, I, R, W> LoggerEventManager<C, E, OT, FT, I, R, W>
where
C: Corpus<I, R>,
@ -460,6 +455,173 @@ where
}
}
#[cfg(feature = "std")]
#[derive(Serialize, Deserialize)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub enum LLMPEventKind<'a, I>
where
I: Input,
{
NewTestcase {
input: Ptr<'a, I>,
observers_buf: Vec<u8>,
corpus_size: usize,
client_config: String,
},
UpdateStats {
executions: usize,
execs_over_sec: u64,
phantom: PhantomData<&'a I>,
},
Crash {
input: I,
},
Timeout {
input: I,
},
Log {
severity_level: u8,
message: String,
phantom: PhantomData<I>,
},
/*Custom {
// TODO: Allow custom events
// custom_event: Box<dyn CustomEvent<I, OT>>,
},*/
}
#[cfg(feature = "std")]
#[derive(Serialize, Deserialize)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct LLMPEvent<'a, I>
where
I: Input,
{
sender_id: u64,
kind: LLMPEventKind<'a, I>,
}
#[cfg(feature = "std")]
impl<'a, I> Event<I> for LLMPEvent<'a, I>
where
I: Input,
{
fn name(&self) -> &str {
match self.kind {
LLMPEventKind::NewTestcase {
input: _,
client_config: _,
corpus_size: _,
observers_buf: _,
} => "New Testcase",
LLMPEventKind::UpdateStats {
executions: _,
execs_over_sec: _,
phantom: _,
} => "Stats",
LLMPEventKind::Crash { input: _ } => "Crash",
LLMPEventKind::Timeout { input: _ } => "Timeout",
LLMPEventKind::Log {
severity_level: _,
message: _,
phantom: _,
} => "Log",
/*Event::Custom {
sender_id: _, /*custom_event} => custom_event.name()*/
} => "todo",*/
}
}
/// Broker fun
#[inline]
fn handle_in_broker(&self, stats: &mut Stats) -> Result<BrokerEventResult, AflError> {
match &self.kind {
LLMPEventKind::NewTestcase {
input: _,
client_config: _,
corpus_size,
observers_buf: _,
} => {
let client = stats.client_stats_mut_for(self.sender_id);
client.corpus_size = *corpus_size as u64;
println!("[NEW] corpus: {}", stats.corpus_size());
Ok(BrokerEventResult::Handled)
}
LLMPEventKind::UpdateStats {
executions,
execs_over_sec: _,
phantom: _,
} => {
// TODO: The stats buffer should be added on client add.
let client = stats.client_stats_mut_for(self.sender_id);
client.executions = *executions as u64;
println!(
"[UPDATE] corpus: {} execs: {} execs/s: {}",
stats.corpus_size(),
stats.total_execs(),
stats.execs_per_sec()
);
Ok(BrokerEventResult::Handled)
}
LLMPEventKind::Crash { input: _ } => {
panic!("LoggerEventManager cannot handle Event::Crash");
}
LLMPEventKind::Timeout { input: _ } => {
panic!("LoggerEventManager cannot handle Event::Timeout");
}
LLMPEventKind::Log {
severity_level,
message,
phantom: _,
} => {
println!("[LOG {}]: {}", severity_level, message);
Ok(BrokerEventResult::Handled)
}
_ => Ok(BrokerEventResult::Forward),
}
}
#[inline]
fn handle_in_client<C, OT, FT, R>(
self,
state: &mut State<I, R, FT, OT>,
corpus: &mut C,
) -> Result<(), AflError>
where
C: Corpus<I, R>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
R: Rand,
{
match self.kind {
LLMPEventKind::NewTestcase {
input,
client_config: _,
corpus_size: _,
observers_buf,
} => {
// TODO: here u should match client_config, if equal to the current one do not re-execute
// we need to pass engine to process() too, TODO
#[cfg(feature = "std")]
println!("Received new Testcase");
let observers = postcard::from_bytes(&observers_buf)?;
let interestingness = state.is_interesting(input.as_ref(), &observers)?;
match input {
Ptr::Owned(b) => {
state.add_if_interesting(corpus, *b, interestingness)?;
}
_ => {}
};
Ok(())
}
_ => Err(AflError::Unknown(format!(
"Received illegal message that message should not have arrived: {:?}.",
self.name()
))),
}
}
}
#[cfg(feature = "std")]
/// Forward this to the client
const _LLMP_TAG_EVENT_TO_CLIENT: llmp::Tag = 0x2C11E471;
@ -532,8 +694,8 @@ where
broker.loop_forever(
&mut |_client_id: u32, tag: Tag, msg: &[u8]| {
if tag == LLMP_TAG_EVENT_TO_BOTH {
let event = postcard::from_bytes(msg)?;
match stats.handle_in_broker::<I>(&event)? {
let event: LLMPEvent<I> = postcard::from_bytes(msg)?;
match event.handle_in_broker(stats)? {
BrokerEventResult::Forward => {
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
}
@ -551,6 +713,13 @@ where
)),
}
}
#[inline]
fn llmp_send<'a>(&mut self, event: LLMPEvent<'a, I>) -> Result<(), AflError> {
let serialized = postcard::to_allocvec(&event)?;
self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?;
Ok(())
}
}
#[cfg(feature = "std")]
@ -566,13 +735,6 @@ where
W: Write,
//CE: CustomEvent<I>,
{
#[inline]
fn fire<'a>(&mut self, event: Event<I>) -> Result<(), AflError> {
let serialized = postcard::to_allocvec(&event)?;
self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?;
Ok(())
}
fn process(
&mut self,
state: &mut State<I, R, FT, OT>,
@ -588,8 +750,8 @@ where
if tag == _LLMP_TAG_EVENT_TO_BROKER {
continue;
}
let event: Event<I> = postcard::from_bytes(event_buf)?;
handle_in_client(event, state, corpus)?;
let event: LLMPEvent<I> = postcard::from_bytes(event_buf)?;
event.handle_in_client(state, corpus)?;
count += 1;
}
None => break count,
@ -602,16 +764,81 @@ where
}
})
}
fn new_testcase(
&mut self,
input: &I,
observers: &OT,
corpus_size: usize,
config: String,
) -> Result<(), AflError> {
let event = LLMPEvent {
sender_id: 0,
kind: LLMPEventKind::NewTestcase {
input: Ptr::Ref(input),
observers_buf: postcard::to_allocvec(observers)?,
corpus_size: corpus_size,
client_config: config,
},
};
self.llmp_send(event)
}
fn update_stats(&mut self, executions: usize, execs_over_sec: u64) -> Result<(), AflError> {
let event = LLMPEvent {
sender_id: 0,
kind: LLMPEventKind::UpdateStats {
executions: executions,
execs_over_sec: execs_over_sec,
phantom: PhantomData,
},
};
self.llmp_send(event)
}
fn crash(&mut self, input: &I) -> Result<(), AflError> {
let event = LLMPEvent {
sender_id: 0,
kind: LLMPEventKind::Crash {
input: input.clone(),
},
};
self.llmp_send(event)
}
fn timeout(&mut self, input: &I) -> Result<(), AflError> {
let event = LLMPEvent {
sender_id: 0,
kind: LLMPEventKind::Timeout {
input: input.clone(),
},
};
self.llmp_send(event)
}
fn log(&mut self, severity_level: u8, message: String) -> Result<(), AflError> {
let event = LLMPEvent {
sender_id: 0,
kind: LLMPEventKind::Log {
severity_level: severity_level,
message: message,
phantom: PhantomData,
},
};
self.llmp_send(event)
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod tests {
use crate::events::{LLMPEvent, LLMPEventKind};
use crate::inputs::bytes::BytesInput;
use crate::observers::ObserversTuple;
use crate::observers::StdMapObserver;
use crate::serde_anymap::Ptr;
use crate::tuples::{tuple_list, MatchNameAndType, Named};
use crate::{events::Event, observers::ObserversTuple};
static mut MAP: [u32; 4] = [0; 4];
#[test]
@ -622,20 +849,24 @@ mod tests {
// test_event_mgr.serialize_observers(&map).unwrap();
let i = BytesInput::new(vec![0]);
let e = Event::NewTestcase {
let e = LLMPEvent {
sender_id: 0,
input: i,
observers_buf,
client_config: "conf".into(),
kind: LLMPEventKind::NewTestcase {
input: Ptr::Ref(&i),
observers_buf,
corpus_size: 123,
client_config: "conf".into(),
},
};
let serialized = postcard::to_allocvec(&e).unwrap();
match postcard::from_bytes::<Event<BytesInput>>(&serialized).unwrap() {
Event::NewTestcase {
sender_id: _,
let d = postcard::from_bytes::<LLMPEvent<BytesInput>>(&serialized).unwrap();
match d.kind {
LLMPEventKind::NewTestcase {
input: _,
observers_buf,
corpus_size: _,
client_config: _,
} => {
let o = map.deserialize(&observers_buf).unwrap();

View File

@ -1,5 +1,6 @@
use core::marker::PhantomData;
use crate::engines::State;
use crate::events::EventManager;
use crate::executors::{Executor, ExecutorsTuple, HasObservers};
use crate::feedbacks::FeedbacksTuple;
@ -10,7 +11,6 @@ use crate::stages::Corpus;
use crate::stages::{Engine, Stage};
use crate::utils::Rand;
use crate::AflError;
use crate::{engines::State, events::Event};
// TODO multi mutators stage
@ -73,7 +73,8 @@ where
// if needed by particular cases
if fitness > 0 {
// TODO decouple events manager and engine
manager.fire(Event::new_testcase("test".into(), input_mut, observers)?)?;
manager.new_testcase(&input_mut, observers, corpus.count() + 1, "test".into())?;
state.add_if_interesting(corpus, input_mut, fitness)?;
// let _ = corpus.add(testcase);
} else {
state.discard_input(&input_mut)?;