Skip to content

Improve test coverage to 100% functions / 88% lines; automate Windows coverage via OpenCppCoverage#5

Open
VipinKum4r wants to merge 9 commits intoamoldhamale1105:masterfrom
VipinKum4r:master
Open

Improve test coverage to 100% functions / 88% lines; automate Windows coverage via OpenCppCoverage#5
VipinKum4r wants to merge 9 commits intoamoldhamale1105:masterfrom
VipinKum4r:master

Conversation

@VipinKum4r
Copy link
Copy Markdown
Contributor

Improve coverage to 100% functions / ~89% lines and automate Windows coverage report

What this PR does

Builds on the test foundation from #4 to push coverage as high as the library's design permits, and adds automated coverage report generation on Windows via OpenCppCoverage.


Coverage results

Metric Before (#4) After (this PR)
Line coverage 67.5% (154 / 228) 88.6% (202 / 228)
Function coverage 84.8% (39 / 46) 100% (46 / 46) ✅

These are defensive/safety net code paths — their presence is valuable for production robustness even if they cannot be exercised by unit tests.


build.sh changes

The -t flag (test + coverage) now auto-detects the platform:

  • Linux / macOS — existing lcov + genhtml flow (unchanged)
  • Windows (MINGW / MSYS / Cygwin) — uses OpenCppCoverage, producing both an HTML report and a Cobertura XML report suitable for CI

If OpenCppCoverage is not on PATH, the script prints a clear install instruction (winget install OpenCppCoverage) and exits gracefully instead of failing the build.


.gitignore update

Added CoverageReport-*/ to ignore the timestamped report folders OpenCppCoverage generates in the working directory.

// =============================================================================
// Test 1: Direct class coverage (no event-loop lifecycle required)
// =============================================================================
TEST(EventLoopTest, DirectCoverage)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have more meaningful test case names, a good practice is <func_name>_test_scenario

Comment on lines +52 to +56
{
EventLoop::Event e("singleArgEvent");
EXPECT_EQ(e.getName(), "singleArgEvent");
EXPECT_EQ(e.getData(), nullptr);
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create separate test cases for each of these scenarios and use proper naming convention as commented above

Comment on lines +75 to +93
// the multiset to invoke EventCompare::operator() to maintain ordering.
{
EventSender sender;
auto now = std::chrono::system_clock::now();
EventLoop::Event* e1 = new EventLoop::Event("scheduled1");
EventLoop::Event* e2 = new EventLoop::Event("scheduled2");
sender.addScheduledEvent(e1, now + std::chrono::milliseconds(200));
// Earlier timestamp forces a comparison against e1 during insertion
sender.addScheduledEvent(e2, now + std::chrono::milliseconds(50));
EXPECT_FALSE(sender.eventScheduleEmpty());

// Drain the queue to avoid leaks
while (!sender.eventScheduleEmpty()) {
EventLoop::Event* evt = sender.nextEventSchedule().first;
delete evt;
sender.removeEventSchedule();
}
EXPECT_TRUE(sender.eventScheduleEmpty());
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a separate test case

Comment on lines +87 to +91
while (!sender.eventScheduleEmpty()) {
EventLoop::Event* evt = sender.nextEventSchedule().first;
delete evt;
sender.removeEventSchedule();
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this, create all events you need in test fixtureSetUp() and ensure memory deallocation in TearDown()

});
// ── Error paths: empty event name guards (before Run) ────────────────────
// Each call hits the `if (evtName.empty())` true branch, prints to stderr,
// and returns early – covering lines 49-50, 66-67, 75-76, 85-86 of EventLoop.cpp.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don't need to add all these coverage details in comments here, the coverage report should speak for itself.

Comment on lines +21 to +22
* - EventManager::start() and eventScheduler() catch blocks – only reachable if OS-level
* thread creation fails (resource exhaustion).
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be orchestrated via mock functions for thread creation that throw std::thread class exceptions.

* - EventManager::start() and eventScheduler() catch blocks – only reachable if OS-level
* thread creation fails (resource exhaustion).
* - EventManager destructor line 45 (stop()) – requires the loop to be alive at program
* exit, which conflicts with safe test teardown.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't get what you mean here by 'safe test teardown'
I think this should be testable if you simulate a sequence where program exits on a non-blocking event loop without calling EventLoop::Halt() in which case the EventManager destructor should detect m_shutdown as true and call stop()

Comment on lines +25 to +28
* - EventManager line 149 (direct eventLoop() BLOCK path) – the NON_BLOCK path on
* line 151 is exercised instead. Testing both modes in one binary is unsafe because
* the static EventManager singleton cannot be restarted after Halt() without joining
* the previous scheduler thread.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not? Have a separate test case for this at the end, call halt in another thread. This should be fairly easy. Nothing is unsafe in unit testing :)

* @file EventLoopBasicTest.cpp
* @brief Comprehensive unit tests targeting 100% function coverage and maximum line coverage.
*
* Coverage strategy:
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this description once you split into multiple test cases. Also I would suggest adding a comment above every test case instead at the top of the file here which would be easier to read.

@@ -1,58 +1,239 @@
/**
* @file EventLoopBasicTest.cpp
* @brief Comprehensive unit tests targeting 100% function coverage and maximum line coverage.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No coverage metric info here please, this will be available in the report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants