/*
* The MIT License
*
* Copyright (c) 2009 The Broad Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package htsjdk.samtools.seekablestream;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import static org.testng.Assert.assertEquals;
public class SeekableBufferedStreamTest {
// private final File BAM_INDEX_FILE = new File("testdata/htsjdk/samtools/BAMFileIndexTest/index_test.bam.bai");
private final File BAM_FILE = new File("testdata/htsjdk/samtools/BAMFileIndexTest/index_test.bam");
private final String BAM_URL_STRING = "http://broadinstitute.github.io/picard/testdata/index_test.bam";
private static File TestFile = new File("testdata/htsjdk/samtools/seekablestream/megabyteZeros.dat");
/**
* Test reading across a buffer boundary (buffer size is 512000). The test first reads a range of
* bytes using an unbuffered stream file stream, then compares this to results from a buffered http stream.
*
* @throws IOException
*/
@Test
public void testRandomRead() throws IOException {
int startPosition = 500000;
int length = 50000;
byte[] buffer1 = new byte[length];
SeekableStream unBufferedStream = new SeekableFileStream(BAM_FILE);
unBufferedStream.seek(startPosition);
int bytesRead = unBufferedStream.read(buffer1, 0, length);
assertEquals(length, bytesRead);
byte[] buffer2 = new byte[length];
SeekableStream bufferedStream = new SeekableBufferedStream(new SeekableHTTPStream(new URL(BAM_URL_STRING)));
bufferedStream.seek(startPosition);
bytesRead = bufferedStream.read(buffer2, 0, length);
assertEquals(length, bytesRead);
assertEquals(buffer1, buffer2);
}
/**
* Test an attempt to read past the end of the file. The test file is 594,149 bytes in length. The test
* attempts to read a 1000 byte block starting at position 594000. A correct result would return 149 bytes.
*
* @throws IOException
*/
@Test
public void testEOF() throws IOException {
int remainder = 149;
long fileLength = BAM_FILE.length();
long startPosition = fileLength - remainder;
int length = 1000;
byte[] buffer = new byte[length];
SeekableStream bufferedStream = new SeekableBufferedStream(new SeekableHTTPStream(new URL(BAM_URL_STRING)));
bufferedStream.seek(startPosition);
int bytesRead = bufferedStream.read(buffer, 0, length);
assertEquals(remainder, bytesRead);
// Subsequent reads should return -1
bytesRead = bufferedStream.read(buffer, 0, length);
assertEquals(-1, bytesRead);
}
@Test
public void testSkip() throws IOException {
final int[] BUFFER_SIZES = new int[]{8, 96, 1024, 8*1024, 16*1024, 96*1024, 48*1024};
for (final int bufferSize : BUFFER_SIZES) {
final SeekableBufferedStream in1 = new SeekableBufferedStream(new SeekableFileStream(BAM_FILE), bufferSize);
final SeekableBufferedStream in2 = new SeekableBufferedStream(new SeekableFileStream(BAM_FILE), bufferSize);
final int SIZE = 10000;
final byte[] bytes1 = new byte[SIZE];
final byte[] bytes2 = new byte[SIZE];
reallyRead(bytes1, in1);
reallyRead(bytes1, in1);
in1.skip(bytes1.length);
reallyRead(bytes1, in1);
reallyRead(bytes2, in2);
reallyRead(bytes2, in2);
in2.seek(bytes2.length * 3);
reallyRead(bytes2, in2);
in1.close();
in2.close();
Assert.assertEquals(bytes1, bytes2, "Error at buffer size " + bufferSize);
}
}
private int reallyRead(final byte[] bytes, final SeekableBufferedStream in) throws IOException {
int read = 0, total = 0;
do {
read = in.read(bytes, total, bytes.length-total);
total += read;
} while (total != bytes.length && read > 0);
return total;
}
@Test
public void testDivisableReads()throws IOException{
testReadsLength(1);
testReadsLength(2);
testReadsLength(4);
testReadsLength(5);
testReadsLength(10);
testReadsLength(20);
testReadsLength(50);
testReadsLength(100);
}
private void testReadsLength(final int length) throws IOException {
final int BUFFERED_STREAM_BUFFER_SIZE = 100;
final byte buffer[]=new byte[BUFFERED_STREAM_BUFFER_SIZE*10];
final SeekableFileStream fileStream = new SeekableFileStream(TestFile);
final SeekableBufferedStream bufferedStream = new SeekableBufferedStream(fileStream,BUFFERED_STREAM_BUFFER_SIZE);
for( int i=0; i<10*BUFFERED_STREAM_BUFFER_SIZE/length ; ++i ){
assertEquals(bufferedStream.read(buffer, 0, length), length);
}
}
}