db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From krist...@apache.org
Subject svn commit: r605531 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/util/UTF8Util.java testing/org/apache/derbyTesting/unitTests/junit/UTF8UtilTest.java testing/org/apache/derbyTesting/unitTests/junit/_Suite.java
Date Wed, 19 Dec 2007 13:09:30 GMT
Author: kristwaa
Date: Wed Dec 19 05:09:19 2007
New Revision: 605531

URL: http://svn.apache.org/viewvc?rev=605531&view=rev
Log:
DERBY-2760: Clean-up issues for UTF8Util.java. Added tests. Added internal result-holder class
to UTF8Util.
Patch-file: derby-2760-2b-inner_class.diff

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/UTF8UtilTest.java
  (with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/util/UTF8Util.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/_Suite.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/util/UTF8Util.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/util/UTF8Util.java?rev=605531&r1=605530&r2=605531&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/util/UTF8Util.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/util/UTF8Util.java Wed Dec 19 05:09:19
2007
@@ -40,11 +40,6 @@
 //@ThreadSafe
 public final class UTF8Util {
 
-    /** Constant used to look up character count in an array. */
-    private static final int CHAR_COUNT = 0;
-    /** Constant used to look up byte count in an array. */
-    private static final int BYTE_COUNT = 1;
-
     /** This class cannot be instantiated. */
     private UTF8Util() {}
 
@@ -61,7 +56,7 @@
         // No need to do the skip in a loop, as Reader.read() returning -1
         // means EOF has been reached.
         // Note that a loop should be used if skip is used instead of read.
-        return internalSkip(in, Long.MAX_VALUE)[CHAR_COUNT];
+        return internalSkip(in, Long.MAX_VALUE).charsSkipped();
     }
 
     /**
@@ -77,13 +72,13 @@
      */
     public static final long skipFully(InputStream in, long charsToSkip)
             throws EOFException, IOException {
-        long[] counts = internalSkip(in, charsToSkip);
-        if (counts[CHAR_COUNT] != charsToSkip) {
+        SkipCount skipped = internalSkip(in, charsToSkip);
+        if (skipped.charsSkipped() != charsToSkip) {
             throw new EOFException("Reached end-of-stream prematurely at " +
-                "character/byte position " + counts[CHAR_COUNT] + "/" +
-                counts[BYTE_COUNT] + ", trying to skip " + charsToSkip);
+                "character/byte position " + skipped.charsSkipped() + "/" +
+                skipped.bytesSkipped() + ", trying to skip " + charsToSkip);
         }
-        return counts[BYTE_COUNT];
+        return skipped.bytesSkipped();
     }
 
     /**
@@ -105,8 +100,8 @@
      * @throws IOException if reading from the stream fails
      * @throws UTFDataFormatException if an invalid UTF-8 encoding is detected
      */
-    private static final long[] internalSkip(final InputStream in,
-                                             final long charsToSkip)
+    private static final SkipCount internalSkip(final InputStream in,
+                                                final long charsToSkip)
             throws IOException {
         long charsSkipped = 0;
         long bytesSkipped = 0;
@@ -166,7 +161,7 @@
         }
         // We don't close the stream, since it might be reused. One example of
         // this is use of Resetable streams.
-        return new long[] {charsSkipped, bytesSkipped};
+        return new SkipCount(charsSkipped, bytesSkipped);
     }
 
     /**
@@ -198,5 +193,46 @@
             skipped += skippedNow;
         }
         return skipped;
+    }
+
+    /**
+     * Helper class to hold skip counts; one for chars and one for bytes.
+     */
+    // @Immutable
+    private static final class SkipCount {
+        /** Number of bytes skipped. */
+        private final long byteCount;
+        /** Number of characters skipped. */
+        private final long charCount; 
+
+        /**
+         * Creates a holder for the specified skip counts.
+         * 
+         * @param byteCount number of bytes
+         * @param charCount number of characters
+         */
+        SkipCount(long charCount, long byteCount) {
+            if (byteCount < 0 || charCount < 0) {
+                // Don't allow negative counts.
+                throw new IllegalArgumentException("charCount/byteCount " +
+                        "cannot be negative: " + charCount + "/" + byteCount);
+            }
+            if (byteCount < charCount) {
+                // A char must always be represented by at least one byte.
+                throw new IllegalArgumentException("Number of bytes cannot be" +
+                        "less than number of chars: " + byteCount + " < " +
+                        charCount);
+            }
+            this.byteCount = byteCount;
+            this.charCount = charCount;
+        }
+
+        long charsSkipped() {
+            return this.charCount;
+        }
+
+        long bytesSkipped() {
+            return this.byteCount;
+        }
     }
 } // End class UTF8Util

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/UTF8UtilTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/UTF8UtilTest.java?rev=605531&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/UTF8UtilTest.java
(added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/UTF8UtilTest.java
Wed Dec 19 05:09:19 2007
@@ -0,0 +1,209 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.junit.UTF8UtilTest
+
+   Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you 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.apache.derbyTesting.unitTests.junit;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import java.io.UTFDataFormatException;
+import org.apache.derby.iapi.types.ReaderToUTF8Stream;
+import org.apache.derby.iapi.util.UTF8Util;
+
+import org.apache.derbyTesting.functionTests.util.streams.CharAlphabet;
+import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader;
+import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetStream;
+import org.apache.derbyTesting.junit.BaseTestCase;
+
+/**
+ * Tests that <code>skipFully</code> and <code>skipUntilEOF</code>
behaves
+ * correctly on Derby's modfied UTF-8 encoded streams.
+ * <p>
+ * These tests are dependent on the behavior of <code>ReaderToUTF8Stream</code>.
+ * Note that this class inserts two bytes at the start of the user/application
+ * stream to encode the length of the stream. These two bytes may be zero, even
+ * if the stream is short enough for its length to be encoded.
+ * <p>
+ * Also note that the lengths chosen for large streams are just suitably large
+ * integers. The point is to choose them large enough to make sure buffer
+ * boundaries are crossed.
+ * 
+ * @see ReaderToUTF8Stream
+ * @see UTF8Util
+ */
+public class UTF8UtilTest
+    extends BaseTestCase {
+
+    /**
+     * Creates a test of the specified name.
+     */
+    public UTF8UtilTest(String name) {
+        super(name);
+    }
+
+    /**
+     * Ensure the assumption that the default looping alphabet stream and the
+     * modified UTF-8 encoding is equal.
+     * <p>
+     * If this assumption is broken, several of the other tests will fail.
+     */
+    public void testEqualityOfModifedUTF8AndASCII()
+            throws IOException {
+        final int length = 12706;
+        InputStream ascii = new LoopingAlphabetStream(length);
+        InputStream modUTF8 = new ReaderToUTF8Stream(
+                                    new LoopingAlphabetReader(length),
+                                    length, 0, "ignored-test-type");
+        modUTF8.skip(2L); // Skip encoded length added by ReaderToUTF8Stream.
+        assertEquals(ascii, modUTF8);
+    }
+
+    public void testSkipUntilEOFOnZeroLengthStream()
+            throws IOException {
+        assertEquals(0, UTF8Util.skipUntilEOF(new LoopingAlphabetStream(0)));
+    }
+    
+    public void testSkipUntilEOFOnShortStreamASCII()
+            throws IOException {
+        assertEquals(5, UTF8Util.skipUntilEOF(new LoopingAlphabetStream(5)));
+    }
+
+    public void testSkipUntilEOFOnShortStreamCJK()
+            throws IOException {
+        final int charLength = 5;
+        InputStream in = new ReaderToUTF8Stream(
+                new LoopingAlphabetReader(charLength, CharAlphabet.cjkSubset()),
+                charLength, 0, "ignored-test-type");
+        in.skip(2L); // Skip encoded length added by ReaderToUTF8Stream.
+        assertEquals(charLength, UTF8Util.skipUntilEOF(in));
+    }
+
+    public void testSkipUntilEOFOnLongStreamASCII()
+            throws IOException {
+        assertEquals(127019, UTF8Util.skipUntilEOF(
+                new LoopingAlphabetStream(127019)));
+    }
+    
+    public void testSkipUntilEOFOnLongStreamCJK()
+            throws IOException {
+        final int charLength = 127019;
+        InputStream in = new ReaderToUTF8Stream(
+                new LoopingAlphabetReader(charLength, CharAlphabet.cjkSubset()),
+                charLength, 0, "ignored-test-type");
+        in.skip(2L); // Skip encoded length added by ReaderToUTF8Stream.
+        assertEquals(charLength, UTF8Util.skipUntilEOF(in));
+    }
+
+    /**
+     * Tests that <code>skipFully</code> successfully skips the requested
+     * characters and returns the correct number of bytes skipped.
+     * 
+     * @throws IOException if the test fails for some unexpected reason
+     */
+    public void testSkipFullyOnValidLongStreamCJK()
+            throws IOException {
+        final int charLength = 161019;
+        InputStream in = new ReaderToUTF8Stream(
+                new LoopingAlphabetReader(charLength, CharAlphabet.cjkSubset()),
+                charLength, 0, "ignored-test-type");
+        in.skip(2L); // Skip encoded length added by ReaderToUTF8Stream.
+        // Returns count in bytes, we are using CJK chars so multiply length
+        // with 3 to get expected number of bytes.
+        assertEquals(charLength *3, UTF8Util.skipFully(in, charLength));
+    }
+
+    /**
+     * Tests that <code>skipFully</code> throws exception if the stream contains
+     * less characters than the requested number of characters to skip.
+     * 
+     * @throws IOException if the test fails for some unexpected reason
+     */
+    public void testSkipFullyOnTooShortStreamCJK()
+            throws IOException {
+        final int charLength = 161019;
+        InputStream in = new ReaderToUTF8Stream(
+                new LoopingAlphabetReader(charLength, CharAlphabet.cjkSubset()),
+                charLength, 0, "ignored-test-type");
+        in.skip(2L); // Skip encoded length added by ReaderToUTF8Stream.
+        try {
+            UTF8Util.skipFully(in, charLength + 100);
+            fail("Should have failed because of too short stream.");
+        } catch (EOFException eofe) {
+            // As expected, do nothing.
+        }
+    }
+    
+    /**
+     * Tests that <code>skipFully</code> throws exception if there is a UTF-8
+     * encoding error in the stream
+     * 
+     * @throws IOException if the test fails for some unexpected reason
+     */
+    public void testSkipFullyOnInvalidStreamCJK()
+            throws IOException {
+        final int charLength = 10;
+        InputStream in = new ReaderToUTF8Stream(
+                new LoopingAlphabetReader(charLength, CharAlphabet.cjkSubset()),
+                charLength, 0, "ignored-test-type");
+        in.skip(2L); // Skip encoded length added by ReaderToUTF8Stream.
+        in.skip(1L); // Skip one more byte to trigger a UTF error.
+        try {
+            UTF8Util.skipFully(in, charLength);
+            fail("Should have failed because of UTF error.");
+        } catch (UTFDataFormatException udfe) {
+            // As expected, do nothing.
+        }
+    }
+
+    /**
+     * Tests a sequence of skip calls.
+     */
+    public void testMixedSkipOnStreamTamil()
+            throws IOException {
+        final int charLength = 161019;
+        InputStream in = new ReaderToUTF8Stream(
+                new LoopingAlphabetReader(charLength, CharAlphabet.tamil()),
+                charLength, 0, "ignored-test-type");
+        in.skip(2L); // Skip encoded length added by ReaderToUTF8Stream.
+        int firstSkip = 10078;
+        assertEquals(firstSkip*3, UTF8Util.skipFully(in, firstSkip));
+        assertEquals(charLength - firstSkip, UTF8Util.skipUntilEOF(in));
+        assertEquals(0, UTF8Util.skipUntilEOF(in)); // Nothing left here.
+        try {
+            UTF8Util.skipFully(in, 1L);
+            fail("Should have failed because the stream has been drained.");
+        } catch (EOFException eofe) {
+            // As expected, do nothing
+        }
+    }
+
+    /**
+     * Returns a suite of tests.
+     */
+    public static Test suite() {
+        return new TestSuite(UTF8UtilTest.class, "UTF8Util tests");
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/UTF8UtilTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/_Suite.java?rev=605531&r1=605530&r2=605531&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/_Suite.java Wed
Dec 19 05:09:19 2007
@@ -48,6 +48,7 @@
 
         suite.addTest(FormatableBitSetTest.suite());
         //suite.addTest(SystemPrivilegesPermissionTest.suite());
+        suite.addTest(UTF8UtilTest.suite());
 
         return suite;
     }



Mime
View raw message