Skip to content

Commit

Permalink
feat(models): impl Arbitrary for OutAction
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexagon committed Feb 17, 2025
1 parent ace8c50 commit 29cfdaf
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/arbitrary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ impl<'a> Arbitrary<'a> for OrdinaryCell {

/// [`Arbitrary`] helper for generating trees of only ordinary cells.
#[repr(transparent)]
#[derive(Debug)]
pub struct OrdinaryCellBuilder(pub CellBuilder);

impl From<OrdinaryCellBuilder> for CellBuilder {
Expand Down Expand Up @@ -101,6 +102,7 @@ impl<'a> Arbitrary<'a> for OrdinaryCellBuilder {

/// [`Arbitrary`] helper for generating a "real-life" balance.
#[cfg(feature = "models")]
#[derive(Debug)]
#[repr(transparent)]
pub struct SimpleBalance(pub crate::models::CurrencyCollection);

Expand Down
8 changes: 5 additions & 3 deletions src/models/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,11 @@ impl<'a> arbitrary::Arbitrary<'a> for StateInit {
0..=128 => {}
n => {
for _ in 128..n {
libraries
.set(u.arbitrary::<HashBytes>()?, u.arbitrary::<SimpleLib>()?)
.unwrap();
let lib = u.arbitrary::<SimpleLib>()?;
if lib.root.level() != 0 || lib.root.has_max_depth() {
return Err(arbitrary::Error::IncorrectFormat);
}
libraries.set(u.arbitrary::<HashBytes>()?, lib).unwrap();
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions src/models/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,37 @@ where
}
}

#[cfg(feature = "arbitrary")]
impl<'a, I: arbitrary::Arbitrary<'a>> arbitrary::Arbitrary<'a> for BaseMessage<I, CellSliceParts> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self {
info: u.arbitrary()?,
init: u.arbitrary()?,
body: {
let cell = u.arbitrary::<Cell>()?;
let range = CellSliceRange::full(cell.as_ref());
(cell, range)
},
layout: u.arbitrary()?,
})
}

fn size_hint(depth: usize) -> (usize, Option<usize>) {
Self::try_size_hint(depth).unwrap_or_default()
}

fn try_size_hint(
depth: usize,
) -> arbitrary::Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
Ok(arbitrary::size_hint::and_all(&[
<I as arbitrary::Arbitrary>::try_size_hint(depth)?,
<Option<StateInit> as arbitrary::Arbitrary>::try_size_hint(depth)?,
<Cell as arbitrary::Arbitrary>::try_size_hint(depth)?,
<Option<MessageLayout> as arbitrary::Arbitrary>::try_size_hint(depth)?,
]))
}
}

impl<I: Borrow<MsgInfo>, B> BaseMessage<I, B> {
/// Returns the type of this message.
pub fn ty(&self) -> MsgType {
Expand Down
20 changes: 20 additions & 0 deletions src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,23 @@ where
}
}
}

#[cfg(feature = "arbitrary")]
impl<'a, T: Store + arbitrary::Arbitrary<'a>> arbitrary::Arbitrary<'a> for Lazy<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let inner = u.arbitrary::<T>()?;
Lazy::new(&inner).map_err(|_| arbitrary::Error::IncorrectFormat)
}

#[inline]
fn size_hint(depth: usize) -> (usize, Option<usize>) {
Self::try_size_hint(depth).unwrap_or_default()
}

#[inline]
fn try_size_hint(
depth: usize,
) -> arbitrary::Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
<T as arbitrary::Arbitrary>::try_size_hint(depth)
}
}
130 changes: 130 additions & 0 deletions src/models/vm/out_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ impl<'a> Load<'a> for SendMsgFlags {
}
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for SendMsgFlags {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary().map(Self::from_bits_retain)
}

#[inline]
fn size_hint(_: usize) -> (usize, Option<usize>) {
(1, Some(1))
}
}

bitflags! {
/// Mode flags for `ReserveCurrency` output action.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -113,6 +125,18 @@ impl<'a> Load<'a> for ReserveCurrencyFlags {
}
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for ReserveCurrencyFlags {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary().map(Self::from_bits_retain)
}

#[inline]
fn size_hint(_: usize) -> (usize, Option<usize>) {
(1, Some(1))
}
}

bitflags! {
/// Mode flags for `ChangeLibrary` output action.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
Expand All @@ -139,6 +163,18 @@ bitflags! {
}
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for ChangeLibraryMode {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary().map(Self::from_bits_retain)
}

#[inline]
fn size_hint(_: usize) -> (usize, Option<usize>) {
(1, Some(1))
}
}

/// Library reference.
#[derive(Debug, Clone)]
pub enum LibRef {
Expand All @@ -148,6 +184,26 @@ pub enum LibRef {
Cell(Cell),
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for LibRef {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
if u.arbitrary::<bool>()? {
u.arbitrary().map(Self::Hash)
} else {
let crate::arbitrary::OrdinaryCell(code) = u.arbitrary()?;
if code.level() != 0 {
return Err(arbitrary::Error::IncorrectFormat);
}
Ok(Self::Cell(code))
}
}

#[inline]
fn size_hint(_: usize) -> (usize, Option<usize>) {
(4, None)
}
}

/// Output action.
#[derive(Debug, Clone)]
pub enum OutAction {
Expand Down Expand Up @@ -261,3 +317,77 @@ impl<'a> Load<'a> for OutAction {
})
}
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for OutAction {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(match u.int_in_range(0u8..=3u8)? {
0 => Self::SendMsg {
mode: u.arbitrary()?,
out_msg: {
let msg: Lazy<OwnedRelaxedMessage> = u.arbitrary()?;
if msg.inner().level() != 0 {
return Err(arbitrary::Error::IncorrectFormat);
}
msg
},
},
1 => Self::SetCode {
new_code: {
let code: Cell = u.arbitrary()?;
if code.level() != 0 {
return Err(arbitrary::Error::IncorrectFormat);
}
code
},
},
2 => Self::ReserveCurrency {
mode: u.arbitrary()?,
value: u.arbitrary()?,
},
3 => Self::ChangeLibrary {
mode: u.arbitrary()?,
lib: {
let lib = u.arbitrary()?;
if let LibRef::Cell(code) = &lib {
if code.level() != 0 {
return Err(arbitrary::Error::IncorrectFormat);
}
}
lib
},
},
_ => unreachable!(),
})
}

#[inline]
fn size_hint(depth: usize) -> (usize, Option<usize>) {
Self::try_size_hint(depth).unwrap_or_default()
}

fn try_size_hint(
depth: usize,
) -> arbitrary::Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
use arbitrary::{size_hint, Arbitrary};

Ok(size_hint::and(
(1, Some(1)),
size_hint::or_all(&[
size_hint::and(
<SendMsgFlags as Arbitrary>::try_size_hint(depth)?,
<Lazy<OwnedRelaxedMessage> as Arbitrary>::try_size_hint(depth)?,
),
<Cell as Arbitrary>::try_size_hint(depth)?,
size_hint::and(
<ReserveCurrencyFlags as Arbitrary>::try_size_hint(depth)?,
<CurrencyCollection as Arbitrary>::try_size_hint(depth)?,
),
size_hint::and(
<ChangeLibraryMode as Arbitrary>::try_size_hint(depth)?,
<LibRef as Arbitrary>::try_size_hint(depth)?,
),
]),
))
}
}

0 comments on commit 29cfdaf

Please sign in to comment.