Fixed issue: NETTY-33 (CompositeChannelBuffer.copy() does not respect the byte order.)
* More test cases..
This commit is contained in:
parent
6f34eca0b6
commit
a7c181072e
@ -296,6 +296,9 @@ public class ByteBufferBackedChannelBuffer extends AbstractChannelBuffer {
|
||||
if (index == 0 && length == capacity()) {
|
||||
return duplicate();
|
||||
} else {
|
||||
if (index >= 0 && length == 0) {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
return new ByteBufferBackedChannelBuffer(
|
||||
((ByteBuffer) buffer.duplicate().position(index).limit(index + length)));
|
||||
}
|
||||
|
@ -620,10 +620,18 @@ public class ChannelBuffers {
|
||||
|
||||
int hashCode = 1;
|
||||
int arrayIndex = buffer.readerIndex();
|
||||
if (buffer.order() == BIG_ENDIAN) {
|
||||
for (int i = intCount; i > 0; i --) {
|
||||
hashCode = 31 * hashCode + buffer.getInt(arrayIndex);
|
||||
arrayIndex += 4;
|
||||
}
|
||||
} else {
|
||||
for (int i = intCount; i > 0; i --) {
|
||||
hashCode = 31 * hashCode + swapInt(buffer.getInt(arrayIndex));
|
||||
arrayIndex += 4;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = byteCount; i > 0; i --) {
|
||||
hashCode = 31 * hashCode + buffer.getByte(arrayIndex ++);
|
||||
}
|
||||
@ -631,6 +639,7 @@ public class ChannelBuffers {
|
||||
if (hashCode == 0) {
|
||||
hashCode = 1;
|
||||
}
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
|
@ -423,7 +423,7 @@ public class CompositeChannelBuffer extends AbstractChannelBuffer {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
ChannelBuffer dst = ChannelBuffers.buffer(length);
|
||||
ChannelBuffer dst = ChannelBuffers.buffer(order(), length);
|
||||
int dstIndex = 0;
|
||||
int i = sliceId;
|
||||
|
||||
@ -443,6 +443,9 @@ public class CompositeChannelBuffer extends AbstractChannelBuffer {
|
||||
}
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
if (length == 0) {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
return new SlicedChannelBuffer(this, index, length);
|
||||
}
|
||||
|
||||
|
@ -214,8 +214,10 @@ public class DynamicChannelBuffer extends AbstractChannelBuffer {
|
||||
|
||||
public ChannelBuffer copy(int index, int length) {
|
||||
DynamicChannelBuffer copiedBuffer = new DynamicChannelBuffer(endianness, Math.max(length, 64));
|
||||
copiedBuffer.buffer = buffer.copy();
|
||||
if (copiedBuffer.buffer.capacity() == 0) {
|
||||
if (readable()) {
|
||||
copiedBuffer.buffer = buffer.copy(readerIndex(), readableBytes());
|
||||
copiedBuffer.setIndex(0, readableBytes());
|
||||
} else {
|
||||
copiedBuffer.buffer = ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
return copiedBuffer;
|
||||
@ -223,8 +225,14 @@ public class DynamicChannelBuffer extends AbstractChannelBuffer {
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
if (index == 0) {
|
||||
if (length == 0) {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
return new TruncatedChannelBuffer(this, length);
|
||||
} else {
|
||||
if (length == 0) {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
return new SlicedChannelBuffer(this, index, length);
|
||||
}
|
||||
}
|
||||
|
@ -155,12 +155,18 @@ public abstract class HeapChannelBuffer extends AbstractChannelBuffer {
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
if (index == 0) {
|
||||
if (length == 0) {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
if (length == array.length) {
|
||||
return duplicate();
|
||||
} else {
|
||||
return new TruncatedChannelBuffer(this, length);
|
||||
}
|
||||
} else {
|
||||
if (length == 0) {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
return new SlicedChannelBuffer(this, index, length);
|
||||
}
|
||||
}
|
||||
|
@ -110,6 +110,9 @@ public class SlicedChannelBuffer extends AbstractChannelBuffer implements Wrappe
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
checkIndex(index, length);
|
||||
if (length == 0) {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
return new SlicedChannelBuffer(buffer, index + adjustment, length);
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,9 @@ public class TruncatedChannelBuffer extends AbstractChannelBuffer implements Wra
|
||||
|
||||
public ChannelBuffer slice(int index, int length) {
|
||||
checkIndex(index, length);
|
||||
if (length == 0) {
|
||||
return ChannelBuffers.EMPTY_BUFFER;
|
||||
}
|
||||
return buffer.slice(index, length);
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,10 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@ -38,7 +41,7 @@ import org.junit.Test;
|
||||
|
||||
public abstract class AbstractChannelBufferTest {
|
||||
|
||||
private static final int CAPACITY = 4096;
|
||||
private static final int CAPACITY = 4096; // Must be even
|
||||
private static final int BLOCK_SIZE = 128;
|
||||
|
||||
private long seed;
|
||||
@ -1071,7 +1074,7 @@ public abstract class AbstractChannelBufferTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequentialCopiedBufferTransfer() {
|
||||
public void testSequentialCopiedBufferTransfer1() {
|
||||
buffer.writerIndex(0);
|
||||
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
|
||||
byte[] value = new byte[BLOCK_SIZE];
|
||||
@ -1097,7 +1100,31 @@ public abstract class AbstractChannelBufferTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequentialSlice() {
|
||||
public void testSequentialCopiedBufferTransfer2() {
|
||||
buffer.clear();
|
||||
buffer.writeZero(buffer.capacity());
|
||||
try {
|
||||
buffer.readBytes(ChannelBufferIndexFinder.CR);
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
assertSame(EMPTY_BUFFER, buffer.readBytes(ChannelBufferIndexFinder.NUL));
|
||||
|
||||
buffer.clear();
|
||||
buffer.writeBytes(new byte[] { 1, 2, 3, 4, 0 });
|
||||
|
||||
ChannelBuffer copy = buffer.readBytes(ChannelBufferIndexFinder.NUL);
|
||||
assertEquals(wrappedBuffer(new byte[] { 1, 2, 3, 4 }), copy);
|
||||
|
||||
// Make sure if it's a copied buffer.
|
||||
copy.setByte(0, (byte) (copy.getByte(0) + 1));
|
||||
assertFalse(buffer.getByte(0) == copy.getByte(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequentialSlice1() {
|
||||
buffer.writerIndex(0);
|
||||
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
|
||||
byte[] value = new byte[BLOCK_SIZE];
|
||||
@ -1122,8 +1149,39 @@ public abstract class AbstractChannelBufferTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequentialSlice2() {
|
||||
buffer.clear();
|
||||
buffer.writeZero(buffer.capacity());
|
||||
try {
|
||||
buffer.readSlice(ChannelBufferIndexFinder.CR);
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
assertSame(EMPTY_BUFFER, buffer.readSlice(ChannelBufferIndexFinder.NUL));
|
||||
|
||||
buffer.clear();
|
||||
buffer.writeBytes(new byte[] { 1, 2, 3, 4, 0 });
|
||||
|
||||
ChannelBuffer slice = buffer.readSlice(ChannelBufferIndexFinder.NUL);
|
||||
assertEquals(wrappedBuffer(new byte[] { 1, 2, 3, 4 }), slice);
|
||||
|
||||
// Make sure if it's a sliced buffer.
|
||||
slice.setByte(0, (byte) (slice.getByte(0) + 1));
|
||||
assertTrue(buffer.getByte(0) == slice.getByte(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteZero() {
|
||||
try {
|
||||
buffer.writeZero(-1);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
buffer.clear();
|
||||
while (buffer.writable()) {
|
||||
buffer.writeByte((byte) 0xFF);
|
||||
@ -1433,4 +1491,72 @@ public abstract class AbstractChannelBufferTest {
|
||||
assertEquals(ByteBuffer.wrap(value, i, BLOCK_SIZE), nioBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipBytes1() {
|
||||
buffer.setIndex(CAPACITY / 4, CAPACITY / 2);
|
||||
|
||||
buffer.skipBytes(CAPACITY / 4);
|
||||
assertEquals(CAPACITY / 4 * 2, buffer.readerIndex());
|
||||
|
||||
try {
|
||||
buffer.skipBytes(CAPACITY / 4 + 1);
|
||||
fail();
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
// Should remain unchanged.
|
||||
assertEquals(CAPACITY / 4 * 2, buffer.readerIndex());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipBytes2() {
|
||||
buffer.clear();
|
||||
buffer.writeZero(buffer.capacity());
|
||||
|
||||
try {
|
||||
buffer.skipBytes(ChannelBufferIndexFinder.LF);
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
buffer.skipBytes(ChannelBufferIndexFinder.NUL);
|
||||
assertEquals(0, buffer.readerIndex());
|
||||
|
||||
buffer.clear();
|
||||
buffer.writeBytes(new byte[] { 1, 2, 3, 4, 0 });
|
||||
buffer.skipBytes(ChannelBufferIndexFinder.NUL);
|
||||
assertEquals(4, buffer.readerIndex());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCode() {
|
||||
ChannelBuffer elemA = buffer(15);
|
||||
ChannelBuffer elemB = directBuffer(15);
|
||||
elemA.writeBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 });
|
||||
elemB.writeBytes(new byte[] { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9 });
|
||||
|
||||
Set<ChannelBuffer> set = new HashSet<ChannelBuffer>();
|
||||
set.add(elemA);
|
||||
set.add(elemB);
|
||||
|
||||
assertEquals(2, set.size());
|
||||
assertTrue(set.contains(elemA.copy()));
|
||||
assertTrue(set.contains(elemB.copy()));
|
||||
|
||||
buffer.clear();
|
||||
buffer.writeBytes(elemA.duplicate());
|
||||
|
||||
assertTrue(set.remove(buffer));
|
||||
assertFalse(set.contains(elemA));
|
||||
assertEquals(1, set.size());
|
||||
|
||||
buffer.clear();
|
||||
buffer.writeBytes(elemB.duplicate());
|
||||
assertTrue(set.remove(buffer));
|
||||
assertFalse(set.contains(elemB));
|
||||
assertEquals(0, set.size());
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import java.util.List;
|
||||
|
||||
|
||||
|
||||
public class CompositeChannelBufferTest extends AbstractChannelBufferTest {
|
||||
public class BigEndianCompositeChannelBufferTest extends AbstractChannelBufferTest {
|
||||
|
||||
private List<ChannelBuffer> buffers;
|
||||
private ChannelBuffer buffer;
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
|
||||
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
package org.jboss.netty.buffer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
|
||||
|
||||
public class DynamicChannelBufferTest extends AbstractChannelBufferTest {
|
||||
|
||||
private ChannelBuffer buffer;
|
||||
|
||||
@Override
|
||||
protected ChannelBuffer newBuffer(int length) {
|
||||
buffer = ChannelBuffers.dynamicBuffer(length);
|
||||
|
||||
// A dynamic buffer does lazy initialization.
|
||||
assertEquals(0, buffer.capacity());
|
||||
|
||||
// Initialize.
|
||||
buffer.writeZero(1);
|
||||
buffer.clear();
|
||||
|
||||
// And validate the initial capacity
|
||||
assertEquals(0, buffer.writerIndex());
|
||||
assertEquals(length, buffer.capacity());
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelBuffer[] components() {
|
||||
return new ChannelBuffer[] { buffer };
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
|
||||
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
package org.jboss.netty.buffer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
|
||||
public class LittleEndianCompositeChannelBufferTest extends AbstractChannelBufferTest {
|
||||
|
||||
private List<ChannelBuffer> buffers;
|
||||
private ChannelBuffer buffer;
|
||||
|
||||
@Override
|
||||
protected ChannelBuffer newBuffer(int length) {
|
||||
buffers = new ArrayList<ChannelBuffer>();
|
||||
for (int i = 0; i < length; i += 10) {
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[1]));
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[2]));
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[3]));
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[4]));
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[5]));
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[6]));
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[7]));
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[8]));
|
||||
buffers.add(ChannelBuffers.wrappedBuffer(ChannelBuffers.LITTLE_ENDIAN, new byte[9]));
|
||||
}
|
||||
|
||||
buffer = ChannelBuffers.wrappedBuffer(buffers.toArray(new ChannelBuffer[buffers.size()]));
|
||||
buffer.writerIndex(length);
|
||||
buffer = ChannelBuffers.wrappedBuffer(buffer);
|
||||
assertEquals(length, buffer.capacity());
|
||||
assertEquals(length, buffer.readableBytes());
|
||||
assertFalse(buffer.writable());
|
||||
buffer.writerIndex(0);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelBuffer[] components() {
|
||||
return buffers.toArray(new ChannelBuffer[buffers.size()]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user