From 3854635dd151a9cad0e39d73a5268a4281e93a94 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 14 Dec 2020 15:45:49 +0900 Subject: [PATCH] Add Parcel Library This library is only for appfw internally. Adds: - parcel_create() - parcel_destroy() - parcel_clone() - parcel_burst_write() - parcel_burst_read() - parcel_write_bool() - parcel_write_byte() - parcel_write_uint16() - parcel_write_uint32() - parcel_write_uint64() - parcel_write_int16() - parcel_write_int32() - parcel_write_int64() - parcel_write_float() - parcel_write_double() - parcel_write_string() - parcel_write_bundle() - parcel_read_bool() - parcel_read_byte() - parcel_read_uint16() - parcel_read_uint32() - parcel_read_uint64() - parcel_read_int16() - parcel_read_int32() - parcel_read_int64() - parcel_read_float() - parcel_read_double() - parcel_read_string() - parcel_read_bundle() - parcel_reset_reader() - parcel_clear() - parcel_reset() - parcel_write() - parcel_read() - parcel_get_raw() Change-Id: I322faee040ca95c4cb8e4b7356e33a9af5daeb8c Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 13 +- packaging/bundle.spec | 53 ++ packaging/parcel.manifest | 5 + parcel/CMakeLists.txt | 51 ++ parcel/api/parcel.h | 554 ++++++++++++++++++++ parcel/common.hh | 23 + parcel/log_private.hh | 37 ++ parcel/parcel.cc | 405 +++++++++++++++ parcel/parcel.hh | 417 +++++++++++++++ parcel/parcel.pc.in | 14 + parcel/parcel_implementation.hh | 59 +++ parcel/parcelable.hh | 76 +++ parcel/stub.cc | 414 +++++++++++++++ tests/CMakeLists.txt | 2 + .../bundle_unittests}/CMakeLists.txt | 12 +- .../bundle_unittests}/src/test_bundle.cc | 0 .../bundle_unittests}/src/test_bundle_cpp.cc | 0 .../bundle_unittests}/src/test_main.cc | 0 tests/parcel_unittests/CMakeLists.txt | 42 ++ tests/parcel_unittests/test_main.cc | 30 ++ tests/parcel_unittests/test_parcel.cc | 568 +++++++++++++++++++++ tests/parcel_unittests/test_parcel_cpp.cc | 263 ++++++++++ 22 files changed, 3029 insertions(+), 9 deletions(-) create mode 100644 packaging/parcel.manifest create mode 100644 parcel/CMakeLists.txt create mode 100644 parcel/api/parcel.h create mode 100644 parcel/common.hh create mode 100644 parcel/log_private.hh create mode 100644 parcel/parcel.cc create mode 100644 parcel/parcel.hh create mode 100644 parcel/parcel.pc.in create mode 100644 parcel/parcel_implementation.hh create mode 100644 parcel/parcelable.hh create mode 100644 parcel/stub.cc create mode 100644 tests/CMakeLists.txt rename {unit_tests => tests/bundle_unittests}/CMakeLists.txt (69%) rename {unit_tests => tests/bundle_unittests}/src/test_bundle.cc (100%) rename {unit_tests => tests/bundle_unittests}/src/test_bundle_cpp.cc (100%) rename {unit_tests => tests/bundle_unittests}/src/test_main.cc (100%) create mode 100644 tests/parcel_unittests/CMakeLists.txt create mode 100644 tests/parcel_unittests/test_main.cc create mode 100644 tests/parcel_unittests/test_parcel.cc create mode 100644 tests/parcel_unittests/test_parcel_cpp.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eaa0a8..92b009e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,12 +46,21 @@ INSTALL(TARGETS bundle DESTINATION ${LIB_INSTALL_DIR}) INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/) INSTALL(FILES ${CMAKE_BINARY_DIR}/bundle.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig/) +ADD_SUBDIRECTORY(parcel) +ADD_DEPENDENCIES(parcel bundle) + IF(NOT DEFINED MINIMUM_BUILD) ENABLE_TESTING() SET(BUNDLE_UNITTESTS bundle_unittests) ADD_TEST(NAME ${BUNDLE_UNITTESTS} COMMAND ${BUNDLE_UNITTESTS} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/unit_tests) + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/bundle_unittests) -ADD_SUBDIRECTORY(unit_tests) +ADD_SUBDIRECTORY(tests) ADD_DEPENDENCIES(bundle_unittests bundle) + +SET(PARCEL_UNITTESTS parcel_unittests) +ADD_TEST(NAME ${PARCEL_UNITTESTS} COMMAND ${PARCEL_UNITTESTS} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/parcel_unittests) + +ADD_DEPENDENCIES(parcel_unittests parcel) ENDIF(NOT DEFINED MINIMUM_BUILD) diff --git a/packaging/bundle.spec b/packaging/bundle.spec index 5dd1a66..d39d5c8 100644 --- a/packaging/bundle.spec +++ b/packaging/bundle.spec @@ -6,6 +6,7 @@ Group: System/Libraries License: Apache-2.0 Source0: bundle-%{version}.tar.gz Source1001: bundle.manifest +Source1002: parcel.manifest BuildRequires: cmake BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(dlog) @@ -51,9 +52,38 @@ Group: Application Framework/Testing Simple string key-val dictionary ADT gcov objects %endif +################################################# +## parcel +################################################# +%package -n parcel +Summary: Parcel Library +Group: Development/Libraries + +%description -n parcel +Parcel Library + +%package -n parcel-devel +Summary: Parcel Library (devel) +Group: Development/Libraries +Requires: parcel = %{version}-%{release} + +%description -n parcel-devel +Parcel Library (devel) + +################################################# +# parcel-unittests +################################################# +%package -n parcel-unittests +Summary: GTest for parcel +Group: Development/Libraries + +%description -n parcel-unittests +GTest for parcel + %prep %setup -q -n %{name}-%{version} cp %{SOURCE1001} . +cp %{SOURCE1002} . %build %if 0%{?gcov:1} @@ -92,6 +122,12 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %postun -p /sbin/ldconfig +%post -n parcel +/sbin/ldconfig + +%postun -n parcel +/sbin/ldconfig + %post unittests %if 0%{?gcov:1} %{_bindir}/bundle_unittests @@ -123,3 +159,20 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %files gcov %{_datadir}/gcov/* %endif + +################################################# +# parcel +################################################# +%files -n parcel +%manifest parcel.manifest +%license LICENSE +%{_libdir}/libparcel.so.* + +%files -n parcel-devel +%manifest parcel.manifest +%{_includedir}/* +%{_libdir}/pkgconfig/parcel.pc +%{_libdir}/libparcel.so + +%files -n parcel-unittests +%{_bindir}/parcel_unittests diff --git a/packaging/parcel.manifest b/packaging/parcel.manifest new file mode 100644 index 0000000..017d22d --- /dev/null +++ b/packaging/parcel.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/parcel/CMakeLists.txt b/parcel/CMakeLists.txt new file mode 100644 index 0000000..d8b9d2b --- /dev/null +++ b/parcel/CMakeLists.txt @@ -0,0 +1,51 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(parcel C CXX) + +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(pkgs REQUIRED dlog capi-base-common) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -flto -Wall -Werror -Winline") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++14") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/api) + +AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/parcel PARCEL_SRCS) + +ADD_LIBRARY (${PROJECT_NAME} SHARED ${PARCEL_SRCS}) + +SET_TARGET_PROPERTIES(parcel PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(parcel PROPERTIES VERSION "${VERSION}") + +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS} -fPIE") +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-pie") +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} bundle) + +### Make pkgconfig file +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/parcel.pc.in + ${CMAKE_BINARY_DIR}/parcel.pc @ONLY) + +### Install +INSTALL(TARGETS parcel DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(FILES ${CMAKE_BINARY_DIR}/parcel.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig/) + +SET(HEADER_PARCEL + common.hh + parcel.hh + parcelable.hh +) + +FOREACH(hfile ${HEADER_PARCEL}) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${hfile} DESTINATION include/parcel) +ENDFOREACH(hfile) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/api/parcel.h + DESTINATION include/parcel) diff --git a/parcel/api/parcel.h b/parcel/api/parcel.h new file mode 100644 index 0000000..886aa1a --- /dev/null +++ b/parcel/api/parcel.h @@ -0,0 +1,554 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#ifndef __PARCEL_H__ +#define __PARCEL_H__ + +#include +#include +#include +#include + +/** + * @addtogroup CORE_LIB_PARCEL_MODULE + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The parcel handle. + * @since_tizen 6.5 + */ +typedef void *parcel_h; + +/** + * @brief The interface for converting data to/from a parcel. + * @since_tizen 6.5 + */ +typedef struct { + void (*to)(parcel_h parcel, void *data); + void (*from)(parcel_h parcel, void *data); +} parcelable_t; + +/** + * @brief Enumeration for error codes for a parcel. + * @since_tizen 6.5 + */ +typedef enum { + PARCEL_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + PARCEL_ERROR_ILLEGAL_BYTE_SEQ = TIZEN_ERROR_ILLEGAL_BYTE_SEQ, /**< Illegal byte sequence */ + PARCEL_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + PARCEL_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data available */ + PARCEL_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ +} parcel_error_e; + +/** + * @brief Creates a parcel handle. + * @since_tizen 6.5 + * @remarks You MUST release @a parcel using parcel_destroy(). + * @param[out] parcel The parcel handle that is newly created + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_OUT_OF_MEMORY Out of memory + * @see parcel_destroy() + */ +int parcel_create(parcel_h *parcel); + +/** + * @brief Destroys a parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER + * @see parcel_create() + */ +int parcel_destroy(parcel_h parcel); + +/** + * @brief Creates and returns a copy of the given parcel handle. + * @since_tizen 6.5 + * @remarks A newly created parcel should be destroyed by calling the parcel_destroy() if it is no longer needed. + * @param[in] parcel The parcel handle + * @param[out] If successful, a newly created parcel handle will be returned + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_destroy() + */ +int parcel_clone(parcel_h parcel, parcel_h *clone); + +/** + * @brief Writes bytes to the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] buf The array buffer to write + * @param[in] size The size of bytes to write + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_burst_read() + */ +int parcel_burst_write(parcel_h parcel, const void *buf, uint32_t size); + +/** + * @brief Reads bytes from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] buf The array buffer to read + * @param[in] size The size of bytes to read + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_burst_write() + */ +int parcel_burst_read(parcel_h parcel, void *buf, uint32_t size); + +/** + * @brief Writes a boolean value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The boolean value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_bool() + */ +int parcel_write_bool(parcel_h parcel, bool val); + +/** + * @brief Writes a byte value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The byte value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_uint8() + */ +int parcel_write_byte(parcel_h parcel, char val); + +/** + * @brief Writes an unsigned short value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The unsigned short value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_uint16() + */ +int parcel_write_uint16(parcel_h parcel, uint16_t val); + +/** + * @brief Writes an unsigned integer value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The unsigned integer value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_uint32() + */ +int parcel_write_uint32(parcel_h parcel, uint32_t val); + +/** + * @brief Writes an unsigned long long integer value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The unsigned long long interger value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_uint64() + */ +int parcel_write_uint64(parcel_h parcel, uint64_t val); + +/** + * @brief Writes a signed short value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The signed short value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_int16() + */ +int parcel_write_int16(parcel_h parcel, int16_t val); + +/** + * @brief Writes a signed integer value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The signed integer value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_int32() + */ +int parcel_write_int32(parcel_h parcel, int32_t val); + +/** + * @brief Writes a signed long long integer value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The signedi long long integer value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_int64() + */ +int parcel_write_int64(parcel_h parcel, int64_t val); + +/** + * @brief Writes a floating point value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The floating point value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCLE_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_float() + */ +int parcel_write_float(parcel_h parcel, float val); + +/** + * @brief Writes a double precision floating point value into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] val The double precision floating point value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCLE_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_double() + */ +int parcel_write_double(parcel_h parcel, double val); + +/** + * @brief Writes a string data into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] str The string data + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_string() + */ +int parcel_write_string(parcel_h parcel, const char *str); + +/** + * @brief Writes a bundle data into the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] b The bundle data + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read_bundle() + */ +int parcel_write_bundle(parcel_h parcel, bundle* b); + +/** + * @brief Reads a boolean value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The boolean value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_bool() + */ +int parcel_read_bool(parcel_h parcel, bool *val); + +/** + * @brief Reads a byte value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The byte value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_uint8() + */ +int parcel_read_byte(parcel_h parcel, char *val); + +/** + * @brief Reads an unsigned short value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The unsigned short value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_uint16() + */ +int parcel_read_uint16(parcel_h parcel, uint16_t *val); + +/** + * @brief Reads an unsigned integer value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The unsigned integer value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_uint32() + */ +int parcel_read_uint32(parcel_h parcel, uint32_t *val); + +/** + * @brief Reads an unsigned long long integer value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The unsigned long long integer value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_uint64() + */ +int parcel_read_uint64(parcel_h parcel, uint64_t *val); + +/** + * @brief Reads a signed short value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The signed short value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_int16() + */ +int parcel_read_int16(parcel_h parcel, int16_t *val); + +/** + * @brief Reads a signed integer value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The signed integer value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_int32() + */ +int parcel_read_int32(parcel_h parcel, int32_t *val); + +/** + * @brief Reads a signed long long integer value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The signed long long integer value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_int64() + */ +int parcel_read_int64(parcel_h parcel, int64_t *val); + +/** + * @brief Reads a floating point value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The floating point value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_uint8() + */ +int parcel_read_float(parcel_h parcel, float *val); + +/** + * @brief Reads a double precision floating point value from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The double precision floating point value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @see parcel_write_uint8() + */ +int parcel_read_double(parcel_h parcel, double *val); + +/** + * @brief Reads a string data from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] str The string data + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @retval #PARCEL_ERROR_OUT_OF_MEMORY Out of memory + * @see parcel_write_uint8() + */ +int parcel_read_string(parcel_h parcel, char **str); + +/** + * @brief Reads a bundle data from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[out] val The bundle data + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PARCEL_ERROR_NO_DATA No data available + * @retval #PARCEL_ERROR_ILLEGAL_BYTE_SEQ Illegal byte sequence + * @retval #PARCEL_ERROR_OUT_OF_MEMORY Out of memory + * @see parcel_write_uint8() + */ +int parcel_read_bundle(parcel_h parcel, bundle **b); + +/** + * @brief Resets the reader pointer of the parcel handle to the start. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + */ +int parcel_reset_reader(parcel_h parcel); + +/** + * @brief Clears the data of the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + */ +int parcel_clear(parcel_h parcel); + +/** + * @brief Resets the data of the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] buf The array buffer to write + * @param[in] size The size of bytes to write + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + */ +int parcel_reset(parcel_h parcel, const void *buf, uint32_t size); + +/** + * @brief Writes the data using @a parcelable to the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] parcelable The interface to write the data into the parcel handle + * @param[in] data The user data which writes into the parcel handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_read() + */ +int parcel_write(parcel_h parcel, parcelable_t *parcelable, void *data); + +/** + * @brief Reads the data using @a parcelable from the parcel handle. + * @since_tizen 6.5 + * @param[in] parcel The parcel handle + * @param[in] parcelable The interface to read the data from the parcel handle + * @param[in] data The user data which reads from the parcel handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + * @see parcel_write() + */ +int parcel_read(parcel_h parcel, parcelable_t *parcelable, void *data); + +/** + * @brief Gets the raw data of the parcel handle. + * @since_tizen 6.5 + * @remarks You MUST NOT release @a raw using free(). It's managed by platform. + * @param[in] parcel The parcel handle + * @param[out] raw The raw data + * @param[out] size The size of the raw data + * @return @c 0 on success, + * otherwise a negative error value + * @retval #PARCEL_ERROR_NONE Successful + * @retval #PARCEL_ERROR_INVALID_PARAMETER Invalid parameter + */ +int parcel_get_raw(parcel_h parcel, void **raw, uint32_t *size); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* __PARCEL_H__ */ diff --git a/parcel/common.hh b/parcel/common.hh new file mode 100644 index 0000000..91f3535 --- /dev/null +++ b/parcel/common.hh @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#ifndef PARCEL_COMMON_HH_ +#define PARCEL_COMMON_HH_ + +#undef EXPORT +#define EXPORT __attribute__((visibility("default"))) + +#endif // PARCEL_COMMON_HH_ diff --git a/parcel/log_private.hh b/parcel/log_private.hh new file mode 100644 index 0000000..a005add --- /dev/null +++ b/parcel/log_private.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#ifndef PARCEL_LOG_PRIVATE_HH_ +#define PARCEL_LOG_PRIVATE_HH_ + +#include + +#undef LOG_TAG +#define LOG_TAG "PARCEL" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // PARCEL_LOG_PRIVATE_HH_ diff --git a/parcel/parcel.cc b/parcel/parcel.cc new file mode 100644 index 0000000..e310654 --- /dev/null +++ b/parcel/parcel.cc @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#include "include/bundle_cpp.h" +#include "parcel/common.hh" +#include "parcel/log_private.hh" +#include "parcel/parcel.hh" +#include "parcel/parcel_implementation.hh" +#include "parcel/parcelable.hh" + +namespace tizen_base { + +Parcel::Impl::Impl(Parcel* parent) : parent_(parent) { +} + +Parcel::Impl::~Impl() = default; + +void Parcel::Impl::Write(const void* buf, uint32_t size) { + auto* p = reinterpret_cast(buf); + std::copy(p, p + size, std::back_inserter(data_)); +} + +int Parcel::Impl::Read(void* buf, uint32_t size) { + if (data_.size() == 0) + return TIZEN_ERROR_NO_DATA; + + if (reader_ + size > data_.size()) + return TIZEN_ERROR_ILLEGAL_BYTE_SEQ; + + auto* p = reinterpret_cast(buf); + std::copy(&data_[reader_], &data_[reader_] + size, p); + reader_ += size; + set_last_result(TIZEN_ERROR_NONE); + return TIZEN_ERROR_NONE; +} + +const std::vector& Parcel::Impl::GetRaw() { + return data_; +} + +void Parcel::Impl::ResetReader() { + reader_ = 0; +} + +void Parcel::Impl::Clear() { + data_.clear(); + reader_ = 0; +} + +void Parcel::Impl::Reset(const void* buf, uint32_t size) { + Clear(); + Write(buf, size); +} + +bool Parcel::Impl::IsEmpty() { + return data_.size() == 0; +} + +void Parcel::Impl::WriteSize(uint32_t size) { + auto* p = reinterpret_cast(&size); + std::copy(p, p + sizeof(size), std::back_inserter(data_)); +} + +template +void Parcel::Impl::Write(T d) { + WriteSize(sizeof(T)); + auto* p = reinterpret_cast(&d); + std::copy(p, p + sizeof(T), std::back_inserter(data_)); +} + +int Parcel::Impl::ReadSize(uint32_t* size) { + if (data_.size() == 0) + return TIZEN_ERROR_NO_DATA; + + if (reader_ + sizeof(uint32_t) > data_.size()) + return TIZEN_ERROR_ILLEGAL_BYTE_SEQ; + + auto* p = reinterpret_cast(size); + std::copy(&data_[reader_], &data_[reader_] + sizeof(uint32_t), p); + reader_ += sizeof(uint32_t); + return TIZEN_ERROR_NONE; +} + +template +int Parcel::Impl::Read(T* d) { + uint32_t size = 0; + int ret = ReadSize(&size); + if (ret != TIZEN_ERROR_NONE) + return ret; + + if (size == 0 || size != sizeof(T)) + return TIZEN_ERROR_ILLEGAL_BYTE_SEQ; + + if (reader_ + size > data_.size()) + return TIZEN_ERROR_ILLEGAL_BYTE_SEQ; + + auto* p = reinterpret_cast(d); + std::copy(&data_[reader_], &data_[reader_] + size, p); + reader_ += size; + return TIZEN_ERROR_NONE; +} + +Parcel::Parcel() : impl_(new Impl(this)) { +} + +Parcel::Parcel(const void* buf, uint32_t size) : impl_(new Impl(this)) { + impl_->Write(buf, size); +} + +Parcel::~Parcel() = default; + +Parcel::Parcel(const Parcel& p) + : impl_(new Impl(this)) { + std::copy(p.impl_->data_.begin(), p.impl_->data_.end(), + std::back_inserter(impl_->data_)); + impl_->reader_ = p.impl_->reader_; +} + +Parcel& Parcel::operator = (const Parcel& p) { + if (this != &p) { + std::copy(p.impl_->data_.begin(), p.impl_->data_.end(), + std::back_inserter(impl_->data_)); + impl_->reader_ = p.impl_->reader_; + } + return *this; +} + +Parcel::Parcel(Parcel&& p) noexcept { + impl_ = std::move(p.impl_); + impl_->parent_ = this; +} + +Parcel& Parcel::operator = (Parcel&& p) noexcept { + if (this != &p) { + impl_->data_ = std::move(p.impl_->data_); + impl_->reader_ = p.impl_->reader_; + p.impl_->reader_ = 0; + } + return *this; +} + +bool Parcel::IsEmpty() const noexcept { + return impl_->IsEmpty(); +} + +void Parcel::Write(const void* buf, uint32_t size) { + impl_->Write(buf, size); +} + +int Parcel::Read(void* buf, uint32_t size) { + return impl_->Read(buf, size); +} + +void Parcel::WriteBool(bool val) { + impl_->Write(val); +} + +void Parcel::WriteByte(char val) { + impl_->Write(val); +} + +void Parcel::WriteUInt16(uint16_t val) { + impl_->Write(val); +} + +void Parcel::WriteUInt32(uint32_t val) { + impl_->Write(val); +} + +void Parcel::WriteUInt64(uint64_t val) { + impl_->Write(val); +} + +void Parcel::WriteInt16(int16_t val) { + impl_->Write(val); +} + +void Parcel::WriteInt32(int32_t val) { + impl_->Write(val); +} + +void Parcel::WriteInt64(int64_t val) { + impl_->Write(val); +} + +void Parcel::WriteFloat(float val) { + impl_->Write(val); +} + +void Parcel::WriteDouble(double val) { + impl_->Write(val); +} + +void Parcel::WriteString(const std::string& str) { + impl_->WriteSize(str.length() + 1); + impl_->Write(str.c_str(), str.length() + 1); +} + +void Parcel::WriteCString(const char* str) { + impl_->WriteSize(strlen(str) + 1); + impl_->Write(str, strlen(str) + 1); +} + +void Parcel::WriteCBundle(bundle* b) { + bundle_raw* raw = nullptr; + int len = 0; + bundle_encode(b, &raw, &len); + auto ptr = std::unique_ptr(raw, std::free); + + auto* p = reinterpret_cast(raw); + impl_->WriteSize(len + 1); + impl_->Write(p, len + 1); +} + +void Parcel::WriteBundle(const Bundle& b) { + auto raw = const_cast(b).ToRaw(); + auto* p = reinterpret_cast(raw.first.get()); + impl_->WriteSize(raw.second + 1); + impl_->Write(p, raw.second + 1); +} + +int Parcel::ReadBool(bool* val) { + return impl_->Read(val); +} + +int Parcel::ReadByte(char* val) { + return impl_->Read(val); +} + +int Parcel::ReadUInt16(uint16_t* val) { + return impl_->Read(val); +} + +int Parcel::ReadUInt32(uint32_t* val) { + return impl_->Read(val); +} + +int Parcel::ReadUInt64(uint64_t* val) { + return impl_->Read(val); +} + +int Parcel::ReadInt16(int16_t* val) { + return impl_->Read(val); +} + +int Parcel::ReadInt32(int32_t* val) { + return impl_->Read(val); +} + +int Parcel::ReadInt64(int64_t* val) { + return impl_->Read(val); +} + +int Parcel::ReadFloat(float* val) { + return impl_->Read(val); +} + +int Parcel::ReadDouble(double* val) { + return impl_->Read(val); +} + +std::string Parcel::ReadString() { + uint32_t len = 0; + int ret = impl_->ReadSize(&len); + if (ret != TIZEN_ERROR_NONE) { + set_last_result(ret); + return {}; + } + + char* str = new (std::nothrow) char [len]; + if (str == nullptr) { + set_last_result(TIZEN_ERROR_OUT_OF_MEMORY); + return {}; + } + + auto ptr = std::unique_ptr(str); + ret = impl_->Read(str, len); + if (ret != TIZEN_ERROR_NONE) { + set_last_result(ret); + return {}; + } + + set_last_result(TIZEN_ERROR_NONE); + return std::string(str); +} + +int Parcel::ReadCString(char** str) { + uint32_t len = 0; + int ret = impl_->ReadSize(&len); + if (ret != TIZEN_ERROR_NONE) + return ret; + + char* val = static_cast(calloc(len, sizeof(char))); + if (val == nullptr) + return TIZEN_ERROR_OUT_OF_MEMORY; + + ret = impl_->Read(val, len); + if (ret != TIZEN_ERROR_NONE) { + free(val); + return ret; + } + + *str = val; + return TIZEN_ERROR_NONE; +} + +int Parcel::ReadCBundle(bundle** b) { + uint32_t len = 0; + int ret = impl_->ReadSize(&len); + if (ret != TIZEN_ERROR_NONE) + return ret; + + uint8_t* raw = new (std::nothrow) uint8_t [len]; + if (raw == nullptr) + return TIZEN_ERROR_OUT_OF_MEMORY; + + auto ptr = std::unique_ptr(raw); + ret = impl_->Read(raw, len); + if (ret != TIZEN_ERROR_NONE) + return ret; + + *b = bundle_decode(reinterpret_cast(raw), len); + if (*b == nullptr) + return get_last_result(); + + return TIZEN_ERROR_NONE; +} + +Bundle Parcel::ReadBundle() { + uint32_t len = 0; + int ret = impl_->ReadSize(&len); + if (ret != TIZEN_ERROR_NONE) { + set_last_result(ret); + return {}; + } + + uint8_t* raw = new (std::nothrow) uint8_t [len]; + if (raw == nullptr) { + set_last_result(TIZEN_ERROR_OUT_OF_MEMORY); + return {}; + } + + auto ptr = std::unique_ptr(raw); + ret = impl_->Read(raw, len); + if (ret != TIZEN_ERROR_NONE) { + set_last_result(ret); + return {}; + } + + bundle* b = bundle_decode(reinterpret_cast(raw), len); + if (b == nullptr) + return {}; + + set_last_result(TIZEN_ERROR_NONE); + return Bundle(b, false, true); +} + +const std::vector& Parcel::GetRaw() { + return impl_->GetRaw(); +} + +void Parcel::ResetReader() { + impl_->ResetReader(); +} + +void Parcel::Clear() { + impl_->Clear(); +} + +void Parcel::Reset(const void* buf, uint32_t size) { + impl_->Reset(buf, size); +} + +void Parcel::WriteParcelable(const Parcelable& parcelable) { + impl_->Write(1); + parcelable.WriteToParcel(this); +} + +int Parcel::ReadParcelable(Parcelable* parcelable) { + int32_t has_parcelable = 0; + int ret = impl_->Read(&has_parcelable); + if (ret != TIZEN_ERROR_NONE) + return ret; + + if (has_parcelable != 1) + return TIZEN_ERROR_ILLEGAL_BYTE_SEQ; + + parcelable->ReadFromParcel(this); + return TIZEN_ERROR_NONE; +} + +} // naemspace tizen_base diff --git a/parcel/parcel.hh b/parcel/parcel.hh new file mode 100644 index 0000000..1b5f731 --- /dev/null +++ b/parcel/parcel.hh @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#ifndef PARCEL_PARCEL_HH_ +#define PARCEL_PARCEL_HH_ + +/** + * @addtogroup CORE_LIB_PARCEL_MODULE + * @{ + */ + +#include +#include + +#include +#include +#include + +#include "parcel/common.hh" +#include "parcel/parcelable.hh" + +namespace tizen_base { + +/** + * @brief The class for Parcel API. + * @since_tizen 6.5 + */ +class EXPORT Parcel final { + public: + /** + * @brief Enumeration for parcel error. + * @since_tizen 6.5 + */ + enum Error { + None = TIZEN_ERROR_NONE, /**< Successful */ + IllegalByteSeq = TIZEN_ERROR_ILLEGAL_BYTE_SEQ, /**< Illegal byte sequence */ + InvalidParameter = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + NoData = TIZEN_ERROR_NO_DATA, /**< No data available */ + OutOfMemory = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + }; + + /** + * @brief Constructor. + * @since_tizen 6.5 + */ + Parcel(); + + /** + * @brief Constructor + * @since_tizen 6.5 + * @param[in] buf The bytes to write + * @param[in] size the size of bytes to write + */ + Parcel(const void* buf, uint32_t size); + + /** + * @brief Destructor + * @since_tizen 6.5 + */ + ~Parcel(); + + /** + * @brief Copy-constructor. + * @since_tizen 6.5 + * @param[in] p The object to copy + */ + Parcel(const Parcel& p); + + /** + * @brief Assignment. + * @since_tizen 6.5 + * @param[in] b The object to copy + */ + Parcel& operator = (const Parcel& p); + + /** + * @brief Move-constructor. + * @since_tizen 6.5 + * @param[in] p The object to move + */ + Parcel(Parcel&& p) noexcept; + + /** + * @brief Assignment. + * @since_tizen 6.5 + * @param[in] p The object to move + */ + Parcel& operator = (Parcel&& p) noexcept; + + /** + * @brief Checks the parcel is empty or not. + * @since_tizen 6.5 + * @return true if the parcel is empty + */ + bool IsEmpty() const noexcept; + + /** + * @brief Writes bytes into the parcel. + * @since_tizen 6.5 + * @param[in] buf The bytes to write + * @param[in] size The size of bytes to write + */ + void Write(const void* buf, uint32_t size); + + /** + * @brief Reads bytes from the parcel. + * @since_tizen 6.5 + * @param[out] buf The bytes to read + * @param[in] size The size of bytes to read + * @return @c 0 on success, + * otherwise a negative error value + */ + int Read(void* buf, uint32_t size); + + /** + * @brief Writes a boolean value into the parcel. + * @since_tizen 6.5 + * @param[in] val The boolean value + */ + void WriteBool(bool val); + + /** + * @brief Writes a byte value into the parcel. + * @since_tizen 6.5 + * @param[in] val The unsigned byte value + */ + void WriteByte(char byte); + + /** + * @brief Writes an unsigned short value into the parcel. + * @since_tizen 6.5 + * @param[in] val The unsigned short value + */ + void WriteUInt16(uint16_t val); + + /** + * @brief Writes an unsigned integer value into the parcel. + * @since_tizen 6.5 + * @param[in] val The unsigned integer value + */ + void WriteUInt32(uint32_t val); + + /** + * @brief Writes an unsigned long long integer into the parcel. + * @since_tizen 6.5 + * @param[in] val The unsigned long long integer value + */ + void WriteUInt64(uint64_t val); + + /** + * @brief Writes a signed short value into the parcel. + * @since_tizen 6.5 + * @param[in] val The signed short value + */ + void WriteInt16(int16_t val); + + /** + * @brief Writes a signed integer value into the parcel. + * @since_tizen 6.5 + * @param[in] val The signed integer value + */ + void WriteInt32(int32_t val); + + /** + * @brief Writes a signed long long integer value into the parcel. + * @since_tizen 6.5 + * @param[in] val The signed long long integer value + */ + void WriteInt64(int64_t val); + + /** + * @brief Writes a floating point value into the parcel. + * @since_tizen 6.5 + * @param[in] val The floating point value + */ + void WriteFloat(float val); + + /** + * @brief Writes a double precision floating point value into the parcel. + * @since_tizen 6.5 + * @param[in] val The double precision floating point value + */ + void WriteDouble(double val); + + /** + * @brief Writes a string data into the parcel. + * @since_tizen 6.5 + * @param[in] str The string data + */ + void WriteString(const std::string& str); + + /** + * @brief Writes a string data into the parcel. + * @since_tizen 6.5 + * @param[in] str The string data + */ + void WriteCString(const char* str); + + /** + * @brief Writes a bundle data into the parcel. + * @since_tizen 6.5 + * @param[in] b The bundle data + */ + void WriteCBundle(bundle* b); + + /** + * @brief Writes a bundle data into the parcel. + * @since_tizen 6.5 + * @param[in] b The bundle data + */ + void WriteBundle(const Bundle& b); + + /** + * @brief Reads a boolean value from the parcel. + * @since_tizen 6.5 + * @param[out] val The boolean value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadBool(bool* val); + + /** + * @brief Reads a byte value from the parcel. + * @since_tizen 6.5 + * @param[out] val The unsigned byte value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadByte(char* val); + + /** + * @breif Reads an unsigned short value from the parcel. + * @since_tizen 6.5 + * @param[out] val The unsigned short value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadUInt16(uint16_t* val); + + /** + * @brief Reads an unsigned integer value from the parcel. + * @since_tizen 6.5 + * @param[out] val The unsigned integer value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadUInt32(uint32_t* val); + + /** + * @brief Reads an unsigned long long integer value from the parcel. + * @since_tizen 6.5 + * @param[out] val The unsigned long long integer value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadUInt64(uint64_t* val); + + /** + * @brief Reads a signed byte value from the parcel. + * @since_tizen 6.5 + * @param[out] val The signed byte value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadInt8(int8_t* val); + + /** + * @brief Reads a signed short value from the parcel. + * @since_tizen 6.5 + * @param[out] val The signed short value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadInt16(int16_t* val); + + /** + * @brief Reads a signed integer value from the parcel. + * @since_tizen 6.5 + * @param[out] val The signed integer value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadInt32(int32_t* val); + + /** + * @brief Reads a signed long long integer value from the parcel. + * @since_tizen 6.5 + * @param[out] val The signed long long integer value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadInt64(int64_t* val); + + /** + * @brief Reads a floating point value from the parcel. + * @since_tizen 6.5 + * @param[out] val The floating point value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadFloat(float* val); + + /** + * @brief Reads a double precision floating point value from the parcel. + * @since_tizen 6.5 + * @param[out] val The double precision floating point value + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadDouble(double* val); + + /** + * @brief Reads a string data from the parcel. + * @since_tizen 6.5 + * @return The string data + * @remarks Before using the returned value, you should check the result using get_last_result(). + * @see get_last_result() + */ + std::string ReadString(); + + /** + * @brief Reads a string data from the parcel. + * @since_tizen 6.5 + * @remarks You should release @a str using free(). + * @param[out] str The string data + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadCString(char** str); + + /** + * @brief Reads a bundle data from the parcel. + * @since_tizen 6.5 + * @remarks You should release @a b using bundle_free(). + * @param[out] b The bundle data + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadCBundle(bundle** b); + + /** + * @brief Reads a bundle data from the parcel. + * @since_tizen 6.5 + * @return The bundle data + * @remarks Before using the returned value, you should check the result using get_last_result(). + * @see get_last_result(); + */ + Bundle ReadBundle(); + + /** + * @brief Gets the raw data of the parcel. + * @since_tizen 6.5 + * @return The raw data + */ + const std::vector& GetRaw(); + + /** + * @brief Resets the reader pointer of the parcel to the start. + * @since_tizen 6.5 + */ + void ResetReader(); + + /** + * @brief Clears the data of the parcel. + * @since_tizen 6.5 + */ + void Clear(); + + /** + * @brief Resets the parcel. + * @since_tizen 6.5 + * @param[in] buf The bytes to write + * @param[in] size The size of bytes to write + */ + void Reset(const void* buf, uint32_t size); + + /** + * @brief Writes the data using @a parcelable into the parcel. + * @since_tizen 6.5 + * @param[in] parcelable The interface to write the data into the parcel + */ + void WriteParcelable(const Parcelable& parcelable); + + /** + * @brief Reads the data using @a parcelable from the parcel. + * @since_tizen 6.5 + * @param[out] parcelable The interface to get data from the parcel + * @return @c 0 on success, + * otherwise a negative error value + */ + int ReadParcelable(Parcelable* parcelable); + + private: + class Impl; + std::unique_ptr impl_; +}; + +} // naemspace tizen_base + +/** + * @} + */ + +#endif // PARCEL_PARCEL_HH_ diff --git a/parcel/parcel.pc.in b/parcel/parcel.pc.in new file mode 100644 index 0000000..56f44e8 --- /dev/null +++ b/parcel/parcel.pc.in @@ -0,0 +1,14 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=${prefix} +libdir=@LIB_INSTALL_DIR@ +includedir=${prefix}/include + +Name: parcel +Description: Parcel library +Version: @VERSION@ +Requires: capi-base-common +Libs: -L${libdir} -lparcel -lbundle +Cflags: -I${includedir} -I${includedir}/parcel +cppflags: -I${includedir} -I${includedir}/parcel diff --git a/parcel/parcel_implementation.hh b/parcel/parcel_implementation.hh new file mode 100644 index 0000000..5ae09c5 --- /dev/null +++ b/parcel/parcel_implementation.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#ifndef PARCEL_PARCEL_IMPLEMENTATION_HH_ +#define PARCEL_PARCEL_IMPLEMENTATION_HH_ + +#include +#include + +#include "parcel/parcel.hh" +#include "parcel/parcelable.hh" + +namespace tizen_base { + +class Parcel::Impl { + public: + virtual ~Impl(); + + void Write(const void* buf, uint32_t size); + int Read(void* buf, uint32_t size); + const std::vector& GetRaw(); + void ResetReader(); + void Clear(); + void Reset(const void* buf, uint32_t size); + bool IsEmpty(); + void WriteSize(uint32_t size); + int ReadSize(uint32_t* size); + + template + void Write(T d); + template + int Read(T* d); + + private: + friend class Parcel; + explicit Impl(Parcel* parent); + + private: + Parcel* parent_; + std::vector data_; + uint64_t reader_ = 0; +}; + +} // naemspace tizen_base + +#endif // PARCEL_PARCEL_IMPLEMENTATION_HH_ diff --git a/parcel/parcelable.hh b/parcel/parcelable.hh new file mode 100644 index 0000000..6dc9471 --- /dev/null +++ b/parcel/parcelable.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#ifndef PARCEL_PARCELABLE_HH_ +#define PARCEL_PARCELABLE_HH_ + +/** + * @addtogroup CORE_LIB_PARCEL_MODULE + * @{ + */ + +#include "parcel/common.hh" + +namespace tizen_base { + +class Parcel; + +/** + * @brief The Parcelable interface. + * @since_tizen 6.5 + */ +class EXPORT Parcelable { + public: + /** + * @brief Constructor. + * @since_tizen 6.5 + */ + Parcelable() = default; + + /** + * @brief Copy constructor. + * @since_tizen 6.5 + */ + Parcelable(const Parcelable&) = default; + + /** + * @brief Destructor. + * @since_tizen 6.5 + */ + virtual ~Parcelable() = default; + + /** + * @brief Writes the data into the parcel. + * @since_tizen 6.5 + * @param[in] parcel The parcel object + */ + virtual void WriteToParcel(Parcel* parcel) const = 0; + + /** + * @brief Reads the data from the parcel. + * @since_tizen 6.5 + * @param[in] parcel The parcel object + */ + virtual void ReadFromParcel(Parcel* parcel) = 0; +}; + +} // naemspace tizen_base + +/** + * @} + */ + +#endif // PARCEL_PARCELABLE_HH_ diff --git a/parcel/stub.cc b/parcel/stub.cc new file mode 100644 index 0000000..24ec529 --- /dev/null +++ b/parcel/stub.cc @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +#include "parcel/api/parcel.h" +#include "parcel/common.hh" +#include "parcel/log_private.hh" +#include "parcel/parcel.hh" +#include "parcel/parcelable.hh" + +using namespace tizen_base; + +extern "C" EXPORT int parcel_create(parcel_h *parcel) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = new (std::nothrow) Parcel(); + if (h == nullptr) { + _E("Out of memory"); + return PARCEL_ERROR_OUT_OF_MEMORY; + } + + *parcel = static_cast(h); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_destroy(parcel_h parcel) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + delete h; + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_clone(parcel_h parcel, parcel_h* clone) { + if (parcel == nullptr || clone == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + auto* c = new (std::nothrow) Parcel(*h); + if (c == nullptr) { + _E("Out of memory"); + return PARCEL_ERROR_OUT_OF_MEMORY; + } + + *clone = static_cast(c); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_burst_write(parcel_h parcel, const void *buf, + uint32_t size) { + if (parcel == nullptr || buf == nullptr || size == 0) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->Write(buf, size); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_burst_read(parcel_h parcel, void *buf, + uint32_t size) { + if (parcel == nullptr || buf == nullptr || size == 0) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->Read(buf, size); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_bool(parcel_h parcel, bool val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteBool(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_byte(parcel_h parcel, char val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteByte(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_uint16(parcel_h parcel, uint16_t val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteUInt16(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_uint32(parcel_h parcel, uint32_t val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteUInt32(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_uint64(parcel_h parcel, uint64_t val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteUInt64(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_int16(parcel_h parcel, int16_t val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteInt16(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_int32(parcel_h parcel, int32_t val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteInt32(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_int64(parcel_h parcel, int64_t val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteInt64(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_float(parcel_h parcel, float val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteFloat(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_double(parcel_h parcel, double val) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteDouble(val); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_string(parcel_h parcel, const char* str) { + if (parcel == nullptr || str == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteCString(str); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write_bundle(parcel_h parcel, bundle* b) { + if (parcel == nullptr || b == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->WriteCBundle(b); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_read_bool(parcel_h parcel, bool* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadBool(val); +} + +extern "C" EXPORT int parcel_read_byte(parcel_h parcel, char* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadByte(val); +} + +extern "C" EXPORT int parcel_read_uint16(parcel_h parcel, uint16_t* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadUInt16(val); +} + +extern "C" EXPORT int parcel_read_uint32(parcel_h parcel, uint32_t* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadUInt32(val); +} + +extern "C" EXPORT int parcel_read_uint64(parcel_h parcel, uint64_t* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadUInt64(val); +} + +extern "C" EXPORT int parcel_read_int16(parcel_h parcel, int16_t* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadInt16(val); +} + +extern "C" EXPORT int parcel_read_int32(parcel_h parcel, int32_t* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadInt32(val); +} + +extern "C" EXPORT int parcel_read_int64(parcel_h parcel, int64_t* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadInt64(val); +} + +extern "C" EXPORT int parcel_read_float(parcel_h parcel, float* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadFloat(val); +} + +extern "C" EXPORT int parcel_read_double(parcel_h parcel, double* val) { + if (parcel == nullptr || val == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadDouble(val); +} + +extern "C" EXPORT int parcel_read_string(parcel_h parcel, char** str) { + if (parcel == nullptr || str == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadCString(str); +} + +extern "C" EXPORT int parcel_read_bundle(parcel_h parcel, bundle** b) { + if (parcel == nullptr || b == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + return h->ReadCBundle(b); +} + +extern "C" EXPORT int parcel_reset_reader(parcel_h parcel) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->ResetReader(); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_clear(parcel_h parcel) { + if (parcel == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->Clear(); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_reset(parcel_h parcel, const void* buf, + uint32_t size) { + if (parcel == nullptr || buf == nullptr || size == 0) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + h->Reset(buf, size); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_write(parcel_h parcel, parcelable_t* parcelable, + void* data) { + if (parcel == nullptr || parcelable == nullptr || parcelable->to == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + parcelable->to(parcel, data); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_read(parcel_h parcel, parcelable_t* parcelable, + void* data) { + if (parcel == nullptr || parcelable == nullptr || + parcelable->from == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + parcelable->from(parcel, data); + return PARCEL_ERROR_NONE; +} + +extern "C" EXPORT int parcel_get_raw(parcel_h parcel, void** raw, + uint32_t* size) { + if (parcel == nullptr || raw == nullptr || size == nullptr) { + _E("Invalid parameter"); + return PARCEL_ERROR_INVALID_PARAMETER; + } + + auto* h = static_cast(parcel); + auto& raw_data = h->GetRaw(); + *raw = reinterpret_cast(const_cast(&raw_data[0])); + *size = raw_data.size(); + return PARCEL_ERROR_NONE; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..30c8c6f --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,2 @@ +ADD_SUBDIRECTORY(bundle_unittests) +ADD_SUBDIRECTORY(parcel_unittests) diff --git a/unit_tests/CMakeLists.txt b/tests/bundle_unittests/CMakeLists.txt similarity index 69% rename from unit_tests/CMakeLists.txt rename to tests/bundle_unittests/CMakeLists.txt index 064f946..a7eb6d5 100644 --- a/unit_tests/CMakeLists.txt +++ b/tests/bundle_unittests/CMakeLists.txt @@ -19,19 +19,17 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_CXX_FLAGS_RELEASE "-O2") -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../src) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../bundle) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../bundle) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src UNITTESTS_SOURCES) -AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../src BUNDLE_SOURCES) -AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../bundle BUNDLE_INTERNAL_SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src BUNDLE_SOURCES) ADD_EXECUTABLE(${PROJECT_NAME} ${BUNDLE_SOURCES} - ${BUNDLE_INTERNAL_SOURCES} ${UNITTESTS_SOURCES} ) diff --git a/unit_tests/src/test_bundle.cc b/tests/bundle_unittests/src/test_bundle.cc similarity index 100% rename from unit_tests/src/test_bundle.cc rename to tests/bundle_unittests/src/test_bundle.cc diff --git a/unit_tests/src/test_bundle_cpp.cc b/tests/bundle_unittests/src/test_bundle_cpp.cc similarity index 100% rename from unit_tests/src/test_bundle_cpp.cc rename to tests/bundle_unittests/src/test_bundle_cpp.cc diff --git a/unit_tests/src/test_main.cc b/tests/bundle_unittests/src/test_main.cc similarity index 100% rename from unit_tests/src/test_main.cc rename to tests/bundle_unittests/src/test_main.cc diff --git a/tests/parcel_unittests/CMakeLists.txt b/tests/parcel_unittests/CMakeLists.txt new file mode 100644 index 0000000..d481e02 --- /dev/null +++ b/tests/parcel_unittests/CMakeLists.txt @@ -0,0 +1,42 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(parcel_unittests C CXX) + +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(parcel_unittests REQUIRED + capi-base-common + dlog + glib-2.0 + gmock + json-glib-1.0 +) + +FOREACH(flag ${parcel_unittests_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++14") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../parcel) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../parcel/api) + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ UNITTESTS_SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src BUNDLE_SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../parcel PARCEL_SOURCES) + +ADD_EXECUTABLE(${PROJECT_NAME} + ${BUNDLE_SOURCES} + ${PARCEL_SOURCES} + ${UNITTESTS_SOURCES} +) + +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS}") +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${parcel_unittests_LDFLAGS}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/) diff --git a/tests/parcel_unittests/test_main.cc b/tests/parcel_unittests/test_main.cc new file mode 100644 index 0000000..acd5cd8 --- /dev/null +++ b/tests/parcel_unittests/test_main.cc @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#include +#include + +#include + +int main(int argc, char** argv) { + try { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); + } catch (std::exception const &e) { + std::cout << "test_main caught exception: " << e.what() << std::endl; + return -1; + } +} diff --git a/tests/parcel_unittests/test_parcel.cc b/tests/parcel_unittests/test_parcel.cc new file mode 100644 index 0000000..2605c93 --- /dev/null +++ b/tests/parcel_unittests/test_parcel.cc @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#include +#include + +#include +#include +#include + +#include "parcel/api/parcel.h" + +class ParcelTest : public ::testing::Test { + public: + virtual void SetUp() { + parcel_create(&parcel_); + } + + virtual void TearDown() { + if (parcel_) + parcel_destroy(parcel_); + } + + parcel_h GetHandle() { + return parcel_; + } + + void SetHandle(parcel_h* parcel) { + parcel_ = parcel; + } + + private: + parcel_h parcel_ = nullptr; +}; + +TEST_F(ParcelTest, parcel_create_P) { + parcel_h parcel = nullptr; + int ret = parcel_create(&parcel); + auto ptr = std::unique_ptr::type, + decltype(parcel_destroy)*>(parcel, parcel_destroy); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_NE(parcel, nullptr); +} + +TEST_F(ParcelTest, parcel_create_N) { + int ret = parcel_create(nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_destroy_P) { + int ret = parcel_destroy(GetHandle()); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + SetHandle(nullptr); +} + +TEST_F(ParcelTest, parcel_destroy_N) { + int ret = parcel_destroy(nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_clone_P) { + parcel_h clone = nullptr; + int ret = parcel_clone(GetHandle(), &clone); + auto ptr = std::unique_ptr::type, + decltype(parcel_destroy)*>(clone, parcel_destroy); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_NE(clone, nullptr); +} + +TEST_F(ParcelTest, parcel_clone_N) { + int ret = parcel_clone(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_burst_write_P) { + char buf[1024] = { 1, }; + int ret = parcel_burst_write(GetHandle(), buf, sizeof(buf)); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char read_buf[1024]; + ret = parcel_burst_read(GetHandle(), read_buf, sizeof(read_buf)); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(read_buf[0], 1); +} + +TEST_F(ParcelTest, parcel_burst_write_N) { + int ret = parcel_burst_write(nullptr, nullptr, 0); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_burst_read_P) { + char buf[1024] = { 2, }; + int ret = parcel_burst_write(GetHandle(), buf, sizeof(buf)); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char read_buf[1024]; + ret = parcel_burst_read(GetHandle(), read_buf, sizeof(read_buf)); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(read_buf[0], 2); +} + +TEST_F(ParcelTest, parcel_burst_read_N) { + int ret = parcel_burst_read(nullptr, nullptr, 0); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_bool_P) { + int ret = parcel_write_bool(GetHandle(), true); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + bool val = false; + ret = parcel_read_bool(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, true); +} + +TEST_F(ParcelTest, parcel_write_bool_N) { + int ret = parcel_write_bool(nullptr, false); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_byte_P) { + int ret = parcel_write_byte(GetHandle(), 1); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char val = 0; + ret = parcel_read_byte(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_write_byte_N) { + int ret = parcel_write_byte(nullptr, 1); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_uint16_P) { + int ret = parcel_write_uint16(GetHandle(), 1); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + uint16_t val = 0; + ret = parcel_read_uint16(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_write_uint16_N) { + int ret = parcel_write_uint16(nullptr, 1); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_uint32_P) { + int ret = parcel_write_uint32(GetHandle(), 1); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + uint32_t val = 0; + ret = parcel_read_uint32(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_write_uint32_N) { + int ret = parcel_write_uint32(nullptr, 1); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_uint64_P) { + int ret = parcel_write_uint64(GetHandle(), 1); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + uint64_t val = 0; + ret = parcel_read_uint64(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_write_uint64_N) { + int ret = parcel_write_uint64(nullptr, 1); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_int16_P) { + int ret = parcel_write_int16(GetHandle(), 1); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + int16_t val = 0; + ret = parcel_read_int16(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_write_int16_N) { + int ret = parcel_write_int16(nullptr, 1); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_int32_P) { + int ret = parcel_write_int32(GetHandle(), 1); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + int32_t val = 0; + ret = parcel_read_int32(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_write_int32_N) { + int ret = parcel_write_int32(nullptr, 1); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_int64_P) { + int ret = parcel_write_int64(GetHandle(), 1); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + int64_t val = 0; + ret = parcel_read_int64(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_write_int64_N) { + int ret = parcel_write_int64(nullptr, 1); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_float_P) { + int ret = parcel_write_float(GetHandle(), 0.1f); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + float val = 0.0f; + ret = parcel_read_float(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 0.1f); +} + +TEST_F(ParcelTest, parcel_write_float_N) { + int ret = parcel_write_float(nullptr, 0.1f); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_double_P) { + int ret = parcel_write_double(GetHandle(), 0.1f); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + double val = 0.0f; + ret = parcel_read_double(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 0.1f); +} + +TEST_F(ParcelTest, parcel_write_double_N) { + int ret = parcel_write_double(nullptr, 0.1f); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_string_P) { + int ret = parcel_write_string(GetHandle(), "TestString"); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char* str = nullptr; + ret = parcel_read_string(GetHandle(), &str); + ASSERT_NE(str, nullptr); + auto ptr = std::unique_ptr(str, std::free); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(std::string(str), "TestString"); +} + +TEST_F(ParcelTest, parcel_write_string_N) { + int ret = parcel_write_string(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_write_bundle_P) { + bundle* b = bundle_create(); + bundle_add_str(b, "Key", "Value"); + int ret = parcel_write_bundle(GetHandle(), b); + bundle_free(b); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + b = nullptr; + ret = parcel_read_bundle(GetHandle(), &b); + ASSERT_NE(b, nullptr); + auto ptr = std::unique_ptr::type, + decltype(bundle_free)*>(b, bundle_free); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char* str = nullptr; + bundle_get_str(b, "Key", &str); + ASSERT_EQ(std::string(str), "Value"); +} + +TEST_F(ParcelTest, parcel_write_bundle_N) { + int ret = parcel_write_bundle(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_bool_P) { + int ret = parcel_write_bool(GetHandle(), false); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + bool val = true; + ret = parcel_read_bool(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, false); +} + +TEST_F(ParcelTest, parcel_read_bool_N) { + int ret = parcel_read_bool(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_byte_P) { + int ret = parcel_write_byte(GetHandle(), 2); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char val = 0; + ret = parcel_read_byte(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 2); +} + +TEST_F(ParcelTest, parcel_read_byte_N) { + int ret = parcel_read_byte(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_uint16_P) { + int ret = parcel_write_uint16(GetHandle(), 2); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + uint16_t val = 0; + ret = parcel_read_uint16(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 2); +} + +TEST_F(ParcelTest, parcel_read_uint16_N) { + int ret = parcel_read_uint16(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_uint32_P) { + int ret = parcel_write_uint32(GetHandle(), 2); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + uint32_t val = 0; + ret = parcel_read_uint32(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 2); +} + +TEST_F(ParcelTest, parcel_read_uint32_N) { + int ret = parcel_read_uint32(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_uint64_P) { + int ret = parcel_write_uint64(GetHandle(), 2); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + uint64_t val = 0; + ret = parcel_read_uint64(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 2); +} + +TEST_F(ParcelTest, parcel_read_uint64_N) { + int ret = parcel_read_uint64(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_int16_P) { + int ret = parcel_write_int16(GetHandle(), 2); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + int16_t val = 0; + ret = parcel_read_int16(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 2); +} + +TEST_F(ParcelTest, parcel_read_int16_N) { + int ret = parcel_read_int16(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_int32_P) { + int ret = parcel_write_int32(GetHandle(), 2); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + int32_t val = 0; + ret = parcel_read_int32(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 2); +} + +TEST_F(ParcelTest, parcel_read_int32_N) { + int ret = parcel_read_int32(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_int64_P) { + int ret = parcel_write_int64(GetHandle(), 2); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + int64_t val = 0; + ret = parcel_read_int64(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 2); +} + +TEST_F(ParcelTest, parcel_read_int64_N) { + int ret = parcel_read_int64(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_float_P) { + int ret = parcel_write_float(GetHandle(), 0.2f); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + float val = 0.0f; + ret = parcel_read_float(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 0.2f); +} + +TEST_F(ParcelTest, parcel_read_float_N) { + int ret = parcel_read_float(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_double_P) { + int ret = parcel_write_double(GetHandle(), 0.2f); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + double val = 0.0f; + ret = parcel_read_double(GetHandle(), &val); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 0.2f); +} + +TEST_F(ParcelTest, parcel_read_double_N) { + int ret = parcel_read_double(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_string_P) { + int ret = parcel_write_string(GetHandle(), "ReadCString"); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char* str = nullptr; + ret = parcel_read_string(GetHandle(), &str); + ASSERT_NE(str, nullptr); + auto ptr = std::unique_ptr(str, std::free); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(std::string(str), "ReadCString"); +} + +TEST_F(ParcelTest, parcel_read_string_N) { + int ret = parcel_read_string(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_bundle_P) { + bundle* b = bundle_create(); + bundle_add_str(b, "Key", "Value"); + int ret = parcel_write_bundle(GetHandle(), b); + bundle_free(b); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + b = nullptr; + ret = parcel_read_bundle(GetHandle(), &b); + ASSERT_NE(b, nullptr); + auto ptr = std::unique_ptr::type, + decltype(bundle_free)*>(b, bundle_free); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char* str = nullptr; + bundle_get_str(b, "Key", &str); + ASSERT_EQ(std::string(str), "Value"); +} + +TEST_F(ParcelTest, parcel_read_bundle_N) { + int ret = parcel_read_bundle(nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_reset_reader_P) { + int ret = parcel_reset_reader(GetHandle()); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); +} + +TEST_F(ParcelTest, parcel_reset_reader_N) { + int ret = parcel_reset_reader(nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_clear_P) { + int ret = parcel_clear(GetHandle()); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); +} + +TEST_F(ParcelTest, parcel_clear_N) { + int ret = parcel_clear(nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_reset_P) { + char buf[1024] = { 128, }; + int ret = parcel_reset(GetHandle(), buf, sizeof(buf)); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + char read_buf[1024] = { 0, }; + ret = parcel_burst_read(GetHandle(), read_buf, sizeof(read_buf)); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(read_buf[0], buf[0]); +} + +TEST_F(ParcelTest, parcel_reset_N) { + int ret = parcel_reset(nullptr, nullptr, 0); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +static void __write_to_parcel(parcel_h parcel, void* data) { + parcel_write_int32(parcel, 1); +} + +static void __read_from_parcel(parcel_h parcel, void* data) { + int32_t* val = static_cast(data); + parcel_read_int32(parcel, val); +} + +TEST_F(ParcelTest, parcel_write_P) { + parcelable_t parcelable = { + .to = __write_to_parcel, + .from = __read_from_parcel + }; + int ret = parcel_write(GetHandle(), &parcelable, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + int32_t val = 0; + ret = parcel_read(GetHandle(), &parcelable, static_cast(&val)); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_write_N) { + int ret = parcel_write(nullptr, nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_read_P) { + parcelable_t parcelable = { + .to = __write_to_parcel, + .from = __read_from_parcel + }; + int ret = parcel_write(GetHandle(), &parcelable, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + int32_t val = 0; + ret = parcel_read(GetHandle(), &parcelable, static_cast(&val)); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelTest, parcel_read_N) { + int ret = parcel_read(nullptr, nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} + +TEST_F(ParcelTest, parcel_get_raw_P) { + int ret = parcel_write_int32(GetHandle(), 1); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + uint8_t* raw = nullptr; + uint32_t size = 0; + ret = parcel_get_raw(GetHandle(), reinterpret_cast(&raw), &size); + ASSERT_EQ(ret, PARCEL_ERROR_NONE); + ASSERT_NE(raw, nullptr); + ASSERT_EQ(size, sizeof(uint32_t) + sizeof(int32_t)); +} + +TEST_F(ParcelTest, parcel_get_raw_N) { + int ret = parcel_get_raw(nullptr, nullptr, nullptr); + ASSERT_EQ(ret, PARCEL_ERROR_INVALID_PARAMETER); +} diff --git a/tests/parcel_unittests/test_parcel_cpp.cc b/tests/parcel_unittests/test_parcel_cpp.cc new file mode 100644 index 0000000..52c0c90 --- /dev/null +++ b/tests/parcel_unittests/test_parcel_cpp.cc @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#include +#include +#include +#include + +#include "parcel/parcel.hh" + +using ::testing::AtLeast; +using namespace tizen_base; + +class ParcelCppTest : public ::testing::Test { + public: + virtual void SetUp() { + } + + virtual void TearDown() { + parcel_.Clear(); + } + + Parcel& GetHandle() { + return parcel_; + } + + private: + Parcel parcel_; +}; + +class Student : public Parcelable { + public: + Student(std::string name, uint32_t age) + : name_(std::move(name)), age_(age) { + } + + Student() = default; + virtual ~Student() = default; + + const std::string& GetName() const { + return name_; + } + + uint32_t GetAge() const { + return age_; + } + + virtual void WriteToParcel(Parcel* parcel) const { + parcel->WriteString(name_); + parcel->WriteUInt32(age_); + } + + virtual void ReadFromParcel(Parcel* parcel) { + name_ = parcel->ReadString(); + parcel->ReadUInt32(&age_); + } + + private: + std::string name_; + uint32_t age_; +}; + +TEST_F(ParcelCppTest, Ctor_AND_Dtor) { + Parcel parcel; +} + +TEST_F(ParcelCppTest, Write_AND_Read) { + char buf[1024] = { 128, }; + GetHandle().Write(buf, sizeof(buf)); + char read_buf[1024] = { 0, }; + int ret = GetHandle().Read(read_buf, sizeof(read_buf)); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(buf[0], read_buf[0]); +} + +TEST_F(ParcelCppTest, WriteBool_AND_ReadBool) { + GetHandle().WriteBool(true); + bool val = false; + int ret = GetHandle().ReadBool(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, true); +} + +TEST_F(ParcelCppTest, WriteByte_AND_ReadByte) { + GetHandle().WriteByte(1); + char val = 0; + int ret = GetHandle().ReadByte(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelCppTest, WriteUInt16_AND_ReadUInt16) { + GetHandle().WriteUInt16(1); + uint16_t val = 0; + int ret = GetHandle().ReadUInt16(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelCppTest, WriteUInt32_AND_ReadUInt32) { + GetHandle().WriteUInt32(1); + uint32_t val = 0; + int ret = GetHandle().ReadUInt32(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelCppTest, WriteUInt64_AND_ReadUInt64) { + GetHandle().WriteUInt64(1); + uint64_t val = 0; + int ret = GetHandle().ReadUInt64(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelCppTest, WriteInt16_AND_ReadInt16) { + GetHandle().WriteInt16(1); + int16_t val = 0; + int ret = GetHandle().ReadInt16(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelCppTest, WriteInt32_AND_ReadInt32) { + GetHandle().WriteInt32(1); + int32_t val = 0; + int ret = GetHandle().ReadInt32(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelCppTest, WriteInt64_AND_ReadInt64) { + GetHandle().WriteInt64(1); + int64_t val = 0; + int ret = GetHandle().ReadInt64(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelCppTest, WriteFloat_AND_ReadFloat) { + GetHandle().WriteFloat(0.1f); + float val = 0.0f; + int ret = GetHandle().ReadFloat(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 0.1f); +} + +TEST_F(ParcelCppTest, WriteDouble_AND_ReadDouble) { + GetHandle().WriteDouble(0.1f); + double val = 0.0f; + int ret = GetHandle().ReadDouble(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 0.1f); +} + +TEST_F(ParcelCppTest, WriteString_AND_ReadString) { + GetHandle().WriteString("TestString"); + auto val = GetHandle().ReadString(); + ASSERT_EQ(get_last_result(), Parcel::Error::None); + ASSERT_EQ(val, "TestString"); +} + +TEST_F(ParcelCppTest, WriteCString_AND_ReadCString) { + GetHandle().WriteCString("TestCString"); + char* str = nullptr; + int ret = GetHandle().ReadCString(&str); + auto ptr = std::unique_ptr(str, std::free); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_NE(str, nullptr); + ASSERT_EQ(std::string(str), "TestCString"); +} + +TEST_F(ParcelCppTest, WriteCBundle_AND_ReadCBundle) { + bundle* b = bundle_create(); + bundle_add_str(b, "Key", "Value"); + GetHandle().WriteCBundle(b); + bundle_free(b); + bundle* val = nullptr; + int ret = GetHandle().ReadCBundle(&val); + auto ptr = std::unique_ptr(val, bundle_free); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_NE(val, nullptr); + char* str = nullptr; + bundle_get_str(b, "Key", &str); + ASSERT_EQ(std::string(str), "Value"); +} + +TEST_F(ParcelCppTest, WriteBundle_AND_ReadBundle) { + Bundle b; + b.Add("Key", "Value"); + GetHandle().WriteBundle(b); + auto val = GetHandle().ReadBundle(); + ASSERT_EQ(get_last_result(), Parcel::Error::None); + auto str = val.GetString("Key"); + ASSERT_EQ(str, "Value"); +} + +TEST_F(ParcelCppTest, GetRaw) { + GetHandle().WriteInt32(0); + auto& raw = GetHandle().GetRaw(); + ASSERT_EQ(raw.size(), sizeof(uint32_t) + sizeof(int32_t)); +} + +TEST_F(ParcelCppTest, ResetReader) { + GetHandle().WriteInt32(1); + GetHandle().WriteInt32(2); + int32_t val = 0; + int ret = GetHandle().ReadInt32(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); + GetHandle().ResetReader(); + val = 0; + ret = GetHandle().ReadInt32(&val); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(val, 1); +} + +TEST_F(ParcelCppTest, Clear) { + GetHandle().WriteInt32(1); + GetHandle().Clear(); + int32_t val = 0; + int ret = GetHandle().ReadInt32(&val); + ASSERT_NE(ret, Parcel::Error::None); + ASSERT_NE(val, 1); +} + +TEST_F(ParcelCppTest, Reset) { + GetHandle().WriteByte(1); + char buf[1024] = { 128, }; + GetHandle().Reset(buf, sizeof(buf)); + char read_buf[1024] = { 0, }; + int ret = GetHandle().Read(read_buf, sizeof(read_buf)); + ASSERT_EQ(ret, Parcel::Error::None); + ASSERT_EQ(buf[0], read_buf[0]); +} + +TEST_F(ParcelCppTest, WriteParcelable_AND_ReadParcelable) { + Student s1("s1", 8); + GetHandle().WriteParcelable(s1); + Student s2; + GetHandle().ReadParcelable(&s2); + ASSERT_EQ(s1.GetName(), s2.GetName()); + ASSERT_EQ(s1.GetAge(), s2.GetAge()); +} + +TEST_F(ParcelCppTest, IsEmpty) { + ASSERT_EQ(GetHandle().IsEmpty(), true); + GetHandle().WriteInt32(1); + ASSERT_EQ(GetHandle().IsEmpty(), false); +} -- 2.7.4