1 macro_rules! sequence_body { 2 ($ctx:ident, ) => { None }; 3 ($ctx:ident, Lower Tester -> IUT: $packet:ident { 4 $($name:ident: $value:expr),* $(,)? 5 } $($tail:tt)*) => {{ 6 use crate::packets::lmp::*; 7 8 let builder = paste! { 9 [<$packet Builder>] { 10 $($name: $value),* 11 } 12 }; 13 $ctx.0.in_lmp_packets.borrow_mut().push_back(builder.build().into()); 14 15 let poll = crate::lmp::test::poll($ctx.1.as_mut()); 16 17 assert!($ctx.0.in_lmp_packets.borrow().is_empty(), "{} was not consumed by procedure", stringify!($packet)); 18 19 println!("Lower Tester -> IUT: {}", stringify!($packet)); 20 21 sequence_body!($ctx, $($tail)*).or(Some(poll)) 22 }}; 23 ($ctx:ident, Upper Tester -> IUT: $packet:ident { 24 $($name:ident: $value:expr),* $(,)? 25 } $($tail:tt)*) => {{ 26 use crate::packets::hci::*; 27 28 let builder = paste! { 29 [<$packet Builder>] { 30 $($name: $value),* 31 } 32 }; 33 $ctx.0.hci_commands.borrow_mut().push_back(builder.build().into()); 34 35 let poll = crate::lmp::test::poll($ctx.1.as_mut()); 36 37 assert!($ctx.0.hci_commands.borrow().is_empty(), "{} was not consumed by procedure", stringify!($packet)); 38 39 println!("Upper Tester -> IUT: {}", stringify!($packet)); 40 41 sequence_body!($ctx, $($tail)*).or(Some(poll)) 42 }}; 43 ($ctx:ident, IUT -> Upper Tester: $packet:ident { 44 $($name:ident: $expected_value:expr),* $(,)? 45 } $($tail:tt)*) => {{ 46 use crate::packets::hci::*; 47 48 paste! { 49 let packet: [<$packet Packet>] = $ctx.0.hci_events.borrow_mut().pop_front().expect("No hci packet").try_into().unwrap(); 50 } 51 52 $( 53 let value = paste! { packet.[<get_ $name>]() }; 54 assert_eq!(value.clone(), $expected_value); 55 )* 56 57 println!("IUT -> Upper Tester: {}", stringify!($packet)); 58 59 sequence_body!($ctx, $($tail)*) 60 }}; 61 ($ctx:ident, IUT -> Lower Tester: $packet:ident { 62 $($name:ident: $expected_value:expr),* $(,)? 63 } $($tail:tt)*) => {{ 64 use crate::packets::lmp::*; 65 66 paste! { 67 let packet: $packet = $ctx.0.out_lmp_packets.borrow_mut().pop_front().expect("No lmp packet").try_into().unwrap(); 68 } 69 70 $( 71 let value = paste! { packet.[<get_ $name>]() }; 72 assert_eq!(value.clone(), $expected_value); 73 )* 74 75 println!("IUT -> Lower Tester: {}", stringify!($packet)); 76 77 sequence_body!($ctx, $($tail)*) 78 }}; 79 ($ctx:ident, repeat $number:literal times with ($var:ident in $iterable:expr) { 80 $($inner:tt)* 81 } $($tail:tt)*) => {{ 82 println!("repeat {}", $number); 83 for (_, $var) in (0..$number).into_iter().zip($iterable) { 84 sequence_body!($ctx, $($inner)*); 85 } 86 println!("endrepeat"); 87 88 sequence_body!($ctx, $($tail)*) 89 }}; 90 ($ctx:ident, repeat $number:literal times { 91 $($inner:tt)* 92 } $($tail:tt)*) => {{ 93 println!("repeat {}", $number); 94 for _ in 0..$number { 95 sequence_body!($ctx, $($inner)*); 96 } 97 println!("endrepeat"); 98 99 sequence_body!($ctx, $($tail)*) 100 }}; 101 } 102 103 macro_rules! sequence { 104 ($procedure_fn:path, $context:path, $($tail:tt)*) => ({ 105 use paste::paste; 106 use std::convert::TryInto; 107 108 let procedure = $procedure_fn(&$context); 109 110 use crate::future::pin; 111 pin!(procedure); 112 113 let mut ctx = (&$context, procedure); 114 use crate::lmp::test::sequence_body; 115 let last_poll = sequence_body!(ctx, $($tail)*).unwrap(); 116 117 assert!(last_poll.is_ready()); 118 assert!($context.in_lmp_packets.borrow().is_empty()); 119 assert!($context.out_lmp_packets.borrow().is_empty()); 120 assert!($context.hci_commands.borrow().is_empty()); 121 assert!($context.hci_events.borrow().is_empty()); 122 }); 123 } 124 125 pub(crate) use sequence; 126 pub(crate) use sequence_body; 127