From 717613ac072b0cb9b49fff79354b99f26060be72 Mon Sep 17 00:00:00 2001 From: Aurelien Poscia Date: Fri, 4 Nov 2022 13:47:21 +0100 Subject: [PATCH] NO-JIRA replace un-necessary and flaky expired_push_events_are_purged_on_schedule IT by predictable junit --- server/sonar-webserver-pushapi/build.gradle | 1 + .../purge/PushEventsPurgeScheduler.java | 9 +- ...shEventsPurgeSchedulerAndExecutorTest.java | 101 ++++++++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerAndExecutorTest.java diff --git a/server/sonar-webserver-pushapi/build.gradle b/server/sonar-webserver-pushapi/build.gradle index b0625c4564a..c7549d06ba5 100644 --- a/server/sonar-webserver-pushapi/build.gradle +++ b/server/sonar-webserver-pushapi/build.gradle @@ -14,6 +14,7 @@ dependencies { testCompile 'junit:junit' testCompile 'org.assertj:assertj-core' testCompile 'org.mockito:mockito-core' + testCompile 'org.awaitility:awaitility' testCompile testFixtures(project(':server:sonar-webserver-ws')) testCompile testFixtures(project(':server:sonar-db-dao')) diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeScheduler.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeScheduler.java index e1ccf7e1458..0d582e57135 100644 --- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeScheduler.java +++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeScheduler.java @@ -19,6 +19,7 @@ */ package org.sonar.server.pushapi.scheduler.purge; +import com.google.common.annotations.VisibleForTesting; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Set; @@ -38,8 +39,12 @@ import static java.util.concurrent.TimeUnit.SECONDS; public class PushEventsPurgeScheduler implements Startable { private static final Logger LOG = Loggers.get(PushEventsPurgeScheduler.class); private static final String LOCK_NAME = "PushPurgeCheck"; - private static final String INITIAL_DELAY_IN_SECONDS = "sonar.push.events.purge.initial.delay"; - private static final String ENQUEUE_DELAY_IN_SECONDS = "sonar.push.events.purge.enqueue.delay"; + + @VisibleForTesting + static final String INITIAL_DELAY_IN_SECONDS = "sonar.push.events.purge.initial.delay"; + @VisibleForTesting + static final String ENQUEUE_DELAY_IN_SECONDS = "sonar.push.events.purge.enqueue.delay"; + private static final int ENQUEUE_LOCK_DELAY_IN_SECONDS = 60; private final DbClient dbClient; diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerAndExecutorTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerAndExecutorTest.java new file mode 100644 index 00000000000..28daef4e7b9 --- /dev/null +++ b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/scheduler/purge/PushEventsPurgeSchedulerAndExecutorTest.java @@ -0,0 +1,101 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.pushapi.scheduler.purge; + +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.config.Configuration; +import org.sonar.api.utils.System2; +import org.sonar.db.DbClient; +import org.sonar.db.DbTester; +import org.sonar.db.pushevent.PushEventDto; +import org.sonar.server.util.GlobalLockManagerImpl; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.server.pushapi.scheduler.purge.PushEventsPurgeScheduler.ENQUEUE_DELAY_IN_SECONDS; +import static org.sonar.server.pushapi.scheduler.purge.PushEventsPurgeScheduler.INITIAL_DELAY_IN_SECONDS; + +public class PushEventsPurgeSchedulerAndExecutorTest { + + private static final String PUSH_EVENT_UUID = "push_event_uuid"; + private static final long INITIAL_AND_ENQUE_DELAY_MS = 1L; + + @Rule + public DbTester dbTester = DbTester.create(System2.INSTANCE); + + private PushEventsPurgeScheduler pushEventsPurgeScheduler; + + @Before + public void setup() { + Configuration configuration = mock(Configuration.class); + when(configuration.getLong(INITIAL_DELAY_IN_SECONDS)).thenReturn(Optional.of(INITIAL_AND_ENQUE_DELAY_MS)); + when(configuration.getLong(ENQUEUE_DELAY_IN_SECONDS)).thenReturn(Optional.of(INITIAL_AND_ENQUE_DELAY_MS)); + + GlobalLockManagerImpl lockManager = mock(GlobalLockManagerImpl.class); + when(lockManager.tryLock(any(), anyInt())).thenReturn(true); + + DbClient dbClient = dbTester.getDbClient(); + pushEventsPurgeScheduler = new PushEventsPurgeScheduler( + dbClient, + configuration, + lockManager, + new PushEventsPurgeExecutorServiceImpl(), + System2.INSTANCE + ); + } + + @Test + public void pushEventsPurgeScheduler_shouldCleanUpPeriodically() throws InterruptedException { + insertOldPushEvent(); + assertThat(pushEventIsCleanedUp()).isFalse(); + + pushEventsPurgeScheduler.start(); + + await() + .atMost(3, TimeUnit.SECONDS) + .pollDelay(500, TimeUnit.MILLISECONDS) + .until(this::pushEventIsCleanedUp); + } + + private void insertOldPushEvent() { + PushEventDto pushEventDto = new PushEventDto(); + pushEventDto.setUuid(PUSH_EVENT_UUID); + pushEventDto.setName("test_event"); + pushEventDto.setProjectUuid("test_project_uuid"); + pushEventDto.setPayload("payload".getBytes(StandardCharsets.UTF_8)); + pushEventDto.setCreatedAt(1656633600); + dbTester.getDbClient().pushEventDao().insert(dbTester.getSession(), pushEventDto); + dbTester.commit(); + } + + private boolean pushEventIsCleanedUp() { + return dbTester.getDbClient().pushEventDao().selectByUuid(dbTester.getSession(), PUSH_EVENT_UUID) == null; + } + +} -- 2.39.5