Skip to content

Pipeline behavior tests: predictions, arrivals/departures, matching, block assignment - #4

Merged
aaronbrethorst merged 2 commits into
developfrom
pipeline-tests-2
Apr 23, 2026
Merged

Pipeline behavior tests: predictions, arrivals/departures, matching, block assignment#4
aaronbrethorst merged 2 commits into
developfrom
pipeline-tests-2

Conversation

@aaronbrethorst

@aaronbrethorst aaronbrethorst commented Apr 23, 2026

Copy link
Copy Markdown
Member

Summary

Extends the pipeline-tests suite with four behavior test classes (24 new tests) that validate previously-unobserved outputs of the prediction pipeline. Pipeline suite now runs 35 tests total (up from 11).

Each class boots a real Core via CoreHarness against the WMATA 5A GTFS fixture and asserts on observable state after driving AVL reports through the matcher/generator stack.

  • PredictionGeneratorBehaviorTest (6 tests) — verifies PredictionGeneratorDefaultImpl populates PredictionDataCache and VehicleState.getPredictions() with the in-horizon stops of the current trip, carrying correct block/route/vehicle metadata and both arrival and departure variants.
  • ArrivalDepartureBehaviorTest (4 tests) — drives a vehicle through two stops on block SE-08's first trip and asserts StopArrivalDepartureCache records a departure at the origin and an arrival at the destination with correct identifying metadata.
  • BlockAssignerBehaviorTest (8 tests) — exercises BLOCK_ID / TRIP_ID / TRIP_SHORT_NAME / ROUTE_ID / UNSET assignments plus invalid-id negative cases, and covers the getRouteIdAssignment entry point.
  • MatchingBehaviorTest (6 tests) — inspects TemporalMatch content: at-stop indicator, stop path index, trip/block/route references, distance-to-segment under maxDistanceFromSegment, populated real-time schedule adherence, and projected-location proximity to the reported AVL point.

Infrastructure change

Adds transitclockPipelineTests/src/test/resources/ehcache.xml that shadows the main-classpath copy to redirect ehcache persistence from /usr/local/transitclock/cache (not writable under CI or most dev machines) to target/ehcache-pipeline-store. Needed the first time pipeline tests caused ArrivalDepartureGeneratorDefaultImpl.updateCache to initialize TripDataHistoryCache.

Rationale

AvlProcessorBehaviorTest only checks vehicle.isPredictable() — a coarse signal. Regressions where the matcher snaps to the wrong segment, predictions carry wrong metadata, or arrival/departure records are silently dropped would all leave that check green while breaking user-visible output. These new tests close those observability gaps by asserting on actual pipeline outputs (cache contents, match fields, record metadata).

Test plan

  • mvn -pl transitclockPipelineTests -am -P include-pipeline-tests test → 35/35 passing
  • mvn verify (default profile, no pipeline profile) → 580/580 passing, unaffected
  • All six test classes use per-class JVM forks via reuseForks=false, so adding classes doesn't risk cross-class singleton pollution

Summary by CodeRabbit

  • Tests
    • Added end-to-end behavior tests covering vehicle matching, block assignment, arrival/departure event generation, and prediction generation; validate vehicle state consistency, event metadata, match distances, and prediction timing/coverage.
  • Chores
    • Added a pipeline-test cache configuration to support local test persistence and cache behavior.

@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 41b6b6d8-3875-47e3-9e70-a5589c2f4cb7

📥 Commits

Reviewing files that changed from the base of the PR and between 9ea7225 and 8dd6757.

📒 Files selected for processing (2)
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/PredictionGeneratorBehaviorTest.java
  • transitclockPipelineTests/src/test/resources/ehcache.xml
✅ Files skipped from review due to trivial changes (2)
  • transitclockPipelineTests/src/test/resources/ehcache.xml
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/PredictionGeneratorBehaviorTest.java

📝 Walkthrough

Walkthrough

Adds four pipeline-level integration test suites for matching, block assignment, arrival/departure event generation, and prediction generation, plus an Ehcache v3 test configuration used by those tests.

Changes

Cohort / File(s) Summary
Pipeline Behavior Tests
transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/ArrivalDepartureBehaviorTest.java, transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/BlockAssignerBehaviorTest.java, transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/MatchingBehaviorTest.java, transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/PredictionGeneratorBehaviorTest.java
Adds four JUnit test classes that exercise CoreHarness-driven pipeline flows: matching (at-stop detection, trip/block/route linking, distance checks), block assignment resolution, arrival/departure event generation and caching, and prediction generation/persistence and metadata/time validation.
Test Cache Configuration
transitclockPipelineTests/src/test/resources/ehcache.xml
Adds Ehcache v3 test config with local persistence (target/ehcache-pipeline-store), disk pool, and multiple caches used by the pipeline tests (typed key/value serializers, TTL/TTI policies, heap/disk sizing).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly and clearly summarizes the main changes: four new behavior test classes covering predictions, arrivals/departures, matching, and block assignment in the pipeline test suite.
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 pipeline-tests-2

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

Base automatically changed from pipeline-tests to develop April 23, 2026 02:47
…ching, and block assignment

Extends the transitclockPipelineTests suite with four new behavior test
classes covering previously-unobserved pipeline outputs. The existing
AvlProcessorBehaviorTest only verified that a matched vehicle became
predictable — regressions in the downstream generators would leave that
check green while silently breaking user-visible output.

- PredictionGeneratorBehaviorTest (6 tests): predictions appear in
  PredictionDataCache and on VehicleState, cover the in-horizon stops of
  the current trip, carry correct block/route/vehicle metadata, and emit
  both arrival and departure predictions for mid-trip stops.
- ArrivalDepartureBehaviorTest (4 tests): driving a vehicle through two
  stops generates departure records at the origin and arrival records at
  the destination in StopArrivalDepartureCache with correct metadata.
- BlockAssignerBehaviorTest (8 tests): exercises BLOCK_ID / TRIP_ID /
  TRIP_SHORT_NAME / ROUTE_ID / UNSET assignments plus negative cases
  (invalid block id, invalid trip id) against the real DbConfig.
- MatchingBehaviorTest (6 tests): inspects TemporalMatch content — at-stop
  indicator, stop path index, trip/block/route references, distance to
  segment under the configured tolerance, populated schedule adherence,
  and projected-location proximity to the reported AVL point.

Pipeline tests now total 35 (up from 11). Also adds a pipeline-test-only
ehcache.xml that shadows the main-classpath copy to redirect the ehcache
persistence directory from /usr/local/transitclock/cache (not writable
in CI) to target/ehcache-pipeline-store.

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/PredictionGeneratorBehaviorTest.java`:
- Around line 128-131: The current assertion using
state.getPredictions().allSatisfy(...) can pass vacuously for an empty list; add
an explicit non-empty precondition before the allSatisfy check (e.g.,
assertThat(state.getPredictions()).isNotEmpty()) so the test fails when
predictions are missing, and apply the same change to the other occurrence that
checks predictionTime vs avlTime (the block using state.getPredictions(),
allSatisfy, getPredictionTime and avlTime).
- Around line 178-191: The test
bothArrivalAndDeparturePredictionsArePresentForMidTripStops currently only
filters predictions by TRIP_ID; update the two checks (the anyArrival and
anyDeparture predicates over state.getPredictions()) to also filter by STOP_MID
so they assert presence of both arrival and departure predictions specifically
for the mid-trip stop. Keep the existing use of IpcPrediction::isArrival (and
its negation) but add a predicate p -> STOP_MID.equals(p.getStopId()) alongside
TRIP_ID.equals(p.getTripId()) to narrow the assertions to the intended stop.

In `@transitclockPipelineTests/src/test/resources/ehcache.xml`:
- Around line 41-42: The test cache configuration uses persistent="true" on the
<ehcache:disk> element which causes disk-backed state to be kept between test
runs; change the <ehcache:disk persistent="true" ...> entries used for tests to
non-persistent (set persistent="false" or remove the attribute) so caches are
in-memory only for hermetic tests and do not write to
target/ehcache-pipeline-store; update the three occurrences of the
<ehcache:disk> element (the shown block and the other two similar blocks
referenced) to disable persistence while keeping the same unit/size values.
🪄 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: f23b68b1-999c-4438-b9fc-db238225a140

📥 Commits

Reviewing files that changed from the base of the PR and between afb8792 and 9ea7225.

📒 Files selected for processing (5)
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/ArrivalDepartureBehaviorTest.java
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/BlockAssignerBehaviorTest.java
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/MatchingBehaviorTest.java
  • transitclockPipelineTests/src/test/java/org/transitclock/pipelinetests/PredictionGeneratorBehaviorTest.java
  • transitclockPipelineTests/src/test/resources/ehcache.xml

Comment on lines +178 to +191
public void bothArrivalAndDeparturePredictionsArePresentForMidTripStops() {
pushHappyPathReport("v-preds-arrdep");

VehicleState state = VehicleStateManager.getInstance().getVehicleState("v-preds-arrdep");
// PredictionGenerator emits both an arrival and a departure prediction
// for each non-terminal stop. Missing one type would mean the UI
// shows only "arriving" but not "departing" (or vice versa) — a
// silent capability regression rather than a crash.
boolean anyArrival = state.getPredictions().stream()
.filter(p -> TRIP_ID.equals(p.getTripId()))
.anyMatch(IpcPrediction::isArrival);
boolean anyDeparture = state.getPredictions().stream()
.filter(p -> TRIP_ID.equals(p.getTripId()))
.anyMatch(p -> !p.isArrival());

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

The “mid-trip stops” assertion currently checks only trip-level presence.

This can pass even if mid-stop predictions lose one variant. Filter by STOP_MID (and trip) so the test matches its stated behavior.

Suggested scope fix
-		boolean anyArrival = state.getPredictions().stream()
-				.filter(p -> TRIP_ID.equals(p.getTripId()))
+		boolean anyArrival = state.getPredictions().stream()
+				.filter(p -> TRIP_ID.equals(p.getTripId()))
+				.filter(p -> STOP_MID.equals(p.getStopId()))
 				.anyMatch(IpcPrediction::isArrival);
 		boolean anyDeparture = state.getPredictions().stream()
-				.filter(p -> TRIP_ID.equals(p.getTripId()))
+				.filter(p -> TRIP_ID.equals(p.getTripId()))
+				.filter(p -> STOP_MID.equals(p.getStopId()))
 				.anyMatch(p -> !p.isArrival());
🤖 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/PredictionGeneratorBehaviorTest.java`
around lines 178 - 191, The test
bothArrivalAndDeparturePredictionsArePresentForMidTripStops currently only
filters predictions by TRIP_ID; update the two checks (the anyArrival and
anyDeparture predicates over state.getPredictions()) to also filter by STOP_MID
so they assert presence of both arrival and departure predictions specifically
for the mid-trip stop. Keep the existing use of IpcPrediction::isArrival (and
its negation) but add a predicate p -> STOP_MID.equals(p.getStopId()) alongside
TRIP_ID.equals(p.getTripId()) to narrow the assertions to the intended stop.

Comment thread transitclockPipelineTests/src/test/resources/ehcache.xml Outdated
- Add isNotEmpty() preconditions before allSatisfy() calls in
  PredictionGeneratorBehaviorTest. AssertJ's allSatisfy passes vacuously
  on empty collections, which would let a regression that stops producing
  predictions slip through as a green test.
- Drop persistent="true" from the three disk-backed caches in the test
  ehcache.xml (arrivalDeparturesByTrip, arrivalDeparturesByStop,
  KalmanErrorCache). Test runs should read fresh cache state, not
  whatever a prior run left in target/ehcache-pipeline-store.
- Rename bothArrivalAndDeparturePredictionsArePresentForMidTripStops to
  ...OnActiveTrip and tighten its comment. The previous name claimed a
  per-stop check but the test actually filters only by trip; narrowing
  to STOP_MID (as suggested in review) fails because mid-trip stops
  without a scheduled departure don't emit a departure prediction, so
  whether both variants appear is a trip-level invariant rather than a
  per-stop one.
@aaronbrethorst
aaronbrethorst merged commit 10dc1d7 into develop Apr 23, 2026
3 checks passed
@aaronbrethorst
aaronbrethorst deleted the pipeline-tests-2 branch April 23, 2026 03:59
@coderabbitai coderabbitai Bot mentioned this pull request Apr 23, 2026
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