package com.beijunyi.parallelgit.filesystem;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.*;
import javax.annotation.Nonnull;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static java.lang.System.arraycopy;
import static java.nio.file.Files.*;
import static java.nio.file.StandardOpenOption.*;
import static org.eclipse.jgit.lib.Constants.encodeASCII;
import static org.junit.Assert.*;
public class FilesNewByteChannelTest extends AbstractGitFileSystemTest {
private static final byte[] TEST_DATA = someBytes();
private SeekableByteChannel channel;
@Before
public void setUp() throws IOException {
initRepository();
writeToCache("/dir/file.txt", TEST_DATA);
commitToMaster();
initGitFileSystem();
}
@After
public void tearDown() throws IOException {
if(channel != null) {
channel.close();
channel = null;
}
}
@Test
public void createNewReadOnlyChannelFromExistingFile_resultChannelShouldAllowReadAccess() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), READ);
assertArrayEquals(TEST_DATA, readChannel(channel));
}
@Test(expected = NoSuchFileException.class)
public void createNewReadOnlyChannelFromNonExistentFile_shouldThrowNoSuchFileException() throws IOException {
newByteChannel(gfs.getPath("/non_existent_file.txt"), READ);
}
@Test(expected = AccessDeniedException.class)
public void createNewReadOnlyChannelFromDirectory_shouldThrowAccessDeniedException() throws IOException {
newByteChannel(gfs.getPath("/dir"), READ);
}
@Test
public void createNewWriteOnlyChannelFromExistingFile_resultChannelShouldAllowWriteAccess() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), WRITE);
writeChannel(channel, someBytes());
}
@Test
public void writeToWritableChannel_shouldOverwriteFileDataFromBeginning() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), WRITE);
byte[] overwrite = encodeASCII("!!!");
writeChannel(channel, overwrite);
byte[] expected = new byte[TEST_DATA.length];
arraycopy(TEST_DATA, 0, expected, 0, TEST_DATA.length);
arraycopy(overwrite, 0, expected, 0, overwrite.length);
assertArrayEquals(expected, readAllBytes(gfs.getPath("/dir/file.txt")));
}
@Test
public void writeToWritableChannelWithTruncateExistingOption_shouldOverwriteEntireFileData() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), WRITE, TRUNCATE_EXISTING);
byte[] overwrite = encodeASCII("!!!");
writeChannel(channel, overwrite);
channel.close();
assertArrayEquals(overwrite, readAllBytes(gfs.getPath("/dir/file.txt")));
}
@Test
public void writeToWritableChannelWithAppendOption_shouldAppendDataToTheEndOfTheFile() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), WRITE, APPEND);
byte[] append = encodeASCII("!!!");
writeChannel(channel, append);
channel.close();
byte[] expected = new byte[TEST_DATA.length + append.length];
arraycopy(TEST_DATA, 0, expected, 0, TEST_DATA.length);
arraycopy(append, 0, expected, TEST_DATA.length, append.length);
assertArrayEquals(expected, readAllBytes(gfs.getPath("/dir/file.txt")));
}
@Test(expected = NoSuchFileException.class)
public void createNewWriteOnlyChannelFromNonExistentFile_shouldThrowNoSuchFileException() throws IOException {
newByteChannel(gfs.getPath("/non_existent_file.txt"), WRITE);
}
@Test(expected = AccessDeniedException.class)
public void createNewWriteOnlyChannelFromDirectory_shouldThrowAccessDeniedException() throws IOException {
newByteChannel(gfs.getPath("/dir"), WRITE);
}
@Test
public void createReadWriteChannel_resultChannelShouldAllowReadWriteAccess() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), READ, WRITE);
byte[] overwrite = encodeASCII("!!!");
writeChannel(channel, overwrite);
byte[] expected = new byte[TEST_DATA.length];
arraycopy(TEST_DATA, 0, expected, 0, TEST_DATA.length);
arraycopy(overwrite, 0, expected, 0, overwrite.length);
channel.position(0);
assertArrayEquals(expected, readChannel(channel));
}
@Test
public void createChannelWithNoExplicitOption_resultChannelShouldAllowReadAccess() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"));
assertArrayEquals(TEST_DATA, readChannel(channel));
}
@Test
public void createChannelWithReadOption_positionShouldBeTheEndOfTheFile() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), READ);
assertEquals(0, channel.position());
}
@Test
public void createChannelWithWriteOption_positionShouldBeTheEndOfTheFile() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), WRITE);
assertEquals(0, channel.position());
}
@Test
public void createChannelWithAppendOption_resultChannelShouldAllowWriteAccess() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), APPEND);
writeChannel(channel, someBytes());
}
@Test
public void createChannelWithAppendOption_positionShouldBeTheEndOfTheFile() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), APPEND);
assertEquals(channel.size(), channel.position());
}
@Test
public void createChannelWithTruncateExistingOption_sizeShouldBecomeZero() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), WRITE, TRUNCATE_EXISTING);
assertEquals(0, channel.size());
}
@Test
public void createChannelWithCreateOptionFromExistingFile_shouldReturnReadableChannel() throws IOException {
channel = newByteChannel(gfs.getPath("/dir/file.txt"), CREATE);
assertArrayEquals(TEST_DATA, readChannel(channel));
}
@Test
public void createChannelWithCreateOptionFromNonExistentFile_shouldReturnEmptyReadableChannel() throws IOException {
channel = newByteChannel(gfs.getPath("/non_existent_file.txt"), CREATE);
assertArrayEquals(new byte[0], readChannel(channel));
}
@Test
public void createChannelWithCreateOptionFromNonExistentFile_fileShouldBeCreated() throws IOException {
Path newFile = gfs.getPath("/new_file.txt");
channel = newByteChannel(newFile, CREATE);
exists(newFile);
}
@Test(expected = FileAlreadyExistsException.class)
public void createChannelWithCreateNewOptionFromExistingFile_shouldThrowFileAlreadyExistsException() throws IOException {
newByteChannel(gfs.getPath("/dir/file.txt"), CREATE_NEW);
}
@Test
public void createChannelWithCreateNewOptionFromNonExistentFile_shouldReturnEmptyReadableChannel() throws IOException {
channel = newByteChannel(gfs.getPath("/non_existent_file.txt"), CREATE_NEW);
assertArrayEquals(new byte[0], readChannel(channel));
}
@Test
public void createChannelWithCreateNewOptionFromNonExistentFile_fileShouldBeCreated() throws IOException {
Path newFile = gfs.getPath("/new_file.txt");
channel = newByteChannel(newFile, CREATE_NEW);
exists(newFile);
}
@Test(expected = UnsupportedOperationException.class)
public void createChannelWitUnsupportedOption_shouldThrowUnsupportedOperationException() throws IOException {
newByteChannel(gfs.getPath("/dir"), DELETE_ON_CLOSE);
}
@Nonnull
private static byte[] readChannel(SeekableByteChannel channel) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate((int) channel.size());
channel.read(buffer);
return buffer.array();
}
private static void writeChannel(SeekableByteChannel channel, byte[] bytes) throws IOException {
ByteBuffer buffer = ByteBuffer.wrap(bytes);
channel.write(buffer);
}
}