use of edu.usf.cutr.gtfsrtvalidator.lib.model.helper.ErrorListHelperModel in project gtfs-realtime-validator by CUTR-at-USF.
the class TestUtils method assertResults.
/**
* Asserts that for a given map of rules to expected number of warnings/errors (expected) and
* error/warning results (results), there should be a certain number of errors warnings for each rule. There should
* be 0 errors/warnings for all other rules not included in the map. In expected, the key is the
* ValidationRule, and the value is the number of expected warnings/errors for that rule.
*
* @param expected A map of the ValidationRules to the number of expected warnings/errors for each rule. If a ValidationRule isn't included in this map, it is expected that there are 0 errors/warnings for that rule.
* @param results list of errors or warnings output from validation
*/
public static void assertResults(@NotNull Map<ValidationRule, Integer> expected, @NotNull List<ErrorListHelperModel> results) {
if (expected == null) {
throw new IllegalArgumentException("expected cannot be null - it must be a list of expected errors or warnings");
}
if (results == null) {
throw new IllegalArgumentException("results cannot be null - it must be a list of actual errors or warnings");
}
// We need to create a map of actual results to actual count, so we can loop through
Map<ValidationRule, Integer> actual = new HashMap<>();
/**
* First, confirm that all actual count for all rules in results match the expected count
*/
for (ErrorListHelperModel error : results) {
// Save the actual count to a map for quick access in the next FOR loop
ValidationRule rule = error.getErrorMessage().getValidationRule();
Integer actualCount = error.getOccurrenceList().size();
actual.put(rule, actualCount);
// Get the expected count for this rule
Integer expectedCount = expected.get(rule);
if (expectedCount != null) {
// Make sure we have expected number of errors/warnings
assertEquals(expectedCount, actualCount);
} else {
// Make sure there aren't any errors/warnings for this rule, as it wasn't in the expected HashMap
assertEquals(0, actualCount.intValue());
}
}
/**
* Second, make sure that all expected counts for all rules in expected match the actual count. We need this loop
* to make sure that there isn't an expected rule in expected that's not included in results.
*/
for (Map.Entry<ValidationRule, Integer> entry : expected.entrySet()) {
ValidationRule rule = entry.getKey();
Integer expectedCount = entry.getValue();
// Get the actual count for this rule
Integer actualCount = actual.get(rule);
if (actualCount != null) {
// Make sure we have expected number of errors/warnings for this rule
assertEquals(actualCount, expectedCount);
} else {
// We're expecting errors/warnings for a rule that wasn't included in the actual results
fail("Expected " + expectedCount + " occurrences for " + rule.getErrorId() + " but found 0 occurrences in actual results");
}
}
}
use of edu.usf.cutr.gtfsrtvalidator.lib.model.helper.ErrorListHelperModel in project gtfs-realtime-validator by CUTR-at-USF.
the class VehicleValidator method validate.
@Override
public List<ErrorListHelperModel> validate(long currentTimeMillis, GtfsDaoImpl gtfsData, GtfsMetadata gtfsMetadata, GtfsRealtime.FeedMessage feedMessage, GtfsRealtime.FeedMessage previousFeedMessage, GtfsRealtime.FeedMessage combinedFeedMessage) {
List<GtfsRealtime.FeedEntity> entityList = feedMessage.getEntityList();
List<OccurrenceModel> e026List = new ArrayList<>();
List<OccurrenceModel> e027List = new ArrayList<>();
List<OccurrenceModel> e028List = new ArrayList<>();
List<OccurrenceModel> e029List = new ArrayList<>();
List<OccurrenceModel> w002List = new ArrayList<>();
List<OccurrenceModel> w004List = new ArrayList<>();
List<OccurrenceModel> e052List = new ArrayList<>();
HashSet<String> vehicleIds = new HashSet<>(entityList.size());
for (GtfsRealtime.FeedEntity entity : entityList) {
if (entity.hasTripUpdate()) {
GtfsRealtime.TripUpdate tripUpdate = entity.getTripUpdate();
if (StringUtils.isEmpty(tripUpdate.getVehicle().getId())) {
// W002 - vehicle_id not populated
RuleUtils.addOccurrence(W002, getTripId(entity, tripUpdate), w002List, _log);
}
}
if (entity.hasVehicle()) {
GtfsRealtime.VehiclePosition v = entity.getVehicle();
if (StringUtils.isEmpty(v.getVehicle().getId())) {
// W002 - vehicle_id not populated
RuleUtils.addOccurrence(W002, "entity ID " + entity.getId(), w002List, _log);
} else {
if (vehicleIds.contains(v.getVehicle().getId())) {
// E052 - vehicle.id is not unique
RuleUtils.addOccurrence(E052, "entity ID " + entity.getId() + " has vehicle.id " + v.getVehicle().getId(), e052List, _log);
} else {
vehicleIds.add(v.getVehicle().getId());
}
}
if (v.hasPosition() && v.getPosition().hasSpeed()) {
if (v.getPosition().getSpeed() > MAX_REALISTIC_SPEED_METERS_PER_SECOND || v.getPosition().getSpeed() < 0f) {
// W004 - vehicle speed is unrealistic
String prefix = getVehicleId(entity, v) + " speed of " + v.getPosition().getSpeed() + " m/s (" + String.format("%.2f", GtfsUtils.toMilesPerHour(v.getPosition().getSpeed())) + " mph)";
RuleUtils.addOccurrence(W004, prefix, w004List, _log);
}
}
if (v.hasPosition()) {
GtfsRealtime.Position position = v.getPosition();
String id = getVehicleId(entity, v);
if (!position.hasLatitude() || !position.hasLongitude()) {
// E026 - Invalid vehicle position - missing lat/long
RuleUtils.addOccurrence(E026, id + " position is missing lat/long", e026List, _log);
} else if (!GtfsUtils.isPositionValid(position)) {
// E026 - Invalid vehicle position - invalid lat/long
RuleUtils.addOccurrence(E026, id + " has latitude/longitude of (" + position.getLatitude() + "," + position.getLongitude() + ")", e026List, _log);
} else {
// Position is valid - check E028, if it lies within the agency bounds, using shapes.txt if it exists
boolean insideBounds = checkE028(entity, gtfsMetadata, e028List);
if (insideBounds) {
// Position is within agency bounds - check E029, if it lies within the trip bounds using shapes.txt
checkE029(entityList, entity, gtfsMetadata, e029List);
}
}
if (!GtfsUtils.isBearingValid(position)) {
// E027 - Invalid vehicle bearing
RuleUtils.addOccurrence(E027, id + " has bearing of " + position.getBearing(), e027List, _log);
}
}
}
}
List<ErrorListHelperModel> errors = new ArrayList<>();
if (!e026List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E026), e026List));
}
if (!e027List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E027), e027List));
}
if (!e028List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E028), e028List));
}
if (!e029List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E029), e029List));
}
if (!w002List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(W002), w002List));
}
if (!w004List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(W004), w004List));
}
if (!e052List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E052), e052List));
}
return errors;
}
use of edu.usf.cutr.gtfsrtvalidator.lib.model.helper.ErrorListHelperModel in project gtfs-realtime-validator by CUTR-at-USF.
the class StopValidator method validate.
@Override
public List<ErrorListHelperModel> validate(long currentTimeMillis, GtfsDaoImpl gtfsData, GtfsMetadata gtfsMetadata, GtfsRealtime.FeedMessage feedMessage, GtfsRealtime.FeedMessage previousFeedMessage, GtfsRealtime.FeedMessage combinedFeedMessage) {
List<OccurrenceModel> e011List = new ArrayList<>();
List<OccurrenceModel> e015List = new ArrayList<>();
List<GtfsRealtime.FeedEntity> allEntities = feedMessage.getEntityList();
// Checks all of the RT feeds entities and checks if matching stop_ids are available in the GTFS feed
for (GtfsRealtime.FeedEntity entity : allEntities) {
String entityId = entity.getId();
if (entity.hasTripUpdate()) {
GtfsRealtime.TripUpdate tripUpdate = entity.getTripUpdate();
List<GtfsRealtime.TripUpdate.StopTimeUpdate> stopTimeUpdateList = tripUpdate.getStopTimeUpdateList();
for (GtfsRealtime.TripUpdate.StopTimeUpdate stopTimeUpdate : stopTimeUpdateList) {
if (stopTimeUpdate.hasStopId()) {
String prefix = "trip_id " + tripUpdate.getTrip().getTripId() + " stop_id " + stopTimeUpdate.getStopId();
if (!gtfsMetadata.getStopIds().contains(stopTimeUpdate.getStopId())) {
// E011 - All stop_ids referenced in GTFS-rt feed must appear in the GTFS feed
RuleUtils.addOccurrence(E011, prefix, e011List, _log);
}
Integer locationType = gtfsMetadata.getStopToLocationTypeMap().get(stopTimeUpdate.getStopId());
if (locationType != null && locationType != 0) {
// E015 - All stop_ids referenced in GTFS-rt feeds must have the location_type = 0
RuleUtils.addOccurrence(E015, prefix, e015List, _log);
}
}
}
}
if (entity.hasVehicle()) {
GtfsRealtime.VehiclePosition v = entity.getVehicle();
if (v.hasStopId()) {
if (!gtfsMetadata.getStopIds().contains(v.getStopId())) {
// E011 - All stop_ids referenced in GTFS-rt feed must appear in the GTFS feed
String prefix = (v.hasVehicle() && v.getVehicle().hasId() ? "vehicle_id " + v.getVehicle().getId() + " " : "") + "stop_id " + v.getStopId();
RuleUtils.addOccurrence(E011, prefix, e011List, _log);
}
Integer locationType = gtfsMetadata.getStopToLocationTypeMap().get(v.getStopId());
if (locationType != null && locationType != 0) {
// E015 - All stop_ids referenced in GTFS-rt feeds must have the location_type = 0
String prefix = (v.hasVehicle() && v.getVehicle().hasId() ? "vehicle_id " + v.getVehicle().getId() + " " : "") + "stop_id " + v.getStopId();
RuleUtils.addOccurrence(E015, prefix, e015List, _log);
}
}
}
if (entity.hasAlert()) {
List<GtfsRealtime.EntitySelector> informedEntityList = entity.getAlert().getInformedEntityList();
for (GtfsRealtime.EntitySelector entitySelector : informedEntityList) {
if (entitySelector.hasStopId()) {
String prefix = "alert entity ID " + entityId + " stop_id " + entitySelector.getStopId();
if (!gtfsMetadata.getStopIds().contains(entitySelector.getStopId())) {
// E011 - All stop_ids referenced in GTFS-rt feed must appear in the GTFS feed
RuleUtils.addOccurrence(E011, prefix, e011List, _log);
}
Integer locationType = gtfsMetadata.getStopToLocationTypeMap().get(entitySelector.getStopId());
if (locationType != null && locationType != 0) {
// E015 - All stop_ids referenced in GTFS-rt feeds must have the location_type = 0
RuleUtils.addOccurrence(E015, prefix, e015List, _log);
}
}
}
}
}
List<ErrorListHelperModel> errors = new ArrayList<>();
if (!e011List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E011), e011List));
}
if (!e015List.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E015), e015List));
}
return errors;
}
use of edu.usf.cutr.gtfsrtvalidator.lib.model.helper.ErrorListHelperModel in project gtfs-realtime-validator by CUTR-at-USF.
the class TripDescriptorValidator method validate.
@Override
public List<ErrorListHelperModel> validate(long currentTimeMillis, GtfsDaoImpl gtfsData, GtfsMetadata gtfsMetadata, GtfsRealtime.FeedMessage feedMessage, GtfsRealtime.FeedMessage previousFeedMessage, GtfsRealtime.FeedMessage combinedFeedMessage) {
List<OccurrenceModel> errorListE003 = new ArrayList<>();
List<OccurrenceModel> errorListE004 = new ArrayList<>();
List<OccurrenceModel> errorListE016 = new ArrayList<>();
List<OccurrenceModel> errorListE020 = new ArrayList<>();
List<OccurrenceModel> errorListE021 = new ArrayList<>();
List<OccurrenceModel> errorListE023 = new ArrayList<>();
List<OccurrenceModel> errorListE024 = new ArrayList<>();
List<OccurrenceModel> errorListE030 = new ArrayList<>();
List<OccurrenceModel> errorListE031 = new ArrayList<>();
List<OccurrenceModel> errorListE032 = new ArrayList<>();
List<OccurrenceModel> errorListE033 = new ArrayList<>();
List<OccurrenceModel> errorListE034 = new ArrayList<>();
List<OccurrenceModel> errorListE035 = new ArrayList<>();
List<OccurrenceModel> errorListW006 = new ArrayList<>();
List<OccurrenceModel> errorListW009 = new ArrayList<>();
// Check the route_id values against the values from the GTFS feed
for (GtfsRealtime.FeedEntity entity : feedMessage.getEntityList()) {
if (entity.hasTripUpdate()) {
GtfsRealtime.TripUpdate tripUpdate = entity.getTripUpdate();
if (!tripUpdate.getTrip().hasTripId()) {
checkW006(entity, tripUpdate.getTrip(), errorListW006);
} else {
String tripId = tripUpdate.getTrip().getTripId();
Trip trip = gtfsMetadata.getTrips().get(tripId);
if (trip == null) {
if (!GtfsUtils.isAddedTrip(tripUpdate.getTrip())) {
// Trip isn't in GTFS data and isn't an ADDED trip - E003
RuleUtils.addOccurrence(E003, GtfsUtils.getTripId(entity, tripUpdate), errorListE003, _log);
}
} else {
if (GtfsUtils.isAddedTrip(tripUpdate.getTrip())) {
// Trip is in GTFS data and is an ADDED trip - E016
RuleUtils.addOccurrence(E016, GtfsUtils.getTripId(entity, tripUpdate), errorListE016, _log);
}
if (tripUpdate.getTrip().hasStartTime()) {
checkE023(tripUpdate, tripUpdate.getTrip(), gtfsMetadata, errorListE023);
}
}
}
if (tripUpdate.getTrip().hasStartTime()) {
checkE020(tripUpdate, tripUpdate.getTrip(), errorListE020);
}
checkE021(tripUpdate, tripUpdate.getTrip(), errorListE021);
checkE004(tripUpdate, tripUpdate.getTrip(), gtfsMetadata, errorListE004);
checkE024(tripUpdate, tripUpdate.getTrip(), gtfsMetadata, errorListE024);
checkE035(entity, tripUpdate.getTrip(), gtfsMetadata, errorListE035);
boolean foundW009 = false;
List<GtfsRealtime.TripUpdate.StopTimeUpdate> stopTimeUpdateList = tripUpdate.getStopTimeUpdateList();
for (GtfsRealtime.TripUpdate.StopTimeUpdate stopTimeUpdate : stopTimeUpdateList) {
// Only flag one occurrence of W009 for stop_time_update per trip to avoid flooding the database
if (!foundW009) {
checkW009(entity, stopTimeUpdate, errorListW009);
if (!errorListW009.isEmpty()) {
foundW009 = true;
}
}
}
if (tripUpdate.hasTrip()) {
checkW009(entity, tripUpdate.getTrip(), errorListW009);
}
}
if (entity.hasVehicle() && entity.getVehicle().hasTrip()) {
GtfsRealtime.TripDescriptor trip = entity.getVehicle().getTrip();
if (!trip.hasTripId()) {
checkW006(entity, trip, errorListW006);
} else {
String tripId = trip.getTripId();
if (!StringUtils.isEmpty(tripId)) {
Trip gtfsTrip = gtfsMetadata.getTrips().get(tripId);
if (gtfsTrip == null) {
if (!GtfsUtils.isAddedTrip(trip)) {
// E003 - Trip isn't in GTFS data and isn't an ADDED trip
RuleUtils.addOccurrence(E003, "vehicle_id " + entity.getVehicle().getVehicle().getId() + " trip_id " + tripId, errorListE003, _log);
}
} else {
if (GtfsUtils.isAddedTrip(trip)) {
// E016 - Trip is in GTFS data and is an ADDED trip
RuleUtils.addOccurrence(E016, "vehicle_id " + entity.getVehicle().getVehicle().getId() + " trip_id " + tripId, errorListE016, _log);
}
if (trip.hasStartTime()) {
checkE023(entity.getVehicle(), trip, gtfsMetadata, errorListE023);
}
}
}
}
if (trip.hasStartTime()) {
checkE020(entity.getVehicle(), trip, errorListE020);
}
checkE004(entity.getVehicle(), trip, gtfsMetadata, errorListE004);
checkE021(entity.getVehicle(), trip, errorListE021);
checkE024(entity.getVehicle(), trip, gtfsMetadata, errorListE024);
checkE035(entity, trip, gtfsMetadata, errorListE035);
checkW009(entity, trip, errorListW009);
}
if (entity.hasAlert()) {
GtfsRealtime.Alert alert = entity.getAlert();
List<GtfsRealtime.EntitySelector> entitySelectors = alert.getInformedEntityList();
if (entitySelectors != null && entitySelectors.size() > 0) {
for (GtfsRealtime.EntitySelector entitySelector : entitySelectors) {
checkE033(entity, entitySelector, errorListE033);
checkE034(entity, entitySelector, gtfsMetadata, errorListE034);
checkE035(entity, entitySelector.getTrip(), gtfsMetadata, errorListE035);
if (entitySelector.hasRouteId() && entitySelector.hasTrip()) {
checkE030(entity, entitySelector, gtfsMetadata, errorListE030);
checkE031(entity, entitySelector, errorListE031);
}
if (entitySelector.hasTrip()) {
checkW006(entity, entitySelector.getTrip(), errorListW006);
checkW009(entity, entitySelector.getTrip(), errorListW009);
}
}
} else {
// E032 - Alert does not have an informed_entity
RuleUtils.addOccurrence(E032, "alert ID " + entity.getId() + " does not have an informed_entity", errorListE032, _log);
}
}
}
List<ErrorListHelperModel> errors = new ArrayList<>();
if (!errorListE003.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E003), errorListE003));
}
if (!errorListE004.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E004), errorListE004));
}
if (!errorListE016.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E016), errorListE016));
}
if (!errorListE020.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E020), errorListE020));
}
if (!errorListE021.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E021), errorListE021));
}
if (!errorListE023.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E023), errorListE023));
}
if (!errorListE024.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E024), errorListE024));
}
if (!errorListE030.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E030), errorListE030));
}
if (!errorListE031.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E031), errorListE031));
}
if (!errorListE032.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E032), errorListE032));
}
if (!errorListE033.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E033), errorListE033));
}
if (!errorListE034.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E034), errorListE034));
}
if (!errorListE035.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(E035), errorListE035));
}
if (!errorListW006.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(W006), errorListW006));
}
if (!errorListW009.isEmpty()) {
errors.add(new ErrorListHelperModel(new MessageLogModel(W009), errorListW009));
}
return errors;
}
use of edu.usf.cutr.gtfsrtvalidator.lib.model.helper.ErrorListHelperModel in project gtfs-realtime-validator by CUTR-at-USF.
the class BatchTest method testBatchProcessing.
@Test
public void testBatchProcessing() throws IOException, NoSuchAlgorithmException {
// Run batch validation on the bundled USF Bull Runner GTFS and GTFS-realtime data
BatchProcessor.Builder builder = new BatchProcessor.Builder("src/test/resources/bullrunner-gtfs.zip", "src/test/resources/");
BatchProcessor processor = builder.build();
processor.processFeeds();
// Read in validation results for GTFS-realtime bullrunner-vehicle-positions file
ObjectMapper mapper = new ObjectMapper();
ErrorListHelperModel[] allErrorLists = mapper.readValue(new File("src/test/resources/bullrunner-vehicle-positions" + BatchProcessor.RESULTS_FILE_EXTENSION), ErrorListHelperModel[].class);
// We should have 3 warnings - W001, W006, and W009, with 10 occurrences each.
// If running on Travis we may have another warning, W008, due to timestamp being older than 65 seconds
assertTrue(allErrorLists.length == 3 || allErrorLists.length == 4);
for (ErrorListHelperModel model : allErrorLists) {
switch(model.getErrorMessage().getValidationRule().getErrorId()) {
case "W001":
assertEquals(10, model.getOccurrenceList().size());
break;
case "W006":
assertEquals(10, model.getOccurrenceList().size());
break;
case "W008":
assertEquals(1, model.getOccurrenceList().size());
break;
case "W009":
assertEquals(10, model.getOccurrenceList().size());
break;
}
}
}
Aggregations