/* * Copyright 2015 Terracotta, Inc., a Software AG company. * * Licensed 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.terracotta.offheapstore.storage.allocator; import org.terracotta.offheapstore.storage.allocator.PowerOfTwoAllocator; import org.terracotta.offheapstore.storage.allocator.PowerOfTwoAllocator.Packing; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.junit.Assert; import org.junit.Test; import static org.terracotta.offheapstore.storage.allocator.PowerOfTwoAllocator.Packing.FLOOR; import static org.terracotta.offheapstore.storage.allocator.PowerOfTwoAllocator.Packing.CEILING; /** * * @author Chris Dennis */ public class PowerOfTwoAllocatorTest { @Test public void testUniformSizedAllocationsFromLeft() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(100); for (int i = 0; i < 100; i++) { Assert.assertEquals(i, test.allocate(1, FLOOR)); } Assert.assertEquals(100, test.occupied()); } @Test public void testUniformSizedFreesFromLeft() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(100); List<Integer> allocated = new ArrayList<Integer>(); for (int i = 0; i < 100; i++) { allocated.add(test.allocate(1, FLOOR)); } Random rndm = new Random(); for (int i = 0; i < 100; i++) { test.free(allocated.remove(rndm.nextInt(allocated.size())), 1); } Assert.assertEquals(0, test.occupied()); } @Test public void testUniformRepeatedAllocFreeFromLeft() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(16 * 1024); for (int i = 1; i < 1024; i <<= 1) { List<Integer> pointers = new ArrayList<Integer>(); for (int k = 0; k < 16; k++) { int p = test.allocate(i, FLOOR); pointers.add(p); } for (Integer p : pointers) { test.free(p, i); } Assert.assertEquals("Testing regions of size " + i, 0, test.occupied()); } } @Test public void testUniformSizedAllocationsFromRight() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(100); for (int i = 0; i < 100; i++) { Assert.assertEquals(99 - i, test.allocate(1, CEILING)); } Assert.assertEquals(100, test.occupied()); } @Test public void testUniformSizedFreesFromRight() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(100); List<Integer> allocated = new ArrayList<Integer>(); for (int i = 0; i < 100; i++) { allocated.add(test.allocate(1, CEILING)); } Random rndm = new Random(); for (int i = 0; i < 100; i++) { test.free(allocated.remove(rndm.nextInt(allocated.size())), 1); } Assert.assertEquals(0, test.occupied()); } @Test public void testUniformRepeatedAllocFreeFromRight() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(16 * 1024); for (int i = 1; i < 1024; i <<= 1) { List<Integer> pointers = new ArrayList<Integer>(); for (int k = 0; k < 16; k++) { int p = test.allocate(i, CEILING); pointers.add(p); } for (Integer p : pointers) { test.free(p, i); } Assert.assertEquals("Testing regions of size " + i, 0, test.occupied()); } } @Test public void testRandomAllocFree() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(100 * 1024 * 1024); List<AllocatedRegion> allocated = new ArrayList<AllocatedRegion>(); Random rndm = new Random(); for (int i = 0; i < 1000; i++) { if (rndm.nextBoolean()) { int size = rndm.nextInt(10); int p = test.allocate(1 << size, rndm.nextBoolean() ? FLOOR : CEILING); if (p >= 0) { allocated.add(new AllocatedRegion(p, 1 << size)); } } else { if (!allocated.isEmpty()) { AllocatedRegion r = allocated.remove(rndm.nextInt(allocated.size())); test.free(r.address, r.size); } } } } @Test public void testUniformSizedClaims() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(100); for (int i = 0; i < 100; i++) { test.claim(i, 1); } Assert.assertEquals(100, test.occupied()); } @Test public void testRandomFindsAndClaims() { PowerOfTwoAllocator test = new PowerOfTwoAllocator(100 * 1024 * 1024); PowerOfTwoAllocator reference = new PowerOfTwoAllocator(100 * 1024 * 1024); List<AllocatedRegion> allocated = new ArrayList<AllocatedRegion>(); Random rndm = new Random(); for (int i = 0; i < 1000; i++) { if (rndm.nextBoolean()) { int size = rndm.nextInt(10); Packing packing = rndm.nextBoolean() ? FLOOR : CEILING; int p = reference.allocate(1 << size, packing); Assert.assertEquals(p, test.find(1 << size, packing)); test.claim(p, 1 << size); if (p >= 0) { allocated.add(new AllocatedRegion(p, 1 << size)); } } else { if (!allocated.isEmpty()) { AllocatedRegion r = allocated.remove(rndm.nextInt(allocated.size())); reference.free(r.address, r.size); test.free(r.address, r.size); } } } } static class AllocatedRegion { private final int address; private final int size; public AllocatedRegion(int address, int size) { this.address = address; this.size = size; } } }