[UnitTest/Utils] Revise conf/utils and add their negative unittests
authorDongju Chae <dongju.chae@samsung.com>
Wed, 8 Apr 2020 06:38:08 +0000 (15:38 +0900)
committer채동주/On-Device Lab(SR)/Staff Engineer/삼성전자 <dongju.chae@samsung.com>
Fri, 10 Apr 2020 04:35:36 +0000 (13:35 +0900)
This path modifies the naive impl. of getConf(), and adds negative test
cases for utils/conf.

Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
src/core/ne-mem.cc
src/core/ne-thread-pool.cc
src/core/utils/ne-conf.cc
src/core/utils/ne-conf.h
src/core/utils/ne-utils.cc
tests/unittests/ne_core_utils_test.cc

index ef368a2..d661260 100644 (file)
@@ -68,7 +68,7 @@ MemAllocator::createInstance (const DriverAPI *api)
 {
   std::unique_ptr<MemAllocator> mem;
 
-  if (Conf::getConf()->getResvMemSize() > 0)
+  if (Conf::getInstance().getResvMemSize() > 0)
     mem.reset (new MemPool (api));
   else
     mem.reset (new MemDefault (api));
index 90dbc13..d313e97 100644 (file)
@@ -33,7 +33,7 @@ ThreadPool::ThreadPool ()
   : stop_ (false)
 {
   /** create workers with the number of threads configured */
-  num_threads_ = (Conf::getConf()->getNumThreads());
+  num_threads_ = (Conf::getInstance().getNumThreads());
   for (uint32_t i = 0; i < num_threads_; i++)
     threads_.emplace_back ([this]() { this->worker(); });
 }
index 8526588..1caf36c 100644 (file)
 #include "ne-conf.h"
 
 /** @brief singleton instance for configuration */
-Conf Conf::instance_;
+std::unique_ptr<Conf> Conf::instance_;
+std::once_flag Conf::once_flag_;
 
 /**
  * @brief get the instance of configuration after reloading .ini file
  * @param[in] [OPTIONAL] inipath the path of .ini file
  * @return the conf instance
  */
-Conf *
-Conf::getConf (const char *inipath)
+Conf &
+Conf::getInstance (const char *inipath)
 {
-  instance_.loadConf (inipath);
-  return &instance_;
+  call_once (once_flag_, []() {
+    instance_.reset (new Conf);
+  });
+
+  instance_->loadConf (inipath);
+  return *(instance_.get ());
 }
 
 /**
index 14c09c3..43c03e8 100644 (file)
@@ -20,6 +20,9 @@
 #include <stdint.h>
 #include <iniparser.h>
 
+#include <memory>
+#include <mutex>
+
 #define MAX_DIR_LEN 256
 
 #define DEFAULT_LOG_DIR         "/tmp/"
@@ -33,7 +36,7 @@
 /** @brief Configuration for NPU-Engine components */
 class Conf {
   public:
-    static Conf* getConf (const char *inipath = nullptr);
+    static Conf & getInstance (const char *inipath = nullptr);
 
     size_t getResvMemSize() { return reserved_mem_size_; }
     uint32_t getNumThreads() { return num_threads_; }
@@ -42,7 +45,10 @@ class Conf {
     void reset();
 
   private:
-    static Conf instance_;
+    static std::unique_ptr<Conf> instance_;
+    static std::once_flag once_flag_;
+
+    Conf () {}
 
     void loadConf (const char *inipath);
     void loadConfIni (dictionary *ini);
index c2c0d8f..27cc9ec 100644 (file)
@@ -93,10 +93,20 @@ Logger::logwrite (loglevel l, module m, const char *format, ...)
   char* time_str;
   va_list args;
 
+  if (l < LOG_INFO || l >= LOG_END)
+    return;
+
+  if (m < _N1 || m >= _NEND)
+    return;
+
+  if (format == nullptr)
+    return;
+
   if (fp_ == NULL) {
     char filename[FILENAME_MAX];
 
-    snprintf(filename, FILENAME_MAX, "%s%s", Conf::getConf()->getLogDir(), logfilename);
+    snprintf(filename, FILENAME_MAX, "%s%s",
+        Conf::getInstance().getLogDir(), logfilename);
     fp_ = fopen (filename, "a");
   }
 
index 0f68c16..1ae94dd 100644 (file)
@@ -49,7 +49,23 @@ static void restore_envvars (ENV_PAIR & envvars)
 }
 
 /**
- * @brief test loading configuration (default configuration)
+ * @brief test getInstance() singleton
+ */
+TEST (ne_core_utils_test, get_instance_singleton)
+{
+  Conf & conf = Conf::getInstance ();
+  Conf & conf2 = Conf::getInstance ();
+
+  EXPECT_EQ (&conf, &conf2);
+
+  Logger & logger = Logger::getInstance ();
+  Logger & logger2 = Logger::getInstance ();
+
+  EXPECT_EQ (&logger, &logger2);
+}
+
+/**
+ * @brief test loadConfDefault()
  */
 TEST (ne_core_utils_test, load_conf_default)
 {
@@ -58,20 +74,18 @@ TEST (ne_core_utils_test, load_conf_default)
   save_and_unset_envvars (envvars);
 
   /** load configuration without argument */
-  Conf * conf = Conf::getConf ();
-  ASSERT_NE (conf, nullptr);
+  Conf & conf = Conf::getInstance ();
 
   /** default configurations */
-  EXPECT_EQ (conf->getResvMemSize(), DEFAULT_RESV_MEM_SIZE);
-  EXPECT_EQ (conf->getNumThreads(), DEFAULT_NUM_THREADS);
-  EXPECT_STREQ (conf->getLogDir(), DEFAULT_LOG_DIR);
+  EXPECT_EQ (conf.getResvMemSize(), DEFAULT_RESV_MEM_SIZE);
+  EXPECT_EQ (conf.getNumThreads(), DEFAULT_NUM_THREADS);
+  EXPECT_STREQ (conf.getLogDir(), DEFAULT_LOG_DIR);
 
-  /** restore envvar*/
   restore_envvars (envvars);
 }
 
 /**
- * @brief test loading configuration (.ini file)
+ * @brief test loadConfIni()
  */
 TEST (ne_core_utils_test, load_conf_ini)
 {
@@ -90,13 +104,46 @@ TEST (ne_core_utils_test, load_conf_ini)
   ASSERT_EQ (fwrite (ini_str, strlen(ini_str), 1, fp), 1);
   ASSERT_EQ (fclose (fp), 0);
 
-  Conf *conf = Conf::getConf ("dummy.ini");
-  EXPECT_NE (conf, nullptr);
-  EXPECT_EQ (conf->getResvMemSize(), 128 * 1024);
-  EXPECT_EQ (conf->getNumThreads(), 4);
-  EXPECT_STREQ (conf->getLogDir(), "/tmp/test_log");
+  Conf & conf = Conf::getInstance ("dummy.ini");
 
-  /** default configurations */
+  EXPECT_EQ (conf.getResvMemSize(), 128 * 1024);
+  EXPECT_EQ (conf.getNumThreads(), 4);
+  EXPECT_STREQ (conf.getLogDir(), "/tmp/test_log");
+
+  conf.reset ();
+  restore_envvars (envvars);
+}
+
+/**
+ * @brief test loadConfIni() with error handling
+ */
+TEST (ne_core_utils_test, load_conf_ini_n)
+{
+  ENV_PAIR envvars;
+  save_and_unset_envvars (envvars);
+
+  /** load default configurations */
+  Conf & conf = Conf::getInstance ();
+
+  /** make dummy .ini file */
+  FILE *fp = fopen ("dummy.ini", "w");
+  const char *ini_str = "[main]\n"
+                        "resv_mem_size=asdf\n"
+                        "num_threads=-1\n";
+
+  /** from .ini file */
+  ASSERT_NE (fp, nullptr);
+  ASSERT_EQ (fwrite (ini_str, strlen(ini_str), 1, fp), 1);
+  ASSERT_EQ (fclose (fp), 0);
+
+  conf = Conf::getInstance ("dummy.ini");
+
+  /** still default configurations */
+  EXPECT_EQ (conf.getResvMemSize(), DEFAULT_RESV_MEM_SIZE);
+  EXPECT_EQ (conf.getNumThreads(), DEFAULT_NUM_THREADS);
+  EXPECT_STREQ (conf.getLogDir(), DEFAULT_LOG_DIR);
+
+  conf.reset ();
   restore_envvars (envvars);
 }
 
@@ -108,38 +155,28 @@ TEST (ne_core_utils_test, load_conf_env)
   ENV_PAIR envvars;
   save_and_unset_envvars (envvars);
 
-  /** from env */
   EXPECT_EQ (setenv("NE_RESV_MEM_SIZE", "1G", 1), 0);
   EXPECT_EQ (setenv("NE_NUM_THREADS", "16", 1), 0);
   EXPECT_EQ (setenv("NE_LOG_DIR", "/tmp/", 1), 0);
 
-  Conf *conf = Conf::getConf ();
-  EXPECT_NE (conf, nullptr);
-  EXPECT_EQ (conf->getResvMemSize(), 1024 * 1024 * 1024);
-  EXPECT_EQ (conf->getNumThreads(), 16);
-  EXPECT_STREQ (conf->getLogDir(), "/tmp/");
+  Conf & conf = Conf::getInstance ();
+
+  EXPECT_EQ (conf.getResvMemSize(), 1024 * 1024 * 1024);
+  EXPECT_EQ (conf.getNumThreads(), 16);
+  EXPECT_STREQ (conf.getLogDir(), "/tmp/");
 
+  conf.reset ();
   restore_envvars (envvars);
 }
 
 /**
  * @brief test loading configuration (negative cases)
  */
-TEST (ne_core_utils_test, load_conf_n)
+TEST (ne_core_utils_test, load_conf_env_n)
 {
   ENV_PAIR envvars;
   save_and_unset_envvars (envvars);
 
-  /** from defaults */
-  Conf * conf = Conf::getConf ();
-  ASSERT_NE (conf, nullptr);
-  conf->reset ();
-
-  /** default configurations */
-  EXPECT_EQ (conf->getResvMemSize(), DEFAULT_RESV_MEM_SIZE);
-  EXPECT_EQ (conf->getNumThreads(), DEFAULT_NUM_THREADS);
-  EXPECT_STREQ (conf->getLogDir(), DEFAULT_LOG_DIR);
-
   /** from env (wrong values) */
   EXPECT_EQ (setenv("NE_RESV_MEM_SIZE", "ASDF", 1), 0);
   EXPECT_EQ (setenv("NE_NUM_THREADS", "-1", 1), 0);
@@ -151,12 +188,15 @@ TEST (ne_core_utils_test, load_conf_n)
 
   EXPECT_EQ (setenv("NE_LOG_DIR", long_log_dir_str, 1), 0);
 
-  conf = Conf::getConf ();
-  ASSERT_NE (conf, nullptr);
-  EXPECT_EQ (conf->getResvMemSize(), DEFAULT_RESV_MEM_SIZE);
-  EXPECT_EQ (conf->getNumThreads(), DEFAULT_NUM_THREADS);
-  EXPECT_STREQ (conf->getLogDir(), DEFAULT_LOG_DIR);
+  /** load conf with envvars */
+  Conf & conf = Conf::getInstance ();
+
+  /** still default configurations */
+  EXPECT_EQ (conf.getResvMemSize(), DEFAULT_RESV_MEM_SIZE);
+  EXPECT_EQ (conf.getNumThreads(), DEFAULT_NUM_THREADS);
+  EXPECT_STREQ (conf.getLogDir(), DEFAULT_LOG_DIR);
 
+  conf.reset ();
   restore_envvars (envvars);
 }
 
@@ -196,24 +236,74 @@ TEST (ne_core_utils_test, thread_safe_map)
 /**
  * @brief test features of thread-safe map (negative cases)
  */
-TEST (ne_core_utils_test, thread_safe_map_n)
+TEST (ne_core_utils_test, thread_safe_map_insert_n)
 {
   ThreadSafeMap<int, int> m;
-  int *val;
 
   EXPECT_EQ (m.insert (1, new int (2)), 0);
-  val = m.find (1);
-  EXPECT_EQ (*val, 2);
-
   EXPECT_NE (m.insert (1, new int (3)), 0);
   EXPECT_NE (m.insert (1, new int (4)), 0);
-  EXPECT_EQ (m.find (2), nullptr);
-  EXPECT_NE (m.remove (3), 0);
 
   m.clear ();
 }
 
 /**
+ * @brief test features of thread-safe map (negative cases)
+ */
+TEST (ne_core_utils_test, thread_safe_map_remove_n)
+{
+  ThreadSafeMap<int, int> m;
+
+  EXPECT_NE (m.remove (0), 0);
+  EXPECT_EQ (m.insert (1, new int (2)), 0);
+  EXPECT_EQ (m.remove (1), 0);
+  EXPECT_NE (m.remove (1), 0);
+
+  m.clear ();
+}
+
+/**
+ * @brief test features of thread-safe map (negative cases)
+ */
+TEST (ne_core_utils_test, thread_safe_map_find_n)
+{
+  ThreadSafeMap<int, int> m;
+
+  EXPECT_EQ (m.find (0), nullptr);
+  EXPECT_EQ (m.insert (1, new int (2)), 0);
+  EXPECT_EQ (m.remove (1), 0);
+  EXPECT_EQ (m.find (1), nullptr);
+
+  m.clear ();
+}
+
+/**
+ * @brief test features of log writing
+ */
+TEST (ne_core_utils_test, log_write)
+{
+  Logger & logger = Logger::getInstance ();
+
+  logger.logwrite (LOG_ERROR, _N1, "test error\n");
+  logger.logwrite (LOG_WARN, _N1, "test warn\n");
+  logger.logwrite (LOG_INFO, _N1, "test info\n");
+}
+
+/**
+ * @brief test features of log writing (negative cases)
+ */
+TEST (ne_core_utils_test, log_write_n)
+{
+  Logger & logger = Logger::getInstance ();
+
+  /** logwrite is ignored for invalid arguments */
+  logger.logwrite (LOG_END, _NEND, "invalid\n");
+  logger.logwrite (LOG_END, _N1, "invalid\n");
+  logger.logwrite (LOG_INFO, _NEND, "invalid\n");
+  logger.logwrite (LOG_INFO, _N1, nullptr);
+}
+
+/**
  * @brief main function for unit test
  */
 int