/* * SonarQube * Copyright (C) 2009-2017 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.db.ce; import com.google.common.base.Function; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.stream.Stream; import javax.annotation.Nullable; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; import org.sonar.api.utils.System2; import org.sonar.api.utils.internal.AlwaysIncreasingSystem2; import org.sonar.api.utils.internal.TestSystem2; import org.sonar.db.DbTester; import static com.google.common.collect.FluentIterable.from; import static com.google.common.collect.Lists.newArrayList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.sonar.db.ce.CeQueueDto.Status.IN_PROGRESS; import static org.sonar.db.ce.CeQueueDto.Status.PENDING; import static org.sonar.db.ce.CeQueueTesting.newCeQueueDto; public class CeQueueDaoTest { private static final long INIT_TIME = 1_450_000_000_000L; private static final String TASK_UUID_1 = "TASK_1"; private static final String TASK_UUID_2 = "TASK_2"; private static final String COMPONENT_UUID_1 = "PROJECT_1"; private static final String COMPONENT_UUID_2 = "PROJECT_2"; private static final String TASK_UUID_3 = "TASK_3"; private static final String SELECT_QUEUE_UUID_AND_STATUS_QUERY = "select uuid,status from ce_queue"; private static final String SUBMITTER_LOGIN = "henri"; private static final String WORKER_UUID_1 = "worker uuid 1"; private static final String WORKER_UUID_2 = "worker uuid 2"; private static final int EXECUTION_COUNT = 42; private static final int MAX_EXECUTION_COUNT = 2; private TestSystem2 system2 = new TestSystem2().setNow(INIT_TIME); @Rule public DbTester db = DbTester.create(system2); private System2 mockedSystem2 = mock(System2.class); private CeQueueDao underTest = new CeQueueDao(system2); private CeQueueDao underTestWithSystem2Mock = new CeQueueDao(mockedSystem2); private CeQueueDao underTestAlwaysIncreasingSystem2 = new CeQueueDao(new AlwaysIncreasingSystem2()); @Test public void insert_populates_createdAt_and_updateAt_from_System2_with_same_value_if_any_is_not_set() { long now = 1_334_333L; CeQueueDto dto = new CeQueueDto() .setTaskType(CeTaskTypes.REPORT) .setComponentUuid(COMPONENT_UUID_1) .setStatus(PENDING) .setSubmitterLogin(SUBMITTER_LOGIN) .setWorkerUuid(WORKER_UUID_1) .setExecutionCount(EXECUTION_COUNT); mockSystem2ForSingleCall(now); underTestWithSystem2Mock.insert(db.getSession(), dto.setUuid(TASK_UUID_1)); mockSystem2ForSingleCall(now); underTestWithSystem2Mock.insert(db.getSession(), dto.setUuid(TASK_UUID_2).setCreatedAt(8_000_999L).setUpdatedAt(0)); mockSystem2ForSingleCall(now); underTestWithSystem2Mock.insert(db.getSession(), dto.setUuid(TASK_UUID_3).setCreatedAt(0).setUpdatedAt(8_000_999L)); mockSystem2ForSingleCall(now); String uuid4 = "uuid 4"; underTestWithSystem2Mock.insert(db.getSession(), dto.setUuid(uuid4).setCreatedAt(6_888_777L).setUpdatedAt(8_000_999L)); db.getSession().commit(); Stream.of(TASK_UUID_1, TASK_UUID_2, TASK_UUID_3) .forEach(uuid -> { CeQueueDto saved = underTest.selectByUuid(db.getSession(), uuid).get(); assertThat(saved.getUuid()).isEqualTo(uuid); assertThat(saved.getTaskType()).isEqualTo(CeTaskTypes.REPORT); assertThat(saved.getComponentUuid()).isEqualTo(COMPONENT_UUID_1); assertThat(saved.getStatus()).isEqualTo(PENDING); assertThat(saved.getSubmitterLogin()).isEqualTo(SUBMITTER_LOGIN); assertThat(saved.getWorkerUuid()).isEqualTo(WORKER_UUID_1); assertThat(saved.getExecutionCount()).isEqualTo(EXECUTION_COUNT); assertThat(saved.getCreatedAt()).isEqualTo(now); assertThat(saved.getUpdatedAt()).isEqualTo(now); assertThat(saved.getStartedAt()).isNull(); }); CeQueueDto saved = underTest.selectByUuid(db.getSession(), uuid4).get(); assertThat(saved.getUuid()).isEqualTo(uuid4); assertThat(saved.getTaskType()).isEqualTo(CeTaskTypes.REPORT); assertThat(saved.getComponentUuid()).isEqualTo(COMPONENT_UUID_1); assertThat(saved.getStatus()).isEqualTo(PENDING); assertThat(saved.getSubmitterLogin()).isEqualTo(SUBMITTER_LOGIN); assertThat(saved.getWorkerUuid()).isEqualTo(WORKER_UUID_1); assertThat(saved.getExecutionCount()).isEqualTo(EXECUTION_COUNT); assertThat(saved.getCreatedAt()).isEqualTo(6_888_777L); assertThat(saved.getUpdatedAt()).isEqualTo(8_000_999L); assertThat(saved.getStartedAt()).isNull(); } @Test public void test_selectByUuid() { insert(TASK_UUID_1, COMPONENT_UUID_1, PENDING); assertThat(underTest.selectByUuid(db.getSession(), "TASK_UNKNOWN").isPresent()).isFalse(); CeQueueDto saved = underTest.selectByUuid(db.getSession(), TASK_UUID_1).get(); assertThat(saved.getUuid()).isEqualTo(TASK_UUID_1); assertThat(saved.getTaskType()).isEqualTo(CeTaskTypes.REPORT); assertThat(saved.getComponentUuid()).isEqualTo(COMPONENT_UUID_1); assertThat(saved.getStatus()).isEqualTo(PENDING); assertThat(saved.getSubmitterLogin()).isEqualTo("henri"); assertThat(saved.getWorkerUuid()).isNull(); assertThat(saved.getExecutionCount()).isEqualTo(0); assertThat(saved.getCreatedAt()).isEqualTo(INIT_TIME); assertThat(saved.getUpdatedAt()).isEqualTo(INIT_TIME); assertThat(saved.getStartedAt()).isNull(); } @Test public void test_selectByComponentUuid() { insert(TASK_UUID_1, COMPONENT_UUID_1, PENDING); insert(TASK_UUID_2, COMPONENT_UUID_1, PENDING); insert(TASK_UUID_3, "PROJECT_2", PENDING); assertThat(underTest.selectByComponentUuid(db.getSession(), "UNKNOWN")).isEmpty(); assertThat(underTest.selectByComponentUuid(db.getSession(), COMPONENT_UUID_1)).extracting("uuid").containsOnly(TASK_UUID_1, TASK_UUID_2); assertThat(underTest.selectByComponentUuid(db.getSession(), "PROJECT_2")).extracting("uuid").containsOnly(TASK_UUID_3); } @Test public void test_selectAllInAscOrder() { insert(TASK_UUID_1, COMPONENT_UUID_1, PENDING); insert(TASK_UUID_2, COMPONENT_UUID_1, PENDING); insert(TASK_UUID_3, "PROJECT_2", PENDING); assertThat(underTest.selectAllInAscOrder(db.getSession())).extracting("uuid").containsOnly(TASK_UUID_1, TASK_UUID_2, TASK_UUID_3); } @Test public void selectPendingByMinimumExecutionCount_returns_pending_tasks_with_executionCount_greater_or_equal_to_argument() { insert("p1", CeQueueDto.Status.PENDING, 0); insert("p2", CeQueueDto.Status.PENDING, 1); insert("p3", CeQueueDto.Status.PENDING, 2); insert("i1", CeQueueDto.Status.IN_PROGRESS, 0); insert("i2", CeQueueDto.Status.IN_PROGRESS, 1); insert("i3", CeQueueDto.Status.IN_PROGRESS, 2); assertThat(underTest.selectPendingByMinimumExecutionCount(db.getSession(), 0)) .extracting(CeQueueDto::getUuid) .containsOnly("p1", "p2", "p3"); assertThat(underTest.selectPendingByMinimumExecutionCount(db.getSession(), 1)) .extracting(CeQueueDto::getUuid) .containsOnly("p2", "p3"); assertThat(underTest.selectPendingByMinimumExecutionCount(db.getSession(), 2)) .extracting(CeQueueDto::getUuid) .containsOnly("p3"); assertThat(underTest.selectPendingByMinimumExecutionCount(db.getSession(), 3)) .isEmpty(); assertThat(underTest.selectPendingByMinimumExecutionCount(db.getSession(), 3 + Math.abs(new Random().nextInt(20)))) .isEmpty(); } @Test public void selectPendingByMinimumExecutionCount_does_not_return_non_pending_tasks() { } @Test public void test_delete() { insert(TASK_UUID_1, COMPONENT_UUID_1, PENDING); underTest.deleteByUuid(db.getSession(), "UNKNOWN"); assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1)).isPresent(); underTest.deleteByUuid(db.getSession(), TASK_UUID_1); assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1).isPresent()).isFalse(); } @Test public void test_resetAllToPendingStatus() throws Exception { insert(TASK_UUID_1, COMPONENT_UUID_1, PENDING); insert(TASK_UUID_2, COMPONENT_UUID_1, IN_PROGRESS); insert(TASK_UUID_3, COMPONENT_UUID_1, IN_PROGRESS); verifyCeQueueStatuses(TASK_UUID_1, PENDING, TASK_UUID_2, IN_PROGRESS, TASK_UUID_3, IN_PROGRESS); underTest.resetAllToPendingStatus(db.getSession()); db.getSession().commit(); verifyCeQueueStatuses(TASK_UUID_1, PENDING, TASK_UUID_2, PENDING, TASK_UUID_3, PENDING); } @Test public void resetAllToPendingStatus_updates_updatedAt() { long now = 1_334_333L; insert(TASK_UUID_1, COMPONENT_UUID_1, IN_PROGRESS); insert(TASK_UUID_2, COMPONENT_UUID_1, IN_PROGRESS); mockSystem2ForSingleCall(now); underTestWithSystem2Mock.resetAllToPendingStatus(db.getSession()); assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1).get().getUpdatedAt()).isEqualTo(now); assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_2).get().getUpdatedAt()).isEqualTo(now); } @Test public void resetAllToPendingStatus_resets_startedAt() { assertThat(insert(TASK_UUID_1, COMPONENT_UUID_1, PENDING).getStartedAt()).isNull(); assertThat(underTest.peek(db.getSession(), WORKER_UUID_1, MAX_EXECUTION_COUNT).get().getUuid()).isEqualTo(TASK_UUID_1); assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1).get().getStartedAt()).isNotNull(); underTest.resetAllToPendingStatus(db.getSession()); assertThat(underTest.selectByUuid(db.getSession(), TASK_UUID_1).get().getStartedAt()).isNull(); } @Test public void resetAllToPendingStatus_does_not_reset_workerUuid_nor_executionCount() { CeQueueDto dto = new CeQueueDto() .setUuid(TASK_UUID_1) .setTaskType(CeTaskTypes.REPORT) .setComponentUuid(COMPONENT_UUID_1) .setStatus(IN_PROGRESS) .setSubmitterLogin(SUBMITTER_LOGIN) .setWorkerUuid(WORKER_UUID_1) .setExecutionCount(EXECUTION_COUNT); underTest.insert(db.getSession(), dto); db.commit(); underTest.resetAllToPendingStatus(db.getSession()); CeQueueDto saved = underTest.selectByUuid(db.getSession(), TASK_UUID_1).get(); assertThat(saved.getWorkerUuid()).isEqualTo(WORKER_UUID_1); assertThat(saved.getExecutionCount()).isEqualTo(EXECUTION_COUNT); } @Test public void resetToPendingForWorker_resets_status_of_non_pending_tasks_only_for_specified_workerUuid() { long startedAt = 2_099_888L; CeQueueDto u1 = insert("u1", CeQueueDto.Status.IN_PROGRESS, 1, WORKER_UUID_1, startedAt); CeQueueDto u2 = insert("u2", CeQueueDto.Status.PENDING, 1, WORKER_UUID_1, startedAt); CeQueueDto u3 = insert("u3", CeQueueDto.Status.PENDING, 0, WORKER_UUID_1, startedAt); CeQueueDto u4 = insert("u4", CeQueueDto.Status.IN_PROGRESS, 2, WORKER_UUID_1, startedAt); CeQueueDto o1 = insert("o1", CeQueueDto.Status.IN_PROGRESS, 1, WORKER_UUID_2, startedAt); CeQueueDto o2 = insert("o2", CeQueueDto.Status.PENDING, 1, WORKER_UUID_2, startedAt); CeQueueDto o3 = insert("o3", CeQueueDto.Status.PENDING, 0, WORKER_UUID_2, startedAt); CeQueueDto o4 = insert("o4", CeQueueDto.Status.IN_PROGRESS, 2, WORKER_UUID_2, startedAt); underTestAlwaysIncreasingSystem2.resetToPendingForWorker(db.getSession(), WORKER_UUID_1); verifyResetToPendingForWorker(u1); verifyUnchangedByResetToPendingForWorker(u2); verifyUnchangedByResetToPendingForWorker(u3); verifyResetToPendingForWorker(u4); verifyUnchangedByResetToPendingForWorker(o1); verifyUnchangedByResetToPendingForWorker(o2); verifyUnchangedByResetToPendingForWorker(o3); verifyUnchangedByResetToPendingForWorker(o4); } @Test public void resetTasksWithUnknownWorkerUUIDs_with_empty_set_resets_status_of_all_pending_tasks() { long startedAt = 2_099_888L; CeQueueDto u1 = insert("u1", CeQueueDto.Status.IN_PROGRESS, 1, WORKER_UUID_1, startedAt); CeQueueDto u2 = insert("u2", CeQueueDto.Status.PENDING, 1, WORKER_UUID_1, startedAt); CeQueueDto u3 = insert("u3", CeQueueDto.Status.PENDING, 0, WORKER_UUID_1, startedAt); CeQueueDto u4 = insert("u4", CeQueueDto.Status.IN_PROGRESS, 2, WORKER_UUID_1, startedAt); CeQueueDto o1 = insert("o1", CeQueueDto.Status.IN_PROGRESS, 1, WORKER_UUID_2, startedAt); CeQueueDto o2 = insert("o2", CeQueueDto.Status.PENDING, 1, WORKER_UUID_2, startedAt); CeQueueDto o3 = insert("o3", CeQueueDto.Status.PENDING, 0, WORKER_UUID_2, startedAt); CeQueueDto o4 = insert("o4", CeQueueDto.Status.IN_PROGRESS, 2, WORKER_UUID_2, startedAt); underTestAlwaysIncreasingSystem2.resetTasksWithUnknownWorkerUUIDs(db.getSession(), ImmutableSet.of()); verifyResetByResetTasks(u1); verifyUnchangedByResetToPendingForWorker(u2); verifyUnchangedByResetToPendingForWorker(u3); verifyResetByResetTasks(u4); verifyResetByResetTasks(o1); verifyUnchangedByResetToPendingForWorker(o2); verifyUnchangedByResetToPendingForWorker(o3); verifyResetByResetTasks(o4); } @Test public void resetTasksWithUnknownWorkerUUIDs_set_resets_status_of_all_pending_tasks_with_unknown_workers() { long startedAt = 2_099_888L; CeQueueDto u1 = insert("u1", CeQueueDto.Status.IN_PROGRESS, 1, WORKER_UUID_1, startedAt); CeQueueDto u2 = insert("u2", CeQueueDto.Status.PENDING, 1, WORKER_UUID_1, startedAt); CeQueueDto u3 = insert("u3", CeQueueDto.Status.PENDING, 0, WORKER_UUID_1, startedAt); CeQueueDto u4 = insert("u4", CeQueueDto.Status.IN_PROGRESS, 2, WORKER_UUID_1, startedAt); CeQueueDto o1 = insert("o1", CeQueueDto.Status.IN_PROGRESS, 1, WORKER_UUID_2, startedAt); CeQueueDto o2 = insert("o2", CeQueueDto.Status.PENDING, 1, WORKER_UUID_2, startedAt); CeQueueDto o3 = insert("o3", CeQueueDto.Status.PENDING, 0, WORKER_UUID_2, startedAt); CeQueueDto o4 = insert("o4", CeQueueDto.Status.IN_PROGRESS, 2, WORKER_UUID_2, startedAt); underTestAlwaysIncreasingSystem2.resetTasksWithUnknownWorkerUUIDs(db.getSession(), ImmutableSet.of(WORKER_UUID_1, "unknown")); verifyUnchangedByResetToPendingForWorker(u1); verifyUnchangedByResetToPendingForWorker(u2); verifyUnchangedByResetToPendingForWorker(u3); verifyUnchangedByResetToPendingForWorker(u4); verifyResetByResetTasks(o1); verifyUnchangedByResetToPendingForWorker(o2); verifyUnchangedByResetToPendingForWorker(o3); verifyResetByResetTasks(o4); } private void verifyResetByResetTasks(CeQueueDto original) { CeQueueDto dto = db.getDbClient().ceQueueDao().selectByUuid(db.getSession(), original.getUuid()).get(); assertThat(dto.getStatus()).isEqualTo(CeQueueDto.Status.PENDING).isNotEqualTo(original.getStatus()); assertThat(dto.getExecutionCount()).isEqualTo(original.getExecutionCount()); assertThat(dto.getStartedAt()).isNull(); assertThat(dto.getCreatedAt()).isEqualTo(original.getCreatedAt()); assertThat(dto.getUpdatedAt()).isGreaterThan(original.getUpdatedAt()); assertThat(dto.getWorkerUuid()).isNull(); } private void verifyResetToPendingForWorker(CeQueueDto original) { CeQueueDto dto = db.getDbClient().ceQueueDao().selectByUuid(db.getSession(), original.getUuid()).get(); assertThat(dto.getStatus()).isEqualTo(CeQueueDto.Status.PENDING); assertThat(dto.getExecutionCount()).isEqualTo(original.getExecutionCount()); assertThat(dto.getStartedAt()).isNull(); assertThat(dto.getCreatedAt()).isEqualTo(original.getCreatedAt()); assertThat(dto.getUpdatedAt()).isGreaterThan(original.getUpdatedAt()); assertThat(dto.getWorkerUuid()).isEqualTo(original.getWorkerUuid()); } private void verifyUnchangedByResetToPendingForWorker(CeQueueDto original) { CeQueueDto dto = db.getDbClient().ceQueueDao().selectByUuid(db.getSession(), original.getUuid()).get(); assertThat(dto.getStatus()).isEqualTo(original.getStatus()); assertThat(dto.getExecutionCount()).isEqualTo(original.getExecutionCount()); assertThat(dto.getStartedAt()).isEqualTo(original.getStartedAt()); assertThat(dto.getCreatedAt()).isEqualTo(original.getCreatedAt()); assertThat(dto.getUpdatedAt()).isEqualTo(original.getUpdatedAt()); assertThat(dto.getWorkerUuid()).isEqualTo(original.getWorkerUuid()); } @Test public void peek_none_if_no_pendings() throws Exception { assertThat(underTest.peek(db.getSession(), WORKER_UUID_1, MAX_EXECUTION_COUNT).isPresent()).isFalse(); // not pending, but in progress insert(TASK_UUID_1, COMPONENT_UUID_1, IN_PROGRESS); assertThat(underTest.peek(db.getSession(), WORKER_UUID_1, MAX_EXECUTION_COUNT).isPresent()).isFalse(); } @Test public void peek_oldest_pending() throws Exception { insert(TASK_UUID_1, COMPONENT_UUID_1, PENDING); system2.setNow(INIT_TIME + 3_000_000); insert(TASK_UUID_2, COMPONENT_UUID_2, PENDING); assertThat(db.countRowsOfTable("ce_queue")).isEqualTo(2); verifyCeQueueStatuses(TASK_UUID_1, PENDING, TASK_UUID_2, PENDING); // peek first one Optional<CeQueueDto> peek = underTest.peek(db.getSession(), WORKER_UUID_1, MAX_EXECUTION_COUNT); assertThat(peek).isPresent(); assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_1); assertThat(peek.get().getStatus()).isEqualTo(IN_PROGRESS); assertThat(peek.get().getWorkerUuid()).isEqualTo(WORKER_UUID_1); assertThat(peek.get().getExecutionCount()).isEqualTo(1); verifyCeQueueStatuses(TASK_UUID_1, IN_PROGRESS, TASK_UUID_2, PENDING); // peek second one peek = underTest.peek(db.getSession(), WORKER_UUID_2, MAX_EXECUTION_COUNT); assertThat(peek).isPresent(); assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_2); assertThat(peek.get().getStatus()).isEqualTo(IN_PROGRESS); assertThat(peek.get().getWorkerUuid()).isEqualTo(WORKER_UUID_2); assertThat(peek.get().getExecutionCount()).isEqualTo(1); verifyCeQueueStatuses(TASK_UUID_1, IN_PROGRESS, TASK_UUID_2, IN_PROGRESS); // no more pendings assertThat(underTest.peek(db.getSession(), WORKER_UUID_1, MAX_EXECUTION_COUNT).isPresent()).isFalse(); } @Test public void do_not_peek_multiple_tasks_on_same_project_at_the_same_time() throws Exception { // two pending tasks on the same project insert(TASK_UUID_1, COMPONENT_UUID_1, PENDING); system2.setNow(INIT_TIME + 3_000_000); insert(TASK_UUID_2, COMPONENT_UUID_1, PENDING); Optional<CeQueueDto> peek = underTest.peek(db.getSession(), WORKER_UUID_1, MAX_EXECUTION_COUNT); assertThat(peek).isPresent(); assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_1); assertThat(peek.get().getWorkerUuid()).isEqualTo(WORKER_UUID_1); assertThat(peek.get().getExecutionCount()).isEqualTo(1); verifyCeQueueStatuses(TASK_UUID_1, IN_PROGRESS, TASK_UUID_2, PENDING); // do not peek second task as long as the first one is in progress peek = underTest.peek(db.getSession(), WORKER_UUID_1, MAX_EXECUTION_COUNT); assertThat(peek.isPresent()).isFalse(); // first one is finished underTest.deleteByUuid(db.getSession(), TASK_UUID_1); peek = underTest.peek(db.getSession(), WORKER_UUID_2, MAX_EXECUTION_COUNT); assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_2); assertThat(peek.get().getWorkerUuid()).isEqualTo(WORKER_UUID_2); assertThat(peek.get().getExecutionCount()).isEqualTo(1); } @Test public void peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount_0() { peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount(0, null); } @Test public void peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount_1() { peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount(1, "u0"); } @Test public void peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount_2() { peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount(2, "u1"); } @Test public void peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount_3() { peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount(3, "u2"); } @Test public void peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount_4() { peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount(4, "u3"); } @Test public void peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount_more_then_4() { peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount(4 + Math.abs(new Random().nextInt(100)), "u3"); } private void peek_ignores_rows_with_executionCount_greater_or_equal_to_specified_maxExecutionCount(int maxExecutionCount, @Nullable String expected) { insert("u3", CeQueueDto.Status.PENDING, 3); insert("u2", CeQueueDto.Status.PENDING, 2); insert("u1", CeQueueDto.Status.PENDING, 1); insert("u0", CeQueueDto.Status.PENDING, 0); Optional<CeQueueDto> dto = underTest.peek(db.getSession(), WORKER_UUID_1, maxExecutionCount); if (expected == null) { assertThat(dto.isPresent()).isFalse(); } else { assertThat(dto.get().getUuid()).isEqualTo(expected); } } @Test public void select_by_query() { // task status not in query insert(newCeQueueDto(TASK_UUID_1) .setComponentUuid(COMPONENT_UUID_1) .setStatus(IN_PROGRESS) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(100_000L)); // too early insert(newCeQueueDto(TASK_UUID_3) .setComponentUuid(COMPONENT_UUID_1) .setStatus(PENDING) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(90_000L)); // task type not in query insert(newCeQueueDto("TASK_4") .setComponentUuid("PROJECT_2") .setStatus(PENDING) .setTaskType("ANOTHER_TYPE") .setCreatedAt(100_000L)); // correct insert(newCeQueueDto(TASK_UUID_2) .setComponentUuid(COMPONENT_UUID_1) .setStatus(PENDING) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(100_000L)); // correct submitted later insert(newCeQueueDto("TASK_5") .setComponentUuid(COMPONENT_UUID_1) .setStatus(PENDING) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(120_000L)); // select by component uuid, status, task type and minimum submitted at CeTaskQuery query = new CeTaskQuery() .setComponentUuids(newArrayList(COMPONENT_UUID_1, "PROJECT_2")) .setStatuses(singletonList(PENDING.name())) .setType(CeTaskTypes.REPORT) .setMinSubmittedAt(100_000L); List<CeQueueDto> result = underTest.selectByQueryInDescOrder(db.getSession(), query, 1_000); int total = underTest.countByQuery(db.getSession(), query); assertThat(result).extracting("uuid").containsExactly("TASK_5", TASK_UUID_2); assertThat(total).isEqualTo(2); } @Test public void select_by_query_returns_empty_list_when_only_current() { insert(newCeQueueDto(TASK_UUID_1) .setComponentUuid(COMPONENT_UUID_1) .setStatus(IN_PROGRESS) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(100_000L)); CeTaskQuery query = new CeTaskQuery().setOnlyCurrents(true); List<CeQueueDto> result = underTest.selectByQueryInDescOrder(db.getSession(), query, 1_000); int total = underTest.countByQuery(db.getSession(), query); assertThat(result).isEmpty(); assertThat(total).isEqualTo(0); } @Test public void select_by_query_returns_empty_list_when_max_submitted_at() { insert(newCeQueueDto(TASK_UUID_1) .setComponentUuid(COMPONENT_UUID_1) .setStatus(IN_PROGRESS) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(100_000L)); CeTaskQuery query = new CeTaskQuery().setMaxExecutedAt(1_000_000_000_000L); List<CeQueueDto> result = underTest.selectByQueryInDescOrder(db.getSession(), query, 1_000); int total = underTest.countByQuery(db.getSession(), query); assertThat(result).isEmpty(); assertThat(total).isEqualTo(0); } @Test public void select_by_query_returns_empty_list_when_empty_list_of_component_uuid() { insert(newCeQueueDto(TASK_UUID_1) .setComponentUuid(COMPONENT_UUID_1) .setStatus(IN_PROGRESS) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(100_000L)); CeTaskQuery query = new CeTaskQuery().setComponentUuids(Collections.<String>emptyList()); List<CeQueueDto> result = underTest.selectByQueryInDescOrder(db.getSession(), query, 1_000); int total = underTest.countByQuery(db.getSession(), query); assertThat(result).isEmpty(); assertThat(total).isEqualTo(0); } @Test public void count_by_status_and_component_uuid() { // task retrieved in the queue insert(newCeQueueDto(TASK_UUID_1) .setComponentUuid(COMPONENT_UUID_1) .setStatus(IN_PROGRESS) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(100_000L)); // on component uuid 2, not returned insert(newCeQueueDto(TASK_UUID_2) .setComponentUuid(COMPONENT_UUID_2) .setStatus(IN_PROGRESS) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(100_000L)); // pending status, not returned insert(newCeQueueDto(TASK_UUID_3) .setComponentUuid(COMPONENT_UUID_1) .setStatus(PENDING) .setTaskType(CeTaskTypes.REPORT) .setCreatedAt(100_000L)); assertThat(underTest.countByStatusAndComponentUuid(db.getSession(), IN_PROGRESS, COMPONENT_UUID_1)).isEqualTo(1); assertThat(underTest.countByStatus(db.getSession(), IN_PROGRESS)).isEqualTo(2); } private void insert(CeQueueDto dto) { underTest.insert(db.getSession(), dto); db.commit(); } private CeQueueDto insert(String uuid, CeQueueDto.Status status, int executionCount) { CeQueueDto dto = new CeQueueDto(); dto.setUuid(uuid); dto.setTaskType(CeTaskTypes.REPORT); dto.setStatus(status); dto.setSubmitterLogin("henri"); dto.setExecutionCount(executionCount); underTestAlwaysIncreasingSystem2.insert(db.getSession(), dto); db.getSession().commit(); return dto; } private CeQueueDto insert(String uuid, CeQueueDto.Status status, int executionCount, String workerUuid, Long startedAt) { CeQueueDto dto = new CeQueueDto(); dto.setUuid(uuid); dto.setTaskType(CeTaskTypes.REPORT); dto.setStatus(status); dto.setSubmitterLogin("henri"); dto.setExecutionCount(executionCount); dto.setWorkerUuid(workerUuid); dto.setStartedAt(startedAt); underTestAlwaysIncreasingSystem2.insert(db.getSession(), dto); db.getSession().commit(); return dto; } private CeQueueDto insert(String uuid, String componentUuid, CeQueueDto.Status status) { CeQueueDto dto = new CeQueueDto(); dto.setUuid(uuid); dto.setTaskType(CeTaskTypes.REPORT); dto.setComponentUuid(componentUuid); dto.setStatus(status); dto.setSubmitterLogin("henri"); underTest.insert(db.getSession(), dto); db.getSession().commit(); return dto; } private static Iterable<Map<String, Object>> upperizeKeys(List<Map<String, Object>> select) { return from(select).transform(new Function<Map<String, Object>, Map<String, Object>>() { @Nullable @Override public Map<String, Object> apply(Map<String, Object> input) { Map<String, Object> res = new HashMap<>(input.size()); for (Map.Entry<String, Object> entry : input.entrySet()) { res.put(entry.getKey().toUpperCase(), entry.getValue()); } return res; } }); } private void verifyCeQueueStatuses(String taskUuid1, CeQueueDto.Status taskStatus1, String taskUuid2, CeQueueDto.Status taskStatus2, String taskUuid3, CeQueueDto.Status taskStatus3) { verifyCeQueueStatuses(new String[] {taskUuid1, taskUuid2, taskUuid3}, new CeQueueDto.Status[] {taskStatus1, taskStatus2, taskStatus3}); } private void verifyCeQueueStatuses(String taskUuid1, CeQueueDto.Status taskStatus1, String taskUuid2, CeQueueDto.Status taskStatus2) { verifyCeQueueStatuses(new String[] {taskUuid1, taskUuid2}, new CeQueueDto.Status[] {taskStatus1, taskStatus2}); } private void verifyCeQueueStatuses(String[] taskUuids, CeQueueDto.Status[] statuses) { Map<String, Object>[] rows = new Map[taskUuids.length]; for (int i = 0; i < taskUuids.length; i++) { rows[i] = rowMap(taskUuids[i], statuses[i]); } assertThat(upperizeKeys(db.select(SELECT_QUEUE_UUID_AND_STATUS_QUERY))).containsOnly(rows); } private static Map<String, Object> rowMap(String uuid, CeQueueDto.Status status) { return ImmutableMap.of("UUID", uuid, "STATUS", status.name()); } private void mockSystem2ForSingleCall(long now) { Mockito.reset(mockedSystem2); when(mockedSystem2.now()) .thenReturn(now) .thenThrow(new IllegalStateException("now should be called only once")); } }