activeTrips = schedule.getActiveTrips(GtfsScheduleTestBuilder.Moments.HOLIDAY);
+
+ assertWeekendAndHoliday(activeTrips);
+ }
+
+ @Test
+ void shouldReturnNoActiveTripsForDaysOutsideValidity() {
+ assertThat(schedule.getActiveTrips(GtfsScheduleTestBuilder.Validity.PERIOD_START.minusDays(1))).isEmpty();
+ assertThat(schedule.getActiveTrips(GtfsScheduleTestBuilder.Validity.PERIOD_END.plusDays(1))).isEmpty();
}
@Test
void shouldReturnNoActiveTripsForNonServiceDay() {
- assertThat(schedule.getActiveTrips(END_DATE.plusMonths(1))).isEmpty();
+ assertThat(schedule.getActiveTrips(GtfsScheduleTestBuilder.Moments.NO_SERVICE)).isEmpty();
}
}
}
diff --git a/src/test/java/ch/naviqore/gtfs/schedule/model/GtfsScheduleTestBuilder.java b/src/test/java/ch/naviqore/gtfs/schedule/model/GtfsScheduleTestBuilder.java
new file mode 100644
index 00000000..c52d74db
--- /dev/null
+++ b/src/test/java/ch/naviqore/gtfs/schedule/model/GtfsScheduleTestBuilder.java
@@ -0,0 +1,182 @@
+package ch.naviqore.gtfs.schedule.model;
+
+import ch.naviqore.gtfs.schedule.type.*;
+import lombok.NoArgsConstructor;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.Month;
+import java.util.*;
+
+/**
+ * Test builder to set up a GTFS schedule for testing purposes.
+ *
+ * Simple example schedule:
+ *
+ * u1 ------------------ u2
+ * | / |
+ * | / |
+ * | / |
+ * s1 ------- u6 ------- s2 ------- u3 ------- s3
+ * | / |
+ * | / |
+ * | / |
+ * u5 ------------------ u4
+ *
+ * Routes:
+ *
+ * - route1 - Everyday service, InterCity train from Other City to Different City via Main Station (s1, s2, s3)
+ * - route2 - Everyday service, Underground system covering six stops (u1, u2, u3, u4, u5, u6)
+ * - route3 - Weekday service, Bus between South-West, Main Station, and North-East (u5, s2, u2)
+ *
+ * Stations:
+ *
+ * - s1 - Other City (47.5, 7.5)
+ * - s2 - Main Station (47.5, 8.5)
+ * - s3 - Different City (47.5, 9.5)
+ *
+ * Underground:
+ *
+ * - u1 - North-West (47.6, 8.4)
+ * - u2 - North-East (47.6, 8.6)
+ * - u3 - East (47.5, 8.6)
+ * - u4 - South-East (47.4, 8.6)
+ * - u5 - South-West (47.4, 8.4)
+ * - u6 - West (47.5, 8.4)
+ *
+ *
+ * @author munterfi
+ */
+@NoArgsConstructor
+public class GtfsScheduleTestBuilder {
+
+ private static final int NO_HEADWAY = -1;
+ private static final Map STOPS = Map.of("s1", new Stop("s1", "Other City", 47.5, 7.5), "s2",
+ new Stop("s2", "Main Station", 47.5, 8.5), "s3", new Stop("s3", "Different City", 47.5, 9.5), "u1",
+ new Stop("u1", "North-West", 47.6, 8.4), "u2", new Stop("u2", "North-East", 47.6, 8.6), "u3",
+ new Stop("u3", "East", 47.5, 8.6), "u4", new Stop("u4", "South-East", 47.4, 8.6), "u5",
+ new Stop("u5", "South-West", 47.4, 8.4), "u6", new Stop("u6", "West", 47.5, 8.4));
+ private static final List ROUTES = List.of(
+ new Route("route1", "agency1", "IC", HierarchicalVehicleType.LONG_DISTANCE_TRAINS, 30, 60, 10, 60, 5,
+ List.of("s1", "s2", "s3")),
+ new Route("route2", "agency2", "UNDERGROUND", HierarchicalVehicleType.SUBURBAN_RAILWAY, 5, 10, 10, 3, 1,
+ List.of("u1", "u2", "u3", "u4", "u5", "u6")),
+ new Route("route3", "agency2", "BUS", DefaultRouteType.BUS, 15, NO_HEADWAY, 3, 5, 1,
+ List.of("u5", "s2", "s2")));
+ private final Set addedStops = new HashSet<>();
+ private final GtfsScheduleBuilder builder = GtfsSchedule.builder();
+
+ public GtfsScheduleTestBuilder withAddAgency() {
+ builder.addAgency("agency1", "National Transit", "https://nationaltransit.example.com", "Europe/Zurich");
+ builder.addAgency("agency2", "City Transit", "https://citytransit.example.com", "Europe/Zurich");
+ return this;
+ }
+
+ public GtfsScheduleTestBuilder withAddCalendars() {
+ builder.addCalendar("weekdays", EnumSet.range(DayOfWeek.MONDAY, DayOfWeek.FRIDAY), Validity.PERIOD_START,
+ Validity.PERIOD_END)
+ .addCalendar("weekends", EnumSet.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY), Validity.PERIOD_START,
+ Validity.PERIOD_END);
+ return this;
+ }
+
+ public GtfsScheduleTestBuilder withAddCalendarDates() {
+ // change service to sunday
+ builder.addCalendarDate("weekdays", Moments.HOLIDAY, ExceptionType.REMOVED);
+ builder.addCalendarDate("weekends", Moments.HOLIDAY, ExceptionType.ADDED);
+ // no service
+ builder.addCalendarDate("weekdays", Moments.NO_SERVICE, ExceptionType.REMOVED);
+ return this;
+ }
+
+ public GtfsScheduleTestBuilder withAddInterCity() {
+ addRoute(ROUTES.getFirst(), true, true);
+ return this;
+ }
+
+ public GtfsScheduleTestBuilder withAddUnderground() {
+ addRoute(ROUTES.get(1), true, false);
+ return this;
+ }
+
+ public GtfsScheduleTestBuilder withAddBus() {
+ addRoute(ROUTES.get(2), false, true);
+ return this;
+ }
+
+ public GtfsSchedule build() {
+ return builder.build();
+ }
+
+ private void addRoute(Route route, boolean everydayService, boolean bidirectional) {
+ builder.addRoute(route.id, route.agencyId, route.name, route.name + "long", route.routeType);
+ addStops(route);
+ addTrips(route, true, false);
+ if (everydayService) {
+ addTrips(route, false, false);
+ }
+ if (bidirectional) {
+ addTrips(route, true, true);
+ if (everydayService) {
+ addTrips(route, false, true);
+ }
+ }
+ }
+
+ private void addTrips(Route route, boolean weekday, boolean reverse) {
+ final int travelTime = route.travelTime * 60;
+ final int dwellTime = route.dwellTime * 60;
+ final int headway = weekday ? route.headwayWeekday * 60 : route.headwayWeekend * 60;
+ final List routeStops = new ArrayList<>(route.stops);
+ String weekdayPostfix = weekday ? "wd" : "we";
+ String directionPostfix = "f";
+ if (reverse) {
+ Collections.reverse(routeStops);
+ directionPostfix = "r";
+ }
+ int tripCount = 0;
+ for (int tripDepartureTime = Validity.SERVICE_DAY_START.getTotalSeconds() + route.offset * 60; tripDepartureTime <= Validity.SERVICE_DAY_END.getTotalSeconds(); tripDepartureTime += headway) {
+ String tripId = String.format("%s_%s_%s_%s", route.id, weekdayPostfix, directionPostfix, ++tripCount);
+ builder.addTrip(tripId, route.id, weekday ? "weekdays" : "weekends");
+ int departureTime = tripDepartureTime;
+ for (String stopId : routeStops) {
+ builder.addStopTime(tripId, stopId, new ServiceDayTime(departureTime - dwellTime),
+ new ServiceDayTime(departureTime));
+ departureTime += travelTime + dwellTime;
+ }
+ }
+ }
+
+ private void addStops(Route route) {
+ for (String stopId : route.stops) {
+ if (!addedStops.contains(stopId)) {
+ Stop stop = STOPS.get(stopId);
+ builder.addStop(stop.id, stop.id, stop.lat, stop.lon);
+ addedStops.add(stopId);
+ }
+ }
+ }
+
+ record Stop(String id, String name, double lat, double lon) {
+ }
+
+ record Route(String id, String agencyId, String name, RouteType routeType, int headwayWeekday, int headwayWeekend,
+ int offset, int travelTime, int dwellTime, List stops) {
+ }
+
+ public static final class Validity {
+ public static final ServiceDayTime SERVICE_DAY_START = new ServiceDayTime(4, 0, 0);
+ public static final ServiceDayTime SERVICE_DAY_END = new ServiceDayTime(25, 0, 0);
+ public static final LocalDate PERIOD_START = LocalDate.of(2024, Month.JANUARY, 1);
+ public static final LocalDate PERIOD_END = LocalDate.of(2024, Month.DECEMBER, 31);
+ }
+
+ public static final class Moments {
+ public static final LocalDateTime WEEKDAY_8_AM = LocalDateTime.of(2024, Month.APRIL, 26, 8, 0);
+ public static final LocalDateTime WEEKDAY_12_PM = LocalDateTime.of(2024, Month.APRIL, 26, 23, 59);
+ public static final LocalDateTime WEEKEND_8_AM = LocalDateTime.of(2024, Month.APRIL, 27, 8, 0);
+ public static final LocalDate NO_SERVICE = LocalDate.of(2024, Month.MAY, 1);
+ public static final LocalDate HOLIDAY = LocalDate.of(2024, Month.DECEMBER, 25);
+ }
+}
diff --git a/src/test/java/ch/naviqore/gtfs/schedule/model/GtfsScheduleTestExtension.java b/src/test/java/ch/naviqore/gtfs/schedule/model/GtfsScheduleTestExtension.java
new file mode 100644
index 00000000..d3ca9ffe
--- /dev/null
+++ b/src/test/java/ch/naviqore/gtfs/schedule/model/GtfsScheduleTestExtension.java
@@ -0,0 +1,24 @@
+package ch.naviqore.gtfs.schedule.model;
+
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolver;
+
+/**
+ * Extension for JUnit 5 tests for injecting GtfsScheduleTestBuilder instances. This extension allows test methods to
+ * receive a GtfsScheduleTestBuilder instance as a parameter.
+ *
+ * @author munterfi
+ */
+public class GtfsScheduleTestExtension implements ParameterResolver {
+
+ @Override
+ public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
+ return parameterContext.getParameter().getType().equals(GtfsScheduleTestBuilder.class);
+ }
+
+ @Override
+ public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
+ return new GtfsScheduleTestBuilder();
+ }
+}
diff --git a/src/test/java/ch/naviqore/raptor/GtfsRoutePartitionerTest.java b/src/test/java/ch/naviqore/raptor/GtfsRoutePartitionerTest.java
new file mode 100644
index 00000000..858f092e
--- /dev/null
+++ b/src/test/java/ch/naviqore/raptor/GtfsRoutePartitionerTest.java
@@ -0,0 +1,45 @@
+package ch.naviqore.raptor;
+
+import ch.naviqore.gtfs.schedule.model.*;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@ExtendWith(GtfsScheduleTestExtension.class)
+class GtfsRoutePartitionerTest {
+
+ private GtfsSchedule schedule;
+ private GtfsRoutePartitioner partitioner;
+
+ @BeforeEach
+ void setUp(GtfsScheduleTestBuilder builder) {
+ schedule = builder.withAddAgency()
+ .withAddCalendars()
+ .withAddCalendarDates()
+ .withAddInterCity()
+ .withAddUnderground()
+ .withAddBus()
+ .build();
+ partitioner = new GtfsRoutePartitioner(schedule);
+ }
+
+ @Test
+ void getSubRoutes() {
+ assertThat(partitioner.getSubRoutes(schedule.getRoutes().get("route1"))).as("SubRoutes").hasSize(2);
+ assertThat(partitioner.getSubRoutes(schedule.getRoutes().get("route2"))).as("SubRoutes").hasSize(1);
+ assertThat(partitioner.getSubRoutes(schedule.getRoutes().get("route3"))).as("SubRoutes").hasSize(2);
+ }
+
+ @Test
+ void getSubRoute() {
+ for (Route route : schedule.getRoutes().values()) {
+ for (Trip trip : route.getTrips()) {
+ GtfsRoutePartitioner.SubRoute subRoute = partitioner.getSubRoute(trip);
+ assertThat(subRoute).as("SubRoute for trip ID " + trip.getId() + " in route " + route.getId())
+ .isNotNull();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/ch/naviqore/raptor/GtfsToRaptorConverterIT.java b/src/test/java/ch/naviqore/raptor/GtfsToRaptorConverterIT.java
index a3e803bd..2f1dcbc4 100644
--- a/src/test/java/ch/naviqore/raptor/GtfsToRaptorConverterIT.java
+++ b/src/test/java/ch/naviqore/raptor/GtfsToRaptorConverterIT.java
@@ -13,6 +13,8 @@
import java.nio.file.Path;
import java.time.LocalDate;
+import static org.assertj.core.api.Assertions.assertThat;
+
class GtfsToRaptorConverterIT {
private static final LocalDate DATE = LocalDate.of(2009, 4, 26);
@@ -26,7 +28,8 @@ void setUp(@TempDir Path tempDir) throws IOException {
@Test
void shouldConvertGtfsScheduleToRaptor() {
- GtfsToRaptorConverter mapper = new GtfsToRaptorConverter(Raptor.builder());
- Raptor raptor = mapper.convert(schedule, DATE);
+ GtfsToRaptorConverter mapper = new GtfsToRaptorConverter(schedule);
+ Raptor raptor = mapper.convert(DATE);
+ assertThat(raptor).isNotNull();
}
}
\ No newline at end of file