[Common] Add get_tensor_type, find_key_strv internal API.
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Thu, 31 May 2018 08:32:26 +0000 (17:32 +0900)
committer함명주/동작제어Lab(SR)/Principal Engineer/삼성전자 <myungjoo.ham@samsung.com>
Fri, 1 Jun 2018 05:39:31 +0000 (14:39 +0900)
1. Added get_tensor_type API for plugins to parse properties
2. Added unittest cases.

get_tensor_type may be implemented with find_key_strv, but, let's
use this "faster" for type property finder.

Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
CMakeLists.txt
common/tensor_common.c
common/test/unittest_common.cpp [new file with mode: 0644]
include/tensor_common.h
packaging/nnstreamer.spec

index 0576337..51dcf4a 100644 (file)
@@ -1,6 +1,6 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 
-PROJECT(nnstreamer C)
+PROJECT(nnstreamer C CXX)
 
 OPTION(TIZEN "Enable Tizen build mode" OFF)
 
@@ -24,12 +24,25 @@ SET(PKG_MODULES
        gstreamer-audio-1.0
        glib-2.0
 )
-IF(TIZEN)
+
+FIND_LIBRARY(GTEST_LIB gtest)
+IF(TIZEN OR GTEST_LIB)
        # Enable dlog of Tizen.
        ADD_DEFINITIONS(-DTIZEN=1)
        SET(PKG_MODULES ${PKG_MODULES} dlog)
-ENDIF(TIZEN)
-       
+       # Use GTEST shared lib
+       SET(gtestLink gtest pthread)
+       SET(gtestSrc "")
+       SET(gtestInc "")
+ELSE(TIZEN OR GTEST_LIB)
+       IF (NOT EXISTS /usr/src/gtest/src/gtest-all.cc)
+               MESSAGE(FATAL FATAL_ERROR "You need to install libgtest-dev or libgtest.so.")
+       ENDIF ()
+       SET(gtestLink pthread)
+       SET(gtestSrc /usr/src/gtest/src/gtest-all.cc)
+       SET(gtestInc /usr/src/gtest)
+ENDIF(TIZEN OR GTEST_LIB)
+
 pkg_check_modules(pkgs REQUIRED ${PKG_MODULES})
 
 INCLUDE_DIRECTORIES(
@@ -40,12 +53,19 @@ LINK_DIRECTORIES(${pkgs_LIBRARY_DIRS})
 FOREACH(flag ${pkgs_CFALGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror ")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror -fPIC")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -Wall -Werror -fPIC")
 
 # Provide common data
 ADD_LIBRARY(common STATIC common/tensor_common.c)
+TARGET_LINK_LIBRARIES(common ${pkgs_LIBRARIES})
 TARGET_INCLUDE_DIRECTORIES(common PUBLIC ${pkgs_INCLUDE_DIRS})
 SET(pkgs_LIBRARIES ${pkgs_LIBRARIES} common)
 
+# Unit test for common
+ADD_EXECUTABLE(unittest_common common/test/unittest_common.cpp ${gtestSrc})
+TARGET_INCLUDE_DIRECTORIES(unittest_common PUBLIC ${pkgs_INCLUDE_DIRS} ${gtestInc})
+TARGET_LINK_LIBRARIES(unittest_common ${pkgs_LIBRARIES} ${gtestLink})
+
 ADD_SUBDIRECTORY(tensor_converter)
 ADD_SUBDIRECTORY(tensor_filter)
index 7ac48a7..d261f5f 100644 (file)
@@ -50,6 +50,8 @@
  */
 
 #include <tensor_common.h>
+#include <string.h>
+#include <glib.h>
 
 /**
  * @brief String representations for each tensor element type.
@@ -63,4 +65,73 @@ const gchar* tensor_element_typename[] = {
         [_NNS_UINT8] = "uint8",
         [_NNS_FLOAT64] = "float64",
         [_NNS_FLOAT32] = "float32",
+       [_NNS_END] = NULL,
 };
+
+
+/**
+ * @brief Get tensor_type from string tensor_type input
+ * @return Corresponding tensor_type. _NNS_END if unrecognized value is there.
+ * @param typestr The string type name, supposed to be one of tensor_element_typename[]
+ */
+tensor_type get_tensor_type(const gchar* typestr) {
+  int len;
+
+  if (!typestr)
+    return _NNS_END;
+  len = strlen(typestr);
+
+  if (typestr[0] == 'u' || typestr[0] == 'U') {
+    /* Let's believe the developer and the following three letters are "int" (case insensitive) */
+    if (len == 6) /* uint16, uint32 */ {
+      if (typestr[4] == '1' && typestr[5] == '6')
+        return _NNS_UINT16;
+      else if (typestr[4] == '3' && typestr[5] == '2')
+        return _NNS_UINT32;
+    } else if (len == 5) /* uint8 */ {
+      if (typestr[4] == '8')
+        return _NNS_UINT8;
+    }
+  } else if (typestr[0] == 'i' || typestr[0] == 'I') {
+    /* Let's believe the developer and the following two letters are "nt" (case insensitive) */
+    if (len == 5) /* int16, int32 */ {
+      if (typestr[3] == '1' && typestr[4] == '6')
+        return _NNS_INT16;
+      else if (typestr[3] == '3' && typestr[4] == '2')
+        return _NNS_INT32;
+    } else if (len == 4) /* int8 */ {
+      if (typestr[3] == '8')
+        return _NNS_INT8;
+    }
+    return _NNS_END;
+  } else if (typestr[0] == 'f' || typestr[0] == 'F') {
+    /* Let's assume that the following 4 letters are "loat" */
+    if (len == 7) {
+      if (typestr[5] == '6' && typestr[6] == '4')
+        return _NNS_FLOAT64;
+      else if (typestr[5] == '3' && typestr[6] == '2')
+        return _NNS_FLOAT32;
+    }
+  }
+
+  return _NNS_END;
+}
+
+/**
+ * @brief Find the index value of the given key string array
+ * @return Corresponding index. Returns -1 if not found.
+ * @param strv Null terminated array of gchar *
+ * @param key The key string value
+ */
+int find_key_strv(const gchar **strv, const gchar *key) {
+  int cursor = 0;
+
+  g_assert(strv != NULL);
+  while (strv[cursor]) {
+    if (!g_ascii_strcasecmp(strv[cursor], key))
+      return cursor;
+    cursor++;
+  }
+
+  return -1; /* Not Found */
+}
diff --git a/common/test/unittest_common.cpp b/common/test/unittest_common.cpp
new file mode 100644 (file)
index 0000000..f38fa17
--- /dev/null
@@ -0,0 +1,205 @@
+/**
+ *  @file unittest_common.cpp
+ *  @date 31 May 2018
+ *  @author MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ *  @brief Unit test module for NNStreamer common library
+ *
+ *  Copyright 2018 Samsung Electronics
+ *
+ */
+
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <tensor_common.h>
+
+TEST(common_get_tensor_type, int32_1) {
+  EXPECT_EQ(get_tensor_type("int32"), _NNS_INT32);
+}
+TEST(common_get_tensor_type, int32_2) {
+  EXPECT_EQ(get_tensor_type("INT32"), _NNS_INT32);
+}
+TEST(common_get_tensor_type, int32_3) {
+  EXPECT_EQ(get_tensor_type("iNt32"), _NNS_INT32);
+}
+TEST(common_get_tensor_type, int32_4) {
+  EXPECT_EQ(get_tensor_type("InT32"), _NNS_INT32);
+}
+TEST(common_get_tensor_type, int32_5) {
+  EXPECT_EQ(get_tensor_type("InT322"), _NNS_END);
+}
+TEST(common_get_tensor_type, int32_6) {
+  EXPECT_EQ(get_tensor_type("int3"), _NNS_END);
+}
+
+
+TEST(common_get_tensor_type, int16_1) {
+  EXPECT_EQ(get_tensor_type("int16"), _NNS_INT16);
+}
+TEST(common_get_tensor_type, int16_2) {
+  EXPECT_EQ(get_tensor_type("INT16"), _NNS_INT16);
+}
+TEST(common_get_tensor_type, int16_3) {
+  EXPECT_EQ(get_tensor_type("iNt16"), _NNS_INT16);
+}
+TEST(common_get_tensor_type, int16_4) {
+  EXPECT_EQ(get_tensor_type("InT16"), _NNS_INT16);
+}
+TEST(common_get_tensor_type, int16_5) {
+  EXPECT_EQ(get_tensor_type("InT162"), _NNS_END);
+}
+TEST(common_get_tensor_type, int16_6) {
+  EXPECT_EQ(get_tensor_type("int1"), _NNS_END);
+}
+
+
+TEST(common_get_tensor_type, int8_1) {
+  EXPECT_EQ(get_tensor_type("int8"), _NNS_INT8);
+}
+TEST(common_get_tensor_type, int8_2) {
+  EXPECT_EQ(get_tensor_type("INT8"), _NNS_INT8);
+}
+TEST(common_get_tensor_type, int8_3) {
+  EXPECT_EQ(get_tensor_type("iNt8"), _NNS_INT8);
+}
+TEST(common_get_tensor_type, int8_4) {
+  EXPECT_EQ(get_tensor_type("InT8"), _NNS_INT8);
+}
+TEST(common_get_tensor_type, int8_5) {
+  EXPECT_EQ(get_tensor_type("InT82"), _NNS_END);
+}
+TEST(common_get_tensor_type, int8_6) {
+  EXPECT_EQ(get_tensor_type("int3"), _NNS_END);
+}
+
+
+TEST(common_get_tensor_type, uint32_1) {
+  EXPECT_EQ(get_tensor_type("uint32"), _NNS_UINT32);
+}
+TEST(common_get_tensor_type, uint32_2) {
+  EXPECT_EQ(get_tensor_type("UINT32"), _NNS_UINT32);
+}
+TEST(common_get_tensor_type, uint32_3) {
+  EXPECT_EQ(get_tensor_type("uiNt32"), _NNS_UINT32);
+}
+TEST(common_get_tensor_type, uint32_4) {
+  EXPECT_EQ(get_tensor_type("UInT32"), _NNS_UINT32);
+}
+TEST(common_get_tensor_type, uint32_5) {
+  EXPECT_EQ(get_tensor_type("UInT322"), _NNS_END);
+}
+TEST(common_get_tensor_type, uint32_6) {
+  EXPECT_EQ(get_tensor_type("uint3"), _NNS_END);
+}
+
+
+TEST(common_get_tensor_type, uint16_1) {
+  EXPECT_EQ(get_tensor_type("uint16"), _NNS_UINT16);
+}
+TEST(common_get_tensor_type, uint16_2) {
+  EXPECT_EQ(get_tensor_type("UINT16"), _NNS_UINT16);
+}
+TEST(common_get_tensor_type, uint16_3) {
+  EXPECT_EQ(get_tensor_type("uiNt16"), _NNS_UINT16);
+}
+TEST(common_get_tensor_type, uint16_4) {
+  EXPECT_EQ(get_tensor_type("UInT16"), _NNS_UINT16);
+}
+TEST(common_get_tensor_type, uint16_5) {
+  EXPECT_EQ(get_tensor_type("UInT162"), _NNS_END);
+}
+TEST(common_get_tensor_type, uint16_6) {
+  EXPECT_EQ(get_tensor_type("uint1"), _NNS_END);
+}
+
+
+TEST(common_get_tensor_type, uint8_1) {
+  EXPECT_EQ(get_tensor_type("uint8"), _NNS_UINT8);
+}
+TEST(common_get_tensor_type, uint8_2) {
+  EXPECT_EQ(get_tensor_type("UINT8"), _NNS_UINT8);
+}
+TEST(common_get_tensor_type, uint8_3) {
+  EXPECT_EQ(get_tensor_type("uiNt8"), _NNS_UINT8);
+}
+TEST(common_get_tensor_type, uint8_4) {
+  EXPECT_EQ(get_tensor_type("UInT8"), _NNS_UINT8);
+}
+TEST(common_get_tensor_type, uint8_5) {
+  EXPECT_EQ(get_tensor_type("UInT82"), _NNS_END);
+}
+TEST(common_get_tensor_type, uint8_6) {
+  EXPECT_EQ(get_tensor_type("uint3"), _NNS_END);
+}
+
+
+TEST(common_get_tensor_type, float32_1) {
+  EXPECT_EQ(get_tensor_type("float32"), _NNS_FLOAT32);
+}
+TEST(common_get_tensor_type, float32_2) {
+  EXPECT_EQ(get_tensor_type("FLOAT32"), _NNS_FLOAT32);
+}
+TEST(common_get_tensor_type, float32_3) {
+  EXPECT_EQ(get_tensor_type("float32"), _NNS_FLOAT32);
+}
+TEST(common_get_tensor_type, float32_4) {
+  EXPECT_EQ(get_tensor_type("FloaT32"), _NNS_FLOAT32);
+}
+TEST(common_get_tensor_type, float32_5) {
+  EXPECT_EQ(get_tensor_type("FloaT322"), _NNS_END);
+}
+TEST(common_get_tensor_type, float32_6) {
+  EXPECT_EQ(get_tensor_type("float3"), _NNS_END);
+}
+
+
+
+TEST(common_get_tensor_type, float64_1) {
+  EXPECT_EQ(get_tensor_type("float64"), _NNS_FLOAT64);
+}
+TEST(common_get_tensor_type, float64_2) {
+  EXPECT_EQ(get_tensor_type("FLOAT64"), _NNS_FLOAT64);
+}
+TEST(common_get_tensor_type, float64_3) {
+  EXPECT_EQ(get_tensor_type("float64"), _NNS_FLOAT64);
+}
+TEST(common_get_tensor_type, float64_4) {
+  EXPECT_EQ(get_tensor_type("FloaT64"), _NNS_FLOAT64);
+}
+TEST(common_get_tensor_type, float64_5) {
+  EXPECT_EQ(get_tensor_type("FloaT642"), _NNS_END);
+}
+TEST(common_get_tensor_type, float64_6) {
+  EXPECT_EQ(get_tensor_type("float6"), _NNS_END);
+}
+
+
+static const gchar* teststrv[] = {
+  "abcde",
+  "ABCDEF",
+  "1234",
+  "abcabc",
+  "tester",
+  NULL
+};
+TEST(common_find_key_strv, case1) {
+  EXPECT_EQ(find_key_strv(teststrv, "abcde"), 0);
+}
+TEST(common_find_key_strv, case2) {
+  EXPECT_EQ(find_key_strv(teststrv, "ABCDE"), 0);
+}
+TEST(common_find_key_strv, case3) {
+  EXPECT_EQ(find_key_strv(teststrv, "1234"), 2);
+}
+TEST(common_find_key_strv, case4) {
+  EXPECT_EQ(find_key_strv(teststrv, "tester"), 4);
+}
+TEST(common_find_key_strv, case5) {
+  EXPECT_EQ(find_key_strv(teststrv, "abcabcd"), -1);
+}
+
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
index 199b967..77ef284 100644 (file)
@@ -109,6 +109,21 @@ static const unsigned int tensor_element_size[] = {
  */
 extern const gchar* tensor_element_typename[];
 
+/**
+ * @brief Get tensor_type from string tensor_type input
+ * @return Corresponding tensor_type. _NNS_END if unrecognized value is there.
+ * @param typestr The string type name, supposed to be one of tensor_element_typename[]
+ */
+extern tensor_type get_tensor_type(const gchar* typestr);
+
+/**
+ * @brief Find the index value of the given key string array
+ * @return Corresponding index
+ * @param strv Null terminated array of gchar *
+ * @param key The key string value
+ */
+extern int find_key_strv(const gchar **strv, const gchar *key);
+
 G_END_DECLS
 
 #endif /* __GST_TENSOR_COMMON_H__ */
index 1b7e478..0920818 100644 (file)
@@ -21,6 +21,8 @@ BuildRequires:        libdlog-devel
 BuildRequires: gst-plugins-good
 BuildRequires: gst-plugins-good-extra
 BuildRequires: gst-plugins-base
+# and gtest
+BuildRequires: gtest-devel
 
 %description
 NNStreamer is a set of gstreamer plugins to support general neural networks
@@ -40,6 +42,10 @@ popd
 
 # DO THE TEST!
 
+pushd build
+./unittest_common
+popd
+
 pushd tensor_converter/test
 # We skip testcase gen because it requires PIL, which requires tk.
 # Use the pre-generated test cases