package org.apache.hadoop.io.simpleseekableformat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.util.Random;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.io.simpleseekableformat.SimpleSeekableFormat;
import org.apache.hadoop.io.simpleseekableformat.SimpleSeekableFormatInputStream;
import org.apache.hadoop.io.simpleseekableformat.SimpleSeekableFormatOutputStream;
/**
* TestCase for {@link SimpleSeekableFormatInputStream} and {@link SimpleSeekableFormatOutputStream}
*/
public class TestSimpleSeekableFormatStreams extends TestCase {
public void testNormalWriteAndRead() throws Exception {
testNormalWriteAndRead(null);
testNormalWriteAndRead(GzipCodec.class);
}
void testNormalWriteAndRead(final Class<? extends CompressionCodec> codecClass
) throws Exception {
// Not using loops here so we can know the exact parameter values from
// the stack trace.
testNormalWriteAndRead(codecClass, 1, 65536);
testNormalWriteAndRead(codecClass, 100, 16384);
testNormalWriteAndRead(codecClass, 1000, 4096);
}
/**
* @param writeSize 0: use "write(int)"; > 0: use "write(byte[])".
* @param readSize 0: use "read()"; > 0: use "read(bytes[])".
*/
void testNormalWriteAndRead(final Class<? extends CompressionCodec> codecClass,
final int numRecord, final int maxRecordSize) throws Exception {
long startMs = System.currentTimeMillis();
// Random seed for data to be written
final Random dataRandom = new Random(333);
// Random seed for verifying data written
final Random dataRandom2 = new Random(333);
// Create the in-memory file and start to write to it.
ByteArrayOutputStream inMemoryFile = new ByteArrayOutputStream();
SimpleSeekableFormatOutputStream out = new SimpleSeekableFormatOutputStream(inMemoryFile);
// Set compression Codec
Configuration conf = new Configuration();
if (codecClass != null) {
conf.setClass(SimpleSeekableFormat.FILEFORMAT_SSF_CODEC_CONF, codecClass,
CompressionCodec.class);
}
out.setConf(conf);
// Write some data
for (int r = 0; r < numRecord; r++) {
byte[] b = new byte[dataRandom.nextInt(maxRecordSize)];
// Generate some compressible random data
TestUtils.nextBytes(dataRandom, b, 16);
out.write(b);
}
out.close();
long writeDoneMs = System.currentTimeMillis();
// Open the in-memory file for read
ByteArrayInputStream fileForRead = new ByteArrayInputStream(inMemoryFile.toByteArray());
SimpleSeekableFormatInputStream in = new SimpleSeekableFormatInputStream(fileForRead);
DataInputStream dataIn = new DataInputStream(in);
// Verify the data
for (int r = 0; r < numRecord; r++) {
// Regenerate the same random bytes
byte[] b = new byte[dataRandom2.nextInt(maxRecordSize)];
TestUtils.nextBytes(dataRandom2, b, 16);
// Read from the file
byte[] b2 = new byte[b.length];
dataIn.readFully(b2);
TestUtils.assertArrayEquals("record " + r + " with length " + b.length,
b, b2);
}
// Verify EOF
Assert.assertEquals(-1, in.read());
byte[] temp = new byte[100];
Assert.assertEquals(-1, in.read(temp));
long readDoneMs = System.currentTimeMillis();
// Output file size and time used for debugging purpose
System.out.println("File size = " + inMemoryFile.size()
+ " writeMs=" + (writeDoneMs - startMs)
+ " readMs=" + (readDoneMs - writeDoneMs)
+ " numRecord=" + numRecord + " maxRecordSize=" + maxRecordSize
+ " codec=" + codecClass);
}
}