Skip to content

Commit

Permalink
Added a test for single file skipped validators.
Browse files Browse the repository at this point in the history
Reformatted the output
  • Loading branch information
jcpitre committed Sep 14, 2023
1 parent 101cee8 commit 28f2988
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,11 @@ private static <T> Constructor<T> chooseConstructor(Class<T> validatorClass)
validatorClass.getCanonicalName()));
}

/** Instantiates a validator of given class and injects its dependencies. */
/**
* Instantiates a validator of given class and injects its dependencies. A dependency is typically
* a table that is used by the validator. If any of the dependencies have errors, we put this
* information in the returned {@link ValidatorWithDependencyStatus}.
*/
private static <T> ValidatorWithDependencyStatus<T> createValidator(
Class<T> clazz, DependencyResolver dependencyResolver) throws ReflectiveOperationException {
Constructor<T> chosenConstructor;
Expand Down Expand Up @@ -246,6 +250,13 @@ public DependencyResolver(
this.feedContainer = feedContainer;
}

/**
* This is typically called to obtain the container related to each parameter in a validator's
* constructor or a basic type related to country code or date.
*
* @param parameterClass The parameter of the constructor we want to examine.
* @return
*/
public Object resolveDependency(Class<?> parameterClass) {
if (feedContainer != null && parameterClass.isAssignableFrom(GtfsFeedContainer.class)) {
if (!feedContainer.isParsedSuccessfully()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.mobilitydata.gtfsvalidator.notice.*;
import org.mobilitydata.gtfsvalidator.parsing.CsvHeader;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntity;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestFileValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestSingleFileValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableDescriptor;
import org.mobilitydata.gtfsvalidator.validator.FileValidator;
import org.mobilitydata.gtfsvalidator.validator.GtfsFieldValidator;
Expand Down Expand Up @@ -128,7 +128,7 @@ public void parsableTableRows() {
var testTableDescriptor = new GtfsTestTableDescriptor();
when(validatorProvider.getTableHeaderValidator()).thenReturn(mock(TableHeaderValidator.class));
when(validatorProvider.getFieldValidator()).thenReturn(mock(GtfsFieldValidator.class));
GtfsTestFileValidator validator = mock(GtfsTestFileValidator.class);
GtfsTestSingleFileValidator validator = mock(GtfsTestSingleFileValidator.class);
ArgumentCaptor<Consumer<Class<? extends FileValidator>>> captor =
ArgumentCaptor.forClass(Consumer.class);
when(validatorProvider.createSingleFileValidators(ArgumentMatchers.any(), captor.capture()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntity;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestFileValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestSingleFileValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableContainer;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableDescriptor;
import org.mobilitydata.gtfsvalidator.testgtfs.WholeFeedValidator;
Expand All @@ -26,7 +26,9 @@
public class GtfsFeedLoaderTest {
private static final ImmutableList<Class<?>> VALIDATOR_CLASSES =
ImmutableList.of(
GtfsTestEntityValidator.class, GtfsTestFileValidator.class, WholeFeedValidator.class);
GtfsTestEntityValidator.class,
GtfsTestSingleFileValidator.class,
WholeFeedValidator.class);

private MockGtfs mockGtfs;
private NoticeContainer noticeContainer = new NoticeContainer();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2021 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.testgtfs;

import javax.inject.Inject;
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
import org.mobilitydata.gtfsvalidator.validator.FileValidator;

public class GtfsTestMultiFileValidator extends FileValidator {

private final GtfsTestTableContainer table;
private final GtfsTestTableContainer2 unparsableTable;

@Inject
public GtfsTestMultiFileValidator(GtfsTestTableContainer table, GtfsTestTableContainer2 table2) {
this.table = table;
this.unparsableTable = table2;
}

@Override
public void validate(NoticeContainer noticeContainer) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
import org.mobilitydata.gtfsvalidator.validator.FileValidator;

public class GtfsTestFileValidator extends FileValidator {
public class GtfsTestSingleFileValidator extends FileValidator {

private final GtfsTestTableContainer table;
private final CountryCode countryCode;
private final CurrentDateTime currentDateTime;

@Inject
public GtfsTestFileValidator(
public GtfsTestSingleFileValidator(
GtfsTestTableContainer table, CountryCode countryCode, CurrentDateTime currentDateTime) {
this.table = table;
this.countryCode = countryCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2021 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.testgtfs;

import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
import org.mobilitydata.gtfsvalidator.parsing.CsvHeader;
import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer;

// We need a second test table class to test multi file validators.
public class GtfsTestTableContainer2 extends GtfsTableContainer<GtfsTestEntity> {
private static final ImmutableList<String> KEY_COLUMN_NAMES =
ImmutableList.of(GtfsTestEntity.ID_FIELD_NAME);

private List<GtfsTestEntity> entities;

private GtfsTestTableContainer2(
GtfsTestTableDescriptor2 descriptor, CsvHeader header, List<GtfsTestEntity> entities) {
super(descriptor, TableStatus.PARSABLE_HEADERS_AND_ROWS, header);
this.entities = entities;
}

public GtfsTestTableContainer2(TableStatus tableStatus) {
super(new GtfsTestTableDescriptor2(), tableStatus, CsvHeader.EMPTY);
this.entities = new ArrayList<>();
}

@Override
public Class<GtfsTestEntity> getEntityClass() {
return GtfsTestEntity.class;
}

@Override
public String gtfsFilename() {
return GtfsTestEntity.FILENAME + "2";
}

@Override
public List<GtfsTestEntity> getEntities() {
return entities;
}

/** Creates a table with given header and entities */
public static GtfsTestTableContainer2 forHeaderAndEntities(
GtfsTestTableDescriptor2 descriptor,
CsvHeader header,
List<GtfsTestEntity> entities,
NoticeContainer noticeContainer) {
GtfsTestTableContainer2 table = new GtfsTestTableContainer2(descriptor, header, entities);
return table;
}

@Override
public ImmutableList<String> getKeyColumnNames() {
return KEY_COLUMN_NAMES;
}

@Override
public Optional<GtfsTestEntity> byTranslationKey(String recordId, String recordSubId) {
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.mobilitydata.gtfsvalidator.testgtfs;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Optional;
import org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum;
import org.mobilitydata.gtfsvalidator.notice.NoticeContainer;
import org.mobilitydata.gtfsvalidator.parsing.CsvHeader;
import org.mobilitydata.gtfsvalidator.parsing.FieldCache;
import org.mobilitydata.gtfsvalidator.parsing.RowParser;
import org.mobilitydata.gtfsvalidator.table.*;

// We need a second test table descriptor to test multi file contaioners
public class GtfsTestTableDescriptor2 extends GtfsTableDescriptor<GtfsTestEntity> {
@Override
public GtfsTableContainer createContainerForInvalidStatus(
GtfsTableContainer.TableStatus tableStatus) {
return new GtfsTestTableContainer2(tableStatus);
}

@Override
public GtfsTableContainer createContainerForHeaderAndEntities(
CsvHeader header, List<GtfsTestEntity> entities, NoticeContainer noticeContainer) {
return GtfsTestTableContainer2.forHeaderAndEntities(this, header, entities, noticeContainer);
}

@Override
public GtfsEntityBuilder createEntityBuilder() {
return new GtfsTestEntity.Builder();
}

@Override
public Class getEntityClass() {
return GtfsTestEntity.class;
}

@Override
public ImmutableList<GtfsColumnDescriptor> getColumns() {
ImmutableList.Builder<GtfsColumnDescriptor> builder = ImmutableList.builder();
builder.add(
GtfsColumnDescriptor.builder()
.setColumnName(GtfsTestEntity.ID_FIELD_NAME)
.setHeaderRequired(true)
.setHeaderRecommended(false)
.setFieldLevel(FieldLevelEnum.REQUIRED)
.setIsMixedCase(false)
.setIsCached(false)
.build());
builder.add(
GtfsColumnDescriptor.builder()
.setColumnName(GtfsTestEntity.CODE_FIELD_NAME)
.setHeaderRequired(false)
.setHeaderRecommended(false)
.setFieldLevel(FieldLevelEnum.OPTIONAL)
.setIsMixedCase(false)
.setIsCached(false)
.build());
return builder.build();
}

@Override
public ImmutableMap<String, GtfsFieldLoader> getFieldLoaders() {
ImmutableMap.Builder<String, GtfsFieldLoader> builder = ImmutableMap.builder();
builder.put(
GtfsTestEntity.ID_FIELD_NAME,
new GtfsFieldLoader<GtfsTestEntity.Builder, String>() {
@Override
public void load(
RowParser rowParser,
int columnIndex,
GtfsColumnDescriptor columnDescriptor,
FieldCache<String> fieldCache,
GtfsTestEntity.Builder builder) {
builder.setId(
addToCacheIfPresent(rowParser.asId(columnIndex, columnDescriptor), fieldCache));
}
});
builder.put(
GtfsTestEntity.CODE_FIELD_NAME,
new GtfsFieldLoader<GtfsTestEntity.Builder, String>() {
@Override
public void load(
RowParser rowParser,
int columnIndex,
GtfsColumnDescriptor columnDescriptor,
FieldCache<String> fieldCache,
GtfsTestEntity.Builder builder) {
builder.setCode(
addToCacheIfPresent(rowParser.asText(columnIndex, columnDescriptor), fieldCache));
}
});
return builder.build();
}

@Override
public String gtfsFilename() {
return GtfsTestEntity.FILENAME + "2";
}

@Override
public boolean isRecommended() {
return false;
}

@Override
public boolean isRequired() {
return true;
}

@Override
public Optional<Integer> maxCharsPerColumn() {
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer.TableStatus;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntity;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestFileValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestMultiFileValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestSingleFileValidator;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableContainer;
import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableContainer2;
import org.mobilitydata.gtfsvalidator.testgtfs.WholeFeedValidator;

@RunWith(JUnit4.class)
Expand All @@ -29,7 +31,7 @@ public void testCreateValidators() throws ValidatorLoaderException {
ValidatorLoader.createForClasses(
ImmutableList.of(
GtfsTestEntityValidator.class,
GtfsTestFileValidator.class,
GtfsTestSingleFileValidator.class,
WholeFeedValidator.class)));

GtfsTestTableContainer tableContainer =
Expand All @@ -52,7 +54,7 @@ public void testCreateValidators() throws ValidatorLoaderException {
tableContainer, singleFileValidatorsWithParsingErrors::add)
.stream()
.map(Object::getClass))
.containsExactly(GtfsTestFileValidator.class);
.containsExactly(GtfsTestSingleFileValidator.class);

List<Class<? extends FileValidator>> skippedValidators = new ArrayList<>();
assertThat(
Expand All @@ -70,18 +72,36 @@ public void testCreateValidators_skippedValidators() throws ValidatorLoaderExcep
ValidatorLoader.createForClasses(
ImmutableList.of(
GtfsTestEntityValidator.class,
GtfsTestFileValidator.class,
GtfsTestMultiFileValidator.class,
GtfsTestSingleFileValidator.class,
WholeFeedValidator.class)));

// Our table had invalid data!
// Create 2 tables, one with errors and the other not.
// This will let us test the multi-file validator.
GtfsTestTableContainer tableContainer = new GtfsTestTableContainer(TableStatus.UNPARSABLE_ROWS);
GtfsFeedContainer feedContainer = new GtfsFeedContainer(ImmutableList.of(tableContainer));
GtfsTestTableContainer2 tableContainer2 =
new GtfsTestTableContainer2(TableStatus.PARSABLE_HEADERS_AND_ROWS);

List<Class<? extends FileValidator>> multiFileValidatorsWithParsingErrors = new ArrayList<>();
assertThat(
provider.createMultiFileValidators(
feedContainer, multiFileValidatorsWithParsingErrors::add))
GtfsFeedContainer feedContainer =
new GtfsFeedContainer(ImmutableList.of(tableContainer, tableContainer2));

List<Class<? extends FileValidator>> skippedValidators = new ArrayList<>();
// First test the multi file validators. Apparently the FeedContainerValidator is considered a
// multi-file validator.
// We should not be able to create any validator since the dependant file container has parsing
// errors. For the WholeFeedValidator the feedContainer is also in error since one of its
// file is in error.
assertThat(provider.createMultiFileValidators(feedContainer, skippedValidators::add)).isEmpty();
// And the 2 validators should be skipped
assertThat(skippedValidators)
.containsExactly(WholeFeedValidator.class, GtfsTestMultiFileValidator.class);

skippedValidators.clear();
// Try with the single file validator. We should not be able to build any validator since the
// file has errors.
assertThat(provider.createSingleFileValidators(tableContainer, skippedValidators::add))
.isEmpty();
assertThat(multiFileValidatorsWithParsingErrors).containsExactly(WholeFeedValidator.class);
// And it should tell us that the single file validator was skipped
assertThat(skippedValidators).containsExactly(GtfsTestSingleFileValidator.class);
}
}
Loading

0 comments on commit 28f2988

Please sign in to comment.