org.opensearch.common.bytes.AbstractBytesReferenceTestCase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of framework Show documentation
Show all versions of framework Show documentation
OpenSearch subproject :test:framework
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.common.bytes;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
import org.apache.lucene.util.BytesRefIterator;
import org.opensearch.common.io.stream.BytesStreamOutput;
import org.opensearch.common.io.stream.ReleasableBytesStreamOutput;
import org.opensearch.common.util.BigArrays;
import org.opensearch.common.util.PageCacheRecycler;
import org.opensearch.core.common.breaker.CircuitBreaker;
import org.opensearch.core.common.bytes.AbstractBytesReference;
import org.opensearch.core.common.bytes.BytesArray;
import org.opensearch.core.common.bytes.BytesReference;
import org.opensearch.core.common.io.stream.StreamInput;
import org.opensearch.core.common.util.ByteArray;
import org.opensearch.core.indices.breaker.NoneCircuitBreakerService;
import org.opensearch.test.OpenSearchTestCase;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class AbstractBytesReferenceTestCase extends OpenSearchTestCase {
protected static final int PAGE_SIZE = PageCacheRecycler.BYTE_PAGE_SIZE;
protected final BigArrays bigarrays = new BigArrays(null, new NoneCircuitBreakerService(), CircuitBreaker.REQUEST);
public void testGet() throws IOException {
int length = randomIntBetween(1, PAGE_SIZE * 3);
BytesReference pbr = newBytesReference(length);
int sliceOffset = randomIntBetween(0, length / 2);
int sliceLength = Math.max(1, length - sliceOffset - 1);
BytesReference slice = pbr.slice(sliceOffset, sliceLength);
assertEquals(pbr.get(sliceOffset), slice.get(0));
assertEquals(pbr.get(sliceOffset + sliceLength - 1), slice.get(sliceLength - 1));
final int probes = randomIntBetween(20, 100);
BytesReference copy = new BytesArray(pbr.toBytesRef(), true);
for (int i = 0; i < probes; i++) {
int index = randomIntBetween(0, copy.length() - 1);
assertEquals(pbr.get(index), copy.get(index));
index = randomIntBetween(sliceOffset, sliceOffset + sliceLength - 1);
assertEquals(pbr.get(index), slice.get(index - sliceOffset));
}
}
public void testLength() throws IOException {
int[] sizes = { 0, randomInt(PAGE_SIZE), PAGE_SIZE, randomInt(PAGE_SIZE * 3) };
for (int i = 0; i < sizes.length; i++) {
BytesReference pbr = newBytesReference(sizes[i]);
assertEquals(sizes[i], pbr.length());
}
}
public void testSlice() throws IOException {
for (int length : new int[] { 0, 1, randomIntBetween(2, PAGE_SIZE), randomIntBetween(PAGE_SIZE + 1, 3 * PAGE_SIZE) }) {
BytesReference pbr = newBytesReference(length);
int sliceOffset = randomIntBetween(0, length / 2);
int sliceLength = Math.max(0, length - sliceOffset - 1);
BytesReference slice = pbr.slice(sliceOffset, sliceLength);
assertEquals(sliceLength, slice.length());
for (int i = 0; i < sliceLength; i++) {
assertEquals(pbr.get(i + sliceOffset), slice.get(i));
}
BytesRef singlePageOrNull = getSinglePageOrNull(slice);
if (singlePageOrNull != null) {
// we can't assert the offset since if the length is smaller than the refercence
// the offset can be anywhere
assertEquals(sliceLength, singlePageOrNull.length);
}
}
}
public void testStreamInput() throws IOException {
int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
BytesReference pbr = newBytesReference(length);
StreamInput si = pbr.streamInput();
assertNotNull(si);
// read single bytes one by one
assertEquals(pbr.get(0), si.readByte());
assertEquals(pbr.get(1), si.readByte());
assertEquals(pbr.get(2), si.readByte());
// reset the stream for bulk reading
si.reset();
// buffer for bulk reads
byte[] origBuf = new byte[length];
random().nextBytes(origBuf);
byte[] targetBuf = Arrays.copyOf(origBuf, origBuf.length);
// bulk-read 0 bytes: must not modify buffer
si.readBytes(targetBuf, 0, 0);
assertEquals(origBuf[0], targetBuf[0]);
si.reset();
// read a few few bytes as ints
int bytesToRead = randomIntBetween(1, length / 2);
for (int i = 0; i < bytesToRead; i++) {
int b = si.read();
assertEquals(pbr.get(i) & 0xff, b);
}
si.reset();
// bulk-read all
si.readFully(targetBuf);
assertArrayEquals(BytesReference.toBytes(pbr), targetBuf);
// continuing to read should now fail with EOFException
try {
si.readByte();
fail("expected EOF");
} catch (EOFException | IndexOutOfBoundsException eof) {
// yay
}
// try to read more than the stream contains
si.reset();
expectThrows(IndexOutOfBoundsException.class, () -> si.readBytes(targetBuf, 0, length * 2));
}
public void testStreamInputMarkAndReset() throws IOException {
int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
BytesReference pbr = newBytesReference(length);
StreamInput si = pbr.streamInput();
assertNotNull(si);
StreamInput wrap = StreamInput.wrap(BytesReference.toBytes(pbr));
while (wrap.available() > 0) {
if (rarely()) {
wrap.mark(Integer.MAX_VALUE);
si.mark(Integer.MAX_VALUE);
} else if (rarely()) {
wrap.reset();
si.reset();
}
assertEquals(si.readByte(), wrap.readByte());
assertEquals(si.available(), wrap.available());
}
}
public void testStreamInputBulkReadWithOffset() throws IOException {
final int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
BytesReference pbr = newBytesReference(length);
StreamInput si = pbr.streamInput();
assertNotNull(si);
// read a bunch of single bytes one by one
int offset = randomIntBetween(1, length / 2);
for (int i = 0; i < offset; i++) {
assertEquals(si.available(), length - i);
assertEquals(pbr.get(i), si.readByte());
}
// now do NOT reset the stream - keep the stream's offset!
// buffer to compare remaining bytes against bulk read
byte[] pbrBytesWithOffset = Arrays.copyOfRange(BytesReference.toBytes(pbr), offset, length);
// randomized target buffer to ensure no stale slots
byte[] targetBytes = new byte[pbrBytesWithOffset.length];
random().nextBytes(targetBytes);
// bulk-read all
si.readFully(targetBytes);
assertArrayEquals(pbrBytesWithOffset, targetBytes);
assertEquals(si.available(), 0);
}
public void testRandomReads() throws IOException {
int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
BytesReference pbr = newBytesReference(length);
StreamInput streamInput = pbr.streamInput();
BytesRefBuilder target = new BytesRefBuilder();
while (target.length() < pbr.length()) {
switch (randomIntBetween(0, 10)) {
case 6:
case 5:
target.append(new BytesRef(new byte[] { streamInput.readByte() }));
break;
case 4:
case 3:
BytesRef bytesRef = streamInput.readBytesRef(scaledRandomIntBetween(1, pbr.length() - target.length()));
target.append(bytesRef);
break;
default:
byte[] buffer = new byte[scaledRandomIntBetween(1, pbr.length() - target.length())];
int offset = scaledRandomIntBetween(0, buffer.length - 1);
int read = streamInput.read(buffer, offset, buffer.length - offset);
target.append(new BytesRef(buffer, offset, read));
break;
}
}
assertEquals(pbr.length(), target.length());
BytesRef targetBytes = target.get();
assertArrayEquals(BytesReference.toBytes(pbr), Arrays.copyOfRange(targetBytes.bytes, targetBytes.offset, targetBytes.length));
}
public void testSliceStreamInput() throws IOException {
int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
BytesReference pbr = newBytesReference(length);
// test stream input over slice (upper half of original)
int sliceOffset = randomIntBetween(1, length / 2);
int sliceLength = length - sliceOffset;
BytesReference slice = pbr.slice(sliceOffset, sliceLength);
StreamInput sliceInput = slice.streamInput();
assertEquals(sliceInput.available(), sliceLength);
// single reads
assertEquals(slice.get(0), sliceInput.readByte());
assertEquals(slice.get(1), sliceInput.readByte());
assertEquals(slice.get(2), sliceInput.readByte());
assertEquals(sliceInput.available(), sliceLength - 3);
// reset the slice stream for bulk reading
sliceInput.reset();
assertEquals(sliceInput.available(), sliceLength);
// bulk read
byte[] sliceBytes = new byte[sliceLength];
sliceInput.readFully(sliceBytes);
assertEquals(sliceInput.available(), 0);
// compare slice content with upper half of original
byte[] pbrSliceBytes = Arrays.copyOfRange(BytesReference.toBytes(pbr), sliceOffset, length);
assertArrayEquals(pbrSliceBytes, sliceBytes);
// compare slice bytes with bytes read from slice via streamInput :D
byte[] sliceToBytes = BytesReference.toBytes(slice);
assertEquals(sliceBytes.length, sliceToBytes.length);
assertArrayEquals(sliceBytes, sliceToBytes);
sliceInput.reset();
assertEquals(sliceInput.available(), sliceLength);
byte[] buffer = new byte[sliceLength + scaledRandomIntBetween(1, 100)];
int offset = scaledRandomIntBetween(0, Math.max(1, buffer.length - sliceLength - 1));
int read = sliceInput.read(buffer, offset, sliceLength / 2);
assertEquals(sliceInput.available(), sliceLength - read);
sliceInput.read(buffer, offset + read, sliceLength - read);
assertArrayEquals(sliceBytes, Arrays.copyOfRange(buffer, offset, offset + sliceLength));
assertEquals(sliceInput.available(), 0);
}
public void testWriteToOutputStream() throws IOException {
int length = randomIntBetween(10, PAGE_SIZE * 4);
BytesReference pbr = newBytesReference(length);
BytesStreamOutput out = new BytesStreamOutput();
pbr.writeTo(out);
assertEquals(pbr.length(), out.size());
assertArrayEquals(BytesReference.toBytes(pbr), BytesReference.toBytes(out.bytes()));
out.close();
}
public void testInputStreamSkip() throws IOException {
int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
BytesReference pbr = newBytesReference(length);
final int iters = randomIntBetween(5, 50);
for (int i = 0; i < iters; i++) {
try (StreamInput input = pbr.streamInput()) {
final int offset = randomIntBetween(0, length - 1);
assertEquals(offset, input.skip(offset));
assertEquals(pbr.get(offset), input.readByte());
if (offset == length - 1) {
continue; // no more bytes to retrieve!
}
final int nextOffset = randomIntBetween(offset, length - 2);
assertEquals(nextOffset - offset, input.skip(nextOffset - offset));
assertEquals(pbr.get(nextOffset + 1), input.readByte()); // +1 for the one byte we read above
assertEquals(length - (nextOffset + 2), input.skip(Long.MAX_VALUE));
assertEquals(0, input.skip(randomIntBetween(0, Integer.MAX_VALUE)));
}
}
}
public void testSliceWriteToOutputStream() throws IOException {
int length = randomIntBetween(10, PAGE_SIZE * randomIntBetween(2, 5));
BytesReference pbr = newBytesReference(length);
int sliceOffset = randomIntBetween(1, length / 2);
int sliceLength = length - sliceOffset;
BytesReference slice = pbr.slice(sliceOffset, sliceLength);
BytesStreamOutput sliceOut = new BytesStreamOutput(sliceLength);
slice.writeTo(sliceOut);
assertEquals(slice.length(), sliceOut.size());
assertArrayEquals(BytesReference.toBytes(slice), BytesReference.toBytes(sliceOut.bytes()));
sliceOut.close();
}
public void testToBytes() throws IOException {
int[] sizes = { 0, randomInt(PAGE_SIZE), PAGE_SIZE, randomIntBetween(2, PAGE_SIZE * randomIntBetween(2, 5)) };
for (int i = 0; i < sizes.length; i++) {
BytesReference pbr = newBytesReference(sizes[i]);
byte[] bytes = BytesReference.toBytes(pbr);
assertEquals(sizes[i], bytes.length);
for (int j = 0; j < bytes.length; j++) {
assertEquals(bytes[j], pbr.get(j));
}
}
}
public void testToBytesRefSharedPage() throws IOException {
int length = randomIntBetween(10, PAGE_SIZE);
BytesReference pbr = newBytesReference(length);
BytesArray ba = new BytesArray(pbr.toBytesRef());
BytesArray ba2 = new BytesArray(pbr.toBytesRef());
assertNotNull(ba);
assertNotNull(ba2);
assertEquals(pbr.length(), ba.length());
assertEquals(ba.length(), ba2.length());
// single-page optimization
assertSame(ba.array(), ba2.array());
}
public void testToBytesRefMaterializedPages() throws IOException {
// we need a length != (n * pagesize) to avoid page sharing at boundaries
int length = 0;
while ((length % PAGE_SIZE) == 0) {
length = randomIntBetween(PAGE_SIZE, PAGE_SIZE * randomIntBetween(2, 5));
}
BytesReference pbr = newBytesReference(length);
BytesArray ba = new BytesArray(pbr.toBytesRef());
BytesArray ba2 = new BytesArray(pbr.toBytesRef());
assertNotNull(ba);
assertNotNull(ba2);
assertEquals(pbr.length(), ba.length());
assertEquals(ba.length(), ba2.length());
}
public void testCopyBytesRefSharesBytes() throws IOException {
// small PBR which would normally share the first page
int length = randomIntBetween(10, PAGE_SIZE);
BytesReference pbr = newBytesReference(length);
BytesArray ba = new BytesArray(pbr.toBytesRef(), true);
BytesArray ba2 = new BytesArray(pbr.toBytesRef(), true);
assertNotNull(ba);
assertNotSame(ba, ba2);
assertNotSame(ba.array(), ba2.array());
}
public void testSliceCopyBytesRef() throws IOException {
int length = randomIntBetween(10, PAGE_SIZE * randomIntBetween(2, 8));
BytesReference pbr = newBytesReference(length);
int sliceOffset = randomIntBetween(0, pbr.length());
int sliceLength = randomIntBetween(0, pbr.length() - sliceOffset);
BytesReference slice = pbr.slice(sliceOffset, sliceLength);
BytesArray ba1 = new BytesArray(slice.toBytesRef(), true);
BytesArray ba2 = new BytesArray(slice.toBytesRef(), true);
assertNotNull(ba1);
assertNotNull(ba2);
assertNotSame(ba1.array(), ba2.array());
assertArrayEquals(BytesReference.toBytes(slice), ba1.array());
assertArrayEquals(BytesReference.toBytes(slice), ba2.array());
assertArrayEquals(ba1.array(), ba2.array());
}
public void testEmptyToBytesRefIterator() throws IOException {
BytesReference pbr = newBytesReference(0);
assertNull(pbr.iterator().next());
}
public void testIterator() throws IOException {
int length = randomIntBetween(10, PAGE_SIZE * randomIntBetween(2, 8));
BytesReference pbr = newBytesReference(length);
BytesRefIterator iterator = pbr.iterator();
BytesRef ref;
BytesRefBuilder builder = new BytesRefBuilder();
while ((ref = iterator.next()) != null) {
builder.append(ref);
}
assertArrayEquals(BytesReference.toBytes(pbr), BytesRef.deepCopyOf(builder.toBytesRef()).bytes);
}
public void testSliceIterator() throws IOException {
int length = randomIntBetween(10, PAGE_SIZE * randomIntBetween(2, 8));
BytesReference pbr = newBytesReference(length);
int sliceOffset = randomIntBetween(0, pbr.length());
int sliceLength = randomIntBetween(0, pbr.length() - sliceOffset);
BytesReference slice = pbr.slice(sliceOffset, sliceLength);
BytesRefIterator iterator = slice.iterator();
BytesRef ref = null;
BytesRefBuilder builder = new BytesRefBuilder();
while ((ref = iterator.next()) != null) {
builder.append(ref);
}
assertArrayEquals(BytesReference.toBytes(slice), BytesRef.deepCopyOf(builder.toBytesRef()).bytes);
}
public void testIteratorRandom() throws IOException {
int length = randomIntBetween(10, PAGE_SIZE * randomIntBetween(2, 8));
BytesReference pbr = newBytesReference(length);
if (randomBoolean()) {
int sliceOffset = randomIntBetween(0, pbr.length());
int sliceLength = randomIntBetween(0, pbr.length() - sliceOffset);
pbr = pbr.slice(sliceOffset, sliceLength);
}
if (randomBoolean()) {
pbr = new BytesArray(pbr.toBytesRef());
}
BytesRefIterator iterator = pbr.iterator();
BytesRef ref = null;
BytesRefBuilder builder = new BytesRefBuilder();
while ((ref = iterator.next()) != null) {
builder.append(ref);
}
assertArrayEquals(BytesReference.toBytes(pbr), BytesRef.deepCopyOf(builder.toBytesRef()).bytes);
}
public void testArrayOffset() throws IOException {
int length = randomInt(PAGE_SIZE * randomIntBetween(2, 5));
BytesReference pbr = newBytesReference(length);
BytesRef singlePageOrNull = getSinglePageOrNull(pbr);
if (singlePageOrNull != null) {
assertEquals(0, singlePageOrNull.offset);
}
}
public void testSliceArrayOffset() throws IOException {
int length = randomIntBetween(1, PAGE_SIZE * randomIntBetween(2, 5));
BytesReference pbr = newBytesReferenceWithOffsetOfZero(length);
int sliceOffset = randomIntBetween(0, pbr.length() - 1); // an offset to the end would be len 0
int sliceLength = randomIntBetween(1, pbr.length() - sliceOffset);
BytesReference slice = pbr.slice(sliceOffset, sliceLength);
BytesRef singlePageOrNull = getSinglePageOrNull(slice);
if (singlePageOrNull != null) {
if (getSinglePageOrNull(pbr) == null) {
// original reference has pages
assertEquals(sliceOffset % PAGE_SIZE, singlePageOrNull.offset);
} else {
// orig ref has no pages ie. BytesArray
assertEquals(sliceOffset, singlePageOrNull.offset);
}
}
}
public void testToUtf8() throws IOException {
// test empty
BytesReference pbr = newBytesReference(0);
assertEquals("", pbr.utf8ToString());
// TODO: good way to test?
}
public void testUTF8toString_ExceedsMaxLength() {
AbstractBytesReference abr = new TestAbstractBytesReference();
IllegalArgumentException e = assertThrows(IllegalArgumentException.class, abr::utf8ToString);
assertTrue(e.getMessage().contains("UTF16 String size is"));
assertTrue(e.getMessage().contains("should be less than"));
}
static class TestAbstractBytesReference extends AbstractBytesReference {
@Override
public byte get(int index) {
return 0;
}
@Override
public int length() {
return 0;
}
@Override
public BytesReference slice(int from, int length) {
return null;
}
@Override
public long ramBytesUsed() {
return 0;
}
@Override
public BytesRef toBytesRef() {
return new BytesRef("UTF16 length exceed test");
}
@Override
public int getMaxUTF16Length() {
return 1;
}
}
public void testToBytesRef() throws IOException {
int length = randomIntBetween(0, PAGE_SIZE);
BytesReference pbr = newBytesReference(length);
BytesRef ref = pbr.toBytesRef();
assertNotNull(ref);
assertEquals(pbr.length(), ref.length);
}
public void testSliceToBytesRef() throws IOException {
int length = randomIntBetween(0, PAGE_SIZE);
BytesReference pbr = newBytesReferenceWithOffsetOfZero(length);
// get a BytesRef from a slice
int sliceOffset = randomIntBetween(0, pbr.length());
int sliceLength = randomIntBetween(0, pbr.length() - sliceOffset);
BytesRef sliceRef = pbr.slice(sliceOffset, sliceLength).toBytesRef();
if (sliceLength == 0 && sliceOffset != sliceRef.offset) {
// some impls optimize this to an empty instance then the offset will be 0
assertEquals(0, sliceRef.offset);
} else {
// note that these are only true if we have <= than a page, otherwise offset/length are shifted
assertEquals(sliceOffset, sliceRef.offset);
}
assertEquals(sliceLength, sliceRef.length);
}
public void testHashCode() throws IOException {
// empty content must have hash 1 (JDK compat)
BytesReference pbr = newBytesReference(0);
assertEquals(Arrays.hashCode(BytesRef.EMPTY_BYTES), pbr.hashCode());
// test with content
pbr = newBytesReference(randomIntBetween(0, PAGE_SIZE * randomIntBetween(2, 5)));
int jdkHash = Arrays.hashCode(BytesReference.toBytes(pbr));
int pbrHash = pbr.hashCode();
assertEquals(jdkHash, pbrHash);
// test hashes of slices
int sliceFrom = randomIntBetween(0, pbr.length());
int sliceLength = randomIntBetween(0, pbr.length() - sliceFrom);
BytesReference slice = pbr.slice(sliceFrom, sliceLength);
int sliceJdkHash = Arrays.hashCode(BytesReference.toBytes(slice));
int sliceHash = slice.hashCode();
assertEquals(sliceJdkHash, sliceHash);
}
public void testEquals() throws IOException {
BytesReference bytesReference = newBytesReference(randomIntBetween(100, PAGE_SIZE * randomIntBetween(2, 5)));
BytesReference copy = bytesReference.slice(0, bytesReference.length());
// get refs & compare
assertEquals(copy, bytesReference);
int sliceFrom = randomIntBetween(0, bytesReference.length());
int sliceLength = randomIntBetween(0, bytesReference.length() - sliceFrom);
assertEquals(copy.slice(sliceFrom, sliceLength), bytesReference.slice(sliceFrom, sliceLength));
BytesRef bytesRef = BytesRef.deepCopyOf(copy.toBytesRef());
assertEquals(new BytesArray(bytesRef), copy);
int offsetToFlip = randomIntBetween(0, bytesRef.length - 1);
int value = ~Byte.toUnsignedInt(bytesRef.bytes[bytesRef.offset + offsetToFlip]);
bytesRef.bytes[bytesRef.offset + offsetToFlip] = (byte) value;
assertNotEquals(new BytesArray(bytesRef), copy);
}
public void testSliceEquals() {
int length = randomIntBetween(100, PAGE_SIZE * randomIntBetween(2, 5));
ByteArray ba1 = bigarrays.newByteArray(length, false);
BytesReference pbr = BytesReference.fromByteArray(ba1, length);
// test equality of slices
int sliceFrom = randomIntBetween(0, pbr.length());
int sliceLength = randomIntBetween(0, pbr.length() - sliceFrom);
BytesReference slice1 = pbr.slice(sliceFrom, sliceLength);
BytesReference slice2 = pbr.slice(sliceFrom, sliceLength);
assertArrayEquals(BytesReference.toBytes(slice1), BytesReference.toBytes(slice2));
// test a slice with same offset but different length,
// unless randomized testing gave us a 0-length slice.
if (sliceLength > 0) {
BytesReference slice3 = pbr.slice(sliceFrom, sliceLength / 2);
assertFalse(Arrays.equals(BytesReference.toBytes(slice1), BytesReference.toBytes(slice3)));
}
}
protected abstract BytesReference newBytesReference(int length) throws IOException;
protected abstract BytesReference newBytesReferenceWithOffsetOfZero(int length) throws IOException;
public void testCompareTo() throws IOException {
final int iters = randomIntBetween(5, 10);
for (int i = 0; i < iters; i++) {
int length = randomIntBetween(10, PAGE_SIZE * randomIntBetween(2, 8));
BytesReference bytesReference = newBytesReference(length);
assertTrue(bytesReference.compareTo(new BytesArray("")) > 0);
assertTrue(new BytesArray("").compareTo(bytesReference) < 0);
assertEquals(0, bytesReference.compareTo(bytesReference));
int sliceFrom = randomIntBetween(0, bytesReference.length());
int sliceLength = randomIntBetween(0, bytesReference.length() - sliceFrom);
BytesReference slice = bytesReference.slice(sliceFrom, sliceLength);
assertEquals(
bytesReference.toBytesRef().compareTo(slice.toBytesRef()),
new BytesArray(bytesReference.toBytesRef(), true).compareTo(new BytesArray(slice.toBytesRef(), true))
);
assertEquals(bytesReference.toBytesRef().compareTo(slice.toBytesRef()), bytesReference.compareTo(slice));
assertEquals(slice.toBytesRef().compareTo(bytesReference.toBytesRef()), slice.compareTo(bytesReference));
assertEquals(0, slice.compareTo(new BytesArray(slice.toBytesRef())));
assertEquals(0, new BytesArray(slice.toBytesRef()).compareTo(slice));
final int crazyLength = length + randomIntBetween(10, PAGE_SIZE * randomIntBetween(2, 8));
ReleasableBytesStreamOutput crazyStream = new ReleasableBytesStreamOutput(length, bigarrays);
final int offset = randomIntBetween(0, crazyLength - length);
for (int j = 0; j < offset; j++) {
crazyStream.writeByte((byte) random().nextInt(1 << 8));
}
bytesReference.writeTo(crazyStream);
for (int j = crazyStream.size(); j < crazyLength; j++) {
crazyStream.writeByte((byte) random().nextInt(1 << 8));
}
BytesReference crazyReference = crazyStream.bytes();
assertFalse(crazyReference.compareTo(bytesReference) == 0);
assertEquals(0, crazyReference.slice(offset, length).compareTo(bytesReference));
assertEquals(0, bytesReference.compareTo(crazyReference.slice(offset, length)));
}
}
public static BytesRef getSinglePageOrNull(BytesReference ref) throws IOException {
if (ref.length() > 0) {
BytesRefIterator iterator = ref.iterator();
BytesRef next = iterator.next();
BytesRef retVal = next.clone();
if (iterator.next() == null) {
return retVal;
}
} else {
return new BytesRef();
}
return null;
}
public static int getNumPages(BytesReference ref) throws IOException {
int num = 0;
if (ref.length() > 0) {
BytesRefIterator iterator = ref.iterator();
while (iterator.next() != null) {
num++;
}
}
return num;
}
public void testBasicEquals() {
final int len = randomIntBetween(0, randomBoolean() ? 10 : 100000);
final int offset1 = randomInt(5);
final byte[] array1 = new byte[offset1 + len + randomInt(5)];
random().nextBytes(array1);
final int offset2 = randomInt(offset1);
final byte[] array2 = Arrays.copyOfRange(array1, offset1 - offset2, array1.length);
final BytesArray b1 = new BytesArray(array1, offset1, len);
final BytesArray b2 = new BytesArray(array2, offset2, len);
assertEquals(b1, b2);
assertEquals(Arrays.hashCode(BytesReference.toBytes(b1)), b1.hashCode());
assertEquals(Arrays.hashCode(BytesReference.toBytes(b2)), b2.hashCode());
// test same instance
assertEquals(b1, b1);
assertEquals(b2, b2);
if (len > 0) {
// test different length
BytesArray differentLen = new BytesArray(array1, offset1, randomInt(len - 1));
assertNotEquals(b1, differentLen);
// test changed bytes
array1[offset1 + randomInt(len - 1)] += (byte) 13;
assertNotEquals(b1, b2);
}
}
public void testGetInt() throws IOException {
final int count = randomIntBetween(1, 10);
final BytesReference bytesReference = newBytesReference(count * Integer.BYTES);
final BytesRef bytesRef = bytesReference.toBytesRef();
final IntBuffer intBuffer = ByteBuffer.wrap(bytesRef.bytes, bytesRef.offset, bytesRef.length)
.order(ByteOrder.BIG_ENDIAN)
.asIntBuffer();
for (int i = 0; i < count; ++i) {
assertEquals(intBuffer.get(i), bytesReference.getInt(i * Integer.BYTES));
}
}
public void testIndexOf() throws IOException {
final int size = randomIntBetween(0, 100);
final BytesReference bytesReference = newBytesReference(size);
final Map> map = new HashMap<>();
for (int i = 0; i < size; ++i) {
final byte value = bytesReference.get(i);
map.computeIfAbsent(value, v -> new ArrayList<>()).add(i);
}
map.forEach((value, positions) -> {
for (int i = 0; i < positions.size(); i++) {
final int pos = positions.get(i);
final int from = i == 0 ? randomIntBetween(0, pos) : positions.get(i - 1) + 1;
assertEquals(bytesReference.indexOf(value, from), pos);
}
});
final byte missing = randomValueOtherThanMany(map::containsKey, OpenSearchTestCase::randomByte);
assertEquals(-1, bytesReference.indexOf(missing, randomIntBetween(0, Math.max(0, size - 1))));
}
}