From: gichan Date: Tue, 19 Apr 2022 10:24:08 +0000 (+0900) Subject: [TEST/ntp] Add ntp unittest using GMock. X-Git-Tag: accepted/tizen/unified/20220526.143642~13 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=16f8b9549d8f3c096846bff4c30e1ef0d656023c;p=platform%2Fupstream%2Fnnstreamer.git [TEST/ntp] Add ntp unittest using GMock. Add ntp uniitest using GMock. Signed-off-by: gichan --- diff --git a/gst/mqtt/meson.build b/gst/mqtt/meson.build index 743e40a..ba9642c 100644 --- a/gst/mqtt/meson.build +++ b/gst/mqtt/meson.build @@ -16,8 +16,5 @@ gstmqtt_shared = shared_library('gstmqtt', install_dir: plugins_install_dir ) -# gstmqtt_shared is a GStreamer plugin so that providing runtime dependency is not necessary. -# This dependency is needed to let the class that mocks the MQTT library use the internal header files. -gstmqtt_mocking_dep = declare_dependency( - include_directories: '.', -) +gstmqtt_dep = declare_dependency(link_with: gstmqtt_shared, + include_directories: include_directories('.')) diff --git a/gst/mqtt/ntputil.c b/gst/mqtt/ntputil.c index 6f55a9b..0eba438 100644 --- a/gst/mqtt/ntputil.c +++ b/gst/mqtt/ntputil.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -120,6 +120,15 @@ const char NTPUTIL_DEFAULT_HNAME[] = "pool.ntp.org"; const uint16_t NTPUTIL_DEFAULT_PORT = 123; /** + * @brief Wrapper function of ntohl. + */ +uint32_t +_convert_to_host_byte_order (uint32_t in) +{ + return ntohl (in); +} + +/** * @brief Get NTP timestamps from the given or public NTP servers * @param[in] hnums A number of hostname and port pairs. If 0 is given, * the NTP server pool will be used. @@ -208,8 +217,8 @@ ntputil_get_epoch (uint32_t hnums, char **hnames, uint16_t * ports) * such as microsceonds. Note that the bit/byte order of those data should * be converted to the host's endianness. */ - recv_sec = ntohl (packet.xmit_ts.sec); - recv_frac = ntohl (packet.xmit_ts.frac); + recv_sec = _convert_to_host_byte_order (packet.xmit_ts.sec); + recv_frac = _convert_to_host_byte_order (packet.xmit_ts.frac); /** * @note NTP uses an epoch of January 1, 1900 while the Unix epoch is diff --git a/gst/mqtt/ntputil.h b/gst/mqtt/ntputil.h index 69c35a2..899f3e1 100644 --- a/gst/mqtt/ntputil.h +++ b/gst/mqtt/ntputil.h @@ -10,10 +10,14 @@ * @author Wook Song * @bug No known bugs except for NYI items */ +#ifndef __NNS_NTP_UTIL_H__ +#define __NNS_NTP_UTIL_H__ #include #include - +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ /** * @brief Get NTP timestamps from the given or public NTP servers * @param[in] hnums A number of hostname and port pairs. If 0 is given, @@ -25,3 +29,15 @@ */ int64_t ntputil_get_epoch (uint32_t hnums, char **hnames, uint16_t * ports); + +/** + * @brief Converting network byte order to host byte order. + * @note There is a problem in mocking ntohl in GMock, so the wrapper function is temporarily used. + * */ +uint32_t +_convert_to_host_byte_order (uint32_t in); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __NNS_NTP_UTIL_H__ */ diff --git a/tests/gstreamer_mqtt/unittest_ntp_util_mock.cc b/tests/gstreamer_mqtt/unittest_ntp_util_mock.cc new file mode 100644 index 0000000..05acf97 --- /dev/null +++ b/tests/gstreamer_mqtt/unittest_ntp_util_mock.cc @@ -0,0 +1,310 @@ +/* SPDX-License-Identifier: LGPL-2.1-only */ +/** + * @file unittest_ntp_util_mock.cc + * @date 25 Apr 2022 + * @brief Unit test for ntp util using GMock. + * @see https://github.com/nnstreamer/nnstreamer + * @author Gichan Jang + * @bug No known bugs + */ + +#include +#include +#include +#include +#include "../gst/mqtt/ntputil.h" +#include "ntputil.h" + +#include +#include + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::Assign; +using ::testing::SetErrnoAndReturn; + +const uint64_t NTPUTIL_TIMESTAMP_DELTA = 2208988800ULL; + +/** + * @brief Interface for NTP util mock class + */ +class INtpUtil { +public: + /** + * @brief Destroy the INtpUtil object + */ + virtual ~INtpUtil () {}; + virtual struct hostent *gethostbyname (const char *name) = 0; + virtual int connect (int sockfd, const struct sockaddr *addr, + socklen_t addrlen) = 0; + virtual ssize_t write (int fd, const void *buf, size_t count) = 0; + virtual ssize_t read (int fd, void *buf, size_t count) = 0; + virtual uint32_t _convert_to_host_byte_order (uint32_t netlong) = 0; +}; + +/** + * @brief Mock class for testing ntp util + */ +class NtpUtilMock : public INtpUtil { +public: + MOCK_METHOD (struct hostent *, gethostbyname, (const char *name)); + MOCK_METHOD (int, connect, (int sockfd, const struct sockaddr *addr, + socklen_t addrlen)); + MOCK_METHOD (ssize_t, write, (int fd, const void *buf, size_t count)); + MOCK_METHOD (ssize_t, read, (int fd, void *buf, size_t count)); + MOCK_METHOD (uint32_t, _convert_to_host_byte_order, (uint32_t netlong)); +}; +NtpUtilMock *mockInstance = nullptr; + +/** + * @brief Mocking function for gethostbyname + */ +struct hostent *gethostbyname (const char *name) +{ + return mockInstance->gethostbyname (name); +} + +/** + * @brief Mocking function for gethostbyname + */ +int connect (int sockfd, const struct sockaddr *addr, + socklen_t addrlen) +{ + return mockInstance->connect (sockfd, addr, addrlen); +} + +/** @note To avoid redundant declaration in the test */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +/** + * @brief Mocking function for write. + */ +ssize_t write (int fd, const void *buf, size_t count) +{ + return mockInstance->write (fd, buf, count); +} + +/** + * @brief Mocking function for read. + */ +ssize_t read (int fd, void *buf, size_t count) +{ + return mockInstance->read (fd, buf, count); +} +#pragma GCC diagnostic pop + +/** + * @brief Mocking function for _convert_to_host_byte_order. + */ +uint32_t _convert_to_host_byte_order (uint32_t netlong) +{ + return mockInstance->_convert_to_host_byte_order (netlong); +} + + +/** + * @brief ntp util testing base class + */ +class ntpUtilMockTest : public ::testing::Test +{ + protected: + struct hostent host; + /** + * @brief Sets up the base fixture + */ + void SetUp () override + { + host.h_name = g_strdup ("github.com"); + host.h_aliases = (char **) calloc (1, sizeof (char *)); + host.h_aliases[0] = g_strdup ("www.github.com"); + host.h_addrtype = AF_INET; + host.h_length = 4; + host.h_addr_list = (char **) calloc (1, sizeof (char *)); + host.h_addr_list[0] = g_strdup ("52.78.231.108"); + } + /** + * @brief tear down the base fixture + */ + void TearDown () + { + g_free (host.h_name); + g_free (host.h_aliases[0]); + g_free (host.h_aliases); + g_free (host.h_addr_list[0]); + g_free (host.h_addr_list); + } +}; + +/** + * @brief Test for ntp util to get epoch. + */ +TEST_F (ntpUtilMockTest, getEpochNormal_p) +{ + int64_t ret; + const char *hnames[] = {"temp"}; + uint16_t ports[] = {8080U}; + + mockInstance = new NtpUtilMock (); + + EXPECT_CALL (*mockInstance, gethostbyname(_)) + .Times(1).WillOnce(Return((struct hostent *)&host)); + EXPECT_CALL (*mockInstance, connect(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, write(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, read(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, _convert_to_host_byte_order(_)) + .Times(2) + .WillOnce(Return(NTPUTIL_TIMESTAMP_DELTA + 1ULL)) + .WillOnce(Return(1ULL)); + + ret = ntputil_get_epoch (1, (char **)hnames, ports); + + EXPECT_GE (ret, 0); + + delete mockInstance; +} + +/** + * @brief Test for ntp util to get epoch when failed to get host name. + */ +TEST_F (ntpUtilMockTest, getEpochHostNameFail_n) +{ + int64_t ret; + + mockInstance = new NtpUtilMock (); + + EXPECT_CALL (*mockInstance, gethostbyname(_)) + .Times(1) + .WillOnce(DoAll( + testing::Assign(&h_errno, HOST_NOT_FOUND), + Return (nullptr))); + + ret = ntputil_get_epoch (0, nullptr, nullptr); + EXPECT_LT (ret, 0); + + delete mockInstance; +} + +/** + * @brief Test for ntp util to get epoch when failed to connect. + */ +TEST_F (ntpUtilMockTest, getEpochConnectFail_n) +{ + int64_t ret; + + mockInstance = new NtpUtilMock (); + + EXPECT_CALL (*mockInstance, gethostbyname(_)) + .Times(1).WillOnce(Return((struct hostent *)&host)); + EXPECT_CALL (*mockInstance, connect(_, _, _)) + .Times(1).WillOnce(SetErrnoAndReturn(EINVAL, -1)); + + ret = ntputil_get_epoch (0, nullptr, nullptr); + EXPECT_LT (ret, 0); + + delete mockInstance; +} + +/** + * @brief Test for ntp util to get epoch when failed to write. + */ +TEST_F (ntpUtilMockTest, getEpochWriteFail_n) +{ + int64_t ret; + + mockInstance = new NtpUtilMock (); + + EXPECT_CALL (*mockInstance, gethostbyname(_)) + .Times(1).WillOnce(Return((struct hostent *)&host)); + EXPECT_CALL (*mockInstance, connect(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, write(_, _, _)) + .Times(1).WillOnce(SetErrnoAndReturn(EINVAL, -1)); + + ret = ntputil_get_epoch (0, nullptr, nullptr); + + EXPECT_LT (ret, 0); + + delete mockInstance; +} + +/** + * @brief Test for ntp util to get epoch failed to read. + */ +TEST_F (ntpUtilMockTest, getEpochReadFail_n) +{ + int64_t ret; + + mockInstance = new NtpUtilMock (); + + EXPECT_CALL (*mockInstance, gethostbyname(_)) + .Times(1).WillOnce(Return((struct hostent *)&host)); + EXPECT_CALL (*mockInstance, connect(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, write(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, read(_, _, _)) + .Times(1).WillOnce(SetErrnoAndReturn(EINVAL, -1)); + + ret = ntputil_get_epoch (0, nullptr, nullptr); + + EXPECT_LT (ret, 0); + + delete mockInstance; +} + +/** + * @brief Test for ntp util to get epoch. + */ +TEST_F (ntpUtilMockTest, getEpochIvalidTimestamp) +{ + int64_t ret; + + mockInstance = new NtpUtilMock (); + + EXPECT_CALL (*mockInstance, gethostbyname(_)) + .Times(1).WillOnce(Return((struct hostent *)&host)); + EXPECT_CALL (*mockInstance, connect(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, write(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, read(_, _, _)) + .Times(1).WillOnce(Return(0)); + EXPECT_CALL (*mockInstance, _convert_to_host_byte_order(_)) + .Times(2) + .WillOnce(Return(1ULL)) + .WillOnce(Return(1ULL)); + + ret = ntputil_get_epoch (0, nullptr, nullptr); + + EXPECT_LT (ret, 0); + + delete mockInstance; +} + +/** + * @brief Main GTest + */ +int +main (int argc, char **argv) +{ + int result = -1; + + try { + testing::InitGoogleTest (&argc, argv); + } catch (...) { + g_warning ("catch 'testing::internal::::ClassUniqueToAlwaysTrue'"); + } + + try { + result = RUN_ALL_TESTS (); + } catch (...) { + g_warning ("catch `testing::internal::GoogleTestFailureException`"); + } + + return result; +} diff --git a/tests/meson.build b/tests/meson.build index 5118b41..2c2ef21 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -147,7 +147,7 @@ if gtest_dep.found() if mqtt_support_is_available unittest_mqtt_w_helper = executable('unittest_mqtt_w_helper', join_paths('gstreamer_mqtt', 'unittest_mqtt_w_helper.cc'), - dependencies: [gstmqtt_mocking_dep, nnstreamer_unittest_deps], + dependencies: [gstmqtt_dep, nnstreamer_unittest_deps], install: get_option('install-test'), install_dir: unittest_install_dir) @@ -160,6 +160,18 @@ if gtest_dep.found() install_dir: unittest_install_dir) test('unittest_mqtt', unittest_mqtt, env: testenv) + + # ntp util test + gmock_dep = dependency('gmock', required: false) + if get_option('enable-tizen') and gmock_dep.found() + gstreamer_ntp_util_mock = executable('unittest_ntp_util', + join_paths('gstreamer_mqtt', 'unittest_ntp_util_mock.cc'), + dependencies: [nnstreamer_unittest_deps, gmock_dep, gstmqtt_dep], + install: get_option('install-test'), + install_dir: unittest_install_dir) + + test('gstreamer_ntp_util_mock', gstreamer_ntp_util_mock, env: testenv) + endif endif # Run unittest_src_iio