[Test] add testcase using gst-harness
authorJaeyun <jy1210.jung@samsung.com>
Thu, 8 Nov 2018 12:25:52 +0000 (21:25 +0900)
committerjaeyun-jung <39614140+jaeyun-jung@users.noreply.github.com>
Fri, 9 Nov 2018 08:36:04 +0000 (17:36 +0900)
Added new testcases using gst-harness.
If needs to test simple data conversion in nnstreamer plugins, add tc in unittest_plugins.

Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
packaging/nnstreamer.spec
tests/CMakeLists.txt
tests/nnstreamer_plugins/unittest_plugins.cpp [new file with mode: 0644]

index 383a037..829f0e4 100644 (file)
@@ -95,6 +95,7 @@ export LD_LIBRARY_PATH=$(pwd):$(pwd)/gst/tensor_filter
 make %{?_smp_mflags}
 ./tests/unittest_common
 ./tests/unittest_sink --gst-plugin-path=.
+./tests/unittest_plugins --gst-plugin-path=.
 popd
 pushd tests
 # The ssat requires 6~7min to run armv7l binary files in the current CI server.
index a6fbd3a..6ce303b 100644 (file)
@@ -40,6 +40,10 @@ TARGET_LINK_LIBRARIES(unittest_sink ${pkgs_LIBRARIES} ${testpkgs_LIBRARIES} ${gt
 ADD_LIBRARY(nnscustom_framecounter SHARED nnstreamer_sink/nnscustom_framecounter.c)
 TARGET_LINK_LIBRARIES(nnscustom_framecounter ${CUSTOMFILTERDEP})
 
+# Unit test for nnstreamer plugins
+ADD_EXECUTABLE(unittest_plugins nnstreamer_plugins/unittest_plugins.cpp ${gtestSrc})
+TARGET_INCLUDE_DIRECTORIES(unittest_plugins PUBLIC ${pkgs_INCLUDE_DIRS} ${testpkgs_INCLUDE_DIRS} ${gtestInc})
+TARGET_LINK_LIBRARIES(unittest_plugins ${pkgs_LIBRARIES} ${testpkgs_LIBRARIES} ${gtestLink})
 
 ADD_TEST(NAME unit_test
         COMMAND sh -c "GST_PLUGIN_PATH=${PROJECT_SOURCE_DIR}/build ssat ${CMAKE_CURRENT_SOURCE_DIR}")
diff --git a/tests/nnstreamer_plugins/unittest_plugins.cpp b/tests/nnstreamer_plugins/unittest_plugins.cpp
new file mode 100644 (file)
index 0000000..e2e3ad7
--- /dev/null
@@ -0,0 +1,323 @@
+/**
+ * @file       unittest_plugins.cpp
+ * @date       7 November 2018
+ * @brief      Unit test for nnstreamer plugins. (testcases to check data conversion or buffer transfer)
+ * @see                https://github.com/nnsuite/nnstreamer
+ * @author     Jaeyun Jung <jy1210.jung@samsung.com>
+ * @bug                No known bugs.
+ */
+
+#include <string.h>
+#include <gtest/gtest.h>
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+#include <gst/check/gsttestclock.h>
+#include <gst/check/gstharness.h>
+#include <tensor_common.h>
+
+/**
+ * @brief Macro for debug mode.
+ */
+#ifndef DBG
+#define DBG FALSE
+#endif
+
+/**
+ * @brief Macro for debug message.
+ */
+#define _print_log(...) if (DBG) g_message (__VA_ARGS__)
+
+/**
+ * @brief Test for tensor_transform typecast (uint8 > uint32)
+ */
+TEST (test_tensor_transform, typecast_1)
+{
+  const guint num_buffers = 3;
+  const guint array_size = 5;
+
+  GstHarness *h;
+  GstBuffer *in_buf, *out_buf;
+  GstTensorConfig config;
+  GstMemory *mem;
+  GstMapInfo info;
+  guint i, b;
+  gsize data_in_size, data_out_size;
+
+  h = gst_harness_new ("tensor_transform");
+
+  g_object_set (h->element, "mode", "typecast", "option", "uint32", NULL);
+
+  /* input tensor info */
+  config.info.type = _NNS_UINT8;
+  get_tensor_dimension ("5", config.info.dimension);
+  config.rate_n = 0;
+  config.rate_d = 1;
+
+  gst_harness_set_src_caps (h, gst_tensor_caps_from_config (&config));
+  data_in_size = gst_tensor_info_get_size (&config.info);
+
+  config.info.type = _NNS_UINT32;
+  data_out_size = gst_tensor_info_get_size (&config.info);
+
+  /* push buffers */
+  for (b = 0; b < num_buffers; b++) {
+    /* set input buffer */
+    in_buf = gst_harness_create_buffer (h, data_in_size);
+
+    mem = gst_buffer_peek_memory (in_buf, 0);
+    ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_WRITE));
+
+    for (i = 0; i < array_size; i++) {
+      uint8_t value = (i + 1) * (b + 1);
+      ((uint8_t *) info.data)[i] = value;
+    }
+
+    gst_memory_unmap (mem, &info);
+
+    EXPECT_EQ (gst_harness_push (h, in_buf), GST_FLOW_OK);
+
+    /* get output buffer */
+    out_buf = gst_harness_pull (h);
+
+    ASSERT_TRUE (out_buf != NULL);
+    ASSERT_EQ (gst_buffer_n_memory (out_buf), 1);
+    ASSERT_EQ (gst_buffer_get_size (out_buf), data_out_size);
+
+    mem = gst_buffer_peek_memory (out_buf, 0);
+    ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+
+    for (i = 0; i < array_size; i++) {
+      uint32_t expected = (i + 1) * (b + 1);
+      EXPECT_EQ (((uint32_t *) info.data)[i], expected);
+    }
+
+    gst_memory_unmap (mem, &info);
+    gst_buffer_unref (out_buf);
+  }
+
+  EXPECT_EQ (gst_harness_buffers_received (h), num_buffers);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_transform typecast (uint32 > float64)
+ */
+TEST (test_tensor_transform, typecast_2)
+{
+  const guint num_buffers = 3;
+  const guint array_size = 5;
+
+  GstHarness *h;
+  GstBuffer *in_buf, *out_buf;
+  GstTensorConfig config;
+  GstMemory *mem;
+  GstMapInfo info;
+  guint i, b;
+  gsize data_in_size, data_out_size;
+
+  h = gst_harness_new ("tensor_transform");
+
+  g_object_set (h->element, "mode", "typecast", "option", "float64", NULL);
+
+  /* input tensor info */
+  config.info.type = _NNS_UINT32;
+  get_tensor_dimension ("5", config.info.dimension);
+  config.rate_n = 0;
+  config.rate_d = 1;
+
+  gst_harness_set_src_caps (h, gst_tensor_caps_from_config (&config));
+  data_in_size = gst_tensor_info_get_size (&config.info);
+
+  config.info.type = _NNS_FLOAT64;
+  data_out_size = gst_tensor_info_get_size (&config.info);
+
+  /* push buffers */
+  for (b = 0; b < num_buffers; b++) {
+    /* set input buffer */
+    in_buf = gst_harness_create_buffer (h, data_in_size);
+
+    mem = gst_buffer_peek_memory (in_buf, 0);
+    ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_WRITE));
+
+    for (i = 0; i < array_size; i++) {
+      uint32_t value = (i + 1) * (b + 1);
+      ((uint32_t *) info.data)[i] = value;
+    }
+
+    gst_memory_unmap (mem, &info);
+
+    EXPECT_EQ (gst_harness_push (h, in_buf), GST_FLOW_OK);
+
+    /* get output buffer */
+    out_buf = gst_harness_pull (h);
+
+    ASSERT_TRUE (out_buf != NULL);
+    ASSERT_EQ (gst_buffer_n_memory (out_buf), 1);
+    ASSERT_EQ (gst_buffer_get_size (out_buf), data_out_size);
+
+    mem = gst_buffer_peek_memory (out_buf, 0);
+    ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+
+    for (i = 0; i < array_size; i++) {
+      double expected = (i + 1) * (b + 1);
+      EXPECT_EQ (((double *) info.data)[i], expected);
+    }
+
+    gst_memory_unmap (mem, &info);
+    gst_buffer_unref (out_buf);
+  }
+
+  EXPECT_EQ (gst_harness_buffers_received (h), num_buffers);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_transform arithmetic (float32, add .5)
+ */
+TEST (test_tensor_transform, arithmetic_1)
+{
+  const guint num_buffers = 3;
+  const guint array_size = 5;
+
+  GstHarness *h;
+  GstBuffer *in_buf, *out_buf;
+  GstTensorConfig config;
+  GstMemory *mem;
+  GstMapInfo info;
+  guint i, b;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_transform");
+
+  g_object_set (h->element, "mode", "arithmetic", "option", "add:.5", NULL);
+
+  /* input tensor info */
+  config.info.type = _NNS_FLOAT32;
+  get_tensor_dimension ("5", config.info.dimension);
+  config.rate_n = 0;
+  config.rate_d = 1;
+
+  gst_harness_set_src_caps (h, gst_tensor_caps_from_config (&config));
+  data_size = gst_tensor_info_get_size (&config.info);
+
+  /* push buffers */
+  for (b = 0; b < num_buffers; b++) {
+    /* set input buffer */
+    in_buf = gst_harness_create_buffer (h, data_size);
+
+    mem = gst_buffer_peek_memory (in_buf, 0);
+    ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_WRITE));
+
+    for (i = 0; i < array_size; i++) {
+      float value = (i + 1) * (b + 1) + .2;
+      ((float *) info.data)[i] = value;
+    }
+
+    gst_memory_unmap (mem, &info);
+
+    EXPECT_EQ (gst_harness_push (h, in_buf), GST_FLOW_OK);
+
+    /* get output buffer */
+    out_buf = gst_harness_pull (h);
+
+    ASSERT_TRUE (out_buf != NULL);
+    ASSERT_EQ (gst_buffer_n_memory (out_buf), 1);
+    ASSERT_EQ (gst_buffer_get_size (out_buf), data_size);
+
+    mem = gst_buffer_peek_memory (out_buf, 0);
+    ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+
+    for (i = 0; i < array_size; i++) {
+      float expected = (i + 1) * (b + 1) + .2 + .5;
+      EXPECT_EQ (((float *) info.data)[i], expected);
+    }
+
+    gst_memory_unmap (mem, &info);
+    gst_buffer_unref (out_buf);
+  }
+
+  EXPECT_EQ (gst_harness_buffers_received (h), num_buffers);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_transform arithmetic (float64, mul .5)
+ */
+TEST (test_tensor_transform, arithmetic_2)
+{
+  const guint num_buffers = 3;
+  const guint array_size = 5;
+
+  GstHarness *h;
+  GstBuffer *in_buf, *out_buf;
+  GstTensorConfig config;
+  GstMemory *mem;
+  GstMapInfo info;
+  guint i, b;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_transform");
+
+  g_object_set (h->element, "mode", "arithmetic", "option", "mul:.5", NULL);
+
+  /* input tensor info */
+  config.info.type = _NNS_FLOAT64;
+  get_tensor_dimension ("5", config.info.dimension);
+  config.rate_n = 0;
+  config.rate_d = 1;
+
+  gst_harness_set_src_caps (h, gst_tensor_caps_from_config (&config));
+  data_size = gst_tensor_info_get_size (&config.info);
+
+  /* push buffers */
+  for (b = 0; b < num_buffers; b++) {
+    /* set input buffer */
+    in_buf = gst_harness_create_buffer (h, data_size);
+
+    mem = gst_buffer_peek_memory (in_buf, 0);
+    ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_WRITE));
+
+    for (i = 0; i < array_size; i++) {
+      double value = (i + 1) * (b + 1) + .2;
+      ((double *) info.data)[i] = value;
+    }
+
+    gst_memory_unmap (mem, &info);
+
+    EXPECT_EQ (gst_harness_push (h, in_buf), GST_FLOW_OK);
+
+    /* get output buffer */
+    out_buf = gst_harness_pull (h);
+
+    ASSERT_TRUE (out_buf != NULL);
+    ASSERT_EQ (gst_buffer_n_memory (out_buf), 1);
+    ASSERT_EQ (gst_buffer_get_size (out_buf), data_size);
+
+    mem = gst_buffer_peek_memory (out_buf, 0);
+    ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+
+    for (i = 0; i < array_size; i++) {
+      double expected = ((i + 1) * (b + 1) + .2) * .5;
+      EXPECT_EQ (((double *) info.data)[i], expected);
+    }
+
+    gst_memory_unmap (mem, &info);
+    gst_buffer_unref (out_buf);
+  }
+
+  EXPECT_EQ (gst_harness_buffers_received (h), num_buffers);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Main function for unit test.
+ */
+int
+main (int argc, char **argv)
+{
+  testing::InitGoogleTest (&argc, argv);
+
+  gst_init (&argc, &argv);
+
+  return RUN_ALL_TESTS ();
+}