aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNaoto Yamaguchi <naoto.yamaguchi@aisin.co.jp>2022-07-04 07:23:53 +0900
committerNaoto Yamaguchi <naoto.yamaguchi@aisin.co.jp>2022-07-30 23:42:18 +0900
commite8a05c6f1ac288a8cfa5b0837313fec8fb7aadaf (patch)
tree4f43e3521ea2384f7298a6f00406aab631f44cde
parente5f52b7e2305019651fe4b6351d3466638af3488 (diff)
Add test case for librefop
The librefop aim to 100% code coverage testing. This patch add test case with mock to aim to that criteria. Bug-AGL: SPEC-4500 Signed-off-by: Naoto Yamaguchi <naoto.yamaguchi@aisin.co.jp> Change-Id: I4bf14d343b9fca784fb7bc3ee6d3e53691a5ea4e
-rw-r--r--test/Makefile.am60
-rw-r--r--test/file_util_test.cpp84
-rw-r--r--test/fileop_test_utils.cpp275
-rw-r--r--test/interface_test.cpp409
-rw-r--r--test/interface_test_unit.cpp199
-rw-r--r--test/mock/libpthread_mock.hpp93
-rw-r--r--test/mock/libsystemd_mock.hpp208
-rw-r--r--test/mock/syscall_io_mock.hpp156
8 files changed, 1484 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..050390e
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,60 @@
+AUTOMAKE_OPTIONS = foreign
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+bin_PROGRAMS = \
+ interface_test interface_test_unit \
+ fileop_test_utils \
+ file_util_test
+
+interface_test_SOURCES = \
+ interface_test.cpp \
+ ../lib/static-configurator.c \
+ ../lib/file-util.c \
+ ../lib/fileop.c
+
+interface_test_unit_SOURCES = \
+ interface_test_unit.cpp \
+ ../lib/static-configurator.c \
+ ../lib/file-util.c \
+ ../lib/fileop.c
+
+fileop_test_utils_SOURCES = \
+ fileop_test_utils.cpp \
+ ../lib/static-configurator.c \
+ ../lib/file-util.c
+
+file_util_test_SOURCES = \
+ file_util_test.cpp
+
+# options
+# Additional library
+LDADD = \
+ -lrt -lpthread \
+ @GTEST_MAIN_LIBS@ \
+ @GMOCK_MAIN_LIBS@
+
+interface_test_LDADD = \
+ ${LDADD}
+
+# C compiler options
+CFLAGS = \
+ -g \
+ -fsanitize=address -coverage \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/include \
+ -D_GNU_SOURCE
+
+# C++ compiler options
+CXXFLAGS = \
+ -g \
+ -std=c++11 -fno-exceptions \
+ -fsanitize=address -coverage \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/include \
+ -D_GNU_SOURCE
+
+# Linker options
+LDFLAGS =
+
+
+CLEANFILES = *.gcda *.gcno
diff --git a/test/file_util_test.cpp b/test/file_util_test.cpp
new file mode 100644
index 0000000..f78fbe2
--- /dev/null
+++ b/test/file_util_test.cpp
@@ -0,0 +1,84 @@
+/**
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * @file data-pool-service-test.c
+ * @brief Unit test fot data-pool-service-test.c
+ */
+#include <gtest/gtest.h>
+#include "mock/syscall_io_mock.hpp"
+
+// Test Terget files ---------------------------------------
+extern "C" {
+#include "../lib/file-util.c"
+}
+// Test Terget files ---------------------------------------
+using namespace ::testing;
+
+struct file_util_test : Test, SyscallIOMockBase {};
+
+//--------------------------------------------------------------------------------------------------------
+TEST_F(file_util_test, file_util_test_safe_read__success)
+{
+ ssize_t ret = -1;
+ uint8_t buffer[1024*1024];
+ size_t sz = 1024*1024;
+ size_t sza = sz - 1024;
+ size_t szb = 1024;
+
+ EXPECT_CALL(sysiom, read(1,buffer,sz)).WillOnce(SetErrnoAndReturn(EIO, -1));
+ ret = safe_read(1, buffer, sz);
+ ASSERT_EQ(-1, ret);
+
+ EXPECT_CALL(sysiom, read(1,buffer,sz)).WillOnce(Return(sz));
+ ret = safe_read(1, buffer, sz);
+ ASSERT_EQ(sz, ret);
+
+ EXPECT_CALL(sysiom, read(1,buffer,sz))
+ .WillOnce(SetErrnoAndReturn(EINTR, -1))
+ .WillOnce(Return(sz));
+ ret = safe_read(1, buffer, sz);
+ ASSERT_EQ(sz, ret);
+
+ EXPECT_CALL(sysiom, read(1,buffer,sz)).WillOnce(Return(sza));
+ EXPECT_CALL(sysiom, read(1,(&buffer[sza]),szb)).WillOnce(Return(szb));
+ ret = safe_read(1, buffer, sz);
+ ASSERT_EQ(sz, ret);
+
+ EXPECT_CALL(sysiom, read(1,buffer,sz)).WillOnce(Return(sza));
+ EXPECT_CALL(sysiom, read(1,(&buffer[sza]),szb)).WillOnce(Return(0));
+ ret = safe_read(1, buffer, sz);
+ ASSERT_EQ(sza, ret);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(file_util_test, file_util_test_safe_write__success)
+{
+ ssize_t ret = -1;
+ uint8_t buffer[1024*1024];
+ size_t sz = 1024*1024;
+ size_t sza = sz - 1024;
+ size_t szb = 1024;
+
+ EXPECT_CALL(sysiom, write(1,buffer,sz)).WillOnce(SetErrnoAndReturn(EIO, -1));
+ ret = safe_write(1, buffer, sz);
+ ASSERT_EQ(-1, ret);
+
+ EXPECT_CALL(sysiom, write(1,buffer,sz)).WillOnce(Return(sz));
+ ret = safe_write(1, buffer, sz);
+ ASSERT_EQ(sz, ret);
+
+ EXPECT_CALL(sysiom, write(1,buffer,sz))
+ .WillOnce(SetErrnoAndReturn(EINTR, -1))
+ .WillOnce(Return(sz));
+ ret = safe_write(1, buffer, sz);
+ ASSERT_EQ(sz, ret);
+
+ EXPECT_CALL(sysiom, write(1,buffer,sz)).WillOnce(Return(sza));
+ EXPECT_CALL(sysiom, write(1,(&buffer[sza]),szb)).WillOnce(Return(szb));
+ ret = safe_write(1, buffer, sz);
+ ASSERT_EQ(sz, ret);
+
+ EXPECT_CALL(sysiom, write(1,buffer,sz)).WillOnce(Return(sza));
+ EXPECT_CALL(sysiom, write(1,(&buffer[sza]),szb)).WillOnce(Return(0));
+ ret = safe_write(1, buffer, sz);
+ ASSERT_EQ(sza, ret);
+}
diff --git a/test/fileop_test_utils.cpp b/test/fileop_test_utils.cpp
new file mode 100644
index 0000000..ca2f6dd
--- /dev/null
+++ b/test/fileop_test_utils.cpp
@@ -0,0 +1,275 @@
+/**
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * @file data-pool-service-test.c
+ * @brief Unit test fot data-pool-service-test.c
+ */
+#include <gtest/gtest.h>
+#include "mock/syscall_io_mock.hpp"
+
+// Test Terget files ---------------------------------------
+extern "C" {
+#include "../lib/fileop.c"
+}
+// Test Terget files ---------------------------------------
+using namespace ::testing;
+
+struct fileop_test_utils : Test, SyscallIOMockBase {};
+//struct data_pool_test_set_get_others : Test {};
+
+//--------------------------------------------------------------------------------------------------------
+TEST_F(fileop_test_utils, fileop_test_utils_refop_header_create__success)
+{
+ s_refop_file_header header;
+ s_refop_file_header *head = &header;
+
+ refop_header_create(head, 0, 0);
+ refop_header_create(head, 0x1234, 1*1024*1024*1024);
+ refop_header_create(head, 0x5678, 64*1024*1024*1024ul);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(fileop_test_utils, fileop_test_utils_refop_header_validation__invalid_header)
+{
+ s_refop_file_header header;
+ s_refop_file_header *head = &header;
+ int ret = -1;
+
+ // broaken magic
+ refop_header_create(head, 0x1234, 64*1024*1024);
+ head->magic = 0;
+ ret = refop_header_validation(head);
+ ASSERT_EQ(-1, ret);
+
+ // broaken version
+ refop_header_create(head, 0x1234, 64*1024*1024);
+ head->version = 0x88888888;
+ head->version_inv = 0x88888888;
+ ret = refop_header_validation(head);
+ ASSERT_EQ(-1, ret);
+
+ // invalid version
+ refop_header_create(head, 0x1234, 64*1024*1024);
+ head->version = 0x88888888;
+ head->version_inv = ~head->version;
+ ret = refop_header_validation(head);
+ ASSERT_EQ(-1, ret);
+
+ // broaken crc
+ refop_header_create(head, 0x1234, 64*1024*1024);
+ head->crc16 = 0x8888;
+ head->crc16_inv = 0x8888;
+ ret = refop_header_validation(head);
+ ASSERT_EQ(-1, ret);
+
+ // broaken size
+ refop_header_create(head, 0x1234, 64*1024*1024);
+ head->size_inv = head->size;
+ ret = refop_header_validation(head);
+ ASSERT_EQ(-1, ret);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(fileop_test_utils, fileop_test_utils_refop_header_validation__valid_header)
+{
+ s_refop_file_header header;
+ s_refop_file_header *head = &header;
+ int ret = -1;
+
+ // Valid header
+ refop_header_create(head, 0x1234, 64*1024*1024);
+ ret = refop_header_validation(head);
+ ASSERT_EQ(0, ret);
+
+ // Valid header
+ refop_header_create(head, 0xabcd, 64*1024);
+ ret = refop_header_validation(head);
+ ASSERT_EQ(0, ret);
+
+ // Valid header
+ refop_header_create(head, 0x0000, 1*1024*1024);
+ ret = refop_header_validation(head);
+ ASSERT_EQ(0, ret);
+
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(fileop_test_utils, fileop_test_utils_refop_file_test__stat_error)
+{
+ int ret = -1;
+
+ //dummy data
+ char testfilename[] = "/tmp/test.bin";
+
+ /* stat error case
+ EACCES
+ EFAULT
+ ELOOP
+ ENAMETOOLONG
+ ENOENT
+ ENOMEM
+ ENOTDIR
+ EOVERFLOW
+ */
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(SetErrnoAndReturn(ENOENT, -1));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(-1, ret);
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(SetErrnoAndReturn(EACCES, -1));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(-2, ret);
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(SetErrnoAndReturn(EFAULT, -1));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(-2, ret);
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(SetErrnoAndReturn(ELOOP, -1));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(-2, ret);
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(SetErrnoAndReturn(ENAMETOOLONG, -1));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(-2, ret);
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(SetErrnoAndReturn(ENOMEM, -1));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(-2, ret);
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(SetErrnoAndReturn(ENOTDIR, -1));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(-2, ret);
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(SetErrnoAndReturn(EOVERFLOW, -1));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(-2, ret);
+
+ EXPECT_CALL(sysiom, stat(testfilename, _)).WillOnce(Return(0));
+ ret = refop_file_test(testfilename);
+ ASSERT_EQ(0, ret);
+}
+
+#if 0
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_create_redundancy_handle__stat_error)
+{
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp";
+ char file[] = "test.bin";
+
+ /* stat error case
+ EACCES
+ EFAULT
+ ELOOP
+ ENAMETOOLONG
+ ENOENT
+ ENOMEM
+ ENOTDIR
+ EOVERFLOW
+ */
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(EACCES, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(EFAULT, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SYSERROR, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ELOOP, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ENAMETOOLONG, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ENOENT, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ENOMEM, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SYSERROR, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ENOTDIR, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(EOVERFLOW, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SYSERROR, ret);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_create_redundancy_handle__pathcheck_error)
+{
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[PATH_MAX];
+ char file[PATH_MAX];
+
+ memset(directry,0,sizeof(directry));
+ memset(file,0,sizeof(file));
+
+ //short directry string
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ //short file string
+ strncpy(directry,"/tmp",PATH_MAX);
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ // too long path
+ for(int i=1;i < (PATH_MAX-1);i++)
+ directry[i] = 'd';
+ strncpy(file,"test.bin",PATH_MAX);
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_create_redundancy_handle__success)
+{
+ struct refop_halndle *hndl;
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp";
+ char directry2[] = "/tmp/";
+ char file[] = "test.bin";
+ char resultstr[] = "/tmp/test.bin";
+ char resultstr_bk1[] = "/tmp/test.bin.bk1";
+ char resultstr_new[] = "/tmp/test.bin.tmp";
+
+ //short directry string
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ //data check
+ hndl = (struct refop_halndle *)handle;
+ ASSERT_EQ(0, strcmp(hndl->latestfile,resultstr));
+ ASSERT_EQ(0, strcmp(hndl->backupfile1,resultstr_bk1));
+ ASSERT_EQ(0, strcmp(hndl->newfile,resultstr_new));
+ ASSERT_EQ(0, strcmp(hndl->basedir,directry2));
+ free(handle);
+
+ //short file string
+ EXPECT_CALL(sysiom, stat(directry2, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry2, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ //data check
+ hndl = (struct refop_halndle *)handle;
+ ASSERT_EQ(0, strcmp(hndl->latestfile,resultstr));
+ ASSERT_EQ(0, strcmp(hndl->backupfile1,resultstr_bk1));
+ ASSERT_EQ(0, strcmp(hndl->newfile,resultstr_new));
+ ASSERT_EQ(0, strcmp(hndl->basedir,directry2));
+ free(handle);
+}
+//--------------------------------------------------------------------------------------------------------
+#endif
diff --git a/test/interface_test.cpp b/test/interface_test.cpp
new file mode 100644
index 0000000..dec50bc
--- /dev/null
+++ b/test/interface_test.cpp
@@ -0,0 +1,409 @@
+/**
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * @file interface_test.cpp
+ * @brief Public interface test fot refop
+ */
+#include <gtest/gtest.h>
+
+// Test Terget files ---------------------------------------
+extern "C" {
+#include "../lib/libredundancyfileop.c"
+}
+// Test Terget files ---------------------------------------
+using namespace ::testing;
+
+struct interface_test : Test {};
+
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_set_redundancy_data__success)
+{
+ struct refop_halndle *hndl;
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp/refop-test/";
+ char file[] = "test.bin";
+ uint8_t *pbuf = NULL;
+ int64_t sz = 1 * 1024 * 1024;
+
+ (void)mkdir(directry, 0777);
+
+ pbuf = (uint8_t*)malloc(sz);
+
+ //short directry string
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0xff,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0xa5,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0x5a,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_release_redundancy_handle(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ free(pbuf);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_get_redundancy_data__success)
+{
+ struct refop_halndle *hndl;
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp/refop-test/";
+ char file[] = "test.bin";
+ uint8_t *pbuf = NULL;
+ int64_t sz = 1 * 1024 * 1024;
+ int64_t szr = 0;
+
+ (void)mkdir(directry, 0777);
+
+ pbuf = (uint8_t*)malloc(sz);
+
+ //short directry string
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_get_redundancy_data(handle, pbuf, sz, &szr);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ ASSERT_EQ(sz, szr);
+
+ ret = refop_release_redundancy_handle(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ free(pbuf);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_set_and_get)
+{
+ struct refop_halndle *hndl;
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp/refop-test/";
+ char file[] = "test.bin";
+ char newfile[] = "/tmp/refop-test/test.bin.tmp";
+ char latestfile[] = "/tmp/refop-test/test.bin";
+ char backupfile[] = "/tmp/refop-test/test.bin.bk1";
+
+ uint8_t *pbuf = NULL;
+ uint8_t *prbuf = NULL;
+ int64_t sz = 64 * 1024;
+ int64_t szr = 0;
+ int checker = 0;
+
+ (void)mkdir(directry, 0777);
+
+ pbuf = (uint8_t*)malloc(sz);
+ prbuf = (uint8_t*)malloc(sz);
+
+ //short directry string
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0xff,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // Operation algorithm
+ // Current Next
+ // | latest | backup | | latest | backup |
+ // a1 | 1 | 2 | | new | 1 |
+ // a2 | 1 | x | | new | 1 |
+ // a3 | x | 2 | | new | 2 |
+ // a4 | x | x | | new | x |
+
+ // a1
+ ret = refop_get_redundancy_data(handle, prbuf, sz, &szr);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ ASSERT_EQ(sz, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xff);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa1,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+
+ // a2
+ unlink(backupfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz, &szr);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ ASSERT_EQ(sz, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xa1);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa2,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // a3
+ unlink(latestfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz, &szr);
+ ASSERT_EQ(REFOP_RECOVER, ret);
+ ASSERT_EQ(sz, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xa1);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa3,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // a4
+ unlink(backupfile);
+ unlink(latestfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz, &szr);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ memset(pbuf,0xa4,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_remove_redundancy_data(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_release_redundancy_handle(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ free(pbuf);
+ free(prbuf);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_set_and_get_smallread)
+{
+ struct refop_halndle *hndl;
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp/refop-test/";
+ char file[] = "test.bin";
+ char newfile[] = "/tmp/refop-test/test.bin.tmp";
+ char latestfile[] = "/tmp/refop-test/test.bin";
+ char backupfile[] = "/tmp/refop-test/test.bin.bk1";
+
+ uint8_t *pbuf = NULL;
+ uint8_t *prbuf = NULL;
+ int64_t sz = 4 * 1024;
+ int64_t szr = 0;
+ int checker = 0;
+
+ (void)mkdir(directry, 0777);
+
+ pbuf = (uint8_t*)malloc(sz);
+ prbuf = (uint8_t*)malloc(sz);
+
+ //short directry string
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0xff,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // Operation algorithm
+ // Current Next
+ // | latest | backup | | latest | backup |
+ // a1 | 1 | 2 | | new | 1 |
+ // a2 | 1 | x | | new | 1 |
+ // a3 | x | 2 | | new | 2 |
+ // a4 | x | x | | new | x |
+
+ // a1
+ ret = refop_get_redundancy_data(handle, prbuf, sz/2, &szr);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ ASSERT_EQ(sz/2, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xff);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa1,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+
+ // a2
+ unlink(backupfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz/2, &szr);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ ASSERT_EQ(sz/2, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xa1);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa2,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // a3
+ unlink(latestfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz/2, &szr);
+ ASSERT_EQ(REFOP_RECOVER, ret);
+ ASSERT_EQ(sz/2, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xa1);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa3,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // a4
+ unlink(backupfile);
+ unlink(latestfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz/2, &szr);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ memset(pbuf,0xa4,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_remove_redundancy_data(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_release_redundancy_handle(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ free(pbuf);
+ free(prbuf);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_set_and_get_largeread)
+{
+ struct refop_halndle *hndl;
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp/refop-test/";
+ char file[] = "test.bin";
+ char newfile[] = "/tmp/refop-test/test.bin.tmp";
+ char latestfile[] = "/tmp/refop-test/test.bin";
+ char backupfile[] = "/tmp/refop-test/test.bin.bk1";
+
+ uint8_t *pbuf = NULL;
+ uint8_t *prbuf = NULL;
+ int64_t sz = 256 * 1024;
+ int64_t szr = 0;
+ int checker = 0;
+
+ (void)mkdir(directry, 0777);
+
+ pbuf = (uint8_t*)malloc(sz);
+ prbuf = (uint8_t*)malloc(sz);
+
+ //short directry string
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ memset(pbuf,0xff,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // Operation algorithm
+ // Current Next
+ // | latest | backup | | latest | backup |
+ // a1 | 1 | 2 | | new | 1 |
+ // a2 | 1 | x | | new | 1 |
+ // a3 | x | 2 | | new | 2 |
+ // a4 | x | x | | new | x |
+
+ // a1
+ ret = refop_get_redundancy_data(handle, prbuf, sz*2, &szr);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ ASSERT_EQ(sz, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xff);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa1,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+
+ // a2
+ unlink(backupfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz*2, &szr);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ ASSERT_EQ(sz, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xa1);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa2,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // a3
+ unlink(latestfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz*2, &szr);
+ ASSERT_EQ(REFOP_RECOVER, ret);
+ ASSERT_EQ(sz, szr);
+ for(int i=0;i < szr;i++) {
+ checker += (prbuf[i] - (uint8_t)0xa1);
+ }
+ ASSERT_EQ(0, checker);
+
+ memset(pbuf,0xa3,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ // a4
+ unlink(backupfile);
+ unlink(latestfile);
+ ret = refop_get_redundancy_data(handle, prbuf, sz*2, &szr);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ memset(pbuf,0xa4,sz);
+ ret = refop_set_redundancy_data(handle, pbuf, sz);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_remove_redundancy_data(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_release_redundancy_handle(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ free(pbuf);
+ free(prbuf);
+}
+//--------------------------------------------------------------------------------------------------------
diff --git a/test/interface_test_unit.cpp b/test/interface_test_unit.cpp
new file mode 100644
index 0000000..b9e8df1
--- /dev/null
+++ b/test/interface_test_unit.cpp
@@ -0,0 +1,199 @@
+/**
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * @file data-pool-service-test.c
+ * @brief Unit test fot data-pool-service-test.c
+ */
+#include <gtest/gtest.h>
+#include "mock/syscall_io_mock.hpp"
+
+// Test Terget files ---------------------------------------
+extern "C" {
+#include "../lib/libredundancyfileop.c"
+}
+// Test Terget files ---------------------------------------
+using namespace ::testing;
+
+struct interface_test : Test, SyscallIOMockBase {};
+
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_create_redundancy_handle__arg_error)
+{
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp";
+ char file[] = "test.bin";
+
+ ret = refop_create_redundancy_handle(NULL, NULL, NULL);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ ret = refop_create_redundancy_handle(&handle, NULL, NULL);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ ret = refop_create_redundancy_handle(NULL, directry, NULL);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ ret = refop_create_redundancy_handle(&handle, directry, NULL);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ ret = refop_create_redundancy_handle(&handle, NULL, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ ret = refop_create_redundancy_handle(NULL, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_create_redundancy_handle__stat_error)
+{
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp";
+ char file[] = "test.bin";
+
+ /* stat error case
+ EACCES
+ EFAULT
+ ELOOP
+ ENAMETOOLONG
+ ENOENT
+ ENOMEM
+ ENOTDIR
+ EOVERFLOW
+ */
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(EACCES, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(EFAULT, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SYSERROR, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ELOOP, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ENAMETOOLONG, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ENOENT, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ENOMEM, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SYSERROR, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(ENOTDIR, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_NOENT, ret);
+
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(SetErrnoAndReturn(EOVERFLOW, -1));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SYSERROR, ret);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_create_redundancy_handle__pathcheck_error)
+{
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[PATH_MAX];
+ char file[PATH_MAX];
+
+ memset(directry,0,sizeof(directry));
+ memset(file,0,sizeof(file));
+
+ //short directry string
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ //short file string
+ strncpy(directry,"/tmp",PATH_MAX);
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ // too long path
+ for(int i=1;i < (PATH_MAX-1);i++)
+ directry[i] = 'd';
+ strncpy(file,"test.bin",PATH_MAX);
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_create_redundancy_handle__success)
+{
+ struct refop_halndle *hndl;
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp";
+ char directry2[] = "/tmp/";
+ char file[] = "test.bin";
+ char resultstr[] = "/tmp/test.bin";
+ char resultstr_bk1[] = "/tmp/test.bin.bk1";
+ char resultstr_new[] = "/tmp/test.bin.tmp";
+
+ //short directry string
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ //data check
+ hndl = (struct refop_halndle *)handle;
+ ASSERT_EQ(0, strcmp(hndl->latestfile,resultstr));
+ ASSERT_EQ(0, strcmp(hndl->backupfile1,resultstr_bk1));
+ ASSERT_EQ(0, strcmp(hndl->newfile,resultstr_new));
+ ASSERT_EQ(0, strcmp(hndl->basedir,directry2));
+ ret = refop_release_redundancy_handle(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ //short file string
+ EXPECT_CALL(sysiom, stat(directry2, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry2, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+ //data check
+ hndl = (struct refop_halndle *)handle;
+ ASSERT_EQ(0, strcmp(hndl->latestfile,resultstr));
+ ASSERT_EQ(0, strcmp(hndl->backupfile1,resultstr_bk1));
+ ASSERT_EQ(0, strcmp(hndl->newfile,resultstr_new));
+ ASSERT_EQ(0, strcmp(hndl->basedir,directry2));
+ ret = refop_release_redundancy_handle(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+}
+//--------------------------------------------------------------------------------------------------------
+TEST_F(interface_test, interface_test_refop_release_redundancy_handle__all)
+{
+ struct refop_halndle *hndl;
+ refop_error_t ret = REFOP_SUCCESS;
+ refop_handle_t handle = NULL;
+
+ //dummy data
+ char directry[] = "/tmp";
+ char directry2[] = "/tmp/";
+ char file[] = "test.bin";
+ char resultstr[] = "/tmp/test.bin";
+ char resultstr_bk1[] = "/tmp/test.bin.bk1";
+ char resultstr_new[] = "/tmp/test.bin.tmp";
+
+ //short directry string
+ EXPECT_CALL(sysiom, stat(directry, _)).WillOnce(Return(0));
+ ret = refop_create_redundancy_handle(&handle, directry, file);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+
+ ret = refop_release_redundancy_handle(NULL);
+ ASSERT_EQ(REFOP_ARGERROR, ret);
+
+ ret = refop_release_redundancy_handle(handle);
+ ASSERT_EQ(REFOP_SUCCESS, ret);
+}
+//--------------------------------------------------------------------------------------------------------
diff --git a/test/mock/libpthread_mock.hpp b/test/mock/libpthread_mock.hpp
new file mode 100644
index 0000000..61ce43c
--- /dev/null
+++ b/test/mock/libpthread_mock.hpp
@@ -0,0 +1,93 @@
+#include <gmock/gmock.h>
+#include <functional>
+
+#include <signal.h>
+
+/*
+int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
+*/
+static std::function<int(int how, const sigset_t *set, sigset_t *oldset)> _pthread_sigmask;
+
+/*
+int pthread_mutex_lock(pthread_mutex_t *mutex);
+int pthread_mutex_trylock(pthread_mutex_t *mutex);
+int pthread_mutex_unlock(pthread_mutex_t *mutex);
+
+static std::function<int(pthread_mutex_t *mutex)> _pthread_mutex_lock;
+static std::function<int(pthread_mutex_t *mutex)> _pthread_mutex_trylock;
+static std::function<int(pthread_mutex_t *mutex)> _pthread_mutex_unlock;
+*/
+
+class LibpthreadMocker {
+public:
+ LibpthreadMocker() {
+ _pthread_sigmask = [this](int how, const sigset_t *set, sigset_t *oldset)
+ {
+ return pthread_sigmask(how, set, oldset);
+ };
+
+/*
+ _pthread_mutex_lock = [this](pthread_mutex_t *mutex)
+ {
+ return pthread_mutex_lock(mutex);
+ };
+ _pthread_mutex_trylock = [this](pthread_mutex_t *mutex)
+ {
+ return pthread_mutex_trylock(mutex);
+ };
+ _pthread_mutex_unlock = [this](pthread_mutex_t *mutex)
+ {
+ return pthread_mutex_unlock(mutex);
+ };
+*/
+ }
+
+ ~LibpthreadMocker() {
+ _pthread_sigmask = {};
+
+/*
+ _pthread_mutex_lock = {};
+ _pthread_mutex_trylock = {};
+ _pthread_mutex_unlock = {};
+*/
+ }
+
+ MOCK_CONST_METHOD3(pthread_sigmask, int(int how, const sigset_t *set, sigset_t *oldset));
+/*
+ MOCK_CONST_METHOD1(pthread_mutex_lock, int(pthread_mutex_t *mutex));
+ MOCK_CONST_METHOD1(pthread_mutex_trylock, int(pthread_mutex_t *mutex));
+ MOCK_CONST_METHOD1(pthread_mutex_unlock, int(pthread_mutex_t *mutex));
+*/
+};
+
+class LibpthreadMockBase {
+protected:
+ LibpthreadMocker lpm;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset)
+{
+ return _pthread_sigmask(how, set, oldset);
+}
+
+/*
+static int pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+ return _pthread_mutex_lock(mutex);
+}
+static int pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+ return _pthread_mutex_trylock(mutex);
+}
+static int pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+ return _pthread_mutex_unlock(mutex);
+}
+*/
+#ifdef __cplusplus
+}
+#endif
diff --git a/test/mock/libsystemd_mock.hpp b/test/mock/libsystemd_mock.hpp
new file mode 100644
index 0000000..34de9a0
--- /dev/null
+++ b/test/mock/libsystemd_mock.hpp
@@ -0,0 +1,208 @@
+#include <gmock/gmock.h>
+#include <functional>
+
+#include <systemd/sd-event.h>
+
+
+/*
+int sd_event_add_signal(sd_event *event, sd_event_source **source,
+ int signal, sd_event_signal_handler_t handler, void *userdata);
+*/
+static std::function<int(sd_event *event, sd_event_source **source,
+ int signal, sd_event_signal_handler_t handler, void *userdata)> _sd_event_add_signal;
+
+/*
+int sd_event_add_io(sd_event *event, sd_event_source **source, int fd,
+ uint32_t events, sd_event_io_handler_t handler, void *userdata);
+int sd_event_source_get_io_fd(sd_event_source *source);
+int sd_event_source_set_io_fd_own(sd_event_source *source, int b);
+*/
+static std::function<int(sd_event *event, sd_event_source **source, int fd,
+ uint32_t events, sd_event_io_handler_t handler, void *userdata)>
+ _sd_event_add_io;
+static std::function<int(sd_event_source *source)> _sd_event_source_get_io_fd;
+static std::function<int(sd_event_source *source, int b)> _sd_event_source_set_io_fd_own;
+
+
+/*
+int sd_event_source_set_time(sd_event_source *source, uint64_t usec);
+int sd_event_now(sd_event *event, clockid_t clock, uint64_t *usec);
+int sd_event_add_time( sd_event *event,
+ sd_event_source **source,
+ clockid_t clock,
+ uint64_t usec,
+ uint64_t accuracy,
+ sd_event_time_handler_t handler,
+ void *userdata);
+int sd_event_source_set_enabled(sd_event_source *source, int enabled);
+*/
+static std::function<int(sd_event_source *source, uint64_t usec)> _sd_event_source_set_time;
+static std::function<int(sd_event *event, clockid_t clock, uint64_t *usec)> _sd_event_now;
+static std::function<int(sd_event *event, sd_event_source **source, clockid_t clock,
+ uint64_t usec, uint64_t accuracy, sd_event_time_handler_t handler, void *userdata)> _sd_event_add_time;
+static std::function<int(sd_event_source *source, int enabled)> _sd_event_source_set_enabled;
+
+
+/*
+sd_event_source* sd_event_source_unref(sd_event_source *source);
+sd_event_source* sd_event_source_ref(sd_event_source *source);
+sd_event_source* sd_event_source_disable_unref(sd_event_source *source);
+*/
+static std::function<sd_event_source*(sd_event_source *source)> _sd_event_source_unref;
+static std::function<sd_event_source*(sd_event_source *source)> _sd_event_source_ref;
+static std::function<sd_event_source*(sd_event_source *source)> _sd_event_source_disable_unref;
+
+
+class LibsystemdMocker {
+public:
+ LibsystemdMocker() {
+ _sd_event_add_signal
+ = [this](sd_event *event, sd_event_source **source, int signal,
+ sd_event_signal_handler_t handler, void *userdata) {
+ return sd_event_add_signal(event, source, signal, handler, userdata);
+ };
+
+ _sd_event_add_io
+ = [this](sd_event *event, sd_event_source **source, int fd,
+ uint32_t events, sd_event_io_handler_t handler, void *userdata) {
+ return sd_event_add_io(event, source, fd, events, handler, userdata);
+ };
+ _sd_event_source_get_io_fd = [this](sd_event_source *source) {
+ return sd_event_source_get_io_fd(source);
+ };
+ _sd_event_source_set_io_fd_own = [this](sd_event_source *source, int b) {
+ return sd_event_source_set_io_fd_own(source, b);
+ };
+
+ _sd_event_source_set_time = [this](sd_event_source *source, uint64_t usec) {
+ return sd_event_source_set_time(source, usec);
+ };
+ _sd_event_now = [this](sd_event *event, clockid_t clock, uint64_t *usec) {
+ return sd_event_now(event, clock, usec);
+ };
+ _sd_event_add_time
+ = [this](sd_event *event, sd_event_source **source, clockid_t clock, uint64_t usec,
+ uint64_t accuracy, sd_event_time_handler_t handler, void *userdata) {
+ return sd_event_add_time(event, source, clock, usec, accuracy, handler, userdata);
+ };
+ _sd_event_source_set_enabled = [this](sd_event_source *source, int enabled) {
+ return sd_event_source_set_enabled(source, enabled);
+ };
+
+ _sd_event_source_unref = [this](sd_event_source *source) {
+ return sd_event_source_unref(source);
+ };
+ _sd_event_source_ref = [this](sd_event_source *source) {
+ return sd_event_source_ref(source);
+ };
+ _sd_event_source_disable_unref = [this](sd_event_source *source) {
+ return sd_event_source_disable_unref(source);
+ };
+ }
+
+ ~LibsystemdMocker() {
+ _sd_event_add_signal = {};
+
+ _sd_event_add_io = {};
+ _sd_event_source_get_io_fd = {};
+ _sd_event_source_set_io_fd_own = {};
+
+ _sd_event_source_set_time = {};
+ _sd_event_now = {};
+ _sd_event_add_time = {};
+ _sd_event_source_set_enabled = {};
+
+ _sd_event_source_unref = {};
+ _sd_event_source_ref = {};
+ _sd_event_source_disable_unref = {};
+ }
+
+ MOCK_CONST_METHOD5(sd_event_add_signal, int(sd_event *event, sd_event_source **source, int signal, sd_event_signal_handler_t handler, void *userdata));
+
+ MOCK_CONST_METHOD6(sd_event_add_io, int(sd_event *event, sd_event_source **source, int fd, uint32_t events, sd_event_io_handler_t handler, void *userdata));
+ MOCK_CONST_METHOD1(sd_event_source_get_io_fd, int(sd_event_source *source));
+ MOCK_CONST_METHOD2(sd_event_source_set_io_fd_own, int(sd_event_source *source, int b));
+
+ MOCK_CONST_METHOD2(sd_event_source_set_time, int(sd_event_source *source, uint64_t usec));
+ MOCK_CONST_METHOD3(sd_event_now, int(sd_event *event, clockid_t clock, uint64_t *usec));
+ MOCK_CONST_METHOD7(sd_event_add_time, int(sd_event *event,sd_event_source **source, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t handler, void *userdata));
+ MOCK_CONST_METHOD2(sd_event_source_set_enabled, int(sd_event_source *source, int enabled));
+
+ MOCK_CONST_METHOD1(sd_event_source_unref, sd_event_source*(sd_event_source *source));
+ MOCK_CONST_METHOD1(sd_event_source_ref, sd_event_source*(sd_event_source *source));
+ MOCK_CONST_METHOD1(sd_event_source_disable_unref, sd_event_source*(sd_event_source *source));
+};
+
+class LibsystemdMockBase {
+protected:
+ LibsystemdMocker lsm;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int sd_event_add_signal( sd_event *event,
+ sd_event_source **source,
+ int signal,
+ sd_event_signal_handler_t handler,
+ void *userdata)
+{
+ return _sd_event_add_signal(event, source, signal, handler, userdata);
+}
+
+int sd_event_add_io(sd_event *event, sd_event_source **source, int fd,
+ uint32_t events, sd_event_io_handler_t handler, void *userdata)
+{
+ return _sd_event_add_io(event, source, fd, events, handler, userdata);
+}
+
+int sd_event_source_get_io_fd( sd_event_source *source)
+{
+ return _sd_event_source_get_io_fd(source);
+}
+
+int sd_event_source_set_io_fd_own(sd_event_source *source, int b)
+{
+ return _sd_event_source_set_io_fd_own(source, b);
+}
+
+int sd_event_source_set_time(sd_event_source *source, uint64_t usec)
+{
+ return _sd_event_source_set_time(source, usec);
+}
+
+int sd_event_now(sd_event *event, clockid_t clock, uint64_t *usec)
+{
+ return _sd_event_now(event, clock, usec);
+}
+
+int sd_event_add_time(sd_event *event, sd_event_source **source, clockid_t clock, uint64_t usec,
+ uint64_t accuracy, sd_event_time_handler_t handler, void *userdata)
+{
+ return _sd_event_add_time(event, source, clock, usec, accuracy, handler, userdata);
+}
+
+int sd_event_source_set_enabled(sd_event_source *source, int enabled)
+{
+ return _sd_event_source_set_enabled(source, enabled);
+}
+
+sd_event_source* sd_event_source_unref(sd_event_source *source)
+{
+ return _sd_event_source_unref(source);
+}
+
+sd_event_source* sd_event_source_ref(sd_event_source *source)
+{
+ return _sd_event_source_ref(source);
+}
+
+sd_event_source* sd_event_source_disable_unref(sd_event_source *source)
+{
+ return _sd_event_source_disable_unref(source);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/test/mock/syscall_io_mock.hpp b/test/mock/syscall_io_mock.hpp
new file mode 100644
index 0000000..75efdb1
--- /dev/null
+++ b/test/mock/syscall_io_mock.hpp
@@ -0,0 +1,156 @@
+#include <gmock/gmock.h>
+#include <functional>
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/*
+ssize_t read(int fd, void *buf, size_t count);
+ssize_t write(int fd, const void *buf, size_t count);
+int close(int fd);
+*/
+static std::function<ssize_t(int fd, void *buf, size_t count)> _read;
+static std::function<ssize_t(int fd, const void *buf, size_t count)> _write;
+static std::function<int(int)> _close;
+
+/*
+int unlink(const char *pathname);
+int stat(const char *pathname, struct stat *buf);
+*/
+static std::function<int(const char *)> _unlink;
+static std::function<int(const char *pathname, struct stat *buf)> _stat;
+
+
+/*
+int socket(int socket_family, int socket_type, int protocol);
+int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
+int listen(int sockfd, int backlog);
+int accept4(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen, int flags);
+*/
+static std::function<int(int socket_family, int socket_type, int protocol)> _socket;
+static std::function<int(int sockfd, const struct sockaddr *addr,socklen_t addrlen)> _bind;
+static std::function<int(int sockfd, int backlog)> _listen;
+static std::function<int(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen, int flags)> _accept4;
+
+class SyscallIOMocker {
+public:
+ SyscallIOMocker() {
+ _read = [this](int fd, void *buf, size_t count) {
+ return read(fd, buf, count);
+ };
+ _write = [this](int fd, const void *buf, size_t count) {
+ return write(fd, buf, count);
+ };
+ _close = [this](int fd){
+ return close(fd);
+ };
+
+ _unlink = [this](const char *pathname){
+ return unlink(pathname);
+ };
+ _stat = [this](const char *pathname, struct stat *buf) {
+ return stat(pathname, buf);
+ };
+
+ _socket = [this](int socket_family, int socket_type, int protocol){
+ return socket(socket_family, socket_type, protocol);
+ };
+ _bind = [this](int sockfd, const struct sockaddr *addr,socklen_t addrlen){
+ return bind(sockfd, addr,addrlen);
+ };
+ _listen = [this](int sockfd, int backlog){
+ return listen(sockfd, backlog);
+ };
+ _accept4
+ = [this](int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
+ return accept4(sockfd, addr, addrlen, flags);
+ };
+ }
+
+ ~SyscallIOMocker() {
+ _read = {};
+ _write = {};
+ _close = {};
+
+ _unlink = {};
+ _stat = {};
+
+ _socket = {};
+ _bind = {};
+ _listen = {};
+ _accept4 = {};
+ }
+
+ MOCK_CONST_METHOD3(read, ssize_t(int fd, void *buf, size_t count));
+ MOCK_CONST_METHOD3(write, ssize_t(int fd, const void *buf, size_t count));
+ MOCK_CONST_METHOD1(close, int(int));
+
+ MOCK_CONST_METHOD1(unlink, int(const char *));
+ MOCK_CONST_METHOD2(stat, int(const char *pathname, struct stat *buf));
+
+ MOCK_CONST_METHOD3(socket, int(int socket_family, int socket_type, int protocol));
+ MOCK_CONST_METHOD3(bind, int(int sockfd, const struct sockaddr *addr,socklen_t addrlen));
+ MOCK_CONST_METHOD2(listen, int(int sockfd, int backlog));
+ MOCK_CONST_METHOD4(accept4, int(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags));
+};
+
+class SyscallIOMockBase {
+protected:
+ SyscallIOMocker sysiom;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ssize_t read(int fd, void *buf, size_t count)
+{
+ return _read(fd, buf, count);
+}
+
+ssize_t write(int fd, const void *buf, size_t count)
+{
+ return _write(fd, buf, count);
+}
+
+int close(int fd)
+{
+ return _close(fd);
+}
+
+int unlink(const char *pathname)
+{
+ return _unlink(pathname);
+}
+
+int stat(const char *pathname, struct stat *buf)
+{
+ return _stat(pathname, buf);
+}
+
+int socket(int socket_family, int socket_type, int protocol)
+{
+ return _socket(socket_family, socket_type, protocol);
+}
+
+int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen)
+{
+ return _bind(sockfd, addr, addrlen);
+}
+
+int listen(int sockfd, int backlog)
+{
+ return _listen(sockfd, backlog);
+}
+
+int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
+{
+ return _accept4(sockfd, addr, addrlen, flags);
+}
+
+#ifdef __cplusplus
+}
+#endif