Skip to content

Commit

Permalink
Merge pull request #6462 from leonardehrenfried/siri-module-tests
Browse files Browse the repository at this point in the history
Convert SIRI tests to feature-specific module tests
  • Loading branch information
leonardehrenfried authored Feb 24, 2025
2 parents 30c1fa5 + 0c44367 commit 7a060aa
Show file tree
Hide file tree
Showing 11 changed files with 762 additions and 613 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package org.opentripplanner.updater.siri.moduletests.cancellation;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.opentripplanner.transit.model.timetable.RealTimeState;
import org.opentripplanner.updater.siri.SiriEtBuilder;
import org.opentripplanner.updater.trip.RealtimeTestConstants;
import org.opentripplanner.updater.trip.RealtimeTestEnvironment;
import org.opentripplanner.updater.trip.TripInput;

class CancellationTest implements RealtimeTestConstants {

private static final TripInput TRIP_INPUT = TripInput
.of(TRIP_1_ID)
.addStop(STOP_A1, "0:00:10", "0:00:11")
.addStop(STOP_B1, "0:00:20", "0:00:21")
.build();

private static final String ADDED_TRIP_ID = "newJourney";

@Test
void testCancelTrip() {
var env = RealtimeTestEnvironment.of().addTrip(TRIP_INPUT).build();

assertEquals(RealTimeState.SCHEDULED, env.getTripTimesForTrip(TRIP_1_ID).getRealTimeState());

var updates = new SiriEtBuilder(env.getDateTimeHelper())
.withDatedVehicleJourneyRef(TRIP_1_ID)
.withCancellation(true)
.buildEstimatedTimetableDeliveries();

var result = env.applyEstimatedTimetable(updates);

assertEquals(1, result.successful());
assertEquals(RealTimeState.CANCELED, env.getTripTimesForTrip(TRIP_1_ID).getRealTimeState());
}

/**
* When a scheduled trip is modified (both trip times and stops) and subsequently cancelled,
* it should be marked as cancelled and reverted to its scheduled trip times and stops.
*/
@Test
void testChangeQuayAndCancelScheduledTrip() {
var env = RealtimeTestEnvironment.of().addTrip(TRIP_INPUT).build();
assertEquals(
"SCHEDULED | A1 0:00:10 0:00:11 | B1 0:00:20 0:00:21",
env.getRealtimeTimetable(TRIP_1_ID)
);
changeQuayAndCancelTrip(env, TRIP_1_ID);

assertEquals(
"CANCELED | A1 0:00:10 0:00:11 | B1 0:00:20 0:00:21",
env.getRealtimeTimetable(TRIP_1_ID)
);
}

/**
* When an added trip is modified (both trip times and stops) and subsequently cancelled,
* it should be marked as cancelled and reverted to its initial trip times and stops
*/
@Test
void testChangeQuayAndCancelAddedTrip() {
var env = RealtimeTestEnvironment.of().addTrip(TRIP_INPUT).build();
var creation = new SiriEtBuilder(env.getDateTimeHelper())
.withEstimatedVehicleJourneyCode(ADDED_TRIP_ID)
.withIsExtraJourney(true)
.withOperatorRef(OPERATOR_1_ID)
.withLineRef(ROUTE_1_ID)
.withEstimatedCalls(builder ->
builder
.call(STOP_A1)
.arriveAimedExpected("0:00:10", "0:00:10")
.departAimedExpected("0:00:11", "0:00:11")
.call(STOP_B1)
.arriveAimedExpected("0:00:20", "0:00:20")
.departAimedExpected("0:00:21", "0:00:21")
)
.buildEstimatedTimetableDeliveries();
var creationResult = env.applyEstimatedTimetable(creation);
assertEquals(1, creationResult.successful());
assertEquals(
"ADDED | A1 0:00:10 0:00:11 | B1 0:00:20 0:00:21",
env.getRealtimeTimetable(ADDED_TRIP_ID)
);
changeQuayAndCancelTrip(env, ADDED_TRIP_ID);

// the arrival time on first stop is adjusted to the departure time to avoid negative dwell time
// conversely the departure time on last stop is adjusted to the arrival time
assertEquals(
"CANCELED | A1 0:00:11 0:00:11 | B1 0:00:20 0:00:20",
env.getRealtimeTimetable(ADDED_TRIP_ID)
);
}

private static void changeQuayAndCancelTrip(RealtimeTestEnvironment env, String tripId) {
var modification = new SiriEtBuilder(env.getDateTimeHelper())
.withDatedVehicleJourneyRef(tripId)
.withEstimatedCalls(builder ->
builder
.call(STOP_A1)
.departAimedExpected("00:00:11", "00:00:15")
// change to another quay in the same station
.call(STOP_B2)
.arriveAimedExpected("00:00:20", "00:00:25")
)
.buildEstimatedTimetableDeliveries();

var modificationResult = env.applyEstimatedTimetable(modification);
assertEquals(1, modificationResult.successful());
assertEquals(
"MODIFIED | A1 0:00:15 0:00:15 | B2 0:00:25 0:00:25",
env.getRealtimeTimetable(tripId)
);

var cancellation = new SiriEtBuilder(env.getDateTimeHelper())
.withDatedVehicleJourneyRef(tripId)
.withCancellation(true)
.buildEstimatedTimetableDeliveries();

var cancellationResult = env.applyEstimatedTimetable(cancellation);

assertEquals(1, cancellationResult.successful());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.opentripplanner.updater.siri.moduletests.cancellation;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.opentripplanner.updater.siri.SiriEtBuilder;
import org.opentripplanner.updater.trip.RealtimeTestConstants;
import org.opentripplanner.updater.trip.RealtimeTestEnvironment;
import org.opentripplanner.updater.trip.TripInput;

class CancelledStopTest implements RealtimeTestConstants {

private static final TripInput TRIP_INPUT = TripInput
.of(TRIP_2_ID)
.addStop(STOP_A1, "0:01:00", "0:01:01")
.addStop(STOP_B1, "0:01:10", "0:01:11")
.addStop(STOP_C1, "0:01:20", "0:01:21")
.build();

@Test
void testCancelStop() {
var env = RealtimeTestEnvironment.of().addTrip(TRIP_INPUT).build();

var updates = new SiriEtBuilder(env.getDateTimeHelper())
.withDatedVehicleJourneyRef(TRIP_2_ID)
.withEstimatedCalls(builder ->
builder
.call(STOP_A1)
.departAimedExpected("00:01:01", "00:01:01")
.call(STOP_B1)
.withIsCancellation(true)
.call(STOP_C1)
.arriveAimedExpected("00:01:30", "00:01:30")
)
.buildEstimatedTimetableDeliveries();

var result = env.applyEstimatedTimetable(updates);

assertEquals(1, result.successful());
assertEquals(
"MODIFIED | A1 0:01:01 0:01:01 | B1 [C] 0:01:10 0:01:11 | C1 0:01:30 0:01:30",
env.getRealtimeTimetable(TRIP_2_ID)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package org.opentripplanner.updater.siri.moduletests.extrajourney;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.opentripplanner.transit.model._data.TimetableRepositoryForTest.id;
import static org.opentripplanner.updater.spi.UpdateResultAssertions.assertFailure;

import org.junit.jupiter.api.Test;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.model.network.Route;
import org.opentripplanner.transit.model.timetable.RealTimeState;
import org.opentripplanner.transit.model.timetable.Trip;
import org.opentripplanner.transit.model.timetable.TripIdAndServiceDate;
import org.opentripplanner.transit.service.TransitService;
import org.opentripplanner.updater.siri.SiriEtBuilder;
import org.opentripplanner.updater.spi.UpdateError;
import org.opentripplanner.updater.trip.RealtimeTestConstants;
import org.opentripplanner.updater.trip.RealtimeTestEnvironment;
import org.opentripplanner.updater.trip.TripInput;

class ExtraJourneyTest implements RealtimeTestConstants {

private static final TripInput TRIP_1_INPUT = TripInput
.of(TRIP_1_ID)
.withRoute(ROUTE_1.copy().withOperator(OPERATOR1).build())
.addStop(STOP_A1, "0:00:10", "0:00:11")
.addStop(STOP_B1, "0:00:20", "0:00:21")
.build();

private static final String ADDED_TRIP_ID = "newJourney";

@Test
void testAddJourneyWithExistingRoute() {
var env = RealtimeTestEnvironment.of().addTrip(TRIP_1_INPUT).build();

Route route = ROUTE_1;
int numPatternForRoute = env.getTransitService().findPatterns(route).size();

var updates = createValidAddedJourney(env).buildEstimatedTimetableDeliveries();

var result = env.applyEstimatedTimetable(updates);

assertEquals(1, result.successful());
assertEquals(
"ADDED | C1 [R] 0:02 0:02 | D1 0:04 0:04",
env.getRealtimeTimetable(ADDED_TRIP_ID)
);
assertEquals(
"SCHEDULED | C1 0:01 0:01 | D1 0:03 0:03",
env.getScheduledTimetable(ADDED_TRIP_ID)
);
FeedScopedId tripId = id(ADDED_TRIP_ID);
TransitService transitService = env.getTransitService();
Trip trip = transitService.getTrip(tripId);
assertNotNull(trip);
assertNotNull(transitService.findPattern(trip));
assertNotNull(transitService.getTripOnServiceDate(tripId));
assertNotNull(
transitService.getTripOnServiceDate(new TripIdAndServiceDate(tripId, SERVICE_DATE))
);
assertEquals(
numPatternForRoute + 1,
transitService.findPatterns(route).size(),
"The added trip should use a new pattern for this route"
);
}

@Test
void testAddJourneyWithNewRoute() {
// we actually don't need the trip, but it's the only way to add a route to the index
var env = RealtimeTestEnvironment.of().addTrip(TRIP_1_INPUT).build();

String newRouteRef = "new route ref";
var updates = createValidAddedJourney(env)
.withLineRef(newRouteRef)
.buildEstimatedTimetableDeliveries();

int numRoutes = env.getTransitService().listRoutes().size();
var result = env.applyEstimatedTimetable(updates);

assertEquals(1, result.successful());
assertEquals(
"ADDED | C1 [R] 0:02 0:02 | D1 0:04 0:04",
env.getRealtimeTimetable(ADDED_TRIP_ID)
);
assertEquals(
"SCHEDULED | C1 0:01 0:01 | D1 0:03 0:03",
env.getScheduledTimetable(ADDED_TRIP_ID)
);
TransitService transitService = env.getTransitService();
assertEquals(numRoutes + 1, transitService.listRoutes().size());
FeedScopedId newRouteId = id(newRouteRef);
Route newRoute = transitService.getRoute(newRouteId);
assertNotNull(newRoute);
assertEquals(1, transitService.findPatterns(newRoute).size());
}

@Test
void testAddJourneyMultipleTimes() {
// we actually don't need the trip, but it's the only way to add a route to the index
var env = RealtimeTestEnvironment.of().addTrip(TRIP_1_INPUT).build();
var updates = createValidAddedJourney(env).buildEstimatedTimetableDeliveries();

int numTrips = env.getTransitService().listTrips().size();
var result1 = env.applyEstimatedTimetable(updates);
assertEquals(1, result1.successful());
assertEquals(numTrips + 1, env.getTransitService().listTrips().size());
var result2 = env.applyEstimatedTimetable(updates);
assertEquals(1, result2.successful());
assertEquals(numTrips + 1, env.getTransitService().listTrips().size());
}

@Test
void testAddedJourneyWithInvalidScheduledData() {
// we actually don't need the trip, but it's the only way to add a route to the index
var env = RealtimeTestEnvironment.of().addTrip(TRIP_1_INPUT).build();

// Create an extra journey with invalid planned data (travel back in time)
// and valid real time data
var createExtraJourney = new SiriEtBuilder(env.getDateTimeHelper())
.withEstimatedVehicleJourneyCode(ADDED_TRIP_ID)
.withIsExtraJourney(true)
.withOperatorRef(OPERATOR_1_ID)
.withLineRef(ROUTE_1_ID)
.withEstimatedCalls(builder ->
builder
.call(STOP_A1)
.departAimedExpected("10:58", "10:48")
.call(STOP_B1)
.arriveAimedExpected("10:08", "10:58")
)
.buildEstimatedTimetableDeliveries();

var result = env.applyEstimatedTimetable(createExtraJourney);
assertEquals(0, result.successful());
assertFailure(UpdateError.UpdateErrorType.NEGATIVE_HOP_TIME, result);
}

@Test
void testReplaceJourney() {
var env = RealtimeTestEnvironment.of().addTrip(TRIP_1_INPUT).build();

var updates = new SiriEtBuilder(env.getDateTimeHelper())
.withEstimatedVehicleJourneyCode(ADDED_TRIP_ID)
.withIsExtraJourney(true)
// replace trip1
.withVehicleJourneyRef(TRIP_1_ID)
.withOperatorRef(OPERATOR_1_ID)
.withLineRef(ROUTE_1_ID)
.withRecordedCalls(builder -> builder.call(STOP_A1).departAimedActual("00:01", "00:02"))
.withEstimatedCalls(builder -> builder.call(STOP_C1).arriveAimedExpected("00:03", "00:04"))
.buildEstimatedTimetableDeliveries();

var result = env.applyEstimatedTimetable(updates);

assertEquals(1, result.successful());

assertEquals(
"ADDED | A1 [R] 0:02 0:02 | C1 0:04 0:04",
env.getRealtimeTimetable(ADDED_TRIP_ID)
);
assertEquals(
"SCHEDULED | A1 0:01 0:01 | C1 0:03 0:03",
env.getScheduledTimetable(ADDED_TRIP_ID)
);

// Original trip should not get canceled
var originalTripTimes = env.getTripTimesForTrip(TRIP_1_ID);
assertEquals(RealTimeState.SCHEDULED, originalTripTimes.getRealTimeState());
}

@Test
void testReplaceJourneyWithoutEstimatedVehicleJourneyCode() {
var env = RealtimeTestEnvironment.of().addTrip(TRIP_1_INPUT).build();

var updates = new SiriEtBuilder(env.getDateTimeHelper())
.withDatedVehicleJourneyRef(ADDED_TRIP_ID)
.withIsExtraJourney(true)
.withVehicleJourneyRef(TRIP_1_ID)
.withOperatorRef(OPERATOR_1_ID)
.withLineRef(ROUTE_1_ID)
.withEstimatedCalls(builder ->
builder
.call(STOP_A1)
.departAimedExpected("00:01", "00:02")
.call(STOP_C1)
.arriveAimedExpected("00:03", "00:04")
)
.buildEstimatedTimetableDeliveries();

var result = env.applyEstimatedTimetable(updates);

// TODO: this should have a more specific error type
assertFailure(UpdateError.UpdateErrorType.UNKNOWN, result);
}

private static SiriEtBuilder createValidAddedJourney(RealtimeTestEnvironment env) {
return new SiriEtBuilder(env.getDateTimeHelper())
.withEstimatedVehicleJourneyCode(ADDED_TRIP_ID)
.withIsExtraJourney(true)
.withOperatorRef(OPERATOR_1_ID)
.withLineRef(ROUTE_1_ID)
.withRecordedCalls(builder -> builder.call(STOP_C1).departAimedActual("00:01", "00:02"))
.withEstimatedCalls(builder -> builder.call(STOP_D1).arriveAimedExpected("00:03", "00:04"));
}
}
Loading

0 comments on commit 7a060aa

Please sign in to comment.