Migrate tests to use Junit5

This commit is contained in:
games647
2022-07-18 11:44:54 +02:00
parent cdb3c50b87
commit f513cffbaf
5 changed files with 125 additions and 188 deletions

View File

@ -110,7 +110,7 @@ final class EncryptionUtil {
* in a login session. * in a login session.
* *
* @param random random generator * @param random random generator
* @return an error with 4 bytes long * @return a token with 4 bytes long
*/ */
public static byte[] generateVerifyToken(RandomGenerator random) { public static byte[] generateVerifyToken(RandomGenerator random) {
byte[] token = new byte[VERIFY_TOKEN_LENGTH]; byte[] token = new byte[VERIFY_TOKEN_LENGTH];
@ -157,11 +157,11 @@ final class EncryptionUtil {
return verifier.verify(clientKey.signature()); return verifier.verify(clientKey.signature());
} }
public static boolean verifyNonce(byte[] exptected, PrivateKey decryptionKey, byte[] encryptedNonce) public static boolean verifyNonce(byte[] expected, PrivateKey decryptionKey, byte[] encryptedNonce)
throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException,
BadPaddingException, InvalidKeyException { BadPaddingException, InvalidKeyException {
byte[] decryptedNonce = decrypt(decryptionKey, encryptedNonce); byte[] decryptedNonce = decrypt(decryptionKey, encryptedNonce);
return Arrays.equals(exptected, decryptedNonce); return Arrays.equals(expected, decryptedNonce);
} }
public static boolean verifySignedNonce(byte[] nonce, PublicKey clientKey, long signatureSalt, byte[] signature) public static boolean verifySignedNonce(byte[] nonce, PublicKey clientKey, long signatureSalt, byte[] signature)
@ -199,6 +199,7 @@ final class EncryptionUtil {
} }
private static byte[] getServerIdHash(String sessionId, PublicKey publicKey, SecretKey sharedSecret) { private static byte[] getServerIdHash(String sessionId, PublicKey publicKey, SecretKey sharedSecret) {
@SuppressWarnings("deprecation")
Hasher hasher = Hashing.sha1().newHasher(); Hasher hasher = Hashing.sha1().newHasher();
hasher.putBytes(sessionId.getBytes(StandardCharsets.ISO_8859_1)); hasher.putBytes(sessionId.getBytes(StandardCharsets.ISO_8859_1));

View File

@ -30,23 +30,21 @@ import com.github.games647.fastlogin.core.CommonUtil;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.chat.ComponentSerializer;
import junit.framework.TestCase; import org.junit.jupiter.api.Test;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.hamcrest.MatcherAssert.assertThat;
public class FastLoginBukkitTest extends TestCase { class FastLoginBukkitTest {
@Test @Test
public void testRGB() { void testRGB() {
var message = "&x00002a00002b&lText"; var message = "&x00002a00002b&lText";
var msg = CommonUtil.translateColorCodes(message); var msg = CommonUtil.translateColorCodes(message);
assertThat(msg, is("§x00002a00002b§lText")); assertEquals(msg, "§x00002a00002b§lText");
var components = TextComponent.fromLegacyText(msg); var components = TextComponent.fromLegacyText(msg);
var expected = """ var expected = """
{"bold":true,"color":"#00a00b","text":"Text"}"""; {"bold":true,"color":"#00a00b","text":"Text"}""";
assertThat(ComponentSerializer.toString(components), is(expected)); assertEquals(ComponentSerializer.toString(components), expected);
} }
} }

View File

@ -50,88 +50,77 @@ import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import org.junit.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.*;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue; class EncryptionUtilTest {
public class EncryptionUtilTest {
@Test @Test
public void testVerifyToken() { void testVerifyToken() {
var random = ThreadLocalRandom.current(); var random = ThreadLocalRandom.current();
byte[] token = EncryptionUtil.generateVerifyToken(random); byte[] token = EncryptionUtil.generateVerifyToken(random);
assertThat(token, notNullValue()); assertAll(
assertThat(token.length, is(4)); () -> assertNotNull(token),
() -> assertEquals(token.length, 4)
);
} }
@Test @Test
public void testServerKey() { void testServerKey() {
KeyPair keyPair = EncryptionUtil.generateKeyPair(); KeyPair keyPair = EncryptionUtil.generateKeyPair();
Key privateKey = keyPair.getPrivate(); Key privateKey = keyPair.getPrivate();
assertThat(privateKey.getAlgorithm(), is("RSA")); assertEquals(privateKey.getAlgorithm(), "RSA");
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
assertThat(publicKey.getAlgorithm(), is("RSA")); assertEquals(publicKey.getAlgorithm(), "RSA");
// clients accept larger values than the standard vanilla server, but we shouldn't crash them // clients accept larger values than the standard vanilla server, but we shouldn't crash them
assertTrue(publicKey.getModulus().bitLength() >= 1024); assertAll(
assertTrue(publicKey.getModulus().bitLength() < 8192); () -> assertTrue(publicKey.getModulus().bitLength() >= 1024),
() -> assertTrue(publicKey.getModulus().bitLength() < 8192)
);
} }
@Test @Test
public void testExpiredClientKey() throws Exception { void testExpiredClientKey() throws Exception {
var clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json"); var clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
// Client expires at the exact second mentioned, so use it for verification // Client expires at the exact second mentioned, so use it for verification
var expiredTimestamp = clientKey.expiry(); var expiredTimestamp = clientKey.expiry();
assertThat(EncryptionUtil.verifyClientKey(clientKey, expiredTimestamp), is(false)); assertFalse(EncryptionUtil.verifyClientKey(clientKey, expiredTimestamp));
} }
@Test @ParameterizedTest
public void testInvalidChangedExpiration() throws Exception { @ValueSource(strings = {
// expiration date changed should make the signature invalid // expiration date changed should make the signature invalid while still being not expired
// expiration should still be valid "client_keys/invalid_wrong_expiration.json",
var clientKey = ResourceLoader.loadClientKey("client_keys/invalid_wrong_expiration.json"); // changed public key no longer corresponding to the signature
"client_keys/invalid_wrong_key.json",
// signature modified no longer corresponding to key and expiration date
"client_keys/invalid_wrong_signature.json"
})
void testInvalidClientKey(String clientKeySource) throws Exception {
var clientKey = ResourceLoader.loadClientKey(clientKeySource);
Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS); Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
assertThat(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp), is(false)); assertFalse(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp));
} }
@Test @Test
public void testInvalidChangedKey() throws Exception { void testValidClientKey() throws Exception {
// changed public key no longer corresponding to the signature
var clientKey = ResourceLoader.loadClientKey("client_keys/invalid_wrong_key.json");
Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
assertThat(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp), is(false));
}
@Test
public void testInvalidChangedSignature() throws Exception {
// signature modified no longer corresponding to key and expiration date
var clientKey = ResourceLoader.loadClientKey("client_keys/invalid_wrong_signature.json");
Instant expireTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
assertThat(EncryptionUtil.verifyClientKey(clientKey, expireTimestamp), is(false));
}
@Test
public void testValidClientKey() throws Exception {
var clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json"); var clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
var verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS); var verificationTimestamp = clientKey.expiry().minus(5, ChronoUnit.HOURS);
assertThat(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp), is(true)); assertTrue(EncryptionUtil.verifyClientKey(clientKey, verificationTimestamp));
} }
@Test @Test
public void testDecryptSharedSecret() throws Exception { void testDecryptSharedSecret() throws Exception {
KeyPair serverPair = EncryptionUtil.generateKeyPair(); KeyPair serverPair = EncryptionUtil.generateKeyPair();
var serverPK = serverPair.getPublic(); var serverPK = serverPair.getPublic();
@ -139,12 +128,12 @@ public class EncryptionUtilTest {
byte[] encryptedSecret = encrypt(serverPK, secretKey.getEncoded()); byte[] encryptedSecret = encrypt(serverPK, secretKey.getEncoded());
SecretKey decryptSharedKey = EncryptionUtil.decryptSharedKey(serverPair.getPrivate(), encryptedSecret); SecretKey decryptSharedKey = EncryptionUtil.decryptSharedKey(serverPair.getPrivate(), encryptedSecret);
assertThat(decryptSharedKey, is(secretKey)); assertEquals(decryptSharedKey, secretKey);
} }
private static byte[] encrypt(PublicKey receiverKey, byte... message) private static byte[] encrypt(PublicKey receiverKey, byte... message)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException { IllegalBlockSizeException, BadPaddingException {
var encryptCipher = Cipher.getInstance(receiverKey.getAlgorithm()); var encryptCipher = Cipher.getInstance(receiverKey.getAlgorithm());
encryptCipher.init(Cipher.ENCRYPT_MODE, receiverKey); encryptCipher.init(Cipher.ENCRYPT_MODE, receiverKey);
return encryptCipher.doFinal(message); return encryptCipher.doFinal(message);
@ -160,13 +149,13 @@ public class EncryptionUtilTest {
} }
@Test @Test
public void testServerIdHash() throws Exception { void testServerIdHash() throws Exception {
var serverId = ""; var serverId = "";
var sharedSecret = generateSharedKey(); var sharedSecret = generateSharedKey();
var serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key(); var serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
String sessionHash = getServerHash(serverId, sharedSecret, serverPK); String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
assertThat(EncryptionUtil.getServerIdHashString(serverId, sharedSecret, serverPK), is(sessionHash)); assertEquals(EncryptionUtil.getServerIdHashString(serverId, sharedSecret, serverPK), sessionHash);
} }
private static String getServerHash(CharSequence serverId, SecretKey sharedSecret, PublicKey serverPK) { private static String getServerHash(CharSequence serverId, SecretKey sharedSecret, PublicKey serverPK) {
@ -183,71 +172,61 @@ public class EncryptionUtilTest {
hasher.putBytes(serverPK.getEncoded()); hasher.putBytes(serverPK.getEncoded());
// It works by treating the sha1 output bytes as one large integer in two's complement and then printing the // It works by treating the sha1 output bytes as one large integer in two's complement and then printing the
// integer in base 16, placing a minus sign if the interpreted number is negative. // integer in base 16, placing a minus sign if the interpreted number is negative.
// reference: https://github.com/SpigotMC/BungeeCord/blob/ff5727c5ef9c0b56ad35f9816ae6bd660b622cf0/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java#L456 // reference:
// https://github.com/SpigotMC/BungeeCord/blob/ff5727c5ef9c0b56ad35f9816ae6bd660b622cf0/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java#L456
return new BigInteger(hasher.hash().asBytes()).toString(16); return new BigInteger(hasher.hash().asBytes()).toString(16);
} }
@Test @Test
public void testServerIdHashWrongSecret() throws Exception { void testServerIdHashWrongSecret() throws Exception {
var serverId = ""; var serverId = "";
var sharedSecret = generateSharedKey(); var sharedSecret = generateSharedKey();
var serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key(); var serverPK = ResourceLoader.loadClientKey("client_keys/valid_public_key.json").key();
String sessionHash = getServerHash(serverId, sharedSecret, serverPK); String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
assertThat(EncryptionUtil.getServerIdHashString("", generateSharedKey(), serverPK), not(sessionHash)); assertNotEquals(EncryptionUtil.getServerIdHashString("", generateSharedKey(), serverPK), sessionHash);
} }
@Test @Test
public void testServerIdHashWrongServerKey() { void testServerIdHashWrongServerKey() {
var serverId = ""; var serverId = "";
var sharedSecret = generateSharedKey(); var sharedSecret = generateSharedKey();
var serverPK = EncryptionUtil.generateKeyPair().getPublic(); var serverPK = EncryptionUtil.generateKeyPair().getPublic();
String sessionHash = getServerHash(serverId, sharedSecret, serverPK); String sessionHash = getServerHash(serverId, sharedSecret, serverPK);
var wrongPK = EncryptionUtil.generateKeyPair().getPublic(); var wrongPK = EncryptionUtil.generateKeyPair().getPublic();
assertThat(EncryptionUtil.getServerIdHashString("", sharedSecret, wrongPK), not(sessionHash)); assertNotEquals(EncryptionUtil.getServerIdHashString("", sharedSecret, wrongPK), sessionHash);
} }
@Test @Test
public void testValidSignedNonce() throws Exception { void testValidSignedNonce() throws Exception {
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json"); ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json"); SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json");
assertThat(verifySignedNonce(testData, clientKey), is(true)); assertTrue(verifySignedNonce(testData, clientKey));
} }
@Test @ParameterizedTest
public void testIncorrectNonce() throws Exception { @ValueSource(strings = {
"signature/incorrect_nonce.json",
"signature/incorrect_salt.json",
"signature/incorrect_signature.json",
})
void testIncorrectNonce(String signatureSource) throws Exception {
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json"); ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
SignatureTestData testData = SignatureTestData.fromResource("signature/incorrect_nonce.json"); SignatureTestData testData = SignatureTestData.fromResource(signatureSource);
assertThat(verifySignedNonce(testData, clientKey), is(false)); assertFalse(verifySignedNonce(testData, clientKey));
} }
@Test @Test
public void testIncorrectSalt() throws Exception { void testWrongPublicKeySigned() throws Exception {
// client generated
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
SignatureTestData testData = SignatureTestData.fromResource("signature/incorrect_salt.json");
assertThat(verifySignedNonce(testData, clientKey), is(false));
}
@Test
public void testIncorrectSignature() throws Exception {
// client generated
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/valid_public_key.json");
SignatureTestData testData = SignatureTestData.fromResource("signature/incorrect_signature.json");
assertThat(verifySignedNonce(testData, clientKey), is(false));
}
@Test
public void testWrongPublicKeySigned() throws Exception {
// load a different public key // load a different public key
ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/invalid_wrong_key.json"); ClientPublicKey clientKey = ResourceLoader.loadClientKey("client_keys/invalid_wrong_key.json");
SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json"); SignatureTestData testData = SignatureTestData.fromResource("signature/valid_signature.json");
assertThat(verifySignedNonce(testData, clientKey), is(false)); assertFalse(verifySignedNonce(testData, clientKey));
} }
private static boolean verifySignedNonce(SignatureTestData testData, ClientPublicKey clientKey) private static boolean verifySignedNonce(SignatureTestData testData, ClientPublicKey clientKey)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
PublicKey clientPublicKey = clientKey.key(); PublicKey clientPublicKey = clientKey.key();
byte[] nonce = testData.getNonce(); byte[] nonce = testData.getNonce();
@ -257,41 +236,44 @@ public class EncryptionUtilTest {
} }
@Test @Test
public void testNonce() throws Exception { void testNonce() throws Exception {
byte[] expected = {1, 2, 3, 4}; byte[] expected = {1, 2, 3, 4};
var serverKey = EncryptionUtil.generateKeyPair(); var serverKey = EncryptionUtil.generateKeyPair();
var encryptedNonce = encrypt(serverKey.getPublic(), expected); var encryptedNonce = encrypt(serverKey.getPublic(), expected);
assertThat(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce), is(true)); assertTrue(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce));
} }
@Test @Test
public void testNonceIncorrect() throws Exception { void testNonceIncorrect() throws Exception {
byte[] expected = {1, 2, 3, 4}; byte[] expected = {1, 2, 3, 4};
var serverKey = EncryptionUtil.generateKeyPair(); var serverKey = EncryptionUtil.generateKeyPair();
// flipped first character // flipped first character
var encryptedNonce = encrypt(serverKey.getPublic(), new byte[]{0, 2, 3 , 4}); var encryptedNonce = encrypt(serverKey.getPublic(), new byte[]{0, 2, 3, 4});
assertFalse(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce));
assertThat(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce), is(false));
} }
@Test(expected = GeneralSecurityException.class) @Test
public void testNonceFailedDecryption() throws Exception { void testNonceFailedDecryption() throws Exception {
byte[] expected = {1, 2, 3, 4}; byte[] expected = {1, 2, 3, 4};
var serverKey = EncryptionUtil.generateKeyPair(); var serverKey = EncryptionUtil.generateKeyPair();
// generate a new keypair that iss different // generate a new keypair that is different
var encryptedNonce = encrypt(EncryptionUtil.generateKeyPair().getPublic(), expected); var encryptedNonce = encrypt(EncryptionUtil.generateKeyPair().getPublic(), expected);
EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce); assertThrows(GeneralSecurityException.class,
() -> EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce)
);
} }
@Test(expected = GeneralSecurityException.class) @Test
public void testNonceIncorrectEmpty() throws Exception { void testNonceIncorrectEmpty() {
byte[] expected = {1, 2, 3, 4}; byte[] expected = {1, 2, 3, 4};
var serverKey = EncryptionUtil.generateKeyPair(); var serverKey = EncryptionUtil.generateKeyPair();
byte[] encryptedNonce = {}; byte[] encryptedNonce = {};
assertThat(EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce), is(false)); assertThrows(GeneralSecurityException.class,
() -> EncryptionUtil.verifyNonce(expected, serverKey.getPrivate(), encryptedNonce)
);
} }
} }

View File

@ -25,132 +25,80 @@
*/ */
package com.github.games647.fastlogin.core; package com.github.games647.fastlogin.core;
import com.github.games647.fastlogin.core.antibot.RateLimiter;
import com.github.games647.fastlogin.core.antibot.TickingRateLimiter; import com.github.games647.fastlogin.core.antibot.TickingRateLimiter;
import java.time.Duration; import java.time.Duration;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.junit.Test; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue;
public class TickingRateLimiterTest { class TickingRateLimiterTest {
/** /**
* Always expired * Always expired
*/ */
@Test @ParameterizedTest
public void allowExpire() { @ValueSource(longs = {5_000_000L, -5_000_000L})
void allowExpire(long initial) {
int size = 3; int size = 3;
FakeTicker ticker = new FakeTicker(5_000_000L); FakeTicker ticker = new FakeTicker(initial);
// run twice the size to fill it first and then test it // run twice the size to fill it first and then test it
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, size, 0); RateLimiter rateLimiter = new TickingRateLimiter(ticker, size, 0);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
assertThat("Filling up", rateLimiter.tryAcquire(), is(true)); assertTrue(rateLimiter.tryAcquire(), "Filling up");
} }
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
ticker.add(Duration.ofSeconds(1)); ticker.add(Duration.ofSeconds(1));
assertThat("Should be expired", rateLimiter.tryAcquire(), is(true)); assertTrue(rateLimiter.tryAcquire(), "Should be expired");
}
}
@Test
public void allowExpireNegative() {
int size = 3;
FakeTicker ticker = new FakeTicker(-5_000_000L);
// run twice the size to fill it first and then test it
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, size, 0);
for (int i = 0; i < size; i++) {
assertThat("Filling up", rateLimiter.tryAcquire(), is(true));
}
for (int i = 0; i < size; i++) {
ticker.add(Duration.ofSeconds(1));
assertThat("Should be expired", rateLimiter.tryAcquire(), is(true));
} }
} }
/** /**
* Too many requests * Too many requests
*/ */
@Test @ParameterizedTest
public void shouldBlock() { @ValueSource(longs = {5_000_000L, -5_000_000L})
void shouldBlock(long initial) {
int size = 3; int size = 3;
FakeTicker ticker = new FakeTicker(5_000_000L); FakeTicker ticker = new FakeTicker(initial);
// fill the size // fill the size
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, size, TimeUnit.SECONDS.toMillis(30)); RateLimiter rateLimiter = new TickingRateLimiter(ticker, size, TimeUnit.SECONDS.toMillis(30));
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
assertThat("Filling up", rateLimiter.tryAcquire(), is(true)); assertTrue(rateLimiter.tryAcquire(), "Filling up");
} }
assertThat("Should be full and no entry should be expired", rateLimiter.tryAcquire(), is(false)); assertFalse(rateLimiter.tryAcquire(), "Should be full and no entry should be expired");
} }
/**
* Too many requests
*/
@Test
public void shouldBlockNegative() {
int size = 3;
FakeTicker ticker = new FakeTicker(-5_000_000L);
// fill the size
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, size, TimeUnit.SECONDS.toMillis(30));
for (int i = 0; i < size; i++) {
assertThat("Filling up", rateLimiter.tryAcquire(), is(true));
}
assertThat("Should be full and no entry should be expired", rateLimiter.tryAcquire(), is(false));
}
/** /**
* Blocked attempts shouldn't replace existing ones. * Blocked attempts shouldn't replace existing ones.
*/ */
@Test @ParameterizedTest
public void blockedNotAdded() { @ValueSource(longs = {5_000_000L, -5_000_000L})
FakeTicker ticker = new FakeTicker(5_000_000L); void blockedNotAdded(long initial) {
FakeTicker ticker = new FakeTicker(initial);
// fill the size - 100ms should be reasonable high // fill the size - 100ms should be reasonable high
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, 1, 100); RateLimiter rateLimiter = new TickingRateLimiter(ticker, 1, 100);
assertThat("Filling up", rateLimiter.tryAcquire(), is(true)); assertTrue(rateLimiter.tryAcquire(), "Filling up");
ticker.add(Duration.ofMillis(50)); ticker.add(Duration.ofMillis(50));
// still is full - should fail // still is full - should fail
assertThat("Expired too early", rateLimiter.tryAcquire(), is(false)); assertFalse(rateLimiter.tryAcquire(), "Expired too early");
// wait the remaining time and add a threshold, because // wait the remaining time and add a threshold, because
ticker.add(Duration.ofMillis(50)); ticker.add(Duration.ofMillis(50));
assertThat("Request not released", rateLimiter.tryAcquire(), is(true)); assertTrue(rateLimiter.tryAcquire(), "Request not released");
}
/**
* Blocked attempts shouldn't replace existing ones.
*/
@Test
public void blockedNotAddedNegative() {
FakeTicker ticker = new FakeTicker(-5_000_000L);
// fill the size - 100ms should be reasonable high
TickingRateLimiter rateLimiter = new TickingRateLimiter(ticker, 1, 100);
assertThat("Filling up", rateLimiter.tryAcquire(), is(true));
ticker.add(Duration.ofMillis(50));
// still is full - should fail
assertThat("Expired too early", rateLimiter.tryAcquire(), is(false));
// wait the remaining time and add a threshold, because
ticker.add(Duration.ofMillis(50));
assertThat("Request not released", rateLimiter.tryAcquire(), is(true));
} }
} }

14
pom.xml
View File

@ -152,6 +152,14 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins> </plugins>
<resources> <resources>
@ -176,9 +184,9 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit</artifactId> <artifactId>junit-jupiter</artifactId>
<version>4.13.2</version> <version>5.8.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>