From 1073e5d9f22bdbe600c15f7333f61be362ff72b3 Mon Sep 17 00:00:00 2001 From: huangyuchen Date: Thu, 18 May 2023 21:31:39 +0800 Subject: [PATCH] Provide rust interfaces for ashmem. And add the build configuration for rust codes of c_utils. 1. Provide shared-library configuration of rust interfaces. Includes `lib.rs` announcing each modules. 2. Provide rust interfaces of ashmem which utilized FFI to call c++ counterparts. 3. Ashmem in C++ now will call `UnmapAshmem()` and `CloseAshmem()` during deconstruction. Issue:I7A7LY Test: UT of rust and c++. Signed-off-by: huangyuchen Change-Id: Ic8fa5310df532d120d5851aa9364be43ace7285f --- base/BUILD.gn | 55 ++ base/include/ashmem.h | 119 ++-- base/src/ashmem.cpp | 94 ++- base/src/rust/ashmem.rs | 232 ++++++++ base/src/rust/file_ex.rs | 26 + base/src/rust/lib.rs | 24 + base/test/BUILD.gn | 5 +- base/test/unittest/rust/BUILD.gn | 35 ++ .../unittest/rust/utils_rust_ashmem_test.rs | 561 ++++++++++++++++++ bundle.json | 10 +- 10 files changed, 1096 insertions(+), 65 deletions(-) create mode 100644 base/src/rust/ashmem.rs create mode 100644 base/src/rust/file_ex.rs create mode 100644 base/src/rust/lib.rs create mode 100644 base/test/unittest/rust/BUILD.gn create mode 100644 base/test/unittest/rust/utils_rust_ashmem_test.rs diff --git a/base/BUILD.gn b/base/BUILD.gn index 452d3a6..b73111d 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/ohos.gni") +import("//build/templates/rust/rust_cxx.gni") # used for templates rust_cxx() ############################################################################### declare_args() { @@ -171,4 +172,58 @@ ohos_shared_library("utils") { ] } } + +########## modules for `c_utils` in rust ########## +rust_cxx("cxx_rust_gen") { + sources = [ + "src/rust/ashmem.rs", + "src/rust/file_ex.rs", + ] +} + +ohos_static_library("utils_static_cxx_rust") { + sources = [ + "src/ashmem.cpp", + "src/file_ex.cpp", + "src/refbase.cpp", + ] + sources += get_target_outputs(":cxx_rust_gen") + defines = [ "UTILS_CXX_RUST" ] + include_dirs = [ + "include", + "${target_gen_dir}", + "//third_party/rust/crates/cxx/include", + ] + deps = [ + ":cxx_rust_gen", + "//build/rust/tests:cxx_cppdeps", + ] + public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ] + + subsystem_name = "commonlibrary" + part_name = "c_utils" +} + +ohos_rust_shared_library("utils_rust") { + sources = [ + "src/rust/ashmem.rs", + "src/rust/file_ex.rs", + "src/rust/lib.rs", + ] + deps = [ + ":utils_static_cxx_rust", + "//third_party/rust/crates/cxx:lib", + ] + + crate_root = "src/rust/lib.rs" + crate_name = "utils_rust" + crate_type = "dylib" + output_extension = "dylib.so" + subsystem_name = "commonlibrary" + part_name = "c_utils" + install_images = [ + "system", + "updater", + ] +} ############################################################################### diff --git a/base/include/ashmem.h b/base/include/ashmem.h index f7d855e..c8ac9a1 100644 --- a/base/include/ashmem.h +++ b/base/include/ashmem.h @@ -25,10 +25,22 @@ #include #include +#ifdef UTILS_CXX_RUST +#include +#endif #include "refbase.h" #include "parcel.h" namespace OHOS { +class Ashmem; + +#ifdef UTILS_CXX_RUST +using c_void = void; +const c_void* AsVoidPtr(const char* inPtr); +const char* AsCharPtr(const c_void* inPtr); +std::shared_ptr CreateAshmemStd(const char *name, int32_t size); +#endif + /** * @brief Create ashmem in kernel with specified name and size. * @@ -80,6 +92,57 @@ public: */ static sptr CreateAshmem(const char *name, int32_t size); + /** + * @brief Construct a new Ashmem object. + * + * @param fd File descriptor of an ashmem in kenrel. + * @param size Size of the corresponding ashmem region in kernel. + */ + Ashmem(int fd, int32_t size); + ~Ashmem() override; + + /** + * @brief Get file descriptor of the corresponding ashmem in kernel. + * + * @return Corresponding file descriptor of this Ashmem object. It will be + * 0 when ashmem is closed. + */ + int GetAshmemFd() const + { + return memoryFd_; + }; + + /** + * @brief Set the protection flag of ashmem region in kernel. + * + * @param protectionType Value of protection flag. + * @return True if set successful. + */ + bool SetProtection(int protectionType) const; + + /** + * @brief Get the protection flag of ashmem region in kernel. + * + * @return Value of protection flag. Refer to linux manual. + */ + int GetProtection() const; + + /** + * @brief Get the size of ashmem region in kernel. + * + * @return Value of size. + */ + int32_t GetAshmemSize() const; + + #ifdef UTILS_CXX_RUST + void CloseAshmem() const; + bool MapAshmem(int mapType) const; + bool MapReadAndWriteAshmem() const; + bool MapReadOnlyAshmem() const; + void UnmapAshmem() const; + bool WriteToAshmem(const void *data, int32_t size, int32_t offset) const; + const void *ReadFromAshmem(int32_t size, int32_t offset) const; + #else /** * @brief Close the ashmem(i.e. close it via file descriptor). * @@ -123,28 +186,6 @@ public: */ void UnmapAshmem(); - /** - * @brief Set the protection flag of ashmem region in kernel. - * - * @param protectionType Value of protection flag. - * @return True if set successful. - */ - bool SetProtection(int protectionType); - - /** - * @brief Get the protection flag of ashmem region in kernel. - * - * @return Value of protection flag. Refer to linux manual. - */ - int GetProtection(); - - /** - * @brief Get the size of ashmem region in kernel. - * - * @return Value of size. - */ - int32_t GetAshmemSize(); - /** * @brief Write data to the `offset` position of ashmem region. * @@ -173,33 +214,21 @@ public: * in user space. */ const void *ReadFromAshmem(int32_t size, int32_t offset); - - /** - * @brief Construct a new Ashmem object. - * - * @param fd File descriptor of an ashmem in kenrel. - * @param size Size of the corresponding ashmem region in kernel. - */ - Ashmem(int fd, int32_t size); - ~Ashmem() override; - - /** - * @brief Get file descriptor of the corresponding ashmem in kernel. - * - * @return Corresponding file descriptor of this Ashmem object. It will be - * 0 when ashmem is closed. - */ - int GetAshmemFd() const - { - return memoryFd_; - }; - + #endif private: + #ifdef UTILS_CXX_RUST + mutable int memoryFd_; // corresponding file descriptor of ashmem. + mutable int32_t memorySize_; // size of ashmem. + mutable int flag_; // protection flag of ashmem in user space. + mutable void *startAddr_; // start address of ashmem region. + #else int memoryFd_; // corresponding file descriptor of ashmem. int32_t memorySize_; // size of ashmem. int flag_; // protection flag of ashmem in user space. void *startAddr_; // start address of ashmem region. - bool CheckValid(int32_t size, int32_t offset, int cmd); + #endif + + bool CheckValid(int32_t size, int32_t offset, int cmd) const; }; } // namespace OHOS -#endif +#endif \ No newline at end of file diff --git a/base/src/ashmem.cpp b/base/src/ashmem.cpp index 6a85f02..48a3bf7 100644 --- a/base/src/ashmem.cpp +++ b/base/src/ashmem.cpp @@ -35,6 +35,34 @@ namespace OHOS { static pthread_mutex_t g_ashmemLock = PTHREAD_MUTEX_INITIALIZER; +#ifdef UTILS_CXX_RUST +std::shared_ptr CreateAshmemStd(const char *name, int32_t size) +{ + if ((name == nullptr) || (size <= 0)) { + UTILS_LOGE("%{public}s: Parameter is invalid, size= %{public}d", __func__, size); + return std::shared_ptr{}; + } + + int fd = AshmemCreate(name, size); + if (fd < 0) { + UTILS_LOGE("%{public}s: Failed to exec AshmemCreate, fd= %{public}d", __func__, size); + return std::shared_ptr{}; + } + + return std::make_shared(fd, size); +} + +const c_void* AsVoidPtr(const char* inPtr) +{ + return static_cast(inPtr); +} + +const char* AsCharPtr(const c_void* inPtr) +{ + return static_cast(inPtr); +} +#endif + static int AshmemOpenLocked() { int fd = TEMP_FAILURE_RETRY(open("/dev/ashmem", O_RDWR | O_CLOEXEC)); @@ -117,12 +145,14 @@ int AshmemGetSize(int fd) return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)); } -Ashmem::Ashmem(int fd, int size) : memoryFd_(fd), memorySize_(size), flag_(0), startAddr_(nullptr) +Ashmem::Ashmem(int fd, int32_t size) : memoryFd_(fd), memorySize_(size), flag_(0), startAddr_(nullptr) { } Ashmem::~Ashmem() { + UnmapAshmem(); + CloseAshmem(); } sptr Ashmem::CreateAshmem(const char *name, int32_t size) @@ -141,7 +171,27 @@ sptr Ashmem::CreateAshmem(const char *name, int32_t size) return new Ashmem(fd, size); } +bool Ashmem::SetProtection(int protectionType) const +{ + int result = AshmemSetProt(memoryFd_, protectionType); + return result >= 0; +} + +int Ashmem::GetProtection() const +{ + return TEMP_FAILURE_RETRY(ioctl(memoryFd_, ASHMEM_GET_PROT_MASK)); +} + +int32_t Ashmem::GetAshmemSize() const +{ + return AshmemGetSize(memoryFd_); +} + +#ifdef UTILS_CXX_RUST +void Ashmem::CloseAshmem() const +#else void Ashmem::CloseAshmem() +#endif { if (memoryFd_ > 0) { ::close(memoryFd_); @@ -152,7 +202,11 @@ void Ashmem::CloseAshmem() startAddr_ = nullptr; } +#ifdef UTILS_CXX_RUST +bool Ashmem::MapAshmem(int mapType) const +#else bool Ashmem::MapAshmem(int mapType) +#endif { void *startAddr = ::mmap(nullptr, memorySize_, mapType, MAP_SHARED, memoryFd_, 0); if (startAddr == MAP_FAILED) { @@ -166,17 +220,29 @@ bool Ashmem::MapAshmem(int mapType) return true; } +#ifdef UTILS_CXX_RUST +bool Ashmem::MapReadAndWriteAshmem() const +#else bool Ashmem::MapReadAndWriteAshmem() +#endif { return MapAshmem(PROT_READ | PROT_WRITE); } +#ifdef UTILS_CXX_RUST +bool Ashmem::MapReadOnlyAshmem() const +#else bool Ashmem::MapReadOnlyAshmem() +#endif { return MapAshmem(PROT_READ); } +#ifdef UTILS_CXX_RUST +void Ashmem::UnmapAshmem() const +#else void Ashmem::UnmapAshmem() +#endif { if (startAddr_ != nullptr) { ::munmap(startAddr_, memorySize_); @@ -185,23 +251,11 @@ void Ashmem::UnmapAshmem() flag_ = 0; } -bool Ashmem::SetProtection(int protectionType) -{ - int result = AshmemSetProt(memoryFd_, protectionType); - return result >= 0; -} - -int Ashmem::GetProtection() -{ - return TEMP_FAILURE_RETRY(ioctl(memoryFd_, ASHMEM_GET_PROT_MASK)); -} - -int32_t Ashmem::GetAshmemSize() -{ - return AshmemGetSize(memoryFd_); -} - +#ifdef UTILS_CXX_RUST +bool Ashmem::WriteToAshmem(const void *data, int32_t size, int32_t offset) const +#else bool Ashmem::WriteToAshmem(const void *data, int32_t size, int32_t offset) +#endif { if (data == nullptr) { return false; @@ -222,7 +276,11 @@ bool Ashmem::WriteToAshmem(const void *data, int32_t size, int32_t offset) return true; } +#ifdef UTILS_CXX_RUST +const void *Ashmem::ReadFromAshmem(int32_t size, int32_t offset) const +#else const void *Ashmem::ReadFromAshmem(int32_t size, int32_t offset) +#endif { if (!CheckValid(size, offset, PROT_READ)) { UTILS_LOGE("%{public}s: invalid input or not map", __func__); @@ -232,7 +290,7 @@ const void *Ashmem::ReadFromAshmem(int32_t size, int32_t offset) return reinterpret_cast(startAddr_) + offset; } -bool Ashmem::CheckValid(int32_t size, int32_t offset, int cmd) +bool Ashmem::CheckValid(int32_t size, int32_t offset, int cmd) const { if (startAddr_ == nullptr) { return false; diff --git a/base/src/rust/ashmem.rs b/base/src/rust/ashmem.rs new file mode 100644 index 0000000..055885c --- /dev/null +++ b/base/src/rust/ashmem.rs @@ -0,0 +1,232 @@ +/* Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ + +/*! + * Ashmem provides interfaces for operating shared memory. + */ + +use cxx::SharedPtr; +use std::ffi::{c_char, CString}; + +/// Memory protection corresponding to PROT_NONE in C code. +pub const PROT_NONE: i32 = 0; +/// Memory protection corresponding to PROT_READ in C code. +pub const PROT_READ: i32 = 1; +/// Memory protection corresponding to PROT_WRITE in C code. +pub const PROT_WRITE: i32 = 2; +/// Memory protection corresponding to PROT_EXEC in C code. +pub const PROT_EXEC: i32 = 4; + +#[cxx::bridge(namespace = "OHOS")] +/// Module Ashmem::ffi. Includes interfaces which will call c++ counterparts via FFI. +pub mod ffi { + #[allow(dead_code)] + unsafe extern "C++" { + include!("commonlibrary/c_utils/base/include/ashmem.h"); + + // global function + /** + * Create an ashmem and return its FD. + * # Safety + * Requires C-style string as parameter to specify the name of Ashmem. + */ + pub unsafe fn AshmemCreate(name: *const c_char, size: usize) -> i32; + + /** + * Create an C++ Ashmem object managed by std::shared_ptr. + * # Safety + * Requires C-style string as parameter to specify the name of Ashmem. + */ + pub unsafe fn CreateAshmemStd(name: *const c_char, size: i32) -> SharedPtr; + + /// Set protection flag of created ashmem specified by FD. + pub fn AshmemSetProt(fd: i32, prot: i32) -> i32; + + /// Get size of created ashmem specified by FD. + pub fn AshmemGetSize(fd: i32) -> i32; + + /// C++ void type. + pub type c_void; + /** + * Cast c_char to c_void + * # Safety + */ + pub unsafe fn AsVoidPtr(inPtr: *const c_char) -> *const c_void; + + /** + * Cast c_char to c_void + * # Safety + */ + pub unsafe fn AsCharPtr(inPtr: *const c_void) -> *const c_char; + + /// C++ Ashmem class. + pub type Ashmem; + + // member function + /// Close inner ashmem. + pub fn CloseAshmem(self: &Ashmem) -> (); + + /// Map inner ashmem to user-space memory with specified map type. + pub fn MapAshmem(self: &Ashmem, mapType: i32) -> bool; + + /// Map inner ashmem to user-space memory with read-write type. + pub fn MapReadAndWriteAshmem(self: &Ashmem) -> bool; + + /// Map inner ashmem to user-space memory with read-only type. + pub fn MapReadOnlyAshmem(self: &Ashmem) -> bool; + + /// UnMap inner ashmem. + pub fn UnmapAshmem(self: &Ashmem) -> (); + + /// Set protection flag of inner ashmem. + pub fn SetProtection(self: &Ashmem, protType: i32) -> bool; + + /// Get protection flag of inner ashmem. + pub fn GetProtection(self: &Ashmem) -> i32; + + /// Get size of inner ashmem. + pub fn GetAshmemSize(self: &Ashmem) -> i32; + + /** + * Write data to inner ashmem. + * # Safety + * Requires a C++-style void pointer as parameter to indicates data expected to be written. + */ + pub unsafe fn WriteToAshmem(self: &Ashmem, data: *const c_void, size: i32, offset: i32) -> bool; + + /** + * Read data from inner ashmem. + * # Safety + * Returns a C++-style void pointer to indicates data expected to be read. + */ + pub unsafe fn ReadFromAshmem(self: &Ashmem, size: i32, offset: i32) -> *const c_void; + + /// Get FD of inner ashmem. + pub fn GetAshmemFd(self: &Ashmem) -> i32; + } +} + +/// Ashmem in rust. +#[allow(dead_code)] +pub struct Ashmem { + c_ashmem: SharedPtr +} + +/// Ashmem implementation. +#[allow(dead_code)] +impl Ashmem { + /// Create an ashmem object. + pub fn new(c_ashmem: SharedPtr) -> Ashmem { + Ashmem { + c_ashmem + } + } + + /// Get corresponding fd. + pub fn get_ashmem_fd(&self) -> i32 { + self.c_ashmem.GetAshmemFd() + } + + /// Get size of the shared memory. + pub fn get_ashmem_size(&self) -> i32 { + self.c_ashmem.GetAshmemSize() + } + + /// Get memory protection flags. + pub fn get_protection(&self) -> i32 { + self.c_ashmem.GetProtection() + } + + /// Set memory protection flags. + pub fn set_protection(&self, prot_type: i32) -> bool { + self.c_ashmem.SetProtection(prot_type) + } + + /// Map the shared memory to user-space. + pub fn map_ashmem(&self, prot_type: i32) -> bool { + self.c_ashmem.MapAshmem(prot_type) + } + + /// Map ashmem in read&write mode. + pub fn map_read_write_ashmem(&self) -> bool { + self.c_ashmem.MapReadAndWriteAshmem() + } + + /// Map ashmem in read-only mode. + pub fn map_read_only_ashmem(&self) -> bool { + self.c_ashmem.MapReadOnlyAshmem() + } + + /// Unmap ashmem. + pub fn unmap_ashmem(&self) { + self.c_ashmem.UnmapAshmem() + } + + /// Close ashmem. + pub fn close_ashmem(&self) { + self.c_ashmem.CloseAshmem() + } + + /** + * Write data to ashmem. + * # Safety + * Requires c-style data(*const c_char) + */ + /// # Safety + pub unsafe fn write_to_ashmem(&self, data: *const c_char, size: i32, offset: i32) -> bool { + let c_void_ptr = ffi::AsVoidPtr(data); + self.c_ashmem.WriteToAshmem(c_void_ptr, size, offset) + } + + /** + * Read data from ashmem. + * # Safety + * Returns c-style data(*const c_char) + */ + /// # Safety + pub unsafe fn read_from_ashmem(&self, size: i32, offset: i32) -> *const c_char { + let c_void_ptr = self.c_ashmem.ReadFromAshmem(size, offset); + ffi::AsCharPtr(c_void_ptr) + } +} + +/** + * Create Ashmem struct in Rust, which holds a refrence to c++ Ashmem object. + * # Safety + * Transmits c-style string of `name`. + */ +#[allow(dead_code)] +pub unsafe fn create_ashmem_instance(name: &str, size: i32) -> Option { + let c_name = CString::new(name).expect("CString::new Failed!"); + let name_ptr = c_name.as_ptr(); + let c_ashmem_ptr = ffi::CreateAshmemStd(name_ptr, size); + + if c_ashmem_ptr.is_null() { + None + } else { + Some(Ashmem::new(c_ashmem_ptr)) + } +} + +/** + * Create raw ashmem and returns its FD. + * # Safety + * Transmits c-style string of `name`. + */ +#[allow(dead_code)] +pub unsafe fn ashmem_create(name: &str, size: i32) -> i32 { + let c_name = CString::new(name).expect("CString::new Failed!"); + let name_ptr = c_name.as_ptr(); + ffi::AshmemCreate(name_ptr, size.try_into().expect("Invalid size.")) +} \ No newline at end of file diff --git a/base/src/rust/file_ex.rs b/base/src/rust/file_ex.rs new file mode 100644 index 0000000..c468551 --- /dev/null +++ b/base/src/rust/file_ex.rs @@ -0,0 +1,26 @@ +/* Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ + +/*! + * File_ex provides interfaces for operating on file. + */ + +#[cxx::bridge(namespace = "OHOS")] +/// Module file_ex::ffi. Includes interfaces which will call c++ counterparts via FFI. +pub mod ffi { + #[allow(dead_code)] + unsafe extern "C++" { + include!("commonlibrary/c_utils/base/include/file_ex.h"); + } +} diff --git a/base/src/rust/lib.rs b/base/src/rust/lib.rs new file mode 100644 index 0000000..c47720a --- /dev/null +++ b/base/src/rust/lib.rs @@ -0,0 +1,24 @@ +/* Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ + +/*! + * Crate utils_rust. Provides rust version implementation of c_utils. Current it essentially call C++ interfaces via FFI. + */ + +/// Module Ashmem. Provides interfaces to operate on ashmem(Anonymous shared memory). +pub mod ashmem; + +/// Module File_ex. Provides interfaces to operate on file. +/// Includes reading from or writting to files and searching for specified strings. +pub mod file_ex; \ No newline at end of file diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index c30bed4..fa78f6d 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn @@ -17,7 +17,10 @@ group("unittest") { testonly = true deps = [] - deps += [ "unittest/common:unittest" ] + deps += [ + "unittest/common:unittest", + "unittest/rust:unittest", + ] if (is_phone_product) { deps += [ diff --git a/base/test/unittest/rust/BUILD.gn b/base/test/unittest/rust/BUILD.gn new file mode 100644 index 0000000..a44d0db --- /dev/null +++ b/base/test/unittest/rust/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# 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. +import("//build/ohos.gni") +import("//build/test.gni") + +config("module_private_config") { + visibility = [ ":*" ] + + # library path + lib_dirs = [ "libs" ] +} + +group("unittest") { + testonly = true + deps = [] + + deps += [ ":utils_rust_ashmem_test" ] +} + +ohos_rust_unittest("utils_rust_ashmem_test") { + module_out_path = "utils/base/rust" + sources = [ "utils_rust_ashmem_test.rs" ] + configs = [ ":module_private_config" ] + deps = [ "../../../../base:utils_rust" ] +} diff --git a/base/test/unittest/rust/utils_rust_ashmem_test.rs b/base/test/unittest/rust/utils_rust_ashmem_test.rs new file mode 100644 index 0000000..b781652 --- /dev/null +++ b/base/test/unittest/rust/utils_rust_ashmem_test.rs @@ -0,0 +1,561 @@ +/* Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ + +use std::ptr; +use std::ffi::{c_char, CStr, CString}; +use utils_rust::ashmem; + +const MEMORY_SIZE: i32 = 1024; +const MEMORY_NAME: &str = "Test SharedMemory"; +const MEMORY_CONTENT: &str = "HelloWorld2023"; + +#[test] +fn test_ashmem_ffi_write_read_001() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + assert_eq!(ashmem.GetAshmemSize(), MEMORY_SIZE); + + assert!(ashmem.MapAshmem(ashmem::PROT_READ | ashmem::PROT_WRITE)); + + ashmem.UnmapAshmem(); + ashmem.CloseAshmem(); +} + +#[test] +fn test_ashmem_ffi_write_read_002() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(ashmem.MapReadAndWriteAshmem()); + + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + let c_content_ptr: *const ashmem::ffi::c_void = unsafe { ashmem::ffi::AsVoidPtr(c_content.as_ptr()) }; + + unsafe { + assert!(ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + assert!(ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), + MEMORY_CONTENT.len().try_into().expect("Invalid content size."))); + } + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem::ffi::AsCharPtr(ashmem.ReadFromAshmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + assert!(!readout_ptr.is_null()); + + // readout_ptr requires a valid nul terminator at the end of the string. + let readout_c_str: &CStr = unsafe { CStr::from_ptr(readout_ptr) }; + let readout_str: &str = readout_c_str.to_str().expect("Bad encoding."); + + let mut expect = String::from(MEMORY_CONTENT); + expect.push_str(MEMORY_CONTENT); + assert_eq!(readout_str, expect.as_str()); + + ashmem.UnmapAshmem(); + ashmem.CloseAshmem(); +} + +#[test] +fn test_ashmem_ffi_write_read_003() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(ashmem.MapReadAndWriteAshmem()); + + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + let c_content_ptr: *const ashmem::ffi::c_void = unsafe { ashmem::ffi::AsVoidPtr(c_content.as_ptr()) }; + + unsafe { + assert!(ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + ashmem.UnmapAshmem(); + assert!(ashmem.MapReadOnlyAshmem()); + + unsafe { + assert!(!ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), + MEMORY_NAME.len().try_into().expect("Invalid content size."))); + } + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem::ffi::AsCharPtr(ashmem.ReadFromAshmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + assert!(!readout_ptr.is_null()); + + // readout_ptr requires a valid nul terminator at the end of the string. + let readout_c_str: &CStr = unsafe { CStr::from_ptr(readout_ptr) }; + let readout_str: &str = readout_c_str.to_str().expect("Bad encoding."); + + assert_eq!(readout_str, MEMORY_CONTENT); + + ashmem.UnmapAshmem(); + ashmem.CloseAshmem(); +} + +#[test] +fn test_ashmem_ffi_write_read_004() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(ashmem.MapReadAndWriteAshmem()); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + let c_content_ptr: *const ashmem::ffi::c_void = unsafe { ashmem::ffi::AsVoidPtr(c_content.as_ptr()) }; + unsafe { + assert!(ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + ashmem.UnmapAshmem(); + assert!(ashmem.SetProtection(ashmem::PROT_READ)); + assert!(!ashmem.MapReadAndWriteAshmem()); + assert!(ashmem.MapReadOnlyAshmem()); + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem::ffi::AsCharPtr(ashmem.ReadFromAshmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + assert!(!readout_ptr.is_null()); + + // readout_ptr requires a valid nul terminator at the end of the string. + let readout_c_str: &CStr = unsafe { CStr::from_ptr(readout_ptr) }; + let readout_str: &str = readout_c_str.to_str().expect("Bad encoding."); + assert_eq!(readout_str, MEMORY_CONTENT); + + ashmem.UnmapAshmem(); + ashmem.CloseAshmem(); +} + +#[test] +fn test_ashmem_ffi_write_read_005() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(ashmem.MapReadAndWriteAshmem()); + assert!(ashmem.SetProtection(ashmem::PROT_READ)); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + let c_content_ptr: *const ashmem::ffi::c_void = unsafe { ashmem::ffi::AsVoidPtr(c_content.as_ptr()) }; + unsafe { + assert!(!ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + assert!(ashmem.MapReadOnlyAshmem()); + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem::ffi::AsCharPtr(ashmem.ReadFromAshmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + assert!(!readout_ptr.is_null()); + + // readout_ptr requires a valid nul terminator at the end of the string. + let readout_c_str: &CStr = unsafe { CStr::from_ptr(readout_ptr) }; + let readout_str: &str = readout_c_str.to_str().expect("Bad encoding."); + assert_eq!(readout_str, ""); + + ashmem.UnmapAshmem(); + ashmem.CloseAshmem(); +} + +#[test] +fn test_ashmem_ffi_invalid_001() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), -1) }; + assert!(ashmem.is_null()); + + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(!ashmem.SetProtection(-1)); + + ashmem.CloseAshmem(); +} + +#[test] +fn test_ashmem_ffi_invalid_002() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + ashmem.CloseAshmem(); + assert!(!ashmem.MapReadAndWriteAshmem()); +} + +#[test] +fn test_ashmem_ffi_invalid_003() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(ashmem.MapReadAndWriteAshmem()); + + ashmem.CloseAshmem(); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + let c_content_ptr: *const ashmem::ffi::c_void = unsafe { ashmem::ffi::AsVoidPtr(c_content.as_ptr()) }; + unsafe { + assert!(!ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem::ffi::AsCharPtr(ashmem.ReadFromAshmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + assert!(readout_ptr.is_null()); +} + +#[test] +fn test_ashmem_ffi_invalid_004() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(ashmem.MapReadAndWriteAshmem()); + + ashmem.UnmapAshmem(); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + let c_content_ptr: *const ashmem::ffi::c_void = unsafe { ashmem::ffi::AsVoidPtr(c_content.as_ptr()) }; + unsafe { + assert!(!ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem::ffi::AsCharPtr(ashmem.ReadFromAshmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + assert!(readout_ptr.is_null()); + + ashmem.CloseAshmem(); +} + +#[test] +fn test_ashmem_ffi_invalid_005() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(ashmem.SetProtection(ashmem::PROT_WRITE)); + assert!(!ashmem.SetProtection(ashmem::PROT_READ)); + assert!(!ashmem.SetProtection(ashmem::PROT_READ | ashmem::PROT_WRITE)); + assert!(ashmem.SetProtection(ashmem::PROT_NONE)); + assert!(!ashmem.SetProtection(ashmem::PROT_READ)); + assert!(!ashmem.SetProtection(ashmem::PROT_WRITE)); + + ashmem.CloseAshmem(); +} + + +#[test] +fn test_ashmem_ffi_invalid_006() +{ + let c_name = CString::new(MEMORY_NAME).expect("CString::new Failed!"); + let ashmem = unsafe { ashmem::ffi::CreateAshmemStd(c_name.as_ptr(), MEMORY_SIZE) }; + assert!(!ashmem.is_null()); + + assert!(ashmem.MapReadAndWriteAshmem()); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + let c_content_ptr: *const ashmem::ffi::c_void = unsafe { ashmem::ffi::AsVoidPtr(c_content.as_ptr()) }; + unsafe { + assert!(!ashmem.WriteToAshmem(ptr::null(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + assert!(!ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), MEMORY_SIZE)); + assert!(!ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), MEMORY_SIZE + 1)); + assert!(!ashmem.WriteToAshmem(c_content_ptr, MEMORY_CONTENT.len().try_into().expect("Invalid content size."), -1)); + assert!(!ashmem.WriteToAshmem(c_content_ptr, MEMORY_SIZE + 1, 0)); + assert!(!ashmem.WriteToAshmem(c_content_ptr, -1, 0)); + } + + ashmem.UnmapAshmem(); + ashmem.CloseAshmem(); +} + + +#[test] +fn test_ashmem_write_read_001() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + assert_eq!(ashmem.get_ashmem_size(), MEMORY_SIZE); + + assert!(ashmem.map_ashmem(ashmem::PROT_READ | ashmem::PROT_WRITE)); + + ashmem.unmap_ashmem(); + ashmem.close_ashmem(); +} + +#[test] +fn test_ashmem_write_read_002() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + assert!(ashmem.map_read_write_ashmem()); + + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + unsafe { + assert!(ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + assert!(ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), + MEMORY_CONTENT.len().try_into().expect("Invalid content size."))); + } + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem.read_from_ashmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0); + assert!(!readout_ptr.is_null()); + } + + // readout_ptr requires a valid nul terminator at the end of the string. + let readout_c_str: &CStr = unsafe { CStr::from_ptr(readout_ptr) }; + let readout_str: &str = readout_c_str.to_str().expect("Bad encoding."); + + let mut expect = String::from(MEMORY_CONTENT); + expect.push_str(MEMORY_CONTENT); + assert_eq!(readout_str, expect.as_str()); + + ashmem.unmap_ashmem(); + ashmem.close_ashmem(); +} + +#[test] +fn test_ashmem_write_read_003() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + assert!(ashmem.map_read_write_ashmem()); + + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + unsafe { + assert!(ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + ashmem.unmap_ashmem(); + assert!(ashmem.map_read_only_ashmem()); + + unsafe { + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), + MEMORY_CONTENT.len().try_into().expect("Invalid content size."))); + } + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem.read_from_ashmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0); + assert!(!readout_ptr.is_null()); + } + + // readout_ptr requires a valid nul terminator at the end of the string. + let readout_c_str: &CStr = unsafe { CStr::from_ptr(readout_ptr) }; + let readout_str: &str = readout_c_str.to_str().expect("Bad encoding."); + + assert_eq!(readout_str, MEMORY_CONTENT); + + ashmem.unmap_ashmem(); + ashmem.close_ashmem(); +} + +#[test] +fn test_ashmem_write_read_004() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + assert!(ashmem.map_read_write_ashmem()); + + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + unsafe { + assert!(ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + ashmem.unmap_ashmem(); + assert!(ashmem.set_protection(ashmem::PROT_READ)); + assert!(!ashmem.map_read_write_ashmem()); + assert!(ashmem.map_read_only_ashmem()); + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem.read_from_ashmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0); + assert!(!readout_ptr.is_null()); + } + + // readout_ptr requires a valid nul terminator at the end of the string. + let readout_c_str: &CStr = unsafe { CStr::from_ptr(readout_ptr) }; + let readout_str: &str = readout_c_str.to_str().expect("Bad encoding."); + assert_eq!(readout_str, MEMORY_CONTENT); + + ashmem.unmap_ashmem(); + ashmem.close_ashmem(); +} + +#[test] +fn test_ashmem_write_read_005() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + assert!(ashmem.map_read_write_ashmem()); + assert!(ashmem.set_protection(ashmem::PROT_READ)); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + unsafe { + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + assert!(ashmem.map_read_only_ashmem()); + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem.read_from_ashmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0); + assert!(!readout_ptr.is_null()); + } + + // readout_ptr requires a valid nul terminator at the end of the string. + let readout_c_str: &CStr = unsafe { CStr::from_ptr(readout_ptr) }; + let readout_str: &str = readout_c_str.to_str().expect("Bad encoding."); + assert_eq!(readout_str, ""); + + ashmem.unmap_ashmem(); + ashmem.close_ashmem(); +} + +#[test] +fn test_ashmem_invalid_001() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, -1i32) }; + assert!(ashmem.is_none()); + + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + + assert!(!ashmem.set_protection(-1)); + + ashmem.close_ashmem(); +} + +#[test] +fn test_ashmem_invalid_002() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + ashmem.close_ashmem(); + + assert!(!ashmem.map_read_write_ashmem()); +} + + +#[test] +fn test_ashmem_invalid_003() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + + assert!(ashmem.map_read_write_ashmem()); + + ashmem.close_ashmem(); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + unsafe { + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem.read_from_ashmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0); + assert!(readout_ptr.is_null()); + } +} + +#[test] +fn test_ashmem_invalid_004() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + + assert!(ashmem.map_read_write_ashmem()); + + ashmem.unmap_ashmem(); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + unsafe { + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + } + + let readout_ptr: *const c_char; + unsafe { + readout_ptr = ashmem.read_from_ashmem(MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0); + assert!(readout_ptr.is_null()); + } + + ashmem.close_ashmem(); +} + +#[test] +fn test_ashmem_invalid_005() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + + assert!(ashmem.set_protection(ashmem::PROT_WRITE)); + assert!(!ashmem.set_protection(ashmem::PROT_READ)); + assert!(!ashmem.set_protection(ashmem::PROT_READ | ashmem::PROT_WRITE)); + assert!(ashmem.set_protection(ashmem::PROT_NONE)); + assert!(!ashmem.set_protection(ashmem::PROT_READ)); + assert!(!ashmem.set_protection(ashmem::PROT_WRITE)); + + ashmem.close_ashmem(); +} + +#[test] +fn test_ashmem_invalid_006() +{ + let ashmem = unsafe { ashmem::create_ashmem_instance(MEMORY_NAME, MEMORY_SIZE) }; + assert!(ashmem.is_some()); + + let ashmem = ashmem.unwrap(); + + assert!(ashmem.map_read_write_ashmem()); + let c_content = CString::new(MEMORY_CONTENT).expect("CString::new Failed!"); + unsafe { + assert!(!ashmem.write_to_ashmem(ptr::null(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), 0)); + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), MEMORY_SIZE)); + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), MEMORY_SIZE + 1)); + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_CONTENT.len().try_into().expect("Invalid content size."), -1)); + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), MEMORY_SIZE + 1, 0)); + assert!(!ashmem.write_to_ashmem(c_content.as_ptr(), -1, 0)); + } + + ashmem.unmap_ashmem(); + ashmem.close_ashmem(); +} \ No newline at end of file diff --git a/bundle.json b/bundle.json index 573033d..ce59662 100644 --- a/bundle.json +++ b/bundle.json @@ -28,7 +28,8 @@ "build": { "sub_component": [ "//commonlibrary/c_utils/base:utils", - "//commonlibrary/c_utils/base:utilsbase" + "//commonlibrary/c_utils/base:utilsbase", + "//commonlibrary/c_utils/base:utils_rust" ], "inner_kits": [ { @@ -96,6 +97,13 @@ ], "header_base": "//commonlibrary/c_utils/base/include" } + }, + { + "name": "//commonlibrary/c_utils/base:utils_rust", + "header": { + "header_files": [], + "header_base": [] + } } ], "test": [ -- Gitee