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