power_manager_integration_test_lib/mocks/
kernel_service.rs

1// Copyright 2023 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 fidl::endpoints::ServerEnd;
6use fidl_fuchsia_io::DirectoryMarker;
7use fuchsia_component::server::ServiceFs;
8use fuchsia_component_test::LocalComponentHandles;
9use futures::{StreamExt, TryStreamExt};
10use log::*;
11use std::sync::{Arc, Mutex};
12use {fidl_fuchsia_kernel as fkernel, fuchsia_async as fasync};
13
14/// Mocks the fuchsia.kernel.Stats service to be used in integration tests.
15pub struct MockKernelService {
16    cpu_stats: Mutex<fkernel::CpuStats>,
17}
18
19impl MockKernelService {
20    pub fn new() -> Arc<MockKernelService> {
21        Arc::new(Self {
22            cpu_stats: Mutex::new(fkernel::CpuStats {
23                actual_num_cpus: 0 as u64,
24                per_cpu_stats: Some(Vec::new()),
25            }),
26        })
27    }
28
29    pub async fn run(self: Arc<Self>, handles: LocalComponentHandles) -> Result<(), anyhow::Error> {
30        self.run_inner(handles.outgoing_dir).await
31    }
32
33    async fn run_inner(
34        self: Arc<Self>,
35        outgoing_dir: ServerEnd<DirectoryMarker>,
36    ) -> Result<(), anyhow::Error> {
37        let mut fs = ServiceFs::new();
38        fs.dir("svc").add_fidl_service(move |mut stream: fkernel::StatsRequestStream| {
39            let this = self.clone();
40            fasync::Task::local(async move {
41                while let Some(stats_request) = stream.try_next().await.unwrap() {
42                    match stats_request {
43                        fkernel::StatsRequest::GetCpuStats { responder } => {
44                            responder
45                                .send(&(*this.cpu_stats.lock().unwrap()))
46                                .unwrap_or_else(|e| info!("MockKernelService send error: {:?}", e));
47                        }
48                        _ => info!("MockKernelService: stats request not supported!"),
49                    }
50                }
51            })
52            .detach();
53        });
54
55        fs.serve_connection(outgoing_dir).unwrap();
56        fs.collect::<()>().await;
57
58        Ok(())
59    }
60
61    pub async fn set_cpu_stats(&self, cpu_stats: fkernel::CpuStats) {
62        let mut stats = self.cpu_stats.lock().unwrap();
63        *stats = cpu_stats;
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70    use fuchsia_component::client::connect_to_protocol_at_dir_svc;
71
72    #[fuchsia::test]
73    async fn test_set_cpu_stats() {
74        // Create and serve the mock service
75        let (dir, outgoing_dir) = fidl::endpoints::create_proxy::<DirectoryMarker>();
76        let mock = MockKernelService::new();
77        let _task = fasync::Task::local(mock.clone().run_inner(outgoing_dir));
78
79        // Connect to the mock server
80        let stats_client = connect_to_protocol_at_dir_svc::<fkernel::StatsMarker>(&dir).unwrap();
81
82        assert_eq!(
83            stats_client.get_cpu_stats().await.unwrap(),
84            fkernel::CpuStats { actual_num_cpus: 0 as u64, per_cpu_stats: Some(Vec::new()) }
85        );
86
87        let stats = fkernel::CpuStats {
88            actual_num_cpus: 0 as u64,
89            per_cpu_stats: Some(vec![fkernel::PerCpuStats {
90                cpu_number: Some(1 as u32),
91                flags: None,
92                idle_time: Some(100),
93                reschedules: None,
94                context_switches: None,
95                irq_preempts: None,
96                yields: None,
97                ints: None,
98                timer_ints: None,
99                timers: None,
100                page_faults: None,
101                exceptions: None,
102                syscalls: None,
103                reschedule_ipis: None,
104                generic_ipis: None,
105                ..Default::default()
106            }]),
107        };
108        mock.set_cpu_stats(stats).await;
109        assert_eq!(
110            stats_client.get_cpu_stats().await.unwrap().per_cpu_stats.unwrap()[0]
111                .idle_time
112                .unwrap(),
113            100
114        );
115    }
116}