/* * 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.util.ArrayList; import java.util.HashSet; import java.util.List; import org.junit.Before; import org.junit.Test; /** * Testcase for {@link RecyclingByteBlockAllocator} */ public class TestRecyclingByteBlockAllocator extends LuceneTestCase { /** */ @Override @Before public void setUp() throws Exception { super.setUp(); } private RecyclingByteBlockAllocator newAllocator() { return new RecyclingByteBlockAllocator(1 << (2 + random().nextInt(15)), random().nextInt(97), Counter.newCounter()); } @Test public void testAllocate() { RecyclingByteBlockAllocator allocator = newAllocator(); HashSet<byte[]> set = new HashSet<>(); byte[] block = allocator.getByteBlock(); set.add(block); assertNotNull(block); final int size = block.length; int num = atLeast(97); for (int i = 0; i < num; i++) { block = allocator.getByteBlock(); assertNotNull(block); assertEquals(size, block.length); assertTrue("block is returned twice", set.add(block)); assertEquals(size * (i + 2), allocator.bytesUsed()); // zero based + 1 assertEquals(0, allocator.numBufferedBlocks()); } } @Test public void testAllocateAndRecycle() { RecyclingByteBlockAllocator allocator = newAllocator(); HashSet<byte[]> allocated = new HashSet<>(); byte[] block = allocator.getByteBlock(); allocated.add(block); assertNotNull(block); final int size = block.length; int numIters = atLeast(97); for (int i = 0; i < numIters; i++) { int num = 1 + random().nextInt(39); for (int j = 0; j < num; j++) { block = allocator.getByteBlock(); assertNotNull(block); assertEquals(size, block.length); assertTrue("block is returned twice", allocated.add(block)); assertEquals(size * (allocated.size() + allocator.numBufferedBlocks()), allocator .bytesUsed()); } byte[][] array = allocated.toArray(new byte[0][]); int begin = random().nextInt(array.length); int end = begin + random().nextInt(array.length - begin); List<byte[]> selected = new ArrayList<>(); for (int j = begin; j < end; j++) { selected.add(array[j]); } allocator.recycleByteBlocks(array, begin, end); for (int j = begin; j < end; j++) { assertNull(array[j]); byte[] b = selected.remove(0); assertTrue(allocated.remove(b)); } } } @Test public void testAllocateAndFree() { RecyclingByteBlockAllocator allocator = newAllocator(); HashSet<byte[]> allocated = new HashSet<>(); int freeButAllocated = 0; byte[] block = allocator.getByteBlock(); allocated.add(block); assertNotNull(block); final int size = block.length; int numIters = atLeast(97); for (int i = 0; i < numIters; i++) { int num = 1 + random().nextInt(39); for (int j = 0; j < num; j++) { block = allocator.getByteBlock(); freeButAllocated = Math.max(0, freeButAllocated - 1); assertNotNull(block); assertEquals(size, block.length); assertTrue("block is returned twice", allocated.add(block)); assertEquals(size * (allocated.size() + allocator.numBufferedBlocks()), allocator.bytesUsed()); } byte[][] array = allocated.toArray(new byte[0][]); int begin = random().nextInt(array.length); int end = begin + random().nextInt(array.length - begin); for (int j = begin; j < end; j++) { byte[] b = array[j]; assertTrue(allocated.remove(b)); } allocator.recycleByteBlocks(array, begin, end); for (int j = begin; j < end; j++) { assertNull(array[j]); } // randomly free blocks int numFreeBlocks = allocator.numBufferedBlocks(); int freeBlocks = allocator.freeBlocks(random().nextInt(7 + allocator .maxBufferedBlocks())); assertEquals(allocator.numBufferedBlocks(), numFreeBlocks - freeBlocks); } } }