diff options
-rw-r--r-- | test/Makefile.am | 60 | ||||
-rw-r--r-- | test/file_util_test.cpp | 84 | ||||
-rw-r--r-- | test/fileop_test_utils.cpp | 275 | ||||
-rw-r--r-- | test/interface_test.cpp | 409 | ||||
-rw-r--r-- | test/interface_test_unit.cpp | 199 | ||||
-rw-r--r-- | test/mock/libpthread_mock.hpp | 93 | ||||
-rw-r--r-- | test/mock/libsystemd_mock.hpp | 208 | ||||
-rw-r--r-- | test/mock/syscall_io_mock.hpp | 156 |
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 |