List observer and feedback (#553)

This commit is contained in:
Andrea Fioraldi 2022-02-23 10:26:46 +01:00 committed by GitHub
parent ef01009f30
commit 5ffddcfd4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 128 additions and 1 deletions

View File

@ -32,7 +32,7 @@ use crate::{
events::EventFirer, events::EventFirer,
executors::ExitKind, executors::ExitKind,
inputs::Input, inputs::Input,
observers::{ObserversTuple, TimeObserver}, observers::{ListObserver, ObserversTuple, TimeObserver},
state::HasClientPerfMonitor, state::HasClientPerfMonitor,
Error, Error,
}; };
@ -913,3 +913,74 @@ impl TimeFeedback {
} }
} }
} }
/// Consider interesting a testcase if the list in ListObserver is not empty.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ListFeedback<T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
name: String,
phantom: PhantomData<T>,
}
impl<I, S, T> Feedback<I, S> for ListFeedback<T>
where
I: Input,
S: HasClientPerfMonitor,
T: Debug + Serialize + serde::de::DeserializeOwned,
{
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<I>,
OT: ObserversTuple<I, S>,
{
// TODO Replace with match_name_type when stable
let observer = observers
.match_name::<ListObserver<T>>(self.name())
.unwrap();
// TODO register the list content in a testcase metadata
Ok(!observer.list().is_empty())
}
}
impl<T> Named for ListFeedback<T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
}
}
impl<T> ListFeedback<T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
/// Creates a new [`ListFeedback`], deciding if the value of a [`ListObserver`] with the given `name` of a run is interesting.
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {
name: name.to_string(),
phantom: PhantomData,
}
}
/// Creates a new [`TimeFeedback`], deciding if the given [`ListObserver`] value of a run is interesting.
#[must_use]
pub fn new_with_observer(observer: &ListObserver<T>) -> Self {
Self {
name: observer.name().to_string(),
phantom: PhantomData,
}
}
}

View File

@ -30,6 +30,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
bolts::{ bolts::{
current_time, current_time,
ownedref::OwnedRefMut,
tuples::{MatchName, Named}, tuples::{MatchName, Named},
}, },
executors::ExitKind, executors::ExitKind,
@ -229,6 +230,61 @@ impl Named for TimeObserver {
} }
} }
/// A simple observer with a list of things.
#[derive(Serialize, Deserialize, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct ListObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
name: String,
/// The list
list: OwnedRefMut<'a, Vec<T>>,
}
impl<'a, T> ListObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
/// Creates a new [`ListObserver`] with the given name.
#[must_use]
pub fn new(name: &'static str, list: &'a mut Vec<T>) -> Self {
Self {
name: name.to_string(),
list: OwnedRefMut::Ref(list),
}
}
/// Get a list ref
pub fn list(&self) -> &Vec<T> {
self.list.as_ref()
}
/// Get a list mut
pub fn list_mut(&mut self) -> &mut Vec<T> {
self.list.as_mut()
}
}
impl<'a, I, S, T> Observer<I, S> for ListObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
self.list.as_mut().clear();
Ok(())
}
}
impl<'a, T> Named for ListObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn name(&self) -> &str {
&self.name
}
}
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {