From 7017213975f84b05e0baaf562521cbdebc88b57d Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 28 Aug 2023 18:16:51 +0900 Subject: [PATCH] Improve code coverage - Adds unit test - Excludes some lines Change-Id: Ice9f4b2605ac517f2c0defca4c6f622aeef982e6 Signed-off-by: Hwankyu Jhun --- include/service_app.hpp | 4 ++ src/job-manager.cc | 14 +++++++ src/job.cc | 10 ++++- src/service_app_main.cc | 56 +++++++++++++++++---------- unittests/mock/module_mock.h | 2 +- unittests/mock/test_fixture.h | 10 +++-- unittests/service_app_cpp_test.cc | 4 +- unittests/service_app_test.cc | 80 ++++++++++++++++++++++++++++++++++++--- 8 files changed, 149 insertions(+), 31 deletions(-) diff --git a/include/service_app.hpp b/include/service_app.hpp index e421364..1c59034 100644 --- a/include/service_app.hpp +++ b/include/service_app.hpp @@ -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(user_data); b->OnAppControl(ReceivedAppControl(app_control)); + // LCOV_EXCL_STOP } }; diff --git a/src/job-manager.cc b/src/job-manager.cc index 3293c11..82bc88a 100644 --- a/src/job-manager.cc +++ b/src/job-manager.cc @@ -57,8 +57,10 @@ bool JobManager::ExistJobHandler(JobHandler* handler) { void JobManager::Do(std::shared_ptr 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) { 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()); diff --git a/src/job.cc b/src/job.cc index 7af489a..0758b9f 100644 --- a/src/job.cc +++ b/src/job.cc @@ -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(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(data); diff --git a/src/service_app_main.cc b/src/service_app_main.cc index 65ed36c..42ebd46 100644 --- a/src/service_app_main.cc +++ b/src/service_app_main.cc @@ -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(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(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_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; } diff --git a/unittests/mock/module_mock.h b/unittests/mock/module_mock.h index 0934014..6610220 100644 --- a/unittests/mock/module_mock.h +++ b/unittests/mock/module_mock.h @@ -19,7 +19,7 @@ class ModuleMock { public: - virtual ~ModuleMock() {} + virtual ~ModuleMock() {} // LCOV_EXCL_LINE }; #endif // MOCK_MODULE_MOCK_H_ diff --git a/unittests/mock/test_fixture.h b/unittests/mock/test_fixture.h index db223f1..f10bf0a 100644 --- a/unittests/mock/test_fixture.h +++ b/unittests/mock/test_fixture.h @@ -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 static T& GetMock() { auto ptr = dynamic_cast(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; } diff --git a/unittests/service_app_cpp_test.cc b/unittests/service_app_cpp_test.cc index 26ec2a9..baaa5e4 100644 --- a/unittests/service_app_cpp_test.cc +++ b/unittests/service_app_cpp_test.cc @@ -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 +} diff --git a/unittests/service_app_test.cc b/unittests/service_app_test.cc index 5785ed8..eca8647 100644 --- a/unittests/service_app_test.cc +++ b/unittests/service_app_test.cc @@ -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> 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(), Run(_, _)).Times(1); + + std::unique_lock lock(mutex_); + EXPECT_CALL(GetMock(), OnLoopRun()) + .WillOnce(testing::Invoke([&]() { + LoopRun(); + })); + + std::thread t([&]() { + { + std::unique_lock t_lock(mutex_); + GSource* source = g_timeout_source_new(100); + g_source_set_callback(source, [](gpointer user_data) { + auto* h = static_cast(user_data); + std::unique_lock 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(), Exit()).Times(1); + EXPECT_CALL(GetMock(), 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; -- 2.7.4