/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.io; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintStream; import java.io.RandomAccessFile; import xxl.core.functions.AbstractFunction; import xxl.core.functions.Function; import xxl.core.io.BufferedRandomAccessFile; import xxl.core.io.LRUBuffer; import xxl.core.io.NullOutputStream; import xxl.core.io.fat.FAT; import xxl.core.io.fat.FATDevice; import xxl.core.io.raw.RAFRawAccess; import xxl.core.io.raw.RawAccessRAF; import xxl.core.io.raw.RawAccessUtils; import xxl.core.util.WrappingRuntimeException; /** * Tests different kinds of RandomAccessFiles in xxl (raw-I/O, fat) * against the implementation of java. */ public class RAFTest { /** number of testoperations */ public static final int TEST_MAX_OPS = 48; /** Output directory */ public static String outDir = null; /** * Performs ops steps of the test of a RandomAccessFile. * @param ra RandomAccessFile which is tested. * @param ops Number of operations which are performed. * @return Values which are generated from the test as String * (can be compared with a test of a different RandomAccessFile). */ public static String makeRAFTest(RandomAccessFile ra, int ops) { StringBuffer s = new StringBuffer(); byte b[] = new byte[] {1,3,5,7,9,2,4,6,8,15}; byte b2[] = xxl.core.util.Arrays.newByteArray(1059,(byte)42); for (int i=1; i<=ops; i++) { long ret=0; try { int opnr=1; if (i==opnr++) ret = ra.getFilePointer(); if (i==opnr++) ra.setLength(712); if (i==opnr++) ret = ra.read(); // Reading at the start of the file if (i==opnr++) ra.seek(766); if (i==opnr++) ra.writeLong(42); if (i==opnr++) ra.writeDouble(777.3); if (i==opnr++) ra.writeFloat(4711.0f); if (i==opnr++) ra.writeInt(-1); if (i==opnr++) ra.writeShort(16222); if (i==opnr++) ra.writeBoolean(true); //10 if (i==opnr++) ra.seek(100000000); if (i==opnr++) ra.seek(100000); if (i==opnr++) ra.write(10); if (i==opnr++) ra.setLength(2000); if (i==opnr++) ret = ra.length(); if (i==opnr++) ret = ra.getFilePointer(); if (i==opnr++) ra.write(11); if (i==opnr++) ret = ra.length(); if (i==opnr++) ra.setLength(4000); if (i==opnr++) ret = ra.getFilePointer(); //20 if (i==opnr++) ra.write(12); if (i==opnr++) ret = ra.skipBytes(600); if (i==opnr++) ret = ra.length(); if (i==opnr++) ra.write(b); if (i==opnr++) ret = ra.length(); if (i==opnr++) ret = ra.skipBytes(3000); // File length is still 4000, filepos before 2000+1+1+600+10= 2612 --> skip goes beyond end of file if (i==opnr++) ret = ra.read(b); // -1 (Reading at the end of the file) if (i==opnr++) ret = ra.getFilePointer(); if (i==opnr++) ra.seek(4500); // Jump beyond the end of file if (i==opnr++) ret = ra.read(b); // exception! //30 if (i==opnr++) ra.seek(2602); if (i==opnr++) { ret = ra.read(b); s.append("value (should be 7):"+b[3]+" ret:"); } // write a 7 into the file if (i==opnr++) ra.seek(10000); if (i==opnr++) ra.setLength(8000); if (i==opnr++) ret = ra.getFilePointer(); if (i==opnr++) ret = ra.length(); if (i==opnr++) ra.seek(10000); if (i==opnr++) ra.setLength(12000); if (i==opnr++) ret = ra.getFilePointer(); if (i==opnr++) ret = ra.length(); //40 if (i==opnr++) ra.seek(766); if (i==opnr++) { s.append("value (should be 42):"+ra.readLong()+" ret:"); } if (i==opnr++) { s.append("value (should be 777.3):"+ra.readDouble()+" ret:"); } if (i==opnr++) { s.append("value (should be 4711.0):"+ra.readFloat()+" ret:"); } if (i==opnr++) { s.append("value (should be -1):"+ra.readInt()+" ret:"); } if (i==opnr++) { s.append("value (should be 16222):"+ra.readShort()+" ret:"); } if (i==opnr++) { s.append("value (should be true):"+ra.readBoolean()+" ret:"); } if (i==opnr++) ra.write(b2); s.append(ret+"\t"); // if (i%5==0) // s.append("\n"); } catch (IOException e) { s.append(e); } } // Protokolliere alle Rueckgabewerte und Exceptions und gebe diese fuer Vergleichszwecke zurueck. return s.toString(); } /** * Tests if the length operation on a RandomAccessFile throws an exception. * @param ra RandomAccessFile * @return true iff an exception was thrown by length. */ static boolean testLengthForEx(RandomAccessFile ra) { try { ra.length(); return false; } catch (IOException e) { return true; } } /** * Compares the content of two RandomAccessFiles. The files have to be open. * @param ra1 RandomAccessFile #1 * @param ra2 RandomAccessFile #2 * @return true iff the files are equal. */ public static boolean compareRAFs (RandomAccessFile ra1, RandomAccessFile ra2) { long pos = 0; int v1,v2; long l1=0,l2=0; boolean ex1=false, ex2=false; boolean equal = true; try { ex1 = testLengthForEx(ra1); ex2 = testLengthForEx(ra2); if (l1!=l2) { System.out.println("Files do not have the same length: l1="+l1+", l2="+l2); return false; } if (ex1!=ex2) { System.out.println("Exceptions have not been the same"); return false; } ra1.seek(0); ra2.seek(0); while (pos<ra1.length()) { ra2.seek(pos); v1 = ra1.read(); v2 = ra2.read(); if (v1!=v2) { System.out.println("Error at position: "+pos+", v1="+v1+", v2="+v2); return false; } pos++; } return equal; } catch (IOException e) { System.out.println("Error at position: "+pos); e.printStackTrace(); return false; } } /** Name of the dummyFile */ private static String dummyFileName = "testRAWdummyFile"; /** Fat device */ private static FATDevice fatdevice; /** Factory for RawAccessRAF */ private static Function GET_RAW_RAF = new AbstractFunction() { public Object invoke(Object o, Object create) { try { return new RawAccessRAF( new RAFRawAccess((String) o), ((Boolean)create).booleanValue(), new File(outDir+dummyFileName), true ); } catch (Exception e) { throw new WrappingRuntimeException(e); } } }; /** Factory for BufferedRandomAccessFile */ private static Function GET_BUFFERED_RAF = new AbstractFunction() { public Object invoke(Object o, Object create) { try { return new BufferedRandomAccessFile((String) o,"rw",new LRUBuffer(10),512); } catch (Exception e) { throw new WrappingRuntimeException(e); } } }; /** Factory for java-RandomAccessFile */ private static Function GET_RAF = new AbstractFunction() { public Object invoke(Object o, Object create) { try { return new RandomAccessFile((String) o,"rw"); } catch (Exception e) { throw new WrappingRuntimeException(e); } } }; /** Factory for fat.ExtendedRandomAccessFile */ private static Function GET_FAT_RAF = new AbstractFunction() { public Object invoke(Object o, Object create) { try { return fatdevice.getRandomAccessFile("testFileNumberOne.bin","rw"); } catch (Exception e) { throw new WrappingRuntimeException(e); } } }; /** * Tests a special RandomAccessFile against java.io.RandomAccessFile. * @param args To get a list of the parameters call the class with no parameters. */ public static void main(String args[]) { int testNr = 0; String testRAF1 = "testRAF"; String testRAF2 = "testRAW"; if (args.length==0) { System.out.println("Test RandomAccessFiles of xxl"); System.out.println("=============================\n"); System.out.println("Parameters: 1 or 4"); System.out.println("1. Number of the test (Default: 0)"); System.out.println(" 0: Test java against java"); System.out.println(" 1: Test java against RawAccessRAF"); System.out.println(" 2: Test java against BufferedRandomAccessFile"); System.out.println(" 3: Test java against fat.ExtendedRandomAccessFile"); System.out.println("2. Filename used for java.io.RandomAccessFile"); System.out.println("3. Filename used for the comparison RandomAccessFile"); System.out.println("4. Filename used for the dummy file for xxl.core.io.raw.RawAccessRAF\n"); System.out.println("The standard filenames for 2-4 are testRAF, testRAW and testRAWdummyFile. Filenames"); System.out.println("are relative to the output directory."); return; } else { testNr = Integer.parseInt(args[0]); if ((testNr<0) || (testNr>3)) { System.out.println("Value of first parameter out of range"); return; } if (args.length==4) { testRAF1 = args[1]; testRAF2 = args[2]; dummyFileName = args[3]; } else if (args.length!=1) { System.out.println("Number of parameters was wrong!"); return; } } System.out.println("Test number: "+testNr); outDir = Common.getOutPath(); System.out.println("Output path: "+outDir); boolean testExceptionHandling = false; Function referenceRAF=GET_RAF; Function testRAF=null; switch (testNr) { case 0: testRAF=GET_RAF; break; case 1: testRAF=GET_RAW_RAF; break; case 2: testRAF=GET_BUFFERED_RAF; break; case 3: testRAF=GET_FAT_RAF; break; } try { // construct dummy file for raw and fat new RandomAccessFile(outDir+dummyFileName,"rw").close(); RandomAccessFile ra1, ra2; boolean equal,succeeded=false; String s1=null,s2=null; if (testNr==3) { RawAccessUtils.createFileForRaw(outDir+testRAF2,1000); try { fatdevice = new FATDevice( "FAT", FAT.FAT12, new RAFRawAccess(outDir+testRAF2), new PrintStream(NullOutputStream.NULL), new File(outDir+dummyFileName) ); } catch (Throwable t) { t.printStackTrace(); } } for (int ops=1; ops<=TEST_MAX_OPS; ops++) { succeeded = false; boolean ex1=false, ex2=false; System.out.println("ops="+ops); // delete files new File(outDir+testRAF1).delete(); new File(outDir+testRAF2).delete(); if (testNr==1) // construct raw access file RawAccessUtils.createFileForRaw(outDir+testRAF2,1000); ra1 = (RandomAccessFile) referenceRAF.invoke(outDir+testRAF1, Boolean.TRUE); s1 = makeRAFTest(ra1,ops); ra2 = (RandomAccessFile) testRAF.invoke(outDir+testRAF2, Boolean.TRUE); s2 = makeRAFTest(ra2,ops); if (!s1.equals(s2)) { System.out.println("Tests were not the same!"); System.out.println("Original:"); System.out.println(s1); System.out.println("Test RandomAccessFile:"); System.out.println(s2); break; } equal = compareRAFs (ra1,ra2); if (!equal) { System.out.println("Before close: the RAFs produced are the same: "+equal); break; } ra1.close(); ra2.close(); if (testExceptionHandling) { ex1 = testLengthForEx(ra1); ex2 = testLengthForEx(ra2); if (ex1!=ex2) { System.out.println("Exception handing after close is different"); System.out.println(ex1+"-"+ex2); return; } } // Reopen ra1 = (RandomAccessFile) referenceRAF.invoke(outDir+testRAF1, Boolean.FALSE); ra2 = (RandomAccessFile) testRAF.invoke(outDir+testRAF2, Boolean.FALSE); equal = compareRAFs (ra1,ra2); if (!equal) { System.out.println("Reopen: the RAFs produced are the same: "+equal); break; } ra1.close(); ra2.close(); if (testNr==3) fatdevice.delete("testFileNumberOne.bin"); succeeded = true; } if (succeeded) { System.out.println("\nLast Test output"); System.out.println(s1); System.out.println("\nTest succeeded"); } // delete files new File(outDir+testRAF1).delete(); new File(outDir+testRAF2).delete(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } if (fatdevice!=null) { // fatdevice.unmount(); fatdevice = null; } } }