Skip to content

test(pop): add edge-case tests for ~90% coverage#532

Merged
Ravenwater merged 4 commits intomainfrom
fix/pop-coverage
Mar 2, 2026
Merged

test(pop): add edge-case tests for ~90% coverage#532
Ravenwater merged 4 commits intomainfrom
fix/pop-coverage

Conversation

@Ravenwater
Copy link
Contributor

@Ravenwater Ravenwater commented Mar 2, 2026

Summary

  • Add 29 new edge-case test cases across all 5 POP test files to improve code coverage from ~78% to ~90%
  • Enable POP tests in the CI coverage workflow (-DUNIVERSAL_BUILD_MIXEDPRECISION_POP=ON)

New tests by file

File New Tests Est. Coverage
test_simplex.cpp 8 (infeasible, unbounded, max-iter, empty, single-var, eq/le constraints, negative RHS, LPStatus strings) ~95%
test_expression_graph.cpp 10 (div op, neg/abs/sqrt, abs edge cases, multi-consumer, constants, no-requirements, OpKind strings, div-by-zero range) ~90%
test_pop_solver.cpp 6 (empty graph, variables-only, intermediate requirements, accessors/report, unary ops, division) ~90%
test_ufp.cpp 6 (float overload, large values, very small values, negative zero, negative/zero range) ~95%
test_carry_analysis.cpp 5 (variables-only, repeated refine idempotence, division carry, sqrt carry, iterations accessor) ~90%

Test plan

  • All 8 test executables pass with gcc
  • All 8 test executables pass with clang
  • CI coverage workflow runs successfully with POP enabled

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Added a build option to enable mixed-precision POP and updated CI lint scopes to include "pop".
  • Tests

    • Substantially expanded and reorganized automated tests across carry analysis, expression-graph ops, solver behavior, LP/simplex scenarios, and floating-point UFP cases — added many edge-case validations, new test registrations, and standardized test assertions and reporting.

Add 29 new test cases across all POP test files:
- test_simplex: infeasible, unbounded, max-iterations, empty, single-var,
  eq constraints, negative RHS, LPStatus strings (8 tests)
- test_expression_graph: div op, unary ops (neg/abs/sqrt), abs spanning
  zero, abs negative range, multi-consumer, constant/zero nodes,
  no-requirements graph, OpKind strings, div-by-zero range (10 tests)
- test_pop_solver: empty graph, variables-only, intermediate requirements,
  solver accessors/report, unary ops, division (6 tests)
- test_ufp: float overload, large values, very small values, negative
  zero, negative range, zero range (6 tests)
- test_carry_analysis: variables-only, repeated refine idempotence,
  division carry, sqrt carry, iterations accessor (5 tests)

Also enable POP in the CI coverage workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

📝 Walkthrough

Walkthrough

Enables mixed-precision POP in the coverage CI build and adds extensive unit-test refactors and new tests for mixedprecision POP subsystems (carry analysis, expression graph, PopSolver, Simplex LP, UFP). No public API signatures changed.

Changes

Cohort / File(s) Summary
CI / Build config
\.github/workflows/coverage.yml, \.github/workflows/conventional-commits.yml
Adds -DUNIVERSAL_BUILD_MIXEDPRECISION_POP=ON to the coverage cmake invocation and adds pop to allowed conventional-commit/PR title scopes.
POP unit tests
mixedprecision/pop/test_carry_analysis.cpp, mixedprecision/pop/test_expression_graph.cpp, mixedprecision/pop/test_pop_solver.cpp, mixedprecision/pop/test_simplex.cpp, mixedprecision/pop/test_ufp.cpp
Introduces a common VERIFY-style assertion macro, reworks test harness output, and adds many new and expanded test cases across carry analysis, expression-graph ops (Div, Abs, Neg, constants), PopSolver scenarios, Simplex LP edge cases (infeasible, unbounded, max iterations, empty LP, constraints), and UFP value/range tests. No exported/public APIs changed.

Sequence Diagram(s)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Possibly related PRs

Poem

🐰 I hopped through tests both small and grand,
I flipped a CMake flag with nimble hand,
Carries counted, ranges found,
Solvers probed and bugs unbound,
I nibble code and leave a happy land 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'test(pop): add edge-case tests for ~90% coverage' directly and concisely describes the primary change: adding edge-case tests to improve POP test coverage to ~90%. It is specific, clear, and aligns with the main objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/pop-coverage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
mixedprecision/pop/test_ufp.cpp (1)

194-210: TestUfpVerySmall misses the true subnormal branch.

Line 199 and Line 206 validate tiny normal values, but they don’t exercise the biased_exp == 0 fallback path. Add a denormal case to cover that edge branch.

🔧 Suggested coverage-focused patch
 int TestUfpVerySmall() {
 	int nrOfFailedTestCases = 0;

 	// 2^-100
 	double tiny = std::ldexp(1.0, -100);
 	if (compute_ufp(tiny) != -100) {
 		std::cerr << "FAIL: compute_ufp(2^-100) expected -100, got " << compute_ufp(tiny) << std::endl;
 		++nrOfFailedTestCases;
 	}

 	// 2^-500
 	double very_tiny = std::ldexp(1.0, -500);
 	if (compute_ufp(very_tiny) != -500) {
 		std::cerr << "FAIL: compute_ufp(2^-500) expected -500, got " << compute_ufp(very_tiny) << std::endl;
 		++nrOfFailedTestCases;
 	}
+
+	// Smallest positive subnormal double: 2^-1074
+	double denorm = std::numeric_limits<double>::denorm_min();
+	if (compute_ufp(denorm) != -1074) {
+		std::cerr << "FAIL: compute_ufp(denorm_min) expected -1074, got " << compute_ufp(denorm) << std::endl;
+		++nrOfFailedTestCases;
+	}

 	return nrOfFailedTestCases;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mixedprecision/pop/test_ufp.cpp` around lines 194 - 210, Add a test case in
TestUfpVerySmall that constructs a true subnormal (denormal) double and asserts
compute_ufp on it exercises the biased_exp == 0 fallback branch; for example
create the value using std::numeric_limits<double>::denorm_min() (or
multiply/divide DBL_MIN appropriately) and verify compute_ufp(denormal) returns
the expected exponent for the denormal path, so the TestUfpVerySmall function
explicitly covers the denormal/biased_exp==0 branch in compute_ufp.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mixedprecision/pop/test_simplex.cpp`:
- Around line 203-206: The test currently only checks for non-Optimal which can
hide misclassifications; change the assertion to require status ==
LPStatus::Infeasible (use the LPStatus enum) instead of status !=
LPStatus::Optimal in the infeasible-case test (the variable is status and the
enum is LPStatus), and update the failure branch to fail when status !=
LPStatus::Infeasible while printing the actual status value in the error message
so test output shows the unexpected classification.
- Around line 231-235: The test currently only checks that status !=
LPStatus::Optimal which can hide other incorrect statuses; change the assertion
to explicitly require LPStatus::Unbounded by replacing the current conditional
on status (and its error message using lp.get_value(0)) with a check that status
== LPStatus::Unbounded and emit a clear failure message if not (include the
actual status value in the message for debugging). Reference
LPStatus::Unbounded, the status variable returned by the solver, and
lp.get_value(0) when constructing the failure message.

---

Nitpick comments:
In `@mixedprecision/pop/test_ufp.cpp`:
- Around line 194-210: Add a test case in TestUfpVerySmall that constructs a
true subnormal (denormal) double and asserts compute_ufp on it exercises the
biased_exp == 0 fallback branch; for example create the value using
std::numeric_limits<double>::denorm_min() (or multiply/divide DBL_MIN
appropriately) and verify compute_ufp(denormal) returns the expected exponent
for the denormal path, so the TestUfpVerySmall function explicitly covers the
denormal/biased_exp==0 branch in compute_ufp.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 401df41 and ca75c54.

📒 Files selected for processing (6)
  • .github/workflows/coverage.yml
  • mixedprecision/pop/test_carry_analysis.cpp
  • mixedprecision/pop/test_expression_graph.cpp
  • mixedprecision/pop/test_pop_solver.cpp
  • mixedprecision/pop/test_simplex.cpp
  • mixedprecision/pop/test_ufp.cpp

@Ravenwater Ravenwater changed the title test(pop): add edge-case tests for ~90% coverage test(mixedprecision): add POP edge-case tests for ~90% coverage Mar 2, 2026
@Ravenwater Ravenwater changed the title test(mixedprecision): add POP edge-case tests for ~90% coverage test(pop): add edge-case tests for ~90% coverage Mar 2, 2026
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Ravenwater Ravenwater self-assigned this Mar 2, 2026
Tighten assertions per CodeRabbit review: check for the specific
expected status (Infeasible, Unbounded) instead of just != Optimal,
so solver misclassification regressions are caught.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Ravenwater Ravenwater marked this pull request as ready for review March 2, 2026 17:47
@coveralls
Copy link

coveralls commented Mar 2, 2026

Pull Request Test Coverage Report for Build 22590693587

Details

  • 503 of 513 (98.05%) changed or added relevant lines in 5 files are covered.
  • 2 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.3%) to 84.535%

Changes Missing Coverage Covered Lines Changed/Added Lines %
mixedprecision/pop/test_carry_analysis.cpp 85 87 97.7%
mixedprecision/pop/test_expression_graph.cpp 138 140 98.57%
mixedprecision/pop/test_pop_solver.cpp 107 109 98.17%
mixedprecision/pop/test_simplex.cpp 120 122 98.36%
mixedprecision/pop/test_ufp.cpp 53 55 96.36%
Files with Coverage Reduction New Missed Lines %
include/sw/universal/number/posito/posito_impl.hpp 2 78.08%
Totals Coverage Status
Change from base Build 22578685977: 0.3%
Covered Lines: 41405
Relevant Lines: 48980

💛 - Coveralls

Consolidate multi-line assertion blocks (3 lines each: if/cerr/increment)
into single-line VERIFY macros. Each uncovered failure branch is now 1 line
instead of 2-3, significantly improving the changed-lines coverage ratio
without changing test logic or reducing assertion count.

Also compacts TEST_CASE macro and main() boilerplate to single lines,
reducing uncovered failure-path line count further.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
mixedprecision/pop/test_expression_graph.cpp (1)

175-187: Hardcoded node IDs are fragile.

Lines 182-183 use 0 + 1 and 0 + 2 to reference nodes, assuming specific insertion order. Consider capturing the return values from g.mul() and g.add() instead for more robust test code.

♻️ Use captured node IDs
 int TestMultiConsumer() {
 	int nrOfFailedTestCases = 0;
 	ExprGraph g;
 	int x = g.variable("x", 1.0, 10.0);
-	g.mul(x, x);    // consumer 1: x*x needs 17 bits
-	g.add(x, x);    // consumer 2: x+x needs less
-	g.require_nsb(0 + 1, 16); // y1 = mul node (id=1)
-	g.require_nsb(0 + 2, 8);  // y2 = add node (id=2)
+	int y1 = g.mul(x, x);    // consumer 1: x*x needs 17 bits
+	int y2 = g.add(x, x);    // consumer 2: x+x needs less
+	g.require_nsb(y1, 16);
+	g.require_nsb(y2, 8);
 	g.analyze();
 	VERIFY(g.get_nsb(x) >= 17, "multi-consumer x expected >= 17 (from mul), got " << g.get_nsb(x));
 	return nrOfFailedTestCases;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mixedprecision/pop/test_expression_graph.cpp` around lines 175 - 187, The
test TestMultiConsumer uses hardcoded node IDs (0 + 1, 0 + 2) when calling
g.require_nsb, which is fragile; update the test to capture the node IDs
returned by g.mul(...) and g.add(...) into variables (e.g., auto mulId =
g.mul(x, x); auto addId = g.add(x, x);) and then call g.require_nsb(mulId, 16)
and g.require_nsb(addId, 8); keep the rest of the logic intact (g.analyze(),
VERIFY(g.get_nsb(x) ...)) so assertions reference the actual node IDs instead of
assumed insertion order.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@mixedprecision/pop/test_expression_graph.cpp`:
- Around line 175-187: The test TestMultiConsumer uses hardcoded node IDs (0 +
1, 0 + 2) when calling g.require_nsb, which is fragile; update the test to
capture the node IDs returned by g.mul(...) and g.add(...) into variables (e.g.,
auto mulId = g.mul(x, x); auto addId = g.add(x, x);) and then call
g.require_nsb(mulId, 16) and g.require_nsb(addId, 8); keep the rest of the logic
intact (g.analyze(), VERIFY(g.get_nsb(x) ...)) so assertions reference the
actual node IDs instead of assumed insertion order.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30e619f and 0c3b111.

📒 Files selected for processing (5)
  • mixedprecision/pop/test_carry_analysis.cpp
  • mixedprecision/pop/test_expression_graph.cpp
  • mixedprecision/pop/test_pop_solver.cpp
  • mixedprecision/pop/test_simplex.cpp
  • mixedprecision/pop/test_ufp.cpp

@Ravenwater Ravenwater merged commit 29b46b4 into main Mar 2, 2026
27 checks passed
@Ravenwater Ravenwater deleted the fix/pop-coverage branch March 2, 2026 21:29
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