Skip to content

Commit c53d598

Browse files
committed
add test for opentripplanner#6242
1 parent 39c0aac commit c53d598

File tree

6 files changed

+397
-88
lines changed

6 files changed

+397
-88
lines changed

application/src/main/java/org/opentripplanner/updater/trip/TimetableSnapshotSource.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ public class TimetableSnapshotSource implements TimetableSnapshotProvider {
9393
private final ZoneId timeZone;
9494

9595
/**
96-
* Long-lived transit editor service that has access to the timetable snapshot buffer.
97-
* This differs from the usual use case where the transit service refers to the latest published
96+
* Long-lived transit editor service that has access to the timetable snapshot buffer. This
97+
* differs from the usual use case where the transit service refers to the latest published
9898
* timetable snapshot.
9999
*/
100100
private final TransitEditorService transitEditorService;
@@ -114,10 +114,9 @@ public TimetableSnapshotSource(
114114
}
115115

116116
/**
117-
* Constructor is package local to allow unit-tests to provide their own clock, not using system
118-
* time.
117+
* Constructor to allow tests to provide their own clock, not using system time.
119118
*/
120-
TimetableSnapshotSource(
119+
public TimetableSnapshotSource(
121120
TimetableSnapshotSourceParameters parameters,
122121
TimetableRepository timetableRepository,
123122
Supplier<LocalDate> localDateNow
@@ -148,8 +147,9 @@ public TimetableSnapshotSource(
148147
*
149148
* @param backwardsDelayPropagationType Defines when delays are propagated to previous stops and
150149
* if these stops are given the NO_DATA flag.
151-
* @param updateIncrementality Determines the incrementality of the updates. FULL updates clear the buffer
152-
* of all previous updates for the given feed id.
150+
* @param updateIncrementality Determines the incrementality of the updates. FULL updates
151+
* clear the buffer of all previous updates for the given
152+
* feed id.
153153
* @param updates GTFS-RT TripUpdate's that should be applied atomically
154154
*/
155155
public UpdateResult applyTripUpdates(
@@ -342,8 +342,8 @@ public TimetableSnapshot getTimetableSnapshot() {
342342

343343
/**
344344
* @return the current timetable snapshot buffer that contains pending changes (not yet published
345-
* in a snapshot). This should be used in the context of an updater to build a TransitEditorService
346-
* that sees all the changes applied so far by real-time updates.
345+
* in a snapshot). This should be used in the context of an updater to build a
346+
* TransitEditorService that sees all the changes applied so far by real-time updates.
347347
*/
348348
public TimetableSnapshot getTimetableSnapshotBuffer() {
349349
return snapshotManager.getTimetableSnapshotBuffer();

application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java

Lines changed: 104 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@
1616
import static org.opentripplanner.transit.model.basic.TransitMode.FERRY;
1717
import static org.opentripplanner.transit.model.timetable.OccupancyStatus.FEW_SEATS_AVAILABLE;
1818

19+
import com.google.transit.realtime.GtfsRealtime;
1920
import jakarta.ws.rs.core.Response;
2021
import java.io.IOException;
2122
import java.nio.file.Files;
2223
import java.nio.file.Path;
2324
import java.nio.file.StandardOpenOption;
2425
import java.time.Instant;
26+
import java.time.LocalDate;
2527
import java.time.OffsetDateTime;
28+
import java.time.ZoneId;
2629
import java.time.temporal.ChronoUnit;
2730
import java.util.Arrays;
2831
import java.util.Comparator;
@@ -42,7 +45,9 @@
4245
import org.opentripplanner.framework.i18n.I18NString;
4346
import org.opentripplanner.framework.i18n.NonLocalizedString;
4447
import org.opentripplanner.framework.model.Grams;
48+
import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore;
4549
import org.opentripplanner.model.FeedInfo;
50+
import org.opentripplanner.model.calendar.CalendarServiceData;
4651
import org.opentripplanner.model.fare.FareMedium;
4752
import org.opentripplanner.model.fare.FareProduct;
4853
import org.opentripplanner.model.fare.ItineraryFares;
@@ -60,6 +65,10 @@
6065
import org.opentripplanner.routing.alertpatch.EntitySelector;
6166
import org.opentripplanner.routing.alertpatch.TimePeriod;
6267
import org.opentripplanner.routing.alertpatch.TransitAlert;
68+
import org.opentripplanner.routing.algorithm.raptoradapter.transit.TransitLayer;
69+
import org.opentripplanner.routing.algorithm.raptoradapter.transit.TransitTuningParameters;
70+
import org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers.TransitLayerMapper;
71+
import org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers.TransitLayerUpdater;
6372
import org.opentripplanner.routing.api.request.RouteRequest;
6473
import org.opentripplanner.routing.graph.Graph;
6574
import org.opentripplanner.routing.graphfinder.GraphFinder;
@@ -91,11 +100,18 @@
91100
import org.opentripplanner.transit.model.site.RegularStop;
92101
import org.opentripplanner.transit.model.site.StopLocation;
93102
import org.opentripplanner.transit.model.timetable.RealTimeTripTimes;
103+
import org.opentripplanner.transit.model.timetable.Trip;
94104
import org.opentripplanner.transit.model.timetable.TripTimesFactory;
95105
import org.opentripplanner.transit.service.DefaultTransitService;
96106
import org.opentripplanner.transit.service.TimetableRepository;
97107
import org.opentripplanner.transit.service.TransitEditorService;
98108
import org.opentripplanner.transit.service.TransitService;
109+
import org.opentripplanner.updater.GtfsRealtimeFuzzyTripMatcher;
110+
import org.opentripplanner.updater.TimetableSnapshotSourceParameters;
111+
import org.opentripplanner.updater.trip.BackwardsDelayPropagationType;
112+
import org.opentripplanner.updater.trip.TimetableSnapshotSource;
113+
import org.opentripplanner.updater.trip.TripUpdateBuilder;
114+
import org.opentripplanner.updater.trip.UpdateIncrementality;
99115
import org.opentripplanner.utils.collection.ListUtils;
100116

101117
class GraphQLIntegrationTest {
@@ -116,6 +132,10 @@ class GraphQLIntegrationTest {
116132
.map(p -> (RegularStop) p.stop)
117133
.toList();
118134
private static final Route ROUTE = TimetableRepositoryForTest.route("a-route").build();
135+
private static final String ADDED_TRIP_ID = "ADDED_TRIP";
136+
private static final String REPLACEMENT_TRIP_ID = "REPLACEMENT_TRIP";
137+
public static final ZoneId TIME_ZONE = ZoneIds.BERLIN;
138+
public static final String FEED_ID = TimetableRepositoryForTest.FEED_ID;
119139

120140
private static VehicleRentalStation VEHICLE_RENTAL_STATION = new TestVehicleRentalStationBuilder()
121141
.withVehicles(10)
@@ -137,6 +157,8 @@ class GraphQLIntegrationTest {
137157
static final Instant ALERT_END_TIME = ALERT_START_TIME.plus(1, ChronoUnit.DAYS);
138158
private static final int TEN_MINUTES = 10 * 60;
139159

160+
private static final LocalDate SERVICE_DATE = LocalDate.of(2024, 1, 1);
161+
140162
private static GraphQLRequestContext context;
141163

142164
private static final Deduplicator DEDUPLICATOR = new Deduplicator();
@@ -157,38 +179,59 @@ static void setup() {
157179
List.of()
158180
);
159181

160-
var siteRepository = TEST_MODEL.siteRepositoryBuilder();
161-
STOP_LOCATIONS.forEach(siteRepository::withRegularStop);
162-
var model = siteRepository.build();
163-
var timetableRepository = new TimetableRepository(model, DEDUPLICATOR);
182+
var siteRepositoryBuilder = TEST_MODEL.siteRepositoryBuilder();
183+
STOP_LOCATIONS.forEach(siteRepositoryBuilder::withRegularStop);
184+
var siteRepository = siteRepositoryBuilder.build();
185+
var timetableRepository = new TimetableRepository(siteRepository, DEDUPLICATOR);
164186

165187
var trip = TimetableRepositoryForTest
166188
.trip("123")
167189
.withHeadsign(I18NString.of("Trip Headsign"))
168190
.build();
169191
var stopTimes = TEST_MODEL.stopTimesEvery5Minutes(3, trip, T11_00);
170192
var tripTimes = TripTimesFactory.tripTimes(trip, stopTimes, DEDUPLICATOR);
193+
194+
var calendar = new CalendarServiceData();
195+
FeedScopedId serviceId = calendar.getOrCreateServiceIdForDate(SERVICE_DATE);
196+
197+
var tripToBeReplaced = TimetableRepositoryForTest
198+
.trip(REPLACEMENT_TRIP_ID)
199+
.withServiceId(serviceId)
200+
.build();
171201
final TripPattern pattern = TEST_MODEL
172202
.pattern(BUS)
173-
.withScheduledTimeTableBuilder(builder -> builder.addTripTimes(tripTimes))
203+
.withScheduledTimeTableBuilder(builder ->
204+
builder
205+
.addTripTimes(tripTimes)
206+
.addTripTimes(
207+
TripTimesFactory.tripTimes(
208+
tripToBeReplaced,
209+
TEST_MODEL.stopTimesEvery5Minutes(3, tripToBeReplaced, T11_30),
210+
DEDUPLICATOR
211+
)
212+
)
213+
)
174214
.build();
175215

176216
timetableRepository.addTripPattern(id("pattern-1"), pattern);
177217

178-
var feedId = "testfeed";
179-
var feedInfo = FeedInfo.dummyForTest(feedId);
218+
var feedInfo = FeedInfo.dummyForTest(FEED_ID);
180219
timetableRepository.addFeedInfo(feedInfo);
181220

182221
var agency = Agency
183-
.of(new FeedScopedId(feedId, "agency-xx"))
222+
.of(new FeedScopedId(FEED_ID, "agency-xx"))
184223
.withName("speedtransit")
185224
.withUrl("www.otp-foo.bar")
186225
.withTimezone("Europe/Berlin")
187226
.build();
188227
timetableRepository.addAgency(agency);
189228

190-
timetableRepository.initTimeZone(ZoneIds.BERLIN);
229+
timetableRepository.initTimeZone(TIME_ZONE);
230+
var serviceCodes = timetableRepository.getServiceCodes();
231+
serviceCodes.put(serviceId, serviceCodes.size());
232+
timetableRepository.updateCalendarServiceData(true, calendar, DataImportIssueStore.NOOP);
191233
timetableRepository.index();
234+
192235
var routes = Arrays
193236
.stream(TransitMode.values())
194237
.sorted(Comparator.comparing(Enum::name))
@@ -226,6 +269,29 @@ public Set<Route> getRoutesForStop(StopLocation stop) {
226269
};
227270
routes.forEach(transitService::addRoutes);
228271

272+
timetableRepository.setTransitLayer(
273+
TransitLayerMapper.map(TransitTuningParameters.FOR_TEST, timetableRepository)
274+
);
275+
timetableRepository.setRealtimeTransitLayer(
276+
new TransitLayer(timetableRepository.getTransitLayer())
277+
);
278+
var transitLayerUpdater = new TransitLayerUpdater(transitService);
279+
timetableRepository.setTransitLayerUpdater(transitLayerUpdater);
280+
281+
var timetableSnapshotProvider = new TimetableSnapshotSource(
282+
TimetableSnapshotSourceParameters.DEFAULT,
283+
timetableRepository,
284+
() -> SERVICE_DATE
285+
);
286+
timetableSnapshotProvider.applyTripUpdates(
287+
new GtfsRealtimeFuzzyTripMatcher(transitService),
288+
BackwardsDelayPropagationType.REQUIRED_NO_DATA,
289+
UpdateIncrementality.FULL_DATASET,
290+
List.of(getAddedTrip(busRoute), getReplacementTrip(tripToBeReplaced)),
291+
FEED_ID
292+
);
293+
timetableSnapshotProvider.flushBuffer();
294+
229295
var step1 = walkStep("street")
230296
.withRelativeDirection(RelativeDirection.DEPART)
231297
.withAbsoluteDirection(20)
@@ -323,6 +389,35 @@ public Set<Route> getRoutesForStop(StopLocation stop) {
323389
);
324390
}
325391

392+
private static GtfsRealtime.TripUpdate getAddedTrip(Route route) {
393+
var tripUpdateBuilder = new TripUpdateBuilder(
394+
route.getId().getId(),
395+
ADDED_TRIP_ID,
396+
SERVICE_DATE,
397+
GtfsRealtime.TripDescriptor.ScheduleRelationship.ADDED,
398+
TIME_ZONE
399+
);
400+
tripUpdateBuilder.addStopTime(A.stop.getId().getId(), 0);
401+
tripUpdateBuilder.addStopTime(B.stop.getId().getId(), 300);
402+
tripUpdateBuilder.addStopTime(C.stop.getId().getId(), 600);
403+
tripUpdateBuilder.addStopTime(D.stop.getId().getId(), 900);
404+
return tripUpdateBuilder.build();
405+
}
406+
407+
private static GtfsRealtime.TripUpdate getReplacementTrip(Trip trip) {
408+
var tripUpdateBuilder = new TripUpdateBuilder(
409+
trip.getId().getId(),
410+
SERVICE_DATE,
411+
GtfsRealtime.TripDescriptor.ScheduleRelationship.REPLACEMENT,
412+
TIME_ZONE
413+
);
414+
tripUpdateBuilder.addStopTime(A.stop.getId().getId(), 0);
415+
tripUpdateBuilder.addStopTime(B.stop.getId().getId(), 300);
416+
tripUpdateBuilder.addStopTime(C.stop.getId().getId(), 600);
417+
tripUpdateBuilder.addStopTime(D.stop.getId().getId(), 900);
418+
return tripUpdateBuilder.build();
419+
}
420+
326421
private static BikeAccess bikesAllowed(TransitMode m) {
327422
return switch (m.ordinal() % 3) {
328423
case 0 -> BikeAccess.ALLOWED;

application/src/test/java/org/opentripplanner/updater/trip/TripUpdateBuilder.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,21 @@ public TripUpdateBuilder(
3737
this.midnight = ServiceDateUtils.asStartOfService(serviceDate, zoneId);
3838
}
3939

40-
public TripUpdateBuilder addStopTime(String stopId, int minutes) {
40+
public TripUpdateBuilder(
41+
String routeId,
42+
String tripId,
43+
LocalDate serviceDate,
44+
GtfsRealtime.TripDescriptor.ScheduleRelationship scheduleRelationship,
45+
ZoneId zoneId
46+
) {
47+
this(tripId, serviceDate, scheduleRelationship, zoneId);
48+
tripDescriptorBuilder.setRouteId(routeId);
49+
}
50+
51+
public TripUpdateBuilder addStopTime(String stopId, int secondsFromMidnight) {
4152
return addStopTime(
4253
stopId,
43-
minutes,
54+
secondsFromMidnight,
4455
NO_VALUE,
4556
NO_DELAY,
4657
NO_DELAY,
@@ -49,10 +60,14 @@ public TripUpdateBuilder addStopTime(String stopId, int minutes) {
4960
);
5061
}
5162

52-
public TripUpdateBuilder addStopTime(String stopId, int minutes, DropOffPickupType pickDrop) {
63+
public TripUpdateBuilder addStopTime(
64+
String stopId,
65+
int secondsFromMidnight,
66+
DropOffPickupType pickDrop
67+
) {
5368
return addStopTime(
5469
stopId,
55-
minutes,
70+
secondsFromMidnight,
5671
NO_VALUE,
5772
NO_DELAY,
5873
NO_DELAY,
@@ -122,7 +137,7 @@ public TripUpdateBuilder addRawStopTime(StopTimeUpdate stopTime) {
122137

123138
private TripUpdateBuilder addStopTime(
124139
String stopId,
125-
int minutes,
140+
int secondsFromMidnight,
126141
int stopSequence,
127142
int arrivalDelay,
128143
int departureDelay,
@@ -153,8 +168,8 @@ private TripUpdateBuilder addStopTime(
153168
final GtfsRealtime.TripUpdate.StopTimeEvent.Builder arrivalBuilder = stopTimeUpdateBuilder.getArrivalBuilder();
154169
final GtfsRealtime.TripUpdate.StopTimeEvent.Builder departureBuilder = stopTimeUpdateBuilder.getDepartureBuilder();
155170

156-
if (minutes > NO_VALUE) {
157-
var epochSeconds = midnight.plusHours(8).plusMinutes(minutes).toEpochSecond();
171+
if (secondsFromMidnight > NO_VALUE) {
172+
var epochSeconds = midnight.plusSeconds(secondsFromMidnight).toEpochSecond();
158173
arrivalBuilder.setTime(epochSeconds);
159174
departureBuilder.setTime(epochSeconds);
160175
}

0 commit comments

Comments
 (0)