1use std::cell::UnsafeCell;
19use std::ffi::c_void;
20use std::sync::{Arc, Mutex, RwLock};
21
22use crate::raw::{self, TEE_ObjectHandle, TEE_ObjectType, TEE_Result};
23
24static GLOBAL_OBJECT_MOCK: RwLock<Option<Box<dyn ObjectController + 'static>>> = RwLock::new(None);
25pub static SERIAL_TEST_LOCK: Mutex<()> = Mutex::new(());
26
27#[mockall::automock]
28pub trait ObjectController: Send + Sync {
30 fn TEE_CloseObject(&self, object: TEE_ObjectHandle);
32
33 fn TEE_AllocateTransientObject(
35 &self,
36 objectType: TEE_ObjectType,
37 maxObjectSize: u32,
38 object: *mut TEE_ObjectHandle,
39 ) -> TEE_Result;
40
41 fn TEE_OpenPersistentObject(
43 &self,
44 storageID: u32,
45 objectID: *const c_void,
46 objectIDLen: usize,
47 flags: u32,
48 object: *mut TEE_ObjectHandle,
49 ) -> TEE_Result;
50 fn TEE_CreatePersistentObject(
51 &self,
52 storageID: u32,
53 objectID: *const c_void,
54 objectIDLen: usize,
55 flags: u32,
56 attributes: TEE_ObjectHandle,
57 initialData: *const c_void,
58 initialDataLen: usize,
59 object: *mut TEE_ObjectHandle,
60 ) -> TEE_Result;
61 fn TEE_CloseAndDeletePersistentObject1(&self, object: TEE_ObjectHandle) -> TEE_Result;
62}
63
64pub fn set_global_object_mock(mock: impl ObjectController + 'static) {
65 let mut value = GLOBAL_OBJECT_MOCK.write().unwrap();
66 value.replace(Box::new(mock));
67}
68
69fn with_global_object_mock<R, F: FnOnce(&dyn ObjectController) -> R>(f: F) -> R {
70 let mock = GLOBAL_OBJECT_MOCK.read().unwrap();
71 let borrow = mock.as_ref().expect("Global Object Mock Not Set");
72 f(borrow.as_ref())
73}
74
75macro_rules! forward_to_mock {
76 ($fn_name:ident($($param:ident: $ty:ty),*) -> $ret:ty) => {
77 #[no_mangle]
78 fn $fn_name($($param: $ty),*) -> $ret {
79 with_global_object_mock(|mock: &dyn ObjectController| {
80 mock.$fn_name($($param),*)
81 })
82 }
83 };
84}
85
86forward_to_mock!(TEE_CloseObject(object: TEE_ObjectHandle) -> ());
87
88forward_to_mock!(TEE_AllocateTransientObject(
89 objectType: TEE_ObjectType,
90 maxObjectSize: u32,
91 object: *mut TEE_ObjectHandle
92) -> TEE_Result);
93
94forward_to_mock!(TEE_OpenPersistentObject(
95 storageID: u32,
96 objectID: *const c_void,
97 objectIDLen: usize,
98 flags: u32,
99 object: *mut TEE_ObjectHandle
100) -> TEE_Result);
101forward_to_mock!(TEE_CreatePersistentObject(
102 storageID: u32,
103 objectID: *const c_void,
104 objectIDLen: usize,
105 flags: u32,
106 attributes: TEE_ObjectHandle,
107 initialData: *const c_void,
108 initialDataLen: usize,
109 object: *mut TEE_ObjectHandle
110) -> TEE_Result);
111forward_to_mock!(TEE_CloseAndDeletePersistentObject1(
112 object: TEE_ObjectHandle
113) -> TEE_Result);
114
115type ValidTestHandle = Arc<UnsafeCell<raw::TEE_ObjectHandle>>;
116
117impl MockObjectController {
118 pub fn new_valid_test_handle_struct() -> raw::__TEE_ObjectHandle {
119 unsafe { core::mem::zeroed() }
120 }
121 pub fn new_valid_test_handle(handle: &mut raw::__TEE_ObjectHandle) -> ValidTestHandle {
122 Arc::new(UnsafeCell::new(handle))
123 }
124
125 pub fn expect_TEE_AllocateTransientObject_success_once(&mut self, handle: ValidTestHandle) {
126 self.expect_TEE_AllocateTransientObject()
127 .return_once_st(move |_, _, obj| {
128 unsafe {
129 *obj = *handle.get();
130 }
131 raw::TEE_SUCCESS
132 });
133 }
134 pub fn expect_TEE_AllocateTransientObject_fail_once(&mut self, code: raw::TEE_Result) {
135 self.expect_TEE_AllocateTransientObject()
136 .return_once_st(move |_, _, _| code);
137 }
138
139 pub fn expect_TEE_CreatePersistentObject_success_once(&mut self, handle: ValidTestHandle) {
140 self.expect_TEE_CreatePersistentObject()
141 .return_once_st(move |_, _, _, _, _, _, _, obj| {
142 unsafe {
143 *obj = *handle.get();
144 }
145 raw::TEE_SUCCESS
146 });
147 }
148 pub fn expect_TEE_CreatePersistentObject_fail_once(&mut self, code: raw::TEE_Result) {
149 self.expect_TEE_CreatePersistentObject()
150 .return_once_st(move |_, _, _, _, _, _, _, _| code);
151 }
152
153 pub fn expect_TEE_OpenPersistentObject_success_once(&mut self, handle: ValidTestHandle) {
154 self.expect_TEE_OpenPersistentObject()
155 .return_once_st(move |_, _, _, _, obj| {
156 unsafe {
157 *obj = *handle.get();
158 }
159 raw::TEE_SUCCESS
160 });
161 }
162 pub fn expect_TEE_OpenPersistentObject_fail_once(&mut self, code: raw::TEE_Result) {
163 self.expect_TEE_OpenPersistentObject()
164 .return_once_st(move |_, _, _, _, _| code);
165 }
166
167 pub fn expect_TEE_CloseAndDeletePersistentObject1_success_once(
168 &mut self,
169 exp_handle: ValidTestHandle,
170 ) {
171 self.expect_TEE_CloseAndDeletePersistentObject1()
172 .return_once_st(move |obj| {
173 assert_eq!(obj, unsafe { *exp_handle.get() });
174 raw::TEE_SUCCESS
175 });
176 }
177 pub fn expect_TEE_CloseAndDeletePersistentObject1_fail_once(&mut self, code: raw::TEE_Result) {
178 self.expect_TEE_CloseAndDeletePersistentObject1()
179 .return_once_st(move |_| code);
180 }
181
182 pub fn expect_TEE_CloseObject_once(&mut self, exp_handle: ValidTestHandle) {
183 self.expect_TEE_CloseObject().return_once_st(move |obj| {
184 assert_eq!(obj, unsafe { *exp_handle.get() });
185 });
186 }
187}
188
189#[cfg(test)]
190mod test {
191 use super::*;
192 use crate::raw;
193
194 #[test]
195 fn test_new_handle() {
196 let mut handle_struct1 = MockObjectController::new_valid_test_handle_struct();
197 let mut handle_struct2 = MockObjectController::new_valid_test_handle_struct();
198
199 let handle1 = MockObjectController::new_valid_test_handle(&mut handle_struct1);
200 let handle2 = MockObjectController::new_valid_test_handle(&mut handle_struct2);
201
202 assert_ne!(unsafe { *handle1.get() }, unsafe { *handle2.get() });
203
204 let handle3: ValidTestHandle = Arc::new(UnsafeCell::new(core::ptr::null_mut()));
205 let handle4: ValidTestHandle = Arc::new(UnsafeCell::new(core::ptr::null_mut()));
206 assert_eq!(unsafe { *handle3.get() }, unsafe { *handle4.get() });
207 }
208
209 #[test]
210 fn test_mock_usage() {
211 let mut handle_struct = MockObjectController::new_valid_test_handle_struct();
212 let handle = MockObjectController::new_valid_test_handle(&mut handle_struct);
213 let mut mock = MockObjectController::new();
214
215 mock.expect_TEE_OpenPersistentObject_success_once(handle.clone());
216 mock.expect_TEE_CloseAndDeletePersistentObject1_success_once(handle.clone());
217 mock.expect_TEE_CloseObject_once(handle.clone());
218
219 set_global_object_mock(mock);
220
221 let mut handle = core::ptr::null_mut();
222 let result =
223 unsafe { raw::TEE_OpenPersistentObject(0, core::ptr::null(), 0, 0, &mut handle) };
224 assert_eq!(result, raw::TEE_SUCCESS);
225
226 let result = unsafe { raw::TEE_CloseAndDeletePersistentObject1(handle) };
227 assert_eq!(result, raw::TEE_SUCCESS);
228
229 unsafe { raw::TEE_CloseObject(handle) };
230 }
231}