/* * JBoss, Home of Professional Open Source * Copyright 2012, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * 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.jboss.shrinkwrap.api.nio.file; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.util.logging.Logger; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Tests to assert that the {@link SeekableInMemoryByteChannel} is working as contracted. * * @author <a href="mailto:alr@jboss.org">Andrew Lee Rubinger</a> */ public class SeekableInMemoryByteChannelTestCase { @SuppressWarnings("unused") private static final Logger log = Logger.getLogger(SeekableInMemoryByteChannelTestCase.class.getName()); private static final String CONTENTS_SMALLER_BUFFER = "Andrew Lee Rubinger"; private static final String CONTENTS_BIGGER_BUFFER = "Andrew Lee Rubinger, JBoss by Red Hat"; private static final String UTF8 = "UTF-8"; /** * Instance under test */ private SeekableInMemoryByteChannel channel; private ByteBuffer smallerBuffer; private ByteBuffer biggerBuffer; @Before public void init() { this.channel = new SeekableInMemoryByteChannel(); try { smallerBuffer = ByteBuffer.wrap(CONTENTS_SMALLER_BUFFER.getBytes(UTF8)); biggerBuffer = ByteBuffer.wrap(CONTENTS_BIGGER_BUFFER.getBytes(UTF8)); } catch (final UnsupportedEncodingException uee) { throw new RuntimeException(uee); } } @After public void closeChannel() throws IOException { if (this.channel.isOpen()) { this.channel.close(); } } @Test(expected = ClosedChannelException.class) public void readAfterCloseThrowsException() throws IOException { this.channel.close(); this.channel.read(ByteBuffer.wrap(new byte[] {})); } @Test(expected = ClosedChannelException.class) public void writeAfterCloseThrowsException() throws IOException { this.channel.close(); this.channel.write(ByteBuffer.wrap(new byte[] {})); } @Test public void isOpenTrue() throws IOException { Assert.assertTrue("Channel should report open before it's closed", this.channel.isOpen()); } @Test public void isOpenFalseAfterClose() throws IOException { this.channel.close(); Assert.assertFalse("Channel should report not open after close", this.channel.isOpen()); } @Test public void positionInit0() throws IOException { Assert.assertEquals("Channel should init to position 0", 0, this.channel.position()); } @Test public void sizeInit0() throws IOException { Assert.assertEquals("Channel should init to size 0", 0, this.channel.size()); } @Test(expected = IllegalArgumentException.class) public void readRequiresBuffer() throws IOException { this.channel.read(null); } @Test(expected = IllegalArgumentException.class) public void writeRequiresBuffer() throws IOException { this.channel.write(null); } @Test public void read() throws IOException { this.channel.write(smallerBuffer); final int newPosition = 2; final byte[] contents = new byte[2]; // Read 2 bytes from the new position final int numBytesRead = this.channel.position(newPosition).read(ByteBuffer.wrap(contents)); final String expected = "dr"; final String contentsRead = new String(contents, UTF8); Assert.assertEquals("Read should report correct number of bytes read", contents.length, numBytesRead); Assert.assertEquals("Channel should respect explicit position during reads", expected, contentsRead); } @Test public void getContents() throws IOException { this.channel.write(smallerBuffer); final BufferedReader reader = new BufferedReader(new InputStreamReader(this.channel.getContents())); final String contents = reader.readLine(); Assert.assertEquals("Contents read were not as expected", CONTENTS_SMALLER_BUFFER, contents); } @Test public void readDestinationBiggerThanChannel() throws IOException { this.channel.write(smallerBuffer); final ByteBuffer destination = biggerBuffer; Assert.assertTrue("Test setup incorrect, should be trying to read into a buffer greater than our size", destination.remaining() > this.channel.size()); // Read more bytes than we currently have size final int numBytesRead = this.channel.position(0).read(destination); Assert.assertEquals("Read to a buffer greater than our size should read only up to our size", this.channel.size(), numBytesRead); } @Test public void nothingToRead() throws IOException { this.channel.write(smallerBuffer); // Read a byte from a position past the size final int numBytesRead = this.channel.position(this.channel.size() + 3).read(ByteBuffer.wrap(new byte[1])); Assert.assertEquals("Read on position > size should return -1", -1, numBytesRead); } @Test public void write() throws IOException { this.channel.write(smallerBuffer); final int newPosition = 2; final int numBytesWritten = this.channel.position(newPosition).write(ByteBuffer.wrap("DR".getBytes(UTF8))); // Read 3 bytes from the new position final byte[] contents = new byte[3]; this.channel.position(newPosition).read(ByteBuffer.wrap(contents)); final String expected = "DRe"; final String read = new String(contents, UTF8); Assert.assertEquals("Write should report correct number of bytes written", 2, numBytesWritten); Assert.assertEquals("Channel should respect explicit position during writes", expected, read); } @Test public void writeWithPositionPastSize() throws IOException { this.channel.write(smallerBuffer); smallerBuffer.clear(); final int gap = 5; // Write again, after a gap past the current size this.channel.position(this.channel.size() + gap).write(smallerBuffer); smallerBuffer.clear(); Assert.assertEquals("Channel size should be equal to the size of the writes we put in, plus " + "the gap when we set the position tpo be greater than the size", smallerBuffer.remaining() * 2 + gap, this.channel.size()); } @Test public void positionSetPastSize() throws IOException { final int newPosition = 30; this.channel.position(newPosition); Assert.assertEquals("Channel should be able to be set past size", newPosition, this.channel.position()); } @Test(expected = IllegalArgumentException.class) public void negativePositionProhibited() throws IOException { this.channel.position(-1); } @Test(expected = IllegalArgumentException.class) public void exceedMaxIntegerPositionProhibited() throws IOException { final long newPosition = Integer.MAX_VALUE + 1L; Assert.assertTrue("Didn't set up new position to be out of int bounds", newPosition > Integer.MAX_VALUE); this.channel.position(newPosition); // Exception expected } @Test(expected = IllegalArgumentException.class) public void negativeTruncateProhibited() throws IOException { this.channel.truncate(-1); } @Test(expected = IllegalArgumentException.class) public void exceedMaxIntegerTruncateProhibited() throws IOException { final long truncateValue = Integer.MAX_VALUE + 1L; Assert.assertTrue("Didn't set up new truncate to be out of int bounds", truncateValue > Integer.MAX_VALUE); this.channel.truncate(truncateValue); // Exception expected } @Test public void size() throws IOException { this.channel.write(smallerBuffer); Assert.assertEquals("Channel should report correct size", this.smallerBuffer.clear().remaining(), this.channel.size()); } @Test public void truncate() throws IOException { this.channel.write(smallerBuffer); final int newSize = (int) this.channel.size() - 3; this.channel.truncate(newSize); // Correct size? Assert.assertEquals("Channel should report correct size after truncate", newSize, this.channel.size()); // Correct position? Assert.assertEquals("Channel should report adjusted position after truncate", newSize, this.channel.position()); } @Test public void truncateLargerThanSizeRepositions() throws IOException { this.channel.write(smallerBuffer); final int oldSize = (int) this.channel.size(); final int newSize = oldSize + 3; this.channel.truncate(newSize); // Size unchanged? Assert.assertEquals("Channel should report unchanged size after truncate to bigger value", oldSize, this.channel.size()); // Correct position, beyond size? Assert.assertEquals("Channel should report unchanged position after truncate to bigger value", oldSize, this.channel.position()); } }