Skip to content

more test coverage - #6

Merged
aaronbrethorst merged 4 commits into
developfrom
di-seam
Apr 23, 2026
Merged

more test coverage#6
aaronbrethorst merged 4 commits into
developfrom
di-seam

Conversation

@aaronbrethorst

@aaronbrethorst aaronbrethorst commented Apr 23, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Documentation

    • Refactored README with updated branding, modernized formatting, and clarified build, setup, and test execution instructions.
  • Bug Fixes

    • Strengthened stability with enhanced null-safety handling in holding time generation and control stop configuration management.

Adds real-Core behavior coverage for two high-value targets that the
existing unit tests leave under-covered:

- MatchProcessorBehaviorTest (new): locks in the contract of the single
  public entry point generateResultsOfMatch — unpredictable short-circuit,
  predictable path populates VehicleState predictions, and Prediction rows
  reach the DB via the async DataDbLogger.

- AvlProcessorBehaviorTest: adds the TRIP_ID assignment path (existing
  suite only covered BLOCK_ID), cacheAvlReportWithoutProcessing,
  makeVehicleUnpredictable's unwind on a predictable vehicle, and the
  sched-based-preds guard against updating lastRegularReportProcessed.
  Introduces pinClockToHappyPathAnchor so multiple happy-path tests can
  coexist without tripping setLastAvlReport's "only store newer" guard
  under JUnit's nondeterministic ordering.

No production code changes.
An operator who enables the default holding-time generator via
transitclock.core.holdingTimeGeneratorClass but does not configure
transitclock.holding.controlStops would previously hit a NullPointerException
on the first arrival event: StringListConfigValue.getValue() returns null
when unset, and getControlPointStops iterated that null without a guard.
isControlStop unconditionally calls getControlPointStops, so the NPE is
reachable from every public generateHoldingTime entry point.

Treats an unset control-stop list as "no control stops" — the feature
correctly becomes a no-op in that case, matching the safety contract.

Surfaced while adding HoldingTimeGeneratorBehaviorTest, which locks in
three invariants against real Core:
- departure events never produce a holding time
- arrivals at non-control stops never produce a holding time
- getControlPointStops() returns an empty (non-null) list by default
Convert the old <b>-tag headers to markdown, update the project
description to reflect the current fork lineage, and inline the
`mvn test` / QuickStart MDEP-187 explanation previously delegated
to CLAUDE.md.
- Warn once at HoldingTimeGeneratorDefaultImpl construction when
  transitclock.holding.controlStops is unset so operators see the
  feature is inactive instead of silently producing zero holding times.
- Drop the now-redundant null-guard in isControlStop and repair the
  sibling NPE in predictionsToLongArray that dereferenced predictions
  before its null check.
- Assert Prediction rows stay out of the DB on the unpredictable-vehicle
  short-circuit test so the guard regression would be caught if the
  predictable check were ever moved.
- Trim block comments in the pipeline tests that restated method names
  or assertion messages; keep the monotonic-clock, feed-up-monitoring,
  and clear-predictions-before-reinvoke rationales.
@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR updates documentation in README.md, improves null-safety in HoldingTimeGeneratorDefaultImpl with defensive checks, and significantly expands the pipeline behavior test suite with new test classes (HoldingTimeGeneratorBehaviorTest, MatchProcessorBehaviorTest) and refactored AvlProcessorBehaviorTest with centralized test helpers.

Changes

Cohort / File(s) Summary
Documentation
README.md
Updates title, badges, and intro content; modernizes section headers to Markdown; adjusts test instructions with clarification on mvn test failures in full reactor and alternative build commands.
Core Implementation
transitclock/src/main/java/org/transitclock/core/holdingmethod/HoldingTimeGeneratorDefaultImpl.java
Adds public constructor with configuration validation warning; introduces null-safe handling in getControlPointStops(), isControlStop(), and predictionsToLongArray() methods to prevent NullPointerExceptions.
Test Suite Enhancements
transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/AvlProcessorBehaviorTest.java, HoldingTimeGeneratorBehaviorTest.java, MatchProcessorBehaviorTest.java
Refactors AvlProcessorBehaviorTest with new helpers (pinClockToHappyPathAnchor(), reportAtFirstStop()) and adds coverage for trip-id predictability, report caching, vehicle unpredictability, and schedule-based predictions; introduces HoldingTimeGeneratorBehaviorTest to validate null-handling and control-stop behavior; adds MatchProcessorBehaviorTest for integration testing of prediction generation and database persistence.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

  • Pipeline behavior tests: predictions, arrivals/departures, matching, block assignment #4 — Adds and expands pipeline behavior tests for the matching/prediction pipeline with MatchProcessor and VehicleState matching assertions, directly complementary to the MatchProcessorBehaviorTest additions.
  • Pipeline tests #3 — Overlaps significantly with this PR in expanding the pipeline test suite (AvlProcessorBehaviorTest, HoldingTimeGeneratorBehaviorTest), README guidance, and build profile changes for opt-in pipeline test execution.
  • Expand core-engine unit test coverage (Tiers 1–4) #2 — Modifies HoldingTimeGeneratorDefaultImpl implementation and adds corresponding unit tests, directly related to the HoldingTimeGeneratorDefaultImpl null-safety improvements and new HoldingTimeGeneratorBehaviorTest in this PR.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'more test coverage' is vague and generic. While the PR does add test coverage, it fails to convey what specific functionality is being tested or what the actual code changes are beyond tests (README updates, holding method changes). Consider a more descriptive title that captures the main changes, such as 'Add holding time generator and match processor tests with README and implementation updates' or 'Improve test coverage for holding time and match processor behavior'
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch di-seam

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
README.md (1)

8-60: Consider standardizing heading style for consistency.

The README mixes setext-style headings (underlined with ====) and atx-style headings (##). While both are valid Markdown, using a consistent style throughout improves readability and passes linter checks.

♻️ Proposed fix: Convert all section headings to atx style
-====
+# TheTransitClock
-====

-## About this Repo
+## About this Repo

-## Build
+## Build

-## Setup
+## Setup

-## Running tests
+## Running tests

-### Code coverage
+### Code coverage
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 8 - 60, The README mixes setext-style underlined
headings and atx-style (##) headings; standardize by converting all setext
headings (e.g., "About this Repo", "Build", "Setup", "Running tests", "Code
coverage") to consistent atx-style headings (use ## for top-level sections and
###/#### for subsections like "Pipeline tests" and "Integration tests"),
updating each heading line to start with the appropriate number of # characters
and removing the underline lines so all headings follow the same atx format.
transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/MatchProcessorBehaviorTest.java (2)

72-79: Consider migrating from deprecated Hibernate Criteria API.

session.createCriteria() is deprecated in Hibernate 5+. While functional for tests, consider using JPA CriteriaBuilder or HQL for better long-term compatibility.

♻️ Optional: Use HQL instead
 `@SuppressWarnings`("unchecked")
 private static List<Prediction> queryPredictionsForVehicle(String vehicleId) {
     try (Session session = HibernateUtils.getSession(AgencyConfig.getAgencyId())) {
-        return session.createCriteria(Prediction.class)
-                .add(Restrictions.eq("vehicleId", vehicleId))
-                .list();
+        return session.createQuery(
+                "FROM Prediction p WHERE p.vehicleId = :vehicleId", Prediction.class)
+                .setParameter("vehicleId", vehicleId)
+                .list();
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/MatchProcessorBehaviorTest.java`
around lines 72 - 79, The test helper method queryPredictionsForVehicle uses the
deprecated session.createCriteria API; replace it with a non-deprecated query
mechanism (e.g., HQL or JPA CriteriaBuilder) inside the same try-with-resources
block: build a typed query against the Prediction entity (for example using
session.createQuery("from Prediction where vehicleId = :vid", Prediction.class)
or equivalent CriteriaBuilder usage), bind the vehicleId parameter, execute the
query to get the List<Prediction>, and remove the Restrictions.eq call; keep the
method signature and HibernateUtils.getSession(AgencyConfig.getAgencyId()) usage
intact.

81-96: Polling approach is functional; Awaitility could simplify.

The manual polling loop with timeout is correct and handles interruption properly. If the project uses Awaitility elsewhere, it would provide cleaner async assertions. Otherwise, this is fine as-is.

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

In
`@transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/MatchProcessorBehaviorTest.java`
around lines 81 - 96, The manual polling loop in waitForDbRows (using
DB_FLUSH_TIMEOUT_MS and DB_POLL_INTERVAL_MS, calling fetcher.get()) can be
replaced with Awaitility to simplify async waiting: use
Awaitility.await().atMost(Duration.ofMillis(DB_FLUSH_TIMEOUT_MS)).pollInterval(Duration.ofMillis(DB_POLL_INTERVAL_MS)).untilAsserted(()
-> assertThat(fetcher.get().size()).isGreaterThanOrEqualTo(minRows)); update
imports accordingly and remove the Thread.sleep/InterruptedException handling
inside waitForDbRows; keep the method signature and semantics (return the final
fetcher.get() result after the await) so callers (tests) behave the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Line 12: Update the README sentence to hyphenate the compound adjective:
change the phrase "cost effective system" to "cost-effective system" in the line
containing "By providing a complete open-source system, agencies can have a cost
effective system and have full ownership of it." so the compound adjective is
grammatically correct.

---

Nitpick comments:
In `@README.md`:
- Around line 8-60: The README mixes setext-style underlined headings and
atx-style (##) headings; standardize by converting all setext headings (e.g.,
"About this Repo", "Build", "Setup", "Running tests", "Code coverage") to
consistent atx-style headings (use ## for top-level sections and ###/#### for
subsections like "Pipeline tests" and "Integration tests"), updating each
heading line to start with the appropriate number of # characters and removing
the underline lines so all headings follow the same atx format.

In
`@transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/MatchProcessorBehaviorTest.java`:
- Around line 72-79: The test helper method queryPredictionsForVehicle uses the
deprecated session.createCriteria API; replace it with a non-deprecated query
mechanism (e.g., HQL or JPA CriteriaBuilder) inside the same try-with-resources
block: build a typed query against the Prediction entity (for example using
session.createQuery("from Prediction where vehicleId = :vid", Prediction.class)
or equivalent CriteriaBuilder usage), bind the vehicleId parameter, execute the
query to get the List<Prediction>, and remove the Restrictions.eq call; keep the
method signature and HibernateUtils.getSession(AgencyConfig.getAgencyId()) usage
intact.
- Around line 81-96: The manual polling loop in waitForDbRows (using
DB_FLUSH_TIMEOUT_MS and DB_POLL_INTERVAL_MS, calling fetcher.get()) can be
replaced with Awaitility to simplify async waiting: use
Awaitility.await().atMost(Duration.ofMillis(DB_FLUSH_TIMEOUT_MS)).pollInterval(Duration.ofMillis(DB_POLL_INTERVAL_MS)).untilAsserted(()
-> assertThat(fetcher.get().size()).isGreaterThanOrEqualTo(minRows)); update
imports accordingly and remove the Thread.sleep/InterruptedException handling
inside waitForDbRows; keep the method signature and semantics (return the final
fetcher.get() result after the await) so callers (tests) behave the same.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: eb11880e-960d-436a-b37f-58b34ef0065d

📥 Commits

Reviewing files that changed from the base of the PR and between 11df7bd and 0ce17ad.

📒 Files selected for processing (5)
  • README.md
  • transitclock/src/main/java/org/transitclock/core/holdingmethod/HoldingTimeGeneratorDefaultImpl.java
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/AvlProcessorBehaviorTest.java
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/HoldingTimeGeneratorBehaviorTest.java
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/MatchProcessorBehaviorTest.java

Comment thread README.md

The complete core Java software for the Transitime real-time transit information project. The purpose of the software is to use any type of real-time GPS data to generate useful public transportation information, namely a GTFS-RT Trip Updates feed.

The system is for both letting passengers know the status of their vehicles and helping agencies more effectively manage their systems. By providing a complete open-source system, agencies can have a cost effective system and have full ownership of it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix grammar: hyphenate compound adjective.

The phrase "cost effective" should be hyphenated when used as a compound adjective before a noun.

📝 Proposed fix
-The system is for both letting passengers know the status of their vehicles and helping agencies more effectively manage their systems. By providing a complete open-source system, agencies can have a cost effective system and have full ownership of it. 
+The system is for both letting passengers know the status of their vehicles and helping agencies more effectively manage their systems. By providing a complete open-source system, agencies can have a cost-effective system and have full ownership of it. 
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The system is for both letting passengers know the status of their vehicles and helping agencies more effectively manage their systems. By providing a complete open-source system, agencies can have a cost effective system and have full ownership of it.
The system is for both letting passengers know the status of their vehicles and helping agencies more effectively manage their systems. By providing a complete open-source system, agencies can have a cost-effective system and have full ownership of it.
🧰 Tools
🪛 LanguageTool

[grammar] ~12-~12: Use a hyphen to join words.
Context: ...-source system, agencies can have a cost effective system and have full ownership...

(QB_NEW_EN_HYPHEN)

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

In `@README.md` at line 12, Update the README sentence to hyphenate the compound
adjective: change the phrase "cost effective system" to "cost-effective system"
in the line containing "By providing a complete open-source system, agencies can
have a cost effective system and have full ownership of it." so the compound
adjective is grammatically correct.

@aaronbrethorst
aaronbrethorst merged commit 08f6570 into develop Apr 23, 2026
3 checks passed
@aaronbrethorst
aaronbrethorst deleted the di-seam branch April 23, 2026 17: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.

1 participant