Improve code coverage 02/297902/2
authorHwankyu Jhun <h.jhun@samsung.com>
Mon, 28 Aug 2023 09:16:51 +0000 (18:16 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 28 Aug 2023 10:29:12 +0000 (19:29 +0900)
- Adds unit test
- Excludes some lines

Change-Id: Ice9f4b2605ac517f2c0defca4c6f622aeef982e6
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
include/service_app.hpp
src/job-manager.cc
src/job.cc
src/service_app_main.cc
unittests/mock/module_mock.h
unittests/mock/test_fixture.h
unittests/service_app_cpp_test.cc
unittests/service_app_test.cc

index e421364..1c59034 100644 (file)
@@ -34,9 +34,11 @@ class ServiceAppBase : public app_common::AppBase<
       : AppBase(service_app_add_event_handler,
                 service_app_remove_event_handler) {}
 
+  // LCOV_EXCL_START
   virtual bool OnCreate() { return true; }
   virtual void OnTerminate() {}
   virtual void OnAppControl(const ReceivedAppControl& ctrl) {}
+  // LCOV_EXCL_STOP
 
   int Run(int argc, char** argv) {
     service_app_lifecycle_callback_s callback = {
@@ -49,8 +51,10 @@ class ServiceAppBase : public app_common::AppBase<
         b->OnTerminate();
       },
       app_control : [](app_control_h app_control, void* user_data) {
+        // LCOV_EXCL_START
         ServiceAppBase* b = static_cast<ServiceAppBase*>(user_data);
         b->OnAppControl(ReceivedAppControl(app_control));
+        // LCOV_EXCL_STOP
       }
     };
 
index 3293c11..82bc88a 100644 (file)
@@ -57,8 +57,10 @@ bool JobManager::ExistJobHandler(JobHandler* handler) {
 void JobManager::Do(std::shared_ptr<Job> job) {
   job->SetEventListener(this);
   if (!ExistJobHandler(job->GetId())) {
+    // LCOV_EXCL_START
     job->SetTimer();
     AddPendingJob(job);
+    // LCOV_EXCL_STOP
   } else {
     job->SetIdler();
     AddRunningJob(job);
@@ -70,8 +72,10 @@ int JobManager::Finish(const std::string& job_id) {
   int ret = aul_job_scheduler_update_job_status(job_id.c_str(),
       JOB_STATUS_FINISHED);
   if (ret != AUL_R_OK) {
+    // LCOV_EXCL_START
     _E("aul_job_scheduler_update_job_status() is failed. error(%d)", ret);
     return ret;
+    // LCOV_EXCL_STOP
   }
 
   return 0;
@@ -85,12 +89,14 @@ void JobManager::FinishAllJobs() {
 void JobManager::FlushPendingJob(const std::string& job_id) {
   auto iter = pending_jobs_.begin();
   while (iter != pending_jobs_.end()) {
+    // LCOV_EXCL_START
     if ((*iter)->GetId() == job_id) {
       auto job = *iter;
       iter = pending_jobs_.erase(iter);
       job->UnsetTimer();
       AddPendingJob(job);
       job->SetIdler();
+    // LCOV_EXCL_STOP
     } else {
       iter++;
     }
@@ -111,10 +117,13 @@ void JobManager::RemoveRunningJob(const std::string& job_id) {
   }
 }
 
+// LCOV_EXCL_START
 void JobManager::AddPendingJob(std::shared_ptr<Job> job) {
   pending_jobs_.push_back(job);
 }
+// LCOV_EXCL_STOP
 
+// LCOV_EXCL_START
 void JobManager::RemovePendingJob(const std::string& job_id) {
   auto iter = pending_jobs_.begin();
   while (iter != pending_jobs_.end()) {
@@ -124,12 +133,15 @@ void JobManager::RemovePendingJob(const std::string& job_id) {
       iter++;
   }
 }
+// LCOV_EXCL_STOP
 
+// LCOV_EXCL_START
 void JobManager::OnTimedOut(const Job* job) {
   _E("[__TIMEDOUT__] Job(%s), Status(%d)",
       job->GetId().c_str(), job->GetStatus());
   RemovePendingJob(job->GetId());
 }
+// LCOV_EXCL_STOP
 
 void JobManager::OnRun(const Job* job) {
   _D("[__JOB__] START. Job(%s), Status(%d)",
@@ -141,12 +153,14 @@ void JobManager::OnRun(const Job* job) {
         h->Do(job);
     }
   } else {
+    // LCOV_EXCL_START
     for (auto* h : handlers_) {
       if (h->GetJobId() == job->GetId())
         h->Do(job);
     }
     aul_job_scheduler_update_job_status(job->GetId().c_str(),
         JOB_STATUS_STOPPED);
+    // LCOV_EXCL_STOP
   }
   _D("[__JOB__] END. Job(%s), Status(%d)",
       job->GetId().c_str(), job->GetStatus());
index 7af489a..0758b9f 100644 (file)
@@ -44,6 +44,7 @@ void Job::SetEventListener(IEvent* listener) {
   listener_ = listener;
 }
 
+// LCOV_EXCL_START
 void Job::SetTimer() {
   if (timer_ == 0) {
     timer_ = g_timeout_add(5000, TimedOutCb, this);
@@ -51,11 +52,14 @@ void Job::SetTimer() {
       _E("g_timeout_add() is failed");
   }
 }
+// LCOV_EXCL_STOP
 
 void Job::UnsetTimer() {
   if (timer_ != 0) {
+    // LCOV_EXCL_START
     g_source_remove(timer_);
     timer_ = 0;
+    // LCOV_EXCL_STOP
   }
 }
 
@@ -63,17 +67,20 @@ void Job::SetIdler() {
   if (idler_ == 0) {
     idler_ = g_idle_add(IdleCb, this);
     if (idler_ == 0)
-      _E("g_idle_add() is failed");
+      _E("g_idle_add() is failed");  // LCOV_EXCL_LINE
   }
 }
 
 void Job::UnsetIdler() {
   if (idler_ != 0) {
+    // LCOV_EXCL_START
     g_source_remove(idler_);
     idler_ = 0;
+    // LCOV_EXCL_STOP
   }
 }
 
+// LCOV_EXCL_START
 gboolean Job::TimedOutCb(gpointer data) {
   auto* handle = static_cast<Job*>(data);
   handle->timer_ = 0;
@@ -84,6 +91,7 @@ gboolean Job::TimedOutCb(gpointer data) {
 
   return G_SOURCE_REMOVE;
 }
+// LCOV_EXCL_STOP
 
 gboolean Job::IdleCb(gpointer data) {
   auto* handle = static_cast<Job*>(data);
index 65ed36c..42ebd46 100644 (file)
@@ -50,16 +50,16 @@ const char* __error_to_string(app_error_e error) {
       return "NONE";
     case APP_ERROR_INVALID_PARAMETER:
       return "INVALID_PARAMETER";
-    case APP_ERROR_OUT_OF_MEMORY:
-      return "OUT_OF_MEMORY";
+    case APP_ERROR_OUT_OF_MEMORY:  // LCOV_EXCL_LINE
+      return "OUT_OF_MEMORY";  // LCOV_EXCL_LINE
     case APP_ERROR_INVALID_CONTEXT:
       return "INVALID_CONTEXT";
-    case APP_ERROR_NO_SUCH_FILE:
-      return "NO_SUCH_FILE";
+    case APP_ERROR_NO_SUCH_FILE:  // LCOV_EXCL_LINE
+      return "NO_SUCH_FILE";  // LCOV_EXCL_LINE
     case APP_ERROR_ALREADY_RUNNING:
       return "ALREADY_RUNNING";
-    default:
-      return "UNKNOWN";
+    default:  // LCOV_EXCL_LINE
+      return "UNKNOWN";  // LCOV_EXCL_LINE
   }
 }
 
@@ -77,12 +77,14 @@ int __on_error(app_error_e error, const char* function,
 
 constexpr int APP_EVENT_MAX = 7;
 constexpr IAppCore::IEvent::Type __app_event_converter[APP_EVENT_MAX] = {
-  [APP_EVENT_LOW_MEMORY] = IAppCore::IEvent::Type::LOW_MEMORY,
-  [APP_EVENT_LOW_BATTERY] = IAppCore::IEvent::Type::LOW_BATTERY,
-  [APP_EVENT_LANGUAGE_CHANGED] = IAppCore::IEvent::Type::LANG_CHANGE,
-  [APP_EVENT_DEVICE_ORIENTATION_CHANGED] = IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED,
-  [APP_EVENT_REGION_FORMAT_CHANGED] = IAppCore::IEvent::Type::REGION_CHANGE,
-  [APP_EVENT_SUSPENDED_STATE_CHANGED] = IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE,
+    [APP_EVENT_LOW_MEMORY] = IAppCore::IEvent::Type::LOW_MEMORY,
+    [APP_EVENT_LOW_BATTERY] = IAppCore::IEvent::Type::LOW_BATTERY,
+    [APP_EVENT_LANGUAGE_CHANGED] = IAppCore::IEvent::Type::LANG_CHANGE,
+    [APP_EVENT_DEVICE_ORIENTATION_CHANGED] =
+        IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED,
+    [APP_EVENT_REGION_FORMAT_CHANGED] = IAppCore::IEvent::Type::REGION_CHANGE,
+    [APP_EVENT_SUSPENDED_STATE_CHANGED] =
+        IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE,
 };
 
 class AppContext : public AppCoreBase {
@@ -109,8 +111,10 @@ class AppContext : public AppCoreBase {
     AppCoreBase::OnReceive(type, b);
 
     if (type == AUL_TERMINATE_BGAPP) {
+      // LCOV_EXCL_START
       Exit();
       return 0;
+      // LCOV_EXCL_STOP
     }
 
     return 0;
@@ -134,7 +138,7 @@ class AppContext : public AppCoreBase {
 
     std::string job_id = b.GetString(AUL_K_JOB_ID);
     if (!job_id.empty()) {
-      _D("[__JOB__] Job(%s)", job_id.c_str());
+      _D("[__JOB__] Job(%s)", job_id.c_str());  // LCOV_EXCL_LINE
       return 0;
     }
 
@@ -162,7 +166,7 @@ class AppContext : public AppCoreBase {
 
   void OnLoopInit(int argc, char** argv) override {
     if (method_.init) {
-      method_.init(argc, argv, data_);
+      method_.init(argc, argv, data_);  // LCOV_EXCL_LINE
     } else {
       _W("ecore_init");
       ecore_init();
@@ -171,7 +175,7 @@ class AppContext : public AppCoreBase {
 
   void OnLoopFinish() override {
     if (method_.fini) {
-      method_.fini();
+      method_.fini();  // LCOV_EXCL_LINE
     } else {
       _W("ecore_shutdown");
       ecore_shutdown();
@@ -180,7 +184,7 @@ class AppContext : public AppCoreBase {
 
   void OnLoopRun() override {
     if (method_.run)
-      method_.run(data_);
+      method_.run(data_);  // LCOV_EXCL_LINE
     else
       ecore_main_loop_begin();
   }
@@ -188,7 +192,7 @@ class AppContext : public AppCoreBase {
   void OnLoopExit() override {
     SetAppState(APP_STATE_NOT_RUNNING);
     if (method_.exit) {
-      method_.exit(data_);
+      method_.exit(data_);  // LCOV_EXCL_LINE
     } else {
       ecore_main_loop_thread_safe_call_sync([](void* data) -> void* {
         ecore_main_loop_quit();
@@ -242,8 +246,10 @@ extern "C" EXPORT_API int service_app_main_ext(int argc, char** argv,
     }
     __context->Run(argc, argv);
   } catch(std::runtime_error& e) {
+    // LCOV_EXCL_START
     __context->SetAppState(AppContext::APP_STATE_NOT_RUNNING);
     return __on_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, nullptr);
+    // LCOV_EXCL_STOP
   }
 
   __job_manager.FinishAllJobs();
@@ -282,15 +288,19 @@ extern "C" EXPORT_API int service_app_add_event_handler(
   auto* ae = new (std::nothrow) AppEvent(__app_event_converter[event_type],
       callback, user_data);
   if (!ae) {
+    // LCOV_EXCL_START
     return __on_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__,
         "failed to create handler");
+    // LCOV_EXCL_STOP
   }
 
   auto* h = new (std::nothrow) std::shared_ptr<AppEvent>(ae);
   if (!h) {
+    // LCOV_EXCL_START
     delete ae;
     return __on_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__,
         "failed to create handler");
+    // LCOV_EXCL_STOP
   }
 
   if (__context.get() &&
@@ -316,13 +326,15 @@ extern "C" EXPORT_API int service_app_remove_event_handler(
   if (type < IAppCore::IEvent::Type::LOW_MEMORY ||
       type > IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE ||
       type == IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED)
-    return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, nullptr);
+    return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, nullptr);  // LCOV_EXCL_LINE
 
   if (__context.get() &&
       __context->GetAppState() == AppContext::APP_STATE_RUNNING) {
     if (!__context->RemoveEvent(*eb)) {
+      // LCOV_EXCL_START
       return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__,
           "invalid raw handler");
+      // LCOV_EXCL_STOP
     }
   } else {
     __pending_app_events.remove(*eb);
@@ -350,8 +362,10 @@ extern "C" EXPORT_API service_app_job_h service_app_add_job_handler(
 
   auto* handle = new (std::nothrow) JobHandler(job_id, callback, user_data);
   if (handle == nullptr) {
+    // LCOV_EXCL_START
     _E("Out of memory");
     return nullptr;
+    // LCOV_EXCL_STOP
   }
 
   __job_manager.AddJobHandler(handle);
@@ -368,8 +382,10 @@ extern "C" EXPORT_API int service_app_remove_job_handler(
 
   auto* h = static_cast<JobHandler*>(handle);
   if (!__job_manager.ExistJobHandler(h)) {
+    // LCOV_EXCL_START
     _E("Invalid parameter");
     return APP_ERROR_INVALID_PARAMETER;
+    // LCOV_EXCL_STOP
   }
 
   __job_manager.RemoveJobHandler(h);
@@ -389,8 +405,10 @@ extern "C" EXPORT_API int service_app_job_raise(int job_status,
   auto job = std::make_shared<Job>(job_status, job_id,
       tizen_base::Bundle(job_data, true, true));
   if (job == nullptr) {
+    // LCOV_EXCL_START
     _E("Out of memory");
     return APP_ERROR_OUT_OF_MEMORY;
+    // LCOV_EXCL_STOP
   }
 
   __job_manager.Do(job);
@@ -404,7 +422,7 @@ extern "C" EXPORT_API int service_app_job_finished(const char* job_id) {
   }
 
   if (__job_manager.Finish(job_id) != 0)
-    return APP_ERROR_INVALID_CONTEXT;
+    return APP_ERROR_INVALID_CONTEXT;  // LCOV_EXCL_LINE
 
   return APP_ERROR_NONE;
 }
index 0934014..6610220 100644 (file)
@@ -19,7 +19,7 @@
 
 class ModuleMock {
  public:
-  virtual ~ModuleMock() {}
+  virtual ~ModuleMock() {}  // LCOV_EXCL_LINE
 };
 
 #endif  // MOCK_MODULE_MOCK_H_
index db223f1..f10bf0a 100644 (file)
@@ -35,15 +35,19 @@ class TestFixture : public ::testing::Test {
     mock_.reset();
   }
 
-  virtual void SetUp() {}
-  virtual void TearDown() {}
+  virtual void SetUp() {}  // LCOV_EXCL_LINE
+  virtual void TearDown() {}  // LCOV_EXCL_LINE
 
   template <typename T>
   static T& GetMock() {
     auto ptr = dynamic_cast<T*>(mock_.get());
-    if (!ptr)
+    if (!ptr) {
+      // LCOV_EXCL_START
       throw std::invalid_argument("The test does not provide mock of \"" +
           std::string(typeid(T).name()) + "\"");
+      // LCOV_EXCL_STOP
+    }
+
     return *ptr;
   }
 
index 26ec2a9..baaa5e4 100644 (file)
@@ -23,12 +23,14 @@ class ServiceApp : public tizen_appfw::ServiceAppBase {
  public:
   ServiceApp() {}
 
+  // LCOV_EXCL_START
   bool OnCreate() override {
     return true;
   }
 
   void OnTerminate() override {}
   void OnAppControl(const tizen_appfw::ReceivedAppControl& ctrl) override {}
+  // LCOV_EXCL_STOP
 };
 
 }  // namespace
@@ -38,4 +40,4 @@ TEST(ServiceAppCppTest, Run_InvalidParameter) {
 
   int ret = app.Run(0, nullptr);
   EXPECT_EQ(ret, APP_ERROR_INVALID_PARAMETER);
-}
\ No newline at end of file
+}
index 5785ed8..eca8647 100644 (file)
@@ -88,6 +88,7 @@ extern "C" int aul_job_scheduler_update_job_status(const char* job_id,
   return 0;
 }
 
+// LCOV_EXCL_START
 bool __service_app_create_cb(void* user_data) {
   return true;
 }
@@ -97,6 +98,7 @@ void __service_app_terminate_cb(void* user_data) {
 
 void __service_app_control_cb(app_control_h app_control, void* user_data) {
 }
+// LCOV_EXCL_STOP
 
 TEST_F(ServiceAppTest, Basic) {
   // test service_app_main
@@ -230,18 +232,80 @@ TEST_F(ServiceAppTest, EventHandlers) {
   EXPECT_THAT(ret, testing::Eq(APP_ERROR_NONE));
   EXPECT_THAT(calledCnt, testing::Eq(0));
 
-  //appcore_base_raise_event(&calledCnt, APPCORE_BASE_EVENT_LOW_MEMORY);
-
-  //EXPECT_THAT(calledCnt, testing::Eq(1));
-
   ret = service_app_remove_event_handler(nullptr);
   EXPECT_THAT(ret, testing::Eq(APP_ERROR_INVALID_PARAMETER));
 
   ret = service_app_remove_event_handler(handle);
   EXPECT_THAT(ret, testing::Eq(APP_ERROR_NONE));
+}
+
+TEST_F(ServiceAppTest, BasicWithoutRestart) {
+  int ret = 0;
+  service_app_lifecycle_callback_s callback = {
+    .create = __service_app_create_cb,
+    .terminate = __service_app_terminate_cb,
+    .app_control = __service_app_control_cb
+  };
+
+  tizen_base::Bundle b;
+  b.Add("dummy", "dummy");
+
+  char** argv;
+  int argc = bundle_export_to_argv(b.GetHandle(), &argv);
+  std::unique_ptr<char**, std::function<void(char***)>> ptr(&argv,
+      [argc](char*** ptr) {
+    bundle_free_exported_argv(argc, ptr);
+  });
+
+  ASSERT_GT(argc, 0);
+  using testing::_;
+
+  ret = service_app_main(0, nullptr, &callback, nullptr);
+  EXPECT_THAT(ret, testing::Eq(APP_ERROR_INVALID_PARAMETER));
+
+  callback.create = nullptr;
+  ret = service_app_main(argc, argv, &callback, nullptr);
+  EXPECT_THAT(ret, testing::Eq(APP_ERROR_INVALID_PARAMETER));
+
+  EXPECT_CALL(GetMock<AppCoreMock>(), Run(_, _)).Times(1);
+
+  std::unique_lock<std::mutex> lock(mutex_);
+  EXPECT_CALL(GetMock<AppCoreMock>(), OnLoopRun())
+    .WillOnce(testing::Invoke([&]() {
+      LoopRun();
+    }));
+
+  std::thread t([&]() {
+      {
+        std::unique_lock<std::mutex> t_lock(mutex_);
+        GSource* source = g_timeout_source_new(100);
+        g_source_set_callback(source, [](gpointer user_data) {
+              auto* h = static_cast<ServiceAppTest*>(user_data);
+              std::unique_lock<std::mutex> l(h->mutex_);
+              h->started_ = true;
+              h->cond_.notify_one();
+              return G_SOURCE_REMOVE;
+            }, this, nullptr);
+        g_source_attach(source, context_);
+        g_source_unref(source);
+      }
 
-  //appcore_base_raise_event(&calledCnt, APPCORE_BASE_EVENT_LOW_MEMORY);
-  //EXPECT_THAT(calledCnt, testing::Eq(1));
+      callback.create = __service_app_create_cb;
+      service_app_main(argc, argv, &callback, this);
+  });
+
+  cond_.wait(lock, [&] { return started_; });
+  ret = service_app_main(argc, argv, &callback, this);
+  EXPECT_THAT(ret, testing::Eq(APP_ERROR_ALREADY_RUNNING));
+
+  // test service_app_exit
+  EXPECT_CALL(GetMock<AppCoreMock>(), Exit()).Times(1);
+  EXPECT_CALL(GetMock<AppCoreMock>(), OnLoopExit())
+    .WillOnce(testing::Invoke([&]() {
+      LoopQuit();
+      t.join();
+    }));
+  service_app_exit_without_restart();
 }
 
 }  // namespace appcore_agent
@@ -251,15 +315,19 @@ int main(int argc, char* argv[]) {
   try {
     ::testing::InitGoogleTest(&argc, argv);
   } catch(...) {
+    // LCOV_EXCL_START
     std::cout << "Exception occured" << std::endl;
     return 1;
+    // LCOV_EXCL_STOP
   }
 
   try {
     return RUN_ALL_TESTS();
   } catch(const ::testing::internal::GoogleTestFailureException& e) {
+    // LCOV_EXCL_START
     std::cout << "GoogleTestFailureException occured:" << e.what() << std::endl;
     ret = 1;
+    // LCOV_EXCL_STOP
   }
 
   return ret;