package au.edu.anu.dcclient.progress;
import static org.junit.Assert.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProgressInputStreamTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ProgressInputStreamTest.class);
private File file;
@Rule
public TemporaryFolder tempDir = new TemporaryFolder();
private ProgressInputStream pis;
private long listenerCalledCount;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() throws Exception {
listenerCalledCount = 0;
file = tempDir.newFile();
writeRandomBytes(file, 5L * 1024L * 1024L);
pis = new ProgressInputStream(new FileInputStream(file), file.length());
pis.addPropertyChangeListener(createPropertyChangeListener());
}
@After
public void tearDown() throws Exception {
assertTrue(listenerCalledCount >= 1 && listenerCalledCount <= 100);
pis.close();
}
/**
* Tests the read() method by reading a file one byte at a time.
*
* @throws IOException
*/
@Test
public void testRead() throws IOException {
int numBytesRead = 0;
while (pis.read() != -1)
numBytesRead++;
assertEquals(file.length(), numBytesRead);
LOGGER.trace("Done");
}
/**
* Tests the read(buffer) method by reading a file one buffer at a time.
*
* @throws IOException
*/
@Test
public void testReadBuffer() throws IOException {
byte[] buffer = new byte[1024];
long buffersRead = 0;
for (int bytesRead = pis.read(buffer); bytesRead != -1; bytesRead = pis.read(buffer)) {
buffersRead++;
}
assertEquals(getExpectedBufferReads(file.length(), buffer.length), buffersRead);
LOGGER.trace("Done");
}
/**
* Tests the read(buffer, offset, length) method by read a file one buffer at the file using the offset and length.
*
* @throws IOException
*/
@Test
public void testReadBufferOffLen() throws IOException {
byte[] buffer = new byte[2048];
int off = 512;
int len = 1024;
initByteArrayWith0(buffer);
long buffersRead = 0;
for (int bytesRead = pis.read(buffer, off, len); bytesRead != -1; bytesRead = pis.read(buffer, off, len)) {
buffersRead++;
}
assertEquals(getExpectedBufferReads(file.length(), len), buffersRead);
LOGGER.trace("Done");
}
/**
* Initialises a byte array with 0x00s.
* @param buffer
*/
private void initByteArrayWith0(byte[] buffer) {
for (int i = 0; i < buffer.length; i++) {
buffer[i] = 0x00;
}
}
private long getExpectedBufferReads(long fileSizeInBytes, int bufferSizeInBytes) {
long expectedBufferReads = fileSizeInBytes / bufferSizeInBytes;
if (fileSizeInBytes % bufferSizeInBytes > 0) {
expectedBufferReads++;
}
return expectedBufferReads;
}
private void writeRandomBytes(File targetFile, long numBytes) throws IOException {
Random rand = new Random();
BufferedOutputStream outStream = null;
byte[] buffer = new byte[1024];
try {
outStream = new BufferedOutputStream(new FileOutputStream(targetFile));
for (int i = 0; i < numBytes / buffer.length; i++) {
rand.nextBytes(buffer);
outStream.write(buffer);
}
} finally {
IOUtils.closeQuietly(outStream);
}
assertEquals(numBytes, file.length());
}
private PropertyChangeListener createPropertyChangeListener() {
return new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
listenerCalledCount++;
LOGGER.debug("Event propertyName: {}, oldValue: {}, newValue: {}.", evt.getPropertyName(),
evt.getOldValue(), evt.getNewValue());
}
};
}
}