From ca9dc65d0f0feb63ebc52458890d40d7d9f22d21 Mon Sep 17 00:00:00 2001 From: Jaeyun Date: Fri, 10 Jul 2020 14:35:44 +0900 Subject: [PATCH] [Test] testcase to convert multi tensors add new testcases to convert byte stream to multi tensors. Signed-off-by: Jaeyun --- tests/nnstreamer_plugins/unittest_plugins.cc | 448 +++++++++++++++++++++++++++ tests/nnstreamer_sink/unittest_sink.cc | 87 ++++++ 2 files changed, 535 insertions(+) diff --git a/tests/nnstreamer_plugins/unittest_plugins.cc b/tests/nnstreamer_plugins/unittest_plugins.cc index eac0e2d..9d31a70 100644 --- a/tests/nnstreamer_plugins/unittest_plugins.cc +++ b/tests/nnstreamer_plugins/unittest_plugins.cc @@ -1756,6 +1756,454 @@ TEST (test_tensor_aggregator, aggregate_5) gst_harness_teardown (h); } +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_1) +{ + GstHarness *h; + GstBuffer *in_buf, *out_buf; + GstTensorsConfig config; + GstCaps *caps; + GstMemory *mem; + GstMapInfo info; + guint i; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-dim", "3:4:2:2,3:4:2:2", + "input-type", "int32,int32", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 2; + + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:4:2:2", config.info.info[0].dimension); + config.info.info[1].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:4:2:2", config.info.info[1].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + 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)); + + memcpy (info.data, aggr_test_frames, data_size); + + 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), 2U); + ASSERT_EQ (gst_buffer_get_size (out_buf), data_size); + + /* 1st tensor */ + mem = gst_buffer_peek_memory (out_buf, 0); + ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ)); + for (i = 0; i < 48; i++) + EXPECT_EQ (((gint *) info.data)[i], aggr_test_frames[0][i]); + gst_memory_unmap (mem, &info); + + /* 2nd tensor */ + mem = gst_buffer_peek_memory (out_buf, 1); + ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ)); + for (i = 0; i < 48; i++) + EXPECT_EQ (((gint *) info.data)[i], aggr_test_frames[1][i]); + gst_memory_unmap (mem, &info); + + gst_buffer_unref (out_buf); + + EXPECT_EQ (gst_harness_buffers_received (h), 1U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_2) +{ + GstHarness *h; + GstBuffer *in_buf, *out_buf; + GstTensorsConfig config; + GstCaps *caps; + GstMemory *mem; + GstMapInfo info; + guint i; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-dim", "3:4:2:1,3:4:2:1,3:4:2:1,3:4:2:1", + "input-type", "int32,int32,int32,int32", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 4; + + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:4:2:1", config.info.info[0].dimension); + config.info.info[1].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:4:2:1", config.info.info[1].dimension); + config.info.info[2].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:4:2:1", config.info.info[2].dimension); + config.info.info[3].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:4:2:1", config.info.info[3].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + 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)); + + memcpy (info.data, aggr_test_frames, data_size); + + 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), 4U); + ASSERT_EQ (gst_buffer_get_size (out_buf), data_size); + + /* 1st tensor */ + mem = gst_buffer_peek_memory (out_buf, 0); + ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ)); + for (i = 0; i < 24; i++) + EXPECT_EQ (((gint *) info.data)[i], aggr_test_frames[0][i]); + gst_memory_unmap (mem, &info); + + /* 2nd tensor */ + mem = gst_buffer_peek_memory (out_buf, 1); + ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ)); + for (i = 24; i < 48; i++) + EXPECT_EQ (((gint *) info.data)[i - 24], aggr_test_frames[0][i]); + gst_memory_unmap (mem, &info); + + /* 3rd tensor */ + mem = gst_buffer_peek_memory (out_buf, 2); + ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ)); + for (i = 0; i < 24; i++) + EXPECT_EQ (((gint *) info.data)[i], aggr_test_frames[1][i]); + gst_memory_unmap (mem, &info); + + /* 4th tensor */ + mem = gst_buffer_peek_memory (out_buf, 3); + ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ)); + for (i = 24; i < 48; i++) + EXPECT_EQ (((gint *) info.data)[i - 24], aggr_test_frames[1][i]); + gst_memory_unmap (mem, &info); + + gst_buffer_unref (out_buf); + + EXPECT_EQ (gst_harness_buffers_received (h), 1U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_invalid_dim_01_n) +{ + GstHarness *h; + GstBuffer *in_buf; + GstTensorsConfig config; + GstCaps *caps; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-dim", "2:2:2:2", + "input-type", "int32,uint64", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 2; + + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension); + config.info.info[1].type = _NNS_UINT64; + gst_tensor_parse_dimension ("2:2:2:2", config.info.info[1].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + in_buf = gst_harness_create_buffer (h, data_size); + EXPECT_DEATH (gst_harness_push (h, in_buf), ""); + + EXPECT_EQ (gst_harness_buffers_received (h), 0U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_invalid_dim_02_n) +{ + GstHarness *h; + GstBuffer *in_buf; + GstTensorsConfig config; + GstCaps *caps; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-dim", "2:2:2:2,2:0:1", + "input-type", "int32,float32", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 2; + + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension); + config.info.info[1].type = _NNS_FLOAT32; + gst_tensor_parse_dimension ("2:2:1:1", config.info.info[1].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + in_buf = gst_harness_create_buffer (h, data_size); + EXPECT_DEATH (gst_harness_push (h, in_buf), ""); + + EXPECT_EQ (gst_harness_buffers_received (h), 0U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_invalid_type_01_n) +{ + GstHarness *h; + GstBuffer *in_buf; + GstTensorsConfig config; + GstCaps *caps; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-type", "int64", + "input-dim", "2:2:2:2,2:2:2:2", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 2; + + config.info.info[0].type = _NNS_INT64; + gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension); + config.info.info[1].type = _NNS_UINT64; + gst_tensor_parse_dimension ("2:2:2:2", config.info.info[1].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + in_buf = gst_harness_create_buffer (h, data_size); + EXPECT_DEATH (gst_harness_push (h, in_buf), ""); + + EXPECT_EQ (gst_harness_buffers_received (h), 0U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_invalid_type_02_n) +{ + GstHarness *h; + GstBuffer *in_buf; + GstTensorsConfig config; + GstCaps *caps; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-dim", "2:2:2:2,2:2:1:1", + "input-type", "int16,invalid", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 2; + + config.info.info[0].type = _NNS_INT16; + gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension); + config.info.info[1].type = _NNS_INT16; + gst_tensor_parse_dimension ("2:2:1:1", config.info.info[1].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + in_buf = gst_harness_create_buffer (h, data_size); + EXPECT_DEATH (gst_harness_push (h, in_buf), ""); + + EXPECT_EQ (gst_harness_buffers_received (h), 0U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_invalid_type_03_n) +{ + GstHarness *h; + GstBuffer *in_buf; + GstTensorsConfig config; + GstCaps *caps; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-dim", "1:1:1:1,2:1:1:1,3", + "input-type", "int16,uint16", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 3; + + config.info.info[0].type = _NNS_INT16; + gst_tensor_parse_dimension ("1:1:1:1", config.info.info[0].dimension); + config.info.info[1].type = _NNS_UINT16; + gst_tensor_parse_dimension ("2:1:1:1", config.info.info[1].dimension); + config.info.info[1].type = _NNS_UINT8; + gst_tensor_parse_dimension ("3:1:1:1", config.info.info[1].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + in_buf = gst_harness_create_buffer (h, data_size); + EXPECT_DEATH (gst_harness_push (h, in_buf), ""); + + EXPECT_EQ (gst_harness_buffers_received (h), 0U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_invalid_size_n) +{ + GstHarness *h; + GstBuffer *in_buf; + GstTensorsConfig config; + GstCaps *caps; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-dim", "2:2:2:2,1:1:1:1", + "input-type", "float32,float64", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 2; + + config.info.info[0].type = _NNS_FLOAT32; + gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension); + config.info.info[1].type = _NNS_FLOAT64; + gst_tensor_parse_dimension ("2:2:1:1", config.info.info[1].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + in_buf = gst_harness_create_buffer (h, data_size); + EXPECT_DEATH (gst_harness_push (h, in_buf), ""); + + EXPECT_EQ (gst_harness_buffers_received (h), 0U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_converter (bytes to multi tensors) + */ +TEST (test_tensor_converter, bytes_to_multi_invalid_frames_n) +{ + GstHarness *h; + GstBuffer *in_buf; + GstTensorsConfig config; + GstCaps *caps; + gsize data_size; + + h = gst_harness_new ("tensor_converter"); + + g_object_set (h->element, "input-dim", "2:2:2:2,1:1:1:1", + "input-type", "float32,float64", "frames-per-tensor", "2", NULL); + + /* in/out caps and tensors info */ + caps = gst_caps_from_string ("application/octet-stream"); + gst_harness_set_src_caps (h, caps); + + gst_tensors_config_init (&config); + config.rate_n = 0; + config.rate_d = 1; + config.info.num_tensors = 2; + + config.info.info[0].type = _NNS_FLOAT32; + gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension); + config.info.info[1].type = _NNS_FLOAT64; + gst_tensor_parse_dimension ("1:1:1:1", config.info.info[1].dimension); + + data_size = gst_tensors_info_get_size (&config.info, -1); + + /* push buffers */ + in_buf = gst_harness_create_buffer (h, data_size); + EXPECT_DEATH (gst_harness_push (h, in_buf), ""); + + EXPECT_EQ (gst_harness_buffers_received (h), 0U); + gst_harness_teardown (h); +} + #ifdef HAVE_ORC #include "transform-orc.h" diff --git a/tests/nnstreamer_sink/unittest_sink.cc b/tests/nnstreamer_sink/unittest_sink.cc index 830b667..8ada9f0 100644 --- a/tests/nnstreamer_sink/unittest_sink.cc +++ b/tests/nnstreamer_sink/unittest_sink.cc @@ -93,6 +93,7 @@ typedef enum TEST_TYPE_OCTET_VALID_TS, /**< pipeline for octet stream, valid timestamp */ TEST_TYPE_OCTET_INVALID_TS, /**< pipeline for octet stream, invalid timestamp */ TEST_TYPE_OCTET_2F, /**< pipeline for octet stream, 2 frames */ + TEST_TYPE_OCTET_MULTI_TENSORS, /**< pipeline for octet stream, byte array to multi tensors */ TEST_TYPE_TENSORS, /**< pipeline for tensors with tensor_mux */ TEST_TYPE_TENSORS_MIX_1, /**< pipeline for tensors with tensor_mux, tensor_demux */ TEST_TYPE_TENSORS_MIX_2, /**< pipeline for tensors with tensor_mux, tensor_demux pick 0,2 */ @@ -714,6 +715,13 @@ _setup_pipeline (TestOption & option) ("appsrc name=appsrc caps=application/octet-stream,framerate=(fraction)10/1 ! " "tensor_converter name=convert input-dim=1:5 input-type=int8 ! tensor_sink name=test_sink"); break; + case TEST_TYPE_OCTET_MULTI_TENSORS: + /** byte stream, byte array to multi tensors */ + str_pipeline = + g_strdup_printf + ("appsrc name=appsrc caps=application/octet-stream,framerate=(fraction)10/1 ! " + "tensor_converter name=convert input-dim=2,2 input-type=int32,int8 ! tensor_sink name=test_sink"); + break; case TEST_TYPE_TENSORS: /** other/tensors with tensor_mux */ str_pipeline = @@ -2939,6 +2947,85 @@ TEST (tensor_stream_test, octet_2f) } /** + * @brief Test for octet stream. + */ +TEST (tensor_stream_test, octet_multi_tensors) +{ + const guint num_buffers = 10; + TestOption option = { num_buffers, TEST_TYPE_OCTET_MULTI_TENSORS }; + GstElement *convert; + gchar *prop_str; + guint prop_uint; + guint timeout_id; + + ASSERT_TRUE (_setup_pipeline (option)); + + /* tensor_converter properties */ + convert = gst_bin_get_by_name (GST_BIN (g_test_data.pipeline), "convert"); + ASSERT_TRUE (convert != NULL); + + g_object_get (convert, "input-dim", &prop_str, NULL); + EXPECT_STREQ (prop_str, "2:1:1:1,2:1:1:1"); + g_free (prop_str); + + g_object_get (convert, "input-type", &prop_str, NULL); + EXPECT_STREQ (prop_str, "int32,int8"); + g_free (prop_str); + + g_object_get (convert, "frames-per-tensor", &prop_uint, NULL); + EXPECT_EQ (prop_uint, 1U); + + gst_object_unref (convert); + + gst_element_set_state (g_test_data.pipeline, GST_STATE_PLAYING); + + g_timeout_add (100, _test_src_push_timer_cb, GINT_TO_POINTER (TRUE)); + + timeout_id = g_timeout_add (5000, _test_src_eos_timer_cb, g_test_data.loop); + g_main_loop_run (g_test_data.loop); + g_source_remove (timeout_id); + + EXPECT_TRUE (_wait_pipeline_process_buffers (num_buffers)); + gst_element_set_state (g_test_data.pipeline, GST_STATE_NULL); + + /** check eos message */ + EXPECT_EQ (g_test_data.status, TEST_EOS); + + /** check received buffers */ + EXPECT_EQ (g_test_data.received, num_buffers); + EXPECT_EQ (g_test_data.mem_blocks, 2U); + EXPECT_EQ (g_test_data.received_size, 10U); + + /** check caps name */ + EXPECT_STREQ (g_test_data.caps_name, "other/tensors"); + + /** check timestamp */ + EXPECT_FALSE (g_test_data.invalid_timestamp); + + /** check tensor config for multi tensors */ + EXPECT_TRUE (gst_tensors_config_validate (&g_test_data.tensors_config)); + EXPECT_EQ (g_test_data.tensors_config.info.num_tensors, 2U); + + EXPECT_EQ (g_test_data.tensors_config.info.info[0].type, _NNS_INT32); + EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[0], 2U); + EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[1], 1U); + EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[2], 1U); + EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[3], 1U); + + EXPECT_EQ (g_test_data.tensors_config.info.info[1].type, _NNS_INT8); + EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[0], 2U); + EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[1], 1U); + EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[2], 1U); + EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[3], 1U); + + EXPECT_EQ (g_test_data.tensors_config.rate_n, 10); + EXPECT_EQ (g_test_data.tensors_config.rate_d, 1); + + EXPECT_FALSE (g_test_data.test_failed); + _free_test_data (); +} + +/** * @brief Test for other/tensor, passthrough custom filter. */ TEST (tensor_stream_test, custom_filter_tensor) -- 2.7.4