From cd563ed7cd4f62602a53a2f878452f320f52ea33 Mon Sep 17 00:00:00 2001 From: Guillaume Duval Date: Thu, 4 Jul 2024 09:55:15 +0200 Subject: [PATCH] Update ResourceHelpers.java, EmailAggregationRepositoryBasedOnEventTest.java, and EmailAggregatorTest.java --- .../notifications/db/ResourceHelpers.java | 33 +++++++ ...AggregationRepositoryBasedOnEventTest.java | 43 ++------- .../processors/email/EmailAggregatorTest.java | 94 ++++++++++++++----- 3 files changed, 112 insertions(+), 58 deletions(-) diff --git a/engine/src/test/java/com/redhat/cloud/notifications/db/ResourceHelpers.java b/engine/src/test/java/com/redhat/cloud/notifications/db/ResourceHelpers.java index 54bc19ac72..dda9b729e1 100644 --- a/engine/src/test/java/com/redhat/cloud/notifications/db/ResourceHelpers.java +++ b/engine/src/test/java/com/redhat/cloud/notifications/db/ResourceHelpers.java @@ -1,5 +1,6 @@ package com.redhat.cloud.notifications.db; +import com.redhat.cloud.notifications.TestHelpers; import com.redhat.cloud.notifications.db.repositories.EmailAggregationRepository; import com.redhat.cloud.notifications.models.AggregationEmailTemplate; import com.redhat.cloud.notifications.models.Application; @@ -23,10 +24,12 @@ import org.apache.commons.lang3.StringUtils; import java.security.SecureRandom; +import java.time.LocalDateTime; import java.util.UUID; import static com.redhat.cloud.notifications.TestConstants.DEFAULT_ORG_ID; import static com.redhat.cloud.notifications.models.SubscriptionType.DAILY; +import static java.time.ZoneOffset.UTC; @ApplicationScoped public class ResourceHelpers { @@ -284,4 +287,34 @@ public EventTypeEmailSubscription findOrCreateEventTypeEmailSubscription(String } return eventTypeEmailSubscription; } + + public com.redhat.cloud.notifications.models.Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, JsonObject payload) { + return addEventEmailAggregation(orgId, bundleName, applicationName, payload, true); + } + + public com.redhat.cloud.notifications.models.Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, JsonObject payload, boolean addUserSubscription) { + Application application = findOrCreateApplication(bundleName, applicationName); + EventType eventType = findOrCreateEventType(application.getId(), TestHelpers.eventType); + if (addUserSubscription) { + findOrCreateEventTypeEmailSubscription(orgId, "obiwan", eventType, SubscriptionType.DAILY); + } + + com.redhat.cloud.notifications.models.Event event = new com.redhat.cloud.notifications.models.Event(); + event.setId(UUID.randomUUID()); + event.setOrgId(orgId); + eventType.setApplication(application); + event.setEventType(eventType); + event.setPayload(payload.toString()); + event.setCreated(LocalDateTime.now(UTC)); + + Event retevent = createEvent(event); + + return retevent; + } + + @Transactional + public void clearEvents() { + entityManager.createQuery("DELETE FROM Event") + .executeUpdate(); + } } diff --git a/engine/src/test/java/com/redhat/cloud/notifications/db/repositories/EmailAggregationRepositoryBasedOnEventTest.java b/engine/src/test/java/com/redhat/cloud/notifications/db/repositories/EmailAggregationRepositoryBasedOnEventTest.java index bb4bdf1a49..9afaa1625f 100644 --- a/engine/src/test/java/com/redhat/cloud/notifications/db/repositories/EmailAggregationRepositoryBasedOnEventTest.java +++ b/engine/src/test/java/com/redhat/cloud/notifications/db/repositories/EmailAggregationRepositoryBasedOnEventTest.java @@ -5,21 +5,18 @@ import com.redhat.cloud.notifications.models.Application; import com.redhat.cloud.notifications.models.Event; import com.redhat.cloud.notifications.models.EventAggregationCriteria; -import com.redhat.cloud.notifications.models.EventType; -import com.redhat.cloud.notifications.models.SubscriptionType; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.vertx.core.json.JsonObject; import jakarta.inject.Inject; import jakarta.persistence.EntityManager; -import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.List; -import java.util.UUID; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; @QuarkusTest @QuarkusTestResource(TestLifecycleManager.class) @@ -48,12 +45,12 @@ void testAllMethods() { Application application = resourceHelpers.findOrCreateApplication(BUNDLE_NAME, APP_NAME); EventAggregationCriteria key = new EventAggregationCriteria(ORG_ID, application.getBundleId(), application.getId(), BUNDLE_NAME, APP_NAME); - clearEvents(); - addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD1); - addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD2); - addEventEmailAggregation("other-org-id", BUNDLE_NAME, APP_NAME, PAYLOAD2); - addEventEmailAggregation(ORG_ID, "other-bundle", APP_NAME, PAYLOAD2); - addEventEmailAggregation(ORG_ID, BUNDLE_NAME, "other-app", PAYLOAD2); + resourceHelpers.clearEvents(); + resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD1); + resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD2); + resourceHelpers.addEventEmailAggregation("other-org-id", BUNDLE_NAME, APP_NAME, PAYLOAD2); + resourceHelpers.addEventEmailAggregation(ORG_ID, "other-bundle", APP_NAME, PAYLOAD2); + resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, "other-app", PAYLOAD2); List aggregations = emailAggregationRepository.getEmailAggregationBasedOnEvent(key, start, end, 0, 10); assertEquals(2, aggregations.size()); @@ -63,30 +60,8 @@ void testAllMethods() { assertEquals(1, aggregations.stream().map(Event::getPayload).map(payload -> new JsonObject(payload)).filter(PAYLOAD1::equals).count()); assertEquals(1, aggregations.stream().map(Event::getPayload).map(payload -> new JsonObject(payload)).filter(PAYLOAD2::equals).count()); - clearEvents(); + resourceHelpers.clearEvents(); } - @Transactional - void clearEvents() { - entityManager.createQuery("DELETE FROM Event") - .executeUpdate(); - } - - private com.redhat.cloud.notifications.models.Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, JsonObject payload) { - Application application = resourceHelpers.findOrCreateApplication(bundleName, applicationName); - EventType eventType = resourceHelpers.findOrCreateEventType(application.getId(), "event_type_test"); - resourceHelpers.findOrCreateEventTypeEmailSubscription(orgId, "obiwan", eventType, SubscriptionType.DAILY); - - com.redhat.cloud.notifications.models.Event event = new com.redhat.cloud.notifications.models.Event(); - event.setId(UUID.randomUUID()); - event.setOrgId(orgId); - eventType.setApplication(application); - event.setEventType(eventType); - event.setPayload(payload.toString()); - event.setCreated(LocalDateTime.now(UTC)); - Event retevent = resourceHelpers.createEvent(event); - - return retevent; - } } diff --git a/engine/src/test/java/com/redhat/cloud/notifications/processors/email/EmailAggregatorTest.java b/engine/src/test/java/com/redhat/cloud/notifications/processors/email/EmailAggregatorTest.java index bf751cdb8c..d72e18ab0c 100644 --- a/engine/src/test/java/com/redhat/cloud/notifications/processors/email/EmailAggregatorTest.java +++ b/engine/src/test/java/com/redhat/cloud/notifications/processors/email/EmailAggregatorTest.java @@ -9,23 +9,26 @@ import com.redhat.cloud.notifications.models.EmailAggregationKey; import com.redhat.cloud.notifications.models.Endpoint; import com.redhat.cloud.notifications.models.EndpointType; +import com.redhat.cloud.notifications.models.EventAggregationCriteria; import com.redhat.cloud.notifications.models.EventType; import com.redhat.cloud.notifications.models.SystemSubscriptionProperties; import com.redhat.cloud.notifications.recipients.RecipientResolver; import com.redhat.cloud.notifications.recipients.User; import com.redhat.cloud.notifications.recipients.recipientsresolver.RecipientsResolverService; import com.redhat.cloud.notifications.recipients.recipientsresolver.pojo.RecipientsQuery; -import io.quarkus.cache.CacheInvalidate; +import io.quarkus.cache.Cache; +import io.quarkus.cache.CacheManager; import io.quarkus.test.InjectMock; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.mockito.InjectSpy; +import io.vertx.core.json.JsonObject; import jakarta.inject.Inject; import org.apache.commons.lang3.RandomStringUtils; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; import java.time.LocalDateTime; @@ -34,6 +37,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -76,6 +80,9 @@ class EmailAggregatorTest { @InjectMock EndpointRepository endpointRepository; + @Inject + CacheManager cacheManager; + Application application; EventType eventType1; EventType eventType2; @@ -84,22 +91,23 @@ class EmailAggregatorTest { @BeforeEach void beforeEach() { emailAggregator.maxPageSize = 5; - clearCachedData(); + clearCachedData("recipients-resolver-results"); clearInvocations(recipientsResolverService); clearInvocations(recipientResolver); emailAggregationRepository.purgeOldAggregation(aggregationKey, LocalDateTime.now(ZoneOffset.UTC).plusMinutes(1)); + resourceHelpers.clearEvents(); } @AfterEach void afterEach() { resourceHelpers.deleteEventTypeEmailSubscription("org-1", "user-2", eventType2, DAILY); resourceHelpers.deleteEventTypeEmailSubscription("org-1", "user-2", eventType1, DAILY); + resourceHelpers.clearEvents(); } @ParameterizedTest - @ValueSource(booleans = {true, false}) - void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappForDailyDigestEnabled) { - + @CsvSource({"true,true", "true,false", "false,true", "false,false"}) + void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappForDailyDigestEnabled, boolean isAggregationBasedOnEvents) { when(engineConfig.isAggregationWithRecipientsResolverEnabled()).thenReturn(useRecipientsResolverClowdappForDailyDigestEnabled); // init test environment application = resourceHelpers.findApp("rhel", "policies"); @@ -136,9 +144,18 @@ void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappF } // Test user subscription based on event type - Map> result = aggregate(); - verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); - verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); + Map> result = null; + if (isAggregationBasedOnEvents) { + result = aggregateWithEvents(); + verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); + verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); + } else { + result = aggregate(); + verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); + verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); + } + //clearCachedData("recipients-resolver-results"); + verifyRecipientsResolverInteractions(4); // nobody subscribed to the right event type yet @@ -147,10 +164,17 @@ void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappF clearInvocations(emailAggregationRepository); resourceHelpers.createEventTypeEmailSubscription("org-1", "user-2", eventType1, DAILY); // because after the previous aggregate() call the email_aggregation DB table was not purged, we already have 4 records on database - result = aggregate(); - verify(emailAggregationRepository, times(2)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); - verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); - verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(5), eq(emailAggregator.maxPageSize)); + if (isAggregationBasedOnEvents) { + result = aggregateWithEvents(); + verify(emailAggregationRepository, times(2)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); + verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); + verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(5), eq(emailAggregator.maxPageSize)); + } else { + result = aggregate(); + verify(emailAggregationRepository, times(2)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); + verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); + verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(5), eq(emailAggregator.maxPageSize)); + } assertEquals(1, result.size()); User user = result.keySet().stream().findFirst().get(); assertTrue(user.getEmail().equals("user-2")); @@ -158,8 +182,9 @@ void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappF verifyRecipientsResolverInteractions(12); } - @Test - void shouldTestFallbackOnLegacyRecipientsResolverFetching() { + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void shouldTestFallbackOnLegacyRecipientsResolverFetching(boolean isAggregationBasedOnEvents) { when(engineConfig.isAggregationWithRecipientsResolverEnabled()).thenReturn(true); // init test environment @@ -187,9 +212,16 @@ void shouldTestFallbackOnLegacyRecipientsResolverFetching() { }); // Test user subscription based on event type - Map> result = aggregate(); - verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); - verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); + Map> result = null; + if (isAggregationBasedOnEvents) { + result = aggregateWithEvents(); + verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); + verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); + } else { + result = aggregate(); + verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt()); + verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize)); + } verify(recipientsResolverService, times(4)).getRecipients(any()); verify(recipientResolver, times(4)).recipientUsers(anyString(), any(), any()); @@ -219,11 +251,25 @@ private Map> aggregate() { return result; } - @CacheInvalidate(cacheName = "recipients-resolver-results") - void clearCachedData() { - /* - * This would normally happen after a certain duration fixed in application.properties with the - * quarkus.cache.caffeine.recipients-resolver-results.expire-after-write key. - */ + private Map> aggregateWithEvents() { + Map> result = new HashMap<>(); + for (int i = 0; i < 4; i++) { + JsonObject payload = TestHelpers.createEmailAggregation("org-1", "rhel", "policies", RandomStringUtils.random(10), RandomStringUtils.random(10)).getPayload(); + resourceHelpers.addEventEmailAggregation("org-1", "rhel", "policies", payload, false); + } + JsonObject payload = TestHelpers.createEmailAggregation("org-2", "rhel", "policies", RandomStringUtils.random(10), RandomStringUtils.random(10)).getPayload(); + resourceHelpers.addEventEmailAggregation("org-2", "rhel", "policies", payload, false); + + Application policiesApp = resourceHelpers.findApp("rhel", "policies"); + EventAggregationCriteria eventAggregationCriteria = new EventAggregationCriteria(aggregationKey.getOrgId(), policiesApp.getBundleId(), policiesApp.getId(), aggregationKey.getBundle(), aggregationKey.getApplication()); + result.putAll(emailAggregator.getAggregated(application.getId(), eventAggregationCriteria, DAILY, LocalDateTime.now(ZoneOffset.UTC).minusMinutes(1), LocalDateTime.now(ZoneOffset.UTC).plusMinutes(1))); + return result; + } + + public void clearCachedData(String cacheName) { + Optional cache = cacheManager.getCache(cacheName); + if (cache.isPresent()) { + cache.get().invalidateAll().await().indefinitely(); + } } }