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