/*
* Copyright 2014
* Ubiquitous Knowledge Processing (UKP) Lab
* Technische Universität Darmstadt
*
* 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 de.tudarmstadt.ukp.dkpro.core.testing;
import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
import static org.apache.uima.fit.factory.CollectionReaderFactory.createReaderDescription;
import static org.apache.uima.fit.factory.ConfigurationParameterFactory.canParameterBeSet;
import static org.apache.uima.fit.factory.ConfigurationParameterFactory.getParameterSettings;
import static org.apache.uima.fit.factory.ConfigurationParameterFactory.setParameter;
import static org.apache.uima.fit.pipeline.SimplePipeline.runPipeline;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_component.AnalysisComponent;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.collection.CollectionReader;
import org.apache.uima.collection.CollectionReaderDescription;
import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;
import de.tudarmstadt.ukp.dkpro.core.api.parameter.ComponentParameters;
import de.tudarmstadt.ukp.dkpro.core.testing.dumper.CasDumpWriter;
import de.tudarmstadt.ukp.dkpro.core.testing.validation.CasValidator;
import de.tudarmstadt.ukp.dkpro.core.testing.validation.Message;
public class IOTestRunner
{
private static final String RESOURCE_COLLECTION_READER_BASE = "de.tudarmstadt.ukp.dkpro.core.api.io.ResourceCollectionReaderBase";
private static final String JCAS_FILE_WRITER_IMPL_BASE = "de.tudarmstadt.ukp.dkpro.core.api.io.JCasFileWriter_ImplBase";
public static void testRoundTrip(Class<? extends CollectionReader> aReader,
Class<? extends AnalysisComponent> aWriter, String aFile)
throws Exception
{
testOneWay(createReaderDescription(aReader), createEngineDescription(aWriter), aFile, aFile);
}
public static void testRoundTrip(Class<? extends CollectionReader> aReader,
Class<? extends AnalysisComponent> aWriter, String aFile, TestOptions aOptions)
throws Exception
{
testOneWay(createReaderDescription(aReader), createEngineDescription(aWriter), aFile,
aFile, aOptions);
}
public static void testRoundTrip(CollectionReaderDescription aReader,
AnalysisEngineDescription aWriter, String aFile, TestOptions aOptions)
throws Exception
{
testOneWay(aReader, aWriter, aFile, aFile, aOptions);
}
public static void testRoundTrip(CollectionReaderDescription aReader,
AnalysisEngineDescription aWriter, String aFile)
throws Exception
{
testOneWay(aReader, aWriter, aFile, aFile);
}
public static void testOneWay(Class<? extends CollectionReader> aReader, String aExpectedFile,
String aFile)
throws Exception
{
testOneWay(createReaderDescription(aReader), aExpectedFile, aFile);
}
public static void testOneWay(CollectionReaderDescription aReader, String aExpectedFile,
String aFile)
throws Exception
{
testOneWay(aReader, aExpectedFile, aFile, null);
}
/**
* One-way test reading a file and writing to the same format but comparing against a reference
* file instead of the original file.
*
* @param aReader
* reader to read the data.
* @param aExpectedFile
* expected file.
* @param aFile
* input file.
* @param aOptions
* test options.
* @throws Exception
* if there was an error.
*/
public static void testOneWay(CollectionReaderDescription aReader, String aExpectedFile,
String aFile, TestOptions aOptions)
throws Exception
{
String outputFolder = StringUtils.substringAfterLast(aReader.getImplementationName(), ".")
+ "-" + FilenameUtils.getBaseName(aFile);
if (DkproTestContext.get() != null) {
outputFolder = DkproTestContext.get().getTestOutputFolderName();
}
File output = new File("target/test-output/" + outputFolder + "/dump.txt");
AnalysisEngineDescription writer = createEngineDescription(
CasDumpWriter.class, CasDumpWriter.PARAM_TARGET_LOCATION, output,
CasDumpWriter.PARAM_SORT, true);
testOneWay2(aReader, writer, aExpectedFile, "dump.txt", aFile, aOptions);
}
public static void testOneWay(Class<? extends CollectionReader> aReader,
Class<? extends AnalysisComponent> aWriter, String aExpectedFile, String aFile)
throws Exception
{
testOneWay(aReader, aWriter, aExpectedFile, aFile, null);
}
public static void testOneWay(Class<? extends CollectionReader> aReader,
Class<? extends AnalysisComponent> aWriter, String aExpectedFile, String aFile,
TestOptions aOptions)
throws Exception
{
Class<?> dkproReaderBase = Class.forName(RESOURCE_COLLECTION_READER_BASE);
if (!dkproReaderBase.isAssignableFrom(aReader)) {
throw new IllegalArgumentException("Reader must be a subclass of ["
+ RESOURCE_COLLECTION_READER_BASE + "]");
}
Class<?> dkproWriterBase = Class.forName(JCAS_FILE_WRITER_IMPL_BASE);
if (!dkproWriterBase.isAssignableFrom(aWriter)) {
throw new IllegalArgumentException("writer must be a subclass of ["
+ JCAS_FILE_WRITER_IMPL_BASE + "]");
}
// We assume that the writer is creating a file with the same extension as is provided as
// the expected file
String extension = FilenameUtils.getExtension(aExpectedFile);
String name = FilenameUtils.getBaseName(aFile);
Object[] aExtraParams = {};
testOneWay2(createReaderDescription(aReader, aExtraParams),
createEngineDescription(aWriter, aExtraParams), aExpectedFile, name + "."
+ extension, aFile, aOptions);
}
public static void testOneWay(CollectionReaderDescription aReader,
AnalysisEngineDescription aWriter, String aExpectedFile, String aFile)
throws Exception
{
testOneWay(aReader, aWriter, aExpectedFile, aFile, null);
}
public static void testOneWay(CollectionReaderDescription aReader,
AnalysisEngineDescription aWriter, String aExpectedFile, String aFile, TestOptions aOptions)
throws Exception
{
Class<?> dkproReaderBase = Class.forName(RESOURCE_COLLECTION_READER_BASE);
if (!dkproReaderBase.isAssignableFrom(Class.forName(aReader.getImplementationName()))) {
throw new IllegalArgumentException("Reader must be a subclass of ["
+ RESOURCE_COLLECTION_READER_BASE + "]");
}
Class<?> dkproWriterBase = Class.forName(JCAS_FILE_WRITER_IMPL_BASE);
if (!dkproWriterBase.isAssignableFrom(Class.forName(aWriter.getAnnotatorImplementationName()))) {
throw new IllegalArgumentException("writer must be a subclass of ["
+ JCAS_FILE_WRITER_IMPL_BASE + "]");
}
// We assume that the writer is creating a file with the same extension as is provided as
// the expected file
String extension = FilenameUtils.getExtension(aExpectedFile);
String name = FilenameUtils.getBaseName(aFile);
testOneWay2(aReader, aWriter, aExpectedFile, name + "." + extension, aFile, aOptions);
}
@Deprecated
public static void testOneWay2(Class<? extends CollectionReader> aReader,
Class<? extends AnalysisComponent> aWriter, String aExpectedFile, String aOutputFile,
String aFile, Object... aExtraParams)
throws Exception
{
testOneWay2(createReaderDescription(aReader, aExtraParams),
createEngineDescription(aWriter, aExtraParams),
aExpectedFile, aOutputFile, aFile, null);
}
public static void testOneWay2(CollectionReaderDescription aReader,
AnalysisEngineDescription aWriter, String aExpectedFile, String aOutputFile,
String aInputFile, TestOptions aOptions)
throws Exception
{
String outputFolder = StringUtils.substringAfterLast(aReader.getImplementationName(), ".")
+ "-" + FilenameUtils.getBaseName(aInputFile);
if (DkproTestContext.get() != null) {
outputFolder = DkproTestContext.get().getTestOutputFolderName();
}
File reference = new File("src/test/resources/" + aExpectedFile);
File input = new File("src/test/resources/" + aInputFile);
File output = new File("target/test-output/" + outputFolder);
setParameter(aReader, ComponentParameters.PARAM_SOURCE_LOCATION, input);
if (canParameterBeSet(aWriter, ComponentParameters.PARAM_STRIP_EXTENSION)) {
setParameter(aWriter, ComponentParameters.PARAM_STRIP_EXTENSION, true);
}
if (canParameterBeSet(aWriter, "overwrite")) {
setParameter(aWriter, "overwrite", true);
}
if (!getParameterSettings(aWriter).containsKey(ComponentParameters.PARAM_TARGET_LOCATION)) {
setParameter(aWriter, ComponentParameters.PARAM_TARGET_LOCATION, output);
}
AnalysisEngineDescription metadataStripper = createEngineDescription(
DocumentMetaDataStripper.class);
AnalysisEngineDescription validator = createEngineDescription(
Validator.class);
Validator.options = aOptions != null ? aOptions : new TestOptions();
runPipeline(aReader, validator, metadataStripper, aWriter);
AssertAnnotations.assertValid(Validator.messages);
if (aOptions == null || aOptions.resultAssertor == null) {
String expected = FileUtils.readFileToString(reference, "UTF-8");
String actual = FileUtils.readFileToString(new File(output, aOutputFile), "UTF-8");
assertEquals(expected.trim(), actual.trim());
}
else {
aOptions.resultAssertor.accept(reference, new File(output, aOutputFile));
}
}
public static class Validator
extends JCasAnnotator_ImplBase
{
public static List<Message> messages;
public static TestOptions options;
@Override
public void initialize(UimaContext aContext)
throws ResourceInitializationException
{
super.initialize(aContext);
messages = new ArrayList<>();
}
@Override
public void process(JCas aJCas)
throws AnalysisEngineProcessException
{
CasValidator validator = CasValidator.createWithAllChecks();
options.skippedChecks.forEach(check -> validator.removeCheck(check));
messages = validator.analyze(aJCas);
}
}
}