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::distributions::{Distribution, Standard};
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 Standard {
234 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> FakeProtectionCfg {
235 let r = rng.gen_range(0..LAST_FAKE_PROTECTION_CFG_VALUE + 1);
236 FromPrimitive::from_isize(r)
237 .unwrap_or_else(|| panic!("Out of range random value for FakeProtectionCfg: {:?}", r))
238 }
239}
240
241impl From<fidl_sme::Protection> for FakeProtectionCfg {
242 fn from(protection: fidl_sme::Protection) -> Self {
243 match protection {
244 fidl_sme::Protection::Unknown => panic!("unknown protection"),
245 fidl_sme::Protection::Open => FakeProtectionCfg::Open,
246 fidl_sme::Protection::Wep => FakeProtectionCfg::Wep,
247 fidl_sme::Protection::Wpa1 => FakeProtectionCfg::Wpa1,
248 fidl_sme::Protection::Wpa1Wpa2PersonalTkipOnly => FakeProtectionCfg::Wpa1Wpa2TkipOnly,
249 fidl_sme::Protection::Wpa2PersonalTkipOnly => FakeProtectionCfg::Wpa2TkipOnly,
250 fidl_sme::Protection::Wpa1Wpa2Personal => FakeProtectionCfg::Wpa1Wpa2,
251 fidl_sme::Protection::Wpa2Personal => FakeProtectionCfg::Wpa2,
252 fidl_sme::Protection::Wpa2Wpa3Personal => FakeProtectionCfg::Wpa2Wpa3,
253 fidl_sme::Protection::Wpa3Personal => FakeProtectionCfg::Wpa3,
254 fidl_sme::Protection::Wpa2Enterprise => FakeProtectionCfg::Wpa2Enterprise,
255 fidl_sme::Protection::Wpa3Enterprise => FakeProtectionCfg::Wpa3Enterprise,
256 }
257 }
258}
259
260pub fn build_fake_bss_description_creator__(
261 protection_cfg: FakeProtectionCfg,
262) -> BssDescriptionCreator {
263 BssDescriptionCreator {
264 bssid: [0x07, 0x01, 0x02, 0x4d, 0x35, 0x08],
265 bss_type: fidl_common::BssType::Infrastructure,
266 beacon_period: 100,
267 channel: Channel::new(3, Cbw::Cbw40),
268 rssi_dbm: 0,
269 snr_db: 0,
270
271 protection_cfg,
272 ssid: Ssid::try_from("fake-ssid").unwrap(),
273 rates: vec![0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c],
274 wmm_param: Some(fake_wmm_param()),
275
276 cf_pollable: false,
277 cf_poll_req: false,
278 short_preamble: false,
279 spectrum_mgmt: false,
280 qos: false,
281 short_slot_time: false,
282 apsd: false,
283 radio_measurement: false,
284 delayed_block_ack: false,
285 immediate_block_ack: false,
286
287 ies_overrides: IesOverrides::new(),
288 }
289}
290
291fn random_ecw_min_max(rng: &mut rand::prelude::ThreadRng) -> ie::EcwMinMax {
292 let min = rng.gen_range(0x0..0xf);
293 let max = rng.gen_range(min..0xf);
294 ie::EcwMinMax((max << 4) | min)
295}
296
297pub fn build_random_bss_description_creator__(
298 protection_cfg: FakeProtectionCfg,
299) -> BssDescriptionCreator {
300 let bss_type = fidl_common::BssType::Infrastructure;
302
303 let mut rng = rand::thread_rng();
304
305 let mut rates: Vec<u8> = vec![];
307 for _ in 0..rng.gen_range(1..ie::SUPPORTED_RATES_MAX_LEN + ie::EXTENDED_SUPPORTED_RATES_MAX_LEN)
308 {
309 rates.push(rng.gen());
310 }
311 let rates = rates; let mut giant_vendor_ies = vec![];
315 for _j in 0..8 {
316 giant_vendor_ies.extend_from_slice(&[221, 250]);
317 giant_vendor_ies.extend((0..250).map(|_| rng.gen::<u8>()))
318 }
319 let ies_overrides = IesOverrides::new().set_raw(giant_vendor_ies);
320
321 let qos: bool = rng.gen();
322 let apsd: bool = qos && rng.gen(); BssDescriptionCreator {
325 bssid: (0..6).map(|_| rng.gen::<u8>()).collect::<Vec<u8>>().try_into().unwrap(),
326 bss_type,
327 beacon_period: rng.gen::<u16>(),
328 channel: Channel::new(rng.gen_range(1..255), Cbw::Cbw20),
330 rssi_dbm: rng.gen::<i8>(),
331 snr_db: rng.gen::<i8>(),
332
333 protection_cfg,
334 ssid: Ssid::from_bytes_unchecked(
335 (0..fidl_ieee80211::MAX_SSID_BYTE_LEN).map(|_| rng.gen::<u8>()).collect::<Vec<u8>>(),
336 ),
337 rates,
338
339 wmm_param: if rng.gen() {
343 Some(ie::WmmParam {
344 wmm_info: ie::WmmInfo(0).with_ap_wmm_info(
345 ie::ApWmmInfo(0)
346 .with_parameter_set_count(rng.gen_range(0x00..0xf))
347 .with_uapsd(rng.gen()),
348 ),
349 _reserved: rng.gen(),
350 ac_be_params: ie::WmmAcParams {
351 aci_aifsn: ie::WmmAciAifsn(0).with_aifsn(rng.gen_range(2..0xf)).with_aci(0),
352 ecw_min_max: random_ecw_min_max(&mut rng),
353 txop_limit: rng.gen(),
354 },
355 ac_bk_params: ie::WmmAcParams {
356 aci_aifsn: ie::WmmAciAifsn(0).with_aifsn(rng.gen_range(2..0xf)).with_aci(1),
357 ecw_min_max: random_ecw_min_max(&mut rng),
358 txop_limit: rng.gen(),
359 },
360 ac_vi_params: ie::WmmAcParams {
361 aci_aifsn: ie::WmmAciAifsn(0).with_aifsn(rng.gen_range(2..0xf)).with_aci(2),
362 ecw_min_max: random_ecw_min_max(&mut rng),
363 txop_limit: rng.gen(),
364 },
365 ac_vo_params: ie::WmmAcParams {
366 aci_aifsn: ie::WmmAciAifsn(0).with_aifsn(rng.gen_range(2..0xf)).with_aci(3),
367 ecw_min_max: random_ecw_min_max(&mut rng),
368 txop_limit: rng.gen(),
369 },
370 })
371 } else {
372 None
373 },
374
375 cf_pollable: rng.gen(),
376 cf_poll_req: rng.gen(),
377 short_preamble: rng.gen(),
378 spectrum_mgmt: rng.gen(),
379 qos,
380 short_slot_time: rng.gen(),
381 apsd,
382 radio_measurement: rng.gen(),
383 delayed_block_ack: rng.gen(),
384 immediate_block_ack: rng.gen(),
385
386 ies_overrides,
389 }
390}
391
392fn derive_rsne(protection_cfg: FakeProtectionCfg) -> Option<Vec<u8>> {
393 match protection_cfg {
394 FakeProtectionCfg::Wpa3Enterprise => Some(fake_wpa3_enterprise_192_bit_rsne()),
395 FakeProtectionCfg::Wpa2Enterprise => Some(fake_wpa2_enterprise_rsne()),
396 FakeProtectionCfg::Wpa3 => Some(fake_wpa3_rsne()),
397 FakeProtectionCfg::Wpa3Transition => Some(fake_wpa3_transition_rsne()),
398 FakeProtectionCfg::Wpa2Wpa3 => Some(fake_wpa2_wpa3_rsne()),
399 FakeProtectionCfg::Wpa2TkipCcmp => Some(fake_wpa2_tkip_ccmp_rsne()),
400 FakeProtectionCfg::Wpa1Wpa2TkipOnly | FakeProtectionCfg::Wpa2TkipOnly => {
401 Some(fake_wpa2_tkip_only_rsne())
402 }
403 FakeProtectionCfg::Wpa1Wpa2 | FakeProtectionCfg::Wpa2 => Some(fake_wpa2_rsne()),
404 FakeProtectionCfg::Eap => Some(fake_eap_rsne()),
405 _ => None,
406 }
407}
408
409fn derive_wpa1_vendor_ies(protection_cfg: FakeProtectionCfg) -> Option<Vec<u8>> {
410 match protection_cfg {
411 FakeProtectionCfg::Wpa1
412 | FakeProtectionCfg::Wpa1Wpa2TkipOnly
413 | FakeProtectionCfg::Wpa1Wpa2 => Some(fake_wpa1_ie(false)),
414 FakeProtectionCfg::Wpa1Enhanced => Some(fake_wpa1_ie(true)),
415 _ => None,
416 }
417}
418
419#[macro_export]
420macro_rules! fake_fidl_bss_description__ {
421 ($build_fake_bss_description_creator__:path, $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)*) => {{
422 let bss_description_creator = $crate::test_utils::fake_stas::BssDescriptionCreator {
423 $(
424 $bss_key: $bss_value,
425 )*
426 ..$build_fake_bss_description_creator__($fake_protection_cfg.into())
427 };
428 bss_description_creator.create_bss_description().expect("expect creating BSS to succeed")
429 }};
430}
431
432#[macro_export]
433macro_rules! fake_fidl_bss_description {
434 ($protection_name:ident $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
435 $crate::fake_fidl_bss_description__!(
436 $crate::test_utils::fake_stas::build_fake_bss_description_creator__,
437 $crate::test_utils::fake_stas::FakeProtectionCfg::$protection_name
438 $(, $bss_key: $bss_value)*)
439 }};
440 (protection => $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
441 $crate::fake_fidl_bss_description__!(
442 $crate::test_utils::fake_stas::build_fake_bss_description_creator__,
443 $fake_protection_cfg
444 $(, $bss_key: $bss_value)*)
445 }};
446}
447
448#[macro_export]
449macro_rules! random_fidl_bss_description {
450 ($($bss_key:ident: $bss_value:expr),* $(,)?) => {{
451 let mut rng = rand::thread_rng();
452 $crate::fake_fidl_bss_description__!(
453 $crate::test_utils::fake_stas::build_random_bss_description_creator__,
454 rng.gen::<$crate::test_utils::fake_stas::FakeProtectionCfg>()
455 $(, $bss_key: $bss_value)*)
456 }};
457 ($protection_name:ident $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
458 $crate::fake_fidl_bss_description__!(
459 $crate::test_utils::fake_stas::build_random_bss_description_creator__,
460 $crate::test_utils::fake_stas::FakeProtectionCfg::$protection_name
461 $(, $bss_key: $bss_value)*)
462 }};
463 (protection => $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
464 $crate::fake_fidl_bss_description__!(
465 $crate::test_utils::fake_stas::build_random_bss_description_creator__,
466 $fake_protection_cfg
467 $(, $bss_key: $bss_value)*)
468 }};
469}
470
471#[macro_export]
472macro_rules! fake_bss_description__ {
473 ($fidl_bss_description_macro:ident, $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
474 let fidl_bss = $crate::$fidl_bss_description_macro!(protection => $fake_protection_cfg $(, $bss_key: $bss_value)*);
475 let bss_description: $crate::bss::BssDescription = std::convert::TryFrom::try_from(fidl_bss)
476 .expect("expect BSS conversion to succeed");
477 bss_description
478 }}
479}
480
481#[macro_export]
482macro_rules! fake_bss_description {
483 ($protection_name:ident $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
484 $crate::fake_bss_description__!(
485 fake_fidl_bss_description,
486 $crate::test_utils::fake_stas::FakeProtectionCfg::$protection_name $(, $bss_key: $bss_value)*)
487 }};
488 (protection => $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
489 $crate::fake_bss_description__!(
490 fake_fidl_bss_description,
491 $fake_protection_cfg $(, $bss_key: $bss_value)*)
492 }};
493}
494
495#[macro_export]
496macro_rules! random_bss_description {
497 ($($bss_key:ident: $bss_value:expr),* $(,)?) => {{
498 let mut rng = rand::thread_rng();
499 $crate::fake_bss_description__!(
500 random_fidl_bss_description,
501 rng.gen::<$crate::test_utils::fake_stas::FakeProtectionCfg>()
502 $(, $bss_key: $bss_value)*)
503 }};
504 ($protection_name:ident $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
505 $crate::fake_bss_description__!(
506 random_fidl_bss_description,
507 $crate::test_utils::fake_stas::FakeProtectionCfg::$protection_name $(, $bss_key: $bss_value)*)
508 }};
509 (protection => $fake_protection_cfg:expr $(, $bss_key:ident: $bss_value:expr)* $(,)?) => {{
510 $crate::fake_bss_description__!(
511 random_fidl_bss_description,
512 $fake_protection_cfg $(, $bss_key: $bss_value)*)
513 }};
514}
515
516#[cfg(test)]
517mod tests {
518 use super::*;
519 use crate::bss::{BssDescription, Protection};
520 use crate::test_utils::fake_frames::{fake_wmm_param_body, fake_wmm_param_header};
521
522 #[test]
523 fn check_simplest_macro_use() {
524 let fidl_bss_description = fake_fidl_bss_description!(Open);
525 let bss_description = fake_bss_description!(Open);
526 assert_eq!(
527 BssDescription::try_from(fidl_bss_description)
528 .expect("Failed to convert fake_fidl_bss_description value"),
529 bss_description
530 );
531
532 for i in 1..=11 {
533 if i > 10 {
534 panic!("random_bss_description is always equal to bss_description");
535 }
536
537 let random_fidl_bss_description = random_fidl_bss_description!(Open);
538 let random_bss_description =
539 BssDescription::try_from(random_fidl_bss_description.clone())
540 .expect("Failed to convert random_fidl_bss_description value");
541 if random_bss_description != bss_description {
542 break;
543 }
544 }
545
546 for i in 1..=11 {
547 if i > 10 {
548 panic!("random_bss_description is always equal to other_random_bss_description");
549 }
550
551 let random_fidl_bss_description = random_fidl_bss_description!(Open);
552 let random_bss_description =
553 BssDescription::try_from(random_fidl_bss_description.clone())
554 .expect("Failed to convert random_fidl_bss_description value");
555 let other_random_bss_description = random_bss_description!(Open);
556 if random_bss_description != other_random_bss_description {
557 break;
558 }
559 }
560 }
561
562 #[test]
563 fn fake_protection_cfg_from_primitive() {
564 assert!(
565 0 <= LAST_FAKE_PROTECTION_CFG_VALUE,
566 "LAST_FAKE_PROTECTION_CFG_VALUE is not positive: {}",
567 LAST_FAKE_PROTECTION_CFG_VALUE,
568 );
569
570 let too_low: Option<FakeProtectionCfg> = FromPrimitive::from_isize(-1);
571 assert_eq!(
572 too_low, None::<FakeProtectionCfg>,
573 "Successfully converted low out of range FakeProtectionCfg value"
574 );
575
576 for i in 0..(LAST_FAKE_PROTECTION_CFG_VALUE + 1) {
577 let _: FakeProtectionCfg = FromPrimitive::from_isize(i).unwrap_or_else(|| {
578 panic!("Failed to convert {:?} to a FakeProtectionCfg value", i)
579 });
580 }
581
582 let too_high: Option<FakeProtectionCfg> =
583 FromPrimitive::from_isize(LAST_FAKE_PROTECTION_CFG_VALUE + 1);
584 assert_eq!(
585 too_high, None::<FakeProtectionCfg>,
586 "Successfully converted high out of range FakeProtectionCfg value"
587 );
588 }
589
590 #[test]
591 fn fake_protection_cfg_expr_syntax() {
592 let fidl_bss_description =
593 fake_fidl_bss_description!(protection => FakeProtectionCfg::Open);
594 assert_eq!(
595 BssDescription::try_from(fidl_bss_description)
596 .expect("Failed to convert fake_fidl_bss_description value")
597 .protection(),
598 Protection::Open
599 );
600
601 let fidl_bss_description =
602 random_fidl_bss_description!(protection => FakeProtectionCfg::Open);
603 assert_eq!(
604 BssDescription::try_from(fidl_bss_description)
605 .expect("Failed to convert random_fidl_bss_description value")
606 .protection(),
607 Protection::Open
608 );
609
610 let bss_description = fake_bss_description!(protection => FakeProtectionCfg::Open);
611 assert_eq!(bss_description.protection(), Protection::Open);
612
613 let bss_description = random_bss_description!(protection => FakeProtectionCfg::Open);
614 assert_eq!(bss_description.protection(), Protection::Open);
615 }
616
617 #[test]
618 fn fake_protection_cfg_privacy_bit_and_protection() {
619 let bss = fake_bss_description!(Open);
620 assert!(!mac::CapabilityInfo(bss.capability_info).privacy());
621 assert_eq!(bss.protection(), Protection::Open);
622
623 let bss = fake_bss_description!(Wep);
624 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
625 assert_eq!(bss.protection(), Protection::Wep);
626
627 let bss = fake_bss_description!(Wpa1);
628 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
629 assert_eq!(bss.protection(), Protection::Wpa1);
630
631 let bss = fake_bss_description!(Wpa2);
632 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
633 assert_eq!(bss.protection(), Protection::Wpa2Personal);
634 }
635
636 #[test]
637 fn fake_protection_cfg_privacy_bit_and_protection_in_random_bss() {
638 let bss = random_bss_description!(Open);
639 assert!(!mac::CapabilityInfo(bss.capability_info).privacy());
640 assert_eq!(bss.protection(), Protection::Open);
641
642 let bss = random_bss_description!(Wep);
643 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
644 assert_eq!(bss.protection(), Protection::Wep);
645
646 let bss = random_bss_description!(Wpa1);
647 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
648 assert_eq!(bss.protection(), Protection::Wpa1);
649
650 let bss = random_bss_description!(Wpa2);
651 assert!(mac::CapabilityInfo(bss.capability_info).privacy());
652 assert_eq!(bss.protection(), Protection::Wpa2Personal);
653 }
654
655 #[test]
656 fn set_capability_info_bits() {
657 macro_rules! check_bit {
658 ($bit_name:ident) => {{
659 let bss = fake_bss_description!(Open, $bit_name: true);
660 assert!(mac::CapabilityInfo(bss.capability_info).$bit_name());
661 let bss = fake_bss_description!(Open, $bit_name: false);
662 assert!(!mac::CapabilityInfo(bss.capability_info).$bit_name());
663 }}
664 }
665 check_bit!(cf_pollable);
666 check_bit!(cf_poll_req);
667 check_bit!(short_preamble);
668 check_bit!(spectrum_mgmt);
669 check_bit!(qos);
670 check_bit!(short_slot_time);
671 check_bit!(apsd);
672 check_bit!(radio_measurement);
673 check_bit!(delayed_block_ack);
674 check_bit!(immediate_block_ack);
675
676 let bss =
677 fake_bss_description!(Open, cf_pollable: true, apsd: false, immediate_block_ack: true);
678 assert!(mac::CapabilityInfo(bss.capability_info).cf_pollable());
679 assert!(!mac::CapabilityInfo(bss.capability_info).apsd());
680 assert!(mac::CapabilityInfo(bss.capability_info).immediate_block_ack());
681 }
682
683 #[test]
684 fn simple_default_override() {
685 let bss = fake_fidl_bss_description!(Open);
686 assert_eq!(bss.beacon_period, 100);
687
688 let bss = fake_fidl_bss_description!(Open, beacon_period: 50);
689 assert_eq!(bss.beacon_period, 50);
690 }
691
692 #[test]
693 #[should_panic(expected = "Personal is not supported")]
694 #[cfg_attr(feature = "variant_asan", ignore)]
696 fn unsupported_bss_type() {
697 fake_fidl_bss_description!(Open, bss_type: fidl_common::BssType::Personal);
698 }
699
700 #[test]
701 fn any_protection_syntax() {
702 let _ = random_fidl_bss_description!();
703 let _ = random_bss_description!();
704 }
705
706 #[test]
707 fn random_fidl_bss_decription_override() {
708 let random_bss = random_bss_description!(ssid: Ssid::try_from("foo").unwrap());
709 assert_eq!(random_bss.ssid, Ssid::try_from("foo").unwrap());
710 }
711
712 #[test]
713 fn valid_random_ecw_min_max() {
714 let mut rng = rand::thread_rng();
715 for _ in 0..100 {
716 let ecw_min_max = random_ecw_min_max(&mut rng);
717 assert!(ecw_min_max.ecw_max() >= ecw_min_max.ecw_min());
718 }
719 }
720
721 #[test]
722 fn random_bss_is_not_constant() {
723 for _ in 0..10 {
724 let random_bss_1 = BssDescription::try_from(random_fidl_bss_description!())
725 .expect("Failed to convert random_bss_description value");
726 let random_bss_2 = BssDescription::try_from(random_fidl_bss_description!())
727 .expect("Failed to convert random_bss_description value");
728 if random_bss_1 != random_bss_2 {
729 return;
730 }
731 }
732 panic!("random bss is always the same");
733 }
734
735 #[test]
736 fn random_bss_protection_is_not_constant() {
737 for _ in 0..10 {
738 let random_bss_1 = BssDescription::try_from(random_fidl_bss_description!())
739 .expect("Failed to convert random_bss_description value");
740 let random_bss_2 = BssDescription::try_from(random_fidl_bss_description!())
741 .expect("Failed to convert random_bss_description value");
742 if random_bss_1.protection() != random_bss_2.protection() {
743 return;
744 }
745 }
746 panic!("random bss protection is always the same");
747 }
748
749 #[test]
750 fn some_random_bss_bits_are_fixed() {
751 for _ in 0..5 {
752 let random_bss = random_fidl_bss_description!(Open);
753 assert_eq!(random_bss.bss_type, fidl_common::BssType::Infrastructure);
754 assert!(mac::CapabilityInfo(random_bss.capability_info).ess());
755 assert!(!mac::CapabilityInfo(random_bss.capability_info).ibss());
756 assert!(!mac::CapabilityInfo(random_bss.capability_info).privacy());
757 }
758 }
759
760 #[test]
763 fn random_bss_decription_protection_randomness() {
764 for _ in 0..10 {
765 let random_bss_1 = random_bss_description!();
766 let random_bss_2 = random_bss_description!();
767 if random_bss_1.protection() != random_bss_2.protection() {
768 return;
769 }
770 }
771 panic!("random protection is always the same");
772 }
773
774 #[test]
775 fn ies_overrides() {
776 let bss = fake_bss_description!(Wpa1Wpa2,
777 ssid: Ssid::try_from("fuchsia").unwrap(),
778 rates: vec![11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24],
779 ies_overrides: IesOverrides::new()
780 .remove(IeType::new_vendor([0x00, 0x0b, 0x86, 0x01, 0x04, 0x08]))
781 .set(IeType::DSSS_PARAM_SET, [136].to_vec()),
782 );
783
784 #[rustfmt::skip]
791 let mut expected_ies = vec![
792 0x00, 0x07, b'f', b'u', b'c', b'h', b's', b'i', b'a',
794 0x01, 0x08, 11, 12, 13, 14, 15, 16, 17, 18,
796 0x03, 0x01, 136,
798 0x05, 0x04, 0x00, 0x01, 0x00, 0x02,
800 0x07, 0x10, 0x55, 0x53, 0x20, 0x24, 0x04, 0x24, 0x34, 0x04, 0x1e, 0x64, 0x0c, 0x1e, 0x95, 0x05, 0x24, 0x00, 0x20, 0x01, 0x00,
809 0x23, 0x02, 0x09, 0x00,
811 0x2d, 0x1a, 0xef, 0x09, 0x17, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815 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,
827 0x3d, 0x16, 0x8c, 0x0d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x7f, 0x08, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40,
835 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,
841 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, ];
849 expected_ies.extend(fake_wmm_param_header());
850 expected_ies.extend(fake_wmm_param_body());
851
852 assert_eq!(bss.ies(), &expected_ies[..]);
853 }
854}