/*
* 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;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.junit.Assert;
import org.terracotta.offheapstore.exceptions.OversizeMappingException;
import org.terracotta.offheapstore.jdk8.BiFunction;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.number.OrderingComparison.lessThan;
import static org.junit.Assert.assertThat;
public final class CacheTestRoutines {
private CacheTestRoutines() {
//
}
public static void testCacheEviction(Map<Integer, Integer> cache, CapacityLimitedIntegerStorageEngineFactory engine) {
Random rndm = new Random();
int toAdd = 100 + rndm.nextInt(90);
engine.setCapacity(toAdd);
for (int i = 0; i < toAdd; i++) {
cache.put(i, i);
Assert.assertEquals(i + 1, cache.size());
for (int j = 0; j <= i; j++) {
Assert.assertTrue(cache.get(j).intValue() == j);
}
}
int toEvict = 100 + rndm.nextInt(90);
for (int i = toAdd; i < toEvict + toAdd; i++) {
cache.put(i, i);
Assert.assertEquals(toAdd, cache.size());
Assert.assertTrue(cache.get(i).intValue() == i);
}
}
public static void testCacheEvictionMinimal(Map<Integer, Integer> cache) {
for (int i = 0; i < 200; i++) {
cache.put(i, i);
Assert.assertTrue(cache.get(i).intValue() == i);
}
}
public static void testCacheEvictionThreshold(Map<Integer, byte[]> cache) {
Assert.assertNull(cache.put(0, new byte[100]));
try {
cache.put(0, new byte[1024 * 1024]);
Assert.fail("Expected OversizeMappingException");
} catch (OversizeMappingException e) {
//expected
}
}
public static void testFillBehavior(Map<Integer, byte[]> cache) {
for (int i = 0; i < 100000; i++) {
Set<Integer> keySetCopy = new HashSet<Integer>(cache.keySet());
AbstractOffHeapMapIT.doFill(cache, i, new byte[i % 1024]);
if (cache.containsKey(i)) {
Assert.assertNotNull(cache.get(i));
Assert.assertEquals(i % 1024, cache.get(i).length);
Assert.assertTrue(keySetCopy.add(i));
Assert.assertEquals(keySetCopy, cache.keySet());
} else {
Assert.assertNull(cache.get(i));
Assert.assertEquals(keySetCopy, cache.keySet());
}
}
assertThat(cache.isEmpty(), is(false));
Set<Integer> keySetCopy = new HashSet<Integer>(cache.keySet());
for (Integer k : keySetCopy) {
if (AbstractOffHeapMapIT.doFill(cache, k, new byte[(k % 1024) + 1]) == null) {
if (cache.containsKey(k)) {
Assert.assertEquals((k % 1024) + 1, cache.get(k).length);
}
} else {
Assert.assertTrue(cache.containsKey(k));
Assert.assertEquals((k % 1024) + 1, cache.get(k).length);
}
}
}
public static void testComputeEvictionBehavior(Map<Integer, byte[]> cache) {
for (int i = 0; i < 100000; i++) {
AbstractOffHeapMapIT.doComputeWithMetadata(cache, i, new BiFunction<Integer, MetadataTuple<byte[]>, MetadataTuple<byte[]>>() {
@Override
public MetadataTuple<byte[]> apply(Integer t, MetadataTuple<byte[]> u) {
return MetadataTuple.metadataTuple(new byte[t % 1024], 0);
}
});
assertThat(cache.get(i).length, is(i % 1024));
}
assertThat(cache.isEmpty(), is(false));
assertThat(cache.size(), lessThan(100000));
for (Integer k : cache.keySet()) {
assertThat(cache.get(k).length, is(k % 1024));
}
}
}