[TEST] Add TC for datarepo and tensor_trainer validation
authorhyunil park <hyunil46.park@samsung.com>
Fri, 21 Apr 2023 04:22:11 +0000 (13:22 +0900)
committerSangjung Woo <again4you@gmail.com>
Fri, 21 Apr 2023 09:52:41 +0000 (18:52 +0900)
- Add datareposrc TC
- Add datareposink TC
- Add tensor_trainer TC

Signed-off-by: hyunil park <hyunil46.park@samsung.com>
tests/meson.build
tests/nnstreamer_datarepo/unittest_datareposink.cc [new file with mode: 0644]
tests/nnstreamer_datarepo/unittest_datareposrc.cc [new file with mode: 0644]
tests/nnstreamer_trainer/unittest_trainer.cc [new file with mode: 0644]
tests/test_models/data/datarepo/mnist.data [new file with mode: 0644]
tests/test_models/data/datarepo/mnist.ini [new file with mode: 0644]
tests/test_models/data/datarepo/mnist.json [new file with mode: 0644]

index 9218d3e..13822bf 100644 (file)
@@ -323,6 +323,37 @@ if gtest_dep.found()
 
     test('unittest_filter_shared_model', unittest_filter_shared_model, timeout: 30, env: testenv)
   endif
+
+  # Run unittest_datareposink
+  unittest_datareposink = executable('unittest_datareposink',
+    join_paths('nnstreamer_datarepo', 'unittest_datareposink.cc'),
+    dependencies: [nnstreamer_unittest_deps],
+    install: get_option('install-test'),
+    install_dir: unittest_install_dir
+  )
+
+  test('unittest_datareposink', unittest_datareposink, env: testenv)
+
+  # Run unittest_datareposrc
+  unittest_datareposrc = executable('unittest_datareposrc',
+    join_paths('nnstreamer_datarepo', 'unittest_datareposrc.cc'),
+    dependencies: [nnstreamer_unittest_deps],
+    install: get_option('install-test'),
+    install_dir: unittest_install_dir
+  )
+
+  test('unittest_datareposrc', unittest_datareposrc, env: testenv)
+
+  # Run unittest_trainer
+  unittest_trainer = executable('unittest_trainer',
+    join_paths('nnstreamer_trainer', 'unittest_trainer.cc'),
+    dependencies: [nnstreamer_unittest_deps],
+    install: get_option('install-test'),
+    install_dir: unittest_install_dir
+  )
+
+  test('unittest_trainer', unittest_trainer, env: testenv)
+
 endif # gtest_dep.found()
 
 tensor_filter_ext_enabled = tflite_support_is_available or \
diff --git a/tests/nnstreamer_datarepo/unittest_datareposink.cc b/tests/nnstreamer_datarepo/unittest_datareposink.cc
new file mode 100644 (file)
index 0000000..0d86846
--- /dev/null
@@ -0,0 +1,444 @@
+ /**
+ * @file        unittest_datareposink.cc
+ * @date        21 Apr 2023
+ * @brief       Unit test for datareposink
+ * @see         https://github.com/nnstreamer/nnstreamer
+ * @author      Hyunil Park <hyunil46.park@samsung.com>
+ * @bug         No known bugs
+ */
+
+#include <gtest/gtest.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+#include <unittest_util.h>
+
+static const gchar filename[] = "mnist.data";
+static const gchar json[] = "mnist.json";
+
+/**
+ * @brief Get file path
+ */
+static gchar *
+get_file_path (const gchar * filename)
+{
+  const gchar *root_path = NULL;
+  gchar *file_path = NULL;
+
+  root_path = g_getenv ("NNSTREAMER_SOURCE_ROOT_PATH");
+
+  /** supposed to run test in build directory */
+  if (root_path == NULL)
+    root_path = "..";
+
+  file_path =
+      g_build_filename (root_path, "tests", "test_models", "data", "datarepo",
+      filename, NULL);
+
+  return file_path;
+}
+
+
+/**
+ * @brief Bus callback function
+ */
+static gboolean
+bus_callback (GstBus * bus, GstMessage * message, gpointer data)
+{
+  switch (GST_MESSAGE_TYPE (message)) {
+    case GST_MESSAGE_EOS:
+      g_main_loop_quit ((GMainLoop *) data);
+      break;
+    default:
+      break;
+  }
+
+  return TRUE;
+}
+
+/**
+ * @brief Test for writing image files
+ */
+TEST (datareposink, writeImageFiles)
+{
+  GError *error = NULL;
+  GFile *file = NULL;
+  gchar *contents = NULL;
+  gchar *filename = NULL;
+  GstBus *bus;
+  GMainLoop *loop;
+  gint i = 0;
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 videotestsrc num-buffers=5 ! pngenc ! "
+      "datareposink location=image_%02d.png json=image.json");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+      UNITTEST_STATECHANGE_TIMEOUT);
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+
+  /* Confirm file creation */
+  for (i = 0; i < 5; i++) {
+    filename = g_strdup_printf ("image_%02d.png", i);
+    file = g_file_new_for_path (filename);
+    g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+    ASSERT_FALSE (error != NULL);
+  }
+
+  g_object_unref (file);
+  g_free (contents);
+  file = NULL;
+  g_free (filename);
+
+  /* Confirm file creation */
+  file = g_file_new_for_path ("image.json");
+  g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+  ASSERT_FALSE (error != NULL);
+
+  g_object_unref (file);
+  g_free (contents);
+}
+
+/**
+ * @brief Test for writing an audio raw file
+ */
+TEST (datareposink, writeAudioRaw)
+{
+  GError *error = NULL;
+  GFile *file = NULL;
+  gchar *contents = NULL;
+  GstBus *bus;
+  GMainLoop *loop;
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup
+      ("gst-launch-1.0 audiotestsrc samplesperbuffer=44100 num-buffers=1 ! "
+      "audio/x-raw, format=S16LE, layout=interleaved, rate=44100, channels=1 ! "
+      "datareposink location=audio.raw json=audio.json");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+      UNITTEST_STATECHANGE_TIMEOUT);
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+
+  /* Confirm file creation */
+  file = g_file_new_for_path ("audio.raw");
+  g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+  ASSERT_FALSE (error != NULL);
+
+  g_object_unref (file);
+  g_free (contents);
+  file = NULL;
+
+  /* Confirm file creation */
+  file = g_file_new_for_path ("audio.json");
+  g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+  ASSERT_FALSE (error != NULL);
+
+  g_object_unref (file);
+  g_free (contents);
+}
+
+/**
+ * @brief Test for writing a video raw file
+ */
+TEST (datareposink, writeVideoRaw)
+{
+  GError *error = NULL;
+  GFile *file = NULL;
+  gchar *contents = NULL;
+  GstBus *bus;
+  GMainLoop *loop;
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 videotestsrc num-buffers=10 ! "
+      "datareposink location=video.raw json=video.json");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+      UNITTEST_STATECHANGE_TIMEOUT);
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+
+  /* Confirm file creation */
+  file = g_file_new_for_path ("video.raw");
+  g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+  ASSERT_FALSE (error != NULL);
+
+  g_object_unref (file);
+  g_free (contents);
+  file = NULL;
+
+  /* Confirm file creation */
+  file = g_file_new_for_path ("video.json");
+  g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+  ASSERT_FALSE (error != NULL);
+
+  g_object_unref (file);
+  g_free (contents);
+}
+
+/**
+ * @brief Test for writing a Tensors file
+ */
+TEST (datareposink, writeTensors)
+{
+  GError *error = NULL;
+  GFile *file = NULL;
+  gchar *contents = NULL;
+  GstBus *bus;
+  GMainLoop *loop;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  GstElement *datareposink = NULL;
+  gchar *get_str = NULL;
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=0 stop-sample-index=9 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "datareposink name=datareposink location=mnist.data json=mnist.json",
+      file_path, json_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposink = gst_bin_get_by_name (GST_BIN (pipeline), "datareposink");
+  EXPECT_NE (datareposink, nullptr);
+
+  g_object_get (datareposink, "location", &get_str, NULL);
+  EXPECT_STREQ (get_str, "mnist.data");
+
+  g_object_get (datareposink, "json", &get_str, NULL);
+  EXPECT_STREQ (get_str, "mnist.json");
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+      UNITTEST_STATECHANGE_TIMEOUT);
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+
+  /* Confirm file creation */
+  file = g_file_new_for_path ("mnist.data");
+  g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+  ASSERT_FALSE (error != NULL);
+
+  g_object_unref (file);
+  g_free (contents);
+  file = NULL;
+
+  /* Confirm file creation */
+  file = g_file_new_for_path ("mnist.json");
+  g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+  ASSERT_FALSE (error != NULL);
+
+  g_free (contents);
+  g_object_unref (file);
+  g_free (file_path);
+  g_free (json_path);
+
+}
+
+/**
+ * @brief Test for writing a file with invalid param (JSON path)
+ */
+TEST (datareposink, invalidJsonPath0_n)
+{
+  GstElement *datareposink = NULL;
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 videotestsrc num-buffers=10 ! pngenc ! "
+      "datareposink name=datareposink");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+
+  datareposink = gst_bin_get_by_name (GST_BIN (pipeline), "datareposink");
+  EXPECT_NE (datareposink, nullptr);
+
+  g_object_set (GST_OBJECT (datareposink), "location", "video.raw", NULL);
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposink), "json", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for writing a file with invalid param (file path)
+ */
+TEST (datareposink, invalidFilePath0_n)
+{
+  GstElement *datareposink = NULL;
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 videotestsrc num-buffers=10 ! pngenc ! "
+      "datareposink name=datareposink");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposink = gst_bin_get_by_name (GST_BIN (pipeline), "datareposink");
+  EXPECT_NE (datareposink, nullptr);
+
+  g_object_set (GST_OBJECT (datareposink), "json", "image.json", NULL);
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposink), "location", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for writing a file with video compression format
+ */
+TEST (datareposink, unsupportedVideoCaps0_n)
+{
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 videotestsrc ! vp8enc ! "
+      "datareposink location=video.raw json=video.json");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  /* Could not to to GST_STATE_PLAYING state due to caps negotiation failure */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for writing a file with audio compression format
+ */
+TEST (datareposink, unsupportedAudioCaps0_n)
+{
+  gchar *str_pipeline =
+      g_strdup
+      ("gst-launch-1.0 audiotestsrc ! audio/x-raw,rate=44100,channels=2 ! wavenc ! "
+      "datareposink location=audio.raw json=audio.json");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  /* Could not to to GST_STATE_PLAYING state due to caps negotiation failure */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief remove test file
+ */
+static void
+remove_test_file (void)
+{
+  gchar *filename = NULL;
+  int i;
+
+  g_remove ("audio.json");
+  g_remove ("audio.raw");
+  g_remove ("video.json");
+  g_remove ("video.raw");
+  g_remove ("mnist.json");
+  g_remove ("mnist.data");
+
+  for (i = 0; i < 5; i++) {
+    filename = g_strdup_printf ("image_%02d.png", i);
+    g_remove (filename);
+  }
+  g_free (filename);
+}
+
+/**
+ * @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'");
+  }
+
+  gst_init (&argc, &argv);
+
+  try {
+    result = RUN_ALL_TESTS ();
+  } catch ( ...) {
+    g_warning ("catch `testing::internal::GoogleTestFailureException`");
+  }
+
+  remove_test_file ();
+
+  return result;
+}
diff --git a/tests/nnstreamer_datarepo/unittest_datareposrc.cc b/tests/nnstreamer_datarepo/unittest_datareposrc.cc
new file mode 100644 (file)
index 0000000..ff88291
--- /dev/null
@@ -0,0 +1,781 @@
+ /**
+ * @file        unittest_datareposrc.cc
+ * @date        21 Apr 2023
+ * @brief       Unit test for datareposrc
+ * @see         https://github.com/nnstreamer/nnstreamer
+ * @author      Hyunil Park <hyunil46.park@samsung.com>
+ * @bug         No known bugs
+ */
+
+#include <gtest/gtest.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+#include <unittest_util.h>
+
+static const gchar filename[] = "mnist.data";
+static const gchar json[] = "mnist.json";
+
+/**
+ * @brief Get file path
+ */
+static gchar *
+get_file_path (const gchar * filename)
+{
+  const gchar *root_path = NULL;
+  gchar *file_path = NULL;
+
+  root_path = g_getenv ("NNSTREAMER_SOURCE_ROOT_PATH");
+
+  /** supposed to run test in build directory */
+  if (root_path == NULL)
+    root_path = "..";
+
+  file_path =
+      g_build_filename (root_path, "tests", "test_models", "data", "datarepo",
+      filename, NULL);
+
+  return file_path;
+}
+
+/**
+ * @brief Bus callback function
+ */
+static gboolean
+bus_callback (GstBus * bus, GstMessage * message, gpointer data)
+{
+  switch (GST_MESSAGE_TYPE (message)) {
+    case GST_MESSAGE_EOS:
+      g_main_loop_quit ((GMainLoop *) data);
+      break;
+    default:
+      break;
+  }
+
+  return TRUE;
+}
+
+/**
+ * @brief create video test file
+ */
+static void
+create_video_test_file ()
+{
+  GstBus *bus;
+  GMainLoop *loop;
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 videotestsrc num-buffers=10 ! "
+      "datareposink location=video1.raw json=video1.json");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+      UNITTEST_STATECHANGE_TIMEOUT);
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+}
+
+/**
+ * @brief create audio test file
+ */
+static void
+create_audio_test_file ()
+{
+  GstBus *bus;
+  GMainLoop *loop;
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup
+      ("gst-launch-1.0 audiotestsrc samplesperbuffer=44100 num-buffers=1 ! "
+      "audio/x-raw, format=S16LE, layout=interleaved, rate=44100, channels=1 ! "
+      "datareposink location=audio1.raw json=audio1.json");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+      UNITTEST_STATECHANGE_TIMEOUT);
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+}
+
+/**
+ * @brief create image test file
+ */
+static void
+create_image_test_file ()
+{
+  GstBus *bus;
+  GMainLoop *loop;
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 videotestsrc num-buffers=5 ! pngenc ! "
+      "datareposink location=img_%02d.png json=img.json");
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+      UNITTEST_STATECHANGE_TIMEOUT);
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+}
+
+/**
+ * @brief Test for reading image files
+ */
+TEST (datareposrc, readImageFiles)
+{
+  GstBus *bus;
+  GMainLoop *loop;
+
+  create_image_test_file ();
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 datareposrc "
+      "location=img_%02d.png "
+      "json=img.json "
+      "start-sample-index=0 stop-sample-index=4 ! pngdec ! fakesink");
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  EXPECT_EQ (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+}
+
+/**
+ * @brief Test for reading a video raw file
+ */
+TEST (datareposrc, readVideoRaw)
+{
+  GstBus *bus;
+  GMainLoop *loop;
+
+  create_video_test_file ();
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 datareposrc "
+      "location=video1.raw "
+      "json=video1.json ! "
+      "video/x-raw, format=RGBx, width=320, height=240, framerate=30/1 ! fakesink");
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  EXPECT_EQ (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+}
+
+/**
+ * @brief Test for reading a video raw file
+ */
+TEST (datareposrc, readAudioRaw)
+{
+  GstBus *bus;
+  GMainLoop *loop;
+
+  create_audio_test_file ();
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 datareposrc "
+      "location=audio1.raw "
+      "json=audio1.json ! "
+      "audio/x-raw, format=S16LE, rate=44100, channels=1, layout=interleaved ! fakesink ");
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  EXPECT_EQ (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (JSON path)
+ */
+TEST (datareposrc, invalidJsonPath0_n)
+{
+  GstElement *datareposrc = NULL;
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 datareposrc name=datareposrc ! "
+      "video/x-raw, format=RGBx, width=320, height=240, framerate=30/1 ! fakesink");
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  g_object_set (GST_OBJECT (datareposrc), "location", "video1.raw", NULL);
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "json", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (JSON path)
+ */
+TEST (datareposrc, invalidJsonPath1_n)
+{
+  GstElement *datareposrc = NULL;
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 datareposrc name=datareposrc ! "
+      "video/x-raw, format=RGBx, width=320, height=240, framerate=30/1 ! fakesink");
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  g_object_set (GST_OBJECT (datareposrc), "location", "video1.raw", NULL);
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "json", "no_search_file", NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (File path)
+ */
+TEST (datareposrc, invalidFilePath0_n)
+{
+  GstElement *datareposrc = NULL;
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 datareposrc name=datareposrc ! "
+      "video/x-raw, format=RGBx, width=320, height=240, framerate=30/1 ! fakesink");
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  g_object_set (GST_OBJECT (datareposrc), "json", "video1.json", NULL);
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "location", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (File path)
+ */
+TEST (datareposrc, invalidFilePath1_n)
+{
+  GstElement *datareposrc = NULL;
+
+  gchar *str_pipeline =
+      g_strdup ("gst-launch-1.0 datareposrc name=datareposrc ! "
+      "video/x-raw, format=RGBx, width=320, height=240, framerate=30/1 ! fakesink");
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  g_object_set (GST_OBJECT (datareposrc), "json", "video1.json", NULL);
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "location", "no_search_file", NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a tensors file
+ * the number of total sample(mnist.data) is 10 (0~9)
+ * the number tensors is 2 and indices (0,1), default is (0,1)
+ * the default epochs is 1,
+ * the default shuffle is TRUE.
+ * can remove start-sample-index, epochs, tensors-sequence, shuffle property.
+ */
+TEST (datareposrc, readTensors)
+{
+  GstBus *bus;
+  GMainLoop *loop;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  GstElement *datareposrc = NULL;
+  gchar *get_str;
+  guint get_value;
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc name=datareposrc location=%s json=%s "
+      "start-sample-index=0 stop-sample-index=9 epochs=2 tensors-sequence=0,1 !"
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! fakesink",
+      file_path, json_path);
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  EXPECT_NE (datareposrc, nullptr);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+  ASSERT_NE (bus, nullptr);
+  gst_bus_add_watch (bus, bus_callback, loop);
+  gst_object_unref (bus);
+
+  g_object_get (datareposrc, "location", &get_str, NULL);
+  EXPECT_STREQ (get_str, file_path);
+
+  g_object_get (datareposrc, "json", &get_str, NULL);
+  EXPECT_STREQ (get_str, json_path);
+
+  g_object_get (datareposrc, "tensors-sequence", &get_str, NULL);
+  EXPECT_STREQ (get_str, "0,1");
+
+  g_object_get (datareposrc, "is-shuffle", &get_value, NULL);
+  ASSERT_EQ (get_value, 1U);
+
+  EXPECT_EQ (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  g_main_loop_run (loop);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+
+  gst_object_unref (pipeline);
+  g_main_loop_unref (loop);
+  g_free (file_path);
+  g_free (json_path);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (start-sample-index)
+ * the number of total sample(mnist.data) is 1000 (0~999)
+ */
+TEST (datareposrc, invalidStartSampleIndex0_n)
+{
+  GstElement *datareposrc = NULL;
+  int idx_out_of_range = 1000;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc name=datareposrc location=%s json=%s "
+      "stop-sample-index=9 epochs=2 tensors-sequence=0,1 !"
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! fakesink",
+      file_path, json_path);
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "start-sample-index",
+      idx_out_of_range, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (start-sample-index)
+ * the number of total sample(mnist.data) is 10 (0~9)
+ */
+TEST (datareposrc, invalidStartSampleIndex1_n)
+{
+  GstElement *datareposrc = NULL;
+  gint idx_out_of_range = -1;
+  guint get_value;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc name=datareposrc location=%s json=%s "
+      "stop-sample-index=9 epochs=2 tensors-sequence=0,1 !"
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! fakesink",
+      file_path, json_path);
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "start-sample-index",
+      idx_out_of_range, NULL);
+  /** value "-1" of type 'gint' is invalid or out of range for property 'start-sample-index' of type 'gint'
+     default value is set */
+  g_object_get (GST_OBJECT (datareposrc), "start-sample-index", &get_value,
+      NULL);
+  EXPECT_EQ (get_value, 0U);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (stop-sample-index)
+ * the number of total sample(mnist.data) is 1000 (0~999)
+ */
+TEST (datareposrc, invalidStopSampleIndex0_n)
+{
+  GstElement *datareposrc = NULL;
+  guint idx_out_of_range = 1000;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc name=datareposrc location=%s json=%s "
+      "start-sample-index=0 epochs=2 tensors-sequence=0,1 !"
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! fakesink",
+      file_path, json_path);
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  g_object_set (GST_OBJECT (datareposrc), "stop-sample-index", idx_out_of_range,
+      NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (start-sample-index)
+ * the number of total sample(mnist.data) is 10 (0~9)
+ */
+TEST (datareposrc, invalidStopSampleIndex1_n)
+{
+  GstElement *datareposrc = NULL;
+  gint idx_out_of_range = -1;
+  guint get_value;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc name=datareposrc location=%s json=%s "
+      "start-sample-index=0 epochs=2 tensors-sequence=0,1 !"
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! fakesink",
+      file_path, json_path);
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "stop-sample-index", idx_out_of_range,
+      NULL);
+  /** value "-1" of type 'gint' is invalid or out of range for property 'start-sample-index' of type 'gint'
+     default value is set */
+  g_object_get (GST_OBJECT (datareposrc), "stop-sample-index", &get_value,
+      NULL);
+  EXPECT_EQ (get_value, 0U);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (epochs)
+ */
+TEST (datareposrc, invalidEpochs0_n)
+{
+  GstElement *datareposrc = NULL;
+  gint invalid_epochs = -1;
+  guint get_value;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc name=datareposrc location=%s json=%s "
+      "start-sample-index=0 stop-sample-index=9 tensors-sequence=0,1 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! fakesink",
+      file_path, json_path);
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "epochs", invalid_epochs, NULL);
+  /** value "-1" of type 'gint' is invalid or out of range for property 'start-sample-index' of type 'gint'
+     default value is set */
+  g_object_get (GST_OBJECT (datareposrc), "epochs", &get_value, NULL);
+  EXPECT_EQ (get_value, 1U);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (epochs)
+ */
+TEST (datareposrc, invalidEpochs1_n)
+{
+  GstElement *datareposrc = NULL;
+  guint invalid_epochs = 0;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc name=datareposrc location=%s json=%s "
+      "start-sample-index=0 stop-sample-index=9 tensors-sequence=0,1 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! fakesink",
+      file_path, json_path);
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "epochs", invalid_epochs, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Test for reading a file with invalid param (tensors-sequence)
+ * the number tensors is 2 and indices (0,1)
+ */
+TEST (datareposrc, invalidTensorsSequence0_n)
+{
+  GstElement *datareposrc = NULL;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc name=datareposrc location=%s json=%s "
+      "start-sample-index=0 stop-sample-index=9 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! fakesink",
+      file_path, json_path);
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  datareposrc = gst_bin_get_by_name (GST_BIN (pipeline), "datareposrc");
+  ASSERT_NE (datareposrc, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (datareposrc), "tensors-sequence", "1,0,2", NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief remove test file
+ */
+static void
+remove_test_file (void)
+{
+  gchar *filename = NULL;
+  int i;
+
+  g_remove ("audio1.json");
+  g_remove ("audio1.raw");
+  g_remove ("video1.json");
+  g_remove ("video1.raw");
+  g_remove ("img.son");
+
+  for (i = 0; i < 5; i++) {
+    filename = g_strdup_printf ("img_%02d.png", i);
+    g_remove (filename);
+  }
+  g_free (filename);
+}
+
+/**
+ * @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'");
+  }
+
+  gst_init (&argc, &argv);
+
+  try {
+    result = RUN_ALL_TESTS ();
+  } catch ( ...) {
+    g_warning ("catch `testing::internal::GoogleTestFailureException`");
+  }
+
+  remove_test_file ();
+
+  return result;
+}
diff --git a/tests/nnstreamer_trainer/unittest_trainer.cc b/tests/nnstreamer_trainer/unittest_trainer.cc
new file mode 100644 (file)
index 0000000..124bdff
--- /dev/null
@@ -0,0 +1,679 @@
+/**
+ * @file        unittest_trainer.cc
+ * @date        21 Apr 2023
+ * @brief       Unit test for tensor_trainer
+ * @see         https://github.com/nnstreamer/nnstreamer
+ * @author      Hyunil Park <hyunil46.park@samsung.com>
+ * @bug         No known bugs
+ */
+
+#include <gtest/gtest.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+#include <unittest_util.h>
+
+static const gchar filename[] = "mnist.data";
+static const gchar json[] = "mnist.json";
+static const gchar model_config[] = "mnist.ini";
+
+/**
+ * @brief Get file path
+ */
+static gchar *
+get_file_path (const gchar * filename)
+{
+  const gchar *root_path = NULL;
+  gchar *file_path = NULL;
+
+  root_path = g_getenv ("NNSTREAMER_SOURCE_ROOT_PATH");
+
+  /** supposed to run test in build directory */
+  if (root_path == NULL)
+    root_path = "..";
+
+  file_path =
+      g_build_filename (root_path, "tests", "test_models", "data", "datarepo",
+      filename, NULL);
+
+  return file_path;
+}
+
+
+/**
+ * @brief Model training test using mnist.data (MNIST Test), model.bin is created.
+ * 
+ * framework: framework to use for training the model
+ * model-config: model configuration file path. models are limited to creating with configuration files.
+ * model-save-path: model save path by query in MLOps
+ * input-dims:input dimensions, in case of MNIST, 1:1:784:1 is a input and 1:1:10:1 is a label.
+ * input_type: data type. Sample(mnist.data)'s data type is float32.
+ * num-inputs: sub-plugin supports multiple inputs, in case of MNIST, num-inputs is 1.
+ * num-labels: sub-plugin supports multiple labels, in case of MNIST, num-labels is 1.
+ * num-training-samples: Number of training samples, A sample can consist of multiple inputs and labels in tensors(in case of MNIST, all is 1),
+ *   set how many samples are taken for training model.
+ * num-validation-samples: num-validation-samples, A sample can consist of multiple inputs and labels in tensors(in case of MNIST, all is 1),
+ *   set how many samples are taken for validation model.
+ * epochs : epochs are repetitions of training samples and validation smaples.
+ *   number of samples received for model training is (num-training-samples + num-validation-samples) * epochs
+ */
+
+TEST (tensor_trainer, SetParams)
+{
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+  guint get_value;
+  gchar *get_str;
+  GstElement *tensor_trainer = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=1 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s "
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-inputs=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 epochs=1 ! "
+      "tensor_sink", file_path, json_path, model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  EXPECT_NE (tensor_trainer, nullptr);
+
+  setPipelineStateSync (pipeline, GST_STATE_PAUSED,
+      UNITTEST_STATECHANGE_TIMEOUT);
+
+  g_object_get (tensor_trainer, "model-config", &get_str, NULL);
+  EXPECT_STREQ (get_str, model_config_path);
+
+  g_object_get (tensor_trainer, "model-save-path", &get_str, NULL);
+  EXPECT_STREQ (get_str, "model.bin");
+
+  g_object_get (tensor_trainer, "input-dim", &get_str, NULL);
+  EXPECT_STREQ (get_str, "1:1:784:1,1:1:10:1");
+
+
+  g_object_get (tensor_trainer, "input-dim", &get_str, NULL);
+  EXPECT_STREQ (get_str, "1:1:784:1,1:1:10:1");
+
+  g_object_get (tensor_trainer, "input-type", &get_str, NULL);
+  EXPECT_STREQ (get_str, "float32,float32");
+
+  g_object_get (tensor_trainer, "num-inputs", &get_value, NULL);
+  ASSERT_EQ (get_value, 1U);
+
+  g_object_get (tensor_trainer, "num-labels", &get_value, NULL);
+  ASSERT_EQ (get_value, 1U);
+
+  g_object_get (tensor_trainer, "num-training-samples", &get_value, NULL);
+  ASSERT_EQ (get_value, 100U);
+
+  g_object_get (tensor_trainer, "num-validation-samples", &get_value, NULL);
+  ASSERT_EQ (get_value, 100U);
+
+  g_object_get (tensor_trainer, "epochs", &get_value, NULL);
+  ASSERT_EQ (get_value, 1U);
+
+  setPipelineStateSync (pipeline, GST_STATE_NULL, UNITTEST_STATECHANGE_TIMEOUT);
+
+  gst_object_unref (pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+}
+
+/**
+ * @brief Model training test with invalid param (framework)
+ */
+TEST (tensor_trainer, invalidFramework0_n)
+{
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+  GstElement *tensor_trainer = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer model-config=%s "
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-inputs=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 epochs=5 ! tensor_sink",
+      file_path, json_path, model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "framework", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (framework)
+ */
+TEST (tensor_trainer, invalidFramework1_n)
+{
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+  GstElement *tensor_trainer = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer model-config=%s "
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-inputs=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 epochs=5 ! tensor_sink",
+      file_path, json_path, model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  ASSERT_NE (pipeline, nullptr);
+
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "framework", "no_framework", NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (model-config)
+ */
+TEST (tensor_trainer, invalidModelConfig0_n)
+{
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  GstElement *tensor_trainer = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s"
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer"
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-inputs=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 epochs=5 ! tensor_sink",
+      file_path, json_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "model-config", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (model-save-path)
+ */
+TEST (tensor_trainer, invalidModelSavePath0_n)
+{
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+  GstElement *tensor_trainer = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s "
+      "input-dim=1:1:784:1,1:1:10:1 input-type=float32,float32 num-inputs=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 epochs=5 ! tensor_sink",
+      file_path, json_path, model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "model-save-path", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (input-dim)
+ */
+TEST (tensor_trainer, invalidInputDimension0_n)
+{
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+  GstElement *tensor_trainer = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s "
+      "model-save-path=model.bin input-type=float32,float32 num-labels=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 epochs=5 ! tensor_sink",
+      file_path, json_path, model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "input-dim", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (input-type)
+ */
+TEST (tensor_trainer, invalidInputType0_n)
+{
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+  GstElement *tensor_trainer = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s "
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 num-labels=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 epochs=5 ! tensor_sink",
+      file_path, json_path, model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "input-type", NULL, NULL);
+
+  /* state chagne failure is expected */
+  EXPECT_NE (setPipelineStateSync (pipeline, GST_STATE_PLAYING,
+          UNITTEST_STATECHANGE_TIMEOUT), 0);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (num-training-samples)
+ */
+TEST (tensor_trainer, invalidModelNumTrainingSamples0_n)
+{
+  GstElement *tensor_trainer = NULL;
+  gint invalid_value = -1;
+  guint get_value;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s "
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-inputs=1 num-labels=1 "
+      "num-validation-samples=100 epochs=5 ! tensor_sink", file_path, json_path,
+      model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "num-training-samples",
+      invalid_value, NULL);
+  /** value "-1" is out of range for property 'num-training-samples' of type 'guint'
+     default value is set */
+  g_object_get (GST_OBJECT (tensor_trainer), "num-training-samples", &get_value,
+      NULL);
+  /* state chagne failure is expected */
+  EXPECT_EQ (get_value, 0U);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (num-validation-samples)
+ */
+TEST (tensor_trainer, invalidModelNumValidationSamples0_n)
+{
+  GstElement *tensor_trainer = NULL;
+  gint invalid_value = -1;
+  guint get_value;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s "
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-inputs=1 num-labels=1 "
+      "num-training-samples=100 epochs=5 ! tensor_sink", file_path, json_path,
+      model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "num-validation-samples",
+      invalid_value, NULL);
+  /** value "-1" is out of range for property 'num-validation-samples' of type 'guint'
+     default value is set */
+  g_object_get (GST_OBJECT (tensor_trainer), "num-validation-samples",
+      &get_value, NULL);
+  /* state chagne failure is expected */
+  EXPECT_EQ (get_value, 0U);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (epochs)
+ */
+TEST (tensor_trainer, invalidEpochs0_n)
+{
+  GstElement *tensor_trainer = NULL;
+  gint invalid_value = -1;
+  guint get_value;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s "
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-inputs=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 ! tensor_sink",
+      file_path, json_path, model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "epochs", invalid_value, NULL);
+  /** value "-1" is out of range for property 'epochs' of type 'guint'
+     default value is set */
+  g_object_get (GST_OBJECT (tensor_trainer), "epochs", &get_value, NULL);
+  /* state chagne failure is expected */
+  EXPECT_EQ (get_value, 1U);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (num-inputs)
+ */
+TEST (tensor_trainer, invalidNumInputs0_n)
+{
+  GstElement *tensor_trainer = NULL;
+  gint invalid_value = -1;
+  guint get_value;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s "
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-labels=1 num-training-samples=100 "
+      "num-validation-samples=100 epochs=5 ! tensor_sink", file_path, json_path,
+      model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "num-inputs", invalid_value, NULL);
+  /** value "-1" is out of range for property 'num-inputs' of type 'guint'
+     default value is set */
+  g_object_get (GST_OBJECT (tensor_trainer), "num-inputs", &get_value, NULL);
+  /* state chagne failure is expected */
+  EXPECT_EQ (get_value, 1U);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @brief Model training test with invalid param (num-labels)
+ */
+TEST (tensor_trainer, invalidNumLabels0_n)
+{
+  GstElement *tensor_trainer = NULL;
+  gint invalid_value = -1;
+  guint get_value;
+  gchar *file_path = NULL;
+  gchar *json_path = NULL;
+  gchar *model_config_path = NULL;
+
+  file_path = get_file_path (filename);
+  json_path = get_file_path (json);
+  model_config_path = get_file_path (model_config);
+
+  gchar *str_pipeline =
+      g_strdup_printf
+      ("gst-launch-1.0 datareposrc location=%s json=%s "
+      "start-sample-index=3 stop-sample-index=202 tensors-sequence=0,1 epochs=5 ! "
+      "other/tensors, format=static, num_tensors=2, framerate=0/1, "
+      "dimensions=1:1:784:1.1:1:10:1, types=float32.float32 ! "
+      "tensor_trainer name=tensor_trainer framework=nntrainer model-config=%s"
+      "model-save-path=model.bin input-dim=1:1:784:1,1:1:10:1 "
+      "input-type=float32,float32 num-labels=1 num-labels=1 "
+      "num-training-samples=100 num-validation-samples=100 epochs=5 ! "
+      "tensor_sink", file_path, json_path, model_config_path);
+
+  GstElement *pipeline = gst_parse_launch (str_pipeline, NULL);
+  g_free (str_pipeline);
+  g_free (file_path);
+  g_free (json_path);
+  g_free (model_config_path);
+  ASSERT_NE (pipeline, nullptr);
+
+  tensor_trainer = gst_bin_get_by_name (GST_BIN (pipeline), "tensor_trainer");
+  ASSERT_NE (tensor_trainer, nullptr);
+
+  /* set invalid param */
+  g_object_set (GST_OBJECT (tensor_trainer), "num-labels", invalid_value, NULL);
+  /** value "-1" of type 'gint64' is invalid or out of range for property 'num-labels' of type 'guint'
+     default value is set */
+  g_object_get (GST_OBJECT (tensor_trainer), "num-labels", &get_value, NULL);
+  /* state chagne failure is expected */
+  EXPECT_EQ (get_value, 1U);
+
+  gst_object_unref (pipeline);
+}
+
+/**
+ * @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'");
+  }
+
+  gst_init (&argc, &argv);
+
+  try {
+    result = RUN_ALL_TESTS ();
+  } catch ( ...) {
+    g_warning ("catch `testing::internal::GoogleTestFailureException`");
+  }
+
+  return result;
+}
diff --git a/tests/test_models/data/datarepo/mnist.data b/tests/test_models/data/datarepo/mnist.data
new file mode 100644 (file)
index 0000000..df8456e
Binary files /dev/null and b/tests/test_models/data/datarepo/mnist.data differ
diff --git a/tests/test_models/data/datarepo/mnist.ini b/tests/test_models/data/datarepo/mnist.ini
new file mode 100644 (file)
index 0000000..a10d4e3
--- /dev/null
@@ -0,0 +1,76 @@
+# Network Section : Network
+
+[Model]
+Type = NeuralNetwork                # Network Type : Regression, KNN, NeuralNetwork
+Epochs = 10                         # Epochs
+Loss = cross                        # Loss function : mse (mean squared error)
+                                    # cross ( for cross entropy )
+#Save_Path = "mnist_model.bin"     # model path to save / read
+batch_size = 10                     # batch size
+
+[Optimizer]
+Type = adam
+beta1 = 0.9                         # beta 1 for adam
+beta2 = 0.999                       # beta 2 for adam
+epsilon = 1e-7                      # epsilon for adam
+
+[LearningRateScheduler]
+type=constant
+Learning_rate = 1e-4                # Learning Rate
+
+# Layer Section : Name
+[inputlayer]
+Type = input
+Input_Shape = 1:28:28
+
+# Layer Section : Name
+[conv2d_c1_layer]
+Type = conv2d
+input_layers = inputlayer
+kernel_size = 5,5
+bias_initializer=zeros
+Activation=sigmoid
+weight_initializer = xavier_uniform
+filters = 6
+stride = 1,1
+padding = 0,0
+
+[pooling2d_p1]
+Type=pooling2d
+input_layers = conv2d_c1_layer
+pool_size = 2,2
+stride =2,2
+padding = 0,0
+pooling = average
+
+[conv2d_c2_layer]
+Type = conv2d
+input_layers = pooling2d_p1
+kernel_size = 5,5
+bias_initializer=zeros
+Activation=sigmoid
+weight_initializer = xavier_uniform
+filters = 12
+stride = 1,1
+padding = 0,0
+
+[pooling2d_p2]
+Type=pooling2d
+input_layers = conv2d_c2_layer
+pool_size = 2,2
+stride =2,2
+padding = 0,0
+pooling = average
+
+[flatten]
+Type=flatten
+input_layers = pooling2d_p2
+
+[outputlayer]
+Type = fully_connected
+input_layers=flatten
+Unit = 10                           # Output Layer Dimension ( = Weight Width )
+weight_initializer = xavier_uniform
+bias_initializer = zeros
+Activation = softmax                # activation : sigmoid, softmax
+
diff --git a/tests/test_models/data/datarepo/mnist.json b/tests/test_models/data/datarepo/mnist.json
new file mode 100644 (file)
index 0000000..be1911c
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "gst_caps":"other/tensors, format=(string)static, framerate=(fraction)0/1, num_tensors=(int)2, dimensions=(string)1:1:784:1.1:1:10:1, types=(string)float32.float32",
+  "total_samples":1000,
+  "sample_size":3176
+}