Skip to content

Commit

Permalink
Merge pull request #420 from timstobal/tc/sm-macro-hygiene
Browse files Browse the repository at this point in the history
Fix hygiene issues with prop_state_machine macro
  • Loading branch information
rexmas authored Feb 5, 2024
2 parents db83eab + f0d55f7 commit a16f6c3
Showing 1 changed file with 79 additions and 6 deletions.
85 changes: 79 additions & 6 deletions proptest-state-machine/src/test_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,15 @@ macro_rules! prop_state_machine {
fn $test_name:ident(sequential $size:expr => $test:ident $(< $( $ty_param:tt ),+ >)?);
)*) => {
$(
proptest! {
::proptest::proptest! {
#![proptest_config($config)]
$(#[$meta])*
fn $test_name(
(initial_state, transitions) in <$test $(< $( $ty_param ),+ >)? as StateMachineTest>::Reference::sequential_strategy($size)
(initial_state, transitions) in <<$test $(< $( $ty_param ),+ >)? as $crate::StateMachineTest>::Reference as $crate::ReferenceStateMachine>::sequential_strategy($size)
) {

let config = $config.__sugar_to_owned();
$test $(::< $( $ty_param ),+ >)? ::test_sequential(config, initial_state, transitions)
<$test $(::< $( $ty_param ),+ >)? as $crate::StateMachineTest>::test_sequential(config, initial_state, transitions)
}
}
)*
Expand All @@ -185,14 +186,86 @@ macro_rules! prop_state_machine {
fn $test_name:ident(sequential $size:expr => $test:ident $(< $( $ty_param:tt ),+ >)?);
)*) => {
$(
proptest! {
::proptest::proptest! {
$(#[$meta])*
fn $test_name(
(initial_state, transitions) in <$test $(< $( $ty_param ),+ >)? as StateMachineTest>::Reference::sequential_strategy($size)
(initial_state, transitions) in <<$test $(< $( $ty_param ),+ >)? as $crate::StateMachineTest>::Reference as $crate::ReferenceStateMachine>::sequential_strategy($size)
) {
$test $(::< $( $ty_param ),+ >)? ::test_sequential(Default::default(), initial_state, transitions)
<$test $(::< $( $ty_param ),+ >)? as $crate::StateMachineTest>::test_sequential(
::proptest::test_runner::Config::default(), initial_state, transitions)
}
}
)*
};
}

#[cfg(test)]
mod tests {

mod macro_test {
//! tests to verify that invocations of all forms of the
//! `prop_state_machine!` macro compile cleanly, and hygenically,
//! as intended.
/// Note: no imports here, so as to guarantee hygienic macros
/// A no-op test. Exists strictly as something to reference
/// in the macro invocation.
struct Test;
impl crate::ReferenceStateMachine for Test {
type State = ();
type Transition = ();

fn init_state() -> proptest::strategy::BoxedStrategy<Self::State> {
use proptest::prelude::*;
Just(()).boxed()
}

fn transitions(
_: &Self::State,
) -> proptest::strategy::BoxedStrategy<Self::Transition>
{
use proptest::prelude::*;
Just(()).boxed()
}

fn apply(_: Self::State, _: &Self::Transition) -> Self::State {
()
}
}

impl crate::StateMachineTest for Test {
type SystemUnderTest = ();

type Reference = Self;

fn init_test(
_: &<Self::Reference as crate::ReferenceStateMachine>::State,
) -> Self::SystemUnderTest {
}

fn apply(
_: Self::SystemUnderTest,
_: &<Self::Reference as crate::ReferenceStateMachine>::State,
_: <Self::Reference as crate::ReferenceStateMachine>::Transition,
) -> Self::SystemUnderTest {
}
}

// Invocation of the `prop_state_machine` macro without
// a `![proptest_config]` annotation
prop_state_machine! {
#[test]
fn no_config_annotation(sequential 1..2 => Test);
}

// Invocation of the `prop_state_machine` macro with a
// `![proptest_config]` annotation
prop_state_machine! {
#![proptest_config(::proptest::test_runner::Config::default())]

#[test]
fn with_config_annotation(sequential 1..2 => Test);
}
}
}

0 comments on commit a16f6c3

Please sign in to comment.