From 2c9f7e5472f2b06aac13d04ceb60611b39c5dabb Mon Sep 17 00:00:00 2001 From: hyunho Date: Wed, 16 Sep 2020 16:34:31 +0900 Subject: [PATCH] Add gtests Change-Id: I96373bc02f800c112dee3345289559586256b69d Signed-off-by: hyunho --- CMakeLists.txt | 18 ++- cmake/Modules/ApplyPkgConfig.cmake | 35 ++++ mock/gio_mock.cc | 123 ++++++++++++++ mock/gio_mock.h | 79 +++++++++ mock/mock_hook.h | 42 +++++ mock/module_mock.h | 25 +++ mock/test_fixture.cc | 21 +++ mock/test_fixture.h | 53 ++++++ packaging/buxton2.spec | 30 +++- test/CMakeLists.txt | 1 + test/unit_tests/CMakeLists.txt | 27 ++++ test/unit_tests/main.cc | 25 +++ test/unit_tests/test_vconf_compat.cc | 301 +++++++++++++++++++++++++++++++++++ 13 files changed, 773 insertions(+), 7 deletions(-) create mode 100644 cmake/Modules/ApplyPkgConfig.cmake create mode 100644 mock/gio_mock.cc create mode 100644 mock/gio_mock.h create mode 100644 mock/mock_hook.h create mode 100644 mock/module_mock.h create mode 100644 mock/test_fixture.cc create mode 100644 mock/test_fixture.h create mode 100644 test/CMakeLists.txt create mode 100644 test/unit_tests/CMakeLists.txt create mode 100644 test/unit_tests/main.cc create mode 100644 test/unit_tests/test_vconf_compat.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 6169a57..8bb667d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(buxton2 C) +PROJECT(buxton2) # check variables IF(NOT DEFINED VERSION) @@ -48,8 +48,20 @@ IF(NOT "${SOCKPATH}" STREQUAL "") ENDIF() # pkg-config +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") +INCLUDE(ApplyPkgConfig) INCLUDE(FindPkgConfig) + PKG_CHECK_MODULES(PKGS REQUIRED glib-2.0>=2.36 dlog) +PKG_CHECK_MODULES(GLIB_DEPS REQUIRED glib-2.0>=2.36 dlog) +PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock) +PKG_CHECK_MODULES(SQLITE3_DEPS REQUIRED sqlite3) +PKG_CHECK_MODULES(TZPLATFORM_CONFIG_DEPS REQUIRED libtzplatform-config) +PKG_CHECK_MODULES(SYSTEMD_DEPS REQUIRED libsystemd) +PKG_CHECK_MODULES(CYNARA_CLIENT_DEPS REQUIRED cynara-client-async) +PKG_CHECK_MODULES(GIO_DEPS REQUIRED gio-2.0) +PKG_CHECK_MODULES(VCONF_INTERNAL_KEYS_DEPS REQUIRED vconf-internal-keys) +PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog) FOREACH(flag ${PKGS_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -58,6 +70,9 @@ ENDFOREACH() SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall") MESSAGE("CFLAGS: ${CMAKE_C_FLAGS}") +ENABLE_TESTING() +SET(TARGET_BUXTON2_UNIT_TEST "buxton2-unit-test") + # build subdirectories INCLUDE_DIRECTORIES(common) @@ -66,6 +81,7 @@ ADD_SUBDIRECTORY(backend) ADD_SUBDIRECTORY(lib) ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(vconf-compat) +ADD_SUBDIRECTORY(test) IF(BUILD_EXAMPLE) ADD_SUBDIRECTORY(example) diff --git a/cmake/Modules/ApplyPkgConfig.cmake b/cmake/Modules/ApplyPkgConfig.cmake new file mode 100644 index 0000000..97679d7 --- /dev/null +++ b/cmake/Modules/ApplyPkgConfig.cmake @@ -0,0 +1,35 @@ +# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# +# This function applies external (out of source tree) dependencies +# to given target. Arguments are: +# TARGET - valid cmake target +# PRIVACY - dependency can be inherited by dependent targets or not: +# PUBLIC - this should be used by default, cause compile/link flags passing +# PRIVATE - do not passes any settings to dependent targets, +# may be usefull for static libraries from the inside of the project +# Argument ARGV2 and following are supposed to be names of checked pkg config +# packages. This function will use variables created by check_pkg_modules(). +# - ${DEP_NAME}_LIBRARIES +# - ${DEP_NAME}_INCLUDE_DIRS +# - ${DEP_NAME}_CFLAGS +# +FUNCTION(APPLY_PKG_CONFIG TARGET PRIVACY) + MATH(EXPR DEST_INDEX "${ARGC}-1") + FOREACH(I RANGE 2 ${DEST_INDEX}) + IF(NOT ${ARGV${I}}_FOUND) + MESSAGE(FATAL_ERROR "Not found dependency - ${ARGV${I}}_FOUND") + ENDIF(NOT ${ARGV${I}}_FOUND) + TARGET_LINK_LIBRARIES(${TARGET} ${PRIVACY} "${${ARGV${I}}_LIBRARIES}") + TARGET_INCLUDE_DIRECTORIES(${TARGET} ${PRIVACY} SYSTEM "${${ARGV${I}}_INCLUDE_DIRS}") + STRING(REPLACE ";" " " CFLAGS_STR "${${ARGV${I}}_CFLAGS}") + SET(CFLAGS_LIST ${CFLAGS_STR}) + SEPARATE_ARGUMENTS(CFLAGS_LIST) + FOREACH(OPTION ${CFLAGS_LIST}) + TARGET_COMPILE_OPTIONS(${TARGET} ${PRIVACY} ${OPTION}) + ENDFOREACH(OPTION) + SET_TARGET_PROPERTIES(${TARGET} PROPERTIES SKIP_BUILD_RPATH true) + ENDFOREACH(I RANGE 2 ${DEST_INDEX}) +ENDFUNCTION(APPLY_PKG_CONFIG TARGET PRIVACY) diff --git a/mock/gio_mock.cc b/mock/gio_mock.cc new file mode 100644 index 0000000..0b88132 --- /dev/null +++ b/mock/gio_mock.cc @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2020 Samsung Electronics 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. + */ + +#include "gio_mock.h" + +#include "mock_hook.h" +#include "test_fixture.h" + +extern "C" GDBusConnection* g_bus_get_sync(GBusType type, + GCancellable* cancellable, GError** error) { + return MOCK_HOOK_P3(GioMock, g_bus_get_sync, type, cancellable, error); +} + +extern "C" GDBusMessage* g_dbus_connection_send_message_with_reply_sync( + GDBusConnection* conn, GDBusMessage* msg, GDBusSendMessageFlags flags, + gint timeout, volatile guint32* out_serial, GCancellable* cancellable, + GError** error) { + return MOCK_HOOK_P7(GioMock, g_dbus_connection_send_message_with_reply_sync, + conn, msg, flags, timeout, out_serial, cancellable, error); +} + +extern "C" GDBusMessage* g_dbus_message_new_method_call(const gchar* arg0, + const gchar* arg1, const gchar* arg2, const gchar* arg3) { + return MOCK_HOOK_P4(GioMock, g_dbus_message_new_method_call, arg0, arg1, arg2, + arg3); +} + +extern "C" void g_dbus_message_set_body(GDBusMessage* arg0, GVariant* arg1) { + return MOCK_HOOK_P2(GioMock, g_dbus_message_set_body, arg0, arg1); +} + +extern "C" GVariant* g_dbus_message_get_body(GDBusMessage* arg0) { + return MOCK_HOOK_P1(GioMock, g_dbus_message_get_body, arg0); +} + +extern "C" gboolean g_dbus_connection_emit_signal(GDBusConnection* arg0, + const gchar* arg1, const gchar* arg2, const gchar* arg3, const gchar* arg4, + GVariant* arg5, GError** arg6) { + return MOCK_HOOK_P7(GioMock, g_dbus_connection_emit_signal, + arg0, arg1, arg2, arg3, arg4, arg5, arg6); +} + +extern "C" GDBusNodeInfo* g_dbus_node_info_new_for_xml( + const gchar* arg0, GError** arg1) { + return MOCK_HOOK_P2(GioMock, g_dbus_node_info_new_for_xml, arg0, arg1); +} + +extern "C" guint g_dbus_connection_register_object(GDBusConnection* arg0, + const gchar* arg1, GDBusInterfaceInfo* arg2, + const GDBusInterfaceVTable* arg3, gpointer arg4, + GDestroyNotify arg5, GError** arg6) { + return MOCK_HOOK_P7(GioMock, g_dbus_connection_register_object, + arg0, arg1, arg2, arg3, arg4, arg5, arg6); +} + +extern "C" gboolean g_dbus_connection_unregister_object (GDBusConnection *connection, + guint registration_id) { + return MOCK_HOOK_P2(GioMock, g_dbus_connection_unregister_object, + connection, registration_id); +} + +extern "C" guint g_bus_own_name_on_connection(GDBusConnection* arg0, + const gchar* arg1, GBusNameOwnerFlags arg2, + GBusNameAcquiredCallback arg3, GBusNameLostCallback arg4, + gpointer arg5, GDestroyNotify arg6) { + return MOCK_HOOK_P7(GioMock, g_bus_own_name_on_connection, + arg0, arg1, arg2, arg3, arg4, arg5, arg6); +} + +extern "C" guint g_dbus_connection_signal_subscribe(GDBusConnection* arg0, + const gchar* arg1, const gchar* arg2, const gchar* arg3, const gchar* arg4, + const gchar* arg5, GDBusSignalFlags arg6, GDBusSignalCallback arg7, + gpointer arg8, GDestroyNotify arg9) { + return MOCK_HOOK_P10(GioMock, g_dbus_connection_signal_subscribe, + arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); +} + +extern "C" void g_dbus_connection_send_message_with_reply(GDBusConnection* arg0, + GDBusMessage* arg1, GDBusSendMessageFlags arg2, gint arg3, + volatile guint32* arg4, GCancellable* arg5, GAsyncReadyCallback arg6, + gpointer arg7) { + return MOCK_HOOK_P8(GioMock, g_dbus_connection_send_message_with_reply, + arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + +extern "C" GDBusMessage* g_dbus_connection_send_message_with_reply_finish( + GDBusConnection* arg0, GAsyncResult* arg1, GError** arg2) { + return MOCK_HOOK_P3(GioMock, g_dbus_connection_send_message_with_reply_finish, + arg0, arg1, arg2); +} + +extern "C" gboolean g_dbus_connection_send_message(GDBusConnection* arg0, + GDBusMessage* arg1, GDBusSendMessageFlags arg2, + volatile guint32* arg3, GError** arg4) { + return MOCK_HOOK_P5(GioMock, g_dbus_connection_send_message, + arg0, arg1, arg2, arg3, arg4); +} + +extern "C" void g_dbus_message_set_unix_fd_list(GDBusMessage* arg0, + GUnixFDList* arg1) { + return MOCK_HOOK_P2(GioMock, g_dbus_message_set_unix_fd_list, arg0, arg1); +} + +extern "C" guint g_bus_watch_name_on_connection(GDBusConnection* arg0, + const gchar* arg1, GBusNameWatcherFlags arg2, + GBusNameAppearedCallback arg3, GBusNameVanishedCallback arg4, gpointer arg5, + GDestroyNotify arg6) { + return MOCK_HOOK_P7(GioMock, g_bus_watch_name_on_connection, arg0, arg1, arg2, + arg3, arg4, arg5, arg6); +} diff --git a/mock/gio_mock.h b/mock/gio_mock.h new file mode 100644 index 0000000..3867d5c --- /dev/null +++ b/mock/gio_mock.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020 Samsung Electronics 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. + */ + +#ifndef UNIT_TESTS_MOCK_GIO_MOCK_H_ +#define UNIT_TESTS_MOCK_GIO_MOCK_H_ + +#include +#include + +#include "module_mock.h" + +class GioMock : public virtual ModuleMock { + public: + virtual ~GioMock() {} + + MOCK_METHOD3(g_bus_get_sync, + GDBusConnection*(GBusType, GCancellable*, GError**)); + MOCK_METHOD7(g_bus_own_name_on_connection, + guint(GDBusConnection*, const gchar*, GBusNameOwnerFlags, + GBusNameAcquiredCallback, GBusNameLostCallback, + gpointer, GDestroyNotify)); + + MOCK_METHOD4(g_dbus_message_new_method_call, + GDBusMessage*(const gchar*, const gchar*, const gchar*, const gchar*)); + MOCK_METHOD2(g_dbus_message_set_body, void(GDBusMessage*, GVariant*)); + MOCK_METHOD2(g_dbus_connection_unregister_object, + gboolean(GDBusConnection*, guint)); + MOCK_METHOD1(g_dbus_message_get_body, GVariant*(GDBusMessage*)); + + MOCK_METHOD7(g_dbus_connection_send_message_with_reply_sync, + GDBusMessage*(GDBusConnection*, GDBusMessage*, GDBusSendMessageFlags, + gint, volatile guint32*, GCancellable*, GError**)); + MOCK_METHOD7(g_dbus_connection_emit_signal, + gboolean(GDBusConnection*, const gchar*, const gchar*, const gchar*, + const gchar*, GVariant*, GError**)); + MOCK_METHOD7(g_dbus_connection_register_object, + guint(GDBusConnection*, const gchar*, GDBusInterfaceInfo*, + const GDBusInterfaceVTable*, gpointer, GDestroyNotify, GError**)); + MOCK_METHOD10(g_dbus_connection_signal_subscribe, + guint(GDBusConnection*, const gchar*, const gchar*, const gchar*, + const gchar*, const gchar*, GDBusSignalFlags, GDBusSignalCallback, + gpointer, GDestroyNotify)); + MOCK_METHOD8(g_dbus_connection_send_message_with_reply, + void(GDBusConnection*, GDBusMessage*, GDBusSendMessageFlags, gint, + volatile guint32*, GCancellable*, GAsyncReadyCallback, gpointer)); + MOCK_METHOD3(g_dbus_connection_send_message_with_reply_finish, + GDBusMessage*(GDBusConnection*, GAsyncResult*, GError**)); + + MOCK_METHOD2(g_dbus_node_info_new_for_xml, + GDBusNodeInfo*(const gchar*, GError**)); + + MOCK_METHOD2(g_dbus_method_invocation_return_value, + GDBusNodeInfo*(GDBusMethodInvocation*, GVariant*)); + + MOCK_METHOD5(g_dbus_connection_send_message, + gboolean(GDBusConnection*, GDBusMessage*, GDBusSendMessageFlags, + volatile guint32*, GError**)); + MOCK_METHOD2(g_dbus_message_set_unix_fd_list, + void(GDBusMessage*, GUnixFDList*)); + MOCK_METHOD7(g_bus_watch_name_on_connection, + guint(GDBusConnection*, const gchar*, GBusNameWatcherFlags, + GBusNameAppearedCallback, GBusNameVanishedCallback, gpointer, + GDestroyNotify)); +}; + +#endif // UNIT_TESTS_MOCK_GIO_MOCK_H_ diff --git a/mock/mock_hook.h b/mock/mock_hook.h new file mode 100644 index 0000000..af27bba --- /dev/null +++ b/mock/mock_hook.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Samsung Electronics 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. + */ + +#ifndef UNIT_TESTS_MOCK_MOCK_HOOK_H_ +#define UNIT_TESTS_MOCK_MOCK_HOOK_H_ + +#define MOCK_HOOK_P0(MOCK_CLASS, f) \ + TestFixture::GetMock().f() +#define MOCK_HOOK_P1(MOCK_CLASS, f, p1) \ + TestFixture::GetMock().f(p1) +#define MOCK_HOOK_P2(MOCK_CLASS, f, p1, p2) \ + TestFixture::GetMock().f(p1, p2) +#define MOCK_HOOK_P3(MOCK_CLASS, f, p1, p2, p3) \ + TestFixture::GetMock().f(p1, p2, p3) +#define MOCK_HOOK_P4(MOCK_CLASS, f, p1, p2, p3, p4) \ + TestFixture::GetMock().f(p1, p2, p3, p4) +#define MOCK_HOOK_P5(MOCK_CLASS, f, p1, p2, p3, p4, p5) \ + TestFixture::GetMock().f(p1, p2, p3, p4, p5) +#define MOCK_HOOK_P6(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6) \ + TestFixture::GetMock().f(p1, p2, p3, p4, p5, p6) +#define MOCK_HOOK_P7(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7) \ + TestFixture::GetMock().f(p1, p2, p3, p4, p5, p6, p7) +#define MOCK_HOOK_P8(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7, p8) \ + TestFixture::GetMock().f(p1, p2, p3, p4, p5, p6, p7, p8) +#define MOCK_HOOK_P10(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) \ + TestFixture::GetMock().f( \ + p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) + +#endif // UNIT_TESTS_MOCK_MOCK_HOOK_H_ diff --git a/mock/module_mock.h b/mock/module_mock.h new file mode 100644 index 0000000..9b19d89 --- /dev/null +++ b/mock/module_mock.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020 Samsung Electronics 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. + */ + +#ifndef UNIT_TESTS_MOCK_MODULE_MOCK_H_ +#define UNIT_TESTS_MOCK_MODULE_MOCK_H_ + +class ModuleMock { + public: + virtual ~ModuleMock() {} +}; + +#endif // UNIT_TESTS_MOCK_MODULE_MOCK_H_ diff --git a/mock/test_fixture.cc b/mock/test_fixture.cc new file mode 100644 index 0000000..27f5666 --- /dev/null +++ b/mock/test_fixture.cc @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020 Samsung Electronics 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. + */ + +#include "test_fixture.h" + +#include + +std::unique_ptr TestFixture::mock_; diff --git a/mock/test_fixture.h b/mock/test_fixture.h new file mode 100644 index 0000000..1ea3b8f --- /dev/null +++ b/mock/test_fixture.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 Samsung Electronics 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. + */ + +#ifndef UNIT_TESTS_MOCK_TEST_FIXTURE_H_ +#define UNIT_TESTS_MOCK_TEST_FIXTURE_H_ + +#include + +#include +#include +#include +#include + +#include "module_mock.h" + +class TestFixture : public ::testing::Test { + public: + explicit TestFixture(std::unique_ptr&& mock) { + mock_ = std::move(mock); + } + virtual ~TestFixture() { + mock_.reset(); + } + + virtual void SetUp() {} + virtual void TearDown() {} + + template + static T& GetMock() { + auto ptr = dynamic_cast(mock_.get()); + if (!ptr) + throw std::invalid_argument("The test does not provide mock of \"" + + std::string(typeid(T).name()) + "\""); + return *ptr; + } + + static std::unique_ptr mock_; +}; + +#endif // UNIT_TESTS_MOCK_TEST_FIXTURE_H_ diff --git a/packaging/buxton2.spec b/packaging/buxton2.spec index 8d5587a..a310d7b 100644 --- a/packaging/buxton2.spec +++ b/packaging/buxton2.spec @@ -22,6 +22,7 @@ BuildRequires: pkgconfig(cynara-client-async) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(gmock) Requires: security-config Requires(post): /usr/bin/getent Requires(post): /usr/bin/chown @@ -33,6 +34,11 @@ Requires(posttrans): /usr/bin/chmod Obsoletes: buxton Provides: buxton +%if 0%{?gcov:1} +BuildRequires: lcov +BuildRequires: zip +%endif + %description Buxton is a security-enabled configuration management system. It features a layered approach to configuration storage, with each @@ -109,17 +115,17 @@ gcov objects for a buxton2 library cp %{SOURCE1001} . %build + +# for Address space layout randomization +export CFLAGS="$CFLAGS -fPIE " +export LDFLAGS="$LDFLAGS -pie" + %if 0%{?gcov:1} export CFLAGS+=" -fprofile-arcs -ftest-coverage" -export CXXFLAGS+=" -fprofile-arcs -ftest-coverage" export FFLAGS+=" -fprofile-arcs -ftest-coverage" export LDFLAGS+=" -lgcov" %endif -# for Address space layout randomization -export CFLAGS="$CFLAGS -fPIE" -export LDFLAGS="$LDFLAGS -pie" - %cmake -DVERSION=%{version} \ -DCONFPATH:PATH=%{_sysconfdir}/%{name}.conf \ -DMODULE_DIR:PATH=%{_libdir}/%{name} \ @@ -138,6 +144,7 @@ mkdir -p gcov-obj find . -name '*.gcno' -exec cp '{}' gcov-obj ';' %endif + %install %make_install @@ -171,6 +178,17 @@ mkdir -p %{buildroot}%{_datadir}/gcov/obj install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %endif +%check +export LD_LIBRARY_PATH=../../vconf-compat:../../lib +ctest -V + +%if 0%{?gcov:1} +lcov -c --ignore-errors graph --no-external -q -d . -o buxton2.info +genhtml buxton2.info -o buxton2.out +zip -r buxton2.zip buxton2.out +install -m 0644 buxton2.zip %{buildroot}%{_datadir}/gcov/ +%endif + %post /sbin/ldconfig @@ -245,5 +263,5 @@ chsmack -a System %{dbdir}/* %if 0%{?gcov:1} %files gcov -%{_datadir}/gcov/obj/* +%{_datadir}/gcov/* %endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..c90fac8 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1 @@ +ADD_SUBDIRECTORY(unit_tests) diff --git a/test/unit_tests/CMakeLists.txt b/test/unit_tests/CMakeLists.txt new file mode 100644 index 0000000..15c710d --- /dev/null +++ b/test/unit_tests/CMakeLists.txt @@ -0,0 +1,27 @@ +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ UNIT_TESTS_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../mock/ UNIT_TESTS_SRCS) +ADD_EXECUTABLE(${TARGET_BUXTON2_UNIT_TEST} + ${UNIT_TESTS_SRCS} +) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_BUXTON2_UNIT_TEST} PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/../" + "${CMAKE_CURRENT_SOURCE_DIR}/../../vconf-compat" + "${CMAKE_CURRENT_SOURCE_DIR}/../../lib/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../../mock" +) + +APPLY_PKG_CONFIG(${TARGET_BUXTON2_UNIT_TEST} PUBLIC + GLIB_DEPS + GMOCK_DEPS + VCONF_INTERNAL_KEYS_DEPS +) + +TARGET_LINK_LIBRARIES(${TARGET_BUXTON2_UNIT_TEST} PUBLIC vconf buxton2) +SET_TARGET_PROPERTIES(${TARGET_BUXTON2_UNIT_TEST} PROPERTIES COMPILE_FLAGS "-fPIE") +SET_TARGET_PROPERTIES(${TARGET_BUXTON2_UNIT_TEST} PROPERTIES LINK_FLAGS "-pie") + +ADD_TEST( + NAME ${TARGET_BUXTON2_UNIT_TEST} + COMMAND ${TARGET_BUXTON2_UNIT_TEST} +) diff --git a/test/unit_tests/main.cc b/test/unit_tests/main.cc new file mode 100644 index 0000000..5f340cd --- /dev/null +++ b/test/unit_tests/main.cc @@ -0,0 +1,25 @@ +// Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a apache 2.0 license that can be +// found in the LICENSE file. + +#include +#include + +int main(int argc, char** argv) { + int ret = -1; + try { + testing::InitGoogleTest(&argc, argv); + } catch(...) { + std::cout << "Exception occurred" << std::endl; + } + + try { + ret = RUN_ALL_TESTS(); + } catch (const ::testing::internal::GoogleTestFailureException& e) { + ret = -1; + std::cout << "GoogleTestFailureException was thrown:" << e.what() + << std::endl; + } + + return ret; +} diff --git a/test/unit_tests/test_vconf_compat.cc b/test/unit_tests/test_vconf_compat.cc new file mode 100644 index 0000000..75bc074 --- /dev/null +++ b/test/unit_tests/test_vconf_compat.cc @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2020 Samsung Electronics 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. + */ + +#include +#include +#include +#include + +#include "vconf.h" +#include "proto.h" +#include "test_fixture.h" +#include "gio_mock.h" + +#include +#include + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::Invoke; + +class Mocks : public ::testing::NiceMock{}; + +GVariant* data__; +class VconfCompatTest : public TestFixture { + public: + VconfCompatTest() : TestFixture(std::make_unique()) {} + virtual ~VconfCompatTest() {} + + virtual void SetUp() { + list_ = vconf_keylist_new(); + data__ = g_variant_new("s", "testvalue"); + ASSERT_NE(list_, nullptr); + } + + virtual void TearDown() { + g_variant_unref(data__); + vconf_keylist_free(list_); + } + keylist_t* list_; +}; + +TEST_F(VconfCompatTest, vconf_keylist_add_int) { + vconf_keylist_add_int(list_, "test", 7); + + keynode_t* node; + vconf_keylist_lookup(list_, "test", &node); + + int ret = vconf_keynode_get_int(node); + EXPECT_EQ(ret, 7); +} + +TEST_F(VconfCompatTest, vconf_keylist_add_bool) { + vconf_keylist_add_bool(list_, "test", true); + + keynode_t* node; + vconf_keylist_lookup(list_, "test", &node); + + int ret = vconf_keynode_get_bool(node); + EXPECT_EQ(ret, 1); +} + +TEST_F(VconfCompatTest, vconf_keylist_add_null) { + int len1 = vconf_keylist_add_null(list_, "test"); + int len2 = vconf_keylist_add_null(list_, "test"); + EXPECT_EQ(len1, len2); +} + +TEST_F(VconfCompatTest, vconf_keylist_del) { + int len1 = vconf_keylist_add_bool(list_, "test", true); + int len2 = vconf_keylist_del(list_, "test"); + + EXPECT_EQ(len1, len2 + 1); +} + +TEST_F(VconfCompatTest, vconf_keynode_get_name) { + vconf_keylist_add_bool(list_, "test", true); + + keynode_t* node; + vconf_keylist_lookup(list_, "test", &node); + + char* name = vconf_keynode_get_name(node); + EXPECT_STREQ(name, "test"); +} + +TEST_F(VconfCompatTest, vconf_keynode_get_type) { + vconf_keylist_add_bool(list_, "test", true); + + keynode_t* node; + vconf_keylist_lookup(list_, "test", &node); + + int type = vconf_keynode_get_type(node); + EXPECT_EQ(VCONF_TYPE_BOOL, type); +} + +TEST_F(VconfCompatTest, vconf_keynode_get_dbl) { + vconf_keylist_add_dbl(list_, "test", 1.1); + + keynode_t* node; + vconf_keylist_lookup(list_, "test", &node); + double ret = vconf_keynode_get_dbl(node); + EXPECT_EQ(ret, 1.1); +} + +TEST_F(VconfCompatTest, vconf_keynode_get_str) { + vconf_keylist_add_str(list_, "test", "value"); + + keynode_t* node; + vconf_keylist_lookup(list_, "test", &node); + char* ret = vconf_keynode_get_str(node); + EXPECT_STREQ(ret, "value"); +} + +TEST_F(VconfCompatTest, vconf_keylist_rewind) { + vconf_keylist_add_str(list_, "test", "value"); + vconf_keylist_add_str(list_, "test2", "value2"); + vconf_keylist_add_str(list_, "test3", "value3"); + + keynode_t* node = vconf_keylist_nextnode(list_); + char* ret = vconf_keynode_get_str(node); + vconf_keylist_rewind(list_); + node = vconf_keylist_nextnode(list_); + char* ret2 = vconf_keynode_get_str(node); + EXPECT_STREQ(ret, ret2); +} + +extern "C" int pthread_mutex_lock(pthread_mutex_t* mutex) { + return 0; +} + +extern "C" int pthread_mutex_unlock(pthread_mutex_t* mutex) { + return 0; +} + +typedef enum { + LOG_ID_INVALID = -1, + LOG_ID_MAIN, + LOG_ID_RADIO, + LOG_ID_SYSTEM, + LOG_ID_APPS, + LOG_ID_KMSG, + LOG_ID_SYSLOG, + LOG_ID_MAX +} log_id_t; + +extern "C" int __dlog_print( + log_id_t log_id, int prio, const char* tag, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + + return 0; +} + +void __vconf_callback_fn(keynode_t *node, void *user_data) { +} + +extern "C" int connect( + int sock, const struct sockaddr *addr, socklen_t addrlen) { + return 1; +} + +extern "C" ssize_t send(int sockfd, const void *buf, size_t len, int flags) { + return len; +} + + +GVariant* g_variant_new_from_data(const GVariantType* type, + gconstpointer data, gsize size, gboolean trusted, GDestroyNotify notify, + gpointer user_data) { + static int msgid = 0; + return g_variant_new("(qv)", MSG_GET, + g_variant_new("(uiuv)", msgid++, 0, 24, + data__)); +} + +extern "C" ssize_t recv(int sockfd, void *buf, size_t len, int flags) { + struct header* hdr = (struct header*)buf; + hdr->type = MSG_SINGLE; + hdr->mtype = MSG_GET; + hdr->total = 12; + hdr->len = 12; + return len; +} + +extern "C" int poll(struct pollfd *fds, nfds_t nfds, int timeout) { + return 1; +} + +extern "C" guint g_idle_add_full(gint priority, GSourceFunc function, + gpointer data, GDestroyNotify notify) { + function(data); + return 1; +} + +TEST_F(VconfCompatTest, vconf_notify_key_changed) { + int ret = vconf_notify_key_changed("test", __vconf_callback_fn, nullptr); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_ignore_key_changed) { + int ret = vconf_ignore_key_changed("test", __vconf_callback_fn); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_set_int) { + int ret = vconf_set_int("key", 1); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_set_bool) { + int ret = vconf_set_bool("key_b", true); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_set_str) { + int ret = vconf_set_str("key_s", "str"); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_set_dbl) { + int ret = vconf_set_dbl("key_d", 0.5); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_get_int) { + int val; + if (data__ != nullptr) + g_variant_unref(data__); + data__ = g_variant_new("i", 777); + int ret = vconf_get_int("key", &val); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_get_bool) { + int val; + if (data__ != nullptr) + g_variant_unref(data__); + data__ = g_variant_new("b", true); + int ret = vconf_get_bool("key_b", &val); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_get_dbl) { + double val; + if (data__ != nullptr) + g_variant_unref(data__); + data__ = g_variant_new("d", true); + int ret = vconf_get_dbl("key_d", &val); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_get_str) { + if (data__ != nullptr) + g_variant_unref(data__); + data__ = g_variant_new("s", "test"); + char* ret = vconf_get_str("key_s"); + EXPECT_STREQ(ret, "test"); +} + +TEST_F(VconfCompatTest, vconf_set) { + vconf_keylist_add_str(list_, "test", "value"); + int ret = vconf_set(list_); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_get) { + int ret = vconf_get(list_, "db/test", VCONF_GET_ALL); + EXPECT_EQ(ret, 0); +} + +TEST_F(VconfCompatTest, vconf_unset_negative) { + int ret = vconf_unset(nullptr); + EXPECT_EQ(ret, VCONF_ERROR_NOT_SUPPORTED); +} + +TEST_F(VconfCompatTest, vconf_unset_recursive_negative) { + int ret = vconf_unset_recursive(nullptr); + EXPECT_EQ(ret, VCONF_ERROR_NOT_SUPPORTED); +} + +TEST_F(VconfCompatTest, vconf_sync_key) { + int ret = vconf_sync_key("test"); + EXPECT_EQ(ret, 0); +} -- 2.7.4