This is an automated email from the ASF dual-hosted git repository.

ivila pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/incubator-teaclave-trustzone-sdk.git

commit c14632cf86e5c0b695537dd4a5b56a7755f651a2
Author: ivila <390810...@qq.com>
AuthorDate: Wed Jul 9 11:45:26 2025 +0800

    optee-utee: add optee-utee-mock
    
    Introduce a mocking library to facilitate unit testing with `optee-utee`
    
    Signed-off-by: Zehui Chen <iv...@apache.org>
    Reviewed-by: Yuan Zhuang <yu...@apache.org>
    Reviewed-by: Zhaofeng Chen <z...@apache.org>
---
 optee-utee/Cargo.toml                       |   1 +
 optee-utee/{ => optee-utee-mock}/Cargo.toml |  29 +---
 optee-utee/optee-utee-mock/src/lib.rs       |  23 +++
 optee-utee/optee-utee-mock/src/object.rs    | 231 ++++++++++++++++++++++++++++
 4 files changed, 260 insertions(+), 24 deletions(-)

diff --git a/optee-utee/Cargo.toml b/optee-utee/Cargo.toml
index 9ca2413..67208a2 100644
--- a/optee-utee/Cargo.toml
+++ b/optee-utee/Cargo.toml
@@ -40,6 +40,7 @@ serde = { version = "1.0.215" }
 serde_json = { version = "1.0.133" }
 # disable linking when running unit tests
 optee-utee-sys = { version = "0.5.0", path = "optee-utee-sys", features = 
["no_link"] }
+optee-utee-mock = { version = "0.5.0", path = "optee-utee-mock" }
 
 [features]
 no_panic_handler = []
diff --git a/optee-utee/Cargo.toml b/optee-utee/optee-utee-mock/Cargo.toml
similarity index 58%
copy from optee-utee/Cargo.toml
copy to optee-utee/optee-utee-mock/Cargo.toml
index 9ca2413..4afb676 100644
--- a/optee-utee/Cargo.toml
+++ b/optee-utee/optee-utee-mock/Cargo.toml
@@ -16,34 +16,15 @@
 # under the License.
 
 [package]
-name = "optee-utee"
+name = "optee-utee-mock"
 version = "0.5.0"
 authors = ["Teaclave Contributors <d...@teaclave.apache.org>"]
 license = "Apache-2.0"
 repository = "https://github.com/apache/incubator-teaclave-trustzone-sdk.git";
-description = "TEE internal core API."
+description = "Mocking library for unittest with optee-utee."
 edition = "2018"
 
 [dependencies]
-optee-utee-sys = { version = "0.5.0", path = "optee-utee-sys" }
-optee-utee-macros = { version = "0.5.0", path = "macros" }
-bitflags = "1.0.4"
-uuid = { version = "0.8", default-features = false }
-hex = { version = "0.4", default-features = false, features = ["alloc"] }
-libc_alloc = "1.0.5"
-strum_macros = "0.26"
-
-[dev-dependencies]
-rand = "0.8.5"
-once_cell = "1.20.2"
-serde = { version = "1.0.215" }
-serde_json = { version = "1.0.133" }
-# disable linking when running unit tests
-optee-utee-sys = { version = "0.5.0", path = "optee-utee-sys", features = 
["no_link"] }
-
-[features]
-no_panic_handler = []
-
-[workspace]
-resolver = "2"
-members = ['systest']
+mockall = "0.13.1"
+once_cell = "1.21.3"
+optee-utee-sys = { version = "0.5.0", path = "../optee-utee-sys", features = 
["no_link"] }
diff --git a/optee-utee/optee-utee-mock/src/lib.rs 
b/optee-utee/optee-utee-mock/src/lib.rs
new file mode 100644
index 0000000..d429ecf
--- /dev/null
+++ b/optee-utee/optee-utee-mock/src/lib.rs
@@ -0,0 +1,23 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+#[allow(non_snake_case)]
+pub mod object;
+
+// re-export some dependencies;
+pub use mockall;
+pub use optee_utee_sys as raw;
diff --git a/optee-utee/optee-utee-mock/src/object.rs 
b/optee-utee/optee-utee-mock/src/object.rs
new file mode 100644
index 0000000..eeb6864
--- /dev/null
+++ b/optee-utee/optee-utee-mock/src/object.rs
@@ -0,0 +1,231 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+use std::cell::UnsafeCell;
+use std::ffi::c_void;
+use std::sync::{Arc, Mutex, RwLock};
+
+use crate::raw::{self, TEE_ObjectHandle, TEE_ObjectType, TEE_Result};
+
+static GLOBAL_OBJECT_MOCK: RwLock<Option<Box<dyn ObjectController + 'static>>> 
= RwLock::new(None);
+pub static SERIAL_TEST_LOCK: Mutex<()> = Mutex::new(());
+
+#[mockall::automock]
+// currently we just add functions that we need
+pub trait ObjectController: Send + Sync {
+    // Data and Key Storage API  - Generic Object Functions
+    fn TEE_CloseObject(&self, object: TEE_ObjectHandle);
+
+    /* Data and Key Storage API  - Transient Object Functions */
+    fn TEE_AllocateTransientObject(
+        &self,
+        objectType: TEE_ObjectType,
+        maxObjectSize: u32,
+        object: *mut TEE_ObjectHandle,
+    ) -> TEE_Result;
+
+    // Data and Key Storage API  - Persistent Object Functions
+    fn TEE_OpenPersistentObject(
+        &self,
+        storageID: u32,
+        objectID: *const c_void,
+        objectIDLen: usize,
+        flags: u32,
+        object: *mut TEE_ObjectHandle,
+    ) -> TEE_Result;
+    fn TEE_CreatePersistentObject(
+        &self,
+        storageID: u32,
+        objectID: *const c_void,
+        objectIDLen: usize,
+        flags: u32,
+        attributes: TEE_ObjectHandle,
+        initialData: *const c_void,
+        initialDataLen: usize,
+        object: *mut TEE_ObjectHandle,
+    ) -> TEE_Result;
+    fn TEE_CloseAndDeletePersistentObject1(&self, object: TEE_ObjectHandle) -> 
TEE_Result;
+}
+
+pub fn set_global_object_mock(mock: impl ObjectController + 'static) {
+    let mut value = GLOBAL_OBJECT_MOCK.write().unwrap();
+    value.replace(Box::new(mock));
+}
+
+fn with_global_object_mock<R, F: FnOnce(&dyn ObjectController) -> R>(f: F) -> 
R {
+    let mock = GLOBAL_OBJECT_MOCK.read().unwrap();
+    let borrow = mock.as_ref().expect("Global Object Mock Not Set");
+    f(borrow.as_ref())
+}
+
+macro_rules! forward_to_mock {
+    ($fn_name:ident($($param:ident: $ty:ty),*) -> $ret:ty) => {
+        #[no_mangle]
+        fn $fn_name($($param: $ty),*) -> $ret {
+            with_global_object_mock(|mock: &dyn ObjectController| {
+                mock.$fn_name($($param),*)
+            })
+        }
+    };
+}
+
+forward_to_mock!(TEE_CloseObject(object: TEE_ObjectHandle) -> ());
+
+forward_to_mock!(TEE_AllocateTransientObject(
+    objectType: TEE_ObjectType,
+    maxObjectSize: u32,
+    object: *mut TEE_ObjectHandle
+) -> TEE_Result);
+
+forward_to_mock!(TEE_OpenPersistentObject(
+    storageID: u32,
+    objectID: *const c_void,
+    objectIDLen: usize,
+    flags: u32,
+    object: *mut TEE_ObjectHandle
+) -> TEE_Result);
+forward_to_mock!(TEE_CreatePersistentObject(
+    storageID: u32,
+    objectID: *const c_void,
+    objectIDLen: usize,
+    flags: u32,
+    attributes: TEE_ObjectHandle,
+    initialData: *const c_void,
+    initialDataLen: usize,
+    object: *mut TEE_ObjectHandle
+) -> TEE_Result);
+forward_to_mock!(TEE_CloseAndDeletePersistentObject1(
+    object: TEE_ObjectHandle
+) -> TEE_Result);
+
+type ValidTestHandle = Arc<UnsafeCell<raw::TEE_ObjectHandle>>;
+
+impl MockObjectController {
+    pub fn new_valid_test_handle_struct() -> raw::__TEE_ObjectHandle {
+        unsafe { core::mem::zeroed() }
+    }
+    pub fn new_valid_test_handle(handle: &mut raw::__TEE_ObjectHandle) -> 
ValidTestHandle {
+        Arc::new(UnsafeCell::new(handle))
+    }
+
+    pub fn expect_TEE_AllocateTransientObject_success_once(&mut self, handle: 
ValidTestHandle) {
+        self.expect_TEE_AllocateTransientObject()
+            .return_once_st(move |_, _, obj| {
+                unsafe {
+                    *obj = *handle.get();
+                }
+                raw::TEE_SUCCESS
+            });
+    }
+    pub fn expect_TEE_AllocateTransientObject_fail_once(&mut self, code: 
raw::TEE_Result) {
+        self.expect_TEE_AllocateTransientObject()
+            .return_once_st(move |_, _, _| code);
+    }
+
+    pub fn expect_TEE_CreatePersistentObject_success_once(&mut self, handle: 
ValidTestHandle) {
+        self.expect_TEE_CreatePersistentObject()
+            .return_once_st(move |_, _, _, _, _, _, _, obj| {
+                unsafe {
+                    *obj = *handle.get();
+                }
+                raw::TEE_SUCCESS
+            });
+    }
+    pub fn expect_TEE_CreatePersistentObject_fail_once(&mut self, code: 
raw::TEE_Result) {
+        self.expect_TEE_CreatePersistentObject()
+            .return_once_st(move |_, _, _, _, _, _, _, _| code);
+    }
+
+    pub fn expect_TEE_OpenPersistentObject_success_once(&mut self, handle: 
ValidTestHandle) {
+        self.expect_TEE_OpenPersistentObject()
+            .return_once_st(move |_, _, _, _, obj| {
+                unsafe {
+                    *obj = *handle.get();
+                }
+                raw::TEE_SUCCESS
+            });
+    }
+    pub fn expect_TEE_OpenPersistentObject_fail_once(&mut self, code: 
raw::TEE_Result) {
+        self.expect_TEE_OpenPersistentObject()
+            .return_once_st(move |_, _, _, _, _| code);
+    }
+
+    pub fn expect_TEE_CloseAndDeletePersistentObject1_success_once(
+        &mut self,
+        exp_handle: ValidTestHandle,
+    ) {
+        self.expect_TEE_CloseAndDeletePersistentObject1()
+            .return_once_st(move |obj| {
+                assert_eq!(obj, unsafe { *exp_handle.get() });
+                raw::TEE_SUCCESS
+            });
+    }
+    pub fn expect_TEE_CloseAndDeletePersistentObject1_fail_once(&mut self, 
code: raw::TEE_Result) {
+        self.expect_TEE_CloseAndDeletePersistentObject1()
+            .return_once_st(move |_| code);
+    }
+
+    pub fn expect_TEE_CloseObject_once(&mut self, exp_handle: ValidTestHandle) 
{
+        self.expect_TEE_CloseObject().return_once_st(move |obj| {
+            assert_eq!(obj, unsafe { *exp_handle.get() });
+        });
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use crate::raw;
+
+    #[test]
+    fn test_new_handle() {
+        let mut handle_struct1 = 
MockObjectController::new_valid_test_handle_struct();
+        let mut handle_struct2 = 
MockObjectController::new_valid_test_handle_struct();
+
+        let handle1 = MockObjectController::new_valid_test_handle(&mut 
handle_struct1);
+        let handle2 = MockObjectController::new_valid_test_handle(&mut 
handle_struct2);
+
+        assert_ne!(unsafe { *handle1.get() }, unsafe { *handle2.get() });
+
+        let handle3: ValidTestHandle = 
Arc::new(UnsafeCell::new(core::ptr::null_mut()));
+        let handle4: ValidTestHandle = 
Arc::new(UnsafeCell::new(core::ptr::null_mut()));
+        assert_eq!(unsafe { *handle3.get() }, unsafe { *handle4.get() });
+    }
+
+    #[test]
+    fn test_mock_usage() {
+        let mut handle_struct = 
MockObjectController::new_valid_test_handle_struct();
+        let handle = MockObjectController::new_valid_test_handle(&mut 
handle_struct);
+        let mut mock = MockObjectController::new();
+
+        mock.expect_TEE_OpenPersistentObject_success_once(handle.clone());
+        
mock.expect_TEE_CloseAndDeletePersistentObject1_success_once(handle.clone());
+        mock.expect_TEE_CloseObject_once(handle.clone());
+
+        set_global_object_mock(mock);
+
+        let mut handle = core::ptr::null_mut();
+        let result =
+            unsafe { raw::TEE_OpenPersistentObject(0, core::ptr::null(), 0, 0, 
&mut handle) };
+        assert_eq!(result, raw::TEE_SUCCESS);
+
+        let result = unsafe { raw::TEE_CloseAndDeletePersistentObject1(handle) 
};
+        assert_eq!(result, raw::TEE_SUCCESS);
+
+        unsafe { raw::TEE_CloseObject(handle) };
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@teaclave.apache.org
For additional commands, e-mail: commits-h...@teaclave.apache.org

Reply via email to