[TEST/ntp] Add ntp unittest using GMock.
authorgichan <gichan2.jang@samsung.com>
Tue, 19 Apr 2022 10:24:08 +0000 (19:24 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Fri, 29 Apr 2022 03:02:20 +0000 (12:02 +0900)
Add ntp uniitest using GMock.

Signed-off-by: gichan <gichan2.jang@samsung.com>
gst/mqtt/meson.build
gst/mqtt/ntputil.c
gst/mqtt/ntputil.h
tests/gstreamer_mqtt/unittest_ntp_util_mock.cc [new file with mode: 0644]
tests/meson.build

index 743e40a..ba9642c 100644 (file)
@@ -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('.'))
index 6f55a9b..0eba438 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <errno.h>
 #include <netdb.h>
-#include <netinet/ip.h>
+#include <arpa/inet.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -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
index 69c35a2..899f3e1 100644 (file)
  * @author  Wook Song <wook16.song@samsung.com>
  * @bug     No known bugs except for NYI items
  */
+#ifndef __NNS_NTP_UTIL_H__
+#define __NNS_NTP_UTIL_H__
 
 #include <stdint.h>
 #include <time.h>
-
+#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,
  */
 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 (file)
index 0000000..05acf97
--- /dev/null
@@ -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 <gichan2.jang@samsung.com>
+ * @bug         No known bugs
+ */
+
+#include <glib.h>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <unittest_util.h>
+#include "../gst/mqtt/ntputil.h"
+#include "ntputil.h"
+
+#include <errno.h>
+#include <netdb.h>
+
+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::<unnamed>::ClassUniqueToAlwaysTrue'");
+  }
+
+  try {
+    result = RUN_ALL_TESTS ();
+  } catch (...) {
+    g_warning ("catch `testing::internal::GoogleTestFailureException`");
+  }
+
+  return result;
+}
index 5118b41..2c2ef21 100644 (file)
@@ -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