1use crate::access_point::types;
6use crate::mode_management::iface_manager_api::SmeForApStateMachine;
7use crate::mode_management::{Defect, IfaceFailure};
8use crate::telemetry::{TelemetryEvent, TelemetrySender};
9use crate::util::listener::Message::NotifyListeners;
10use crate::util::listener::{
11 ApListenerMessageSender, ApStateUpdate, ApStatesUpdate, ConnectedClientInformation,
12};
13use crate::util::state_machine::{self, ExitReason, IntoStateExt, StateMachineStatusPublisher};
14use anyhow::format_err;
15use fidl_fuchsia_wlan_sme as fidl_sme;
16use fuchsia_async::{self as fasync, DurationExt};
17use fuchsia_inspect::Node as InspectNode;
18use fuchsia_inspect_contrib::inspect_insert;
19use fuchsia_inspect_contrib::log::WriteInspect;
20use fuchsia_sync::Mutex;
21
22use futures::channel::{mpsc, oneshot};
23use futures::future::FutureExt;
24use futures::select;
25use futures::stream::{self, Fuse, FuturesUnordered, StreamExt, TryStreamExt};
26use log::{info, warn};
27use std::borrow::Cow;
28use std::fmt::Debug;
29use std::pin::pin;
30use std::sync::Arc;
31use wlan_common::channel::{Cbw, Channel};
32use wlan_common::RadioConfig;
33
34const AP_STATUS_INTERVAL_SEC: i64 = 10;
35
36const AP_START_RETRY_INTERVAL: i64 = 2;
45const AP_START_MAX_RETRIES: u16 = 6;
46
47type State = state_machine::State<ExitReason>;
48type ReqStream = stream::Fuse<mpsc::Receiver<ManualRequest>>;
49
50pub trait AccessPointApi {
51 fn start(
52 &mut self,
53 request: ApConfig,
54 responder: oneshot::Sender<()>,
55 ) -> Result<(), anyhow::Error>;
56 fn stop(&mut self, responder: oneshot::Sender<()>) -> Result<(), anyhow::Error>;
57 fn exit(&mut self, responder: oneshot::Sender<()>) -> Result<(), anyhow::Error>;
58}
59
60pub struct AccessPoint {
61 req_sender: mpsc::Sender<ManualRequest>,
62}
63
64impl AccessPoint {
65 pub fn new(req_sender: mpsc::Sender<ManualRequest>) -> Self {
66 Self { req_sender }
67 }
68}
69
70impl AccessPointApi for AccessPoint {
71 fn start(
72 &mut self,
73 request: ApConfig,
74 responder: oneshot::Sender<()>,
75 ) -> Result<(), anyhow::Error> {
76 self.req_sender
77 .try_send(ManualRequest::Start((request, responder)))
78 .map_err(|e| format_err!("failed to send start request: {:?}", e))
79 }
80
81 fn stop(&mut self, responder: oneshot::Sender<()>) -> Result<(), anyhow::Error> {
82 self.req_sender
83 .try_send(ManualRequest::Stop(responder))
84 .map_err(|e| format_err!("failed to send stop request: {:?}", e))
85 }
86
87 fn exit(&mut self, responder: oneshot::Sender<()>) -> Result<(), anyhow::Error> {
88 self.req_sender
89 .try_send(ManualRequest::Exit(responder))
90 .map_err(|e| format_err!("failed to send exit request: {:?}", e))
91 }
92}
93
94pub enum ManualRequest {
95 Start((ApConfig, oneshot::Sender<()>)),
96 Stop(oneshot::Sender<()>),
97 Exit(oneshot::Sender<()>),
98}
99
100#[derive(Clone, Debug, Default, PartialEq)]
103pub enum Status {
104 Stopping,
105 #[default]
106 Stopped,
107 Starting,
108 Started {
109 band: types::OperatingBand,
110 channel: u8,
111 mode: types::ConnectivityMode,
112 num_clients: u16,
113 security_type: types::SecurityType,
114 },
115}
116
117impl Status {
118 fn started_from_config(config: &ApConfig) -> Self {
119 Status::Started {
120 band: config.band,
121 channel: config.radio_config.channel.primary,
122 mode: config.mode,
123 num_clients: 0,
124 security_type: config.id.security_type,
125 }
126 }
127
128 fn started_from_sme_update(update: &fidl_sme::Ap, config: &ApConfig) -> Self {
129 Status::Started {
130 band: config.band,
131 channel: update.channel,
132 mode: config.mode,
133 num_clients: update.num_clients,
134 security_type: config.id.security_type,
135 }
136 }
137}
138
139impl WriteInspect for Status {
140 fn write_inspect<'a>(&self, writer: &InspectNode, key: impl Into<Cow<'a, str>>) {
141 match self {
142 Status::Started { band, channel, mode, num_clients, security_type } => {
143 inspect_insert!(writer, var key: {
144 Started: {
145 band: format!("{:?}", band),
146 channel: channel,
147 mode: format!("{:?}", mode),
148 num_clients: num_clients,
149 security_type: format!("{:?}", security_type)
150 }
151 })
152 }
153 other => inspect_insert!(writer, var key: format!("{:?}", other)),
154 }
155 }
156}
157
158#[cfg_attr(test, derive(Debug))]
160#[derive(Clone, PartialEq)]
161pub struct ApConfig {
162 pub id: types::NetworkIdentifier,
163 pub credential: Vec<u8>,
164 pub radio_config: RadioConfig,
165 pub mode: types::ConnectivityMode,
166 pub band: types::OperatingBand,
167}
168
169impl From<ApConfig> for fidl_sme::ApConfig {
170 fn from(config: ApConfig) -> Self {
171 fidl_sme::ApConfig {
172 ssid: config.id.ssid.to_vec(),
173 password: config.credential,
174 radio_cfg: config.radio_config.into(),
175 }
176 }
177}
178
179struct ApStateTrackerInner {
180 state: Option<ApStateUpdate>,
181 sender: ApListenerMessageSender,
182}
183
184impl ApStateTrackerInner {
185 fn send_update(&mut self) -> Result<(), anyhow::Error> {
186 let updates = match self.state.clone() {
187 Some(state) => ApStatesUpdate { access_points: [state].to_vec() },
188 None => ApStatesUpdate { access_points: [].to_vec() },
189 };
190
191 self.sender
192 .clone()
193 .unbounded_send(NotifyListeners(updates))
194 .map_err(|e| format_err!("failed to send state update: {}", e))
195 }
196}
197
198struct ApStateTracker {
199 inner: Mutex<ApStateTrackerInner>,
200}
201
202impl ApStateTracker {
203 fn new(sender: ApListenerMessageSender) -> Self {
204 ApStateTracker { inner: Mutex::new(ApStateTrackerInner { state: None, sender }) }
205 }
206
207 fn reset_state(&self, state: ApStateUpdate) -> Result<(), anyhow::Error> {
208 let mut inner = self.inner.lock();
209 inner.state = Some(state);
210 inner.send_update()
211 }
212
213 fn consume_sme_status_update(
214 &self,
215 cbw: Cbw,
216 update: fidl_sme::Ap,
217 ) -> Result<(), anyhow::Error> {
218 let mut inner = self.inner.lock();
219
220 if let Some(ref mut state) = inner.state {
221 let channel = Channel::new(update.channel, cbw);
222 let frequency = match channel.get_center_freq() {
223 Ok(frequency) => Some(frequency as u32),
224 Err(e) => {
225 info!("failed to convert channel to frequency: {}", e);
226 None
227 }
228 };
229
230 let client_info = Some(ConnectedClientInformation { count: update.num_clients as u8 });
231
232 if frequency != state.frequency || client_info != state.clients {
233 state.frequency = frequency;
234 state.clients = client_info;
235 inner.send_update()?;
236 }
237 }
238
239 Ok(())
240 }
241
242 fn update_operating_state(
243 &self,
244 new_state: types::OperatingState,
245 ) -> Result<(), anyhow::Error> {
246 let mut inner = self.inner.lock();
247
248 if let Some(ref mut state) = inner.state {
250 if state.state != new_state {
251 state.state = new_state;
252 }
253 inner.send_update()?;
254 }
255
256 Ok(())
257 }
258
259 fn set_stopped_state(&self) -> Result<(), anyhow::Error> {
260 let mut inner = self.inner.lock();
261 inner.state = None;
262 inner.send_update()
263 }
264}
265
266struct CommonStateDependencies {
267 iface_id: u16,
268 proxy: SmeForApStateMachine,
269 req_stream: ReqStream,
270 state_tracker: Arc<ApStateTracker>,
271 telemetry_sender: TelemetrySender,
272 defect_sender: mpsc::Sender<Defect>,
273 status_publisher: StateMachineStatusPublisher<Status>,
274}
275
276pub async fn serve(
277 iface_id: u16,
278 proxy: SmeForApStateMachine,
279 sme_event_stream: fidl_sme::ApSmeEventStream,
280 req_stream: Fuse<mpsc::Receiver<ManualRequest>>,
281 message_sender: ApListenerMessageSender,
282 telemetry_sender: TelemetrySender,
283 defect_sender: mpsc::Sender<Defect>,
284 status_publisher: StateMachineStatusPublisher<Status>,
285) {
286 let state_tracker = Arc::new(ApStateTracker::new(message_sender));
287 let deps = CommonStateDependencies {
288 iface_id,
289 proxy,
290 req_stream,
291 state_tracker: state_tracker.clone(),
292 telemetry_sender,
293 defect_sender,
294 status_publisher: status_publisher.clone(),
295 };
296 let state_machine = stopped_state(deps).into_state_machine();
297 let removal_watcher = sme_event_stream.map_ok(|_| ()).try_collect::<()>();
298 select! {
299 state_machine = state_machine.fuse() => {
300 match state_machine {
301 Err(ExitReason(Ok(()))) => info!("AP state machine for iface #{} exited", iface_id),
302 Err(ExitReason(Err(e))) => {
303 info!("AP state machine for iface #{} terminated with an error: {}", iface_id, e)
304 }
305 }
306 },
307 removal_watcher = removal_watcher.fuse() => {
308 match removal_watcher {
309 Ok(()) => info!("AP interface was unexpectedly removed: {}", iface_id),
310 Err(e) => {
311 info!("Error reading from AP SME channel of iface #{}: {}", iface_id, e);
312 }
313 }
314 let _ = state_tracker.update_operating_state(types::OperatingState::Failed);
315 }
316 }
317
318 status_publisher.publish_status(Status::Stopped);
319}
320
321fn perform_manual_request(
322 deps: CommonStateDependencies,
323 req: Option<ManualRequest>,
324) -> Result<State, ExitReason> {
325 match req {
326 Some(ManualRequest::Start((req, responder))) => {
327 Ok(starting_state(deps, req, AP_START_MAX_RETRIES, Some(responder)).into_state())
328 }
329 Some(ManualRequest::Stop(responder)) => Ok(stopping_state(deps, responder).into_state()),
330 Some(ManualRequest::Exit(responder)) => {
331 responder.send(()).unwrap_or(());
332 Err(ExitReason(Ok(())))
333 }
334 None => {
335 deps.state_tracker
339 .update_operating_state(types::OperatingState::Failed)
340 .map_err(|e| ExitReason(Err(e)))?;
341
342 Err(ExitReason(Err(format_err!("The stream of user requests ended unexpectedly"))))
343 }
344 }
345}
346
347fn transition_to_starting(
349 deps: CommonStateDependencies,
350 req: ApConfig,
351 remaining_retries: u16,
352 responder: Option<oneshot::Sender<()>>,
353) -> Result<State, ExitReason> {
354 Ok(starting_state(deps, req, remaining_retries, responder).into_state())
355}
356
357async fn starting_state(
378 mut deps: CommonStateDependencies,
379 req: ApConfig,
380 remaining_retries: u16,
381 responder: Option<oneshot::Sender<()>>,
382) -> Result<State, ExitReason> {
383 deps.status_publisher.publish_status(Status::Starting);
384
385 let stop_result = match deps.proxy.stop().await {
387 Ok(fidl_sme::StopApResultCode::Success) => Ok(()),
388 Ok(code) => Err(format_err!("Unexpected StopApResultCode: {:?}", code)),
389 Err(e) => Err(format_err!("Failed to send a stop command to wlanstack: {}", e)),
390 };
391
392 if stop_result.is_err() {
394 deps.state_tracker
395 .reset_state(ApStateUpdate::new(
396 req.id.clone(),
397 types::OperatingState::Failed,
398 req.mode,
399 req.band,
400 ))
401 .map_err(|e| ExitReason(Err(e)))?;
402
403 stop_result.map_err(|e| ExitReason(Err(e)))?;
404 }
405
406 deps.state_tracker.set_stopped_state().map_err(|e| ExitReason(Err(e)))?;
408
409 if remaining_retries == AP_START_MAX_RETRIES {
411 deps.state_tracker
412 .reset_state(ApStateUpdate::new(
413 req.id.clone(),
414 types::OperatingState::Starting,
415 req.mode,
416 req.band,
417 ))
418 .map_err(|e| ExitReason(Err(e)))?;
419 }
420
421 let ap_config = fidl_sme::ApConfig::from(req.clone());
422 let start_result = match deps.proxy.start(&ap_config).await {
423 Ok(fidl_sme::StartApResultCode::Success) => {
424 deps.telemetry_sender.send(TelemetryEvent::StartApResult(Ok(())));
425 Ok(())
426 }
427 Ok(code) => {
428 deps.telemetry_sender.send(TelemetryEvent::StartApResult(Err(())));
430 if let Err(e) = deps
431 .defect_sender
432 .try_send(Defect::Iface(IfaceFailure::ApStartFailure { iface_id: deps.iface_id }))
433 {
434 warn!("Failed to log AP start defect: {}", e)
435 }
436
437 if remaining_retries > 0 {
442 let mut retry_timer = pin!(fasync::Timer::new(
443 zx::MonotonicDuration::from_seconds(AP_START_RETRY_INTERVAL).after_now(),
444 ));
445
446 select! {
449 () = retry_timer => {
450 return transition_to_starting(
451 deps,
452 req,
453 remaining_retries - 1,
454 responder,
455 );
456 },
457 req = deps.req_stream.next() => {
458 deps.state_tracker
460 .set_stopped_state()
461 .map_err(|e| ExitReason(Err(e)))?;
462 return perform_manual_request(deps, req)
463 }
464 }
465 }
466
467 Err(format_err!("Failed to start AP: {:?}", code))
469 }
470 Err(e) => {
471 Err(format_err!("Failed to send a start command to wlanstack: {}", e))
474 }
475 };
476
477 start_result.map_err(|e| {
478 if let Err(e) = deps.state_tracker.reset_state(ApStateUpdate::new(
480 req.id.clone(),
481 types::OperatingState::Failed,
482 req.mode,
483 req.band,
484 )) {
485 info!("Unable to notify listeners of AP start failure: {:?}", e);
486 }
487 ExitReason(Err(e))
488 })?;
489
490 #[allow(clippy::single_match, reason = "mass allow for https://fxbug.dev/381896734")]
491 match responder {
492 Some(responder) => responder.send(()).unwrap_or(()),
493 None => {}
494 }
495
496 deps.state_tracker
497 .update_operating_state(types::OperatingState::Active)
498 .map_err(|e| ExitReason(Err(e)))?;
499 Ok(started_state(deps, req).into_state())
500}
501
502async fn stopping_state(
514 deps: CommonStateDependencies,
515 responder: oneshot::Sender<()>,
516) -> Result<State, ExitReason> {
517 deps.status_publisher.publish_status(Status::Stopping);
518
519 let result = match deps.proxy.stop().await {
520 Ok(fidl_sme::StopApResultCode::Success) => Ok(()),
521 Ok(code) => Err(format_err!("Unexpected StopApResultCode: {:?}", code)),
522 Err(e) => Err(format_err!("Failed to send a stop command to wlanstack: {}", e)),
523 };
524
525 deps.state_tracker.set_stopped_state().map_err(|e| ExitReason(Err(e)))?;
529 result.map_err(|e| ExitReason(Err(e)))?;
530
531 responder.send(()).unwrap_or(());
533
534 Ok(stopped_state(deps).into_state())
535}
536
537async fn stopped_state(mut deps: CommonStateDependencies) -> Result<State, ExitReason> {
538 deps.status_publisher.publish_status(Status::Stopped);
539
540 loop {
542 let req = deps.req_stream.next().await;
543 match req {
544 Some(ManualRequest::Stop(responder)) => {
546 responder.send(()).unwrap_or(());
547 }
548 other => return perform_manual_request(deps, other),
550 }
551 }
552}
553
554async fn started_state(
555 mut deps: CommonStateDependencies,
556 req: ApConfig,
557) -> Result<State, ExitReason> {
558 deps.status_publisher.publish_status(Status::started_from_config(&req));
559
560 let mut pending_status_req = FuturesUnordered::new();
562 let status_proxy = deps.proxy.clone();
563 pending_status_req.push(async move { status_proxy.status().await }.boxed());
564
565 let mut status_timer =
566 fasync::Interval::new(zx::MonotonicDuration::from_seconds(AP_STATUS_INTERVAL_SEC));
567
568 let cbw = req.radio_config.channel.cbw;
570
571 loop {
572 select! {
573 status_response = pending_status_req.select_next_some() => {
574 let status_response = match status_response {
575 Ok(status_response) => status_response,
576 Err(e) => {
577 deps.state_tracker.update_operating_state(types::OperatingState::Failed)
580 .map_err(|e| { ExitReason(Err(e)) })?;
581
582 return Err(ExitReason(Err(e)));
583 }
584 };
585
586 match status_response.running_ap {
587 Some(sme_state) => {
588 deps.status_publisher
589 .publish_status(Status::started_from_sme_update(&sme_state, &req));
590 deps.state_tracker.consume_sme_status_update(cbw, *sme_state)
591 .map_err(|e| { ExitReason(Err(e)) })?;
592 }
593 None => {
594 deps.state_tracker.update_operating_state(types::OperatingState::Failed)
595 .map_err(|e| { ExitReason(Err(e)) })?;
596
597 return transition_to_starting(
598 deps,
599 req,
600 AP_START_MAX_RETRIES,
601 None,
602 );
603 }
604 }
605 },
606 _ = status_timer.select_next_some() => {
607 if pending_status_req.is_empty() {
608 let status_proxy = deps.proxy.clone();
609 pending_status_req.push(async move {
610 status_proxy.status().await
611 }.boxed());
612 }
613 },
614 manual_req = deps.req_stream.next() => {
615 return perform_manual_request(deps, manual_req)
616 },
617 complete => {
618 panic!("AP state machine terminated unexpectedly");
619 }
620 }
621 }
622}
623
624#[cfg(test)]
625mod tests {
626 use super::*;
627 use crate::util::listener;
628 use crate::util::state_machine::{status_publisher_and_reader, StateMachineStatusReader};
629 use assert_matches::assert_matches;
630 use fidl::endpoints::create_proxy;
631 use fidl_fuchsia_wlan_common as fidl_common;
632 use futures::stream::StreamFuture;
633 use futures::task::Poll;
634 use futures::Future;
635 use std::pin::pin;
636
637 struct TestValues {
638 deps: CommonStateDependencies,
639 sme_req_stream: fidl_sme::ApSmeRequestStream,
640 ap_req_sender: mpsc::Sender<ManualRequest>,
641 update_receiver: mpsc::UnboundedReceiver<listener::ApMessage>,
642 telemetry_receiver: mpsc::Receiver<TelemetryEvent>,
643 defect_receiver: mpsc::Receiver<Defect>,
644 status_reader: StateMachineStatusReader<Status>,
645 }
646
647 fn test_setup() -> TestValues {
648 let (ap_req_sender, ap_req_stream) = mpsc::channel(1);
649 let (update_sender, update_receiver) = mpsc::unbounded();
650 let (telemetry_sender, telemetry_receiver) = mpsc::channel(100);
651 let telemetry_sender = TelemetrySender::new(telemetry_sender);
652 let (defect_sender, defect_receiver) = mpsc::channel(100);
653 let (status_publisher, status_reader) = status_publisher_and_reader::<Status>();
654 let (sme_proxy, sme_server) = create_proxy::<fidl_sme::ApSmeMarker>();
655 let sme_req_stream = sme_server.into_stream();
656 let sme_proxy = SmeForApStateMachine::new(sme_proxy, 123, defect_sender.clone());
657
658 let deps = CommonStateDependencies {
659 iface_id: 123,
660 proxy: sme_proxy,
661 req_stream: ap_req_stream.fuse(),
662 state_tracker: Arc::new(ApStateTracker::new(update_sender)),
663 telemetry_sender,
664 defect_sender,
665 status_publisher,
666 };
667
668 TestValues {
669 deps,
670 sme_req_stream,
671 ap_req_sender,
672 update_receiver,
673 telemetry_receiver,
674 defect_receiver,
675 status_reader,
676 }
677 }
678
679 fn create_network_id() -> types::NetworkIdentifier {
680 types::NetworkIdentifier {
681 ssid: types::Ssid::try_from("test_ssid").unwrap(),
682 security_type: types::SecurityType::None,
683 }
684 }
685
686 fn poll_sme_req(
687 exec: &mut fasync::TestExecutor,
688 next_sme_req: &mut StreamFuture<fidl_sme::ApSmeRequestStream>,
689 ) -> Poll<fidl_sme::ApSmeRequest> {
690 exec.run_until_stalled(next_sme_req).map(|(req, stream)| {
691 *next_sme_req = stream.into_future();
692 req.expect("did not expect the SME request stream to end")
693 .expect("error polling SME request stream")
694 })
695 }
696
697 #[allow(clippy::needless_return, reason = "mass allow for https://fxbug.dev/381896734")]
698 async fn run_state_machine(fut: impl Future<Output = Result<State, ExitReason>> + 'static) {
699 let state_machine = fut.into_state_machine();
700 select! {
701 _state_machine = state_machine.fuse() => return,
702 }
703 }
704
705 #[fuchsia::test]
706 fn test_stop_during_started() {
707 let mut exec = fasync::TestExecutor::new();
708 let test_values = test_setup();
709
710 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
711 let req = ApConfig {
712 id: create_network_id(),
713 credential: vec![],
714 radio_config,
715 mode: types::ConnectivityMode::Unrestricted,
716 band: types::OperatingBand::Any,
717 };
718 {
719 let state = ApStateUpdate::new(
720 create_network_id(),
721 types::OperatingState::Starting,
722 types::ConnectivityMode::Unrestricted,
723 types::OperatingBand::Any,
724 );
725 test_values.deps.state_tracker.inner.lock().state = Some(state);
726 }
727
728 let fut = started_state(test_values.deps, req);
730 let fut = run_state_machine(fut);
731 let mut fut = pin!(fut);
732
733 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
734
735 let sme_fut = test_values.sme_req_stream.into_future();
736 let mut sme_fut = pin!(sme_fut);
737
738 assert_matches!(
739 poll_sme_req(&mut exec, &mut sme_fut),
740 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
741 let ap_info = fidl_sme::Ap { ssid: vec![], channel: 0, num_clients: 0 };
742 let response = fidl_sme::ApStatusResponse {
743 running_ap: Some(Box::new(ap_info))
744 };
745 responder.send(&response).expect("could not send AP status response");
746 }
747 );
748
749 let mut ap = AccessPoint::new(test_values.ap_req_sender);
751 let (sender, mut receiver) = oneshot::channel();
752 ap.stop(sender).expect("failed to make stop request");
753
754 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
756 assert_matches!(
757 poll_sme_req(&mut exec, &mut sme_fut),
758 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
759 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send SME stop response");
760 }
761 );
762
763 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
765 assert_matches!(exec.run_until_stalled(&mut receiver), Poll::Ready(Ok(())));
766 }
767
768 #[fuchsia::test]
769 fn test_exit_during_started() {
770 let mut exec = fasync::TestExecutor::new();
771 let test_values = test_setup();
772
773 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
774 let req = ApConfig {
775 id: create_network_id(),
776 credential: vec![],
777 radio_config,
778 mode: types::ConnectivityMode::Unrestricted,
779 band: types::OperatingBand::Any,
780 };
781 {
782 let state = ApStateUpdate::new(
783 create_network_id(),
784 types::OperatingState::Starting,
785 types::ConnectivityMode::Unrestricted,
786 types::OperatingBand::Any,
787 );
788 test_values.deps.state_tracker.inner.lock().state = Some(state);
789 }
790
791 let fut = started_state(test_values.deps, req);
793 let fut = run_state_machine(fut);
794 let mut fut = pin!(fut);
795
796 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
797
798 let sme_fut = test_values.sme_req_stream.into_future();
799 let mut sme_fut = pin!(sme_fut);
800
801 assert_matches!(
802 poll_sme_req(&mut exec, &mut sme_fut),
803 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
804 let ap_info = fidl_sme::Ap { ssid: vec![], channel: 0, num_clients: 0 };
805 let response = fidl_sme::ApStatusResponse {
806 running_ap: Some(Box::new(ap_info))
807 };
808 responder.send(&response).expect("could not send AP status response");
809 }
810 );
811
812 let mut ap = AccessPoint::new(test_values.ap_req_sender);
814 let (sender, mut receiver) = oneshot::channel();
815 ap.exit(sender).expect("failed to make stop request");
816
817 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
819 assert_matches!(exec.run_until_stalled(&mut receiver), Poll::Ready(Ok(())));
820 }
821
822 #[fuchsia::test]
823 fn test_start_during_started() {
824 let mut exec = fasync::TestExecutor::new();
825 let test_values = test_setup();
826
827 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
828 let req = ApConfig {
829 id: create_network_id(),
830 credential: vec![],
831 radio_config,
832 mode: types::ConnectivityMode::Unrestricted,
833 band: types::OperatingBand::Any,
834 };
835 {
836 let state = ApStateUpdate::new(
837 create_network_id(),
838 types::OperatingState::Starting,
839 types::ConnectivityMode::Unrestricted,
840 types::OperatingBand::Any,
841 );
842 test_values.deps.state_tracker.inner.lock().state = Some(state);
843 }
844
845 let fut = started_state(test_values.deps, req);
847 let fut = run_state_machine(fut);
848 let mut fut = pin!(fut);
849
850 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
851
852 let sme_fut = test_values.sme_req_stream.into_future();
853 let mut sme_fut = pin!(sme_fut);
854
855 assert_matches!(
856 poll_sme_req(&mut exec, &mut sme_fut),
857 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
858 let ap_info = fidl_sme::Ap { ssid: vec![], channel: 0, num_clients: 0 };
859 let response = fidl_sme::ApStatusResponse {
860 running_ap: Some(Box::new(ap_info))
861 };
862 responder.send(&response).expect("could not send AP status response");
863 }
864 );
865
866 let mut ap = AccessPoint::new(test_values.ap_req_sender);
868 let (sender, mut receiver) = oneshot::channel();
869 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
870 let req = ApConfig {
871 id: create_network_id(),
872 credential: vec![],
873 radio_config,
874 mode: types::ConnectivityMode::Unrestricted,
875 band: types::OperatingBand::Any,
876 };
877 ap.start(req, sender).expect("failed to make stop request");
878
879 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
881 assert_matches!(
882 poll_sme_req(&mut exec, &mut sme_fut),
883 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
884 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
885 }
886 );
887
888 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
889 assert_matches!(
890 poll_sme_req(&mut exec, &mut sme_fut),
891 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
892 responder
893 .send(fidl_sme::StartApResultCode::Success)
894 .expect("could not send AP stop response");
895 }
896 );
897
898 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
900 assert_matches!(exec.run_until_stalled(&mut receiver), Poll::Ready(Ok(())));
901 }
902
903 #[fuchsia::test]
904 fn test_duplicate_status_during_started() {
905 let mut exec = fasync::TestExecutor::new();
906 let test_values = test_setup();
907
908 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
909 let req = ApConfig {
910 id: create_network_id(),
911 credential: vec![],
912 radio_config,
913 mode: types::ConnectivityMode::Unrestricted,
914 band: types::OperatingBand::Any,
915 };
916 {
917 let mut state = ApStateUpdate::new(
918 create_network_id(),
919 types::OperatingState::Starting,
920 types::ConnectivityMode::Unrestricted,
921 types::OperatingBand::Any,
922 );
923 state.frequency = Some(2437);
924 state.clients = Some(ConnectedClientInformation { count: 0 });
925 test_values.deps.state_tracker.inner.lock().state = Some(state);
926 }
927
928 let fut = started_state(test_values.deps, req);
930 let fut = run_state_machine(fut);
931 let mut fut = pin!(fut);
932
933 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
934
935 let sme_fut = test_values.sme_req_stream.into_future();
936 let mut sme_fut = pin!(sme_fut);
937
938 assert_matches!(
939 poll_sme_req(&mut exec, &mut sme_fut),
940 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
941 let ap_info = fidl_sme::Ap { ssid: vec![], channel: 6, num_clients: 0 };
942 let response = fidl_sme::ApStatusResponse {
943 running_ap: Some(Box::new(ap_info))
944 };
945 responder.send(&response).expect("could not send AP status response");
946 }
947 );
948
949 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
951 assert_matches!(
952 exec.run_until_stalled(&mut test_values.update_receiver.into_future()),
953 Poll::Pending
954 );
955 }
956
957 #[fuchsia::test]
958 fn test_new_status_during_started() {
959 let mut exec = fasync::TestExecutor::new();
960 let test_values = test_setup();
961
962 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
963 let req = ApConfig {
964 id: create_network_id(),
965 credential: vec![],
966 radio_config,
967 mode: types::ConnectivityMode::Unrestricted,
968 band: types::OperatingBand::Any,
969 };
970 {
971 let mut state = ApStateUpdate::new(
972 create_network_id(),
973 types::OperatingState::Starting,
974 types::ConnectivityMode::Unrestricted,
975 types::OperatingBand::Any,
976 );
977 state.frequency = Some(0);
978 state.clients = Some(ConnectedClientInformation { count: 0 });
979 test_values.deps.state_tracker.inner.lock().state = Some(state);
980 }
981
982 let fut = started_state(test_values.deps, req);
984 let fut = run_state_machine(fut);
985 let mut fut = pin!(fut);
986
987 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
988
989 assert_matches!(
991 test_values.status_reader.read_status(),
992 Ok(Status::Started {
993 band: types::OperatingBand::Any,
994 channel: 6,
995 mode: types::ConnectivityMode::Unrestricted,
996 num_clients: 0,
997 security_type: types::SecurityType::None,
998 })
999 );
1000
1001 let sme_fut = test_values.sme_req_stream.into_future();
1003 let mut sme_fut = pin!(sme_fut);
1004
1005 assert_matches!(
1006 poll_sme_req(&mut exec, &mut sme_fut),
1007 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
1008 let ap_info = fidl_sme::Ap { ssid: vec![], channel: 1, num_clients: 1 };
1009 let response = fidl_sme::ApStatusResponse {
1010 running_ap: Some(Box::new(ap_info))
1011 };
1012 responder.send(&response).expect("could not send AP status response");
1013 }
1014 );
1015
1016 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1018 assert_matches!(
1019 exec.run_until_stalled(&mut test_values.update_receiver.into_future()),
1020 Poll::Ready((Some(listener::Message::NotifyListeners(updates)), _)) => {
1021 assert!(!updates.access_points.is_empty());
1022 });
1023
1024 assert_matches!(
1026 test_values.status_reader.read_status(),
1027 Ok(Status::Started {
1028 band: types::OperatingBand::Any,
1029 channel: 1,
1030 mode: types::ConnectivityMode::Unrestricted,
1031 num_clients: 1,
1032 security_type: types::SecurityType::None,
1033 })
1034 );
1035 }
1036
1037 #[fuchsia::test]
1038 fn test_sme_failure_during_started() {
1039 let mut exec = fasync::TestExecutor::new();
1040 let mut test_values = test_setup();
1041
1042 drop(test_values.sme_req_stream);
1044
1045 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1046 let req = ApConfig {
1047 id: create_network_id(),
1048 credential: vec![],
1049 radio_config,
1050 mode: types::ConnectivityMode::Unrestricted,
1051 band: types::OperatingBand::Any,
1052 };
1053 {
1054 let mut state = ApStateUpdate::new(
1055 create_network_id(),
1056 types::OperatingState::Starting,
1057 types::ConnectivityMode::Unrestricted,
1058 types::OperatingBand::Any,
1059 );
1060 state.frequency = Some(0);
1061 state.clients = Some(ConnectedClientInformation { count: 0 });
1062 test_values.deps.state_tracker.inner.lock().state = Some(state);
1063 }
1064
1065 let fut = started_state(test_values.deps, req);
1067 let fut = run_state_machine(fut);
1068 let mut fut = pin!(fut);
1069
1070 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1072
1073 assert_matches!(
1075 test_values.update_receiver.try_next(),
1076 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
1077 let update = updates.access_points.pop().expect("no new updates available.");
1078 assert_eq!(update.state, types::OperatingState::Failed);
1079 });
1080 }
1081
1082 #[fuchsia::test]
1083 fn test_stop_while_stopped() {
1084 let mut exec = fasync::TestExecutor::new();
1085 let test_values = test_setup();
1086
1087 let fut = stopped_state(test_values.deps);
1089 let fut = run_state_machine(fut);
1090 let mut fut = pin!(fut);
1091
1092 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1093
1094 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1096 let (sender, mut receiver) = oneshot::channel();
1097 ap.stop(sender).expect("failed to make stop request");
1098
1099 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1101 assert_matches!(exec.run_until_stalled(&mut receiver), Poll::Ready(Ok(())));
1102 }
1103
1104 #[fuchsia::test]
1105 fn test_exit_while_stopped() {
1106 let mut exec = fasync::TestExecutor::new();
1107 let test_values = test_setup();
1108
1109 let fut = stopped_state(test_values.deps);
1111 let fut = run_state_machine(fut);
1112 let mut fut = pin!(fut);
1113
1114 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1116 let (sender, mut receiver) = oneshot::channel();
1117 ap.exit(sender).expect("failed to make stop request");
1118
1119 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1121 assert_matches!(exec.run_until_stalled(&mut receiver), Poll::Ready(Ok(())));
1122 }
1123
1124 #[fuchsia::test]
1125 fn test_start_while_stopped() {
1126 let mut exec = fasync::TestExecutor::new();
1127 let mut test_values = test_setup();
1128
1129 let fut = stopped_state(test_values.deps);
1131 let fut = run_state_machine(fut);
1132 let mut fut = pin!(fut);
1133
1134 let (sender, mut receiver) = oneshot::channel();
1136 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1137 let req = ApConfig {
1138 id: create_network_id(),
1139 credential: vec![],
1140 radio_config,
1141 mode: types::ConnectivityMode::Unrestricted,
1142 band: types::OperatingBand::Any,
1143 };
1144
1145 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1146 ap.start(req, sender).expect("failed to make stop request");
1147
1148 let sme_fut = test_values.sme_req_stream.into_future();
1150 let mut sme_fut = pin!(sme_fut);
1151
1152 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1153 assert_matches!(
1154 poll_sme_req(&mut exec, &mut sme_fut),
1155 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1156 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
1157 }
1158 );
1159
1160 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1162 assert_matches!(
1163 test_values.update_receiver.try_next(),
1164 Ok(Some(listener::Message::NotifyListeners(updates))) => {
1165 assert!(updates.access_points.is_empty());
1166 });
1167
1168 assert_matches!(
1170 test_values.update_receiver.try_next(),
1171 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
1172 let update = updates.access_points.pop().expect("no new updates available.");
1173 assert_eq!(update.state, types::OperatingState::Starting);
1174 });
1175
1176 assert_matches!(
1178 poll_sme_req(&mut exec, &mut sme_fut),
1179 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
1180 responder
1181 .send(fidl_sme::StartApResultCode::Success)
1182 .expect("could not send AP stop response");
1183 }
1184 );
1185
1186 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1188 assert_matches!(exec.run_until_stalled(&mut receiver), Poll::Ready(Ok(())));
1189
1190 assert_matches!(
1192 test_values.update_receiver.try_next(),
1193 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
1194 let update = updates.access_points.pop().expect("no new updates available.");
1195 assert_eq!(update.state, types::OperatingState::Active);
1196 });
1197 }
1198
1199 #[fuchsia::test]
1200 fn test_exit_while_stopping() {
1201 let mut exec = fasync::TestExecutor::new();
1202 let test_values = test_setup();
1203
1204 let (stop_sender, mut stop_receiver) = oneshot::channel();
1206 let fut = stopping_state(test_values.deps, stop_sender);
1207 let fut = run_state_machine(fut);
1208 let mut fut = pin!(fut);
1209
1210 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1212 let (exit_sender, mut exit_receiver) = oneshot::channel();
1213 ap.exit(exit_sender).expect("failed to make stop request");
1214
1215 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1217 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Pending);
1218 assert_matches!(exec.run_until_stalled(&mut exit_receiver), Poll::Pending);
1219
1220 let sme_fut = test_values.sme_req_stream.into_future();
1222 let mut sme_fut = pin!(sme_fut);
1223 assert_matches!(
1224 poll_sme_req(&mut exec, &mut sme_fut),
1225 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1226 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
1227 }
1228 );
1229 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1230 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Ready(Ok(())));
1231 assert_matches!(exec.run_until_stalled(&mut exit_receiver), Poll::Ready(Ok(())));
1232 }
1233
1234 #[fuchsia::test]
1235 fn test_stop_while_stopping() {
1236 let mut exec = fasync::TestExecutor::new();
1237 let mut test_values = test_setup();
1238
1239 let (stop_sender, mut stop_receiver) = oneshot::channel();
1241 let fut = stopping_state(test_values.deps, stop_sender);
1242 let fut = run_state_machine(fut);
1243 let mut fut = pin!(fut);
1244
1245 assert_matches!(&mut test_values.update_receiver.try_next(), Err(_));
1247
1248 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1250 let (second_stop_sender, mut second_stop_receiver) = oneshot::channel();
1251 ap.stop(second_stop_sender).expect("failed to make stop request");
1252
1253 let sme_fut = test_values.sme_req_stream.into_future();
1255 let mut sme_fut = pin!(sme_fut);
1256
1257 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1258 assert_matches!(
1259 poll_sme_req(&mut exec, &mut sme_fut),
1260 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1261 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
1262 }
1263 );
1264
1265 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1267 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Ready(Ok(())));
1268 assert_matches!(exec.run_until_stalled(&mut second_stop_receiver), Poll::Ready(Ok(())));
1269
1270 assert_matches!(
1272 test_values.update_receiver.try_next(),
1273 Ok(Some(listener::Message::NotifyListeners(updates))) => {
1274 assert!(updates.access_points.is_empty());
1275 });
1276 }
1277
1278 #[fuchsia::test]
1279 fn test_start_while_stopping() {
1280 let mut exec = fasync::TestExecutor::new();
1281 let test_values = test_setup();
1282
1283 let (stop_sender, mut stop_receiver) = oneshot::channel();
1285 let fut = stopping_state(test_values.deps, stop_sender);
1286 let fut = run_state_machine(fut);
1287 let mut fut = pin!(fut);
1288
1289 let (start_sender, mut start_receiver) = oneshot::channel();
1291 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1292 let req = ApConfig {
1293 id: create_network_id(),
1294 credential: vec![],
1295 radio_config,
1296 mode: types::ConnectivityMode::Unrestricted,
1297 band: types::OperatingBand::Any,
1298 };
1299
1300 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1301 ap.start(req, start_sender).expect("failed to make stop request");
1302
1303 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1305 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Pending);
1306 let sme_fut = test_values.sme_req_stream.into_future();
1307 let mut sme_fut = pin!(sme_fut);
1308 let stop_responder = assert_matches!(
1309 poll_sme_req(&mut exec, &mut sme_fut),
1310 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => responder
1311 );
1312
1313 assert_matches!(poll_sme_req(&mut exec, &mut sme_fut), Poll::Pending);
1315
1316 stop_responder
1318 .send(fidl_sme::StopApResultCode::Success)
1319 .expect("could not send AP stop response");
1320 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1321 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Ready(Ok(())));
1322
1323 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1325 assert_matches!(
1326 poll_sme_req(&mut exec, &mut sme_fut),
1327 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1328 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
1329 }
1330 );
1331
1332 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1334 assert_matches!(
1335 poll_sme_req(&mut exec, &mut sme_fut),
1336 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
1337 responder
1338 .send(fidl_sme::StartApResultCode::Success)
1339 .expect("could not send AP stop response");
1340 }
1341 );
1342
1343 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1345 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Ready(Ok(())));
1346 }
1347
1348 #[fuchsia::test]
1349 fn test_sme_failure_while_stopping() {
1350 let mut exec = fasync::TestExecutor::new();
1351 let mut test_values = test_setup();
1352
1353 drop(test_values.sme_req_stream);
1355
1356 let (stop_sender, mut stop_receiver) = oneshot::channel();
1358 let fut = stopping_state(test_values.deps, stop_sender);
1359 let fut = run_state_machine(fut);
1360 let mut fut = pin!(fut);
1361
1362 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1364 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Ready(Err(_)));
1365
1366 assert_matches!(
1368 test_values.update_receiver.try_next(),
1369 Ok(Some(listener::Message::NotifyListeners(updates))) => {
1370 assert!(updates.access_points.is_empty());
1371 });
1372 }
1373
1374 #[fuchsia::test]
1375 fn test_failed_result_code_while_stopping() {
1376 let mut exec = fasync::TestExecutor::new();
1377 let mut test_values = test_setup();
1378
1379 let (stop_sender, mut stop_receiver) = oneshot::channel();
1381 let fut = stopping_state(test_values.deps, stop_sender);
1382 let fut = run_state_machine(fut);
1383 let mut fut = pin!(fut);
1384
1385 assert_matches!(&mut test_values.update_receiver.try_next(), Err(_));
1387
1388 let sme_fut = test_values.sme_req_stream.into_future();
1390 let mut sme_fut = pin!(sme_fut);
1391
1392 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1393 assert_matches!(
1394 poll_sme_req(&mut exec, &mut sme_fut),
1395 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1396 responder.send(fidl_sme::StopApResultCode::InternalError).expect("could not send AP stop response");
1397 }
1398 );
1399
1400 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1402 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Ready(Err(_)));
1403
1404 assert_matches!(
1406 test_values.update_receiver.try_next(),
1407 Ok(Some(listener::Message::NotifyListeners(updates))) => {
1408 assert!(updates.access_points.is_empty());
1409 });
1410 }
1411
1412 #[fuchsia::test]
1413 fn test_stop_while_starting() {
1414 let mut exec = fasync::TestExecutor::new();
1415 let mut test_values = test_setup();
1416
1417 let (start_sender, mut start_receiver) = oneshot::channel();
1418 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1419 let req = ApConfig {
1420 id: create_network_id(),
1421 credential: vec![],
1422 radio_config,
1423 mode: types::ConnectivityMode::Unrestricted,
1424 band: types::OperatingBand::Any,
1425 };
1426
1427 let fut = starting_state(test_values.deps, req, 0, Some(start_sender));
1429 let fut = run_state_machine(fut);
1430 let mut fut = pin!(fut);
1431
1432 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1434
1435 let sme_fut = test_values.sme_req_stream.into_future();
1436 let mut sme_fut = pin!(sme_fut);
1437
1438 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1439 assert_matches!(
1440 poll_sme_req(&mut exec, &mut sme_fut),
1441 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1442 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
1443 }
1444 );
1445
1446 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1448 let start_responder = assert_matches!(
1449 poll_sme_req(&mut exec, &mut sme_fut),
1450 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
1451 responder
1452 }
1453 );
1454
1455 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1457 let (stop_sender, mut stop_receiver) = oneshot::channel();
1458 ap.stop(stop_sender).expect("failed to make stop request");
1459
1460 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1462 assert_matches!(poll_sme_req(&mut exec, &mut sme_fut), Poll::Pending);
1463
1464 start_responder
1466 .send(fidl_sme::StartApResultCode::Success)
1467 .expect("could not send SME start response");
1468 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1469 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Ready(Ok(())));
1470
1471 assert_matches!(
1473 poll_sme_req(&mut exec, &mut sme_fut),
1474 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1475 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send SME stop response");
1476 }
1477 );
1478
1479 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1481 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Ready(Ok(())));
1482
1483 assert_matches!(
1485 test_values.telemetry_receiver.try_next(),
1486 Ok(Some(TelemetryEvent::StartApResult(Ok(()))))
1487 );
1488 }
1489
1490 #[fuchsia::test]
1491 fn test_start_while_starting() {
1492 let mut exec = fasync::TestExecutor::new();
1493 let mut test_values = test_setup();
1494
1495 let (start_sender, mut start_receiver) = oneshot::channel();
1496 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1497 let req = ApConfig {
1498 id: create_network_id(),
1499 credential: vec![],
1500 radio_config,
1501 mode: types::ConnectivityMode::Unrestricted,
1502 band: types::OperatingBand::Any,
1503 };
1504
1505 let fut = starting_state(test_values.deps, req, 0, Some(start_sender));
1507 let fut = run_state_machine(fut);
1508 let mut fut = pin!(fut);
1509
1510 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1512
1513 let sme_fut = test_values.sme_req_stream.into_future();
1514 let mut sme_fut = pin!(sme_fut);
1515
1516 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1517 assert_matches!(
1518 poll_sme_req(&mut exec, &mut sme_fut),
1519 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1520 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
1521 }
1522 );
1523
1524 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1526 let start_responder = assert_matches!(
1527 poll_sme_req(&mut exec, &mut sme_fut),
1528 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
1529 responder
1530 }
1531 );
1532
1533 let (second_start_sender, mut second_start_receiver) = oneshot::channel();
1535 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1536 let req = ApConfig {
1537 id: create_network_id(),
1538 credential: vec![],
1539 radio_config,
1540 mode: types::ConnectivityMode::Unrestricted,
1541 band: types::OperatingBand::Any,
1542 };
1543 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1544 ap.start(req, second_start_sender).expect("failed to make start request");
1545
1546 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1549 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Pending);
1550 assert_matches!(poll_sme_req(&mut exec, &mut sme_fut), Poll::Pending);
1551
1552 start_responder
1554 .send(fidl_sme::StartApResultCode::Success)
1555 .expect("failed to send start response");
1556
1557 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1559 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Ready(Ok(())));
1560 assert_matches!(exec.run_until_stalled(&mut second_start_receiver), Poll::Pending);
1561
1562 assert_matches!(
1565 poll_sme_req(&mut exec, &mut sme_fut),
1566 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1567 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send SME stop response");
1568 }
1569 );
1570
1571 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1573 assert_matches!(
1574 poll_sme_req(&mut exec, &mut sme_fut),
1575 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
1576 responder
1577 .send(fidl_sme::StartApResultCode::Success)
1578 .expect("failed to send start response");
1579 }
1580 );
1581
1582 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1584 assert_matches!(exec.run_until_stalled(&mut second_start_receiver), Poll::Ready(Ok(())));
1585
1586 assert_matches!(
1588 test_values.telemetry_receiver.try_next(),
1589 Ok(Some(TelemetryEvent::StartApResult(Ok(()))))
1590 );
1591 }
1592
1593 #[fuchsia::test]
1594 fn test_exit_while_starting() {
1595 let mut exec = fasync::TestExecutor::new();
1596 let mut test_values = test_setup();
1597
1598 let (start_sender, mut start_receiver) = oneshot::channel();
1599 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1600 let req = ApConfig {
1601 id: create_network_id(),
1602 credential: vec![],
1603 radio_config,
1604 mode: types::ConnectivityMode::Unrestricted,
1605 band: types::OperatingBand::Any,
1606 };
1607
1608 let fut = starting_state(test_values.deps, req, 0, Some(start_sender));
1610 let fut = run_state_machine(fut);
1611 let mut fut = pin!(fut);
1612
1613 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1615
1616 let sme_fut = test_values.sme_req_stream.into_future();
1617 let mut sme_fut = pin!(sme_fut);
1618
1619 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1620 assert_matches!(
1621 poll_sme_req(&mut exec, &mut sme_fut),
1622 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1623 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
1624 }
1625 );
1626
1627 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1629 let start_responder = assert_matches!(
1630 poll_sme_req(&mut exec, &mut sme_fut),
1631 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
1632 responder
1633 }
1634 );
1635
1636 let mut ap = AccessPoint::new(test_values.ap_req_sender);
1638 let (exit_sender, mut exit_receiver) = oneshot::channel();
1639 ap.exit(exit_sender).expect("failed to make stop request");
1640
1641 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1643 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Pending);
1644 assert_matches!(exec.run_until_stalled(&mut exit_receiver), Poll::Pending);
1645
1646 start_responder
1648 .send(fidl_sme::StartApResultCode::Success)
1649 .expect("could not send AP start response");
1650
1651 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1652 assert_matches!(exec.run_until_stalled(&mut exit_receiver), Poll::Ready(Ok(())));
1653 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Ready(Ok(())));
1654
1655 assert_matches!(
1657 test_values.telemetry_receiver.try_next(),
1658 Ok(Some(TelemetryEvent::StartApResult(Ok(()))))
1659 );
1660 }
1661
1662 #[fuchsia::test]
1663 fn test_sme_breaks_while_starting() {
1664 let mut exec = fasync::TestExecutor::new();
1665 let mut test_values = test_setup();
1666
1667 drop(test_values.sme_req_stream);
1669
1670 let (start_sender, _start_receiver) = oneshot::channel();
1671 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1672 let req = ApConfig {
1673 id: create_network_id(),
1674 credential: vec![],
1675 radio_config,
1676 mode: types::ConnectivityMode::Unrestricted,
1677 band: types::OperatingBand::Any,
1678 };
1679
1680 let fut = starting_state(test_values.deps, req, 0, Some(start_sender));
1682 let fut = run_state_machine(fut);
1683 let mut fut = pin!(fut);
1684
1685 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1687
1688 assert_matches!(test_values.telemetry_receiver.try_next(), Ok(None));
1690 }
1691
1692 #[fuchsia::test]
1693 fn test_sme_fails_to_stop_while_starting() {
1694 let mut exec = fasync::TestExecutor::new();
1695 let mut test_values = test_setup();
1696
1697 let (start_sender, _start_receiver) = oneshot::channel();
1698 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1699 let req = ApConfig {
1700 id: create_network_id(),
1701 credential: vec![],
1702 radio_config,
1703 mode: types::ConnectivityMode::Unrestricted,
1704 band: types::OperatingBand::Any,
1705 };
1706
1707 let fut = starting_state(test_values.deps, req, 0, Some(start_sender));
1709 let fut = run_state_machine(fut);
1710 let mut fut = pin!(fut);
1711
1712 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1714
1715 let sme_fut = test_values.sme_req_stream.into_future();
1716 let mut sme_fut = pin!(sme_fut);
1717
1718 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1719 assert_matches!(
1720 poll_sme_req(&mut exec, &mut sme_fut),
1721 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1722 responder
1723 .send(fidl_sme::StopApResultCode::TimedOut)
1724 .expect("could not send AP stop response");
1725 }
1726 );
1727
1728 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1730
1731 assert_matches!(
1733 test_values.update_receiver.try_next(),
1734 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
1735 let update = updates.access_points.pop().expect("no new updates available.");
1736 assert_eq!(update.state, types::OperatingState::Failed);
1737 });
1738
1739 assert_matches!(test_values.telemetry_receiver.try_next(), Ok(None));
1741 }
1742
1743 #[fuchsia::test]
1744 fn test_sme_fails_to_start_while_starting() {
1745 let mut exec = fasync::TestExecutor::new();
1746 let mut test_values = test_setup();
1747
1748 let (start_sender, mut start_receiver) = oneshot::channel();
1749 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1750 let req = ApConfig {
1751 id: create_network_id(),
1752 credential: vec![],
1753 radio_config,
1754 mode: types::ConnectivityMode::Unrestricted,
1755 band: types::OperatingBand::Any,
1756 };
1757
1758 let fut = starting_state(test_values.deps, req, AP_START_MAX_RETRIES, Some(start_sender));
1760 let fut = run_state_machine(fut);
1761 let mut fut = pin!(fut);
1762
1763 let sme_fut = test_values.sme_req_stream.into_future();
1765 let mut sme_fut = pin!(sme_fut);
1766
1767 for retry_number in 0..(AP_START_MAX_RETRIES + 1) {
1768 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1770 assert_matches!(
1771 poll_sme_req(&mut exec, &mut sme_fut),
1772 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1773 responder
1774 .send(fidl_sme::StopApResultCode::Success)
1775 .expect("could not send AP stop response");
1776 }
1777 );
1778
1779 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1781 assert_matches!(
1782 test_values.update_receiver.try_next(),
1783 Ok(Some(listener::Message::NotifyListeners(_)))
1784 );
1785
1786 if retry_number == 0 {
1789 assert_matches!(
1790 test_values.update_receiver.try_next(),
1791 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
1792 let update = updates.access_points.pop().expect("no new updates available.");
1793 assert_eq!(update.state, types::OperatingState::Starting);
1794 });
1795 } else {
1796 assert_matches!(test_values.update_receiver.try_next(), Err(_));
1797 }
1798
1799 assert_matches!(
1801 poll_sme_req(&mut exec, &mut sme_fut),
1802 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
1803 responder
1804 .send(fidl_sme::StartApResultCode::TimedOut)
1805 .expect("could not send AP stop response");
1806 }
1807 );
1808
1809 if retry_number < AP_START_MAX_RETRIES {
1810 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1812
1813 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Pending);
1815
1816 assert_matches!(exec.wake_next_timer(), Some(_));
1818 }
1819 }
1820
1821 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1823
1824 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Ready(Err(_)));
1826
1827 assert_matches!(
1829 test_values.update_receiver.try_next(),
1830 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
1831 let update = updates.access_points.pop().expect("no new updates available.");
1832 assert_eq!(update.state, types::OperatingState::Failed);
1833 });
1834
1835 assert_matches!(
1837 test_values.telemetry_receiver.try_next(),
1838 Ok(Some(TelemetryEvent::StartApResult(Err(()))))
1839 );
1840
1841 assert_matches!(
1843 test_values.defect_receiver.try_next(),
1844 Ok(Some(Defect::Iface(IfaceFailure::ApStartFailure { .. })))
1845 );
1846 }
1847
1848 #[fuchsia::test]
1849 fn test_stop_after_start_failure() {
1850 let mut exec = fasync::TestExecutor::new();
1851 let mut test_values = test_setup();
1852
1853 let (start_sender, mut start_receiver) = oneshot::channel();
1854 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1855 let req = ApConfig {
1856 id: create_network_id(),
1857 credential: vec![],
1858 radio_config,
1859 mode: types::ConnectivityMode::Unrestricted,
1860 band: types::OperatingBand::Any,
1861 };
1862
1863 let (stop_sender, mut stop_receiver) = oneshot::channel();
1865 test_values
1866 .ap_req_sender
1867 .try_send(ManualRequest::Stop(stop_sender))
1868 .expect("failed to request AP stop");
1869
1870 let fut = starting_state(test_values.deps, req, AP_START_MAX_RETRIES, Some(start_sender));
1872 let fut = run_state_machine(fut);
1873 let mut fut = pin!(fut);
1874
1875 let sme_fut = test_values.sme_req_stream.into_future();
1877 let mut sme_fut = pin!(sme_fut);
1878
1879 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1881 assert_matches!(
1882 poll_sme_req(&mut exec, &mut sme_fut),
1883 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1884 responder
1885 .send(fidl_sme::StopApResultCode::Success)
1886 .expect("could not send AP stop response");
1887 }
1888 );
1889
1890 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1892 assert_matches!(
1893 test_values.update_receiver.try_next(),
1894 Ok(Some(listener::Message::NotifyListeners(_)))
1895 );
1896
1897 assert_matches!(
1899 test_values.update_receiver.try_next(),
1900 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
1901 let update = updates.access_points.pop().expect("no new updates available.");
1902 assert_eq!(update.state, types::OperatingState::Starting);
1903 });
1904
1905 assert_matches!(
1907 poll_sme_req(&mut exec, &mut sme_fut),
1908 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
1909 responder
1910 .send(fidl_sme::StartApResultCode::TimedOut)
1911 .expect("could not send AP stop response");
1912 }
1913 );
1914
1915 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1919
1920 assert_matches!(
1922 test_values.telemetry_receiver.try_next(),
1923 Ok(Some(TelemetryEvent::StartApResult(Err(()))))
1924 );
1925
1926 assert_matches!(
1928 test_values.defect_receiver.try_next(),
1929 Ok(Some(Defect::Iface(IfaceFailure::ApStartFailure { .. })))
1930 );
1931
1932 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Ready(Err(_)));
1934
1935 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1937 assert_matches!(
1938 poll_sme_req(&mut exec, &mut sme_fut),
1939 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
1940 responder
1941 .send(fidl_sme::StopApResultCode::Success)
1942 .expect("could not send AP stop response");
1943 }
1944 );
1945
1946 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1948
1949 assert_matches!(exec.run_until_stalled(&mut stop_receiver), Poll::Ready(Ok(())));
1951
1952 assert_matches!(
1954 test_values.update_receiver.try_next(),
1955 Ok(Some(listener::Message::NotifyListeners(updates))) => {
1956 assert!(updates.access_points.is_empty());
1957 });
1958 }
1959
1960 #[fuchsia::test]
1961 fn test_start_after_start_failure() {
1962 let mut exec = fasync::TestExecutor::new();
1963 let mut test_values = test_setup();
1964
1965 let (start_sender, mut start_receiver) = oneshot::channel();
1966 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
1967 let req = ApConfig {
1968 id: create_network_id(),
1969 credential: vec![],
1970 radio_config: radio_config.clone(),
1971 mode: types::ConnectivityMode::Unrestricted,
1972 band: types::OperatingBand::Any,
1973 };
1974
1975 let mut requested_id = create_network_id();
1977 requested_id.ssid = types::Ssid::try_from("second_test_ssid").unwrap();
1978
1979 let requested_config = ApConfig {
1980 id: requested_id.clone(),
1981 credential: vec![],
1982 radio_config,
1983 mode: types::ConnectivityMode::Unrestricted,
1984 band: types::OperatingBand::Any,
1985 };
1986
1987 let (start_response_sender, _) = oneshot::channel();
1988 test_values
1989 .ap_req_sender
1990 .try_send(ManualRequest::Start((requested_config, start_response_sender)))
1991 .expect("failed to request AP stop");
1992
1993 let fut = starting_state(test_values.deps, req, AP_START_MAX_RETRIES, Some(start_sender));
1995 let fut = run_state_machine(fut);
1996 let mut fut = pin!(fut);
1997
1998 let sme_fut = test_values.sme_req_stream.into_future();
2000 let mut sme_fut = pin!(sme_fut);
2001
2002 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2004 assert_matches!(
2005 poll_sme_req(&mut exec, &mut sme_fut),
2006 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
2007 responder
2008 .send(fidl_sme::StopApResultCode::Success)
2009 .expect("could not send AP stop response");
2010 }
2011 );
2012
2013 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2015 assert_matches!(
2016 test_values.update_receiver.try_next(),
2017 Ok(Some(listener::Message::NotifyListeners(_)))
2018 );
2019
2020 assert_matches!(
2022 test_values.update_receiver.try_next(),
2023 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
2024 let update = updates.access_points.pop().expect("no new updates available.");
2025 assert_eq!(update.state, types::OperatingState::Starting);
2026 });
2027
2028 assert_matches!(
2030 poll_sme_req(&mut exec, &mut sme_fut),
2031 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
2032 responder
2033 .send(fidl_sme::StartApResultCode::TimedOut)
2034 .expect("could not send AP stop response");
2035 }
2036 );
2037
2038 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2042
2043 assert_matches!(
2045 test_values.telemetry_receiver.try_next(),
2046 Ok(Some(TelemetryEvent::StartApResult(Err(()))))
2047 );
2048
2049 assert_matches!(
2051 test_values.defect_receiver.try_next(),
2052 Ok(Some(Defect::Iface(IfaceFailure::ApStartFailure { .. })))
2053 );
2054
2055 assert_matches!(exec.run_until_stalled(&mut start_receiver), Poll::Ready(Err(_)));
2057
2058 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2060 assert_matches!(
2061 poll_sme_req(&mut exec, &mut sme_fut),
2062 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
2063 responder
2064 .send(fidl_sme::StopApResultCode::Success)
2065 .expect("could not send AP stop response");
2066 }
2067 );
2068
2069 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2071 assert_matches!(
2072 poll_sme_req(&mut exec, &mut sme_fut),
2073 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config, responder: _ }) => {
2074 assert_eq!(config.ssid, requested_id.ssid);
2075 }
2076 );
2077 }
2078
2079 #[fuchsia::test]
2080 fn test_exit_after_start_failure() {
2081 let mut exec = fasync::TestExecutor::new();
2082 let mut test_values = test_setup();
2083
2084 let (start_sender, _) = oneshot::channel();
2085 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
2086 let req = ApConfig {
2087 id: create_network_id(),
2088 credential: vec![],
2089 radio_config,
2090 mode: types::ConnectivityMode::Unrestricted,
2091 band: types::OperatingBand::Any,
2092 };
2093
2094 let (exit_sender, mut exit_receiver) = oneshot::channel();
2096 test_values
2097 .ap_req_sender
2098 .try_send(ManualRequest::Exit(exit_sender))
2099 .expect("failed to request AP stop");
2100
2101 let fut = starting_state(test_values.deps, req, AP_START_MAX_RETRIES, Some(start_sender));
2103 let fut = run_state_machine(fut);
2104 let mut fut = pin!(fut);
2105
2106 let sme_fut = test_values.sme_req_stream.into_future();
2108 let mut sme_fut = pin!(sme_fut);
2109
2110 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2112 assert_matches!(
2113 poll_sme_req(&mut exec, &mut sme_fut),
2114 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
2115 responder
2116 .send(fidl_sme::StopApResultCode::Success)
2117 .expect("could not send AP stop response");
2118 }
2119 );
2120
2121 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2123 assert_matches!(
2124 test_values.update_receiver.try_next(),
2125 Ok(Some(listener::Message::NotifyListeners(_)))
2126 );
2127
2128 assert_matches!(
2130 test_values.update_receiver.try_next(),
2131 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
2132 let update = updates.access_points.pop().expect("no new updates available.");
2133 assert_eq!(update.state, types::OperatingState::Starting);
2134 });
2135
2136 assert_matches!(
2138 poll_sme_req(&mut exec, &mut sme_fut),
2139 Poll::Ready(fidl_sme::ApSmeRequest::Start{ config: _, responder }) => {
2140 responder
2141 .send(fidl_sme::StartApResultCode::TimedOut)
2142 .expect("could not send AP stop response");
2143 }
2144 );
2145
2146 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
2150 assert_matches!(exec.run_until_stalled(&mut exit_receiver), Poll::Ready(Ok(())));
2151
2152 assert_matches!(
2154 test_values.telemetry_receiver.try_next(),
2155 Ok(Some(TelemetryEvent::StartApResult(Err(()))))
2156 );
2157
2158 assert_matches!(
2160 test_values.defect_receiver.try_next(),
2161 Ok(Some(Defect::Iface(IfaceFailure::ApStartFailure { .. })))
2162 );
2163 }
2164
2165 #[fuchsia::test]
2166 fn test_manual_start_causes_starting_notification() {
2167 let mut exec = fasync::TestExecutor::new();
2168 let mut test_values = test_setup();
2169
2170 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
2172 let requested_config = ApConfig {
2173 id: create_network_id(),
2174 credential: vec![],
2175 radio_config,
2176 mode: types::ConnectivityMode::Unrestricted,
2177 band: types::OperatingBand::Any,
2178 };
2179
2180 let (start_response_sender, _) = oneshot::channel();
2181 let manual_request = ManualRequest::Start((requested_config, start_response_sender));
2182
2183 let fut = perform_manual_request(test_values.deps, Some(manual_request));
2184 let fut = run_state_machine(async move { fut });
2185 let mut fut = pin!(fut);
2186 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2187
2188 let sme_fut = test_values.sme_req_stream.into_future();
2190 let mut sme_fut = pin!(sme_fut);
2191
2192 assert_matches!(
2193 poll_sme_req(&mut exec, &mut sme_fut),
2194 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
2195 responder
2196 .send(fidl_sme::StopApResultCode::Success)
2197 .expect("could not send SME stop response");
2198 }
2199 );
2200
2201 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2204 assert_matches!(
2205 test_values.update_receiver.try_next(),
2206 Ok(Some(listener::Message::NotifyListeners(updates))) => {
2207 assert!(updates.access_points.is_empty());
2208 });
2209
2210 assert_matches!(
2211 test_values.update_receiver.try_next(),
2212 Ok(Some(listener::Message::NotifyListeners(mut updates))) => {
2213 let update = updates.access_points.pop().expect("no new updates available.");
2214 assert_eq!(update.state, types::OperatingState::Starting);
2215 });
2216 }
2217
2218 #[fuchsia::test]
2219 fn test_serve_does_not_terminate_right_away() {
2220 let mut exec = fasync::TestExecutor::new();
2221 let test_values = test_setup();
2222 let sme_event_stream = test_values.deps.proxy.take_event_stream();
2223 let sme_fut = test_values.sme_req_stream.into_future();
2224 let mut sme_fut = pin!(sme_fut);
2225
2226 let update_sender = test_values.deps.state_tracker.inner.lock().sender.clone();
2227
2228 let fut = serve(
2229 0,
2230 test_values.deps.proxy,
2231 sme_event_stream,
2232 test_values.deps.req_stream,
2233 update_sender,
2234 test_values.deps.telemetry_sender,
2235 test_values.deps.defect_sender,
2236 test_values.deps.status_publisher,
2237 );
2238 let mut fut = pin!(fut);
2239
2240 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2242 assert_matches!(poll_sme_req(&mut exec, &mut sme_fut), Poll::Pending);
2243 }
2244
2245 #[fuchsia::test]
2246 fn test_no_notification_when_sme_fails_while_stopped() {
2247 let mut exec = fasync::TestExecutor::new();
2248 let test_values = test_setup();
2249 let sme_event_stream = test_values.deps.proxy.take_event_stream();
2250 let update_sender = test_values.deps.state_tracker.inner.lock().sender.clone();
2251
2252 test_values.deps.status_publisher.publish_status(Status::Starting);
2254
2255 let fut = serve(
2256 0,
2257 test_values.deps.proxy,
2258 sme_event_stream,
2259 test_values.deps.req_stream,
2260 update_sender,
2261 test_values.deps.telemetry_sender,
2262 test_values.deps.defect_sender,
2263 test_values.deps.status_publisher.clone(),
2264 );
2265 let mut fut = pin!(fut);
2266
2267 drop(test_values.sme_req_stream);
2269
2270 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
2272
2273 assert_matches!(
2275 exec.run_until_stalled(&mut test_values.update_receiver.into_future()),
2276 Poll::Pending
2277 );
2278
2279 assert_matches!(test_values.status_reader.read_status(), Ok(Status::Stopped));
2281 }
2282
2283 #[fuchsia::test]
2284 fn test_failure_notification_when_configured() {
2285 let mut exec = fasync::TestExecutor::new();
2286 let mut test_values = test_setup();
2287 let sme_event_stream = test_values.deps.proxy.take_event_stream();
2288 let mut sme_fut = Box::pin(test_values.sme_req_stream.into_future());
2289
2290 let update_sender = test_values.deps.state_tracker.inner.lock().sender.clone();
2291 let fut = serve(
2292 0,
2293 test_values.deps.proxy,
2294 sme_event_stream,
2295 test_values.deps.req_stream,
2296 update_sender,
2297 test_values.deps.telemetry_sender,
2298 test_values.deps.defect_sender,
2299 test_values.deps.status_publisher,
2300 );
2301 let mut fut = pin!(fut);
2302
2303 let mut ap = AccessPoint::new(test_values.ap_req_sender);
2305 let (sender, _receiver) = oneshot::channel();
2306 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
2307 let config = ApConfig {
2308 id: create_network_id(),
2309 credential: vec![],
2310 radio_config,
2311 mode: types::ConnectivityMode::Unrestricted,
2312 band: types::OperatingBand::Any,
2313 };
2314 ap.start(config, sender).expect("failed to make start request");
2315
2316 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2318 assert_matches!(
2319 poll_sme_req(&mut exec, &mut sme_fut),
2320 Poll::Ready(fidl_sme::ApSmeRequest::Stop{ responder }) => {
2321 responder.send(fidl_sme::StopApResultCode::Success).expect("could not send AP stop response");
2322 }
2323 );
2324
2325 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2326
2327 assert_matches!(
2330 test_values.update_receiver.try_next(),
2331 Ok(Some(listener::Message::NotifyListeners(update))) => {
2332 assert!(update.access_points.is_empty());
2333 }
2334 );
2335 assert_matches!(
2336 test_values.update_receiver.try_next(),
2337 Ok(Some(listener::Message::NotifyListeners(update))) => {
2338 assert_eq!(update.access_points.len(), 1);
2339 assert_eq!(update.access_points[0].state, types::OperatingState::Starting);
2340 }
2341 );
2342
2343 drop(sme_fut);
2345
2346 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
2348
2349 assert_matches!(
2351 test_values.update_receiver.try_next(),
2352 Ok(Some(listener::Message::NotifyListeners(update))) => {
2353 assert_eq!(update.access_points.len(), 1);
2354 assert_eq!(update.access_points[0].state, types::OperatingState::Failed);
2355 }
2356 );
2357 }
2358
2359 #[fuchsia::test]
2360 fn test_state_tracker_reset() {
2361 let _exec = fasync::TestExecutor::new();
2362 let (sender, mut receiver) = mpsc::unbounded();
2363
2364 let state = ApStateTracker::new(sender);
2366 {
2367 assert!(state.inner.lock().state.is_none());
2368 }
2369
2370 assert_matches!(receiver.try_next(), Err(_));
2372
2373 let new_state = ApStateUpdate::new(
2375 create_network_id(),
2376 types::OperatingState::Starting,
2377 types::ConnectivityMode::Unrestricted,
2378 types::OperatingBand::Any,
2379 );
2380 state.reset_state(new_state).expect("failed to reset state");
2381 assert_matches!(state.inner.lock().state.as_ref(), Some(ApStateUpdate {
2382 id: types::NetworkIdentifier {
2383 ssid,
2384 security_type: types::SecurityType::None,
2385 },
2386 state: types::OperatingState::Starting,
2387 mode: Some(types::ConnectivityMode::Unrestricted),
2388 band: Some(types::OperatingBand::Any),
2389 frequency: None,
2390 clients: None,
2391 }) => {
2392 let expected_ssid = types::Ssid::try_from("test_ssid").unwrap();
2393 assert_eq!(ssid, &expected_ssid);
2394 });
2395
2396 assert_matches!(
2398 receiver.try_next(),
2399 Ok(Some(listener::Message::NotifyListeners(ApStatesUpdate { access_points }))) => {
2400 assert_eq!(access_points.len(), 1);
2401
2402 let expected_id = types::NetworkIdentifier {
2403 ssid: types::Ssid::try_from("test_ssid").unwrap(),
2404 security_type: types::SecurityType::None,
2405 };
2406 assert_eq!(access_points[0].id, expected_id);
2407 assert_eq!(access_points[0].state, types::OperatingState::Starting);
2408 assert_eq!(access_points[0].mode, Some(types::ConnectivityMode::Unrestricted));
2409 assert_eq!(access_points[0].band, Some(types::OperatingBand::Any));
2410 assert_eq!(access_points[0].frequency, None);
2411 assert_eq!(access_points[0].clients, None);
2412 }
2413 );
2414 }
2415
2416 #[fuchsia::test]
2417 fn test_state_tracker_consume_sme_update() {
2418 let _exec = fasync::TestExecutor::new();
2419 let (sender, mut receiver) = mpsc::unbounded();
2420 let state = ApStateTracker::new(sender);
2421
2422 let new_state = ApStateUpdate::new(
2424 create_network_id(),
2425 types::OperatingState::Active,
2426 types::ConnectivityMode::Unrestricted,
2427 types::OperatingBand::Any,
2428 );
2429 state.reset_state(new_state).expect("failed to reset state");
2430
2431 assert_matches!(
2433 receiver.try_next(),
2434 Ok(Some(listener::Message::NotifyListeners(ApStatesUpdate { access_points }))
2435 ) => {
2436 assert_eq!(access_points.len(), 1);
2437
2438 let expected_id = types::NetworkIdentifier {
2439 ssid: types::Ssid::try_from("test_ssid").unwrap(),
2440 security_type: types::SecurityType::None,
2441 };
2442 assert_eq!(access_points[0].id, expected_id);
2443 assert_eq!(access_points[0].state, types::OperatingState::Active);
2444 assert_eq!(access_points[0].mode, Some(types::ConnectivityMode::Unrestricted));
2445 assert_eq!(access_points[0].band, Some(types::OperatingBand::Any));
2446 assert_eq!(access_points[0].frequency, None);
2447 assert_eq!(access_points[0].clients, None);
2448 });
2449
2450 let ap_info = fidl_sme::Ap {
2452 ssid: types::Ssid::try_from("test_ssid").unwrap().to_vec(),
2453 channel: 6,
2454 num_clients: 123,
2455 };
2456 state
2457 .consume_sme_status_update(Cbw::Cbw20, ap_info)
2458 .expect("failure while updating SME status");
2459
2460 assert_matches!(
2461 receiver.try_next(),
2462 Ok(Some(listener::Message::NotifyListeners(ApStatesUpdate { access_points }))
2463 ) => {
2464 assert_eq!(access_points.len(), 1);
2465
2466 let expected_id = types::NetworkIdentifier {
2467 ssid: types::Ssid::try_from("test_ssid").unwrap(),
2468 security_type: types::SecurityType::None,
2469 };
2470 assert_eq!(access_points[0].id, expected_id);
2471 assert_eq!(access_points[0].state, types::OperatingState::Active);
2472 assert_eq!(access_points[0].mode, Some(types::ConnectivityMode::Unrestricted));
2473 assert_eq!(access_points[0].band, Some(types::OperatingBand::Any));
2474 assert_eq!(access_points[0].frequency, Some(2437));
2475 assert_eq!(access_points[0].clients, Some(ConnectedClientInformation { count: 123 }));
2476 });
2477 }
2478
2479 #[fuchsia::test]
2480 fn test_state_tracker_update_operating_state() {
2481 let _exec = fasync::TestExecutor::new();
2482 let (sender, mut receiver) = mpsc::unbounded();
2483 let state = ApStateTracker::new(sender);
2484
2485 let new_state = ApStateUpdate::new(
2487 create_network_id(),
2488 types::OperatingState::Starting,
2489 types::ConnectivityMode::Unrestricted,
2490 types::OperatingBand::Any,
2491 );
2492 state.reset_state(new_state).expect("failed to reset state");
2493
2494 assert_matches!(
2496 receiver.try_next(),
2497 Ok(Some(listener::Message::NotifyListeners(ApStatesUpdate { access_points }))
2498 ) => {
2499 assert_eq!(access_points.len(), 1);
2500
2501 let expected_id = types::NetworkIdentifier {
2502 ssid: types::Ssid::try_from("test_ssid").unwrap(),
2503 security_type: types::SecurityType::None,
2504 };
2505 assert_eq!(access_points[0].id, expected_id);
2506 assert_eq!(access_points[0].state, types::OperatingState::Starting);
2507 assert_eq!(access_points[0].mode, Some(types::ConnectivityMode::Unrestricted));
2508 assert_eq!(access_points[0].band, Some(types::OperatingBand::Any));
2509 assert_eq!(access_points[0].frequency, None);
2510 assert_eq!(access_points[0].clients, None);
2511 });
2512
2513 state
2515 .update_operating_state(types::OperatingState::Starting)
2516 .expect("failed to send duplicate update.");
2517 assert_matches!(
2518 receiver.try_next(),
2519 Ok(Some(listener::Message::NotifyListeners(ApStatesUpdate { access_points }))
2520 ) => {
2521 assert_eq!(access_points.len(), 1);
2522
2523 let expected_id = types::NetworkIdentifier {
2524 ssid: types::Ssid::try_from("test_ssid").unwrap(),
2525 security_type: types::SecurityType::None,
2526 };
2527 assert_eq!(access_points[0].id, expected_id);
2528 assert_eq!(access_points[0].state, types::OperatingState::Starting);
2529 assert_eq!(access_points[0].mode, Some(types::ConnectivityMode::Unrestricted));
2530 assert_eq!(access_points[0].band, Some(types::OperatingBand::Any));
2531 assert_eq!(access_points[0].frequency, None);
2532 assert_eq!(access_points[0].clients, None);
2533 });
2534
2535 state
2537 .update_operating_state(types::OperatingState::Active)
2538 .expect("failed to send active update.");
2539 assert_matches!(
2540 receiver.try_next(),
2541 Ok(Some(listener::Message::NotifyListeners(ApStatesUpdate { access_points }))
2542 ) => {
2543 assert_eq!(access_points.len(), 1);
2544
2545 let expected_id = types::NetworkIdentifier {
2546 ssid: types::Ssid::try_from("test_ssid").unwrap(),
2547 security_type: types::SecurityType::None,
2548 };
2549 assert_eq!(access_points[0].id, expected_id);
2550 assert_eq!(access_points[0].state, types::OperatingState::Active);
2551 assert_eq!(access_points[0].mode, Some(types::ConnectivityMode::Unrestricted));
2552 assert_eq!(access_points[0].band, Some(types::OperatingBand::Any));
2553 assert_eq!(access_points[0].frequency, None);
2554 assert_eq!(access_points[0].clients, None);
2555 });
2556 }
2557
2558 #[fuchsia::test]
2559 fn test_state_tracker_set_stopped_state() {
2560 let _exec = fasync::TestExecutor::new();
2561 let (sender, mut receiver) = mpsc::unbounded();
2562 let state = ApStateTracker::new(sender);
2563
2564 {
2566 let new_state = ApStateUpdate::new(
2567 create_network_id(),
2568 types::OperatingState::Active,
2569 types::ConnectivityMode::Unrestricted,
2570 types::OperatingBand::Any,
2571 );
2572 state.inner.lock().state = Some(new_state);
2573 }
2574
2575 state.set_stopped_state().expect("failed to send stopped notification");
2578 {
2579 assert!(state.inner.lock().state.is_none());
2580 }
2581
2582 assert_matches!(
2584 receiver.try_next(),
2585 Ok(Some(listener::Message::NotifyListeners(ApStatesUpdate { access_points }))
2586 ) => {
2587 assert!(access_points.is_empty());
2588 });
2589 }
2590
2591 #[fuchsia::test]
2592 fn test_state_tracker_failure_modes() {
2593 let _exec = fasync::TestExecutor::new();
2594 let (sender, receiver) = mpsc::unbounded();
2595 let state = ApStateTracker::new(sender);
2596 {
2597 let new_state = ApStateUpdate::new(
2598 create_network_id(),
2599 types::OperatingState::Active,
2600 types::ConnectivityMode::Unrestricted,
2601 types::OperatingBand::Any,
2602 );
2603 state.inner.lock().state = Some(new_state);
2604 }
2605
2606 drop(receiver);
2610
2611 let _ = state
2612 .update_operating_state(types::OperatingState::Failed)
2613 .expect_err("unexpectedly able to set operating state");
2614 let _ = state
2615 .consume_sme_status_update(
2616 Cbw::Cbw20,
2617 fidl_sme::Ap {
2618 ssid: types::Ssid::try_from("test_ssid").unwrap().to_vec(),
2619 channel: 6,
2620 num_clients: 123,
2621 },
2622 )
2623 .expect_err("unexpectedly able to update SME status");
2624 let _ = state.set_stopped_state().expect_err("unexpectedly able to set stopped state");
2625 }
2626
2627 #[fuchsia::test]
2628 fn test_state_when_stopping() {
2629 let mut exec = fasync::TestExecutor::new();
2630 let test_values = test_setup();
2631
2632 let (stop_sender, _) = oneshot::channel();
2634 let fut = stopping_state(test_values.deps, stop_sender);
2635 let fut = run_state_machine(fut);
2636 let mut fut = pin!(fut);
2637 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2638
2639 assert_matches!(test_values.status_reader.read_status(), Ok(Status::Stopping));
2641 }
2642
2643 #[fuchsia::test]
2644 fn test_state_when_stopped() {
2645 let mut exec = fasync::TestExecutor::new();
2646 let test_values = test_setup();
2647
2648 test_values.deps.status_publisher.publish_status(Status::Starting);
2650
2651 let fut = stopped_state(test_values.deps);
2653 let fut = run_state_machine(fut);
2654 let mut fut = pin!(fut);
2655 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2656
2657 assert_matches!(test_values.status_reader.read_status(), Ok(Status::Stopped));
2659 }
2660
2661 #[fuchsia::test]
2662 fn test_state_when_starting() {
2663 let mut exec = fasync::TestExecutor::new();
2664 let test_values = test_setup();
2665
2666 let (start_sender, _) = oneshot::channel();
2668 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
2669 let req = ApConfig {
2670 id: create_network_id(),
2671 credential: vec![],
2672 radio_config,
2673 mode: types::ConnectivityMode::Unrestricted,
2674 band: types::OperatingBand::Any,
2675 };
2676 let fut = starting_state(test_values.deps, req, 0, Some(start_sender));
2677 let fut = run_state_machine(fut);
2678 let mut fut = pin!(fut);
2679 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2680
2681 assert_matches!(test_values.status_reader.read_status(), Ok(Status::Starting));
2683 }
2684
2685 #[fuchsia::test]
2686 fn test_state_when_started() {
2687 let mut exec = fasync::TestExecutor::new();
2688 let test_values = test_setup();
2689
2690 let radio_config = RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6);
2692 let req = ApConfig {
2693 id: create_network_id(),
2694 credential: vec![],
2695 radio_config,
2696 mode: types::ConnectivityMode::Unrestricted,
2697 band: types::OperatingBand::Any,
2698 };
2699 let fut = started_state(test_values.deps, req);
2700 let fut = run_state_machine(fut);
2701 let mut fut = pin!(fut);
2702 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2703
2704 assert_matches!(test_values.status_reader.read_status(), Ok(Status::Started { .. }));
2706 }
2707
2708 struct InspectTestValues {
2709 exec: fasync::TestExecutor,
2710 inspector: fuchsia_inspect::Inspector,
2711 _node: fuchsia_inspect::Node,
2712 status_node: fuchsia_inspect_contrib::nodes::BoundedListNode,
2713 }
2714
2715 impl InspectTestValues {
2716 fn new(exec: fasync::TestExecutor) -> Self {
2717 let inspector = fuchsia_inspect::Inspector::default();
2718 let _node = inspector.root().create_child("node");
2719 let status_node =
2720 fuchsia_inspect_contrib::nodes::BoundedListNode::new(_node.clone_weak(), 1);
2721
2722 Self { exec, inspector, _node, status_node }
2723 }
2724
2725 fn log_status(&mut self, status: Status) -> fuchsia_inspect::reader::DiagnosticsHierarchy {
2726 fuchsia_inspect_contrib::inspect_log!(self.status_node, "status" => status);
2727 let read_fut = fuchsia_inspect::reader::read(&self.inspector);
2728 let mut read_fut = pin!(read_fut);
2729 assert_matches!(
2730 self.exec.run_until_stalled(&mut read_fut),
2731 Poll::Ready(Ok(hierarchy)) => hierarchy
2732 )
2733 }
2734 }
2735
2736 #[fuchsia::test]
2737 fn test_stopping_status_inspect_log() {
2738 let exec = fasync::TestExecutor::new_with_fake_time();
2739 let mut test_values = InspectTestValues::new(exec);
2740 let hierarchy = test_values.log_status(Status::Stopping);
2741 diagnostics_assertions::assert_data_tree!(
2742 @executor test_values.exec,
2743 hierarchy,
2744 root: contains {
2745 node: contains {
2746 "0": contains {
2747 status: "Stopping"
2748 }
2749 }
2750 });
2751 }
2752
2753 #[fuchsia::test]
2754 fn test_stopped_status_inspect_log() {
2755 let exec = fasync::TestExecutor::new_with_fake_time();
2756 let mut test_values = InspectTestValues::new(exec);
2757 let hierarchy = test_values.log_status(Status::Stopped);
2758 diagnostics_assertions::assert_data_tree!(
2759 @executor test_values.exec,
2760 hierarchy,
2761 root: contains {
2762 node: contains {
2763 "0": contains {
2764 status: "Stopped"
2765 }
2766 }
2767 });
2768 }
2769
2770 #[fuchsia::test]
2771 fn test_starting_status_inspect_log() {
2772 let exec = fasync::TestExecutor::new_with_fake_time();
2773 let mut test_values = InspectTestValues::new(exec);
2774 let hierarchy = test_values.log_status(Status::Starting);
2775 diagnostics_assertions::assert_data_tree!(
2776 @executor test_values.exec,
2777 hierarchy,
2778 root: contains {
2779 node: contains {
2780 "0": contains {
2781 status: "Starting"
2782 }
2783 }
2784 });
2785 }
2786
2787 #[fuchsia::test]
2788 fn test_started_status_inspect_log() {
2789 let exec = fasync::TestExecutor::new_with_fake_time();
2790 let mut test_values = InspectTestValues::new(exec);
2791 let hierarchy = test_values.log_status(Status::Started {
2792 band: types::OperatingBand::Any,
2793 channel: 1,
2794 mode: types::ConnectivityMode::Unrestricted,
2795 num_clients: 2,
2796 security_type: types::SecurityType::None,
2797 });
2798 diagnostics_assertions::assert_data_tree!(
2799 @executor test_values.exec,
2800 hierarchy,
2801 root: contains {
2802 node: contains {
2803 "0": contains {
2804 status: contains {
2805 Started: {
2806 band: "Any",
2807 channel: 1_u64,
2808 mode: "Unrestricted",
2809 num_clients: 2_u64,
2810 security_type: "None"
2811 }
2812 }
2813 }
2814 }
2815 });
2816 }
2817}