diff --git a/test-suite-caffeine-native/build.gradle b/test-suite-caffeine-native/build.gradle index 203ce420f..650b58647 100644 --- a/test-suite-caffeine-native/build.gradle +++ b/test-suite-caffeine-native/build.gradle @@ -14,7 +14,9 @@ repositories { dependencies { testAnnotationProcessor(mn.micronaut.inject.java) - testImplementation projects.micronautCacheCaffeine + testAnnotationProcessor(mnSerde.micronaut.serde.processor) + testImplementation(mnSerde.micronaut.serde.api) + testImplementation(projects.micronautCacheCaffeine) testImplementation(mn.micronaut.http.server.netty) testImplementation(mn.micronaut.http.client) testImplementation(mnTest.micronaut.test.junit5) diff --git a/test-suite-caffeine-native/src/test/java/io/micronaut/cache/News.java b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/News.java new file mode 100644 index 000000000..2ebe01a94 --- /dev/null +++ b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/News.java @@ -0,0 +1,37 @@ +package io.micronaut.cache; + +import io.micronaut.serde.annotation.Serdeable; + +import java.time.Month; +import java.util.List; + +@Serdeable +public class News { + private Month month; + + private List headlines; + + public News() { + } + + public News(Month month, List headlines) { + this.month = month; + this.headlines = headlines; + } + + public Month getMonth() { + return month; + } + + public void setMonth(Month month) { + this.month = month; + } + + public List getHeadlines() { + return headlines; + } + + public void setHeadlines(List headlines) { + this.headlines = headlines; + } +} diff --git a/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsController.java b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsController.java new file mode 100644 index 000000000..c9bf0edba --- /dev/null +++ b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsController.java @@ -0,0 +1,21 @@ +package io.micronaut.cache; + +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; + +import java.time.Month; + +@Controller +public class NewsController { + + private final NewsService newsService; + + public NewsController(NewsService newsService) { + this.newsService = newsService; + } + + @Get("/{month}") + public News index(Month month) { + return new News(month, newsService.headlines(month)); + } +} diff --git a/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsControllerTest.java b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsControllerTest.java new file mode 100644 index 000000000..15364740c --- /dev/null +++ b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsControllerTest.java @@ -0,0 +1,36 @@ +package io.micronaut.cache; + +import io.micronaut.http.HttpRequest; +import io.micronaut.http.client.HttpClient; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.http.uri.UriBuilder; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import java.time.Month; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@MicronautTest +class NewsControllerTest { + + @Inject + @Client("/") + HttpClient client; + + @Timeout(4) + @Test + void fetchingOctoberHeadlinesUsesCache() { + HttpRequest request = HttpRequest.GET(UriBuilder.of("/").path(Month.OCTOBER.toString()).build()); + + News news = client.toBlocking().retrieve(request, News.class); + String expected = "Micronaut AOP: Awesome flexibility without the complexity"; + assertEquals(List.of(expected), news.getHeadlines()); + + news = client.toBlocking().retrieve(request, News.class); + assertEquals(List.of(expected), news.getHeadlines()); + } +} diff --git a/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsService.java b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsService.java new file mode 100644 index 000000000..0b6514afa --- /dev/null +++ b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsService.java @@ -0,0 +1,58 @@ +package io.micronaut.cache; + +import io.micronaut.cache.annotation.CacheInvalidate; +import io.micronaut.cache.annotation.CachePut; +import io.micronaut.cache.annotation.Cacheable; +import jakarta.inject.Singleton; + +import java.time.Month; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@Singleton +public class NewsService { + + Map> headlines = new HashMap<>(Map.of( + Month.NOVEMBER, List.of( + "Micronaut Graduates to Trial Level in Thoughtworks technology radar Vol.1", + "Micronaut AOP: Awesome flexibility without the complexity" + ), + Month.OCTOBER, Collections.singletonList("Micronaut AOP: Awesome flexibility without the complexity") + )); + + @SuppressWarnings("java:S2925") // Sleep is used for testing purposes only + @Cacheable(value = "headlines", parameters = {"month"}) + public List headlines(Month month) { + try { + TimeUnit.SECONDS.sleep(3); + return headlines.get(month); + } catch (InterruptedException e) { + return null; + } + } + + @CachePut(value = "headlines", parameters = {"month"}) + public List addHeadline(Month month, String headline) { + if (headlines.containsKey(month)) { + List l = new ArrayList<>(headlines.get(month)); + l.add(headline); + headlines.put(month, l); + } else { + headlines.put(month, Collections.singletonList(headline)); + } + return headlines.get(month); + } + + @CacheInvalidate(value = "headlines", parameters = {"month"}) + public void removeHeadline(Month month, String headline) { + if (headlines.containsKey(month)) { + List l = new ArrayList<>(headlines.get(month)); + l.remove(headline); + headlines.put(month, l); + } + } +} diff --git a/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsServiceTest.java b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsServiceTest.java new file mode 100644 index 000000000..ab82654a3 --- /dev/null +++ b/test-suite-caffeine-native/src/test/java/io/micronaut/cache/NewsServiceTest.java @@ -0,0 +1,97 @@ +package io.micronaut.cache; + +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.Timeout; + +import java.time.Month; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@MicronautTest +@SuppressWarnings("java:S5976") // Sonar thinks these can be parameterized +class NewsServiceTest { + + @Inject + NewsService newsService; + + @Timeout(4) + @Test + @Order(1) + void firstInvocationOfNovemberDoesNotHitCache() { + List headlines = newsService.headlines(Month.NOVEMBER); + assertEquals(2, headlines.size()); + } + + @Timeout(1) + @Test + @Order(2) + void secondInvocationOfNovemberHitsCache() { + List headlines = newsService.headlines(Month.NOVEMBER); + assertEquals(2, headlines.size()); + } + + @Timeout(4) + @Test + @Order(3) + void firstInvocationOfOctoberDoesNotHitCache() { + List headlines = newsService.headlines(Month.OCTOBER); + assertEquals(1, headlines.size()); + } + + @Timeout(1) + @Test + @Order(4) + void secondInvocationOfOctoberHitsCache() { + List headlines = newsService.headlines(Month.OCTOBER); + assertEquals(1, headlines.size()); + } + + @Timeout(1) + @Test + @Order(5) + void addingAHeadlineToNovemberUpdatesCache() { + List headlines = newsService.addHeadline(Month.NOVEMBER, "Micronaut 1.3 Milestone 1 Released"); + assertEquals(3, headlines.size()); + } + + @Timeout(1) + @Test + @Order(6) + void novemberCacheWasUpdatedByCachePutAndThusTheValueIsRetrievedFromTheCache() { + List headlines = newsService.headlines(Month.NOVEMBER); + assertEquals(3, headlines.size()); + } + + @Timeout(1) + @Test + @Order(7) + void invalidateNovemberCacheWithCacheInvalidate() { + assertDoesNotThrow(() -> { + newsService.removeHeadline(Month.NOVEMBER, "Micronaut 1.3 Milestone 1 Released"); + }); + } + + @Timeout(1) + @Test + @Order(8) + void octoberCacheIsStillValid() { + List headlines = newsService.headlines(Month.OCTOBER); + assertEquals(1, headlines.size()); + } + + @Timeout(4) + @Test + @Order(9) + void novemberCacheWasInvalidated() { + List headlines = newsService.headlines(Month.NOVEMBER); + assertEquals(2, headlines.size()); + } +}