mock_space/
lib.rs

1// Copyright 2022 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 anyhow::{anyhow, Error};
6use fidl_fuchsia_space::ErrorCode;
7use fuchsia_async as fasync;
8use futures::prelude::*;
9use std::sync::Arc;
10
11type CallHook = Box<dyn Fn() -> Result<(), ErrorCode> + Send + Sync>;
12
13pub struct MockSpaceService {
14    call_hook: CallHook,
15}
16
17impl MockSpaceService {
18    pub fn new(call_hook: CallHook) -> Self {
19        Self { call_hook }
20    }
21
22    pub fn spawn_space_service(self: &Arc<Self>) -> fidl_fuchsia_space::ManagerProxy {
23        let (proxy, stream) =
24            fidl::endpoints::create_proxy_and_stream::<fidl_fuchsia_space::ManagerMarker>();
25
26        fasync::Task::spawn(
27            Arc::clone(self)
28                .run_space_service(stream)
29                .unwrap_or_else(|e| panic!("error running space service: {:#}", anyhow!(e))),
30        )
31        .detach();
32
33        proxy
34    }
35
36    pub async fn run_space_service(
37        self: Arc<Self>,
38        mut stream: fidl_fuchsia_space::ManagerRequestStream,
39    ) -> Result<(), Error> {
40        while let Some(event) = stream.try_next().await.expect("received request") {
41            let fidl_fuchsia_space::ManagerRequest::Gc { responder } = event;
42            responder.send((self.call_hook)())?;
43        }
44
45        Ok(())
46    }
47}
48#[cfg(test)]
49mod tests {
50    use super::*;
51    use std::sync::atomic::{AtomicU32, Ordering};
52
53    #[fasync::run_singlethreaded(test)]
54    async fn test_mock_space() {
55        let called = Arc::new(AtomicU32::new(0));
56        let called_clone = Arc::clone(&called);
57        let mock = Arc::new(MockSpaceService::new(Box::new(move || {
58            called_clone.fetch_add(1, Ordering::SeqCst);
59            Ok(())
60        })));
61        let proxy = mock.spawn_space_service();
62
63        assert_eq!(called.load(Ordering::SeqCst), 0);
64
65        let gc_result = proxy.gc().await.expect("made fidl call");
66        assert_eq!(gc_result, Ok(()));
67        assert_eq!(called.load(Ordering::SeqCst), 1);
68
69        let gc_result = proxy.gc().await.expect("made fidl call");
70        assert_eq!(gc_result, Ok(()));
71
72        let gc_result = proxy.gc().await.expect("made fidl call");
73        assert_eq!(gc_result, Ok(()));
74
75        assert_eq!(called.load(Ordering::SeqCst), 3);
76    }
77
78    #[fasync::run_singlethreaded(test)]
79    async fn test_mock_error() {
80        let called = Arc::new(AtomicU32::new(0));
81        let called_clone = Arc::clone(&called);
82        let mock = Arc::new(MockSpaceService::new(Box::new(move || {
83            called_clone.fetch_add(1, Ordering::SeqCst);
84            Err(ErrorCode::Internal)
85        })));
86        let proxy = mock.spawn_space_service();
87
88        let gc_result = proxy.gc().await.expect("made fidl call");
89        assert_eq!(gc_result, Err(ErrorCode::Internal));
90
91        assert_eq!(called.load(Ordering::SeqCst), 1);
92    }
93}