/**
* Copyright 2013 MIR@MU Project
*
* 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 cz.muni.fi.mir.mathmlcanonicalization.modules;
import cz.muni.fi.mir.mathmlcanonicalization.Settings;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.custommonkey.xmlunit.XMLTestCase;
import org.custommonkey.xmlunit.XMLUnit;
import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;
import org.junit.*;
import org.xml.sax.SAXException;
/**
* Abstract class to allow descendants to simple compare desired and produced
* XML documents by calling testXML method (tests idempotence by default)
*
* @author David Formanek
*/
@Ignore // no tests
abstract class AbstractModuleTest {
private static final Logger LOGGER = Logger.getLogger(
AbstractModuleTest.class.getName());
private boolean shouldPrintProcessed = true;
protected void setPrintProcessed(boolean shouldPrintProcessed) {
this.shouldPrintProcessed = shouldPrintProcessed;
}
protected void testXML(Module instance, String testFile) {
testXML(instance, testFile, true);
}
protected void testXML(Module instance, String testFile, boolean testIdempotence) {
final InputStream processed = getProcessed(instance, testFile, shouldPrintProcessed);
final InputStream canonical = getCanonical(testFile);
XMLUnit.setIgnoreWhitespace(true);
try {
new XMLTestCase() {
}.assertXMLEqual(getReader(canonical), getReader(processed));
} catch (SAXException ex) {
LOGGER.log(Level.SEVERE, "cannot compare XML streams", ex);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "problem with streams", ex);
}
if (testIdempotence) {
testIdempotence(instance, testFile);
}
}
protected void testIdempotence(Module instance, String testFile) {
final InputStream processed = getProcessed(instance, testFile, false);
final InputStream processedTwice = getProcessed(
instance, getProcessed(instance, testFile, false), false);
try {
new XMLTestCase() {
}.assertXMLEqual(getReader(processed), getReader(processedTwice));
} catch (SAXException ex) {
LOGGER.log(Level.SEVERE, "cannot compare XML streams", ex);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "problem with streams", ex);
}
}
private InputStream getProcessed(Module instance, String testFile, boolean shouldPrint) {
InputStream resourceStream = this.getClass().getResourceAsStream(testFile + ".original.xml");
return getProcessed(instance, resourceStream, shouldPrint);
}
/**
* Get input processed by specified module.
*
* @param instance a configured instance of the tested module
* @param in input stream with original XML document
* @return input stream with processed input
*/
private InputStream getProcessed(Module instance, InputStream in, boolean shouldPrint) {
if (instance instanceof StreamModule) {
return getProcessed((StreamModule) instance, in, shouldPrint);
} else if (instance instanceof DOMModule) {
return getProcessed((DOMModule) instance, in, shouldPrint);
} else {
throw new UnsupportedOperationException("Module type not supported");
}
}
private InputStream getProcessed(StreamModule instance, InputStream in, boolean shouldPrint) {
try {
ByteArrayOutputStream output = instance.execute(in);
if (shouldPrint) {
printDocument(output, "Output of " + instance);
}
return getInputStream(output);
} catch (ModuleException ex) {
Logger.getLogger(this.getClass().getName()).log(
Level.SEVERE, "cannot execute the module", ex);
return null;
}
}
private InputStream getProcessed(DOMModule instance, InputStream in, boolean shouldPrint) {
SAXBuilder builder = Settings.setupSAXBuilder();
Document doc;
XMLOutputter serializer = new XMLOutputter();
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
doc = builder.build(in);
instance.execute(doc);
serializer.output(doc, output);
} catch (JDOMException ex) {
Logger.getLogger(this.getClass().getName()).log(
Level.SEVERE, "cannot build document", ex);
} catch (IOException ex) {
Logger.getLogger(this.getClass().getName()).log(
Level.SEVERE, "cannot convert between stream and DOM", ex);
} catch (ModuleException ex) {
Logger.getLogger(this.getClass().getName()).log(
Level.SEVERE, "cannot execute the module", ex);
}
if (shouldPrint) {
printDocument(output, "Output of " + instance);
}
return getInputStream(output);
}
private InputStream getCanonical(String testFile) {
return this.getClass().getResourceAsStream(testFile + ".canonical.xml");
}
private InputStreamReader getReader(InputStream inputStream) {
return new InputStreamReader(inputStream);
}
private InputStream getInputStream(ByteArrayOutputStream output) {
return new ByteArrayInputStream(output.toByteArray());
}
private void printDocument(ByteArrayOutputStream output, String header) {
System.out.println(header);
System.out.println("--------------------");
try {
output.writeTo(System.out);
} catch (IOException ex) {
Logger.getLogger(this.getClass().getName()).log(
Level.WARNING, "cannot print result", ex);
}
System.out.println("--------------------");
System.out.println();
}
}