Skip to content

Commit 75e0fa5

Browse files
committed
Add module test for fuzzy matching by vehicle ref
Add module test for invalid DSJ ID fallback
1 parent cce894f commit 75e0fa5

4 files changed

Lines changed: 115 additions & 5 deletions

File tree

application/src/test/java/org/opentripplanner/transit/model/_data/TimetableRepositoryTestBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ public Trip trip(TripInput tripInput, Consumer<TripBuilder> customizer) {
183183
.withHeadsign(tripInput.headsign())
184184
.withServiceId(serviceId)
185185
.withMode(tripInput.mode())
186-
.withNetexSubmode(tripInput.netexSubmode());
186+
.withNetexSubmode(tripInput.netexSubmode())
187+
.withNetexInternalPlanningCode(tripInput.netexInternalPlanningCode());
187188
if (customizer != null) {
188189
customizer.accept(tripBuilder);
189190
}

application/src/test/java/org/opentripplanner/transit/model/_data/TripInput.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ public class TripInput {
4848
@Nullable
4949
private String netexSubmode;
5050

51+
@Nullable
52+
private String netexInternalPlanningCode;
53+
5154
private final boolean isFlex;
5255

5356
private TripInput(String id, boolean isFlex) {
@@ -107,6 +110,11 @@ public String netexSubmode() {
107110
return netexSubmode;
108111
}
109112

113+
@Nullable
114+
public String netexInternalPlanningCode() {
115+
return netexInternalPlanningCode;
116+
}
117+
110118
public boolean isFlex() {
111119
return isFlex;
112120
}
@@ -193,6 +201,11 @@ public TripInput withNetexSubmode(String netexSubmode) {
193201
return this;
194202
}
195203

204+
public TripInput withNetexInternalPlanningCode(String netexInternalPlanningCode) {
205+
this.netexInternalPlanningCode = netexInternalPlanningCode;
206+
return this;
207+
}
208+
196209
private interface StopCallInput {
197210
StopTime toStopTime(Trip trip, int stopSequence);
198211
StopLocation stopLocation();

application/src/test/java/org/opentripplanner/updater/trip/siri/SiriEtBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import uk.org.siri.siri21.StopPointRefStructure;
2929
import uk.org.siri.siri21.VehicleJourneyRef;
3030
import uk.org.siri.siri21.VehicleModesEnumeration;
31+
import uk.org.siri.siri21.VehicleRef;
3132

3233
/**
3334
* This is a helper class for constucting Siri ET messages to use in tests.
@@ -114,6 +115,13 @@ public SiriEtBuilder withPublishedLineName(String lineName) {
114115
return this;
115116
}
116117

118+
public SiriEtBuilder withVehicleRef(String vehicleRef) {
119+
var ref = new VehicleRef();
120+
ref.setValue(vehicleRef);
121+
evj.setVehicleRef(ref);
122+
return this;
123+
}
124+
117125
public SiriEtBuilder withVehicleMode(VehicleModesEnumeration mode) {
118126
evj.getVehicleModes().add(mode);
119127
return this;

application/src/test/java/org/opentripplanner/updater/trip/siri/moduletests/fuzzymatching/FuzzyTripMatchingTest.java

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
44
import static org.opentripplanner.updater.spi.UpdateResultAssertions.assertFailure;
5+
import static org.opentripplanner.updater.spi.UpdateResultAssertions.assertSuccess;
56

67
import org.junit.jupiter.api.Test;
78
import org.opentripplanner.transit.model._data.TransitTestEnvironment;
89
import org.opentripplanner.transit.model._data.TransitTestEnvironmentBuilder;
910
import org.opentripplanner.transit.model._data.TripInput;
11+
import org.opentripplanner.transit.model.basic.TransitMode;
1012
import org.opentripplanner.transit.model.site.RegularStop;
1113
import org.opentripplanner.updater.spi.UpdateError;
1214
import org.opentripplanner.updater.trip.RealtimeTestConstants;
1315
import org.opentripplanner.updater.trip.SiriTestHelper;
16+
import uk.org.siri.siri21.VehicleModesEnumeration;
1417

1518
class FuzzyTripMatchingTest implements RealtimeTestConstants {
1619

@@ -41,8 +44,11 @@ void testUpdateJourneyWithFuzzyMatching() {
4144
)
4245
.buildEstimatedTimetableDeliveries();
4346
var result = siri.applyEstimatedTimetableWithFuzzyMatcher(updates);
44-
assertEquals(1, result.successful());
45-
assertTripUpdated(env);
47+
assertSuccess(result);
48+
assertEquals(
49+
"UPDATED | A 0:00:15 0:00:15 | B 0:00:25 0:00:25",
50+
env.tripData(TRIP_1_ID).showTimetable()
51+
);
4652
}
4753

4854
/**
@@ -73,10 +79,92 @@ void testUpdateJourneyWithFuzzyMatchingAndMissingAimedDepartureTime() {
7379
assertFailure(UpdateError.UpdateErrorType.NO_FUZZY_TRIP_MATCH, result);
7480
}
7581

76-
private static void assertTripUpdated(TransitTestEnvironment env) {
82+
/**
83+
* Two RAIL trips with identical stops and times but different internalPlanningCodes.
84+
* The SIRI update has a non-matching VehicleJourneyRef but includes a VehicleRef that
85+
* corresponds to one trip's planning code. The matcher should disambiguate using VehicleRef.
86+
*/
87+
@Test
88+
void testFuzzyMatchByVehicleRefForRailTrip() {
89+
var railRoute = ENV_BUILDER.route("RailRoute", r -> r.withMode(TransitMode.RAIL));
90+
91+
var railTrip1 = TripInput.of("RailTrip1")
92+
.withRoute(railRoute)
93+
.withNetexInternalPlanningCode("47")
94+
.addStop(STOP_A, "0:00:10", "0:00:11")
95+
.addStop(STOP_B, "0:00:20", "0:00:21");
96+
97+
var railTrip2 = TripInput.of("RailTrip2")
98+
.withRoute(railRoute)
99+
.withNetexInternalPlanningCode("48")
100+
.addStop(STOP_A, "0:00:10", "0:00:11")
101+
.addStop(STOP_B, "0:00:20", "0:00:21");
102+
103+
var env = ENV_BUILDER.addTrip(railTrip1).addTrip(railTrip2).build();
104+
105+
var siri = SiriTestHelper.of(env);
106+
107+
var updates = siri
108+
.etBuilder()
109+
.withFramedVehicleJourneyRef(builder ->
110+
builder.withServiceDate(env.defaultServiceDate()).withVehicleJourneyRef("NONEXISTENT")
111+
)
112+
.withVehicleRef("47")
113+
.withVehicleMode(VehicleModesEnumeration.RAIL)
114+
.withEstimatedCalls(builder ->
115+
builder
116+
.call(STOP_A)
117+
.departAimedExpected("00:00:11", "00:00:15")
118+
.call(STOP_B)
119+
.arriveAimedExpected("00:00:20", "00:00:25")
120+
)
121+
.buildEstimatedTimetableDeliveries();
122+
123+
var result = siri.applyEstimatedTimetableWithFuzzyMatcher(updates);
124+
assertSuccess(result);
77125
assertEquals(
78126
"UPDATED | A 0:00:15 0:00:15 | B 0:00:25 0:00:25",
79-
env.tripData(TRIP_1_ID).showTimetable()
127+
env.tripData("RailTrip1").showTimetable()
128+
);
129+
}
130+
131+
/**
132+
* The fuzzy matcher should still resolve the trip via VehicleRef → internalPlanningCode
133+
* when only DatedVehicleJourneyRef is provided.
134+
*/
135+
@Test
136+
void testFuzzyMatchByVehicleRefWithDatedVehicleJourneyRefOnly() {
137+
var railRoute = ENV_BUILDER.route("RailRoute2", r -> r.withMode(TransitMode.RAIL));
138+
139+
var railTrip = TripInput.of("RailTrip3")
140+
.withRoute(railRoute)
141+
.withNetexInternalPlanningCode("406")
142+
.addStop(STOP_A, "0:00:10", "0:00:11")
143+
.addStop(STOP_B, "0:00:20", "0:00:21");
144+
145+
var env = ENV_BUILDER.addTrip(railTrip).build();
146+
147+
var siri = SiriTestHelper.of(env);
148+
149+
var updates = siri
150+
.etBuilder()
151+
.withDatedVehicleJourneyRef("406:2026-02-17")
152+
.withVehicleRef("406")
153+
.withVehicleMode(VehicleModesEnumeration.RAIL)
154+
.withEstimatedCalls(builder ->
155+
builder
156+
.call(STOP_A)
157+
.departAimedExpected("00:00:11", "00:00:15")
158+
.call(STOP_B)
159+
.arriveAimedExpected("00:00:20", "00:00:25")
160+
)
161+
.buildEstimatedTimetableDeliveries();
162+
163+
var result = siri.applyEstimatedTimetableWithFuzzyMatcher(updates);
164+
assertSuccess(result);
165+
assertEquals(
166+
"UPDATED | A 0:00:15 0:00:15 | B 0:00:25 0:00:25",
167+
env.tripData("RailTrip3").showTimetable()
80168
);
81169
}
82170
}

0 commit comments

Comments
 (0)