/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2013 Red Hat, Inc. and/or its affiliates, and individual
* contributors as indicated by the @author tags.
*
* Licensed 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.xnio;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.xnio.AssertReadWrite.assertReadMessage;
import static org.xnio.AssertReadWrite.assertWrittenMessage;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.xnio.channels.BlockingByteChannel;
import org.xnio.channels.PushBackStreamChannel;
import org.xnio.mock.ConnectedStreamChannelMock;
/**
* Test for {@link XnioFileChannel}.
*
* @author <a href="mailto:frainone@redhat.com">Flavia Rainone</a>
*
*/
public class XnioFileChannelTestCase {
private RandomAccessFile randomAccessFile;
private FileChannel fileChannel;
@Before
public void initFileChannel() throws IOException {
final File file = File.createTempFile("test", ".txt");
file.deleteOnExit();
randomAccessFile = new RandomAccessFile(file, "rw");
fileChannel = new XnioFileChannel(randomAccessFile.getChannel());
}
@After
public void closeFileChannel() throws IOException {
fileChannel.close();
randomAccessFile.close();
}
@Test
public void simpleReadAndWrite() throws IOException {
assertEquals(0, fileChannel.size());
final ByteBuffer buffer = ByteBuffer.allocate(5);
buffer.put("abcde".getBytes()).flip();
assertEquals(5, fileChannel.write(buffer));
assertEquals(5, fileChannel.size());
assertEquals(5, fileChannel.position());
fileChannel.position(0);
assertEquals(0, fileChannel.position());
assertEquals(5, fileChannel.size());
final ByteBuffer readBuffer = ByteBuffer.allocate(10);
assertEquals(5, fileChannel.read(readBuffer));
assertEquals(5, fileChannel.position());
assertReadMessage(readBuffer, "abcde");
assertEquals(5, fileChannel.size());
}
@Test
public void readAndWriteWithOffset() throws IOException {
final ByteBuffer[] buffers = new ByteBuffer[] {ByteBuffer.allocate(3), ByteBuffer.allocate(3),
ByteBuffer.allocate(3), ByteBuffer.allocate(3), ByteBuffer.allocate(3), ByteBuffer.allocate(3)};
buffers[0].put("#$%".getBytes()).flip();
buffers[1].put("abc".getBytes()).flip();
buffers[2].put("de".getBytes()).flip();
buffers[3].flip();
buffers[4].put("ABC".getBytes()).flip();
buffers[5].put("DEF".getBytes()).flip();
assertEquals(5, fileChannel.write(buffers, 1, 3));
assertEquals(5, fileChannel.position());
fileChannel.position(0);
assertEquals(0, fileChannel.position());
final ByteBuffer[] readBuffers = new ByteBuffer[] {ByteBuffer.allocate(1), ByteBuffer.allocate(2),
ByteBuffer.allocate(3), ByteBuffer.allocate(4)};
assertEquals(2, fileChannel.read(readBuffers, 1, 1));
assertEquals(2, fileChannel.position());
assertReadMessage(readBuffers[1], "ab");
assertEquals(3, fileChannel.read(readBuffers, 1, 3));
assertEquals(5, fileChannel.position());
assertReadMessage(readBuffers[2], "cde");
}
@Test
public void readAndWriteWithPosition() throws IOException {
assertEquals(0, fileChannel.size());
final ByteBuffer buffer = ByteBuffer.allocate(5);
buffer.put("abcde".getBytes()).flip();
assertEquals(5, fileChannel.write(buffer, 3));
assertEquals(8, fileChannel.size());
assertEquals(0, fileChannel.position());
fileChannel.position(3);
assertEquals(3, fileChannel.position());
assertEquals(8, fileChannel.size());
final ByteBuffer readBuffer = ByteBuffer.allocate(10);
assertEquals(4, fileChannel.read(readBuffer, 4));
assertEquals(3, fileChannel.position());
assertReadMessage(readBuffer, "bcde");
assertEquals(8, fileChannel.size());
}
@Test
public void truncate() throws IOException {
assertEquals(0, fileChannel.size());
final ByteBuffer buffer = ByteBuffer.allocate(20);
buffer.put("message to truncate".getBytes()).flip();
assertEquals(19, fileChannel.write(buffer));
assertEquals(19, fileChannel.size());
fileChannel.truncate(10);
assertEquals(10, fileChannel.size());
buffer.clear();
fileChannel.position(0);
assertEquals(10, fileChannel.read(buffer));
assertReadMessage(buffer, "message to");
buffer.clear();
fileChannel.truncate(15);
assertEquals(10, fileChannel.size());
buffer.clear();
fileChannel.position(0);
assertEquals(10, fileChannel.read(buffer));
assertReadMessage(buffer, "message to");
buffer.clear();
fileChannel.truncate(7);
assertEquals(7, fileChannel.size());
buffer.clear();
fileChannel.position(0);
assertEquals(7, fileChannel.read(buffer));
assertReadMessage(buffer, "message");
//test force... nothing noticeable should happen
fileChannel.force(true);
fileChannel.force(false);
}
@Test
public void transferBlockingToFile1() throws IOException {
final ConnectedStreamChannelMock channelMock = new ConnectedStreamChannelMock();
channelMock.setReadData("test");
channelMock.enableRead(true);
fileChannel.transferFrom(channelMock, 0, 4);
fileChannel.position(0);
ByteBuffer buffer = ByteBuffer.allocate(10);
fileChannel.read(buffer);
assertReadMessage(buffer, "test");
}
@Test
public void transferBlockingToFile2() throws IOException, InterruptedException {
final ConnectedStreamChannelMock channelMock = new ConnectedStreamChannelMock();
channelMock.setReadData("test", "12345");
channelMock.enableRead(true);
fileChannel.transferFrom(new PushBackStreamChannel(channelMock), 0, 8);
fileChannel.position(0);
ByteBuffer buffer = ByteBuffer.allocate(10);
fileChannel.read(buffer);
assertReadMessage(buffer, "test", "1234");
}
@Test
public void transferBlockingToFile3() throws IOException {
final ConnectedStreamChannelMock channelMock = new ConnectedStreamChannelMock();
channelMock.setReadData("test");
channelMock.enableRead(true);
fileChannel.transferFrom(new BlockingByteChannel(channelMock), 0, 4);
fileChannel.position(0);
ByteBuffer buffer = ByteBuffer.allocate(10);
fileChannel.read(buffer);
assertReadMessage(buffer, "test");
}
@Test
public void transferBlockingFromFile1() throws IOException {
final ConnectedStreamChannelMock channelMock = new ConnectedStreamChannelMock();
final ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put("test".getBytes("UTF-8")).flip();
assertEquals(4, fileChannel.write(buffer));
fileChannel.position(0);
fileChannel.transferTo(0, 4, channelMock);
assertWrittenMessage(channelMock, "test");
}
@Test
public void transferBlockingFromFile2() throws IOException, InterruptedException {
final ConnectedStreamChannelMock channelMock = new ConnectedStreamChannelMock();
channelMock.enableWrite(false);
final ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put("test12345".getBytes("UTF-8")).flip();
assertEquals(9, fileChannel.write(buffer));
fileChannel.position(0);
channelMock.enableWrite(true);
fileChannel.transferTo(0, 8, channelMock);
assertWrittenMessage(channelMock, "test", "1234");
}
@Test
public void transferBlockingFromFile3() throws IOException {
final ConnectedStreamChannelMock channelMock = new ConnectedStreamChannelMock();
final ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put("test".getBytes("UTF-8")).flip();
assertEquals(4, fileChannel.write(buffer));
fileChannel.position(0);
fileChannel.transferTo(0, 4, new BlockingByteChannel(channelMock));
assertWrittenMessage(channelMock, "test");
}
@Test
public void map() throws IOException {
final ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put("1234567890".getBytes()).flip();
assertEquals(10, fileChannel.write(buffer));
MappedByteBuffer mappedBuffer = fileChannel.map(MapMode.READ_WRITE, 5, 2);
assertNotNull(mappedBuffer);
assertEquals(2, mappedBuffer.limit());
mappedBuffer.position(2);
assertReadMessage(mappedBuffer, "67");
}
@Test
public void lock() throws IOException {
final ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put("1234567890".getBytes()).flip();
assertEquals(10, fileChannel.write(buffer));
FileLock lock = fileChannel.lock();
assertNotNull(lock);
OverlappingFileLockException expected = null;
try {
fileChannel.lock(3, 5, false);
} catch (OverlappingFileLockException e) {
expected = e;
}
assertNotNull(expected);
lock.release();
lock = fileChannel.lock(3, 5, false);
assertNotNull(lock);
expected = null;
try {
fileChannel.tryLock();
} catch (OverlappingFileLockException e) {
expected = e;
}
assertNotNull(expected);
lock.release();
lock = fileChannel.tryLock();
assertNotNull(lock);
lock.release();
lock = fileChannel.tryLock(1, 3, true);
assertNotNull(lock);
expected = null;
try {
fileChannel.tryLock(1, 3, true);
} catch (OverlappingFileLockException e) {
expected = e;
}
assertNotNull(expected);
}
}