From d7d54fb843035ea14b7ad8b68e30ae5bc6aa485d Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 14 Apr 2022 11:40:33 -0700 Subject: uwb(uci-rust): Reorganize unit test codebase i. Move all Mocks to separate files. ii. Add #cfg(tests) or #cfg(tests, fuzzing) for all mocks. Bug: 229275354 Test: make uwb_uci_rust_fuzzer libuwb_uci_rust_tests Change-Id: Id6bc6631d034112a7f0aa603b120184a01da046d --- src/fuzz/fuzzer.rs | 4 +- src/rust/adaptation/mock_adaptation.rs | 291 +++++++++++++++++ src/rust/adaptation/mock_hal.rs | 213 +++++++++++++ src/rust/adaptation/mod.rs | 452 +-------------------------- src/rust/event_manager/mock_event_manager.rs | 223 +++++++++++++ src/rust/event_manager/mod.rs | 202 +----------- src/rust/uci/mock_uci_logger.rs | 47 +++ src/rust/uci/mod.rs | 7 +- src/rust/uci/uci_logger.rs | 22 -- src/rust/uwb_core/src/uci/mock_uci_hal.rs | 1 - 10 files changed, 790 insertions(+), 672 deletions(-) create mode 100644 src/rust/adaptation/mock_adaptation.rs create mode 100644 src/rust/adaptation/mock_hal.rs create mode 100644 src/rust/event_manager/mock_event_manager.rs create mode 100644 src/rust/uci/mock_uci_logger.rs diff --git a/src/fuzz/fuzzer.rs b/src/fuzz/fuzzer.rs index a34b560..e96a010 100644 --- a/src/fuzz/fuzzer.rs +++ b/src/fuzz/fuzzer.rs @@ -18,9 +18,9 @@ use uwb_uci_packets::{ SessionType, SessionUpdateControllerMulticastListRspBuilder, StatusCode, UciCommandPacket, UciPacketChild, UciPacketPacket, UciVendor_9_ResponseBuilder, }; -use uwb_uci_rust::adaptation::MockUwbAdaptation; +use uwb_uci_rust::adaptation::mock_adaptation::MockUwbAdaptation; use uwb_uci_rust::error::UwbErr; -use uwb_uci_rust::event_manager::MockEventManager; +use uwb_uci_rust::event_manager::mock_event_manager::MockEventManager; use uwb_uci_rust::uci::{ uci_hmsgs, uci_hrcv, Dispatcher, DispatcherImpl, HalCallback, JNICommand, SyncUwbAdaptation, }; diff --git a/src/rust/adaptation/mock_adaptation.rs b/src/rust/adaptation/mock_adaptation.rs new file mode 100644 index 0000000..53bee81 --- /dev/null +++ b/src/rust/adaptation/mock_adaptation.rs @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! MockUwbAdaptation + +use crate::adaptation::UwbAdaptation; +use crate::error::UwbErr; +use crate::uci::uci_hrcv; +use crate::uci::HalCallback; +use android_hardware_uwb::aidl::android::hardware::uwb::{ + UwbEvent::UwbEvent, UwbStatus::UwbStatus, +}; +use async_trait::async_trait; +use log::warn; +use std::collections::VecDeque; +use std::sync::Mutex as StdMutex; +use tokio::sync::mpsc; +use uwb_uci_packets::{Packet, UciCommandPacket}; + +type Result = std::result::Result; + +#[cfg(any(test, fuzzing))] +enum ExpectedCall { + Finalize { + expected_exit_status: bool, + }, + HalOpen { + out: Result<()>, + }, + HalClose { + out: Result<()>, + }, + CoreInitialization { + out: Result<()>, + }, + SessionInitialization { + expected_session_id: i32, + out: Result<()>, + }, + SendUciMessage { + expected_cmd: UciCommandPacket, + rsp: Option, + notf: Option, + out: Result<()>, + }, +} + +#[cfg(any(test, fuzzing))] +pub struct MockUwbAdaptation { + rsp_sender: mpsc::UnboundedSender, + expected_calls: StdMutex>, +} + +#[cfg(any(test, fuzzing))] +impl MockUwbAdaptation { + pub fn new(rsp_sender: mpsc::UnboundedSender) -> Self { + Self { rsp_sender, expected_calls: StdMutex::new(VecDeque::new()) } + } + + pub fn expect_finalize(&self, expected_exit_status: bool) { + self.expected_calls + .lock() + .unwrap() + .push_back(ExpectedCall::Finalize { expected_exit_status }); + } + pub fn expect_hal_open(&self, out: Result<()>) { + self.expected_calls.lock().unwrap().push_back(ExpectedCall::HalOpen { out }); + } + pub fn expect_hal_close(&self, out: Result<()>) { + self.expected_calls.lock().unwrap().push_back(ExpectedCall::HalClose { out }); + } + pub fn expect_core_initialization(&self, out: Result<()>) { + self.expected_calls.lock().unwrap().push_back(ExpectedCall::CoreInitialization { out }); + } + pub fn expect_session_initialization(&self, expected_session_id: i32, out: Result<()>) { + self.expected_calls + .lock() + .unwrap() + .push_back(ExpectedCall::SessionInitialization { expected_session_id, out }); + } + pub fn expect_send_uci_message( + &self, + expected_cmd: UciCommandPacket, + rsp: Option, + notf: Option, + out: Result<()>, + ) { + self.expected_calls.lock().unwrap().push_back(ExpectedCall::SendUciMessage { + expected_cmd, + rsp, + notf, + out, + }); + } + + pub fn clear_expected_calls(&self) { + self.expected_calls.lock().unwrap().clear(); + } + + async fn send_hal_event(&self, event: UwbEvent, event_status: UwbStatus) { + self.rsp_sender.send(HalCallback::Event { event, event_status }).unwrap(); + } + + async fn send_uci_response(&self, rsp: uci_hrcv::UciResponse) { + self.rsp_sender.send(HalCallback::UciRsp(rsp)).unwrap(); + } + + async fn send_uci_notification(&self, ntf: uci_hrcv::UciNotification) { + self.rsp_sender.send(HalCallback::UciNtf(ntf)).unwrap(); + } +} + +#[cfg(any(test, fuzzing))] +impl Drop for MockUwbAdaptation { + fn drop(&mut self) { + assert!(self.expected_calls.lock().unwrap().is_empty()); + } +} + +#[cfg(any(test, fuzzing))] +#[async_trait] +impl UwbAdaptation for MockUwbAdaptation { + async fn finalize(&mut self, exit_status: bool) { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::Finalize { expected_exit_status }) + if expected_exit_status == exit_status => + { + return; + } + Some(call) => { + expected_calls.push_front(call); + } + None => {} + } + warn!("unpected finalize() called"); + } + + async fn hal_open(&self) -> Result<()> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::HalOpen { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some(out) => { + let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED }; + self.send_hal_event(UwbEvent::OPEN_CPLT, status).await; + out + } + None => { + warn!("unpected hal_open() called"); + Err(UwbErr::Undefined) + } + } + } + + async fn hal_close(&self) -> Result<()> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::HalClose { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some(out) => { + let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED }; + self.send_hal_event(UwbEvent::CLOSE_CPLT, status).await; + out + } + None => { + warn!("unpected hal_close() called"); + Err(UwbErr::Undefined) + } + } + } + + async fn core_initialization(&self) -> Result<()> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::CoreInitialization { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some(out) => { + let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED }; + self.send_hal_event(UwbEvent::POST_INIT_CPLT, status).await; + out + } + None => { + warn!("unpected core_initialization() called"); + Err(UwbErr::Undefined) + } + } + } + + async fn session_initialization(&self, session_id: i32) -> Result<()> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::SessionInitialization { expected_session_id, out }) + if expected_session_id == session_id => + { + Some(out) + } + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some(out) => out, + None => { + warn!("unpected session_initialization() called"); + Err(UwbErr::Undefined) + } + } + } + + async fn send_uci_message(&self, cmd: UciCommandPacket) -> Result<()> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::SendUciMessage { + expected_cmd, + rsp, + notf, + out, + // PDL generated packets do not implement PartialEq, so use the raw bytes for comparison. + }) if expected_cmd.clone().to_bytes() == cmd.to_bytes() => Some((rsp, notf, out)), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some((rsp, notf, out)) => { + if let Some(notf) = notf { + self.send_uci_notification(notf).await; + } + if let Some(rsp) = rsp { + self.send_uci_response(rsp).await; + } + out + } + None => { + warn!("unpected send_uci_message() called"); + Err(UwbErr::Undefined) + } + } + } +} diff --git a/src/rust/adaptation/mock_hal.rs b/src/rust/adaptation/mock_hal.rs new file mode 100644 index 0000000..dc3b5b2 --- /dev/null +++ b/src/rust/adaptation/mock_hal.rs @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! MockHal + +use android_hardware_uwb::aidl::android::hardware::uwb::{ + IUwbChip::IUwbChipAsync, IUwbClientCallback::IUwbClientCallback, +}; +use android_hardware_uwb::binder::{Result as BinderResult, Strong}; +use async_trait::async_trait; +use binder::{SpIBinder, StatusCode}; +use std::collections::VecDeque; +use std::sync::Mutex as StdMutex; + +#[cfg(test)] +enum ExpectedHalCall { + Open { out: BinderResult<()> }, + Close { out: BinderResult<()> }, + CoreInit { out: BinderResult<()> }, + SessionInit { expected_session_id: i32, out: BinderResult<()> }, + SendUciMessage { expected_data: Vec, out: BinderResult }, +} + +#[cfg(test)] +pub struct MockHal { + expected_calls: StdMutex>, +} + +#[cfg(test)] +impl MockHal { + pub fn new() -> Self { + Self { expected_calls: StdMutex::new(VecDeque::new()) } + } + #[allow(dead_code)] + pub fn expect_open(&self, out: BinderResult<()>) { + self.expected_calls.lock().unwrap().push_back(ExpectedHalCall::Open { out }); + } + #[allow(dead_code)] + pub fn expect_close(&self, out: BinderResult<()>) { + self.expected_calls.lock().unwrap().push_back(ExpectedHalCall::Close { out }); + } + #[allow(dead_code)] + pub fn expect_core_init(&self, out: BinderResult<()>) { + self.expected_calls.lock().unwrap().push_back(ExpectedHalCall::CoreInit { out }); + } + #[allow(dead_code)] + pub fn expect_session_init(&self, expected_session_id: i32, out: BinderResult<()>) { + self.expected_calls + .lock() + .unwrap() + .push_back(ExpectedHalCall::SessionInit { expected_session_id, out }); + } + pub fn expect_send_uci_message(&self, expected_data: Vec, out: BinderResult) { + self.expected_calls + .lock() + .unwrap() + .push_back(ExpectedHalCall::SendUciMessage { expected_data, out }); + } +} + +#[cfg(test)] +impl Drop for MockHal { + fn drop(&mut self) { + assert!(self.expected_calls.lock().unwrap().is_empty()); + } +} + +#[cfg(test)] +impl Default for MockHal { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +impl binder::Interface for MockHal {} + +#[cfg(test)] +impl binder::FromIBinder for MockHal { + fn try_from(_ibinder: SpIBinder) -> std::result::Result, binder::StatusCode> { + Err(binder::StatusCode::OK) + } +} + +#[cfg(test)] +#[async_trait] +impl IUwbChipAsync

for MockHal { + fn getName(&self) -> binder::BoxFuture> { + Box::pin(std::future::ready(Ok("default".into()))) + } + + fn open<'a>( + &'a self, + _cb: &'a binder::Strong, + ) -> binder::BoxFuture<'a, BinderResult<()>> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedHalCall::Open { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some(out) => Box::pin(std::future::ready(out)), + None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), + } + } + + fn close(&self) -> binder::BoxFuture> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedHalCall::Close { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some(out) => Box::pin(std::future::ready(out)), + None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), + } + } + + fn coreInit(&self) -> binder::BoxFuture> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedHalCall::CoreInit { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some(out) => Box::pin(std::future::ready(out)), + None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), + } + } + + fn sessionInit(&self, session_id: i32) -> binder::BoxFuture> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedHalCall::SessionInit { expected_session_id, out }) + if expected_session_id == session_id => + { + Some(out) + } + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + match expected_out { + Some(out) => Box::pin(std::future::ready(out)), + None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), + } + } + + fn getSupportedAndroidUciVersion(&self) -> binder::BoxFuture> { + Box::pin(std::future::ready(Ok(0))) + } + + fn sendUciMessage(&self, cmd: &[u8]) -> binder::BoxFuture> { + let expected_out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedHalCall::SendUciMessage { expected_data, out }) + if expected_data == cmd => + { + Some(out) + } + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + match expected_out { + Some(out) => Box::pin(std::future::ready(out)), + None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), + } + } +} diff --git a/src/rust/adaptation/mod.rs b/src/rust/adaptation/mod.rs index a97fa53..4478ebf 100644 --- a/src/rust/adaptation/mod.rs +++ b/src/rust/adaptation/mod.rs @@ -1,4 +1,4 @@ -//! Definition of UwbClientCallback +//! HAL interface. use crate::error::UwbErr; use crate::uci::uci_hrcv; @@ -19,9 +19,7 @@ use binder::IBinder; use binder_tokio::{Tokio, TokioRuntime}; use log::{error, warn}; use rustutils::system_properties; -use std::collections::VecDeque; use std::sync::Arc; -use std::sync::Mutex as StdMutex; use tokio::runtime::Handle; use tokio::sync::{mpsc, Mutex}; use uwb_uci_packets::{ @@ -197,283 +195,19 @@ impl UwbAdaptation for UwbAdaptationImpl { } } -enum ExpectedCall { - Finalize { - expected_exit_status: bool, - }, - HalOpen { - out: Result<()>, - }, - HalClose { - out: Result<()>, - }, - CoreInitialization { - out: Result<()>, - }, - SessionInitialization { - expected_session_id: i32, - out: Result<()>, - }, - SendUciMessage { - expected_cmd: UciCommandPacket, - rsp: Option, - notf: Option, - out: Result<()>, - }, -} - -pub struct MockUwbAdaptation { - rsp_sender: mpsc::UnboundedSender, - expected_calls: StdMutex>, -} - -impl MockUwbAdaptation { - pub fn new(rsp_sender: mpsc::UnboundedSender) -> Self { - Self { rsp_sender, expected_calls: StdMutex::new(VecDeque::new()) } - } - - #[allow(dead_code)] - pub fn expect_finalize(&self, expected_exit_status: bool) { - self.expected_calls - .lock() - .unwrap() - .push_back(ExpectedCall::Finalize { expected_exit_status }); - } - #[allow(dead_code)] - pub fn expect_hal_open(&self, out: Result<()>) { - self.expected_calls.lock().unwrap().push_back(ExpectedCall::HalOpen { out }); - } - #[allow(dead_code)] - pub fn expect_hal_close(&self, out: Result<()>) { - self.expected_calls.lock().unwrap().push_back(ExpectedCall::HalClose { out }); - } - #[allow(dead_code)] - pub fn expect_core_initialization(&self, out: Result<()>) { - self.expected_calls.lock().unwrap().push_back(ExpectedCall::CoreInitialization { out }); - } - #[allow(dead_code)] - pub fn expect_session_initialization(&self, expected_session_id: i32, out: Result<()>) { - self.expected_calls - .lock() - .unwrap() - .push_back(ExpectedCall::SessionInitialization { expected_session_id, out }); - } - #[allow(dead_code)] - pub fn expect_send_uci_message( - &self, - expected_cmd: UciCommandPacket, - rsp: Option, - notf: Option, - out: Result<()>, - ) { - self.expected_calls.lock().unwrap().push_back(ExpectedCall::SendUciMessage { - expected_cmd, - rsp, - notf, - out, - }); - } - - #[allow(dead_code)] - pub fn clear_expected_calls(&self) { - self.expected_calls.lock().unwrap().clear(); - } - - async fn send_hal_event(&self, event: UwbEvent, event_status: UwbStatus) { - self.rsp_sender.send(HalCallback::Event { event, event_status }).unwrap(); - } - - async fn send_uci_response(&self, rsp: uci_hrcv::UciResponse) { - self.rsp_sender.send(HalCallback::UciRsp(rsp)).unwrap(); - } - - async fn send_uci_notification(&self, ntf: uci_hrcv::UciNotification) { - self.rsp_sender.send(HalCallback::UciNtf(ntf)).unwrap(); - } -} - -impl Drop for MockUwbAdaptation { - fn drop(&mut self) { - assert!(self.expected_calls.lock().unwrap().is_empty()); - } -} - -#[async_trait] -impl UwbAdaptation for MockUwbAdaptation { - async fn finalize(&mut self, exit_status: bool) { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::Finalize { expected_exit_status }) - if expected_exit_status == exit_status => - { - return; - } - Some(call) => { - expected_calls.push_front(call); - } - None => {} - } - warn!("unpected finalize() called"); - } - - async fn hal_open(&self) -> Result<()> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::HalOpen { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some(out) => { - let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED }; - self.send_hal_event(UwbEvent::OPEN_CPLT, status).await; - out - } - None => { - warn!("unpected hal_open() called"); - Err(UwbErr::Undefined) - } - } - } - - async fn hal_close(&self) -> Result<()> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::HalClose { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some(out) => { - let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED }; - self.send_hal_event(UwbEvent::CLOSE_CPLT, status).await; - out - } - None => { - warn!("unpected hal_close() called"); - Err(UwbErr::Undefined) - } - } - } - - async fn core_initialization(&self) -> Result<()> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::CoreInitialization { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some(out) => { - let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED }; - self.send_hal_event(UwbEvent::POST_INIT_CPLT, status).await; - out - } - None => { - warn!("unpected core_initialization() called"); - Err(UwbErr::Undefined) - } - } - } - - async fn session_initialization(&self, session_id: i32) -> Result<()> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::SessionInitialization { expected_session_id, out }) - if expected_session_id == session_id => - { - Some(out) - } - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some(out) => out, - None => { - warn!("unpected session_initialization() called"); - Err(UwbErr::Undefined) - } - } - } - - async fn send_uci_message(&self, cmd: UciCommandPacket) -> Result<()> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::SendUciMessage { - expected_cmd, - rsp, - notf, - out, - // PDL generated packets do not implement PartialEq, so use the raw bytes for comparison. - }) if expected_cmd.clone().to_bytes() == cmd.to_bytes() => Some((rsp, notf, out)), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some((rsp, notf, out)) => { - if let Some(notf) = notf { - self.send_uci_notification(notf).await; - } - if let Some(rsp) = rsp { - self.send_uci_response(rsp).await; - } - out - } - None => { - warn!("unpected send_uci_message() called"); - Err(UwbErr::Undefined) - } - } - } -} +#[cfg(any(test, fuzzing))] +pub mod mock_adaptation; +#[cfg(test)] +mod mock_hal; #[cfg(test)] pub mod tests { use super::*; - use android_hardware_uwb::aidl::android::hardware::uwb::IUwbClientCallback::IUwbClientCallback; - use binder::{SpIBinder, StatusCode}; + use crate::adaptation::mock_hal::MockHal; + use crate::uci::mock_uci_logger::MockUciLogger; use bytes::Bytes; use uwb_uci_packets::*; - enum ExpectedHalCall { - Open { out: BinderResult<()> }, - Close { out: BinderResult<()> }, - CoreInit { out: BinderResult<()> }, - SessionInit { expected_session_id: i32, out: BinderResult<()> }, - SendUciMessage { expected_data: Vec, out: BinderResult }, - } - use crate::uci::uci_logger::MockUciLogger; - #[cfg(test)] fn create_uwb_client_callback( rsp_sender: mpsc::UnboundedSender, ) -> UwbClientCallback { @@ -481,178 +215,6 @@ pub mod tests { UwbClientCallback::new(rsp_sender, Arc::new(MockUciLogger::new())) } - pub struct MockHal { - expected_calls: StdMutex>, - } - - impl MockHal { - pub fn new() -> Self { - Self { expected_calls: StdMutex::new(VecDeque::new()) } - } - - #[allow(dead_code)] - pub fn expect_open(&self, out: BinderResult<()>) { - self.expected_calls.lock().unwrap().push_back(ExpectedHalCall::Open { out }); - } - #[allow(dead_code)] - pub fn expect_close(&self, out: BinderResult<()>) { - self.expected_calls.lock().unwrap().push_back(ExpectedHalCall::Close { out }); - } - #[allow(dead_code)] - pub fn expect_core_init(&self, out: BinderResult<()>) { - self.expected_calls.lock().unwrap().push_back(ExpectedHalCall::CoreInit { out }); - } - #[allow(dead_code)] - pub fn expect_session_init(&self, expected_session_id: i32, out: BinderResult<()>) { - self.expected_calls - .lock() - .unwrap() - .push_back(ExpectedHalCall::SessionInit { expected_session_id, out }); - } - #[allow(dead_code)] - pub fn expect_send_uci_message(&self, expected_data: Vec, out: BinderResult) { - self.expected_calls - .lock() - .unwrap() - .push_back(ExpectedHalCall::SendUciMessage { expected_data, out }); - } - } - - impl Drop for MockHal { - fn drop(&mut self) { - assert!(self.expected_calls.lock().unwrap().is_empty()); - } - } - impl Default for MockHal { - fn default() -> Self { - Self::new() - } - } - - impl binder::Interface for MockHal {} - - impl binder::FromIBinder for MockHal { - fn try_from(_ibinder: SpIBinder) -> std::result::Result, binder::StatusCode> { - Err(binder::StatusCode::OK) - } - } - - #[async_trait] - impl IUwbChipAsync

for MockHal { - fn getName(&self) -> binder::BoxFuture> { - Box::pin(std::future::ready(Ok("default".into()))) - } - - fn open<'a>( - &'a self, - _cb: &'a binder::Strong, - ) -> binder::BoxFuture<'a, BinderResult<()>> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedHalCall::Open { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some(out) => Box::pin(std::future::ready(out)), - None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), - } - } - - fn close(&self) -> binder::BoxFuture> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedHalCall::Close { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some(out) => Box::pin(std::future::ready(out)), - None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), - } - } - - fn coreInit(&self) -> binder::BoxFuture> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedHalCall::CoreInit { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some(out) => Box::pin(std::future::ready(out)), - None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), - } - } - - fn sessionInit(&self, session_id: i32) -> binder::BoxFuture> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedHalCall::SessionInit { expected_session_id, out }) - if expected_session_id == session_id => - { - Some(out) - } - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - match expected_out { - Some(out) => Box::pin(std::future::ready(out)), - None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), - } - } - - fn getSupportedAndroidUciVersion(&self) -> binder::BoxFuture> { - Box::pin(std::future::ready(Ok(0))) - } - - fn sendUciMessage(&self, cmd: &[u8]) -> binder::BoxFuture> { - let expected_out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedHalCall::SendUciMessage { expected_data, out }) - if expected_data == cmd => - { - Some(out) - } - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - match expected_out { - Some(out) => Box::pin(std::future::ready(out)), - None => Box::pin(std::future::ready(Err(StatusCode::UNKNOWN_ERROR.into()))), - } - } - } - fn setup_client_callback() -> (mpsc::UnboundedReceiver, UwbClientCallback) { // TODO: Remove this once we call it somewhere real. logger::init( diff --git a/src/rust/event_manager/mock_event_manager.rs b/src/rust/event_manager/mock_event_manager.rs new file mode 100644 index 0000000..2a3c2cc --- /dev/null +++ b/src/rust/event_manager/mock_event_manager.rs @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! MockEventManager + +use crate::event_manager::EventManager; +use jni::errors::{Error, JniError, Result}; +use log::warn; +use std::collections::VecDeque; +use std::sync::Mutex; +use uwb_uci_packets::{ + DeviceStatusNtfPacket, ExtendedMacTwoWayRangeDataNtfPacket, GenericErrorPacket, + SessionStatusNtfPacket, SessionUpdateControllerMulticastListNtfPacket, + ShortMacTwoWayRangeDataNtfPacket, UciNotificationPacket, +}; + +#[cfg(any(test, fuzzing))] +enum ExpectedCall { + DeviceStatus { out: Result<()> }, + CoreGenericError { out: Result<()> }, + SessionStatus { out: Result<()> }, + ShortRangeData { out: Result<()> }, + ExtendedRangeData { out: Result<()> }, + SessionUpdateControllerMulticastList { out: Result<()> }, + VendorUci { out: Result<()> }, +} + +#[cfg(any(test, fuzzing))] +#[derive(Default)] +pub struct MockEventManager { + expected_calls: Mutex>, +} + +#[cfg(any(test, fuzzing))] +impl MockEventManager { + pub fn new() -> Self { + Default::default() + } + + pub fn expect_device_status_notification_received(&mut self, out: Result<()>) { + self.add_expected_call(ExpectedCall::DeviceStatus { out }); + } + + pub fn expect_core_generic_error_notification_received(&mut self, out: Result<()>) { + self.add_expected_call(ExpectedCall::CoreGenericError { out }); + } + + pub fn expect_session_status_notification_received(&mut self, out: Result<()>) { + self.add_expected_call(ExpectedCall::SessionStatus { out }); + } + + pub fn expect_short_range_data_notification_received(&mut self, out: Result<()>) { + self.add_expected_call(ExpectedCall::ShortRangeData { out }); + } + + pub fn expect_extended_range_data_notification_received(&mut self, out: Result<()>) { + self.add_expected_call(ExpectedCall::ExtendedRangeData { out }); + } + + pub fn expect_session_update_controller_multicast_list_notification_received( + &mut self, + out: Result<()>, + ) { + self.add_expected_call(ExpectedCall::SessionUpdateControllerMulticastList { out }); + } + + pub fn expect_vendor_uci_notification_received(&mut self, out: Result<()>) { + self.add_expected_call(ExpectedCall::VendorUci { out }); + } + + fn add_expected_call(&mut self, call: ExpectedCall) { + self.expected_calls.lock().unwrap().push_back(call); + } + + fn unwrap_out(&self, out: Option>, method_name: &str) -> Result<()> { + out.unwrap_or_else(move || { + warn!("unpected {:?}() called", method_name); + Err(Error::JniCall(JniError::Unknown)) + }) + } +} + +#[cfg(any(test, fuzzing))] +impl Drop for MockEventManager { + fn drop(&mut self) { + assert!(self.expected_calls.lock().unwrap().is_empty()); + } +} +#[cfg(any(test, fuzzing))] +impl EventManager for MockEventManager { + fn device_status_notification_received(&self, _data: DeviceStatusNtfPacket) -> Result<()> { + let out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::DeviceStatus { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + self.unwrap_out(out, "device_status_notification_received") + } + + fn core_generic_error_notification_received(&self, _data: GenericErrorPacket) -> Result<()> { + let out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::CoreGenericError { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + self.unwrap_out(out, "core_generic_error_notification_received") + } + + fn session_status_notification_received(&self, _data: SessionStatusNtfPacket) -> Result<()> { + let out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::SessionStatus { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + self.unwrap_out(out, "session_status_notification_received") + } + + fn short_range_data_notification_received( + &self, + _data: ShortMacTwoWayRangeDataNtfPacket, + ) -> Result<()> { + let out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::ShortRangeData { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + self.unwrap_out(out, "short_range_data_notification_received") + } + fn extended_range_data_notification_received( + &self, + _data: ExtendedMacTwoWayRangeDataNtfPacket, + ) -> Result<()> { + let out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::ExtendedRangeData { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + self.unwrap_out(out, "extended_range_data_notification_received") + } + + fn session_update_controller_multicast_list_notification_received( + &self, + _data: SessionUpdateControllerMulticastListNtfPacket, + ) -> Result<()> { + let out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::SessionUpdateControllerMulticastList { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + self.unwrap_out(out, "session_update_controller_multicast_list_notification_received") + } + + fn vendor_uci_notification_received(&self, _data: UciNotificationPacket) -> Result<()> { + let out = { + let mut expected_calls = self.expected_calls.lock().unwrap(); + match expected_calls.pop_front() { + Some(ExpectedCall::VendorUci { out }) => Some(out), + Some(call) => { + expected_calls.push_front(call); + None + } + None => None, + } + }; + + self.unwrap_out(out, "vendor_uci_notification_received") + } +} diff --git a/src/rust/event_manager/mod.rs b/src/rust/event_manager/mod.rs index c8e5f65..90aaf67 100644 --- a/src/rust/event_manager/mod.rs +++ b/src/rust/event_manager/mod.rs @@ -712,203 +712,5 @@ impl EventManagerImpl { } } -use log::warn; -use std::collections::VecDeque; -use std::sync::Mutex; - -enum ExpectedCall { - DeviceStatus { out: Result<()> }, - CoreGenericError { out: Result<()> }, - SessionStatus { out: Result<()> }, - ShortRangeData { out: Result<()> }, - ExtendedRangeData { out: Result<()> }, - SessionUpdateControllerMulticastList { out: Result<()> }, - VendorUci { out: Result<()> }, -} - -#[derive(Default)] -pub struct MockEventManager { - expected_calls: Mutex>, -} - -impl MockEventManager { - pub fn new() -> Self { - Default::default() - } - - #[allow(dead_code)] - pub fn expect_device_status_notification_received(&mut self, out: Result<()>) { - self.add_expected_call(ExpectedCall::DeviceStatus { out }); - } - - #[allow(dead_code)] - pub fn expect_core_generic_error_notification_received(&mut self, out: Result<()>) { - self.add_expected_call(ExpectedCall::CoreGenericError { out }); - } - - #[allow(dead_code)] - pub fn expect_session_status_notification_received(&mut self, out: Result<()>) { - self.add_expected_call(ExpectedCall::SessionStatus { out }); - } - - #[allow(dead_code)] - pub fn expect_short_range_data_notification_received(&mut self, out: Result<()>) { - self.add_expected_call(ExpectedCall::ShortRangeData { out }); - } - - #[allow(dead_code)] - pub fn expect_extended_range_data_notification_received(&mut self, out: Result<()>) { - self.add_expected_call(ExpectedCall::ExtendedRangeData { out }); - } - - #[allow(dead_code)] - pub fn expect_session_update_controller_multicast_list_notification_received( - &mut self, - out: Result<()>, - ) { - self.add_expected_call(ExpectedCall::SessionUpdateControllerMulticastList { out }); - } - - #[allow(dead_code)] - pub fn expect_vendor_uci_notification_received(&mut self, out: Result<()>) { - self.add_expected_call(ExpectedCall::VendorUci { out }); - } - - fn add_expected_call(&mut self, call: ExpectedCall) { - self.expected_calls.lock().unwrap().push_back(call); - } - - fn unwrap_out(&self, out: Option>, method_name: &str) -> Result<()> { - out.unwrap_or_else(move || { - warn!("unpected {:?}() called", method_name); - Err(Error::JniCall(JniError::Unknown)) - }) - } -} - -impl Drop for MockEventManager { - fn drop(&mut self) { - assert!(self.expected_calls.lock().unwrap().is_empty()); - } -} -impl EventManager for MockEventManager { - fn device_status_notification_received(&self, _data: DeviceStatusNtfPacket) -> Result<()> { - let out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::DeviceStatus { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - self.unwrap_out(out, "device_status_notification_received") - } - - fn core_generic_error_notification_received(&self, _data: GenericErrorPacket) -> Result<()> { - let out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::CoreGenericError { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - self.unwrap_out(out, "core_generic_error_notification_received") - } - - fn session_status_notification_received(&self, _data: SessionStatusNtfPacket) -> Result<()> { - let out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::SessionStatus { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - self.unwrap_out(out, "session_status_notification_received") - } - - fn short_range_data_notification_received( - &self, - _data: ShortMacTwoWayRangeDataNtfPacket, - ) -> Result<()> { - let out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::ShortRangeData { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - self.unwrap_out(out, "short_range_data_notification_received") - } - fn extended_range_data_notification_received( - &self, - _data: ExtendedMacTwoWayRangeDataNtfPacket, - ) -> Result<()> { - let out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::ExtendedRangeData { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - self.unwrap_out(out, "extended_range_data_notification_received") - } - - fn session_update_controller_multicast_list_notification_received( - &self, - _data: SessionUpdateControllerMulticastListNtfPacket, - ) -> Result<()> { - let out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::SessionUpdateControllerMulticastList { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - self.unwrap_out(out, "session_update_controller_multicast_list_notification_received") - } - - fn vendor_uci_notification_received(&self, _data: UciNotificationPacket) -> Result<()> { - let out = { - let mut expected_calls = self.expected_calls.lock().unwrap(); - match expected_calls.pop_front() { - Some(ExpectedCall::VendorUci { out }) => Some(out), - Some(call) => { - expected_calls.push_front(call); - None - } - None => None, - } - }; - - self.unwrap_out(out, "vendor_uci_notification_received") - } -} +#[cfg(any(test, fuzzing))] +pub mod mock_event_manager; diff --git a/src/rust/uci/mock_uci_logger.rs b/src/rust/uci/mock_uci_logger.rs new file mode 100644 index 0000000..131d842 --- /dev/null +++ b/src/rust/uci/mock_uci_logger.rs @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +extern crate libc; + +use crate::uci::uci_logger::UciLogger; +use async_trait::async_trait; +use uwb_uci_packets::{UciCommandPacket, UciNotificationPacket, UciResponsePacket}; + +#[cfg(test)] +pub struct MockUciLogger {} + +#[cfg(test)] +impl MockUciLogger { + pub fn new() -> Self { + MockUciLogger {} + } +} + +#[cfg(test)] +impl Default for MockUciLogger { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +#[async_trait] +impl UciLogger for MockUciLogger { + async fn log_uci_command(&self, _cmd: UciCommandPacket) {} + async fn log_uci_response(&self, _rsp: UciResponsePacket) {} + async fn log_uci_notification(&self, _ntf: UciNotificationPacket) {} + async fn close_file(&self) {} +} diff --git a/src/rust/uci/mod.rs b/src/rust/uci/mod.rs index 120459d..29675c0 100644 --- a/src/rust/uci/mod.rs +++ b/src/rust/uci/mod.rs @@ -546,14 +546,17 @@ impl Dispatcher for DispatcherImpl { } } +#[cfg(test)] +pub mod mock_uci_logger; + #[cfg(test)] mod tests { use self::uci_hrcv::UciNotification; use self::uci_hrcv::UciResponse; use super::*; - use crate::adaptation::MockUwbAdaptation; - use crate::event_manager::MockEventManager; + use crate::adaptation::mock_adaptation::MockUwbAdaptation; + use crate::event_manager::mock_event_manager::MockEventManager; use android_hardware_uwb::aidl::android::hardware::uwb::{ UwbEvent::UwbEvent, UwbStatus::UwbStatus, }; diff --git a/src/rust/uci/uci_logger.rs b/src/rust/uci/uci_logger.rs index e4abdb9..d0af648 100644 --- a/src/rust/uci/uci_logger.rs +++ b/src/rust/uci/uci_logger.rs @@ -351,25 +351,3 @@ impl UciLogger for UciLoggerImpl { self.buf_file.lock().await.close_file().await; } } - -pub struct MockUciLogger {} - -impl MockUciLogger { - pub fn new() -> Self { - MockUciLogger {} - } -} - -impl Default for MockUciLogger { - fn default() -> Self { - Self::new() - } -} - -#[async_trait] -impl UciLogger for MockUciLogger { - async fn log_uci_command(&self, _cmd: UciCommandPacket) {} - async fn log_uci_response(&self, _rsp: UciResponsePacket) {} - async fn log_uci_notification(&self, _ntf: UciNotificationPacket) {} - async fn close_file(&self) {} -} diff --git a/src/rust/uwb_core/src/uci/mock_uci_hal.rs b/src/rust/uwb_core/src/uci/mock_uci_hal.rs index f1ff4f6..332d5d0 100644 --- a/src/rust/uwb_core/src/uci/mock_uci_hal.rs +++ b/src/rust/uwb_core/src/uci/mock_uci_hal.rs @@ -32,7 +32,6 @@ pub struct MockUciHal { expect_call_consumed: Arc, } -#[allow(dead_code)] impl MockUciHal { pub fn new() -> Self { Default::default() -- cgit v1.2.3