Skip to main content

bt_hfp/audio/
test.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::codec_id::CodecId;
6use crate::sco;
7use fuchsia_bluetooth::types::PeerId;
8use fuchsia_sync::Mutex;
9use futures::StreamExt;
10use futures::stream::BoxStream;
11use std::collections::{HashMap, HashSet};
12use std::sync::Arc;
13
14use super::{Control, ControlEvent, Error};
15
16struct TestControlInner {
17    started: HashSet<PeerId>,
18    connected: HashMap<PeerId, HashSet<CodecId>>,
19    connections: HashMap<PeerId, sco::Connection>,
20    event_sender: futures::channel::mpsc::Sender<ControlEvent>,
21}
22
23#[derive(Clone)]
24pub struct TestControl {
25    inner: Arc<Mutex<TestControlInner>>,
26}
27
28impl TestControl {
29    pub fn unexpected_stop(&self, id: PeerId, error: Error) {
30        let mut lock = self.inner.lock();
31        let _ = lock.started.remove(&id);
32        let _ = lock.connections.remove(&id);
33        let _ = lock.event_sender.try_send(ControlEvent::Stopped { id, error: Some(error) });
34    }
35
36    pub fn is_started(&self, id: PeerId) -> bool {
37        let lock = self.inner.lock();
38        lock.started.contains(&id) && lock.connections.contains_key(&id)
39    }
40
41    pub fn is_connected(&self, id: PeerId) -> bool {
42        let lock = self.inner.lock();
43        lock.connected.contains_key(&id)
44    }
45}
46
47impl Default for TestControl {
48    fn default() -> Self {
49        // Make a disconnected sender, we do not care about whether it succeeds.
50        let (event_sender, _) = futures::channel::mpsc::channel(0);
51        Self {
52            inner: Arc::new(Mutex::new(TestControlInner {
53                started: Default::default(),
54                connected: Default::default(),
55                connections: Default::default(),
56                event_sender,
57            })),
58        }
59    }
60}
61
62impl Control for TestControl {
63    fn start(
64        &mut self,
65        id: PeerId,
66        connection: sco::Connection,
67        _codec: CodecId,
68    ) -> Result<(), Error> {
69        let mut lock = self.inner.lock();
70        if !lock.started.insert(id) {
71            return Err(Error::AlreadyStarted);
72        }
73        let _ = lock.connections.insert(id, connection);
74        let _ = lock.event_sender.try_send(ControlEvent::Started { id });
75        Ok(())
76    }
77
78    fn stop(&mut self, id: PeerId) -> Result<(), Error> {
79        let mut lock = self.inner.lock();
80        if !lock.started.remove(&id) {
81            return Err(Error::NotStarted);
82        }
83        let _ = lock.connections.remove(&id);
84        let _ = lock.event_sender.try_send(ControlEvent::Stopped { id, error: None });
85        Ok(())
86    }
87
88    fn connect(&mut self, id: PeerId, supported_codecs: &[CodecId]) {
89        let mut lock = self.inner.lock();
90        let _ = lock.connected.insert(id, supported_codecs.iter().cloned().collect());
91    }
92
93    fn disconnect(&mut self, id: PeerId) {
94        let _ = self.stop(id);
95        let mut lock = self.inner.lock();
96        let _ = lock.connected.remove(&id);
97    }
98
99    fn take_events(&self) -> BoxStream<'static, ControlEvent> {
100        let mut lock = self.inner.lock();
101        // Replace the sender.
102        let (sender, receiver) = futures::channel::mpsc::channel(1);
103        lock.event_sender = sender;
104        receiver.boxed()
105    }
106
107    fn failed_request(&self, _request: ControlEvent, _error: Error) {
108        // Nothing to do here for the moment
109    }
110}