// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.testutil; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.util.zip.GZIPOutputStream; import org.junit.Assert; import org.junit.rules.TemporaryFolder; import org.openstreetmap.osmosis.core.OsmosisConstants; import org.openstreetmap.osmosis.core.OsmosisRuntimeException; /** * Provides re-usable functionality for utilising data files within junit tests. * * @author Brett Henderson */ public class TestDataUtilities extends TemporaryFolder { private static final Charset UTF8 = Charset.forName("UTF-8"); /** * Obtains the data file with the specified name. The name is a path * relative to the data input directory. The returned file will have any * occurrences of %VERSION% replaced with the current version. * * @param dataFileName * The name of the data file to be loaded. * @return The file object pointing to the data file. */ public File createDataFile(String dataFileName) { try { BufferedReader dataReader; BufferedWriter dataWriter; File tmpFile; String line; // Open the data template file. dataReader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream( "/data/template/" + dataFileName), UTF8)); // Create a temporary file and open it. tmpFile = newFile(); dataWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tmpFile), UTF8)); // Copy all data into the temp file replacing the version string. while ((line = dataReader.readLine()) != null) { line = line.replace("%VERSION%", OsmosisConstants.VERSION); dataWriter.write(line); dataWriter.newLine(); } dataReader.close(); dataWriter.close(); return tmpFile; } catch (IOException e) { throw new OsmosisRuntimeException("Unable to build test data file " + dataFileName, e); } } /** * Obtains the data file with the specified name. The name is a path * relative to the data input directory. * * @param systemPropertyName * The system property to use for getting the file name. If this * doesn't exist, the dataFileName is used instead. * @param dataFileName * The name of the data file to be loaded. * @return The file object pointing to the data file. */ public File createDataFile(String systemPropertyName, String dataFileName) { String fileName; // Get the filename from the system property if it exists. fileName = System.getProperty(systemPropertyName); if (fileName != null) { return new File(fileName); } // No system property is available so use the provided file name. return createDataFile(dataFileName); } private void copyFiles(File from, File to) throws IOException { byte[] buffer; int bytesRead; BufferedInputStream isFrom; BufferedOutputStream osTo; buffer = new byte[4096]; isFrom = new BufferedInputStream(new FileInputStream(from)); osTo = new BufferedOutputStream(new FileOutputStream(to)); while ((bytesRead = isFrom.read(buffer)) >= 0) { osTo.write(buffer, 0, bytesRead); } isFrom.close(); osTo.close(); } private void handleInequalFiles(File file1, File file2, long failureoffset) throws IOException { File file1Copy; File file2Copy; // We must create copies of the files because the originals will be // cleaned up at the completion of the test. file1Copy = File.createTempFile("junit", null); file2Copy = File.createTempFile("junit", null); copyFiles(file1, file1Copy); copyFiles(file2, file2Copy); Assert.fail("File " + file1Copy + " and file " + file2Copy + " are not equal at file offset " + failureoffset + "."); } /** * Validates the contents of two files for equality. * * @param file1 * The first file. * @param file2 * The second file. * @throws IOException * if an exception occurs. */ public void compareFiles(File file1, File file2) throws IOException { BufferedInputStream inStream1; BufferedInputStream inStream2; int byte1; int byte2; long offset; inStream1 = new BufferedInputStream(new FileInputStream(file1)); inStream2 = new BufferedInputStream(new FileInputStream(file2)); offset = 0; do { byte1 = inStream1.read(); byte2 = inStream2.read(); if (byte1 != byte2) { handleInequalFiles(file1, file2, offset); } offset++; } while (byte1 >= 0); inStream2.close(); inStream1.close(); } /** * Compresses the contents of a file into a new compressed file. * * @param inputFile * The uncompressed input file. * @param outputFile * The compressed output file to generate. * @throws IOException * if an exception occurs. */ public void compressFile(File inputFile, File outputFile) throws IOException { BufferedInputStream inStream; BufferedOutputStream outStream; byte[] buffer; int bytesRead; inStream = new BufferedInputStream(new FileInputStream(inputFile)); outStream = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(outputFile))); buffer = new byte[4096]; do { bytesRead = inStream.read(buffer); if (bytesRead > 0) { outStream.write(buffer, 0, bytesRead); } } while (bytesRead >= 0); outStream.close(); inStream.close(); } }