-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tests for redis cache and coverage for quarkusio/quarkus#35680
Most of the tests are reused from caffeine module anshould cover similar scenarios as spring che and caffeine cache.
- Loading branch information
Showing
12 changed files
with
379 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>io.quarkus.ts.qe</groupId> | ||
<artifactId>parent</artifactId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
<relativePath>../..</relativePath> | ||
</parent> | ||
<artifactId>cache-redis</artifactId> | ||
<packaging>jar</packaging> | ||
<name>Quarkus QE TS: Cache: Redis</name> | ||
<dependencies> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-cache</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-redis-cache</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-resteasy-reactive</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-qute</artifactId> | ||
</dependency> | ||
<!--> Added dependency to check https://github.com/quarkusio/quarkus/issues/35680 <--> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-mailer</artifactId> | ||
</dependency> | ||
</dependencies> | ||
</project> |
7 changes: 7 additions & 0 deletions
7
cache/redis/src/main/java/io/quarkus/ts/cache/redis/ApplicationScopeService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package io.quarkus.ts.cache.caffeine; | ||
|
||
import jakarta.enterprise.context.ApplicationScoped; | ||
|
||
@ApplicationScoped | ||
public class ApplicationScopeService extends BaseServiceWithCache { | ||
} |
38 changes: 38 additions & 0 deletions
38
cache/redis/src/main/java/io/quarkus/ts/cache/redis/BaseServiceWithCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package io.quarkus.ts.cache.caffeine; | ||
|
||
import io.quarkus.cache.CacheInvalidate; | ||
import io.quarkus.cache.CacheInvalidateAll; | ||
import io.quarkus.cache.CacheKey; | ||
import io.quarkus.cache.CacheResult; | ||
|
||
public abstract class BaseServiceWithCache { | ||
|
||
private static final String CACHE_NAME = "service-cache"; | ||
|
||
private static int counter = 0; | ||
|
||
@CacheResult(cacheName = CACHE_NAME) | ||
public String getValue() { | ||
return "Value: " + counter++; | ||
} | ||
|
||
@CacheInvalidate(cacheName = CACHE_NAME) | ||
public void invalidate() { | ||
// do nothing | ||
} | ||
|
||
@CacheResult(cacheName = CACHE_NAME) | ||
public String getValueWithPrefix(@CacheKey String prefix) { | ||
return prefix + ": " + counter++; | ||
} | ||
|
||
@CacheInvalidate(cacheName = CACHE_NAME) | ||
public void invalidateWithPrefix(@CacheKey String prefix) { | ||
// do nothing | ||
} | ||
|
||
@CacheInvalidateAll(cacheName = CACHE_NAME) | ||
public void invalidateAll() { | ||
// do nothing | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
cache/redis/src/main/java/io/quarkus/ts/cache/redis/RequestScopeService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package io.quarkus.ts.cache.caffeine; | ||
|
||
import jakarta.enterprise.context.RequestScoped; | ||
|
||
@RequestScoped | ||
public class RequestScopeService extends BaseServiceWithCache { | ||
} |
65 changes: 65 additions & 0 deletions
65
cache/redis/src/main/java/io/quarkus/ts/cache/redis/ServiceWithCacheResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package io.quarkus.ts.cache.caffeine; | ||
|
||
import jakarta.inject.Inject; | ||
import jakarta.ws.rs.GET; | ||
import jakarta.ws.rs.POST; | ||
import jakarta.ws.rs.Path; | ||
import jakarta.ws.rs.PathParam; | ||
import jakarta.ws.rs.Produces; | ||
import jakarta.ws.rs.core.MediaType; | ||
|
||
@Path("/services") | ||
public class ServiceWithCacheResource { | ||
|
||
public static final String APPLICATION_SCOPE_SERVICE_PATH = "application-scope"; | ||
public static final String REQUEST_SCOPE_SERVICE_PATH = "request-scope"; | ||
|
||
@Inject | ||
ApplicationScopeService applicationScopeService; | ||
|
||
@Inject | ||
RequestScopeService requestScopeService; | ||
|
||
@GET | ||
@Path("/{service}") | ||
@Produces(MediaType.TEXT_PLAIN) | ||
public String getValueFromService(@PathParam("service") String service) { | ||
return lookupServiceByPathParam(service).getValue(); | ||
} | ||
|
||
@POST | ||
@Path("/{service}/invalidate-cache") | ||
public void invalidateCacheFromService(@PathParam("service") String service) { | ||
lookupServiceByPathParam(service).invalidate(); | ||
} | ||
|
||
@POST | ||
@Path("/{service}/invalidate-cache-all") | ||
public void invalidateCacheAllFromService(@PathParam("service") String service) { | ||
lookupServiceByPathParam(service).invalidateAll(); | ||
} | ||
|
||
@GET | ||
@Path("/{service}/using-prefix/{prefix}") | ||
@Produces(MediaType.TEXT_PLAIN) | ||
public String getValueUsingPrefixFromService(@PathParam("service") String service, @PathParam("prefix") String prefix) { | ||
return lookupServiceByPathParam(service).getValueWithPrefix(prefix); | ||
} | ||
|
||
@POST | ||
@Path("/{service}/using-prefix/{prefix}/invalidate-cache") | ||
public void invalidateCacheUsingPrefixFromService(@PathParam("service") String service, | ||
@PathParam("prefix") String prefix) { | ||
lookupServiceByPathParam(service).invalidateWithPrefix(prefix); | ||
} | ||
|
||
private BaseServiceWithCache lookupServiceByPathParam(String service) { | ||
if (APPLICATION_SCOPE_SERVICE_PATH.equals(service)) { | ||
return applicationScopeService; | ||
} else if (REQUEST_SCOPE_SERVICE_PATH.equals(service)) { | ||
return requestScopeService; | ||
} | ||
|
||
throw new IllegalArgumentException("Service " + service + " is not recognised"); | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
cache/redis/src/main/java/io/quarkus/ts/cache/redis/TemplateCacheResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package io.quarkus.ts.cache.caffeine; | ||
|
||
import jakarta.inject.Inject; | ||
import jakarta.ws.rs.GET; | ||
import jakarta.ws.rs.Path; | ||
|
||
import io.quarkus.qute.Template; | ||
|
||
@Path("template") | ||
public class TemplateCacheResource { | ||
|
||
@Inject | ||
Template cached; | ||
|
||
/** | ||
* Check for remote cache with Qute template. Qute should not use remote cache. | ||
* See https://github.com/quarkusio/quarkus/issues/35680#issuecomment-1711153725 | ||
* | ||
* @return Should return error contains `not supported for remote caches` | ||
*/ | ||
@GET | ||
@Path("error") | ||
public String getQuteTemplate() { | ||
try { | ||
return cached.render(); | ||
} catch (IllegalStateException e) { | ||
return e.getMessage(); | ||
} | ||
} | ||
|
||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{#cached}This cached template won't be working with remote cache like redis.{/cached} |
7 changes: 7 additions & 0 deletions
7
cache/redis/src/test/java/io/quarkus/ts/cache/redis/OpenShiftRedisCacheIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package io.quarkus.ts.cache.redis; | ||
|
||
import io.quarkus.test.scenarios.OpenShiftScenario; | ||
|
||
@OpenShiftScenario | ||
public class OpenShiftRedisCacheIT extends RedisCacheIT { | ||
} |
185 changes: 185 additions & 0 deletions
185
cache/redis/src/test/java/io/quarkus/ts/cache/redis/RedisCacheIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
package io.quarkus.ts.cache.redis; | ||
|
||
import static io.quarkus.ts.cache.caffeine.ServiceWithCacheResource.APPLICATION_SCOPE_SERVICE_PATH; | ||
import static io.quarkus.ts.cache.caffeine.ServiceWithCacheResource.REQUEST_SCOPE_SERVICE_PATH; | ||
import static org.hamcrest.CoreMatchers.containsString; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertNotEquals; | ||
|
||
import org.apache.http.HttpStatus; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
import io.quarkus.test.bootstrap.DefaultService; | ||
import io.quarkus.test.bootstrap.RestService; | ||
import io.quarkus.test.scenarios.QuarkusScenario; | ||
import io.quarkus.test.services.Container; | ||
import io.quarkus.test.services.QuarkusApplication; | ||
|
||
@QuarkusScenario | ||
public class RedisCacheIT { | ||
|
||
private static final String SERVICE_APPLICATION_SCOPE_PATH = "/services/" + APPLICATION_SCOPE_SERVICE_PATH; | ||
private static final String SERVICE_REQUEST_SCOPE_PATH = "/services/" + REQUEST_SCOPE_SERVICE_PATH; | ||
|
||
private static final String PREFIX_ONE = "prefix1"; | ||
private static final String PREFIX_TWO = "prefix2"; | ||
|
||
private static final int REDIS_PORT = 6379; | ||
|
||
@Container(image = "${redis.image}", port = REDIS_PORT, expectedLog = "Ready to accept connections") | ||
static DefaultService redis = new DefaultService().withProperty("ALLOW_EMPTY_PASSWORD", "YES"); | ||
|
||
@QuarkusApplication | ||
static RestService app = new RestService() | ||
.withProperty("quarkus.redis.hosts", | ||
() -> { | ||
String redisHost = redis.getURI().withScheme("redis").getRestAssuredStyleUri(); | ||
return String.format("%s:%d", redisHost, redis.getURI().getPort()); | ||
}); | ||
|
||
/** | ||
* Check whether the `@CacheResult` annotation works when used in a service. | ||
*/ | ||
@ParameterizedTest | ||
@ValueSource(strings = { SERVICE_APPLICATION_SCOPE_PATH, SERVICE_REQUEST_SCOPE_PATH }) | ||
public void shouldGetTheSameValueAlwaysWhenGettingValueFromPath(String path) { | ||
// We call the service endpoint | ||
String value = getFromPath(path); | ||
|
||
// At this point, the cache is populated and we should get the same value from the cache | ||
assertEquals(value, getFromPath(path), "Value was different which means cache is not working"); | ||
} | ||
|
||
/** | ||
* Check whether the `@CacheInvalidate` annotation invalidates the cache when used in a service. | ||
*/ | ||
@ParameterizedTest | ||
@ValueSource(strings = { SERVICE_APPLICATION_SCOPE_PATH, SERVICE_REQUEST_SCOPE_PATH }) | ||
public void shouldGetDifferentValueWhenInvalidateCacheFromPath(String path) { | ||
// We call the service endpoint | ||
String value = getFromPath(path); | ||
|
||
// invalidate the cache | ||
invalidateCacheFromPath(path); | ||
|
||
// Then the value should be different as we have invalidated the cache. | ||
assertNotEquals(value, getFromPath(path), "Value was equal which means cache invalidate didn't work"); | ||
} | ||
|
||
/** | ||
* Check whether the `@CacheResult` annotation works when used in a service. | ||
*/ | ||
@ParameterizedTest | ||
@ValueSource(strings = { SERVICE_APPLICATION_SCOPE_PATH, SERVICE_REQUEST_SCOPE_PATH }) | ||
public void shouldGetTheSameValueForSamePrefixesWhenGettingValueFromPath(String path) { | ||
// We call the service endpoint | ||
String value = getValueFromPathUsingPrefix(path, PREFIX_ONE); | ||
|
||
// At this point, the cache is populated and we should get the same value from the cache | ||
assertEquals(value, getValueFromPathUsingPrefix(path, PREFIX_ONE), | ||
"Value was different which means cache is not working"); | ||
// But different value using another prefix | ||
assertNotEquals(value, getValueFromPathUsingPrefix(path, PREFIX_TWO), | ||
"Value was equal which means @CacheKey didn't work"); | ||
} | ||
|
||
/** | ||
* Check whether the `@CacheInvalidate` annotation does not invalidate all the caches | ||
*/ | ||
@ParameterizedTest | ||
@ValueSource(strings = { SERVICE_APPLICATION_SCOPE_PATH, SERVICE_REQUEST_SCOPE_PATH }) | ||
public void shouldGetTheSameValuesEvenAfterCallingToCacheInvalidateFromPath(String path) { | ||
// We call the service endpoints | ||
String valueOfPrefix1 = getValueFromPathUsingPrefix(path, PREFIX_ONE); | ||
String valueOfPrefix2 = getValueFromPathUsingPrefix(path, PREFIX_TWO); | ||
|
||
// invalidate the cache: this should not invalidate all the keys | ||
invalidateCacheFromPath(path); | ||
|
||
// At this point, the cache is populated and we should get the same value for both prefixes | ||
assertEquals(valueOfPrefix1, getValueFromPathUsingPrefix(path, PREFIX_ONE)); | ||
assertEquals(valueOfPrefix2, getValueFromPathUsingPrefix(path, PREFIX_TWO)); | ||
} | ||
|
||
/** | ||
* Check whether the `@CacheInvalidate` and `@CacheKey` annotations work as expected. | ||
*/ | ||
@ParameterizedTest | ||
@ValueSource(strings = { SERVICE_APPLICATION_SCOPE_PATH, SERVICE_REQUEST_SCOPE_PATH }) | ||
public void shouldGetDifferentValueWhenInvalidateCacheOnlyForOnePrefixFromPath(String path) { | ||
// We call the service endpoints | ||
String valueOfPrefix1 = getValueFromPathUsingPrefix(path, PREFIX_ONE); | ||
String valueOfPrefix2 = getValueFromPathUsingPrefix(path, PREFIX_TWO); | ||
|
||
// invalidate the cache: this should not invalidate all the keys | ||
invalidateCacheWithPrefixFromPath(path, PREFIX_ONE); | ||
|
||
// The cache was invalidated only for prefix1, so the value should be different | ||
assertNotEquals(valueOfPrefix1, getValueFromPathUsingPrefix(path, PREFIX_ONE)); | ||
// The cache was not invalidated for prefix2, so the value should be the same | ||
assertEquals(valueOfPrefix2, getValueFromPathUsingPrefix(path, PREFIX_TWO)); | ||
} | ||
|
||
/** | ||
* Check whether the `@CacheInvalidateAll` annotation works as expected. | ||
*/ | ||
@ParameterizedTest | ||
@ValueSource(strings = { SERVICE_APPLICATION_SCOPE_PATH, SERVICE_REQUEST_SCOPE_PATH }) | ||
public void shouldGetDifferentValueWhenInvalidateAllTheCacheFromPath(String path) { | ||
// We call the service endpoints | ||
String value = getFromPath(path); | ||
String valueOfPrefix1 = getValueFromPathUsingPrefix(path, PREFIX_ONE); | ||
String valueOfPrefix2 = getValueFromPathUsingPrefix(path, PREFIX_TWO); | ||
|
||
// invalidate all the cache | ||
invalidateCacheAllFromPath(path); | ||
|
||
// Then, all the values should be different: | ||
assertNotEquals(value, getFromPath(path)); | ||
assertNotEquals(valueOfPrefix1, getValueFromPathUsingPrefix(path, PREFIX_ONE)); | ||
assertNotEquals(valueOfPrefix2, getValueFromPathUsingPrefix(path, PREFIX_TWO)); | ||
} | ||
|
||
/** | ||
* Check if the usage of Qute and redis throw expected error | ||
*/ | ||
@Test | ||
public void quteShouldThrowError() { | ||
assertThat(getFromPath("/template/error"), containsString("not supported for remote caches")); | ||
} | ||
|
||
private void invalidateCacheAllFromPath(String path) { | ||
postFromPath(path + "/invalidate-cache-all"); | ||
} | ||
|
||
private void invalidateCacheWithPrefixFromPath(String path, String prefix) { | ||
postFromPath(path + "/using-prefix/" + prefix + "/invalidate-cache"); | ||
} | ||
|
||
private void invalidateCacheFromPath(String path) { | ||
postFromPath(path + "/invalidate-cache"); | ||
} | ||
|
||
private String getValueFromPathUsingPrefix(String path, String prefix) { | ||
return getFromPath(path + "/using-prefix/" + prefix); | ||
} | ||
|
||
private String getFromPath(String path) { | ||
return app.given() | ||
.when().get(path) | ||
.then() | ||
.statusCode(HttpStatus.SC_OK) | ||
.extract().asString(); | ||
} | ||
|
||
private void postFromPath(String path) { | ||
app.given() | ||
.when().post(path) | ||
.then() | ||
.statusCode(HttpStatus.SC_NO_CONTENT); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ts.redis.openshift.use-internal-service-as-url=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters