Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Validation for conditionally required/forbidden fare_rules.txt file. #1261

Closed
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Each Notice is associated with a severity: `INFO`, `WARNING`, `ERROR`.
| [`empty_column_name`](#empty_column_name) | A column name is empty. |
| [`empty_file`](#empty_file) | A CSV file is empty. |
| [`equal_shape_distance_diff_coordinates`](#equal_shape_distance_diff_coordinates) | Two consecutive points have equal `shape_dist_traveled` and different lat/lon coordinates in `shapes.txt`. |
| [`forbidden_file`](#forbidden_file) | A conditionally forbidden file is present in the feed. |
bdferris-v2 marked this conversation as resolved.
Show resolved Hide resolved
| [`foreign_key_violation`](#foreign_key_violation) | Wrong foreign key. |
| [`inconsistent_agency_timezone`](#inconsistent_agency_timezone) | Inconsistent Timezone among agencies. |
| [`invalid_color`](#invalid_color) | A field contains an invalid color value. |
Expand Down Expand Up @@ -184,6 +185,26 @@ Trips with the same block id have overlapping stop times.

</details>

<a name="ForbiddenFileNotice"/>

### forbidden_file

A conditionally forbidden file is present in the feed.
bdferris-v2 marked this conversation as resolved.
Show resolved Hide resolved

#### References
* [GTFS terms definition](https://gtfs.org/reference/static/#term-definitions)
<details>

#### Notice fields description
| Field name | Description | Type |
|-------------- |-------------------------------- |-------- |
| `filename` | The name of the forbidden file. | String |

#### Affected files
[All GTFS files supported by the specification.](http://gtfs.org/reference/static#dataset-files)

</details>

<a name="CsvParsingFailedNotice"/>

### csv_parsing_failed
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.mobilitydata.gtfsvalidator.notice;

/**
* A conditionally forbidden file is present in the feed.
*
* <p>Severity: {@code SeverityLevel.ERROR}
*/
public class ForbiddenFileNotice extends ValidationNotice {
private final String filename;

public ForbiddenFileNotice(String filename) {
super(SeverityLevel.ERROR);
this.filename = filename;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.mobilitydata.gtfsvalidator.validator;

import javax.inject.Inject;
import org.mobilitydata.gtfsvalidator.notice.ForbiddenFileNotice;
import org.mobilitydata.gtfsvalidator.notice.MissingRequiredFileNotice;
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
import org.mobilitydata.gtfsvalidator.table.GtfsFareAttributeTableContainer;
import org.mobilitydata.gtfsvalidator.table.GtfsFareRuleTableContainer;

public class FaresV1FileValidator extends FileValidator {

private final GtfsFareAttributeTableContainer fareAttributeTable;
private final GtfsFareRuleTableContainer fareRuleTable;

@Inject
public FaresV1FileValidator(
GtfsFareAttributeTableContainer fareAttributeTable,
GtfsFareRuleTableContainer fareRuleTable) {
this.fareAttributeTable = fareAttributeTable;
this.fareRuleTable = fareRuleTable;
}

@Override
public void validate(NoticeContainer noticeContainer) {
if (!fareAttributeTable.isMissingFile() && fareRuleTable.isMissingFile()) {
noticeContainer.addValidationNotice(
new MissingRequiredFileNotice(fareRuleTable.gtfsFilename()));
isabelle-dr marked this conversation as resolved.
Show resolved Hide resolved
} else if (fareAttributeTable.isMissingFile() && !fareRuleTable.isMissingFile()) {
noticeContainer.addValidationNotice(new ForbiddenFileNotice(fareRuleTable.gtfsFilename()));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package org.mobilitydata.gtfsvalidator.validator;

import static com.google.common.truth.Truth.assertThat;

import junit.framework.TestCase;
import org.junit.Test;
import org.mobilitydata.gtfsvalidator.notice.ForbiddenFileNotice;
import org.mobilitydata.gtfsvalidator.notice.MissingRequiredFileNotice;
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
import org.mobilitydata.gtfsvalidator.table.GtfsFareAttributeTableContainer;
import org.mobilitydata.gtfsvalidator.table.GtfsFareRuleTableContainer;
import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer.TableStatus;

public class FaresV1FileValidatorTest extends TestCase {

private NoticeContainer noticeContainer = new NoticeContainer();

@Test
public void testFareAttributesPresentAndFareRulesPresent() {
new FaresV1FileValidator(
new GtfsFareAttributeTableContainer(TableStatus.PARSABLE_HEADERS_AND_ROWS),
new GtfsFareRuleTableContainer(TableStatus.PARSABLE_HEADERS_AND_ROWS))
.validate(noticeContainer);
assertThat(noticeContainer.getValidationNotices()).isEmpty();
}

@Test
public void testFareAttributesPresentAndFareRulesPresentByEmpty() {
// We still consider an empty file to be "present".
new FaresV1FileValidator(
new GtfsFareAttributeTableContainer(TableStatus.EMPTY_FILE),
new GtfsFareRuleTableContainer(TableStatus.EMPTY_FILE))
.validate(noticeContainer);
assertThat(noticeContainer.getValidationNotices()).isEmpty();
}

@Test
public void testFareAttributesMissingAndFareRulesMissing() {
new FaresV1FileValidator(
new GtfsFareAttributeTableContainer(TableStatus.MISSING_FILE),
new GtfsFareRuleTableContainer(TableStatus.MISSING_FILE))
.validate(noticeContainer);
assertThat(noticeContainer.getValidationNotices()).isEmpty();
}

@Test
public void testFareAttributesPresentButFareRulesMissing() {
new FaresV1FileValidator(
new GtfsFareAttributeTableContainer(TableStatus.PARSABLE_HEADERS_AND_ROWS),
new GtfsFareRuleTableContainer(TableStatus.MISSING_FILE))
.validate(noticeContainer);
assertThat(noticeContainer.getValidationNotices())
.containsExactly(new MissingRequiredFileNotice("fare_rules.txt"));
}

@Test
public void testFareAttributesMissingButFareRulesPresent() {
new FaresV1FileValidator(
new GtfsFareAttributeTableContainer(TableStatus.MISSING_FILE),
new GtfsFareRuleTableContainer(TableStatus.PARSABLE_HEADERS_AND_ROWS))
.validate(noticeContainer);
assertThat(noticeContainer.getValidationNotices())
.containsExactly(new ForbiddenFileNotice("fare_rules.txt"));
}
}