From e6a9eef049112d88efd533dfa83dbd0805e7a187 Mon Sep 17 00:00:00 2001 From: Kwang Son Date: Sun, 8 Aug 2021 23:24:45 -0400 Subject: [PATCH] test: Add mv_test media vision unit test based on Gtest media vision already has testsuites and assessment but each has some limitations. See test/README.md more details. Change-Id: I1d62adaeac92efe5ddc9cc6fa7a350e1aa3c846a Signed-off-by: Kwang Son --- packaging/capi-media-vision.spec | 3 +- test/CMakeLists.txt | 11 ++++ test/README.md | 26 +++++++++ .../inference/test_image_classification.cpp | 58 ++++++++++++++++++++ .../inference/test_inference_helper.cpp | 62 ++++++++++++++++++++++ .../inference/test_inference_helper.hpp | 15 ++++++ 6 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 test/README.md create mode 100644 test/testsuites/machine_learning/inference/test_image_classification.cpp create mode 100644 test/testsuites/machine_learning/inference/test_inference_helper.cpp create mode 100644 test/testsuites/machine_learning/inference/test_inference_helper.hpp diff --git a/packaging/capi-media-vision.spec b/packaging/capi-media-vision.spec index e2543f2..805d60f 100644 --- a/packaging/capi-media-vision.spec +++ b/packaging/capi-media-vision.spec @@ -1,6 +1,6 @@ Name: capi-media-vision Summary: Media Vision library for Tizen Native API -Version: 0.8.3 +Version: 0.8.4 Release: 0 Group: Multimedia/Framework License: Apache-2.0 and BSD-3-Clause @@ -29,6 +29,7 @@ BuildRequires: pkgconfig(gstreamer-app-1.0) BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(ncurses) BuildRequires: pkgconfig(check) +BuildRequires: pkgconfig(gtest) %endif Requires: %{name}-machine_learning diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e8822a8..57768b0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,2 +1,13 @@ add_subdirectory(assessment) add_subdirectory(testsuites) + +project(mv_test) +cmake_minimum_required(VERSION 2.6) + +pkg_check_modules(${PROJECT_NAME}_DEP REQUIRED gtest gtest_main) +add_executable(${PROJECT_NAME} + testsuites/machine_learning/inference/test_inference_helper.cpp + testsuites/machine_learning/inference/test_image_classification.cpp +) +target_link_libraries(${PROJECT_NAME} ${${PROJECT_NAME}_DEP_LIBRARIES} mv_inference mv_image_helper) +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) \ No newline at end of file diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..310adf8 --- /dev/null +++ b/test/README.md @@ -0,0 +1,26 @@ +# mv_test +media vision unit test based on [GTEST](https://github.com/google/googletest) + +## Why? +media vision already has testsuites and assessment but each has some limitations. +1. testsuite - ITC(interactive test case) based which is mean when you modify some of vision code, you need type ITC commands on terminal. ITC hides some resource allocation and logics, it makes hard to debug code. +2. assessment - it's basically testsuite with timer so most of code are duplicated. + +mv_test try convert testsuite ITC to unit test and timer function. + +## How test? +First test needs dataset https://github.sec.samsung.net/k-son/mv_test.git +Install dataset on target using install.sh script and type `$ mv_test` + +### ASAN build command +`$ gbs build -A $ARCH --include-all --extra-packs asan-force-options,sanitizer-devel` +install libasan on target and on target terminal `$ ASAN_OPTIONS=detect_leaks=1 mv_test` + +## FAQ +### What about Tizen TCT? +Tizen tct is for public API verification. It's still valid however mv_test is more focus on internal APIs. +Another point is Tizen tct has huge amount of datset of other packages which is not related with media vision so build takes long, and complicated. + +### Why gtest? +I tried with libcheck but since Tizen API is C/C++, hard to cover all of C++ modules (interal API is more rely on C++). +libcheck also needs runtime dependancy. \ No newline at end of file diff --git a/test/testsuites/machine_learning/inference/test_image_classification.cpp b/test/testsuites/machine_learning/inference/test_image_classification.cpp new file mode 100644 index 0000000..979ebfa --- /dev/null +++ b/test/testsuites/machine_learning/inference/test_image_classification.cpp @@ -0,0 +1,58 @@ +#include +#include "test_inference_helper.hpp" + +#define IC_LABEL_MOBILENET_V1_224_PATH \ + MV_CONFIG_PATH \ + "/models/IC/tflite/ic_mobilenet_v1_label.txt" +#define IC_TFLITE_WEIGHT_MOBILENET_V1_224_PATH \ + MV_CONFIG_PATH \ + "/models/IC/tflite/ic_mobilenet_v1_224x224.tflite" +#define IMG_BANANA \ + MV_CONFIG_PATH \ + "/res/inference/images/banana.jpg" + +void _image_classified_cb(mv_source_h source, const int number_of_classes, + const int *indices, const char **names, + const float *confidences, void *user_data) +{ + ASSERT_EQ(number_of_classes, 1); + EXPECT_STREQ(names[0], "banana"); +} + +class TestImageClassification : public ::testing::Test +{ +public: + TestImageClassification() + { + EXPECT_EQ(mv_create_engine_config(&engine_cfg), + MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_inference_create(&infer), MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_create_source(&mv_source), MEDIA_VISION_ERROR_NONE); + } + ~TestImageClassification() + { + EXPECT_EQ(mv_destroy_source(mv_source), MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_inference_destroy(infer), MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_destroy_engine_config(engine_cfg), + MEDIA_VISION_ERROR_NONE); + } + mv_engine_config_h engine_cfg; + mv_inference_h infer; + mv_source_h mv_source; +}; + +TEST_F(TestImageClassification, CPU_TFLITE_MobilenetV1) +{ + engine_config_hosted_cpu_tflite_user_model( + engine_cfg, IC_TFLITE_WEIGHT_MOBILENET_V1_224_PATH, + IC_LABEL_MOBILENET_V1_224_PATH); + EXPECT_EQ(mv_inference_configure(infer, engine_cfg), + MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_inference_prepare(infer), MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(load_mv_source_from_file(mv_source, IMG_BANANA), + MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_inference_image_classify(mv_source, infer, NULL, + _image_classified_cb, NULL), + MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_source_clear(mv_source), MEDIA_VISION_ERROR_NONE); +} \ No newline at end of file diff --git a/test/testsuites/machine_learning/inference/test_inference_helper.cpp b/test/testsuites/machine_learning/inference/test_inference_helper.cpp new file mode 100644 index 0000000..9700001 --- /dev/null +++ b/test/testsuites/machine_learning/inference/test_inference_helper.cpp @@ -0,0 +1,62 @@ +#include +#include +#include "test_inference_helper.hpp" + +void engine_config_hosted_cpu_tflite(mv_engine_config_h handle, + const char *tf_weight) +{ + EXPECT_EQ(mv_engine_config_set_string_attribute( + handle, MV_INFERENCE_MODEL_WEIGHT_FILE_PATH, tf_weight), + MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_engine_config_set_int_attribute(handle, + MV_INFERENCE_BACKEND_TYPE, + MV_INFERENCE_BACKEND_TFLITE), + MEDIA_VISION_ERROR_NONE); + EXPECT_EQ(mv_engine_config_set_int_attribute(handle, + MV_INFERENCE_TARGET_TYPE, + MV_INFERENCE_TARGET_CPU), + MEDIA_VISION_ERROR_NONE); +} + +void engine_config_hosted_cpu_tflite_user_model(mv_engine_config_h handle, + const char *tf_weight, + const char *user_file) +{ + engine_config_hosted_cpu_tflite(handle, tf_weight); + EXPECT_EQ(mv_engine_config_set_string_attribute( + handle, MV_INFERENCE_MODEL_USER_FILE_PATH, user_file), + MEDIA_VISION_ERROR_NONE); +} + +// TODO: memcpy twice to one time +int load_mv_source_from_file(mv_source_h source, const char *path_to_image) +{ + unsigned char *data_buffer = NULL; + unsigned long buffer_size = 0; + image_data_s image_data; + + int err = load_image_to_buffer(path_to_image, &data_buffer, &buffer_size, + &image_data); + if (MEDIA_VISION_ERROR_NONE != err) { + printf("ERROR: Errors were occurred during opening file!!! code: %i\n", + err); + if (NULL != data_buffer) + destroy_loaded_buffer(data_buffer); + + return err; + } + + err = mv_source_fill_by_buffer(source, data_buffer, buffer_size, + image_data.image_width, + image_data.image_height, + image_data.image_colorspace); + + if (MEDIA_VISION_ERROR_NONE != err) + printf("ERROR: Errors were occurred during filling source!!! code %i\n", + err); + + if (NULL != data_buffer) + destroy_loaded_buffer(data_buffer); + + return err; +} diff --git a/test/testsuites/machine_learning/inference/test_inference_helper.hpp b/test/testsuites/machine_learning/inference/test_inference_helper.hpp new file mode 100644 index 0000000..4d1f679 --- /dev/null +++ b/test/testsuites/machine_learning/inference/test_inference_helper.hpp @@ -0,0 +1,15 @@ +#ifndef __TEST_INFERENCE_HELPER_HPP__ +#define __TEST_INFERENCE_HELPER_HPP__ + +#include + +void engine_config_hosted_cpu_tflite(mv_engine_config_h handle, + const char *tf_weight); + +void engine_config_hosted_cpu_tflite_user_model(mv_engine_config_h handle, + const char *tf_weight, + const char *user_file); + +int load_mv_source_from_file(mv_source_h source, const char *path_to_image); + +#endif //__TEST_INFERENCE_HELPER_HPP__ \ No newline at end of file -- 2.7.4