/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Copyright (C) 2006 University of Waikato
*/
package weka.core.converters;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.OptionHandler;
import weka.core.Utils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
/**
* Abstract Test class for file converters.
*
* @author FracPete (fracpete at waikato dot ac dot nz)
* @version $Revision: 1.2 $
*/
public abstract class AbstractFileConverterTest
extends AbstractConverterTest {
/** the filename used for the data in ARFF format */
protected String m_SourceFilename;
/** the filename used for loading/saving in the export file format */
protected String m_ExportFilename;
/** the command line options */
protected String[] m_CommandlineOptions;
/**
* Constructs the <code>AbstractFileConverterTest</code>. Called by
* subclasses.
*
* @param name the name of the test class
*/
public AbstractFileConverterTest(String name) {
super(name);
}
/**
* returns a filename in ARFF format which can be used for loading and saving
*/
protected String getSourceFilename() {
String result;
File file;
result = null;
try {
file = File.createTempFile("weka_core_converters", ".arff");
file.deleteOnExit();
result = file.getAbsolutePath();
}
catch (Exception e) {
result = null;
}
return result;
}
/**
* returns a filename in the export format which can be used for
* loading and saving
*
* @return the filename
*/
protected String getExportFilename() {
String result;
File file;
result = null;
try {
file = File.createTempFile(
"weka_core_converters",
((FileSourcedConverter) getLoader()).getFileExtension());
file.deleteOnExit();
result = file.getAbsolutePath();
}
catch (Exception e) {
result = null;
}
return result;
}
/**
* returns the command line options, either for the loader or the saver
*
* @param loader if true the options for the loader will be returned,
* otherwise the ones for the saver
* @return the command line options
*/
protected String[] getCommandlineOptions(boolean loader) {
if (loader)
return new String[]{m_ExportFilename};
else
return new String[]{"-i", m_SourceFilename, "-o", m_ExportFilename};
}
/**
* Compare two datasets to see if they differ.
*
* @param data1 one set of instances
* @param data2 the other set of instances
* @throws Exception if the datasets differ
*/
protected void compareDatasets(Instances data1, Instances data2)
throws Exception {
if (!data2.equalHeaders(data1)) {
throw new Exception("header has been modified");
}
if (!(data2.numInstances() == data1.numInstances())) {
throw new Exception("number of instances has changed");
}
for (int i = 0; i < data2.numInstances(); i++) {
Instance orig = data1.instance(i);
Instance copy = data2.instance(i);
for (int j = 0; j < orig.numAttributes(); j++) {
if (orig.isMissing(j)) {
if (!copy.isMissing(j)) {
throw new Exception("instances have changed");
}
} else if (orig.value(j) != copy.value(j)) {
throw new Exception("instances have changed");
}
if (orig.weight() != copy.weight()) {
throw new Exception("instance weights have changed");
}
}
}
}
/**
* Called by JUnit before each test method. This implementation creates
* the default loader/saver to test and generates a test set of Instances.
*
* @throws Exception if an error occurs reading the example instances.
*/
protected void setUp() throws Exception {
BufferedWriter writer;
super.setUp();
m_SourceFilename = getSourceFilename();
m_ExportFilename = getExportFilename();
// generate source file
writer = new BufferedWriter(new FileWriter(m_SourceFilename));
writer.write(m_Instances.toString());
writer.newLine();
writer.flush();
writer.close();
}
/**
* Called by JUnit after each test method
*/
protected void tearDown() throws Exception {
File file;
// delete temp. files
file = new File(m_SourceFilename);
if (file.exists())
file.delete();
file = new File(m_ExportFilename);
if (file.exists())
file.delete();
m_SourceFilename = null;
m_ExportFilename = null;
super.tearDown();
}
/**
* test the batch saving/loading (via setFile(File))
*/
public void testBatch() {
Instances data;
try {
// save
m_Saver.setInstances(m_Instances);
m_Saver.setFile(new File(m_ExportFilename));
m_Saver.writeBatch();
// load
((AbstractFileLoader) m_Loader).setFile(new File(m_ExportFilename));
data = m_Loader.getDataSet();
// compare data
try {
if (m_Instances.classIndex() != data.classIndex())
data.setClassIndex(m_Instances.classIndex());
compareDatasets(m_Instances, data);
}
catch (Exception e) {
fail("Incremental load failed (datasets differ): " + e.toString());
}
}
catch (Exception e) {
e.printStackTrace();
fail("Batch save/load failed: " + e.toString());
}
}
/**
* test the incremental loading (via setFile(File))
*/
public void testIncrementalLoader() {
Instance temp;
Instances data;
if (!(getLoader() instanceof IncrementalConverter))
return;
try {
// save
m_Saver.setInstances(m_Instances);
m_Saver.setFile(new File(m_ExportFilename));
m_Saver.writeBatch();
// load
((AbstractFileLoader) m_Loader).setFile(new File(m_ExportFilename));
data = new Instances(m_Loader.getStructure());
do {
temp = m_Loader.getNextInstance(data);
if (temp != null)
data.add(temp);
}
while (temp != null);
// compare data
try {
if (m_Instances.classIndex() != data.classIndex())
data.setClassIndex(m_Instances.classIndex());
compareDatasets(m_Instances, data);
}
catch (Exception e) {
fail("Incremental load failed (datasets differ): " + e.toString());
}
}
catch (Exception e) {
e.printStackTrace();
fail("Incremental load failed: " + e.toString());
}
}
/**
* test the incremental save (via setFile(File))
*/
public void testIncrementalSaver() {
int i;
File file;
if (!(getSaver() instanceof IncrementalConverter))
return;
try {
// remove output file if it exists
file = new File(m_ExportFilename);
if (file.exists())
file.delete();
// save
m_Saver.setFile(new File(m_ExportFilename));
m_Saver.setRetrieval(AbstractSaver.INCREMENTAL);
m_Saver.setStructure(new Instances(m_Instances, 0));
for (i = 0; i < m_Instances.numInstances(); i++) {
m_Saver.writeIncremental(m_Instances.instance(i));
}
m_Saver.writeIncremental(null);
}
catch (Exception e) {
e.printStackTrace();
fail("Incremental save failed: " + e.toString());
}
}
/**
* tests the commandline operation of the loader (via setFile(File)).
* does nothing currently, but can be overridden by derived classes.
*/
public void testLoaderCommandlineArgs() {
}
/**
* tests the commandline operation of the saver
*/
public void testSaverCommandlineArgs() {
String[] options;
options = getCommandlineOptions(false);
try {
((OptionHandler) m_Saver).setOptions(options);
}
catch (Exception e) {
e.printStackTrace();
fail("Command line test failed ('" + Utils.arrayToString(options) + "'): " + e.toString());
}
}
/**
* tests whether a URL can be loaded (via setURL(URL))
*/
public void testURLSourcedLoader() {
Instances data;
if (!(getLoader() instanceof URLSourcedLoader))
return;
try {
// save
m_Saver.setInstances(m_Instances);
m_Saver.setFile(new File(m_ExportFilename));
m_Saver.writeBatch();
// load
((URLSourcedLoader) m_Loader).setURL(new File(m_ExportFilename).toURL().toString());
data = m_Loader.getDataSet();
// compare data
try {
if (m_Instances.classIndex() != data.classIndex())
data.setClassIndex(m_Instances.classIndex());
compareDatasets(m_Instances, data);
}
catch (Exception e) {
fail("URL load failed (datasets differ): " + e.toString());
}
}
catch (Exception e) {
e.printStackTrace();
fail("URL load failed: " + e.toString());
}
}
/**
* tests whether data can be loaded via setSource() with a file stream
*/
public void testLoaderWithStream() {
Instances data;
try {
// save
m_Saver.setInstances(m_Instances);
m_Saver.setFile(new File(m_ExportFilename));
m_Saver.writeBatch();
// load
m_Loader.setSource(new FileInputStream(new File(m_ExportFilename)));
data = m_Loader.getDataSet();
// compare data
try {
if (m_Instances.classIndex() != data.classIndex())
data.setClassIndex(m_Instances.classIndex());
compareDatasets(m_Instances, data);
}
catch (Exception e) {
fail("File stream loading failed (datasets differ): " + e.toString());
}
}
catch (Exception e) {
e.printStackTrace();
fail("File stream loading failed: " + e.toString());
}
}
}