From ad84e129f8411773b728b1d09770020bcfc15ec9 Mon Sep 17 00:00:00 2001 From: Yelin Jeong Date: Thu, 29 Dec 2022 10:45:16 +0900 Subject: [PATCH] [Tests] Add tests for increasing rank This patch changes hardcoded ranks and adds higher rank testdata. Signed-off-by: Yelin Jeong --- tests/common/unittest_common.cc | 102 +++++++++ tests/nnstreamer_converter/runTest.sh | 7 +- .../nnstreamer_customfilter_example_average.c | 3 - .../nnstreamer_customfilter_example_passthrough.c | 12 +- .../nnstreamer_customfilter_example_scaler.c | 3 - ...treamer_customfilter_example_scaler_allocator.c | 3 - tests/nnstreamer_filter_pytorch/generateTest.py | 24 +++ tests/nnstreamer_filter_pytorch/runTest.sh | 44 +++- .../unittest_filter_single.cc | 127 +++++++++++ .../nnstreamer_filter_tensorflow2_lite/runTest.sh | 35 +++- tests/nnstreamer_if/unittest_if.cc | 2 +- tests/nnstreamer_plugins/unittest_plugins.cc | 232 ++++++++++++++++++++- tests/test_models/models/custom_decoder.py | 2 +- tests/test_models/models/passthrough.py | 8 +- .../sample_4x4x4x4x4_two_input_one_output.pt | Bin 0 -> 1696 bytes .../sample_4x4x4x4x4_two_input_one_output.tflite | Bin 0 -> 1660 bytes tests/test_models/models/scaler.py | 2 +- tests/transform_dimchg/runTest.sh | 16 ++ 18 files changed, 602 insertions(+), 20 deletions(-) create mode 100644 tests/nnstreamer_filter_pytorch/generateTest.py create mode 100644 tests/test_models/models/sample_4x4x4x4x4_two_input_one_output.pt create mode 100644 tests/test_models/models/sample_4x4x4x4x4_two_input_one_output.tflite diff --git a/tests/common/unittest_common.cc b/tests/common/unittest_common.cc index d54aac3..a62d3e1 100644 --- a/tests/common/unittest_common.cc +++ b/tests/common/unittest_common.cc @@ -350,6 +350,100 @@ TEST (commonGetTensorDimension, case4) } /** + * @brief Test for tensor dimension. + */ +TEST (commonGetTensorDimension, case5) +{ + tensor_dim dim; + gchar *dim_str; + guint rank; + + rank = gst_tensor_parse_dimension ("345:123:433:177:851", dim); + EXPECT_EQ (rank, 5U); + EXPECT_EQ (dim[0], 345U); + EXPECT_EQ (dim[1], 123U); + EXPECT_EQ (dim[2], 433U); + EXPECT_EQ (dim[3], 177U); + EXPECT_EQ (dim[4], 851U); + + dim_str = gst_tensor_get_dimension_string (dim); + EXPECT_TRUE (gst_tensor_dimension_string_is_equal (dim_str, "345:123:433:177:851")); + g_free (dim_str); +} + +/** + * @brief Test for tensor dimension. + */ +TEST (commonGetTensorDimension, case6) +{ + tensor_dim dim; + gchar *dim_str; + guint rank; + + rank = gst_tensor_parse_dimension ("345:123:433:177:851:369", dim); + EXPECT_EQ (rank, 6U); + EXPECT_EQ (dim[0], 345U); + EXPECT_EQ (dim[1], 123U); + EXPECT_EQ (dim[2], 433U); + EXPECT_EQ (dim[3], 177U); + EXPECT_EQ (dim[4], 851U); + EXPECT_EQ (dim[5], 369U); + + dim_str = gst_tensor_get_dimension_string (dim); + EXPECT_TRUE (gst_tensor_dimension_string_is_equal (dim_str, "345:123:433:177:851:369")); + g_free (dim_str); +} + +/** + * @brief Test for tensor dimension. + */ +TEST (commonGetTensorDimension, case7) +{ + tensor_dim dim; + gchar *dim_str; + guint rank; + + rank = gst_tensor_parse_dimension ("345:123:433:177:851:369:456", dim); + EXPECT_EQ (rank, 7U); + EXPECT_EQ (dim[0], 345U); + EXPECT_EQ (dim[1], 123U); + EXPECT_EQ (dim[2], 433U); + EXPECT_EQ (dim[3], 177U); + EXPECT_EQ (dim[4], 851U); + EXPECT_EQ (dim[5], 369U); + EXPECT_EQ (dim[6], 456U); + + dim_str = gst_tensor_get_dimension_string (dim); + EXPECT_TRUE (gst_tensor_dimension_string_is_equal (dim_str, "345:123:433:177:851:369:456")); + g_free (dim_str); +} + +/** + * @brief Test for tensor dimension. + */ +TEST (commonGetTensorDimension, case8) +{ + tensor_dim dim; + gchar *dim_str; + guint rank; + + rank = gst_tensor_parse_dimension ("345:123:433:177:851:369:456:91", dim); + EXPECT_EQ (rank, 8U); + EXPECT_EQ (dim[0], 345U); + EXPECT_EQ (dim[1], 123U); + EXPECT_EQ (dim[2], 433U); + EXPECT_EQ (dim[3], 177U); + EXPECT_EQ (dim[4], 851U); + EXPECT_EQ (dim[5], 369U); + EXPECT_EQ (dim[6], 456U); + EXPECT_EQ (dim[7], 91U); + + dim_str = gst_tensor_get_dimension_string (dim); + EXPECT_TRUE (gst_tensor_dimension_string_is_equal (dim_str, "345:123:433:177:851:369:456:91")); + g_free (dim_str); +} + +/** * @brief Test to copy tensor info. */ TEST (commonTensorInfo, copyTensor) @@ -439,11 +533,19 @@ fill_tensors_info_for_test (GstTensorsInfo *info1, GstTensorsInfo *info2) info1->info[0].dimension[1] = info2->info[0].dimension[1] = 3; info1->info[0].dimension[2] = info2->info[0].dimension[2] = 1; info1->info[0].dimension[3] = info2->info[0].dimension[3] = 1; + info1->info[0].dimension[4] = info2->info[0].dimension[4] = 2; + info1->info[0].dimension[5] = info2->info[0].dimension[5] = 3; + info1->info[0].dimension[6] = info2->info[0].dimension[6] = 1; + info1->info[0].dimension[7] = info2->info[0].dimension[7] = 1; info1->info[1].dimension[0] = info2->info[1].dimension[0] = 5; info1->info[1].dimension[1] = info2->info[1].dimension[1] = 5; info1->info[1].dimension[2] = info2->info[1].dimension[2] = 1; info1->info[1].dimension[3] = info2->info[1].dimension[3] = 1; + info1->info[1].dimension[4] = info2->info[1].dimension[4] = 5; + info1->info[1].dimension[5] = info2->info[1].dimension[5] = 5; + info1->info[1].dimension[6] = info2->info[1].dimension[6] = 1; + info1->info[1].dimension[7] = info2->info[1].dimension[7] = 1; } /** diff --git a/tests/nnstreamer_converter/runTest.sh b/tests/nnstreamer_converter/runTest.sh index 040659c..ff92878 100644 --- a/tests/nnstreamer_converter/runTest.sh +++ b/tests/nnstreamer_converter/runTest.sh @@ -24,6 +24,7 @@ if [ "$SKIPGEN" == "YES" ]; then else echo "Test Case Generation Started" python3 generateGoldenTestResult.py + python3 ../nnstreamer_filter_pytorch/generateTest.py sopath=$1 fi convertBMP2PNG @@ -87,6 +88,10 @@ callCompareTest testcase08.golden testcase08.log 6-2 "PNG Stream Test" 0 0 gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! videoscale ! videoconvert ! video/x-raw,format=RGB,framerate=30/1,height=300,width=300 ! tensor_converter ! other/tensor,dimension=3:300:300,types=uint8,framerate=30/1,format=static ! fakesink" 7-1 0 0 $PERFORMANCE gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! videoscale ! videoconvert ! video/x-raw,format=RGB,framerate=30/1,height=300,width=300 ! tensor_converter ! other/tensors,num_tensors=1,dimension=3:300:300,types=uint8,framerate=30/1,format=static ! fakesink" 7-2 0 0 $PERFORMANCE -rm *.log *.bmp *.png *.golden +# Test with high dimension (rank>4) +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} filesrc location=\"test_00.dat\" blocksize=-1 ! application/octet-stream ! tensor_converter input-dim=4:4:4:4:4 input-type=float32 ! fakesink" 8-1 0 0 $PERFORMANCE +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} filesrc location=\"test_01.dat\" blocksize=-1 ! application/octet-stream ! tensor_converter input-dim=3:10:10:4:5:6 input-type=uint8 ! fakesink" 8-2 0 0 $PERFORMANCE + +rm *.log *.bmp *.png *.golden *.dat report diff --git a/tests/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c b/tests/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c index 1a324d9..834aadd 100644 --- a/tests/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c +++ b/tests/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c @@ -131,9 +131,6 @@ pt_invoke (void *private_data, const GstTensorFilterProperties * prop, assert (input); assert (output); - /* This assumes the limit is 4 */ - assert (NNS_TENSOR_RANK_LIMIT == 4); - assert (prop->input_meta.info[0].dimension[0] == prop->output_meta.info[0].dimension[0]); assert (prop->input_meta.info[0].dimension[3] == diff --git a/tests/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough.c b/tests/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough.c index 0533c39..5279d1d 100644 --- a/tests/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough.c +++ b/tests/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough.c @@ -25,6 +25,10 @@ #define D2 (280) #define D3 (40) #define D4 (1) +#define D5 (1) +#define D6 (1) +#define D7 (1) +#define D8 (1) /** * @brief _pt_data @@ -52,6 +56,10 @@ pt_init (const GstTensorFilterProperties * prop) data->info.dimension[1] = D2; data->info.dimension[2] = D3; data->info.dimension[3] = D4; + data->info.dimension[4] = D5; + data->info.dimension[5] = D6; + data->info.dimension[6] = D7; + data->info.dimension[7] = D8; data->info.type = _NNS_UINT8; return data; @@ -80,7 +88,7 @@ get_inputDim (void *private_data, const GstTensorFilterProperties * prop, UNUSED (prop); assert (data); - assert (NNS_TENSOR_RANK_LIMIT >= 3); + assert (NNS_TENSOR_RANK_LIMIT >= 7); info->num_tensors = 1; gst_tensor_info_copy (&info->info[0], &data->info); @@ -98,7 +106,7 @@ get_outputDim (void *private_data, const GstTensorFilterProperties * prop, UNUSED (prop); assert (data); - assert (NNS_TENSOR_RANK_LIMIT >= 3); + assert (NNS_TENSOR_RANK_LIMIT >= 7); info->num_tensors = 1; gst_tensor_info_copy (&info->info[0], &data->info); diff --git a/tests/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c b/tests/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c index 2c235df..f2ca5c1 100644 --- a/tests/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c +++ b/tests/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c @@ -138,9 +138,6 @@ pt_invoke (void *private_data, const GstTensorFilterProperties * prop, assert (input); assert (output); - /* This assumes the limit is 4 */ - assert (NNS_TENSOR_RANK_LIMIT == 4); - assert (prop->input_meta.info[0].dimension[0] == prop->output_meta.info[0].dimension[0]); assert (prop->input_meta.info[0].dimension[3] == diff --git a/tests/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c b/tests/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c index 505d962..253c6c7 100644 --- a/tests/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c +++ b/tests/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c @@ -144,9 +144,6 @@ pt_allocate_invoke (void *private_data, output[0].data = malloc (size); assert (output[0].data != NULL); - /* This assumes the limit is 4 */ - assert (NNS_TENSOR_RANK_LIMIT == 4); - assert (prop->input_meta.info[0].dimension[0] == prop->output_meta.info[0].dimension[0]); assert (prop->input_meta.info[0].dimension[3] == diff --git a/tests/nnstreamer_filter_pytorch/generateTest.py b/tests/nnstreamer_filter_pytorch/generateTest.py new file mode 100644 index 0000000..eb42577 --- /dev/null +++ b/tests/nnstreamer_filter_pytorch/generateTest.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +## +# SPDX-License-Identifier: LGPL-2.1-only +# +# Copyright (C) 2022 Samsung Electronics +# +# @file generateTest.py +# @brief generate test data and golden test result +# @author Yelin Jeong + +import numpy as np + +def save_test_data(filename, shape, type): + data = np.random.uniform(-100, 100, shape).astype(type) + with open(filename, 'wb') as file: + file.write(data.tobytes()) + + golden = data*2 + with open(filename + '.golden', 'wb') as file: + file.write(golden.tobytes()) + +save_test_data('test_00.dat', [4,4,4,4,4], np.float32) +save_test_data('test_01.dat', [3,10,10,4,5,6], np.int8) diff --git a/tests/nnstreamer_filter_pytorch/runTest.sh b/tests/nnstreamer_filter_pytorch/runTest.sh index b01a101..8b3a0a3 100644 --- a/tests/nnstreamer_filter_pytorch/runTest.sh +++ b/tests/nnstreamer_filter_pytorch/runTest.sh @@ -67,6 +67,15 @@ else fi fi +if [ "$SKIPGEN" == "YES" ]; then + echo "Test Case Generation Skipped" + sopath=$2 +else + echo "Test Case Generation Started" + python3 generateTest.py + sopath=$1 +fi + gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} filesrc location=${PATH_TO_IMAGE} ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=GRAY8,framerate=0/1 ! tensor_converter ! tensor_filter framework=pytorch model=${PATH_TO_MODEL} input=1:28:28:1 inputtype=uint8 output=10:1:1:1 outputtype=uint8 ! filesink location=tensorfilter.out.log" 1 0 0 $PERFORMANCE python3 checkLabel.py tensorfilter.out.log ${PATH_TO_IMAGE} testResult $? 1 "Golden test comparison" 0 1 @@ -132,7 +141,40 @@ gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=2 ! videos gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=2 ! videoscale ! videoconvert ! video/x-raw,width=3,height=4,format=GRAY8,framerate=0/1 ! tensor_converter ! tensor_transform mode=transpose option=2:1:0:3 ! other/tensors,num_tensors=1,dimensions=4:3:1:1,types=uint8,format=static,framerate=0/1 ! tensor_transform mode=typecast option=float32 ! tee name=t t. ! queue ! mux.sink_0 t. ! queue ! mux.sink_1 tensor_mux name=mux sync_mode=nosync ! queue ! tensor_filter framework=pytorch model=${PATH_TO_MODEL} input=4:3:1:1.4:3:1:1 inputtype=float32.float32 output=4:3:1:1.4:3:1:1 outputtype=float32.float32 ! other/tensors,num_tensors=2,dimensions=4:3.4:3 ! filesink location=tensorfilter.out.log" 10-2 0 0 $PERFORMANCE +PATH_TO_MODEL="../test_models/models/sample_4x4x4x4x4_two_input_one_output.pt" +# This model is made with below simple python script: +# +# import torch +# class MyCell(torch.nn.Module): +# def __init__(self): +# super(MyCell, self).__init__() +# def forward(self, x, y): +# z = x + y +# return z + +# my_cell = MyCell() +# x, y = torch.rand(4, 4, 4, 4, 4), torch.rand(4, 4, 4, 4, 4) +# traced_cell = torch.jit.trace(my_cell, (x, y)) +# traced_cell(x, y) +# traced_cell.save('sample_4x4x4x4x4_two_input_one_output.pt') + +# Test multiple input output tensors + +## correct input/output info +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} filesrc location=\"test_00.dat\" blocksize=-1 ! application/octet-stream ! tensor_converter input-dim=4:4:4:4:4 input-type=float32 ! tee name=t t. ! queue ! mux.sink_0 t. ! queue ! mux.sink_1 tensor_mux name=mux sync_mode=nosync ! queue ! tensor_filter framework=pytorch model=${PATH_TO_MODEL} input=4:4:4:4:4,4:4:4:4:4 inputtype=float32.float32 output=4:4:4:4:4 outputtype=float32 ! filesink location=tensorfilter.out.log" 11-1 0 0 $PERFORMANCE +callCompareTest test_00.dat.golden tensorfilter.out.log 11-1 "Compare 11-1" 1 0 + +## correct input/output info with full dimension +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} filesrc location=\"test_00.dat\" blocksize=-1 ! application/octet-stream ! tensor_converter input-dim=4:4:4:4:4:1:1:1 input-type=float32 ! tee name=t t. ! queue ! mux.sink_0 t. ! queue ! mux.sink_1 tensor_mux name=mux sync_mode=nosync ! queue ! tensor_filter framework=pytorch model=${PATH_TO_MODEL} input=4:4:4:4:4:1:1:1,4:4:4:4:4:1:1:1 inputtype=float32.float32 output=4:4:4:4:4:1:1:1 outputtype=float32 ! filesink location=tensorfilter.out.log" 11-2 0 0 $PERFORMANCE +callCompareTest test_00.dat.golden tensorfilter.out.log 11-2 "Compare 11-2" 1 0 + +## wrong input info +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} filesrc location=\"test_00.dat\" blocksize=-1 ! application/octet-stream ! tensor_converter input-dim=4:4:4:4:4 input-type=uint8 ! tee name=t t. ! queue ! mux.sink_0 t. ! queue ! mux.sink_1 tensor_mux name=mux sync_mode=nosync ! queue ! tensor_filter framework=pytorch model=${PATH_TO_MODEL} input=4:4:4:4:2:2,4:4:4:4:2:2 inputtype=uint8.uint8 output=4:4:4:4:4 outputtype=uint8 ! filesink location=tensorfilter.out.log" 12_n 0 1 $PERFORMANCE + +## wrong output info +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} filesrc location=\"test_00.dat\" blocksize=-1 ! application/octet-stream ! tensor_converter input-dim=4:4:4:4:4 input-type=uint8 ! tee name=t t. ! queue ! mux.sink_0 t. ! queue ! mux.sink_1 tensor_mux name=mux sync_mode=nosync ! queue ! tensor_filter framework=pytorch model=${PATH_TO_MODEL} input=4:4:4:4:4,4:4:4:4:4 inputtype=uint8.uint8 output=4:2:2:4:4 outputtype=uint8 ! filesink location=tensorfilter.out.log" 13_n 0 1 $PERFORMANCE + # Cleanup -rm info *.log *.golden +rm info *.log *.golden *.dat report diff --git a/tests/nnstreamer_filter_single/unittest_filter_single.cc b/tests/nnstreamer_filter_single/unittest_filter_single.cc index a3a7188..1130ba2 100644 --- a/tests/nnstreamer_filter_single/unittest_filter_single.cc +++ b/tests/nnstreamer_filter_single/unittest_filter_single.cc @@ -202,6 +202,133 @@ TEST_F (NNSFilterSingleTest, invalidProperty_n) } #endif /* ENABLE_TENSORFLOW_LITE */ +#ifdef ENABLE_TENSORFLOW2_LITE +/** + * @brief Test Fixture class for a tensor-filter single functionality with high rank. + */ +class NNSFilterSingleTestExtended : public::testing::Test +{ +protected: + GTensorFilterSingle *single; + GTensorFilterSingleClass *klass; + GstTensorMemory input[2]; + GstTensorMemory output; + gboolean loaded; + +public: + /** + * @brief Construct a new NNSFilterSingleTestExtended object + */ + NNSFilterSingleTestExtended () + : single (nullptr), klass (nullptr), loaded (FALSE) + { + input[0].data = input[1].data = output.data = nullptr; + input[0].size = input[1].size = output.size = 0; + } + + /** + * @brief SetUp method for each test case + */ + void SetUp () override + { + g_autofree gchar *model_file = nullptr; + gsize length = 4 * 4 * 4 * 4 * 4; + guint i; + const gchar *root_path = g_getenv ("NNSTREAMER_SOURCE_ROOT_PATH"); + + input[0].size = length * 4; + input[1].size = length * 4; + output.size = length * 4; + + single = (GTensorFilterSingle *) g_object_new (G_TYPE_TENSOR_FILTER_SINGLE, NULL); + klass = (GTensorFilterSingleClass *) g_type_class_ref (G_TYPE_TENSOR_FILTER_SINGLE); + + /* supposed to run test in build directory */ + if (root_path == NULL) + root_path = ".."; + + model_file = g_build_filename (root_path, "tests", "test_models", "models", + "sample_4x4x4x4x4_two_input_one_output.tflite", NULL); + ASSERT_TRUE (g_file_test (model_file, G_FILE_TEST_EXISTS)); + + input[0].data = g_malloc0(sizeof(gfloat)*length); + input[1].data = g_malloc0(sizeof(gfloat)*length); + + for (i = 0; i < length ; i++) { + ((gfloat*)input[0].data)[i] = i; + ((gfloat*)input[1].data)[i] = i + 1; + } + + g_object_set (G_OBJECT (single), "framework", "tensorflow-lite", + "model", model_file, NULL); + loaded = TRUE; + } + + /** + * @brief TearDown method for each test case + */ + void TearDown () override + { + g_type_class_unref (klass); + g_object_unref (single); + g_free (input[0].data); + g_free (input[1].data); + g_free (output.data); + } +}; + +/** + * @brief Test to invoke tf-lite model. + */ +TEST_F (NNSFilterSingleTestExtended, invoke_p) +{ + guint i, length = 4 * 4 * 4 * 4 * 4; + ASSERT_TRUE (this->loaded); + + /* invoke the model and check output result */ + EXPECT_TRUE (klass->invoke (single, input, &output, TRUE)); + + for (i = 0 ; i < length ; i++) + EXPECT_EQ (((gfloat *)output.data)[i], (((gfloat*)input[0].data)[i] + ((gfloat*)input[1].data)[i])); + + EXPECT_TRUE (klass->input_configured (single)); + EXPECT_TRUE (klass->output_configured (single)); + EXPECT_FALSE (klass->allocate_in_invoke (single)); + + klass->destroy_notify (single, &output); +} + +/** + * @brief Test to set invalid info. + */ +TEST_F (NNSFilterSingleTestExtended, setInvalidInfo_n) +{ + GstTensorsInfo in_info, out_info; + gst_tensors_info_init (&in_info); + gst_tensors_info_init (&out_info); + + ASSERT_TRUE (this->loaded); + EXPECT_TRUE (klass->start (single)); + + /* valid tensor info */ + in_info.num_tensors = 2U; + in_info.info[0].type = _NNS_FLOAT32; + gst_tensor_parse_dimension ("4:4:4:4:4", in_info.info[0].dimension); + in_info.info[1].type = _NNS_FLOAT32; + gst_tensor_parse_dimension ("4:4:4:4:4", in_info.info[1].dimension); + EXPECT_TRUE (klass->set_input_info (single, &in_info, &out_info) == 0); + + /* request to set invalid tensor info */ + in_info.num_tensors = 1U; + EXPECT_FALSE (klass->set_input_info (single, &in_info, &out_info) == 0); + + EXPECT_TRUE (klass->stop (single)); + gst_tensors_info_free (&in_info); + gst_tensors_info_free (&out_info); +} + +#endif /* ENABLE_TENSORFLOW2_LITE */ + /** * @brief Test to start before initializing. */ diff --git a/tests/nnstreamer_filter_tensorflow2_lite/runTest.sh b/tests/nnstreamer_filter_tensorflow2_lite/runTest.sh index addbcc4..f28d4b0 100644 --- a/tests/nnstreamer_filter_tensorflow2_lite/runTest.sh +++ b/tests/nnstreamer_filter_tensorflow2_lite/runTest.sh @@ -65,6 +65,15 @@ else fi fi +if [ "$SKIPGEN" == "YES" ]; then + echo "Test Case Generation Skipped" + sopath=$2 +else + echo "Test Case Generation Started" + python3 ../nnstreamer_filter_pytorch/generateTest.py + sopath=$1 +fi + PATH_TO_MODEL="../test_models/models/mobilenet_v1_1.0_224_quant.tflite" PATH_TO_LABEL="../test_models/labels/labels.txt" PATH_TO_IMAGE="../test_models/data/orange.png" @@ -201,7 +210,31 @@ gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} filesrc location=${PATH_TO_IMAGE} ! python3 checkLabel.py tensorfilter.out.log ${PATH_TO_LABEL} orange testResult $? 5 "Golden test comparison" 0 1 +PATH_TO_MODEL="../test_models/models/sample_4x4x4x4x4_two_input_one_output.tflite" +# This model is made with below simple python script: +# +# import tensorflow as tf +# from tensorflow import keras +# from tensorflow.keras.layers import * +# from tensorflow.keras import * + +# x1 = Input((4,4,4,4,4)) +# x2 = Input((4,4,4,4,4)) +# output = Add()([x1,x2]) +# model = Model(inputs=[x1,x2],outputs=[output]) +# model.compile() +# model.summary() + +# converter = tf.lite.TFLiteConverter.from_keras_model(model) +# tflite_model = converter.convert() + +# with open("tflite_model.tflite", "wb") as f: +# f.write(tflite_model) + +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} multifilesrc location=\"test_00.dat\" blocksize=-1 num_buffers=2 ! application/octet-stream ! tensor_converter input-dim=4:4:4:4:4 input-type=float32 ! tee name=t t. ! queue ! mux.sink_0 t. ! queue ! mux.sink_1 tensor_mux name=mux sync_mode=nosync ! queue ! tensor_filter framework=tensorflow2-lite model=${PATH_TO_MODEL} ! multifilesink location=tensorfilter.out.log" 6 0 0 $PERFORMANCE +callCompareTest test_00.dat.golden tensorfilter.out.log 6 "Compare 6" 1 0 + # Cleanup -rm info *.log +rm info *.log *.dat *.golden report diff --git a/tests/nnstreamer_if/unittest_if.cc b/tests/nnstreamer_if/unittest_if.cc index 32a4320..c9ccdc0 100644 --- a/tests/nnstreamer_if/unittest_if.cc +++ b/tests/nnstreamer_if/unittest_if.cc @@ -99,7 +99,7 @@ TEST (tensorIfProp, properties0) EXPECT_EQ (TIFCV_A_VALUE, int_val); g_object_get (tif_handle, "compared-value-option", &str_val, NULL); - EXPECT_STREQ ("0:2:1:1,0", str_val); + EXPECT_STREQ ("0:2:1:1:0:0:0:0,0", str_val); g_free (str_val); g_object_get (tif_handle, "supplied-value", &str_val, NULL); diff --git a/tests/nnstreamer_plugins/unittest_plugins.cc b/tests/nnstreamer_plugins/unittest_plugins.cc index dc514d3..ae57978 100644 --- a/tests/nnstreamer_plugins/unittest_plugins.cc +++ b/tests/nnstreamer_plugins/unittest_plugins.cc @@ -2140,7 +2140,7 @@ TEST (testTensorTransform, arithmeticFlexTensor) } /** - * @brief Test data for tensor_aggregator (2 frames with dimension 3:4:2:2) + * @brief Test data for tensor_aggregator (2 frames with dimension 3:4:2:2 or 3:2:2:2:2) */ const gint aggr_test_frames[2][48] = { { 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, @@ -2484,6 +2484,236 @@ TEST (testTensorAggregator, aggregate5) } /** + * @brief Test for tensor_aggregator (concatenate 2 frames with frames-dim 4, out-dimension 3:2:2:2:4) + */ +TEST (testTensorAggregator, aggregate6) +{ + GstHarness *h; + GstTensorsConfig config; + guint i; + gsize data_in_size; + + h = gst_harness_new ("tensor_aggregator"); + + g_object_set (h->element, "frames-out", 2, "frames-dim", 4, NULL); + + /* input tensor info */ + gst_tensors_config_init (&config); + config.info.num_tensors = 1; + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:2:2:2:2", config.info.info[0].dimension); + config.rate_n = 0; + config.rate_d = 1; + + gst_harness_set_src_caps (h, gst_tensors_caps_from_config (&config)); + data_in_size = gst_tensors_info_get_size (&config.info, 0); + + /* push buffers */ + for (i = 0; i < 2; i++) { + _aggregator_test_push_buffer (h, aggr_test_frames[i], data_in_size); + } + + /* get output buffer */ + const gint expected[96] = { 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, + 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, + 1121, 1122, 1123, 1124, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, + 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, + 1222, 1223, 1224, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, + 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, + 2124, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, + 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224 }; + + _aggregator_test_check_output (h, expected, 96); + + EXPECT_EQ (gst_harness_buffers_received (h), 1U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_aggregator (concatenate 2 frames with frames-dim 3, out-dimension 3:2:2:4:2) + */ +TEST (testTensorAggregator, aggregate7) +{ + GstHarness *h; + GstTensorsConfig config; + guint i; + gsize data_in_size; + + h = gst_harness_new ("tensor_aggregator"); + + g_object_set (h->element, "frames-out", 2, "frames-dim", 3, NULL); + + /* input tensor info */ + gst_tensors_config_init (&config); + config.info.num_tensors = 1; + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:2:2:2:2", config.info.info[0].dimension); + config.rate_n = 0; + config.rate_d = 1; + + gst_harness_set_src_caps (h, gst_tensors_caps_from_config (&config)); + data_in_size = gst_tensors_info_get_size (&config.info, 0); + + /* push buffers */ + for (i = 0; i < 2; i++) { + _aggregator_test_push_buffer (h, aggr_test_frames[i], data_in_size); + } + + /* get output buffer */ + const gint expected[96] = { 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, + 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, + 1121, 1122, 1123, 1124, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, + 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, + 2122, 2123, 2124, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, + 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, + 1224, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, + 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224 }; + + _aggregator_test_check_output (h, expected, 96); + + EXPECT_EQ (gst_harness_buffers_received (h), 1U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_aggregator (concatenate 2 frames with frames-dim 2, out-dimension 3:2:4:2:2) + */ +TEST (testTensorAggregator, aggregate8) +{ + GstHarness *h; + GstTensorsConfig config; + guint i; + gsize data_in_size; + + h = gst_harness_new ("tensor_aggregator"); + + g_object_set (h->element, "frames-out", 2, "frames-dim", 2, NULL); + + /* input tensor info */ + gst_tensors_config_init (&config); + config.info.num_tensors = 1; + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:2:2:2:2", config.info.info[0].dimension); + config.rate_n = 0; + config.rate_d = 1; + + gst_harness_set_src_caps (h, gst_tensors_caps_from_config (&config)); + data_in_size = gst_tensors_info_get_size (&config.info, 0); + + /* push buffers */ + for (i = 0; i < 2; i++) { + _aggregator_test_push_buffer (h, aggr_test_frames[i], data_in_size); + } + + /* get output buffer */ + const gint expected[96] = { 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, + 1109, 1110, 1111, 1112, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, + 2109, 2110, 2111, 2112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, + 1121, 1122, 1123, 1124, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, + 2122, 2123, 2124, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, + 1211, 1212, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, + 2212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, + 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224 }; + + _aggregator_test_check_output (h, expected, 96); + + EXPECT_EQ (gst_harness_buffers_received (h), 1U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_aggregator (concatenate 2 frames with frames-dim 1, out-dimension 3:4:2:2:2) + */ +TEST (testTensorAggregator, aggregate9) +{ + GstHarness *h; + GstTensorsConfig config; + guint i; + gsize data_in_size; + + h = gst_harness_new ("tensor_aggregator"); + + g_object_set (h->element, "frames-out", 2, "frames-dim", 1, NULL); + + /* input tensor info */ + gst_tensors_config_init (&config); + config.info.num_tensors = 1; + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:2:2:2:2", config.info.info[0].dimension); + config.rate_n = 0; + config.rate_d = 1; + + gst_harness_set_src_caps (h, gst_tensors_caps_from_config (&config)); + data_in_size = gst_tensors_info_get_size (&config.info, 0); + + /* push buffers */ + for (i = 0; i < 2; i++) { + _aggregator_test_push_buffer (h, aggr_test_frames[i], data_in_size); + } + + /* get output buffer */ + const gint expected[96] = { 1101, 1102, 1103, 1104, 1105, 1106, 2101, 2102, + 2103, 2104, 2105, 2106, 1107, 1108, 1109, 1110, 1111, 1112, 2107, 2108, + 2109, 2110, 2111, 2112, 1113, 1114, 1115, 1116, 1117, 1118, 2113, 2114, + 2115, 2116, 2117, 2118, 1119, 1120, 1121, 1122, 1123, 1124, 2119, 2120, 2121, + 2122, 2123, 2124, 1201, 1202, 1203, 1204, 1205, 1206, 2201, 2202, 2203, 2204, + 2205, 2206, 1207, 1208, 1209, 1210, 1211, 1212, 2207, 2208, 2209, 2210, 2211, + 2212, 1213, 1214, 1215, 1216, 1217, 1218, 2213, 2214, 2215, 2216, 2217, 2218, + 1219, 1220, 1221, 1222, 1223, 1224, 2219, 2220, 2221, 2222, 2223, 2224 }; + + _aggregator_test_check_output (h, expected, 96); + + EXPECT_EQ (gst_harness_buffers_received (h), 1U); + gst_harness_teardown (h); +} + +/** + * @brief Test for tensor_aggregator (concatenate 2 frames with frames-dim 0, out-dimension 6:2:2:2:2) + */ +TEST (testTensorAggregator, aggregate10) +{ + GstHarness *h; + GstTensorsConfig config; + guint i; + gsize data_in_size; + + h = gst_harness_new ("tensor_aggregator"); + + g_object_set (h->element, "frames-out", 2, "frames-dim", 0, NULL); + + /* input tensor info */ + gst_tensors_config_init (&config); + config.info.num_tensors = 1; + config.info.info[0].type = _NNS_INT32; + gst_tensor_parse_dimension ("3:2:2:2:2", config.info.info[0].dimension); + config.rate_n = 0; + config.rate_d = 1; + + gst_harness_set_src_caps (h, gst_tensors_caps_from_config (&config)); + data_in_size = gst_tensors_info_get_size (&config.info, 0); + + /* push buffers */ + for (i = 0; i < 2; i++) { + _aggregator_test_push_buffer (h, aggr_test_frames[i], data_in_size); + } + + /* get output buffer */ + const gint expected[96] = { 1101, 1102, 1103, 2101, 2102, 2103, 1104, 1105, + 1106, 2104, 2105, 2106, 1107, 1108, 1109, 2107, 2108, 2109, 1110, 1111, + 1112, 2110, 2111, 2112, 1113, 1114, 1115, 2113, 2114, 2115, 1116, 1117, + 1118, 2116, 2117, 2118, 1119, 1120, 1121, 2119, 2120, 2121, 1122, 1123, 1124, + 2122, 2123, 2124, 1201, 1202, 1203, 2201, 2202, 2203, 1204, 1205, 1206, 2204, + 2205, 2206, 1207, 1208, 1209, 2207, 2208, 2209, 1210, 1211, 1212, 2210, 2211, + 2212, 1213, 1214, 1215, 2213, 2214, 2215, 1216, 1217, 1218, 2216, 2217, 2218, + 1219, 1220, 1221, 2219, 2220, 2221, 1222, 1223, 1224, 2222, 2223, 2224 }; + + _aggregator_test_check_output (h, expected, 96); + + EXPECT_EQ (gst_harness_buffers_received (h), 1U); + gst_harness_teardown (h); +} + +/** * @brief Test for tensor_aggregator (flush old data in aggregator) */ TEST (testTensorAggregator, flushData) diff --git a/tests/test_models/models/custom_decoder.py b/tests/test_models/models/custom_decoder.py index b357485..3c8ec32 100644 --- a/tests/test_models/models/custom_decoder.py +++ b/tests/test_models/models/custom_decoder.py @@ -71,7 +71,7 @@ class CustomDecoder(object): fbb.String("") fbb.Int(ttype) with fbb.TypedVector(): - for j in range(4): + for j in range(8): fbb.Int(dims[j]) fbb.Blob(raw_data[i]) diff --git a/tests/test_models/models/passthrough.py b/tests/test_models/models/passthrough.py index af8e683..af94d0c 100644 --- a/tests/test_models/models/passthrough.py +++ b/tests/test_models/models/passthrough.py @@ -14,6 +14,10 @@ D1 = 3 D2 = 280 D3 = 40 D4 = 1 +D5 = 1 +D6 = 1 +D7 = 1 +D8 = 1 ## @@ -22,8 +26,8 @@ class CustomFilter(object): ## # @brief The constructor for custom filter: passthrough def __init__(self, *args): - self.input_dims = [nns.TensorShape([D1, D2, D3, D4], np.uint8)] - self.output_dims = [nns.TensorShape([D1, D2, D3, D4], np.uint8)] + self.input_dims = [nns.TensorShape([D1, D2, D3, D4, D5, D6, D7, D8], np.uint8)] + self.output_dims = [nns.TensorShape([D1, D2, D3, D4, D5, D6, D7, D8], np.uint8)] ## # @brief python callback: getInputDim diff --git a/tests/test_models/models/sample_4x4x4x4x4_two_input_one_output.pt b/tests/test_models/models/sample_4x4x4x4x4_two_input_one_output.pt new file mode 100644 index 0000000000000000000000000000000000000000..8145bb4233e70bf81d1417c9ad6094df62e147b7 GIT binary patch literal 1696 zcmWIWW@cev;NW1u0D25248@7L1v#nlCKXT^Us9eQpP5%sS`we1ml~g6S^{M1rzDmn z>J? z!}Ogw10Ru|OU_S8)rUJ#ub|S+i3`b>p?w?qnhkhd%J&^o_L#!oaYb)#;Pku|o0vSg z4)snH4*Bt0D5E`Z-|qC^R+khV_QvT3#%-Q?QcR24Va}Ep(|g01l;$j~e3NHw{XO0F zVzc}oVUaCorYulgFuQZZ)w@5gC2dHT+y2MwXye{xYK@uKBiQ>?4J$W1x$;e6Q;BU- zX^56NS3+RHcDoHSMSo8+`AvVn;+sp(oTG>97GFB{#G5mFVl6Nb*g5{hZdF_a43MXI z1I3X+pWHyvOG!;CO^*jB0&S$=A($GrUi9ueWWd7^F#V^e?NOa{vEc2WA1fbWRr+?< zbs>w8$LwXiPIou1KJs@5BfH|lCT4{VI+5QVMQ$p$WzyVXpwQru&Ge}Iyz?%82A%b} zA!hRb=P&-=x^CN=S?wAn=Qcj{5|hxJYuM^_ZbQzR3rGD;4n#%$3*D4+cG@1d)vJ9H z0u$Cfmww6?`!!35Kbie<)Jxr3hWSVC&ns_PWTbyJ_nTMLl5I&hC1wBd&Z*4H-2O@~ z>%aNV6%U_2>y+=^Ej#(bmrLe5?2gz>ynf9_c*eWtX*+DXUcZj|EHoD!>Zk99DBS>t z_)SJgQpBFmj2YO84)wg^lEl1{Vn}9V28DA2lO{OX=jwBY12ZxM2!oP6cDr;L6p6H} zEVZaOGe6JGNfv)>8gqft*Ts41p-e!VK{&vh5k$eu6yyx42a-Smq?Irbvk_SuIbEBh zn0pt%Nv1D3;$S~;Pg&dQ{DAr{#6K@?-NRX;LXOS12sa98DSVJR18MH0R|KZ1c8z#5CHYDgJ?T85Xry*k`C}@1@l-LSQ$X- GA!-3UmIHtQ literal 0 HcmV?d00001 diff --git a/tests/test_models/models/sample_4x4x4x4x4_two_input_one_output.tflite b/tests/test_models/models/sample_4x4x4x4x4_two_input_one_output.tflite new file mode 100644 index 0000000000000000000000000000000000000000..4fc02ced60b4bc55d705cecac3f5d4b20c09da16 GIT binary patch literal 1660 zcmai!ziU%b6vvMm+iGKtG)ROD89F$W+O)+MachwZ2^8sAh=KRi2gyrGU%LuUMMQAx z(9zM^KR`qrI*2$qIg6v4==1Zvc{fdKV{Z87-Fxo&@qOQW?kk(w=Dpft(JEH9k`=9B zd2ADwV{X{Y4!}pSa?WfW{J3a#fi+XS%)b9lQ^m-430ws`VRtWzA2)*VQFFJI^nKr? zX*$ln;*_Hq1a_Wh1;}>9zRxSaDBj*p8VmLuyY`Q5RhP5JHShRNuzv~2ZyL0txY6B> zlc*gw_QLK?)QRmf_7(`h7T5$eumlr?Zmyd>g z45igcdM9b_b1I)8ANdR7^O>Bg$yoM0-(h2&lfUmb&869O{*~XqW69ZVSx;%#JG*hm zorTNc-$A>|qh9iywO0QeVkm$w81_L8e8ZjqaXz5erQvJ_#i(zj5p-RT%5Mr@@R z%cwdzV*aVK`2RXDAua6$^$R1Xv)VW-*TQk{eHe(7HVhZHe^y-eIL_a#>8ua^-BNw^ z6T{{CM4l@wPH4tjdP$2HS$%)z>Y24{Z`e7^uyF&QQ{TZx_B|VU_C@zq==HdIOdaC2 z^E||F6c2rGhx4e8