1 // Copyright 2023 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 macro_rules! sequence_body { 16 ($ctx:ident, ) => { None }; 17 ($ctx:ident, Lower Tester -> IUT: $packet:ident { 18 $($name:ident: $value:expr),* $(,)? 19 } $($tail:tt)*) => {{ 20 use crate::packets::lmp::*; 21 22 let builder = paste! { 23 [<$packet Builder>] { 24 $($name: $value),* 25 } 26 }; 27 $ctx.0.in_lmp_packets.borrow_mut().push_back(builder.build().into()); 28 29 let poll = crate::lmp::test::poll($ctx.1.as_mut()); 30 31 assert!($ctx.0.in_lmp_packets.borrow().is_empty(), "{} was not consumed by procedure", stringify!($packet)); 32 33 println!("Lower Tester -> IUT: {}", stringify!($packet)); 34 35 sequence_body!($ctx, $($tail)*).or(Some(poll)) 36 }}; 37 ($ctx:ident, Upper Tester -> IUT: $packet:ident { 38 $($name:ident: $value:expr),* $(,)? 39 } $($tail:tt)*) => {{ 40 use crate::packets::hci::*; 41 42 let builder = paste! { 43 [<$packet Builder>] { 44 $($name: $value),* 45 } 46 }; 47 $ctx.0.hci_commands.borrow_mut().push_back(builder.build().into()); 48 49 let poll = crate::lmp::test::poll($ctx.1.as_mut()); 50 51 assert!($ctx.0.hci_commands.borrow().is_empty(), "{} was not consumed by procedure", stringify!($packet)); 52 53 println!("Upper Tester -> IUT: {}", stringify!($packet)); 54 55 sequence_body!($ctx, $($tail)*).or(Some(poll)) 56 }}; 57 ($ctx:ident, IUT -> Upper Tester: $packet:ident { 58 $($name:ident: $expected_value:expr),* $(,)? 59 } $($tail:tt)*) => {{ 60 use crate::packets::hci::*; 61 62 paste! { 63 let packet: $packet = $ctx.0.hci_events.borrow_mut().pop_front().expect("No hci packet").try_into().unwrap(); 64 } 65 66 $( 67 let value = paste! { packet.[<get_ $name>]() }; 68 assert_eq!(value.clone(), $expected_value); 69 )* 70 71 println!("IUT -> Upper Tester: {}", stringify!($packet)); 72 73 sequence_body!($ctx, $($tail)*) 74 }}; 75 ($ctx:ident, IUT -> Lower Tester: $packet:ident { 76 $($name:ident: $expected_value:expr),* $(,)? 77 } $($tail:tt)*) => {{ 78 use crate::packets::lmp::*; 79 80 paste! { 81 let packet: $packet = $ctx.0.out_lmp_packets.borrow_mut().pop_front().expect("No lmp packet").try_into().unwrap(); 82 } 83 84 $( 85 let value = paste! { packet.[<get_ $name>]() }; 86 assert_eq!(value.clone(), $expected_value); 87 )* 88 89 println!("IUT -> Lower Tester: {}", stringify!($packet)); 90 91 sequence_body!($ctx, $($tail)*) 92 }}; 93 ($ctx:ident, repeat $number:literal times with ($var:ident in $iterable:expr) { 94 $($inner:tt)* 95 } $($tail:tt)*) => {{ 96 println!("repeat {}", $number); 97 for (_, $var) in (0..$number).into_iter().zip($iterable) { 98 sequence_body!($ctx, $($inner)*); 99 } 100 println!("endrepeat"); 101 102 sequence_body!($ctx, $($tail)*) 103 }}; 104 ($ctx:ident, repeat $number:literal times { 105 $($inner:tt)* 106 } $($tail:tt)*) => {{ 107 println!("repeat {}", $number); 108 for _ in 0..$number { 109 sequence_body!($ctx, $($inner)*); 110 } 111 println!("endrepeat"); 112 113 sequence_body!($ctx, $($tail)*) 114 }}; 115 } 116 117 macro_rules! sequence { 118 ($procedure_fn:path, $context:path, $($tail:tt)*) => ({ 119 use paste::paste; 120 use std::convert::TryInto; 121 122 let procedure = $procedure_fn(&$context); 123 124 use crate::future::pin; 125 pin!(procedure); 126 127 let mut ctx = (&$context, procedure); 128 use crate::lmp::test::sequence_body; 129 let last_poll = sequence_body!(ctx, $($tail)*).unwrap(); 130 131 assert!(last_poll.is_ready()); 132 assert!($context.in_lmp_packets.borrow().is_empty()); 133 assert!($context.out_lmp_packets.borrow().is_empty()); 134 assert!($context.hci_commands.borrow().is_empty()); 135 assert!($context.hci_events.borrow().is_empty()); 136 }); 137 } 138 139 pub(crate) use sequence; 140 pub(crate) use sequence_body; 141