use alloc::string::String;
use core::{convert::Into, default::Default, option::Option, time::Duration};
use serde::{Deserialize, Serialize};
use crate::{
bolts::serdeany::SerdeAnyMap,
inputs::{HasLen, Input},
state::HasMetadata,
Error,
};
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct Testcase<I>
where
I: Input,
{
input: Option<I>,
filename: Option<String>,
metadata: SerdeAnyMap,
exec_time: Option<Duration>,
cached_len: Option<usize>,
}
impl<I> HasMetadata for Testcase<I>
where
I: Input,
{
#[inline]
fn metadata(&self) -> &SerdeAnyMap {
&self.metadata
}
#[inline]
fn metadata_mut(&mut self) -> &mut SerdeAnyMap {
&mut self.metadata
}
}
impl<I> Testcase<I>
where
I: Input,
{
pub fn load_input(&mut self) -> Result<&I, Error> {
if self.input.is_none() {
self.input = Some(I::from_file(self.filename.as_ref().unwrap())?);
}
Ok(self.input.as_ref().unwrap())
}
pub fn store_input(&mut self) -> Result<bool, Error> {
match self.filename() {
Some(fname) => {
let saved = match self.input() {
None => false,
Some(i) => {
i.to_file(fname)?;
true
}
};
if saved {
*self.input_mut() = None;
}
Ok(saved)
}
None => Ok(false),
}
}
#[inline]
pub fn input(&self) -> &Option<I> {
&self.input
}
#[inline]
pub fn input_mut(&mut self) -> &mut Option<I> {
&mut self.input
}
#[inline]
pub fn set_input(&mut self, input: I) {
self.input = Some(input);
}
#[inline]
pub fn filename(&self) -> &Option<String> {
&self.filename
}
#[inline]
pub fn filename_mut(&mut self) -> &mut Option<String> {
&mut self.filename
}
#[inline]
pub fn set_filename(&mut self, filename: String) {
self.filename = Some(filename);
}
#[inline]
pub fn exec_time(&self) -> &Option<Duration> {
&self.exec_time
}
#[inline]
pub fn exec_time_mut(&mut self) -> &mut Option<Duration> {
&mut self.exec_time
}
#[inline]
pub fn set_exec_time(&mut self, time: Duration) {
self.exec_time = Some(time);
}
#[inline]
pub fn new<T>(input: T) -> Self
where
T: Into<I>,
{
Testcase {
input: Some(input.into()),
filename: None,
metadata: SerdeAnyMap::new(),
exec_time: None,
cached_len: None,
}
}
#[inline]
pub fn with_filename(input: I, filename: String) -> Self {
Testcase {
input: Some(input),
filename: Some(filename),
metadata: SerdeAnyMap::new(),
exec_time: None,
cached_len: None,
}
}
#[must_use]
#[inline]
pub fn default() -> Self {
Testcase {
input: None,
filename: None,
metadata: SerdeAnyMap::new(),
exec_time: None,
cached_len: None,
}
}
}
impl<I> Testcase<I>
where
I: Input + HasLen,
{
#[inline]
pub fn cached_len(&mut self) -> Result<usize, Error> {
Ok(match &self.input {
Some(i) => {
let l = i.len();
self.cached_len = Some(l);
l
}
None => {
if let Some(l) = self.cached_len {
l
} else {
let l = self.load_input()?.len();
self.cached_len = Some(l);
l
}
}
})
}
}
impl<I> From<I> for Testcase<I>
where
I: Input,
{
fn from(input: I) -> Self {
Testcase::new(input)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PowerScheduleTestcaseMetaData {
bitmap_size: u64,
fuzz_level: u64,
handicap: u64,
depth: u64,
n_fuzz_entry: usize,
}
impl PowerScheduleTestcaseMetaData {
#[must_use]
pub fn new(depth: u64) -> Self {
Self {
bitmap_size: 0,
fuzz_level: 0,
handicap: 0,
depth,
n_fuzz_entry: 0,
}
}
#[must_use]
pub fn bitmap_size(&self) -> u64 {
self.bitmap_size
}
pub fn set_bitmap_size(&mut self, val: u64) {
self.bitmap_size = val;
}
#[must_use]
pub fn fuzz_level(&self) -> u64 {
self.fuzz_level
}
pub fn set_fuzz_level(&mut self, val: u64) {
self.fuzz_level = val;
}
#[must_use]
pub fn handicap(&self) -> u64 {
self.handicap
}
pub fn set_handicap(&mut self, val: u64) {
self.handicap = val;
}
#[must_use]
pub fn depth(&self) -> u64 {
self.depth
}
pub fn set_depth(&mut self, val: u64) {
self.depth = val;
}
#[must_use]
pub fn n_fuzz_entry(&self) -> usize {
self.n_fuzz_entry
}
pub fn set_n_fuzz_entry(&mut self, val: usize) {
self.n_fuzz_entry = val;
}
}
crate::impl_serdeany!(PowerScheduleTestcaseMetaData);