You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ck...@apache.org on 2020/08/28 12:06:07 UTC

[httpcomponents-core] branch 5.1.x updated (3cbf7dc -> 65726a3)

This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a change to branch 5.1.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git.


    from 3cbf7dc  Use decimal numbers for endpoint/execution IDs
     new a45d5f4  HTTPCORE-648: Buffer array access respects the arrayOffset
     new 65726a3  HTTPCORE-649: Implement ByteArrayBuffer.append(ByteBuffer)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/hc/core5/http2/hpack/HPackDecoder.java  | 18 ++---
 .../apache/hc/core5/http2/hpack/HPackEncoder.java  | 11 +---
 .../hc/core5/http2/hpack/TestHPackCoding.java      | 31 +++++----
 .../http/impl/nio/SessionInputBufferImpl.java      |  6 +-
 .../http/impl/nio/SessionOutputBufferImpl.java     |  3 +-
 .../http/nio/entity/BasicAsyncEntityConsumer.java  | 11 +---
 .../org/apache/hc/core5/util/ByteArrayBuffer.java  | 16 +++++
 .../entity/TestAbstractBinAsyncEntityConsumer.java | 11 +---
 .../apache/hc/core5/util/TestByteArrayBuffer.java  | 76 ++++++++++++++++++++++
 9 files changed, 126 insertions(+), 57 deletions(-)


[httpcomponents-core] 01/02: HTTPCORE-648: Buffer array access respects the arrayOffset

Posted by ck...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a commit to branch 5.1.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit a45d5f4cb5bdc414a9f29508f5dbf75683bcc2f8
Author: Carter Kozak <ck...@ckozak.net>
AuthorDate: Thu Aug 27 12:31:21 2020 -0400

    HTTPCORE-648: Buffer array access respects the arrayOffset
---
 .../apache/hc/core5/http2/hpack/HPackDecoder.java  |  2 +-
 .../apache/hc/core5/http2/hpack/HPackEncoder.java  |  2 +-
 .../hc/core5/http2/hpack/TestHPackCoding.java      | 31 ++++++++++++++--------
 .../http/impl/nio/SessionInputBufferImpl.java      |  6 ++---
 .../http/impl/nio/SessionOutputBufferImpl.java     |  3 ++-
 5 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackDecoder.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackDecoder.java
index 62ad3bb..dd9379c 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackDecoder.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackDecoder.java
@@ -133,7 +133,7 @@ public final class HPackDecoder {
         if (src.hasArray()) {
             final byte[] b = src.array();
             final int off = src.position();
-            buffer.append(b, off, strLen);
+            buffer.append(b, src.arrayOffset() + off, strLen);
             src.position(off + strLen);
         } else {
             for (int i = 0; i < strLen; i++) {
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackEncoder.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackEncoder.java
index dc3179d..2824760 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackEncoder.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackEncoder.java
@@ -113,7 +113,7 @@ public final class HPackEncoder {
             if (src.hasArray()) {
                 final byte[] b = src.array();
                 final int off = src.position();
-                dst.append(b, off, strLen);
+                dst.append(b, src.arrayOffset() + off, strLen);
                 src.position(off + strLen);
             } else {
                 while (src.hasRemaining()) {
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java
index 7d1603a..8e71d5f 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java
@@ -66,8 +66,17 @@ public class TestHPackCoding {
     }
 
     static ByteBuffer wrap(final ByteArrayBuffer src) {
+        // Use buffers with array offsets to verify correcness in additional cases
+        final byte[] originalArray = src.array();
+        final byte[] newArray = new byte[originalArray.length + 2];
+        System.arraycopy(originalArray, 0, newArray, 1, src.length());
+        return ByteBuffer.wrap(newArray, 1, src.length()).slice();
+    }
 
-        return ByteBuffer.wrap(src.array(), 0, src.length());
+    private static byte[] toArray(final ByteBuffer buffer) {
+        final byte[] result = new byte[buffer.remaining()];
+        buffer.get(result);
+        return result;
     }
 
     @Test
@@ -192,7 +201,7 @@ public class TestHPackCoding {
         HPackEncoder.encodeHuffman(buffer, createByteBuffer("www.example.com", StandardCharsets.US_ASCII));
         final ByteBuffer expected = createByteBuffer(
                 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff);
-        Assert.assertEquals(expected, wrap(buffer));
+        Assert.assertArrayEquals(toArray(expected), buffer.toByteArray());
     }
 
     @Test
@@ -205,13 +214,13 @@ public class TestHPackCoding {
         encoder.encodeString(buffer, "this and that", false);
 
         final StringBuilder strBuf = new StringBuilder();
-        decoder.decodeString(ByteBuffer.wrap(buffer.array(), 0, buffer.length()), strBuf);
+        decoder.decodeString(wrap(buffer), strBuf);
         Assert.assertEquals("this and that", strBuf.toString());
 
         buffer.clear();
         strBuf.setLength(0);
         encoder.encodeString(buffer, "this and that and Huffman", true);
-        decoder.decodeString(ByteBuffer.wrap(buffer.array(), 0, buffer.length()), strBuf);
+        decoder.decodeString(wrap(buffer), strBuf);
         Assert.assertEquals("this and that and Huffman", strBuf.toString());
     }
 
@@ -257,7 +266,7 @@ public class TestHPackCoding {
                     buffer.clear();
                     encoder.encodeString(buffer, hello, b);
                     strBuf.setLength(0);
-                    decoder.decodeString(ByteBuffer.wrap(buffer.array(), 0, buffer.length()), strBuf);
+                    decoder.decodeString(wrap(buffer), strBuf);
                     final String helloBack = strBuf.toString();
                     Assert.assertEquals("charset: " + charset + "; huffman: " + b, hello, helloBack);
                 }
@@ -285,7 +294,7 @@ public class TestHPackCoding {
                     buffer.clear();
                     strBuf.setLength(0);
                     encoder.encodeString(buffer, hello, b);
-                    decoder.decodeString(ByteBuffer.wrap(buffer.array(), 0, buffer.length()), strBuf);
+                    decoder.decodeString(wrap(buffer), strBuf);
                     final String helloBack = strBuf.toString();
                     Assert.assertEquals("charset: " + charset + "; huffman: " + b, hello, helloBack);
                 }
@@ -1004,7 +1013,7 @@ public class TestHPackCoding {
         decoder1.setMaxTableSize(48);
 
         encoder1.encodeHeader(buffer, header);
-        assertHeaderEquals(header, decoder1.decodeHeader(ByteBuffer.wrap(buffer.array(), 0, buffer.length())));
+        assertHeaderEquals(header, decoder1.decodeHeader(wrap(buffer)));
 
         Assert.assertEquals(1, outboundTable1.dynamicLength());
         Assert.assertEquals(1, inboundTable1.dynamicLength());
@@ -1023,7 +1032,7 @@ public class TestHPackCoding {
         decoder2.setMaxTableSize(48);
 
         encoder2.encodeHeader(buffer, header);
-        assertHeaderEquals(header, decoder2.decodeHeader(ByteBuffer.wrap(buffer.array(), 0, buffer.length())));
+        assertHeaderEquals(header, decoder2.decodeHeader(wrap(buffer)));
 
         Assert.assertEquals(0, outboundTable2.dynamicLength());
         Assert.assertEquals(0, inboundTable2.dynamicLength());
@@ -1044,13 +1053,13 @@ public class TestHPackCoding {
                                 "123456789012345678901234567890123456789012345678901234567890")),
                 false);
 
-        Assert.assertThat(decoder.decodeHeaders(ByteBuffer.wrap(buf.toByteArray())).size(), CoreMatchers.equalTo(2));
+        Assert.assertThat(decoder.decodeHeaders(wrap(buf)).size(), CoreMatchers.equalTo(2));
 
         decoder.setMaxListSize(1000000);
-        Assert.assertThat(decoder.decodeHeaders(ByteBuffer.wrap(buf.toByteArray())).size(), CoreMatchers.equalTo(2));
+        Assert.assertThat(decoder.decodeHeaders(wrap(buf)).size(), CoreMatchers.equalTo(2));
 
         decoder.setMaxListSize(200);
-        decoder.decodeHeaders(ByteBuffer.wrap(buf.toByteArray()));
+        decoder.decodeHeaders(wrap(buf));
     }
 
 }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java
index 52f9b29..cab13b7 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionInputBufferImpl.java
@@ -250,7 +250,7 @@ class SessionInputBufferImpl extends ExpandableBuffer implements SessionInputBuf
                 final byte[] b = buffer().array();
                 final int off = buffer().position();
                 final int len = buffer().remaining();
-                lineBuffer.append(b, off, len);
+                lineBuffer.append(b, buffer().arrayOffset() + off, len);
                 buffer().position(off + len);
             } else {
                 while (buffer().hasRemaining()) {
@@ -275,7 +275,7 @@ class SessionInputBufferImpl extends ExpandableBuffer implements SessionInputBuf
                     this.charbuffer.flip();
                     lineBuffer.append(
                             this.charbuffer.array(),
-                            this.charbuffer.position(),
+                            this.charbuffer.arrayOffset() + this.charbuffer.position(),
                             this.charbuffer.remaining());
                     this.charbuffer.clear();
                 }
@@ -291,7 +291,7 @@ class SessionInputBufferImpl extends ExpandableBuffer implements SessionInputBuf
             if (this.charbuffer.hasRemaining()) {
                 lineBuffer.append(
                         this.charbuffer.array(),
-                        this.charbuffer.position(),
+                        this.charbuffer.arrayOffset() + this.charbuffer.position(),
                         this.charbuffer.remaining());
             }
 
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionOutputBufferImpl.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionOutputBufferImpl.java
index bfc81df..23b8da2 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionOutputBufferImpl.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionOutputBufferImpl.java
@@ -169,8 +169,9 @@ class SessionOutputBufferImpl extends ExpandableBuffer implements SessionOutputB
                     final byte[] b = buffer().array();
                     final int len = lineBuffer.length();
                     final int off = buffer().position();
+                    final int arrayOffset = buffer().arrayOffset();
                     for (int i = 0; i < len; i++) {
-                        b[off + i]  = (byte) lineBuffer.charAt(i);
+                        b[arrayOffset + off + i]  = (byte) lineBuffer.charAt(i);
                     }
                     buffer().position(off + len);
                 } else {


[httpcomponents-core] 02/02: HTTPCORE-649: Implement ByteArrayBuffer.append(ByteBuffer)

Posted by ck...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a commit to branch 5.1.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit 65726a3409b2df517ad897ee74f616937b4d5147
Author: Carter Kozak <ck...@ckozak.net>
AuthorDate: Thu Aug 27 13:51:02 2020 -0400

    HTTPCORE-649: Implement ByteArrayBuffer.append(ByteBuffer)
---
 .../apache/hc/core5/http2/hpack/HPackDecoder.java  | 18 ++---
 .../apache/hc/core5/http2/hpack/HPackEncoder.java  | 11 +---
 .../http/nio/entity/BasicAsyncEntityConsumer.java  | 11 +---
 .../org/apache/hc/core5/util/ByteArrayBuffer.java  | 16 +++++
 .../entity/TestAbstractBinAsyncEntityConsumer.java | 11 +---
 .../apache/hc/core5/util/TestByteArrayBuffer.java  | 76 ++++++++++++++++++++++
 6 files changed, 101 insertions(+), 42 deletions(-)

diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackDecoder.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackDecoder.java
index dd9379c..1df29a2 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackDecoder.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackDecoder.java
@@ -125,21 +125,15 @@ public final class HPackDecoder {
     }
 
     static void decodePlainString(final ByteArrayBuffer buffer, final ByteBuffer src) throws HPackException {
-
         final int strLen = decodeInt(src, 7);
-        if (strLen > src.remaining()) {
+        final int remaining = src.remaining();
+        if (strLen > remaining) {
             throw new HPackException(UNEXPECTED_EOS);
         }
-        if (src.hasArray()) {
-            final byte[] b = src.array();
-            final int off = src.position();
-            buffer.append(b, src.arrayOffset() + off, strLen);
-            src.position(off + strLen);
-        } else {
-            for (int i = 0; i < strLen; i++) {
-                buffer.append(src.get());
-            }
-        }
+        final int originalLimit = src.limit();
+        src.limit(originalLimit - (remaining - strLen));
+        buffer.append(src);
+        src.limit(originalLimit);
     }
 
     static void decodeHuffman(final ByteArrayBuffer buffer, final ByteBuffer src) throws HPackException {
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackEncoder.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackEncoder.java
index 2824760..621bdf4 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackEncoder.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/HPackEncoder.java
@@ -110,16 +110,7 @@ public final class HPackEncoder {
         } else {
             dst.ensureCapacity(strLen + 8);
             encodeInt(dst, 7, strLen, 0x0);
-            if (src.hasArray()) {
-                final byte[] b = src.array();
-                final int off = src.position();
-                dst.append(b, src.arrayOffset() + off, strLen);
-                src.position(off + strLen);
-            } else {
-                while (src.hasRemaining()) {
-                    dst.append(src.get());
-                }
-            }
+            dst.append(src);
         }
     }
 
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/entity/BasicAsyncEntityConsumer.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/entity/BasicAsyncEntityConsumer.java
index 26487ec..648bde6 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/entity/BasicAsyncEntityConsumer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/entity/BasicAsyncEntityConsumer.java
@@ -60,16 +60,7 @@ public class BasicAsyncEntityConsumer extends AbstractBinAsyncEntityConsumer<byt
 
     @Override
     protected void data(final ByteBuffer src, final boolean endOfStream) throws IOException {
-        if (src == null) {
-            return;
-        }
-        if (src.hasArray()) {
-            buffer.append(src.array(), src.arrayOffset() + src.position(), src.remaining());
-        } else {
-            while (src.hasRemaining()) {
-                buffer.append(src.get());
-            }
-        }
+        buffer.append(src);
     }
 
     @Override
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/util/ByteArrayBuffer.java b/httpcore5/src/main/java/org/apache/hc/core5/util/ByteArrayBuffer.java
index 573faa5..c9479c3 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/util/ByteArrayBuffer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/util/ByteArrayBuffer.java
@@ -28,6 +28,7 @@
 package org.apache.hc.core5.util;
 
 import java.io.Serializable;
+import java.nio.ByteBuffer;
 
 /**
  * A resizable byte array.
@@ -171,6 +172,21 @@ public final class ByteArrayBuffer implements Serializable {
         append(b.array(), off, len);
     }
 
+    public void append(final ByteBuffer buffer) {
+        if (buffer == null) {
+            return;
+        }
+        final int bufferLength = buffer.remaining();
+        if (bufferLength > 0) {
+            final int newLength = this.len + bufferLength;
+            if (newLength > this.array.length) {
+                expand(newLength);
+            }
+            buffer.get(this.array, this.len, bufferLength);
+            this.len = newLength;
+        }
+    }
+
     /**
      * Clears content of the buffer. The underlying byte array is not resized.
      */
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/nio/entity/TestAbstractBinAsyncEntityConsumer.java b/httpcore5/src/test/java/org/apache/hc/core5/http/nio/entity/TestAbstractBinAsyncEntityConsumer.java
index 7c7b12a..ea7609e 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/nio/entity/TestAbstractBinAsyncEntityConsumer.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/nio/entity/TestAbstractBinAsyncEntityConsumer.java
@@ -62,16 +62,7 @@ public class TestAbstractBinAsyncEntityConsumer {
 
         @Override
         protected void data(final ByteBuffer src, final boolean endOfStream) throws IOException {
-            if (src == null) {
-                return;
-            }
-            if (src.hasArray()) {
-                buffer.append(src.array(), src.arrayOffset() + src.position(), src.remaining());
-            } else {
-                while (src.hasRemaining()) {
-                    buffer.append(src.get());
-                }
-            }
+            buffer.append(src);
         }
 
         @Override
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/util/TestByteArrayBuffer.java b/httpcore5/src/test/java/org/apache/hc/core5/util/TestByteArrayBuffer.java
index 204426a..6d8d6f5 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/util/TestByteArrayBuffer.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/util/TestByteArrayBuffer.java
@@ -31,6 +31,7 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 
 import org.junit.Assert;
@@ -109,6 +110,73 @@ public class TestByteArrayBuffer {
     }
 
     @Test
+    public void testAppendHeapByteBuffer() {
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
+        Assert.assertEquals(4, buffer.capacity());
+
+        final ByteBuffer tmp = ByteBuffer.wrap(new byte[] { 1, 2, 3, 4, 5, 6});
+        buffer.append(tmp);
+
+        Assert.assertFalse("The input buffer should be drained", tmp.hasRemaining());
+        Assert.assertEquals(8, buffer.capacity());
+        Assert.assertEquals(6, buffer.length());
+
+        tmp.clear();
+        buffer.append(tmp);
+
+        Assert.assertFalse("The input buffer should be drained", tmp.hasRemaining());
+        Assert.assertEquals(16, buffer.capacity());
+        Assert.assertEquals(12, buffer.length());
+        Assert.assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6}, buffer.toByteArray());
+    }
+
+    @Test
+    public void testAppendHeapByteBufferWithOffset() {
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
+        Assert.assertEquals(4, buffer.capacity());
+
+        final ByteBuffer tmp = ByteBuffer.wrap(new byte[] { 7, 7, 1, 2, 3, 4, 5, 6, 7, 7}, 2, 6).slice();
+        Assert.assertTrue("Validate this is testing a buffer with an array offset", tmp.arrayOffset() > 0);
+
+        buffer.append(tmp);
+
+        Assert.assertFalse("The input buffer should be drained", tmp.hasRemaining());
+        Assert.assertEquals(8, buffer.capacity());
+        Assert.assertEquals(6, buffer.length());
+
+        tmp.clear();
+        Assert.assertEquals(6, tmp.remaining());
+        buffer.append(tmp);
+
+        Assert.assertFalse("The input buffer should be drained", tmp.hasRemaining());
+        Assert.assertEquals(16, buffer.capacity());
+        Assert.assertEquals(12, buffer.length());
+        Assert.assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6}, buffer.toByteArray());
+    }
+
+    @Test
+    public void testAppendDirectByteBuffer() {
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
+        Assert.assertEquals(4, buffer.capacity());
+
+        final ByteBuffer tmp = ByteBuffer.allocateDirect(6);
+        tmp.put(new byte[] { 1, 2, 3, 4, 5, 6}).flip();
+        buffer.append(tmp);
+
+        Assert.assertFalse("The input buffer should be drained", tmp.hasRemaining());
+        Assert.assertEquals(8, buffer.capacity());
+        Assert.assertEquals(6, buffer.length());
+
+        tmp.clear();
+        buffer.append(tmp);
+
+        Assert.assertFalse("The input buffer should be drained", tmp.hasRemaining());
+        Assert.assertEquals(16, buffer.capacity());
+        Assert.assertEquals(12, buffer.length());
+        Assert.assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6}, buffer.toByteArray());
+    }
+
+    @Test
     public void testInvalidAppend() throws Exception {
         final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
         buffer.append((byte[])null, 0, 0);
@@ -251,6 +319,14 @@ public class TestByteArrayBuffer {
     }
 
     @Test
+    public void testAppendNullByteBuffer() throws Exception {
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(8);
+        final ByteBuffer nullBuffer = null;
+        buffer.append(nullBuffer);
+        Assert.assertEquals(0, buffer.length());
+    }
+
+    @Test
     public void testInvalidAppendCharArrayAsAscii() throws Exception {
         final ByteArrayBuffer buffer = new ByteArrayBuffer(4);
         buffer.append((char[])null, 0, 0);