/* * 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: 5419 $ */ 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; /** the maximum different for attribute values. */ protected double m_MaxDiffValues; /** the maximum different for attribute weights. */ protected double m_MaxDiffWeights; /** whether to check the header when comparing datasets. */ protected boolean m_CheckHeader; /** whether to compare the attribute values as string. */ protected boolean m_CompareValuesAsString; /** * 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. * * @return the filename */ 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 (m_CheckHeader) { if (!data2.equalHeaders(data1)) { throw new Exception("header has been modified\n" + data2.equalHeadersMsg(data1)); } } 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 (m_CompareValuesAsString) { if (!orig.toString(j).equals(copy.toString(j))) { throw new Exception("instances have changed"); } } else { if (Math.abs(orig.value(j) - copy.value(j)) > m_MaxDiffValues) { throw new Exception("instances have changed"); } } } if (Math.abs(orig.weight() - copy.weight()) > m_MaxDiffWeights) { 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(); // how to compare datasets // see compareDatasets(Instances,Instances) m_MaxDiffValues = 0.0; m_MaxDiffWeights = 0.0; m_CheckHeader = true; m_CompareValuesAsString = false; 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. * * @throws Exception if fails */ 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()); } } }