1use crate::channel::{Cbw, Channel};
6use crate::ie::fake_ies::fake_wmm_param;
7use crate::ie::{self, write_wmm_param, IeType};
8use crate::mac;
9use crate::test_utils::fake_frames::{
10 fake_eap_rsne, fake_wpa1_ie, fake_wpa2_enterprise_rsne, fake_wpa2_rsne,
11 fake_wpa2_tkip_ccmp_rsne, fake_wpa2_tkip_only_rsne, fake_wpa2_wpa3_rsne,
12 fake_wpa3_enterprise_192_bit_rsne, fake_wpa3_rsne, fake_wpa3_transition_rsne,
13};
14use anyhow::Context;
15use ieee80211::Ssid;
16use num_derive::FromPrimitive;
17use num_traits::FromPrimitive;
18use rand::distr::{Distribution, StandardUniform};
19use rand::Rng;
20use {
21 fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211,
22 fidl_fuchsia_wlan_sme as fidl_sme,
23};
24
25#[rustfmt::skip]
26const DEFAULT_MOCK_IES: &'static [u8] = &[
27 0x03, 0x01, 0x8c,
29 0x05, 0x04, 0x00, 0x01, 0x00, 0x02,
31 0x07, 0x10, 0x55, 0x53, 0x20, 0x24, 0x04, 0x24, 0x34, 0x04, 0x1e, 0x64, 0x0c, 0x1e, 0x95, 0x05, 0x24, 0x00, 0x20, 0x01, 0x00,
40 0x23, 0x02, 0x09, 0x00,
42 0x2d, 0x1a, 0xef, 0x09, 0x17, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x16, 0x8c, 0x0d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x7f, 0x08, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40,
58 0xbf, 0x0c, 0x91, 0x59, 0x82, 0x0f, 0xea, 0xff, 0x00, 0x00, 0xea, 0xff, 0x00, 0x00, 0xc0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0xc3, 0x03, 0x01, 0x24, 0x24,
65 0xdd, 0x07, 0x00, 0x0b, 0x86, 0x01, 0x04, 0x08, 0x09,
67];
68
69pub struct BssDescriptionCreator {
70 pub bssid: [u8; 6],
72 pub bss_type: fidl_common::BssType,
73 pub beacon_period: u16,
74 pub channel: Channel,
75 pub rssi_dbm: i8,
76 pub snr_db: i8,
77
78 pub protection_cfg: FakeProtectionCfg,
80 pub ssid: Ssid,
81 pub rates: Vec<u8>,
82 pub wmm_param: Option<ie::WmmParam>,
83
84 pub cf_pollable: bool,
89 pub cf_poll_req: bool,
90 pub short_preamble: bool,
91 pub spectrum_mgmt: bool,
92 pub qos: bool,
93 pub short_slot_time: bool,
94 pub apsd: bool,
95 pub radio_measurement: bool,
96 pub delayed_block_ack: bool,
97 pub immediate_block_ack: bool,
98
99 pub ies_overrides: IesOverrides,
100}
101
102impl BssDescriptionCreator {
103 pub fn create_bss_description(self) -> Result<fidl_common::BssDescription, anyhow::Error> {
104 let mut ies_updater = ie::IesUpdater::new(DEFAULT_MOCK_IES.to_vec());
105 ies_updater.set(IeType::SSID, &self.ssid[..]).context("set SSID")?;
106
107 let rates_writer = ie::RatesWriter::try_new(&self.rates[..]).context("set rates")?;
108 let mut rates_buf = vec![];
109 rates_writer.write_supported_rates(&mut rates_buf);
110 ies_updater.set_raw(&rates_buf[..]).context("set rates")?;
111
112 let mut ext_rates_buf = vec![];
113 rates_writer.write_extended_supported_rates(&mut ext_rates_buf);
114 ies_updater.set_raw(&ext_rates_buf[..]).context("set extended rates")?;
115
116 if let Some(rsne) = derive_rsne(self.protection_cfg) {
117 ies_updater.set_raw(&rsne[..]).context("set RSNE")?;
118 }
119 if let Some(wpa1_vendor_ie) = derive_wpa1_vendor_ies(self.protection_cfg) {
120 ies_updater.set_raw(&wpa1_vendor_ie[..]).context("set WPA1 vendor IE")?;
121 }
122
123 if let Some(wmm_param) = self.wmm_param {
124 let mut wmm_param_vendor_ie = vec![];
125 write_wmm_param(&mut wmm_param_vendor_ie, &wmm_param)
126 .context("failed to write WmmParam to vendor IE buffer")?;
127 ies_updater.set_raw(&wmm_param_vendor_ie[..]).context("set WMM parameter IE")?;
128 }
129
130 let capability_info = mac::CapabilityInfo(0)
131 .with_cf_pollable(self.cf_pollable)
132 .with_cf_poll_req(self.cf_poll_req)
133 .with_short_preamble(self.short_preamble)
134 .with_spectrum_mgmt(self.spectrum_mgmt)
135 .with_qos(self.qos)
136 .with_short_slot_time(self.short_slot_time)
137 .with_apsd(self.apsd)
138 .with_radio_measurement(self.radio_measurement)
139 .with_delayed_block_ack(self.delayed_block_ack)
140 .with_immediate_block_ack(self.immediate_block_ack);
141
142 let capability_info = match self.protection_cfg {
145 FakeProtectionCfg::Open => capability_info.with_privacy(false),
146 _ => capability_info.with_privacy(true),
147 };
148 let capability_info = match self.bss_type {
149 fidl_common::BssType::Infrastructure => capability_info.with_ess(true).with_ibss(false),
150 _ => panic!("{:?} is not supported", self.bss_type),
151 };
152 let capability_info = capability_info.0;
153
154 for ovr in self.ies_overrides.overrides {
155 match ovr {
156 IeOverride::Remove(ie_type) => ies_updater.remove(&ie_type),
157 IeOverride::Set(ie_type, bytes) => {
158 ies_updater
159 .set(ie_type, &bytes[..])
160 .with_context(|| format!("set IE type: {:?}", ie_type))?;
161 }
162 IeOverride::SetRaw(bytes) => {
163 ies_updater.set_raw(&bytes[..]).context("set raw IE")?;
164 }
165 }
166 }
167
168 Ok(fidl_common::BssDescription {
169 bssid: self.bssid,
170 bss_type: self.bss_type,
171 beacon_period: self.beacon_period,
172 capability_info,
173 ies: ies_updater.finalize(),
174 channel: self.channel.into(),
175 rssi_dbm: self.rssi_dbm,
176 snr_db: self.snr_db,
177 })
178 }
179}
180
181pub struct IesOverrides {
182 overrides: Vec<IeOverride>,
183}
184
185impl IesOverrides {
186 pub fn new() -> Self {
187 Self { overrides: vec![] }
188 }
189
190 pub fn remove(mut self, ie_type: IeType) -> Self {
191 self.overrides.push(IeOverride::Remove(ie_type));
192 self
193 }
194
195 pub fn set(mut self, ie_type: IeType, bytes: Vec<u8>) -> Self {
196 self.overrides.push(IeOverride::Set(ie_type, bytes));
197 self
198 }
199
200 pub fn set_raw(mut self, bytes: Vec<u8>) -> Self {
201 self.overrides.push(IeOverride::SetRaw(bytes));
202 self
203 }
204}
205
206enum IeOverride {
207 Remove(IeType),
208 Set(IeType, Vec<u8>),
209 SetRaw(Vec<u8>),
210}
211
212const LAST_FAKE_PROTECTION_CFG_VALUE: isize = 14;
213
214#[derive(Debug, FromPrimitive, Copy, Clone, PartialEq)]
215pub enum FakeProtectionCfg {
216 Open = 0,
217 Wep,
218 Wpa1,
219 Wpa1Enhanced,
220 Wpa1Wpa2TkipOnly,
221 Wpa2TkipOnly,
222 Wpa1Wpa2,
223 Wpa2TkipCcmp,
224 Wpa2Enterprise,
225 Wpa2,
226 Wpa2Wpa3,
227 Wpa3Transition,
228 Wpa3,
229 Wpa3Enterprise,
230 Eap = LAST_FAKE_PROTECTION_CFG_VALUE,
231}
232
233impl Distribution<FakeProtectionCfg> for StandardUniform {
234 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> FakeProtectionCfg {
235 let r = rng.random_range(0..usize::try_from(LAST_FAKE_PROTECTION_CFG_VALUE + 1).unwrap());
237 FromPrimitive::from_usize(r)
238 .unwrap_or_else(|| panic!("Out of range random value for FakeProtectionCfg: {:?}", r))
239 }
240}
241
242impl From<fidl_sme::Protection> for FakeProtectionCfg {
243 fn from(protection: fidl_sme::Protection) -> Self {
244 match protection {
245 fidl_sme::Protection::Unknown => panic!("unknown protection"),
246 fidl_sme::Protection::Open => FakeProtectionCfg::Open,
247 fidl_sme::Protection::Wep => FakeProtectionCfg::Wep,
248 fidl_sme::Protection::Wpa1 => FakeProtectionCfg::Wpa1,
249 fidl_sme::Protection::Wpa1Wpa2PersonalTkipOnly => FakeProtectionCfg::Wpa1Wpa2TkipOnly,
250 fidl_sme::Protection::Wpa2PersonalTkipOnly => FakeProtectionCfg::Wpa2TkipOnly,
251 fidl_sme::Protection::Wpa1Wpa2Personal => FakeProtectionCfg::Wpa1Wpa2,
252 fidl_sme::Protection::Wpa2Personal => FakeProtectionCfg::Wpa2,
253 fidl_sme::Protection::Wpa2Wpa3Personal => FakeProtectionCfg::Wpa2Wpa3,
254 fidl_sme::Protection::Wpa3Personal => FakeProtectionCfg::Wpa3,
255 fidl_sme::Protection::Wpa2Enterprise => FakeProtectionCfg::Wpa2Enterprise,
256 fidl_sme::Protection::Wpa3Enterprise => FakeProtectionCfg::Wpa3Enterprise,
257 }
258 }
259}
260
261pub fn build_fake_bss_description_creator__(
262 protection_cfg: FakeProtectionCfg,
263) -> BssDescriptionCreator {
264 BssDescriptionCreator {
265 bssid: [0x07, 0x01, 0x02, 0x4d, 0x35, 0x08],
266 bss_type: fidl_common::BssType::Infrastructure,
267 beacon_period: 100,
268 channel: Channel::new(3, Cbw::Cbw40),
269 rssi_dbm: 0,
270 snr_db: 0,
271
272 protection_cfg,
273 ssid: Ssid::try_from("fake-ssid").unwrap(),
274 rates: vec![0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c],
275 wmm_param: Some(fake_wmm_param()),
276
277 cf_pollable: false,
278 cf_poll_req: false,
279 short_preamble: false,
280 spectrum_mgmt: false,
281 qos: false,
282 short_slot_time: false,
283 apsd: false,
284 radio_measurement: false,
285 delayed_block_ack: false,
286 immediate_block_ack: false,
287
288 ies_overrides: IesOverrides::new(),
289 }
290}
291
292fn random_ecw_min_max(rng: &mut rand::prelude::ThreadRng) -> ie::EcwMinMax {
293 let min = rng.random_range(0x0..0xf);
294 let max = rng.random_range(min..0xf);
295 ie::EcwMinMax((max << 4) | min)
296}
297
298pub fn build_random_bss_description_creator__(
299 protection_cfg: FakeProtectionCfg,
300) -> BssDescriptionCreator {
301 let bss_type = fidl_common::BssType::Infrastructure;
303
304 let mut rng = rand::rng();
305
306 let mut rates: Vec<u8> = vec![];
308 for _ in
309 0..rng.random_range(1..ie::SUPPORTED_RATES_MAX_LEN + ie::EXTENDED_SUPPORTED_RATES_MAX_LEN)
310 {
311 rates.push(rng.random());
312 }
313 let rates = rates; let mut giant_vendor_ies = vec![];
317 for _j in 0..8 {
318 giant_vendor_ies.extend_from_slice(&[221, 250]);
319 giant_vendor_ies.extend((0..250).map(|_| rng.random::<u8>()))
320 }
321 let ies_overrides = IesOverrides::new().set_raw(giant_vendor_ies);
322
323 let qos: bool = rng.random();
324 let apsd: bool = qos && rng.random(); BssDescriptionCreator {
327 bssid: (0..6).map(|_| rng.random::<u8>()).collect::<Vec<u8>>().try_into().unwrap(),
328 bss_type,
329 beacon_period: rng.random::<u16>(),
330 channel: Channel::new(rng.random_range(1..255), Cbw::Cbw20),
332 rssi_dbm: rng.random::<i8>(),
333 snr_db: rng.random::<i8>(),
334
335 protection_cfg,
336 ssid: Ssid::from_bytes_unchecked(
337 (0..fidl_ieee80211::MAX_SSID_BYTE_LEN).map(|_| rng.random::<u8>()).collect::<Vec<u8>>(),
338 ),
339 rates,
340
341 wmm_param: if rng.random() {
345 Some(ie::WmmParam {
346 wmm_info: ie::WmmInfo(0).with_ap_wmm_info(
347 ie::ApWmmInfo(0)
348 .with_parameter_set_count(rng.random_range(0x00..0xf))
349 .with_uapsd(rng.random()),
350 ),
351 _reserved: rng.random(),
352 ac_be_params: ie::WmmAcParams {
353 aci_aifsn: ie::WmmAciAifsn(0).with_aifsn(rng.random_range(2..0xf)).with_aci(0),
354 ecw_min_max: random_ecw_min_max(&mut rng),
355 txop_limit: rng.random(),
356 },
357 ac_bk_params: ie::WmmAcParams {
358 aci_aifsn: ie::WmmAciAifsn(0).with_aifsn(rng.random_range(2..0xf)).with_aci(1),
359 ecw_min_max: random_ecw_min_max(&mut rng),
360 txop_limit: rng.random(),
361 },
362 ac_vi_params: ie::WmmAcParams {
363 aci_aifsn: ie::WmmAciAifsn(0).with_aifsn(rng.random_range(2..0xf)).with_aci(2),
364 ecw_min_max: random_ecw_min_max(&mut rng),
365 txop_limit: rng.random(),
366 },
367 ac_vo_params: ie::WmmAcParams {
368 aci_aifsn: ie::WmmAciAifsn(0).with_aifsn(rng.random_range(2..0xf)).with_aci(3),
369 ecw_min_max: random_ecw_min_max(&mut rng),
370 txop_limit: rng.random(),
371 },
372 })
373 } else {
374 None
375 },
376
377 cf_pollable: rng.random(),
378 cf_poll_req: rng.random(),
379 short_preamble: rng.random(),
380 spectrum_mgmt: rng.random(),
381 qos,
382 short_slot_time: rng.random(),
383 apsd,
384 radio_measurement: rng.random(),
385 delayed_block_ack: rng.random(),
386 immediate_block_ack: rng.random(),
387
388 ies_overrides,
391 }
392}
393
394fn derive_rsne(protection_cfg: FakeProtectionCfg) -> Option<Vec<u8>> {
395 match protection_cfg {
396 FakeProtectionCfg::Wpa3Enterprise => Some(fake_wpa3_enterprise_192_bit_rsne()),
397 FakeProtectionCfg::Wpa2Enterprise => Some(fake_wpa2_enterprise_rsne()),
398 FakeProtectionCfg::Wpa3 => Some(fake_wpa3_rsne()),
399 FakeProtectionCfg::Wpa3Transition => Some(fake_wpa3_transition_rsne()),
400 FakeProtectionCfg::Wpa2Wpa3 => Some(fake_wpa2_wpa3_rsne()),
401 FakeProtectionCfg::Wpa2TkipCcmp => Some(fake_wpa2_tkip_ccmp_rsne()),
402 FakeProtectionCfg::Wpa1Wpa2TkipOnly | FakeProtectionCfg::Wpa2TkipOnly => {
403 Some(fake_wpa2_tkip_only_rsne())
404 }
405 FakeProtectionCfg::Wpa1Wpa2 | FakeProtectionCfg::Wpa2 => Some(fake_wpa2_rsne()),
406 FakeProtectionCfg::Eap => Some(fake_eap_rsne()),
407 _ => None,
408 }
409}
410
411fn derive_wpa1_vendor_ies(protection_cfg: FakeProtectionCfg) -> Option<Vec<u8>> {
412 match protection_cfg {
413 FakeProtectionCfg::Wpa1
414 | FakeProtectionCfg::Wpa1Wpa2TkipOnly
415 | FakeProtectionCfg::Wpa1Wpa2 => Some(fake_wpa1_ie(false)),
416 FakeProtectionCfg::Wpa1Enhanced => Some(fake_wpa1_ie(true)),
417 _ => None,
418 }
419}
420
421#[macro_export]
422macro_rules! fake_fidl_bss_description__ {
423 ($build_fake_bss_description_creator__:path, $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)*) => {{
424 let bss_description_creator = $crate::test_utils::fake_stas::BssDescriptionCreator {
425 $(
426 $bss_key: $bss_value,
427 )*
428 ..$build_fake_bss_description_creator__($fake_protection_cfg.into())
429 };
430 bss_description_creator.create_bss_description().expect("expect creating BSS to succeed")
431 }};
432}
433
434#[macro_export]
435macro_rules! fake_fidl_bss_description {
436 ($protection_name:ident $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
437 $crate::fake_fidl_bss_description__!(
438 $crate::test_utils::fake_stas::build_fake_bss_description_creator__,
439 $crate::test_utils::fake_stas::FakeProtectionCfg::$protection_name
440 $(, $bss_key: $bss_value)*)
441 }};
442 (protection => $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
443 $crate::fake_fidl_bss_description__!(
444 $crate::test_utils::fake_stas::build_fake_bss_description_creator__,
445 $fake_protection_cfg
446 $(, $bss_key: $bss_value)*)
447 }};
448}
449
450#[macro_export]
451macro_rules! random_fidl_bss_description {
452 ($($bss_key:ident: $bss_value:expr),* $(,)?) => {{
453 let mut rng = rand::rng();
454 $crate::fake_fidl_bss_description__!(
455 $crate::test_utils::fake_stas::build_random_bss_description_creator__,
456 rng.random::<$crate::test_utils::fake_stas::FakeProtectionCfg>()
457 $(, $bss_key: $bss_value)*)
458 }};
459 ($protection_name:ident $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
460 $crate::fake_fidl_bss_description__!(
461 $crate::test_utils::fake_stas::build_random_bss_description_creator__,
462 $crate::test_utils::fake_stas::FakeProtectionCfg::$protection_name
463 $(, $bss_key: $bss_value)*)
464 }};
465 (protection => $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
466 $crate::fake_fidl_bss_description__!(
467 $crate::test_utils::fake_stas::build_random_bss_description_creator__,
468 $fake_protection_cfg
469 $(, $bss_key: $bss_value)*)
470 }};
471}
472
473#[macro_export]
474macro_rules! fake_bss_description__ {
475 ($fidl_bss_description_macro:ident, $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
476 let fidl_bss = $crate::$fidl_bss_description_macro!(protection => $fake_protection_cfg $(, $bss_key: $bss_value)*);
477 let bss_description: $crate::bss::BssDescription = std::convert::TryFrom::try_from(fidl_bss)
478 .expect("expect BSS conversion to succeed");
479 bss_description
480 }}
481}
482
483#[macro_export]
484macro_rules! fake_bss_description {
485 ($protection_name:ident $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
486 $crate::fake_bss_description__!(
487 fake_fidl_bss_description,
488 $crate::test_utils::fake_stas::FakeProtectionCfg::$protection_name $(, $bss_key: $bss_value)*)
489 }};
490 (protection => $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
491 $crate::fake_bss_description__!(
492 fake_fidl_bss_description,
493 $fake_protection_cfg $(, $bss_key: $bss_value)*)
494 }};
495}
496
497#[macro_export]
498macro_rules! random_bss_description {
499 ($($bss_key:ident: $bss_value:expr),* $(,)?) => {{
500 let mut rng = rand::rng();
501 $crate::fake_bss_description__!(
502 random_fidl_bss_description,
503 rng.random::<$crate::test_utils::fake_stas::FakeProtectionCfg>()
504 $(, $bss_key: $bss_value)*)
505 }};
506 ($protection_name:ident $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
507 $crate::fake_bss_description__!(
508 random_fidl_bss_description,
509 $crate::test_utils::fake_stas::FakeProtectionCfg::$protection_name $(, $bss_key: $bss_value)*)
510 }};
511 (protection => $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
512 $crate::fake_bss_description__!(
513 random_fidl_bss_description,
514 $fake_protection_cfg $(, $bss_key: $bss_value)*)
515 }};
516}
517
518#[cfg(test)]
519mod tests {
520 use super::*;
521 use crate::bss::{BssDescription, Protection};
522 use crate::test_utils::fake_frames::{fake_wmm_param_body, fake_wmm_param_header};
523
524 #[test]
525 fn check_simplest_macro_use() {
526 let fidl_bss_description = fake_fidl_bss_description!(Open);
527 let bss_description = fake_bss_description!(Open);
528 assert_eq!(
529 BssDescription::try_from(fidl_bss_description)
530 .expect("Failed to convert fake_fidl_bss_description value"),
531 bss_description
532 );
533
534 for i in 1..=11 {
535 if i > 10 {
536 panic!("random_bss_description is always equal to bss_description");
537 }
538
539 let random_fidl_bss_description = random_fidl_bss_description!(Open);
540 let random_bss_description =
541 BssDescription::try_from(random_fidl_bss_description.clone())
542 .expect("Failed to convert random_fidl_bss_description value");
543 if random_bss_description != bss_description {
544 break;
545 }
546 }
547
548 for i in 1..=11 {
549 if i > 10 {
550 panic!("random_bss_description is always equal to other_random_bss_description");
551 }
552
553 let random_fidl_bss_description = random_fidl_bss_description!(Open);
554 let random_bss_description =
555 BssDescription::try_from(random_fidl_bss_description.clone())
556 .expect("Failed to convert random_fidl_bss_description value");
557 let other_random_bss_description = random_bss_description!(Open);
558 if random_bss_description != other_random_bss_description {
559 break;
560 }
561 }
562 }
563
564 #[test]
565 fn fake_protection_cfg_from_primitive() {
566 assert!(
567 0 <= LAST_FAKE_PROTECTION_CFG_VALUE,
568 "LAST_FAKE_PROTECTION_CFG_VALUE is not positive: {}",
569 LAST_FAKE_PROTECTION_CFG_VALUE,
570 );
571
572 let too_low: Option<FakeProtectionCfg> = FromPrimitive::from_isize(-1);
573 assert_eq!(
574 too_low, None::<FakeProtectionCfg>,
575 "Successfully converted low out of range FakeProtectionCfg value"
576 );
577
578 for i in 0..(LAST_FAKE_PROTECTION_CFG_VALUE + 1) {
579 let _: FakeProtectionCfg = FromPrimitive::from_isize(i).unwrap_or_else(|| {
580 panic!("Failed to convert {:?} to a FakeProtectionCfg value", i)
581 });
582 }
583
584 let too_high: Option<FakeProtectionCfg> =
585 FromPrimitive::from_isize(LAST_FAKE_PROTECTION_CFG_VALUE + 1);
586 assert_eq!(
587 too_high, None::<FakeProtectionCfg>,
588 "Successfully converted high out of range FakeProtectionCfg value"
589 );
590 }
591
592 #[test]
593 fn fake_protection_cfg_expr_syntax() {
594 let fidl_bss_description =
595 fake_fidl_bss_description!(protection => FakeProtectionCfg::Open);
596 assert_eq!(
597 BssDescription::try_from(fidl_bss_description)
598 .expect("Failed to convert fake_fidl_bss_description value")
599 .protection(),
600 Protection::Open
601 );
602
603 let fidl_bss_description =
604 random_fidl_bss_description!(protection => FakeProtectionCfg::Open);
605 assert_eq!(
606 BssDescription::try_from(fidl_bss_description)
607 .expect("Failed to convert random_fidl_bss_description value")
608 .protection(),
609 Protection::Open
610 );
611
612 let bss_description = fake_bss_description!(protection => FakeProtectionCfg::Open);
613 assert_eq!(bss_description.protection(), Protection::Open);
614
615 let bss_description = random_bss_description!(protection => FakeProtectionCfg::Open);
616 assert_eq!(bss_description.protection(), Protection::Open);
617 }
618
619 #[test]
620 fn fake_protection_cfg_privacy_bit_and_protection() {
621 let bss = fake_bss_description!(Open);
622 assert!(!mac::CapabilityInfo(bss.capability_info).privacy());
623 assert_eq!(bss.protection(), Protection::Open);
624
625 let bss = fake_bss_description!(Wep);
626 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
627 assert_eq!(bss.protection(), Protection::Wep);
628
629 let bss = fake_bss_description!(Wpa1);
630 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
631 assert_eq!(bss.protection(), Protection::Wpa1);
632
633 let bss = fake_bss_description!(Wpa2);
634 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
635 assert_eq!(bss.protection(), Protection::Wpa2Personal);
636 }
637
638 #[test]
639 fn fake_protection_cfg_privacy_bit_and_protection_in_random_bss() {
640 let bss = random_bss_description!(Open);
641 assert!(!mac::CapabilityInfo(bss.capability_info).privacy());
642 assert_eq!(bss.protection(), Protection::Open);
643
644 let bss = random_bss_description!(Wep);
645 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
646 assert_eq!(bss.protection(), Protection::Wep);
647
648 let bss = random_bss_description!(Wpa1);
649 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
650 assert_eq!(bss.protection(), Protection::Wpa1);
651
652 let bss = random_bss_description!(Wpa2);
653 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
654 assert_eq!(bss.protection(), Protection::Wpa2Personal);
655 }
656
657 #[test]
658 fn set_capability_info_bits() {
659 macro_rules! check_bit {
660 ($bit_name:ident) => {{
661 let bss = fake_bss_description!(Open, $bit_name: true);
662 assert!(mac::CapabilityInfo(bss.capability_info).$bit_name());
663 let bss = fake_bss_description!(Open, $bit_name: false);
664 assert!(!mac::CapabilityInfo(bss.capability_info).$bit_name());
665 }}
666 }
667 check_bit!(cf_pollable);
668 check_bit!(cf_poll_req);
669 check_bit!(short_preamble);
670 check_bit!(spectrum_mgmt);
671 check_bit!(qos);
672 check_bit!(short_slot_time);
673 check_bit!(apsd);
674 check_bit!(radio_measurement);
675 check_bit!(delayed_block_ack);
676 check_bit!(immediate_block_ack);
677
678 let bss =
679 fake_bss_description!(Open, cf_pollable: true, apsd: false, immediate_block_ack: true);
680 assert!(mac::CapabilityInfo(bss.capability_info).cf_pollable());
681 assert!(!mac::CapabilityInfo(bss.capability_info).apsd());
682 assert!(mac::CapabilityInfo(bss.capability_info).immediate_block_ack());
683 }
684
685 #[test]
686 fn simple_default_override() {
687 let bss = fake_fidl_bss_description!(Open);
688 assert_eq!(bss.beacon_period, 100);
689
690 let bss = fake_fidl_bss_description!(Open, beacon_period: 50);
691 assert_eq!(bss.beacon_period, 50);
692 }
693
694 #[test]
695 #[should_panic(expected = "Personal is not supported")]
696 #[cfg_attr(feature = "variant_asan", ignore)]
698 #[cfg_attr(feature = "variant_hwasan", ignore)]
699 fn unsupported_bss_type() {
700 fake_fidl_bss_description!(Open, bss_type: fidl_common::BssType::Personal);
701 }
702
703 #[test]
704 fn any_protection_syntax() {
705 let _ = random_fidl_bss_description!();
706 let _ = random_bss_description!();
707 }
708
709 #[test]
710 fn random_fidl_bss_decription_override() {
711 let random_bss = random_bss_description!(ssid: Ssid::try_from("foo").unwrap());
712 assert_eq!(random_bss.ssid, Ssid::try_from("foo").unwrap());
713 }
714
715 #[test]
716 fn valid_random_ecw_min_max() {
717 let mut rng = rand::rng();
718 for _ in 0..100 {
719 let ecw_min_max = random_ecw_min_max(&mut rng);
720 assert!(ecw_min_max.ecw_max() >= ecw_min_max.ecw_min());
721 }
722 }
723
724 #[test]
725 fn random_bss_is_not_constant() {
726 for _ in 0..10 {
727 let random_bss_1 = BssDescription::try_from(random_fidl_bss_description!())
728 .expect("Failed to convert random_bss_description value");
729 let random_bss_2 = BssDescription::try_from(random_fidl_bss_description!())
730 .expect("Failed to convert random_bss_description value");
731 if random_bss_1 != random_bss_2 {
732 return;
733 }
734 }
735 panic!("random bss is always the same");
736 }
737
738 #[test]
739 fn random_bss_protection_is_not_constant() {
740 for _ in 0..10 {
741 let random_bss_1 = BssDescription::try_from(random_fidl_bss_description!())
742 .expect("Failed to convert random_bss_description value");
743 let random_bss_2 = BssDescription::try_from(random_fidl_bss_description!())
744 .expect("Failed to convert random_bss_description value");
745 if random_bss_1.protection() != random_bss_2.protection() {
746 return;
747 }
748 }
749 panic!("random bss protection is always the same");
750 }
751
752 #[test]
753 fn some_random_bss_bits_are_fixed() {
754 for _ in 0..5 {
755 let random_bss = random_fidl_bss_description!(Open);
756 assert_eq!(random_bss.bss_type, fidl_common::BssType::Infrastructure);
757 assert!(mac::CapabilityInfo(random_bss.capability_info).ess());
758 assert!(!mac::CapabilityInfo(random_bss.capability_info).ibss());
759 assert!(!mac::CapabilityInfo(random_bss.capability_info).privacy());
760 }
761 }
762
763 #[test]
766 fn random_bss_decription_protection_randomness() {
767 for _ in 0..10 {
768 let random_bss_1 = random_bss_description!();
769 let random_bss_2 = random_bss_description!();
770 if random_bss_1.protection() != random_bss_2.protection() {
771 return;
772 }
773 }
774 panic!("random protection is always the same");
775 }
776
777 #[test]
778 fn ies_overrides() {
779 let bss = fake_bss_description!(Wpa1Wpa2,
780 ssid: Ssid::try_from("fuchsia").unwrap(),
781 rates: vec![11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24],
782 ies_overrides: IesOverrides::new()
783 .remove(IeType::new_vendor([0x00, 0x0b, 0x86, 0x01, 0x04, 0x08]))
784 .set(IeType::DSSS_PARAM_SET, [136].to_vec()),
785 );
786
787 #[rustfmt::skip]
794 let mut expected_ies = vec![
795 0x00, 0x07, b'f', b'u', b'c', b'h', b's', b'i', b'a',
797 0x01, 0x08, 11, 12, 13, 14, 15, 16, 17, 18,
799 0x03, 0x01, 136,
801 0x05, 0x04, 0x00, 0x01, 0x00, 0x02,
803 0x07, 0x10, 0x55, 0x53, 0x20, 0x24, 0x04, 0x24, 0x34, 0x04, 0x1e, 0x64, 0x0c, 0x1e, 0x95, 0x05, 0x24, 0x00, 0x20, 0x01, 0x00,
812 0x23, 0x02, 0x09, 0x00,
814 0x2d, 0x1a, 0xef, 0x09, 0x17, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 18, 1, 0, 0x00, 0x0F, 0xAC, 4, 1, 0, 0x00, 0x0F, 0xAC, 4, 1, 0, 0x00, 0x0F, 0xAC, 2, 0x32, 0x06, 19, 20, 21, 22, 23, 24,
830 0x3d, 0x16, 0x8c, 0x0d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835 0x00, 0x00, 0x7f, 0x08, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40,
838 0xbf, 0x0c, 0x91, 0x59, 0x82, 0x0f, 0xea, 0xff, 0x00, 0x00, 0xea, 0xff, 0x00, 0x00, 0xc0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x03, 0x01, 0x24, 0x24,
844 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, ];
852 expected_ies.extend(fake_wmm_param_header());
853 expected_ies.extend(fake_wmm_param_body());
854
855 assert_eq!(bss.ies(), &expected_ies[..]);
856 }
857}