/* * This file is part of the Heritrix web crawler (crawler.archive.org). * * Licensed to the Internet Archive (IA) by one or more individual * contributors. * * The IA licenses this file to You 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 org.archive.util.ms; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Random; import org.archive.io.ArraySeekInputStream; import org.archive.io.SafeSeekInputStream; import org.archive.io.SeekInputStream; import junit.framework.TestCase; /** * Unit test for PieceReader. Takes a quatrain of a sonnet and stores the * lines out-of-order, then constructs a PieceTable that will re-order the * lines correctly. Finally constructs a PieceReader with that raw data * and piece table and sees if the correct quatrain is produced by the * stream. Also performs some tests of random seeking within the stream. * * @author pjack */ public class PieceReaderTest extends TestCase { final private static String[] QUATRAIN = new String[] { "If the dull substance of my flesh were thought\n", "Injurious distance could not stop my way\n", "For then, despite of space, I would be brought\n", "From limits far remote where thou dost stay.\n" }; final private static String QUATRAIN_STRING = QUATRAIN[0] + QUATRAIN[1] + QUATRAIN[2] + QUATRAIN[3]; final private static byte[] QUATRAIN_BYTES; final private static byte[] PIECE_TABLE; public void testPosition() throws Exception { PieceTable table = makePieceTable(); SeekInputStream asis = new ArraySeekInputStream(QUATRAIN_BYTES); asis = new SafeSeekInputStream(asis); PieceReader reader = new PieceReader(table, asis); StringBuilder sb = new StringBuilder(); for (int ch = reader.read(); ch > 0; ch = reader.read()) { sb.append((char)ch); } assertEquals(QUATRAIN_STRING, sb.toString()); reader.position(0); sb = new StringBuilder(); for (int ch = reader.read(); ch > 0; ch = reader.read()) { sb.append((char)ch); } assertEquals(QUATRAIN_STRING, sb.toString()); Random random = new Random(); for (int i = 0; i < 1000; i++) { int index = random.nextInt(QUATRAIN_BYTES.length); reader.position(index); char ch = (char)reader.read(); assertEquals(QUATRAIN_STRING.charAt(index), ch); } } private static PieceTable makePieceTable() throws IOException { ArraySeekInputStream stream = new ArraySeekInputStream(PIECE_TABLE); int maxSize = QUATRAIN_BYTES.length; return new PieceTable(stream, 0, maxSize, 4); } static { QUATRAIN_BYTES = new byte[QUATRAIN_STRING.length()]; PIECE_TABLE = new byte[4 * 12 + 5 + 4]; int ofs = 0; int line3 = 0; ofs += addLine(ofs, QUATRAIN[2]); int line1 = ofs; ofs += addLine(ofs, QUATRAIN[0]); int line4 = ofs; ofs += addLine(ofs, QUATRAIN[3]); int line2 = ofs; ofs += addLine(ofs, QUATRAIN[1]); int start = 0; int end = QUATRAIN[0].length(); addPiece(0, start, end, line1); start += QUATRAIN[0].length(); end += QUATRAIN[1].length(); addPiece(1, start, end, line2); start += QUATRAIN[1].length(); end += QUATRAIN[2].length(); addPiece(2, start, end, line3); start += QUATRAIN[2].length(); end += QUATRAIN[3].length(); addPiece(3, start, end, line4); ByteBuffer buf = ByteBuffer.wrap(PIECE_TABLE); buf.order(ByteOrder.LITTLE_ENDIAN); buf.put(0, (byte)2); buf.putInt(1, 52); } private static int addLine(int ofs, String line) { for (int i = 0; i < line.length(); i++) { QUATRAIN_BYTES[ofs + i] = (byte)line.charAt(i); } return line.length(); } private static void addPiece(int index, int start, int end, int fp) { ByteBuffer buf = ByteBuffer.wrap(PIECE_TABLE); buf.order(ByteOrder.LITTLE_ENDIAN); int orig = fp; fp = (fp * 2) | PieceTable.CP1252_INDICATOR; if ((fp & PieceTable.CP1252_MASK) / 2 != orig) { throw new RuntimeException("No."); } buf.putInt(index * 4 + 5, start); buf.putInt(5 + 20 + index * 8 + 2, fp); } }