256 lines
7.7 KiB
Java

package net.reslate.islandsurvivalcraft.utilities.caching;
import static org.junit.Assert.assertSame;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
@TestInstance(Lifecycle.PER_CLASS)
public class CacheTest {
private volatile Cache<Integer, String> integerCache;
private final int LARGE_CACHE_SIZE = 262144;
private final int[] answers = new int[LARGE_CACHE_SIZE];
private final Random rand = new Random();
Cache<Integer, Integer> lCache = new Cache<>(LARGE_CACHE_SIZE);
@BeforeAll
public void setUp() {
integerCache = new Cache<>(3);
for (int i = 0; i < answers.length; i++) {
answers[i] = rand.nextInt();
}
}
@AfterEach
public void cleanUp() {
lCache.clearCache();
integerCache.clearCache();
}
@Test
public void testBasicCaching() {
String val = integerCache.get(0);
assertTrue(val == null);
val = "first";
integerCache.set(0, val);
assertTrue(integerCache.get(0) != null);
assertSame(val, integerCache.get(0));
val = integerCache.get(1);
assertTrue(val == null);
val = "second";
integerCache.set(1, val);
assertTrue(integerCache.get(1) != null);
assertSame(val, integerCache.get(1));
}
@Test
public void testUsageBasedClean() {
integerCache.set(0, "first");
integerCache.set(1, "second");
integerCache.set(2, "third");
assertEquals("first", integerCache.get(0));
integerCache.set(3, "fourth");
assertEquals("first", integerCache.get(0));
integerCache.set(4, "fifth");
assertTrue(integerCache.get(3) != null);
assertTrue(integerCache.get(0) != null);
}
@Test
public void testUsageLargeData() {
int amount = 1024;
Random random = new Random();
Cache<Integer, Integer> largeCache = new Cache<>(amount / 2);
int[] values = new int[amount];
for (int i = 0; i < amount; i++) {
values[i] = random.nextInt();
largeCache.set(i, values[i]);
}
for (int i = 0; i < amount / 2; i++) {
assertEquals(null, largeCache.get(i), "Current accessor: " + i);
}
for (int i = amount / 2; i < amount; i++) {
assertEquals(values[i], largeCache.get(i), "Current accessor: " + i);
}
}
@Test
public void testUsageLargeDataImportance() {
int amount = 1024;
Random random = new Random();
Cache<Integer, Integer> largeCache = new Cache<>(amount / 2);
int[] values = new int[amount];
for (int i = 0; i < amount; i++) {
values[i] = random.nextInt();
largeCache.set(i, values[i]);
largeCache.get(0);
}
for (int i = 1; i < (amount / 2) + 1; i++) {
assertEquals(null, largeCache.get(i), "Current accessor: " + i);
}
for (int i = (amount / 2) + 1; i < amount; i++) {
assertEquals(values[i], largeCache.get(i), "Current accessor: " + i);
}
assertEquals(values[0], largeCache.get(0));
}
@Test
public void testMultithreadingWriteConsistency() {
Runnable write = new Runnable() {
@Override
public void run() {
for (int i = 0; i < LARGE_CACHE_SIZE; i++) {
lCache.set(i, answers[i]);
}
}
};
Thread firstThread = new Thread(write);
firstThread.start();
Thread secondThread = new Thread(write);
secondThread.start();
Thread thirdThread = new Thread(write);
thirdThread.start();
try {
firstThread.join();
secondThread.join();
thirdThread.join();
} catch (InterruptedException e) {
assertFalse(false, e.getCause().getMessage());
}
for (int i = 0; i < LARGE_CACHE_SIZE; i++) {
assertEquals(answers[i], lCache.get(i), "Accessor at: " + i);
}
}
@Test
public void testMultithreadingReadConsistency() {
for (int i = 0; i < answers.length; i++) {
lCache.set(i, answers[i]);
}
Runnable read = new Runnable() {
@Override
public void run() {
for (int i = 0; i < LARGE_CACHE_SIZE; i++) {
assertEquals(answers[i], lCache.get(i), "Accessor at: " + i);
}
}
};
Thread firstThread = new Thread(read);
firstThread.start();
Thread secondThread = new Thread(read);
secondThread.start();
Thread thirdThread = new Thread(read);
thirdThread.start();
try {
firstThread.join();
secondThread.join();
thirdThread.join();
} catch (InterruptedException e) {
assertFalse(false, e.getCause().getMessage());
}
}
@Test
public void testMulthreadedReadWrite() {
Runnable readWrite = new Runnable() {
@Override
public void run() {
for (int i = 0; i < LARGE_CACHE_SIZE; i++) {
if (lCache.get(i) == null) {
lCache.set(i, answers[i]);
} else {
assertEquals(answers[i], lCache.get(i), "Accessor at: " + i);
}
}
}
};
Runnable readAll = new Runnable() {
@Override
public void run() {
for (int i = 0; i < LARGE_CACHE_SIZE; i++) {
assertEquals(answers[i], lCache.get(i), "Accessor at: " + i);
}
}
};
Thread firstThread = new Thread(readWrite);
firstThread.start();
Thread secondThread = new Thread(readWrite);
secondThread.start();
Thread thirdThread = new Thread(readAll);
try {
firstThread.join();
secondThread.join();
thirdThread.start();
thirdThread.join();
} catch (InterruptedException e) {
assertFalse(false, e.getCause().getMessage());
}
}
@Test
public void testMultiThreadConsistency() {
Runnable readWriteCheck = new Runnable(){
@Override
public void run() {
for (int i = 0; i < LARGE_CACHE_SIZE; i++) {
if (lCache.get(i) != null) {
assertEquals(answers[i], lCache.get(i), "Accessor at: " + i);
} else {
lCache.set(i, answers[i]);
}
}
}
};
ExecutorService executorService = Executors.newFixedThreadPool(6);
executorService.submit(readWriteCheck);
executorService.submit(readWriteCheck);
executorService.submit(readWriteCheck);
executorService.submit(readWriteCheck);
executorService.submit(readWriteCheck);
executorService.submit(readWriteCheck);
try {
executorService.shutdown();
assertTrue(executorService.awaitTermination(1, TimeUnit.MINUTES), "Timed out.");
} catch (InterruptedException e) {
assertFalse(false, e.getCause().getMessage());
}
}
}