blob: 28050b4b562c1e6f64ca74f186c7cd775dd3c7ab [file] [log] [blame]
/*
* 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.lucene.util;
import java.io.IOException;
import java.util.*;
import org.apache.lucene.store.BaseDirectoryWrapper;
import org.apache.lucene.store.DataInput;
import org.apache.lucene.store.DataOutput;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.MockDirectoryWrapper;
import org.junit.Ignore;
public class TestPagedBytes extends LuceneTestCase {
// Writes random byte/s to "normal" file in dir, then
// copies into PagedBytes and verifies with
// PagedBytes.Reader:
public void testDataInputOutput() throws Exception {
Random random = random();
int numIters = atLeast(1);
for (int iter = 0; iter < numIters; iter++) {
BaseDirectoryWrapper dir = newFSDirectory(createTempDir("testOverflow"));
if (dir instanceof MockDirectoryWrapper) {
((MockDirectoryWrapper) dir).setThrottling(MockDirectoryWrapper.Throttling.NEVER);
}
final int blockBits = TestUtil.nextInt(random, 1, 20);
final int blockSize = 1 << blockBits;
final PagedBytes p = new PagedBytes(blockBits);
final IndexOutput out = dir.createOutput("foo", IOContext.DEFAULT);
final int numBytes;
if (TEST_NIGHTLY) {
numBytes = TestUtil.nextInt(random(), 2, 10_000_000);
} else {
numBytes = TestUtil.nextInt(random(), 2, 1_000_000);
}
final byte[] answer = new byte[numBytes];
random.nextBytes(answer);
int written = 0;
while (written < numBytes) {
if (random.nextInt(100) == 7) {
out.writeByte(answer[written++]);
} else {
int chunk = Math.min(random.nextInt(1000), numBytes - written);
out.writeBytes(answer, written, chunk);
written += chunk;
}
}
out.close();
final IndexInput input = dir.openInput("foo", IOContext.DEFAULT);
final DataInput in = input.clone();
p.copy(input, input.length());
final PagedBytes.Reader reader = p.freeze(random.nextBoolean());
final byte[] verify = new byte[numBytes];
int read = 0;
while (read < numBytes) {
if (random.nextInt(100) == 7) {
verify[read++] = in.readByte();
} else {
int chunk = Math.min(random.nextInt(1000), numBytes - read);
in.readBytes(verify, read, chunk);
read += chunk;
}
}
assertTrue(Arrays.equals(answer, verify));
final BytesRef slice = new BytesRef();
for (int iter2 = 0; iter2 < 100; iter2++) {
final int pos = random.nextInt(numBytes - 1);
final int len = random.nextInt(Math.min(blockSize + 1, numBytes - pos));
reader.fillSlice(slice, pos, len);
for (int byteUpto = 0; byteUpto < len; byteUpto++) {
assertEquals(answer[pos + byteUpto], slice.bytes[slice.offset + byteUpto]);
}
}
input.close();
dir.close();
}
}
// Writes random byte/s into PagedBytes via
// .getDataOutput(), then verifies with
// PagedBytes.getDataInput():
public void testDataInputOutput2() throws Exception {
Random random = random();
int numIters = atLeast(1);
for (int iter = 0; iter < numIters; iter++) {
final int blockBits = TestUtil.nextInt(random, 1, 20);
final int blockSize = 1 << blockBits;
final PagedBytes p = new PagedBytes(blockBits);
final DataOutput out = p.getDataOutput();
final int numBytes;
if (TEST_NIGHTLY) {
numBytes = random().nextInt(10_000_000);
} else {
numBytes = random().nextInt(1_000_000);
}
final byte[] answer = new byte[numBytes];
random().nextBytes(answer);
int written = 0;
while (written < numBytes) {
if (random().nextInt(10) == 7) {
out.writeByte(answer[written++]);
} else {
int chunk = Math.min(random().nextInt(1000), numBytes - written);
out.writeBytes(answer, written, chunk);
written += chunk;
}
}
final PagedBytes.Reader reader = p.freeze(random.nextBoolean());
final DataInput in = p.getDataInput();
final byte[] verify = new byte[numBytes];
int read = 0;
while (read < numBytes) {
if (random().nextInt(10) == 7) {
verify[read++] = in.readByte();
} else {
int chunk = Math.min(random().nextInt(1000), numBytes - read);
in.readBytes(verify, read, chunk);
read += chunk;
}
}
assertTrue(Arrays.equals(answer, verify));
final BytesRef slice = new BytesRef();
for (int iter2 = 0; iter2 < 100; iter2++) {
final int pos = random.nextInt(numBytes - 1);
final int len = random.nextInt(Math.min(blockSize + 1, numBytes - pos));
reader.fillSlice(slice, pos, len);
for (int byteUpto = 0; byteUpto < len; byteUpto++) {
assertEquals(answer[pos + byteUpto], slice.bytes[slice.offset + byteUpto]);
}
}
// test skipping
final DataInput in2 = p.getDataInput();
int maxSkipTo = numBytes - 1;
// skip chunks of bytes until exhausted
for (int curr = 0; curr < maxSkipTo; ) {
int skipTo = TestUtil.nextInt(random, curr, maxSkipTo);
int step = skipTo - curr;
in2.skipBytes(step);
assertEquals(answer[skipTo], in2.readByte());
curr = skipTo + 1; // +1 for read byte
}
}
}
@Ignore // memory hole
public void testOverflow() throws IOException {
BaseDirectoryWrapper dir = newFSDirectory(createTempDir("testOverflow"));
if (dir instanceof MockDirectoryWrapper) {
((MockDirectoryWrapper) dir).setThrottling(MockDirectoryWrapper.Throttling.NEVER);
}
final int blockBits = TestUtil.nextInt(random(), 14, 28);
final int blockSize = 1 << blockBits;
byte[] arr = new byte[TestUtil.nextInt(random(), blockSize / 2, blockSize * 2)];
for (int i = 0; i < arr.length; ++i) {
arr[i] = (byte) i;
}
final long numBytes = (1L << 31) + TestUtil.nextInt(random(), 1, blockSize * 3);
final PagedBytes p = new PagedBytes(blockBits);
final IndexOutput out = dir.createOutput("foo", IOContext.DEFAULT);
for (long i = 0; i < numBytes; ) {
assertEquals(i, out.getFilePointer());
final int len = (int) Math.min(arr.length, numBytes - i);
out.writeBytes(arr, len);
i += len;
}
assertEquals(numBytes, out.getFilePointer());
out.close();
final IndexInput in = dir.openInput("foo", IOContext.DEFAULT);
p.copy(in, numBytes);
final PagedBytes.Reader reader = p.freeze(random().nextBoolean());
for (long offset :
new long[] {
0L, Integer.MAX_VALUE, numBytes - 1, TestUtil.nextLong(random(), 1, numBytes - 2)
}) {
BytesRef b = new BytesRef();
reader.fillSlice(b, offset, 1);
assertEquals(arr[(int) (offset % arr.length)], b.bytes[b.offset]);
}
in.close();
dir.close();
}
public void testRamBytesUsed() {
final int blockBits = TestUtil.nextInt(random(), 4, 22);
PagedBytes b = new PagedBytes(blockBits);
final int totalBytes = random().nextInt(10000);
for (long pointer = 0; pointer < totalBytes; ) {
BytesRef bytes = new BytesRef(TestUtil.randomSimpleString(random(), 10));
pointer = b.copyUsingLengthPrefix(bytes);
}
assertEquals(RamUsageTester.sizeOf(b), b.ramBytesUsed());
final PagedBytes.Reader reader = b.freeze(random().nextBoolean());
assertEquals(RamUsageTester.sizeOf(b), b.ramBytesUsed());
assertEquals(RamUsageTester.sizeOf(reader), reader.ramBytesUsed());
}
}