|
6 | 6 | import java.time.LocalDate; |
7 | 7 | import java.util.List; |
8 | 8 | import org.junit.Test; |
| 9 | +import org.mobilitydata.gtfsvalidator.input.DateForValidation; |
9 | 10 | import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; |
10 | 11 | import org.mobilitydata.gtfsvalidator.notice.ValidationNotice; |
11 | 12 | import org.mobilitydata.gtfsvalidator.table.GtfsCalendar; |
|
15 | 16 | import org.mobilitydata.gtfsvalidator.table.GtfsCalendarTableContainer; |
16 | 17 | import org.mobilitydata.gtfsvalidator.type.GtfsDate; |
17 | 18 | import org.mobilitydata.gtfsvalidator.util.ServiceIntervalCache; |
18 | | -import org.mobilitydata.gtfsvalidator.validator.ServiceGapValidator.BigGapInServiceNotice; |
| 19 | +import org.mobilitydata.gtfsvalidator.validator.ServiceSpreadValidator.BigGapInServiceNotice; |
| 20 | +import org.mobilitydata.gtfsvalidator.validator.ServiceSpreadValidator.ServiceExtendsFarInTheFutureNotice; |
19 | 21 |
|
20 | | -public class ServiceGapValidatorTest { |
| 22 | +public class ServiceSpreadValidatorTest { |
21 | 23 |
|
22 | 24 | private record CalendarMetadata( |
23 | 25 | String serviceId, String startDate, String endDate, boolean activeAllWeek) {} |
@@ -74,7 +76,9 @@ private static List<ValidationNotice> generateNotices( |
74 | 76 | GtfsCalendarDateTableContainer calendarDateTable = |
75 | 77 | GtfsCalendarDateTableContainer.forEntities(calendarDates, noticeContainer); |
76 | 78 |
|
77 | | - new ServiceGapValidator(new ServiceIntervalCache(), calendarTable, calendarDateTable) |
| 79 | + DateForValidation dateForValidation = new DateForValidation(LocalDate.of(2024, 1, 1)); |
| 80 | + new ServiceSpreadValidator( |
| 81 | + new ServiceIntervalCache(), dateForValidation, calendarTable, calendarDateTable) |
78 | 82 | .validate(noticeContainer); |
79 | 83 |
|
80 | 84 | return noticeContainer.getValidationNotices(); |
@@ -255,4 +259,89 @@ public void singleDayService_noNotice() { |
255 | 259 | ImmutableList.of(new CalendarMetadata("service_1", "20240101", "20240101", true))); |
256 | 260 | assertThat(notices).isEmpty(); |
257 | 261 | } |
| 262 | + |
| 263 | + @Test |
| 264 | + public void serviceEndFarInFuture_calendarOnly_generatesNotice() { |
| 265 | + // calendar.txt defines a service ending more than 2 years after the validation date |
| 266 | + // (2024-01-01). |
| 267 | + // Here endDate is 2026-02-01 (> 2 * 365 days after 2024-01-01), so exactly one |
| 268 | + // ServiceExtendsFarInTheFutureNotice should be emitted. We assert that there is one and only |
| 269 | + // one such notice with the expected data, allowing for any additional notices of other types. |
| 270 | + List<ValidationNotice> notices = |
| 271 | + generateNotices( |
| 272 | + ImmutableList.of( |
| 273 | + new CalendarMetadata("service_future_cal", "20240101", "20260201", true))); |
| 274 | + |
| 275 | + LocalDate end = LocalDate.of(2026, 2, 1); |
| 276 | + ValidationNotice expectedFutureNotice = |
| 277 | + new ServiceExtendsFarInTheFutureNotice("service_future_cal", end); |
| 278 | + |
| 279 | + List<ServiceExtendsFarInTheFutureNotice> futureNotices = |
| 280 | + notices.stream() |
| 281 | + .filter(ServiceExtendsFarInTheFutureNotice.class::isInstance) |
| 282 | + .map(ServiceExtendsFarInTheFutureNotice.class::cast) |
| 283 | + .toList(); |
| 284 | + |
| 285 | + assertThat(futureNotices).containsExactly(expectedFutureNotice); |
| 286 | + } |
| 287 | + |
| 288 | + @Test |
| 289 | + public void serviceEndFarInFuture_calendarDatesOnly_generatesNotice() { |
| 290 | + // No real range in calendar.txt (single day), service effectively defined by far future |
| 291 | + // SERVICE_ADDED in calendar_dates.txt. |
| 292 | + // Last added date is 2026-02-01 (> 2 years after 2024-01-01), so exactly one |
| 293 | + // ServiceExtendsFarInTheFutureNotice should be emitted for this service. There may also be |
| 294 | + // other notices of different types (e.g., BigGapInServiceNotice); we only assert that there |
| 295 | + // is one and only one future-extent notice with the expected data. |
| 296 | + List<ValidationNotice> notices = |
| 297 | + generateNotices( |
| 298 | + ImmutableList.of( |
| 299 | + new CalendarMetadata("service_future_cd", "20240101", "20240101", true)), |
| 300 | + ImmutableList.of( |
| 301 | + new CalendarDateMetadata( |
| 302 | + "service_future_cd", "20260201", GtfsCalendarDateExceptionType.SERVICE_ADDED))); |
| 303 | + |
| 304 | + LocalDate end = LocalDate.of(2026, 2, 1); |
| 305 | + ValidationNotice expectedFutureNotice = |
| 306 | + new ServiceExtendsFarInTheFutureNotice("service_future_cd", end); |
| 307 | + |
| 308 | + // Filter out only ServiceExtendsFarInTheFutureNotice instances. |
| 309 | + List<ServiceExtendsFarInTheFutureNotice> futureNotices = |
| 310 | + notices.stream() |
| 311 | + .filter(ServiceExtendsFarInTheFutureNotice.class::isInstance) |
| 312 | + .map(ServiceExtendsFarInTheFutureNotice.class::cast) |
| 313 | + .toList(); |
| 314 | + |
| 315 | + assertThat(futureNotices).containsExactly(expectedFutureNotice); |
| 316 | + } |
| 317 | + |
| 318 | + @Test |
| 319 | + public void serviceEndFarInFuture_calendarAndCalendarDates_generatesNotice() { |
| 320 | + // calendar.txt defines regular service through 2025-01-01. |
| 321 | + // calendar_dates.txt adds a single far-future SERVICE_ADDED date in 2026. Exactly one |
| 322 | + // ServiceExtendsFarInTheFutureNotice should be emitted for this service. There may be other |
| 323 | + // notices (e.g., BigGapInServiceNotice); we only assert that there is one and only one |
| 324 | + // future-extent notice with the expected data. |
| 325 | + List<ValidationNotice> notices = |
| 326 | + generateNotices( |
| 327 | + ImmutableList.of( |
| 328 | + new CalendarMetadata("service_future_both", "20240101", "20250101", true)), |
| 329 | + ImmutableList.of( |
| 330 | + new CalendarDateMetadata( |
| 331 | + "service_future_both", |
| 332 | + "20260201", |
| 333 | + GtfsCalendarDateExceptionType.SERVICE_ADDED))); |
| 334 | + |
| 335 | + LocalDate end = LocalDate.of(2026, 2, 1); |
| 336 | + ValidationNotice expectedFutureNotice = |
| 337 | + new ServiceExtendsFarInTheFutureNotice("service_future_both", end); |
| 338 | + |
| 339 | + List<ServiceExtendsFarInTheFutureNotice> futureNotices = |
| 340 | + notices.stream() |
| 341 | + .filter(ServiceExtendsFarInTheFutureNotice.class::isInstance) |
| 342 | + .map(ServiceExtendsFarInTheFutureNotice.class::cast) |
| 343 | + .toList(); |
| 344 | + |
| 345 | + assertThat(futureNotices).containsExactly(expectedFutureNotice); |
| 346 | + } |
258 | 347 | } |
0 commit comments