You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2014/04/25 17:23:33 UTC

svn commit: r1590057 - in /sis/branches/JDK8: core/sis-utility/src/test/java/org/apache/sis/test/ storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ storage/sis-storage/src/test/java/org/apache/sis/internal/storage/

Author: desruisseaux
Date: Fri Apr 25 15:23:32 2014
New Revision: 1590057

URL: http://svn.apache.org/r1590057
Log:
Fixed ChannelDataOutput.getStreamPosition().

Modified:
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataOutput.java
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ByteArrayChannel.java
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataInputTest.java
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataOutputTest.java
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataTestCase.java
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageInputStreamTest.java
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageOutputStreamTest.java

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -122,7 +122,7 @@ public strictfp class Assert extends org
     public static void assertMultilinesEquals(final String message, final CharSequence expected, final CharSequence actual) {
         final CharSequence[] expectedLines = CharSequences.splitOnEOL(expected);
         final CharSequence[] actualLines   = CharSequences.splitOnEOL(actual);
-        final int length = Math.min(expectedLines.length, actualLines.length);
+        final int length = StrictMath.min(expectedLines.length, actualLines.length);
         final StringBuilder buffer = new StringBuilder(message != null ? message : "Line").append('[');
         final int base = buffer.length();
         for (int i=0; i<length; i++) {

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -28,6 +28,7 @@ import java.text.Format;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import org.apache.sis.util.Debug;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
@@ -44,7 +45,7 @@ import static org.junit.Assert.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.16)
- * @version 0.4
+ * @version 0.5
  * @module
  */
 public final strictfp class TestUtilities extends Static {
@@ -171,6 +172,31 @@ public final strictfp class TestUtilitie
     }
 
     /**
+     * Returns a new random number generator with the given seed. This method is used only for debugging a test failure.
+     * The seed given in argument is the value printed by the test runner. This argument shall be removed after the test
+     * has been fixed.
+     *
+     * <p>The work flow is as below:</p>
+     * <ul>
+     *   <li>Uses {@link #createRandomNumberGenerator()} (without argument} in tests.</li>
+     *   <li>If a test fail, find the seed value printed by the test runner, then insert that value in argument
+     *       to {@code createRandomNumberGenerator(…)}.</li>
+     *   <li>Debug the test.</li>
+     *   <li>Once the test has been fixed, remove the argument from the {@code createRandomNumberGenerator()} call.</li>
+     * </ul>
+     *
+     * @param  seed The random generator seed.
+     * @return A new random number generator initialized with the given seed.
+     *
+     * @since 0.5
+     */
+    @Debug
+    public static Random createRandomNumberGenerator(final long seed) {
+        TestCase.randomSeed = seed;
+        return new Random(seed);
+    }
+
+    /**
      * Parses the date for the given string using the {@code "yyyy-MM-dd HH:mm:ss"} pattern
      * in UTC timezone.
      *

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -133,7 +133,7 @@ public abstract class ChannelData {
      * @return The bit offset of the stream.
      */
     public final int getBitOffset() {
-        final long position = getStreamPosition();
+        final long position = bufferOffset + buffer.position();
         if ((bitPosition >>> BIT_OFFSET_SIZE) != position) {
             bitPosition = position << BIT_OFFSET_SIZE;
         }
@@ -147,7 +147,15 @@ public abstract class ChannelData {
      */
     public final void setBitOffset(final int bitOffset) {
         ensureBetween("bitOffset", 0, Byte.SIZE - 1, bitOffset);
-        bitPosition = (getStreamPosition() << BIT_OFFSET_SIZE) | bitOffset;
+        final long position = bufferOffset + buffer.position();
+        bitPosition = (position << BIT_OFFSET_SIZE) | bitOffset;
+    }
+
+    /**
+     * Sets the bit offset to zero.
+     */
+    final void clearBitOffset() {
+        bitPosition = 0;
     }
 
     /**
@@ -155,7 +163,7 @@ public abstract class ChannelData {
      *
      * @return The position of the stream.
      */
-    public final long getStreamPosition() {
+    public long getStreamPosition() {
         return bufferOffset + buffer.position();
     }
 
@@ -165,13 +173,22 @@ public abstract class ChannelData {
      * be invoked when some external code has performed some work with the channel and wants to inform this
      * {@code ChannelData} about the new position resulting from this work.
      *
-     * <p>This method does not need to be invoked when only the {@linkplain ByteBuffer#position() buffer position}
-     * has changed.</p>
+     * <b>Notes:</b>
+     * <ul>
+     *   <li>Invoking this method clears the {@linkplain #getBitOffset() bit offset}
+     *       and the {@linkplain #mark() marks}.</li>
+     *   <li>This method does not need to be invoked when only the {@linkplain ByteBuffer#position() buffer position}
+     *       has changed.</li>
+     * </ul>
      *
      * @param position The new position of the stream.
      */
     public final void setStreamPosition(final long position) {
         bufferOffset = position - buffer.position();
+        // Clearing the bit offset is needed if we don't want to handle the case of ChannelDataOutput,
+        // which use a different stream position calculation when the bit offset is non-zero.
+        clearBitOffset();
+        mark = null;
     }
 
     /**
@@ -204,9 +221,8 @@ public abstract class ChannelData {
         final int n = (int) (position - bufferOffset);
         final int p = buffer.position() - n;
         final int r = buffer.limit() - n;
-        buffer.position(n); // Number of bytes to forget.
+        flushAndSetPosition(n); // Number of bytes to forget.
         buffer.compact().position(p).limit(r);
-        setStreamPosition(currentPosition);
 
         // Discard obolete marks.
         Mark parent = null;
@@ -224,6 +240,16 @@ public abstract class ChannelData {
     }
 
     /**
+     * Writes (if applicable) the buffer content up to the given position, then set the buffer position
+     * to the given value. The {@linkplain ByteBuffer#limit() buffer limit} is unchanged, and the buffer
+     * offset is incremented by the given value.
+     */
+    void flushAndSetPosition(final int position) throws IOException {
+        buffer.position(position);
+        bufferOffset += position;
+    }
+
+    /**
      * Moves to the given position in the stream, relative to the stream position at construction time.
      *
      * @param  position The position where to move.

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -743,5 +743,6 @@ public class ChannelDataInput extends Ch
              */
             throw new IOException(Errors.format(Errors.Keys.StreamIsForwardOnly_1, filename));
         }
+        clearBitOffset();
     }
 }

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataOutput.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataOutput.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataOutput.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataOutput.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -130,6 +130,25 @@ public class ChannelDataOutput extends C
     }
 
     /**
+     * Returns the current byte position of the stream.
+     *
+     * @return The position of the stream.
+     */
+    @Override
+    public long getStreamPosition() {
+        long position = super.getStreamPosition();
+        /*
+         * ChannelDataOutput uses a different strategy than ChannelDataInput: if some bits were in process
+         * of being written, the buffer position is set to the byte AFTER the byte containing the bits. We
+         * need to apply a correction here for this strategy.
+         */
+        if (getBitOffset() != 0) {
+            position--;
+        }
+        return position;
+    }
+
+    /**
      * Writes a single bit. This method uses only the rightmost bit of the given argument;
      * the upper 31 bits are ignored.
      *
@@ -141,7 +160,7 @@ public class ChannelDataOutput extends C
     }
 
     /**
-     * Writes a sequence of bits. This method uses only the <var>numBits</code> rightmost bits;
+     * Writes a sequence of bits. This method uses only the <code>numBits</code> rightmost bits;
      * other bits are ignored.
      *
      * @param  bits The bits to write (rightmost bits).
@@ -183,7 +202,7 @@ public class ChannelDataOutput extends C
                     part = bits >>> numBits;
                 } else {
                     part = bits << -numBits;
-                    bitOffset = (int) (Byte.SIZE + numBits);
+                    bitOffset = Byte.SIZE + numBits;
                 }
                 writeByte((int) part);
             }
@@ -398,12 +417,20 @@ public class ChannelDataOutput extends C
      * @throws IOException If an error occurred while writing the stream.
      */
     public final void write(final byte[] src, int offset, int length) throws IOException {
-        while (length != 0) {
-            final int n = Math.min(buffer.capacity(), length);
-            ensureBufferAccepts(n);
-            buffer.put(src, offset, n);
-            offset += n;
-            length -= n;
+        if (length != 0) {
+            do {
+                final int n = Math.min(buffer.capacity(), length);
+                ensureBufferAccepts(n);
+                buffer.put(src, offset, n);
+                offset += n;
+                length -= n;
+            } while (length != 0);
+        } else {
+            /*
+             * Since the 'bitOffset' validity is determined by the position, if the position
+             * did not changed, then we need to clear the 'bitOffset' flag manually.
+             */
+            clearBitOffset();
         }
     }
 
@@ -568,12 +595,13 @@ public class ChannelDataOutput extends C
              * Requested position is inside the current limits of the buffer.
              */
             buffer.position((int) p);
+            clearBitOffset();
         } else if (channel instanceof SeekableByteChannel) {
-            flush();
             /*
              * Requested position is outside the current limits of the buffer,
              * but we can set the new position directly in the channel.
              */
+            flush();
             ((SeekableByteChannel) channel).position(channelOffset + position);
             bufferOffset = position;
         } else {
@@ -584,12 +612,38 @@ public class ChannelDataOutput extends C
 
     /**
      * Flushes the {@link #buffer buffer} content to the channel.
+     * This method does <strong>not</strong> flush the channel itself.
      *
-     * @throws IOException If an error occurred while writing the stream.
+     * @throws IOException If an error occurred while writing to the channel.
      */
     @Override
     public final void flush() throws IOException {
         buffer.flip();
+        writeFully();
+        buffer.clear().limit(0);
+        clearBitOffset();
+    }
+
+    /**
+     * Writes the buffer content up to the given position, then set the buffer position to the given value.
+     * The {@linkplain ByteBuffer#limit() buffer limit} is unchanged, and the buffer offset is incremented
+     * by the given value.
+     */
+    @Override
+    final void flushAndSetPosition(final int position) throws IOException {
+        final int limit = buffer.limit();
+        buffer.position(0).limit(position);
+        writeFully();
+        buffer.limit(limit);
+    }
+
+    /**
+     * Writes fully the buffer content from its position to its limit.
+     * After this method call, the buffer position is equals to its limit.
+     *
+     * @throws IOException If an error occurred while writing to the channel.
+     */
+    private void writeFully() throws IOException {
         int n = buffer.remaining();
         bufferOffset += n;
         while (n != 0) {
@@ -599,6 +653,6 @@ public class ChannelDataOutput extends C
             }
             n -= c;
         }
-        buffer.clear().limit(0);
+        assert !buffer.hasRemaining() : buffer;
     }
 }

Modified: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ByteArrayChannel.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ByteArrayChannel.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ByteArrayChannel.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ByteArrayChannel.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -76,7 +76,7 @@ final strictfp class ByteArrayChannel im
         if (position >= limit) {
             return -1;
         }
-        final int length = Math.min(dst.remaining(), limit - position);
+        final int length = StrictMath.min(dst.remaining(), limit - position);
         dst.put(data, position, length);
         return length;
     }
@@ -90,7 +90,7 @@ final strictfp class ByteArrayChannel im
         final int length = src.remaining();
         src.get(data, position, length);
         position += length;
-        limit = Math.max(limit, position);
+        limit = StrictMath.max(limit, position);
         return length;
     }
 

Modified: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataInputTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataInputTest.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataInputTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataInputTest.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -37,6 +37,16 @@ import static org.junit.Assert.*;
  */
 public final strictfp class ChannelDataInputTest extends ChannelDataTestCase {
     /**
+     * The implementation to test.
+     */
+    private ChannelDataInput testedStream;
+
+    /**
+     * A stream to use as a reference implementation.
+     */
+    private DataInput referenceStream;
+
+    /**
      * Fills a buffer with random data and compare the result with a standard image input stream.
      * We allocate a small buffer for the {@code ChannelDataInput} in order to force frequent
      * interactions between the buffer and the channel.
@@ -46,84 +56,79 @@ public final strictfp class ChannelDataI
     @Test
     public void testAllReadMethods() throws IOException {
         final byte[] array = createRandomArray(STREAM_LENGTH);
-        compareStreamToBuffer(array.length - ARRAY_MAX_LENGTH, // Margin against buffer underflow.
-                new DataInputStream(new ByteArrayInputStream(array)),
-                new ChannelDataInput("testAllReadMethods",
-                    new DripByteChannel(array, random, 1, 1024),
-                    ByteBuffer.allocate(random.nextInt(BUFFER_MAX_CAPACITY) + Double.BYTES), false));
+        referenceStream = new DataInputStream(new ByteArrayInputStream(array));
+        testedStream = new ChannelDataInput("testAllReadMethods", new DripByteChannel(array, random, 1, 1024),
+                ByteBuffer.allocate(random.nextInt(BUFFER_MAX_CAPACITY) + Double.BYTES), false);
+        transferRandomData(testedStream, array.length - ARRAY_MAX_LENGTH, 16);
     }
 
     /**
-     * Compares the data returned by the given input to the data returned by the given buffer.
-     *
-     * @param  length Number of bytes in the {@code data} stream.
-     * @param  data   A stream over all expected data.
-     * @param  input  The instance to test.
-     * @throws IOException Should never happen.
+     * Reads a random unit of data using a method selected randomly.
+     * This method is invoked (indirectly) by {@link #testAllReadMethods()}.
      */
-    private void compareStreamToBuffer(final int length, final DataInput data, final ChannelDataInput input) throws IOException {
-        while (input.getStreamPosition() < length) {
-            final int operation = random.nextInt(16);
-            switch (operation) {
-                default: throw new AssertionError(operation);
-                case  0: assertEquals("readByte()",          data.readByte(),              input.readByte());          break;
-                case  1: assertEquals("readShort()",         data.readShort(),             input.readShort());         break;
-                case  2: assertEquals("readUnsignedShort()", data.readUnsignedShort(),     input.readUnsignedShort()); break;
-                case  3: assertEquals("readChar()",          data.readChar(),              input.readChar());          break;
-                case  4: assertEquals("readInt()",           data.readInt(),               input.readInt());           break;
-                case  5: assertEquals("readUnsignedInt()",   data.readInt() & 0xFFFFFFFFL, input.readUnsignedInt());   break;
-                case  6: assertEquals("readLong()",          data.readLong(),              input.readLong());          break;
-                case  7: assertEquals("readFloat()",         data.readFloat(),             input.readFloat(),  0f);    break;
-                case  8: assertEquals("readDouble()",        data.readDouble(),            input.readDouble(), 0d);    break;
-                case  9: {
-                    final int n = random.nextInt(ARRAY_MAX_LENGTH);
-                    final byte[] tmp = new byte[n];
-                    data.readFully(tmp);
-                    assertArrayEquals("readBytes(int)", tmp, input.readBytes(n));
-                    break;
-                }
-                case 10: {
-                    final int n = random.nextInt(ARRAY_MAX_LENGTH / Character.BYTES);
-                    final char[] tmp = new char[n];
-                    for (int i=0; i<n; i++) tmp[i] = data.readChar();
-                    assertArrayEquals("readChars(int)", tmp, input.readChars(n));
-                    break;
-                }
-                case 11: {
-                    final int n = random.nextInt(ARRAY_MAX_LENGTH / Short.BYTES);
-                    final short[] tmp = new short[n];
-                    for (int i=0; i<n; i++) tmp[i] = data.readShort();
-                    assertArrayEquals("readShorts(int)", tmp, input.readShorts(n));
-                    break;
-                }
-                case 12: {
-                    final int n = random.nextInt(ARRAY_MAX_LENGTH / Integer.BYTES);
-                    final int[] tmp = new int[n];
-                    for (int i=0; i<n; i++) tmp[i] = data.readInt();
-                    assertArrayEquals("readInts(int)", tmp, input.readInts(n));
-                    break;
-                }
-                case 13: {
-                    final int n = random.nextInt(ARRAY_MAX_LENGTH / Long.BYTES);
-                    final long[] tmp = new long[n];
-                    for (int i=0; i<n; i++) tmp[i] = data.readLong();
-                    assertArrayEquals("readLongs(int)", tmp, input.readLongs(n));
-                    break;
-                }
-                case 14: {
-                    final int n = random.nextInt(ARRAY_MAX_LENGTH / Float.BYTES);
-                    final float[] tmp = new float[n];
-                    for (int i=0; i<n; i++) tmp[i] = data.readFloat();
-                    assertArrayEquals("readFloats(int)", tmp, input.readFloats(n), 0);
-                    break;
-                }
-                case 15: {
-                    final int n = random.nextInt(ARRAY_MAX_LENGTH / Double.BYTES);
-                    final double[] tmp = new double[n];
-                    for (int i=0; i<n; i++) tmp[i] = data.readDouble();
-                    assertArrayEquals("readDoubles(int)", tmp, input.readDoubles(n), 0);
-                    break;
-                }
+    @Override
+    final void transferRandomData(final int operation) throws IOException {
+        final ChannelDataInput t = testedStream;
+        final DataInput r = referenceStream;
+        switch (operation) {
+            default: throw new AssertionError(operation);
+            case  0: assertEquals("readByte()",          r.readByte(),              t.readByte());          break;
+            case  1: assertEquals("readShort()",         r.readShort(),             t.readShort());         break;
+            case  2: assertEquals("readUnsignedShort()", r.readUnsignedShort(),     t.readUnsignedShort()); break;
+            case  3: assertEquals("readChar()",          r.readChar(),              t.readChar());          break;
+            case  4: assertEquals("readInt()",           r.readInt(),               t.readInt());           break;
+            case  5: assertEquals("readUnsignedInt()",   r.readInt() & 0xFFFFFFFFL, t.readUnsignedInt());   break;
+            case  6: assertEquals("readLong()",          r.readLong(),              t.readLong());          break;
+            case  7: assertEquals("readFloat()",         r.readFloat(),             t.readFloat(),  0f);    break;
+            case  8: assertEquals("readDouble()",        r.readDouble(),            t.readDouble(), 0d);    break;
+            case  9: {
+                final int n = random.nextInt(ARRAY_MAX_LENGTH);
+                final byte[] tmp = new byte[n];
+                r.readFully(tmp);
+                assertArrayEquals("readBytes(int)", tmp, t.readBytes(n));
+                break;
+            }
+            case 10: {
+                final int n = random.nextInt(ARRAY_MAX_LENGTH / Character.BYTES);
+                final char[] tmp = new char[n];
+                for (int i=0; i<n; i++) tmp[i] = r.readChar();
+                assertArrayEquals("readChars(int)", tmp, t.readChars(n));
+                break;
+            }
+            case 11: {
+                final int n = random.nextInt(ARRAY_MAX_LENGTH / Short.BYTES);
+                final short[] tmp = new short[n];
+                for (int i=0; i<n; i++) tmp[i] = r.readShort();
+                assertArrayEquals("readShorts(int)", tmp, t.readShorts(n));
+                break;
+            }
+            case 12: {
+                final int n = random.nextInt(ARRAY_MAX_LENGTH / Integer.BYTES);
+                final int[] tmp = new int[n];
+                for (int i=0; i<n; i++) tmp[i] = r.readInt();
+                assertArrayEquals("readInts(int)", tmp, t.readInts(n));
+                break;
+            }
+            case 13: {
+                final int n = random.nextInt(ARRAY_MAX_LENGTH / Long.BYTES);
+                final long[] tmp = new long[n];
+                for (int i=0; i<n; i++) tmp[i] = r.readLong();
+                assertArrayEquals("readLongs(int)", tmp, t.readLongs(n));
+                break;
+            }
+            case 14: {
+                final int n = random.nextInt(ARRAY_MAX_LENGTH / Float.BYTES);
+                final float[] tmp = new float[n];
+                for (int i=0; i<n; i++) tmp[i] = r.readFloat();
+                assertArrayEquals("readFloats(int)", tmp, t.readFloats(n), 0);
+                break;
+            }
+            case 15: {
+                final int n = random.nextInt(ARRAY_MAX_LENGTH / Double.BYTES);
+                final double[] tmp = new double[n];
+                for (int i=0; i<n; i++) tmp[i] = r.readDouble();
+                assertArrayEquals("readDoubles(int)", tmp, t.readDoubles(n), 0);
+                break;
             }
         }
     }

Modified: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataOutputTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataOutputTest.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataOutputTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataOutputTest.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -194,146 +194,165 @@ public strictfp class ChannelDataOutputT
      * @throws IOException Should never happen.
      */
     private void writeInStreams() throws IOException {
-        final int numOperations = (testedStream instanceof DataOutput) ? 19 : 14;
-        final int length = testedStreamBackingArray.length - ARRAY_MAX_LENGTH; // Keep a margin against buffer underflow.
-        while (testedStream.getStreamPosition() < length) {
-            final int operation = random.nextInt(numOperations);
-            switch (operation) {
-                case 0: {
-                    final byte v = (byte) random.nextInt(1 << Byte.SIZE);
-                    referenceStream.writeByte(v);
-                    testedStream.writeByte(v);
-                    break;
-                }
-                case 1: {
-                    final short v = (short) random.nextInt(1 << Short.SIZE);
-                    referenceStream.writeShort(v);
-                    testedStream.writeShort(v);
-                    break;
-                }
-                case 2: {
-                    final char v = (char) random.nextInt(1 << Character.SIZE);
-                    referenceStream.writeChar(v);
-                    testedStream.writeChar(v);
-                    break;
-                }
-                case 3: {
-                    final int v = random.nextInt();
-                    referenceStream.writeInt(v);
-                    testedStream.writeInt(v);
-                    break;
-                }
-                case 4: {
-                    final long v = random.nextLong();
-                    referenceStream.writeLong(v);
-                    testedStream.writeLong(v);
-                    break;
-                }
-                case 5: {
-                    final float v = random.nextFloat();
-                    referenceStream.writeFloat(v);
-                    testedStream.writeFloat(v);
-                    break;
-                }
-                case 6: {
-                    final double v = random.nextDouble();
-                    referenceStream.writeDouble(v);
-                    testedStream.writeDouble(v);
-                    break;
-                }
-                case 7: {
-                    final byte[] tmp = new byte[random.nextInt(ARRAY_MAX_LENGTH / Byte.BYTES)];
-                    random.nextBytes(tmp);
-                    referenceStream.write(tmp);
-                    testedStream.write(tmp);
-                    break;
-                }
-                case 8: {
-                    final char[] tmp = new char[random.nextInt(ARRAY_MAX_LENGTH / Character.BYTES)];
-                    for (int i=0; i<tmp.length; i++) {
-                        referenceStream.writeChar(tmp[i] = (char) random.nextInt(1 << Character.SIZE));
-                    }
-                    testedStream.writeChars(tmp);
-                    break;
-                }
-                case 9: {
-                    final short[] tmp = new short[random.nextInt(ARRAY_MAX_LENGTH / Short.BYTES)];
-                    for (int i=0; i<tmp.length; i++) {
-                        referenceStream.writeShort(tmp[i] = (short) random.nextInt(1 << Short.SIZE));
-                    }
-                    testedStream.writeShorts(tmp);
-                    break;
-                }
-                case 10: {
-                    final int[] tmp = new int[random.nextInt(ARRAY_MAX_LENGTH / Integer.BYTES)];
-                    for (int i=0; i<tmp.length; i++) {
-                        referenceStream.writeInt(tmp[i] = random.nextInt());
-                    }
-                    testedStream.writeInts(tmp);
-                    break;
-                }
-                case 11: {
-                    final long[] tmp = new long[random.nextInt(ARRAY_MAX_LENGTH / Long.BYTES)];
-                    for (int i=0; i<tmp.length; i++) {
-                        referenceStream.writeLong(tmp[i] = random.nextLong());
-                    }
-                    testedStream.writeLongs(tmp);
-                    break;
-                }
-                case 12: {
-                    final float[] tmp = new float[random.nextInt(ARRAY_MAX_LENGTH / Float.BYTES)];
-                    for (int i=0; i<tmp.length; i++) {
-                        referenceStream.writeFloat(tmp[i] = random.nextFloat());
-                    }
-                    testedStream.writeFloats(tmp);
-                    break;
-                }
-                case 13: {
-                    final double[] tmp = new double[random.nextInt(ARRAY_MAX_LENGTH / Double.BYTES)];
-                    for (int i=0; i<tmp.length; i++) {
-                        referenceStream.writeDouble(tmp[i] = random.nextDouble());
-                    }
-                    testedStream.writeDoubles(tmp);
-                    break;
-                }
-                /*
-                 * Cases below this point are executed only by ChannelImageOutputStreamTest.
-                 */
-                case 14: {
-                    final long v = random.nextLong();
-                    final int numBits = random.nextInt(Byte.SIZE);
-                    ((ImageOutputStream) referenceStream).writeBits(v, numBits);
-                    testedStream.writeBits(v, numBits);
-                    break;
-                }
-                case 15: {
-                    final boolean v = random.nextBoolean();
-                    referenceStream.writeBoolean(v);
-                    ((DataOutput) testedStream).writeBoolean(v);
-                    break;
-                }
-                case 16: {
-                    final String s = "Byte sequence";
-                    referenceStream.writeBytes(s);
-                    ((DataOutput) testedStream).writeBytes(s);
-                    break;
-                }
-                case 17: {
-                    final String s = "Character sequence";
-                    referenceStream.writeChars(s);
-                    ((DataOutput) testedStream).writeChars(s);
-                    break;
-                }
-                case 18: {
-                    final String s = "お元気ですか";
-                    final byte[] array = s.getBytes("UTF-8");
-                    assertEquals(s.length() * 3, array.length); // Sanity check.
-                    referenceStream.writeUTF(s);
-                    ((DataOutput) testedStream).writeUTF(s);
-                    break;
+        transferRandomData(testedStream, testedStreamBackingArray.length - ARRAY_MAX_LENGTH,
+                (testedStream instanceof DataOutput) ? 20 : 14);
+    }
+
+    /**
+     * Writes a random unit of data using a method selected randomly.
+     * This method is invoked (indirectly) by {@link #writeInStreams()}.
+     */
+    @Override
+    final void transferRandomData(final int operation) throws IOException {
+        final DataOutput r = this.referenceStream;
+        final ChannelDataOutput t = this.testedStream;
+        switch (operation) {
+            case 0: {
+                final byte v = (byte) random.nextInt(1 << Byte.SIZE);
+                r.writeByte(v);
+                t.writeByte(v);
+                break;
+            }
+            case 1: {
+                final short v = (short) random.nextInt(1 << Short.SIZE);
+                r.writeShort(v);
+                t.writeShort(v);
+                break;
+            }
+            case 2: {
+                final char v = (char) random.nextInt(1 << Character.SIZE);
+                r.writeChar(v);
+                t.writeChar(v);
+                break;
+            }
+            case 3: {
+                final int v = random.nextInt();
+                r.writeInt(v);
+                t.writeInt(v);
+                break;
+            }
+            case 4: {
+                final long v = random.nextLong();
+                r.writeLong(v);
+                t.writeLong(v);
+                break;
+            }
+            case 5: {
+                final float v = random.nextFloat();
+                r.writeFloat(v);
+                t.writeFloat(v);
+                break;
+            }
+            case 6: {
+                final double v = random.nextDouble();
+                r.writeDouble(v);
+                t.writeDouble(v);
+                break;
+            }
+            case 7: {
+                final byte[] tmp = new byte[random.nextInt(ARRAY_MAX_LENGTH / Byte.BYTES)];
+                random.nextBytes(tmp);
+                r.write(tmp);
+                t.write(tmp);
+                break;
+            }
+            case 8: {
+                final char[] tmp = new char[random.nextInt(ARRAY_MAX_LENGTH / Character.BYTES)];
+                for (int i=0; i<tmp.length; i++) {
+                    r.writeChar(tmp[i] = (char) random.nextInt(1 << Character.SIZE));
+                }
+                t.writeChars(tmp);
+                break;
+            }
+            case 9: {
+                final short[] tmp = new short[random.nextInt(ARRAY_MAX_LENGTH / Short.BYTES)];
+                for (int i=0; i<tmp.length; i++) {
+                    r.writeShort(tmp[i] = (short) random.nextInt(1 << Short.SIZE));
+                }
+                t.writeShorts(tmp);
+                break;
+            }
+            case 10: {
+                final int[] tmp = new int[random.nextInt(ARRAY_MAX_LENGTH / Integer.BYTES)];
+                for (int i=0; i<tmp.length; i++) {
+                    r.writeInt(tmp[i] = random.nextInt());
                 }
-                default: throw new AssertionError(operation);
+                t.writeInts(tmp);
+                break;
             }
+            case 11: {
+                final long[] tmp = new long[random.nextInt(ARRAY_MAX_LENGTH / Long.BYTES)];
+                for (int i=0; i<tmp.length; i++) {
+                    r.writeLong(tmp[i] = random.nextLong());
+                }
+                t.writeLongs(tmp);
+                break;
+            }
+            case 12: {
+                final float[] tmp = new float[random.nextInt(ARRAY_MAX_LENGTH / Float.BYTES)];
+                for (int i=0; i<tmp.length; i++) {
+                    r.writeFloat(tmp[i] = random.nextFloat());
+                }
+                t.writeFloats(tmp);
+                break;
+            }
+            case 13: {
+                final double[] tmp = new double[random.nextInt(ARRAY_MAX_LENGTH / Double.BYTES)];
+                for (int i=0; i<tmp.length; i++) {
+                    r.writeDouble(tmp[i] = random.nextDouble());
+                }
+                t.writeDoubles(tmp);
+                break;
+            }
+            /*
+             * Cases below this point are executed only by ChannelImageOutputStreamTest.
+             */
+            case 14: {
+                final long v = random.nextLong();
+                final int numBits = random.nextInt(Byte.SIZE);
+                ((ImageOutputStream) r).writeBits(v, numBits);
+                t.writeBits(v, numBits);
+                break;
+            }
+            case 15: {
+                final boolean v = random.nextBoolean();
+                r.writeBoolean(v);
+                ((DataOutput) t).writeBoolean(v);
+                break;
+            }
+            case 16: {
+                final String s = "Byte sequence";
+                r.writeBytes(s);
+                ((DataOutput) t).writeBytes(s);
+                break;
+            }
+            case 17: {
+                final String s = "Character sequence";
+                r.writeChars(s);
+                ((DataOutput) t).writeChars(s);
+                break;
+            }
+            case 18: {
+                final String s = "お元気ですか";
+                final byte[] array = s.getBytes("UTF-8");
+                assertEquals(s.length() * 3, array.length); // Sanity check.
+                r.writeUTF(s);
+                ((DataOutput) t).writeUTF(s);
+                break;
+            }
+            case 19: {
+                final ImageOutputStream ir = (ImageOutputStream) r;
+                long flushedPosition = StrictMath.max(ir.getFlushedPosition(), t.getFlushedPosition());
+                flushedPosition += random.nextInt(1 + (int) (ir.getStreamPosition() - flushedPosition));
+                ir.flushBefore(flushedPosition);
+                t .flushBefore(flushedPosition);
+                break;
+            }
+            default: throw new AssertionError(operation);
+        }
+        if (r instanceof ImageOutputStream) {
+            assertEquals("getBitOffset()",      ((ImageOutputStream) r).getBitOffset(),      t.getBitOffset());
+            assertEquals("getStreamPosition()", ((ImageOutputStream) r).getStreamPosition(), t.getStreamPosition());
         }
     }
 }

Modified: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataTestCase.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataTestCase.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelDataTestCase.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -18,8 +18,10 @@ package org.apache.sis.internal.storage;
 
 
 import java.util.Random;
+import java.io.IOException;
 import org.apache.sis.test.TestCase;
 import org.apache.sis.test.TestUtilities;
+import org.apache.sis.util.Debug;
 
 
 /**
@@ -64,6 +66,68 @@ abstract strictfp class ChannelDataTestC
     }
 
     /**
+     * Edit this number if break point is desired in the execution of {@link #transferRandomData(int)}.
+     * The breakpoint value is the value given by the {@code "Iter. count"} line on the console.
+     *
+     * <p>This breakpoint is useful only if the {@link #random} has been fixed to a constant seed.</p>
+     */
+    @Debug
+    private static final int BREAKPOINT = 0;
+
+    /**
+     * Invoked when the iteration count reaches the {@link #BREAKPOINT} value.
+     */
+    @Debug
+    void breakpoint() {
+    }
+
+    /**
+     * Transfers many random data between the channel and the buffer.
+     * This method invokes {@link #transferRandomData(int)} in a loop,
+     * with an operation identifier selected randomly between 0 inclusive to {@code numOperations} exclusive.
+     *
+     * @param  testedStream  The stream to be tested.
+     * @param  length        Length threshold for stopping the test. Shall be the backing array length
+     *                       minus {@link #ARRAY_MAX_LENGTH}, in order to keep a margin for test cases.
+     * @param  numOperations Number of operations to be tested randomly.
+     * @throws IOException If an I/O error occurred.
+     */
+    final void transferRandomData(final ChannelData testedStream, final int length, final int numOperations)
+            throws IOException
+    {
+        long position  = 0;
+        int  bitOffset = 0;
+        int  operation = 0;
+        int  count     = 0;
+        try {
+            while ((position = testedStream.getStreamPosition()) < length) {
+                if (++count == BREAKPOINT) {
+                    breakpoint();
+                }
+                bitOffset = testedStream.getBitOffset();
+                operation = random.nextInt(numOperations);
+                transferRandomData(operation);
+            }
+        } catch (AssertionError | RuntimeException e) {
+            out.println("Iter. count: " + count);
+            out.println("Position:    " + position);
+            out.println("Bit offset:  " + bitOffset);
+            out.println("Byte order:  " + testedStream.buffer.order());
+            out.println("Operation:   " + operation);
+            out.println("Exception:   " + e.getLocalizedMessage());
+            throw e;
+        }
+    }
+
+    /**
+     * Transfers random data using a method selected randomly.
+     *
+     * @param  operation An identifier of the method to use for transfering data.
+     * @throws IOException If an I/O error occurred.
+     */
+    abstract void transferRandomData(final int operation) throws IOException;
+
+    /**
      * Creates an array filled with random values.
      *
      * @param length The length of the array to create.

Modified: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageInputStreamTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageInputStreamTest.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageInputStreamTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageInputStreamTest.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -36,12 +36,22 @@ import static org.junit.Assert.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-3.07)
- * @version 0.3
+ * @version 0.5
  * @module
  */
 @DependsOn(ChannelDataInputTest.class)
 public final strictfp class ChannelImageInputStreamTest extends ChannelDataTestCase {
     /**
+     * The implementation to test.
+     */
+    private ChannelImageInputStream testedStream;
+
+    /**
+     * A stream to use as a reference implementation.
+     */
+    private ImageInputStream referenceStream;
+
+    /**
      * Fills a buffer with random data and compares the result with a standard image input stream.
      * We will allocate a small buffer for the {@code ChannelImageInputStream} in order to force
      * frequent interactions between the buffer and the channel.
@@ -50,130 +60,125 @@ public final strictfp class ChannelImage
      */
     @Test
     public void testWithRandomData() throws IOException {
-        long position = 0;
-        int bitOffset = 0;
-        int operation = 0;
-        final ByteBuffer buffer = ByteBuffer.allocate(128);
+        final ByteBuffer buffer = ByteBuffer.allocate(BUFFER_MAX_CAPACITY);
         final ByteOrder byteOrder = random.nextBoolean() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
         final byte[] data = createRandomArray(STREAM_LENGTH);
-        try (ImageInputStream r = ImageIO.createImageInputStream(new ByteArrayInputStream(data));
-             ImageInputStream t = new ChannelImageInputStream("Test data",
-                     Channels.newChannel(new ByteArrayInputStream(data)), buffer, false))
-        {
-            r.setByteOrder(byteOrder);
-            t.setByteOrder(byteOrder);
-            while ((position = r.getStreamPosition()) < data.length - ARRAY_MAX_LENGTH) {
-                bitOffset = r.getBitOffset();
-                operation = random.nextInt(24);
-                switch (operation) {
-                    default: throw new AssertionError(operation);
-                    case  0: assertEquals("read()",              r.read(),              t.read());              break;
-                    case  1: assertEquals("readBoolean()",       r.readBoolean(),       t.readBoolean());       break;
-                    case  2: assertEquals("readChar()",          r.readChar(),          t.readChar());          break;
-                    case  3: assertEquals("readByte()",          r.readByte(),          t.readByte());          break;
-                    case  4: assertEquals("readShort()",         r.readShort(),         t.readShort());         break;
-                    case  5: assertEquals("readUnsignedShort()", r.readUnsignedShort(), t.readUnsignedShort()); break;
-                    case  6: assertEquals("readInt()",           r.readInt(),           t.readInt());           break;
-                    case  7: assertEquals("readUnsignedInt()",   r.readUnsignedInt(),   t.readUnsignedInt());   break;
-                    case  8: assertEquals("readLong()",          r.readLong(),          t.readLong());          break;
-                    case  9: assertEquals("readFloat()",         r.readFloat(),         t.readFloat(),  0f);    break;
-                    case 10: assertEquals("readDouble()",        r.readDouble(),        t.readDouble(), 0d);    break;
-                    case 11: assertEquals("readBit()",           r.readBit(),           t.readBit());           break;
-                    case 12: {
-                        final int n = random.nextInt(Long.SIZE + 1);
-                        assertEquals("readBits(" + n + ')', r.readBits(n), t.readBits(n));
-                        break;
-                    }
-                    case 13: {
-                        final int length = random.nextInt(ARRAY_MAX_LENGTH);
-                        final byte[] actual = new byte[length];
-                        final int n = t.read(actual);
-                        assertFalse("Reached EOF", n < 0);
-                        final byte[] expected = new byte[n];
-                        r.readFully(expected);
-                        assertArrayEquals("read(byte[])", expected, actual);
-                        break;
-                    }
-                    case 14: {
-                        final int length = random.nextInt(ARRAY_MAX_LENGTH);
-                        final byte[] expected = new byte[length]; r.readFully(expected);
-                        final byte[] actual   = new byte[length]; t.readFully(actual);
-                        assertArrayEquals("readFully(byte[])", expected, actual);
-                        break;
-                    }
-                    case 15: {
-                        final int length = random.nextInt(ARRAY_MAX_LENGTH / Character.BYTES);
-                        final char[] expected = new char[length]; r.readFully(expected, 0, length);
-                        final char[] actual   = new char[length]; t.readFully(actual,   0, length);
-                        assertArrayEquals("readFully(char[])", expected, actual);
-                        break;
-                    }
-                    case 16: {
-                        final int length = random.nextInt(ARRAY_MAX_LENGTH / Short.BYTES);
-                        final short[] expected = new short[length]; r.readFully(expected, 0, length);
-                        final short[] actual   = new short[length]; t.readFully(actual,   0, length);
-                        assertArrayEquals("readFully(short[])", expected, actual);
-                        break;
-                    }
-                    case 17: {
-                        final int length = random.nextInt(ARRAY_MAX_LENGTH / Integer.BYTES);
-                        final int[] expected = new int[length]; r.readFully(expected, 0, length);
-                        final int[] actual   = new int[length]; t.readFully(actual,   0, length);
-                        assertArrayEquals("readFully(int[])", expected, actual);
-                        break;
-                    }
-                    case 18: {
-                        final int length = random.nextInt(ARRAY_MAX_LENGTH / Long.BYTES);
-                        final long[] expected = new long[length]; r.readFully(expected, 0, length);
-                        final long[] actual   = new long[length]; t.readFully(actual,   0, length);
-                        assertArrayEquals("readFully(long[])", expected, actual);
-                        break;
-                    }
-                    case 19: {
-                        final int length = random.nextInt(ARRAY_MAX_LENGTH / Float.BYTES);
-                        final float[] expected = new float[length]; r.readFully(expected, 0, length);
-                        final float[] actual   = new float[length]; t.readFully(actual,   0, length);
-                        assertTrue("readFully(float[])", Arrays.equals(expected, actual));
-                        break;
-                    }
-                    case 20: {
-                        final int length = random.nextInt(ARRAY_MAX_LENGTH / Double.BYTES);
-                        final double[] expected = new double[length]; r.readFully(expected, 0, length);
-                        final double[] actual   = new double[length]; t.readFully(actual,   0, length);
-                        assertTrue("readFully(double[])", Arrays.equals(expected, actual));
-                        break;
-                    }
-                    case 21: {
-                        final long length = random.nextInt(ARRAY_MAX_LENGTH);
-                        final long n = t.skipBytes(length);
-                        assertFalse("Reached EOF", n < 0);
-                        r.readFully(new byte[(int) n]);
-                        assertEquals("skipBytes(int)", r.getStreamPosition(), t.getStreamPosition());
-                        break;
-                    }
-                    case 22: {
-                        long flushedPosition = StrictMath.max(r.getFlushedPosition(), t.getFlushedPosition());
-                        flushedPosition += random.nextInt(1 + (int) (r.getStreamPosition() - flushedPosition));
-                        r.flushBefore(flushedPosition);
-                        t.flushBefore(flushedPosition);
-                        break;
-                    }
-                    case 23: {
-                        r.flush();
-                        t.flush();
-                        break;
-                    }
-                }
-                assertEquals("getStreamPosition()", r.getStreamPosition(), t.getStreamPosition());
-                assertEquals("getBitOffset()",      r.getBitOffset(),      t.getBitOffset());
-            }
-        } catch (AssertionError | RuntimeException e) {
-            out.println("Position:    " + position);
-            out.println("Bit offset:  " + bitOffset);
-            out.println("Byte order:  " + byteOrder);
-            out.println("Operation:   " + operation);
-            out.println("Exception:   " + e.getLocalizedMessage());
-            throw e;
+        referenceStream = ImageIO.createImageInputStream(new ByteArrayInputStream(data));
+        referenceStream.setByteOrder(byteOrder);
+        testedStream = new ChannelImageInputStream("testWithRandomData",
+                Channels.newChannel(new ByteArrayInputStream(data)), buffer, false);
+        testedStream.setByteOrder(byteOrder);
+        transferRandomData(testedStream, data.length - ARRAY_MAX_LENGTH, 24);
+    }
+
+    /**
+     * Reads a random unit of data using a method selected randomly.
+     * This method is invoked (indirectly) by {@link #testWithRandomData()}.
+     */
+    @Override
+    final void transferRandomData(final int operation) throws IOException {
+        final ChannelImageInputStream t = testedStream;
+        final ImageInputStream r = referenceStream;
+        switch (operation) {
+            default: throw new AssertionError(operation);
+            case  0: assertEquals("read()",              r.read(),              t.read());              break;
+            case  1: assertEquals("readBoolean()",       r.readBoolean(),       t.readBoolean());       break;
+            case  2: assertEquals("readChar()",          r.readChar(),          t.readChar());          break;
+            case  3: assertEquals("readByte()",          r.readByte(),          t.readByte());          break;
+            case  4: assertEquals("readShort()",         r.readShort(),         t.readShort());         break;
+            case  5: assertEquals("readUnsignedShort()", r.readUnsignedShort(), t.readUnsignedShort()); break;
+            case  6: assertEquals("readInt()",           r.readInt(),           t.readInt());           break;
+            case  7: assertEquals("readUnsignedInt()",   r.readUnsignedInt(),   t.readUnsignedInt());   break;
+            case  8: assertEquals("readLong()",          r.readLong(),          t.readLong());          break;
+            case  9: assertEquals("readFloat()",         r.readFloat(),         t.readFloat(),  0f);    break;
+            case 10: assertEquals("readDouble()",        r.readDouble(),        t.readDouble(), 0d);    break;
+            case 11: assertEquals("readBit()",           r.readBit(),           t.readBit());           break;
+            case 12: {
+                final int n = random.nextInt(Long.SIZE + 1);
+                assertEquals("readBits(" + n + ')', r.readBits(n), t.readBits(n));
+                break;
+            }
+            case 13: {
+                final int length = random.nextInt(ARRAY_MAX_LENGTH);
+                final byte[] actual = new byte[length];
+                final int n = t.read(actual);
+                assertFalse("Reached EOF", n < 0);
+                final byte[] expected = new byte[n];
+                r.readFully(expected);
+                assertArrayEquals("read(byte[])", expected, actual);
+                break;
+            }
+            case 14: {
+                final int length = random.nextInt(ARRAY_MAX_LENGTH);
+                final byte[] expected = new byte[length]; r.readFully(expected);
+                final byte[] actual   = new byte[length]; t.readFully(actual);
+                assertArrayEquals("readFully(byte[])", expected, actual);
+                break;
+            }
+            case 15: {
+                final int length = random.nextInt(ARRAY_MAX_LENGTH / Character.BYTES);
+                final char[] expected = new char[length]; r.readFully(expected, 0, length);
+                final char[] actual   = new char[length]; t.readFully(actual,   0, length);
+                assertArrayEquals("readFully(char[])", expected, actual);
+                break;
+            }
+            case 16: {
+                final int length = random.nextInt(ARRAY_MAX_LENGTH / Short.BYTES);
+                final short[] expected = new short[length]; r.readFully(expected, 0, length);
+                final short[] actual   = new short[length]; t.readFully(actual,   0, length);
+                assertArrayEquals("readFully(short[])", expected, actual);
+                break;
+            }
+            case 17: {
+                final int length = random.nextInt(ARRAY_MAX_LENGTH / Integer.BYTES);
+                final int[] expected = new int[length]; r.readFully(expected, 0, length);
+                final int[] actual   = new int[length]; t.readFully(actual,   0, length);
+                assertArrayEquals("readFully(int[])", expected, actual);
+                break;
+            }
+            case 18: {
+                final int length = random.nextInt(ARRAY_MAX_LENGTH / Long.BYTES);
+                final long[] expected = new long[length]; r.readFully(expected, 0, length);
+                final long[] actual   = new long[length]; t.readFully(actual,   0, length);
+                assertArrayEquals("readFully(long[])", expected, actual);
+                break;
+            }
+            case 19: {
+                final int length = random.nextInt(ARRAY_MAX_LENGTH / Float.BYTES);
+                final float[] expected = new float[length]; r.readFully(expected, 0, length);
+                final float[] actual   = new float[length]; t.readFully(actual,   0, length);
+                assertTrue("readFully(float[])", Arrays.equals(expected, actual));
+                break;
+            }
+            case 20: {
+                final int length = random.nextInt(ARRAY_MAX_LENGTH / Double.BYTES);
+                final double[] expected = new double[length]; r.readFully(expected, 0, length);
+                final double[] actual   = new double[length]; t.readFully(actual,   0, length);
+                assertTrue("readFully(double[])", Arrays.equals(expected, actual));
+                break;
+            }
+            case 21: {
+                final long length = random.nextInt(ARRAY_MAX_LENGTH);
+                final long n = t.skipBytes(length);
+                assertFalse("Reached EOF", n < 0);
+                r.readFully(new byte[(int) n]);
+                assertEquals("skipBytes(int)", r.getStreamPosition(), t.getStreamPosition());
+                break;
+            }
+            case 22: {
+                long flushedPosition = StrictMath.max(r.getFlushedPosition(), t.getFlushedPosition());
+                flushedPosition += random.nextInt(1 + (int) (r.getStreamPosition() - flushedPosition));
+                r.flushBefore(flushedPosition);
+                t.flushBefore(flushedPosition);
+                break;
+            }
+            case 23: {
+                r.flush();
+                t.flush();
+                break;
+            }
         }
+        assertEquals("getStreamPosition()", r.getStreamPosition(), t.getStreamPosition());
+        assertEquals("getBitOffset()",      r.getBitOffset(),      t.getBitOffset());
     }
 }

Modified: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageOutputStreamTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageOutputStreamTest.java?rev=1590057&r1=1590056&r2=1590057&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageOutputStreamTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/ChannelImageOutputStreamTest.java [UTF-8] Fri Apr 25 15:23:32 2014
@@ -65,13 +65,13 @@ public final strictfp class ChannelImage
             /*
              * Randomly force flushing of bits.
              */
-            if (random.nextInt(16) == 0) {
+            if (random.nextInt(256) == 0) {
                 final int f = random.nextInt(256);
                 referenceStream.writeByte(f);
                 testedStream.writeByte(f);
             }
-//            assertEquals("getStreamPosition", referenceStream.getStreamPosition(), testedStream.getStreamPosition());
             assertEquals("getBitOffset", referenceStream.getBitOffset(), testedStream.getBitOffset());
+            assertEquals("getStreamPosition", referenceStream.getStreamPosition(), testedStream.getStreamPosition());
         }
         assertStreamContentEquals();
     }