use Junit5 instead of TestNG

We want to be able to use @SpringBootTest tests that fully initialize
the Spring application. This is much easier done with Junit than TestNG.
Gradle does not support (at least not easily) to run Junit and TestNG
tests. Therefore we switch to Junit with all tests.
The original reason for using TestNG was that Junit didn't support
data providers. But that finally changed in Junit5 with
ParameterizedTest.
This commit is contained in:
2019-12-13 14:33:20 +01:00
parent 394e16ad27
commit 07ad62ddd9
26 changed files with 660 additions and 837 deletions

View File

@@ -1,39 +1,37 @@
package org.lucares.utils.byteencoder;
import static org.testng.Assert.assertEquals;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.lucares.collections.LongList;
import org.lucares.utils.byteencoder.VariableByteEncoder;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@Test
public class VariableByteEncoderTest {
@DataProvider
public Object[][] providerEncodeDecode() {
return new Object[][] { //
public static Stream<Arguments> providerEncodeDecode() {
return Stream.of( //
// encoded into 1 byte
{ 10, -5, 5 }, //
{ 10, 0, 5 }, //
{ 10, -63, 63 }, //
Arguments.of(10, -5, 5), //
Arguments.of(10, 0, 5), //
Arguments.of(10, -63, 63), //
// encoded into 2 bytes
{ 10, 130, 131 }, //
Arguments.of(10, 130, 131), //
// encoded into 3 bytes
{ 10, -8191, 8191 }, //
Arguments.of(10, -8191, 8191), //
// encoded into n bytes
{ 1, Long.MAX_VALUE / 2 - 4, Long.MAX_VALUE / 2 }, //
{ 1, Long.MIN_VALUE / 2, Long.MAX_VALUE / 2 }, //
{ 11, Long.MIN_VALUE / 2 + 1, Long.MIN_VALUE / 2 + 3 }, //
{ 12, Long.MAX_VALUE / 2 - 3, Long.MAX_VALUE / 2 },//
};
Arguments.of(1, Long.MAX_VALUE / 2 - 4, Long.MAX_VALUE / 2), //
Arguments.of(1, Long.MIN_VALUE / 2, Long.MAX_VALUE / 2), //
Arguments.of(11, Long.MIN_VALUE / 2 + 1, Long.MIN_VALUE / 2 + 3), //
Arguments.of(12, Long.MAX_VALUE / 2 - 3, Long.MAX_VALUE / 2)//
);
}
@Test(dataProvider = "providerEncodeDecode")
@ParameterizedTest
@MethodSource("providerEncodeDecode")
public void testEncodeDecode(final long numValues, final long minValue, final long maxValue) {
final LongList originalValues = new LongList();
@@ -48,63 +46,63 @@ public class VariableByteEncoderTest {
final LongList actualValues = VariableByteEncoder.decode(buffer);
assertEquals(actualValues.toString(), originalValues.toString());
Assertions.assertEquals(originalValues.toString(), actualValues.toString());
}
@DataProvider
public Object[][] providerEncodeDecodeOfTwoValues() {
return new Object[][] { //
{ 12345, 67890, false, 1 }, // first value needs three bytes, it does not fit
{ 12345, 67890, false, 2 }, // first value needs three bytes, it does not fit
{ 12345, 67890, false, 3 }, // first value needs three bytes, second value does not fit
{ 12345, 67890, false, 4 }, // first value needs three bytes, second value does not fit
{ 12345, 67890, false, 5 }, // first value needs three bytes, second value does not fit
{ 12345, 67890, true, 6 }, // both values need three bytes
{ 12345, 67890, true, 10 }, //
};
public static Stream<Arguments> providerEncodeDecodeOfTwoValues() {
return Stream.of( //
Arguments.of(12345, 67890, false, 1), // first value needs three bytes, it does not fit
Arguments.of(12345, 67890, false, 2), // first value needs three bytes, it does not fit
Arguments.of(12345, 67890, false, 3), // first value needs three bytes, second value does not fit
Arguments.of(12345, 67890, false, 4), // first value needs three bytes, second value does not fit
Arguments.of(12345, 67890, false, 5), // first value needs three bytes, second value does not fit
Arguments.of(12345, 67890, true, 6), // both values need three bytes
Arguments.of(12345, 67890, true, 10) //
);
}
@Test(dataProvider = "providerEncodeDecodeOfTwoValues")
@ParameterizedTest
@MethodSource("providerEncodeDecodeOfTwoValues")
public void testEncodeDecodeOfTwoValues(final long value1, final long value2, final boolean fits,
final int bufferSize) {
final LongList originalValues = new LongList();
final byte[] buffer = new byte[bufferSize];
final int bytesAdded = VariableByteEncoder.encodeInto(value1, value2, buffer, 0);
Assert.assertEquals(bytesAdded > 0, fits);
Assertions.assertEquals(fits, bytesAdded > 0);
if (fits) {
originalValues.addAll(value1, value2);
} else {
Assert.assertEquals(buffer, new byte[bufferSize],
Assertions.assertArrayEquals(new byte[bufferSize], buffer,
"checks that buffer is resetted after it discovers the values do not fit");
}
final LongList decodedValues = VariableByteEncoder.decode(buffer);
Assert.assertEquals(decodedValues, originalValues);
Assertions.assertEquals(originalValues, decodedValues);
}
@DataProvider
public Object[][] providerNededBytes() {
return new Object[][] { //
{ 0, 1 }, //
{ -10, 1 }, //
{ 10, 1 }, //
{ -63, 1 }, //
{ 63, 1 }, //
{ -64, 2 }, //
{ 64, 2 }, //
{ -8191, 2 }, //
{ 8191, 2 }, //
{ -8192, 3 }, //
{ 8192, 3 }, //
};
public static Stream<Arguments> providerNededBytes() {
return Stream.of( //
Arguments.of(0, 1), //
Arguments.of(-10, 1), //
Arguments.of(10, 1), //
Arguments.of(-63, 1), //
Arguments.of(63, 1), //
Arguments.of(-64, 2), //
Arguments.of(64, 2), //
Arguments.of(-8191, 2), //
Arguments.of(8191, 2), //
Arguments.of(-8192, 3), //
Arguments.of(8192, 3) //
);
}
@Test(dataProvider = "providerNededBytes")
@ParameterizedTest
@MethodSource("providerNededBytes")
public void testNeededBytes(final long value, final int expectedNeededBytes) {
final int neededBytes = VariableByteEncoder.neededBytes(value);
final byte[] encoded = VariableByteEncoder.encode(value);
Assert.assertEquals(encoded.length, neededBytes);
Assertions.assertEquals(neededBytes, encoded.length);
}
}

View File

@@ -18,28 +18,27 @@ import java.util.concurrent.TimeoutException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;
@Test
public class HotEntryCacheTest {
static {
Configurator.setRootLevel(Level.TRACE);
Configurator.setRootLevel(Level.INFO);
}
private static final Logger LOGGER = LoggerFactory.getLogger(HotEntryCacheTest.class);
private int cacheId = 0;
@Test(invocationCount = 1)
@Test
public void testRemovalListenerCalledOnExpire() throws InterruptedException {
LOGGER.info("");
LOGGER.info("");
LOGGER.info("start: testRemovalListenerCalledOnExpire");
LOGGER.debug("");
LOGGER.debug("");
LOGGER.debug("start: testRemovalListenerCalledOnExpire");
final long originalMinSleepPeriod = HotEntryCache.getMinSleepPeriod();
final long originalMaxSleepPeriod = HotEntryCache.getMaxSleepPeriod();
@@ -53,36 +52,38 @@ public class HotEntryCacheTest {
HotEntryCache.setMinSleepPeriod(1);
HotEntryCache.setMaxSleepPeriod(2);
cache.addListener((k, v) -> {
Assert.assertEquals(k, key);
Assert.assertEquals(v, value);
Assertions.assertEquals(key, k);
Assertions.assertEquals(value, v);
latch.countDown();
});
cache.put(key, value);
final boolean listenerCalled = latch.await(100, TimeUnit.MILLISECONDS);
Assert.assertTrue(listenerCalled, "removal listener called");
Assertions.assertTrue(listenerCalled, "removal listener called");
} finally {
HotEntryCache.setMinSleepPeriod(originalMinSleepPeriod);
HotEntryCache.setMaxSleepPeriod(originalMaxSleepPeriod);
}
}
@Test
public void testPutAndGet() throws InterruptedException, ExecutionException, TimeoutException {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final String replacedNull = cache.put("key", "value1");
Assert.assertEquals(replacedNull, null);
Assertions.assertEquals(null, replacedNull);
final String cachedValue1 = cache.get("key");
Assert.assertEquals(cachedValue1, "value1");
Assertions.assertEquals("value1", cachedValue1);
final String replacedValue1 = cache.put("key", "value2");
Assert.assertEquals(replacedValue1, "value1");
Assertions.assertEquals("value1", replacedValue1);
final String cachedValue2 = cache.get("key");
Assert.assertEquals(cachedValue2, "value2");
Assertions.assertEquals("value2", cachedValue2);
}
@Test
public void testPutTouches() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
@@ -101,16 +102,17 @@ public class HotEntryCacheTest {
// second put.
final String cachedValue2 = cache.get("key");
Assert.assertEquals(cachedValue2, "value2");
Assertions.assertEquals("value2", cachedValue2);
clock.plus(timeToLive.plusSeconds(1));
// time elapsed since the last put: timeToLive +1s
cache.triggerEvictionAndWait();
final String cachedValue1_evicted = cache.get("key");
Assert.assertEquals(cachedValue1_evicted, null);
Assertions.assertEquals(null, cachedValue1_evicted);
}
@Test
public void testGetTouches() throws Exception {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
@@ -127,9 +129,10 @@ public class HotEntryCacheTest {
cache.triggerEvictionAndWait(); // if get didn't touch, then this will evict the entry
final String cachedValue1 = cache.get("key");
Assert.assertEquals(cachedValue1, "value1");
Assertions.assertEquals("value1", cachedValue1);
}
@Test
public void testEvictionByBackgroundThread() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
@@ -150,13 +153,14 @@ public class HotEntryCacheTest {
cache.triggerEvictionAndWait();
final String evictedValue1 = evictionEventFuture.get(5, TimeUnit.MINUTES); // enough time for debugging
Assert.assertEquals(evictedValue1, "value1");
Assertions.assertEquals("value1", evictedValue1);
}
@Test
public void testRemove() throws InterruptedException, ExecutionException, TimeoutException {
LOGGER.info("");
LOGGER.info("");
LOGGER.info("start: testRemove");
LOGGER.debug("");
LOGGER.debug("");
LOGGER.debug("start: testRemove");
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
@@ -166,13 +170,14 @@ public class HotEntryCacheTest {
cache.put("key", "value1");
final String removedValue = cache.remove("key");
Assert.assertEquals(removedValue, "value1");
Assertions.assertEquals("value1", removedValue);
Assert.assertEquals(removedValues, Arrays.asList("value1"));
Assertions.assertEquals(Arrays.asList("value1"), removedValues);
Assert.assertEquals(cache.get("key"), null);
Assertions.assertEquals(null, cache.get("key"));
}
@Test
public void testClear() throws InterruptedException, ExecutionException, TimeoutException {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
@@ -184,12 +189,13 @@ public class HotEntryCacheTest {
cache.clear();
Assert.assertEquals(cache.get("key1"), null);
Assert.assertEquals(cache.get("key2"), null);
Assertions.assertEquals(null, cache.get("key1"));
Assertions.assertEquals(null, cache.get("key2"));
Assert.assertEquals(removedValues, Arrays.asList("value1", "value2"));
Assertions.assertEquals(Arrays.asList("value1", "value2"), removedValues);
}
@Test
public void testForEachTouches() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
@@ -216,13 +222,13 @@ public class HotEntryCacheTest {
cache.triggerEvictionAndWait();
// if the touch didn't happen, then the value is now evicted
Assert.assertEquals(evictionEventFuture.isDone(), false);
Assertions.assertEquals(false, evictionEventFuture.isDone());
// seek again, so that the entry will get evicted
clock.plus(timeToLive.minusMillis(1));
cache.triggerEvictionAndWait();
Assert.assertEquals(cache.get("key"), null);
Assertions.assertEquals(null, cache.get("key"));
}
/**
@@ -235,6 +241,7 @@ public class HotEntryCacheTest {
*
* @throws Exception
*/
@Test
public void testPutIfAbsentIsAtomic() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
@@ -264,12 +271,13 @@ public class HotEntryCacheTest {
pool.awaitTermination(1, TimeUnit.MINUTES);
final String actual = cache.get(key);
Assert.assertEquals(actual, valueA);
Assertions.assertEquals(valueA, actual);
} finally {
pool.shutdownNow();
}
}
@Test
public void testPutIfAbsentReturnsExistingValue() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
@@ -280,23 +288,25 @@ public class HotEntryCacheTest {
cache.put(key, valueA);
final String returnedByPutIfAbsent = cache.putIfAbsent(key, k -> valueB);
Assert.assertEquals(returnedByPutIfAbsent, valueA);
Assertions.assertEquals(valueA, returnedByPutIfAbsent);
final String actualInCache = cache.get(key);
Assert.assertEquals(actualInCache, valueA);
Assertions.assertEquals(valueA, actualInCache);
}
@Test
public void testPutIfAbsentDoesNotAddNull() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final String key = "key";
final String returnedByPutIfAbsent = cache.putIfAbsent(key, k -> null);
Assert.assertNull(returnedByPutIfAbsent, null);
Assertions.assertNull(returnedByPutIfAbsent);
final String actualInCache = cache.get(key);
Assert.assertEquals(actualInCache, null);
Assertions.assertEquals(null, actualInCache);
}
@Test
public void testMaxSizeIsRespected() {
final int maxSize = 10;
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
@@ -312,8 +322,8 @@ public class HotEntryCacheTest {
clock.plus(2L, ChronoUnit.MILLIS);
cache.updateTime();
}
Assert.assertEquals(cache.size(), maxSize, "cache is full");
Assert.assertEquals(removedKeys, List.of(), "removed keys at point A");
Assertions.assertEquals(maxSize, cache.size(), "cache is full");
Assertions.assertEquals(Set.of(), removedKeys, "removed keys at point A");
// add an item to a full cache -> the oldest 20% of the entries will be evicted
// before the new entry is added
@@ -322,10 +332,11 @@ public class HotEntryCacheTest {
cache.updateTime();
count++;
Assert.assertEquals(cache.size(), maxSize - 1, "cache was full, 20% (2 items) were removed and one added");
Assert.assertEquals(removedKeys, Set.of("key0", "key1"), "removed keys at point B");
Assertions.assertEquals(maxSize - 1, cache.size(), "cache was full, 20% (2 items) were removed and one added");
Assertions.assertEquals(Set.of("key0", "key1"), removedKeys, "removed keys at point B");
}
@Test
public void testEvictionDueToSizeLimitDoesNotRemoveMoreThan20Percent() {
final int maxSize = 10;
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
@@ -339,16 +350,16 @@ public class HotEntryCacheTest {
// all entries get the same eviction time due to the fixed clock
cache.put("key" + count, "value" + count);
}
Assert.assertEquals(cache.size(), maxSize, "cache is full");
Assert.assertEquals(removedKeys, List.of(), "removed keys at point A");
Assertions.assertEquals(maxSize, cache.size(), "cache is full");
Assertions.assertEquals(Set.of(), removedKeys, "removed keys at point A");
// add an item to a full cache -> the oldest 20% of the entries will be evicted
// before the new entry is added
cache.put("key" + count, "value" + count);
count++;
Assert.assertEquals(cache.size(), maxSize - 1, "cache was full, 20% (2 items) were removed and one added");
Assert.assertEquals(removedKeys.size(), (int) (maxSize * 0.2), "number of removed keys at point B");
Assertions.assertEquals(maxSize - 1, cache.size(), "cache was full, 20% (2 items) were removed and one added");
Assertions.assertEquals((int) (maxSize * 0.2), removedKeys.size(), "number of removed keys at point B");
}
private void sleep(final TimeUnit timeUnit, final long timeout) {