From 4085269c08104482e8c88b268642ecc39ff90770 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Wed, 16 Aug 2017 12:27:40 +0200 Subject: [PATCH] SONAR-9708 Return 'incremental' field on tasks in queue --- .../sonar/db/ce/CeTaskCharacteristicDao.java | 17 +++-- .../sonar/db/ce/CeTaskCharacteristicDto.java | 15 +++- .../db/ce/CeTaskCharacteristicMapper.java | 6 +- .../db/ce/CeTaskCharacteristicMapper.xml | 55 +++++++++----- .../db/ce/CeTaskCharacteristicDaoTest.java | 58 ++++++++++---- .../sonar/server/ce/ws/ActivityAction.java | 3 +- .../sonar/server/ce/ws/ComponentAction.java | 9 ++- .../org/sonar/server/ce/ws/TaskAction.java | 6 +- .../org/sonar/server/ce/ws/TaskFormatter.java | 66 ++++++++-------- .../server/ce/ws/ActivityActionTest.java | 56 +++++++++++--- .../server/ce/ws/ComponentActionTest.java | 47 +++++++++++- .../sonar/server/ce/ws/TaskActionTest.java | 76 ++++++++++++++++--- .../sonar/server/ce/ws/TaskFormatterTest.java | 5 +- .../queue/ReportSubmitterTest.java | 41 +++++----- .../org/sonarqube/ws/client/ce/CeService.java | 8 ++ .../sonarqube/ws/client/ce/CeServiceTest.java | 13 ++++ 16 files changed, 346 insertions(+), 135 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicDao.java index ceebc8134d0..7c417ef1148 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicDao.java @@ -20,25 +20,26 @@ package org.sonar.db.ce; import java.util.Collection; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; - import org.sonar.db.Dao; import org.sonar.db.DbSession; +import static org.sonar.db.DatabaseUtils.executeLargeInputs; + public class CeTaskCharacteristicDao implements Dao { + public void insert(DbSession dbSession, Collection characteristics) { for (CeTaskCharacteristicDto dto : characteristics) { mapper(dbSession).insert(dto); } } - public Map getTaskCharacteristics(DbSession dbSession, String taskUuid) { - Map map = new LinkedHashMap<>(); - List characteristics = mapper(dbSession).selectTaskCharacteristics(taskUuid); - characteristics.stream().forEach(dto -> map.put(dto.getKey(), dto.getValue())); - return map; + public List selectByTaskUuid(DbSession dbSession, String taskUuid) { + return mapper(dbSession).selectByTaskUuid(taskUuid); + } + + public List selectByTaskUuids(DbSession dbSession, List taskUuids) { + return executeLargeInputs(taskUuids, uuid -> mapper(dbSession).selectByTaskUuids(uuid)); } private static CeTaskCharacteristicMapper mapper(DbSession session) { diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicDto.java index 993049aa93d..06fbcfac5c8 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicDto.java @@ -20,6 +20,9 @@ package org.sonar.db.ce; public class CeTaskCharacteristicDto { + + public static final String INCREMENTAL_KEY = "incremental"; + private String uuid; private String taskUuid; private String key; @@ -29,31 +32,35 @@ public class CeTaskCharacteristicDto { return uuid; } - public void setUuid(String uuid) { + public CeTaskCharacteristicDto setUuid(String uuid) { this.uuid = uuid; + return this; } public String getTaskUuid() { return taskUuid; } - public void setTaskUuid(String taskUuid) { + public CeTaskCharacteristicDto setTaskUuid(String taskUuid) { this.taskUuid = taskUuid; + return this; } public String getKey() { return key; } - public void setKey(String key) { + public CeTaskCharacteristicDto setKey(String key) { this.key = key; + return this; } public String getValue() { return value; } - public void setValue(String value) { + public CeTaskCharacteristicDto setValue(String value) { this.value = value; + return this; } } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicMapper.java index 492b88505e8..fe9fa7994b1 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeTaskCharacteristicMapper.java @@ -20,11 +20,13 @@ package org.sonar.db.ce; import java.util.List; - import org.apache.ibatis.annotations.Param; public interface CeTaskCharacteristicMapper { - List selectTaskCharacteristics(@Param("taskUuid") String taskUuid); + + List selectByTaskUuid(@Param("taskUuid") String taskUuid); + + List selectByTaskUuids(@Param("taskUuids") List taskUuids); void insert(CeTaskCharacteristicDto taskCharacteristic); diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeTaskCharacteristicMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeTaskCharacteristicMapper.xml index 002219c4b71..2e65de2cce9 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeTaskCharacteristicMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeTaskCharacteristicMapper.xml @@ -2,30 +2,45 @@ - - insert into ce_task_characteristics ( - uuid, - task_uuid, - kee, - text_value - ) - values ( - #{uuid,jdbcType=VARCHAR}, - #{taskUuid,jdbcType=VARCHAR}, - #{key,jdbcType=VARCHAR}, - #{value,jdbcType=VARCHAR} - ) - - - SELECT - c.uuid as "uuid", - c.task_uuid as "taskUuid", - c.kee as "key", - c.text_value as "value" + FROM ce_task_characteristics c WHERE c.task_uuid = #{taskUuid,jdbcType=VARCHAR} + + + + + insert into ce_task_characteristics ( + uuid, + task_uuid, + kee, + text_value + ) + values ( + #{uuid,jdbcType=VARCHAR}, + #{taskUuid,jdbcType=VARCHAR}, + #{key,jdbcType=VARCHAR}, + #{value,jdbcType=VARCHAR} + ) + + diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeTaskCharacteristicDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeTaskCharacteristicDaoTest.java index e4d3d3b9f9a..aa3eca59a9a 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeTaskCharacteristicDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeTaskCharacteristicDaoTest.java @@ -19,17 +19,17 @@ */ package org.sonar.db.ce; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.entry; - -import java.util.Collections; - import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + public class CeTaskCharacteristicDaoTest { @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); @@ -39,21 +39,49 @@ public class CeTaskCharacteristicDaoTest { private CeTaskCharacteristicDao underTest = new CeTaskCharacteristicDao(); @Test - public void test_insert() { - CeTaskCharacteristicDto dto = new CeTaskCharacteristicDto(); - dto.setKey("key"); - dto.setValue("value"); - dto.setUuid("uuid"); - dto.setTaskUuid("task"); - underTest.insert(dbTester.getSession(), Collections.singletonList(dto)); + public void selectByTaskUuid() { + CeTaskCharacteristicDto dto1 = new CeTaskCharacteristicDto() + .setKey("key1") + .setValue("value1") + .setUuid("uuid1") + .setTaskUuid("task"); + CeTaskCharacteristicDto dto2 = new CeTaskCharacteristicDto() + .setKey("key2") + .setValue("value2") + .setUuid("uuid2") + .setTaskUuid("task"); + underTest.insert(dbTester.getSession(), asList(dto1, dto2)); dbTester.getSession().commit(); - assertThat(underTest.getTaskCharacteristics(dbTester.getSession(), "task")).containsOnly(entry("key", "value")); + assertThat(underTest.selectByTaskUuid(dbTester.getSession(), "task")) + .extracting(CeTaskCharacteristicDto::getTaskUuid, CeTaskCharacteristicDto::getUuid, CeTaskCharacteristicDto::getKey, CeTaskCharacteristicDto::getValue) + .containsOnly( + tuple("task", "uuid1", "key1", "value1"), + tuple("task", "uuid2", "key2", "value2")); + assertThat(underTest.selectByTaskUuid(dbTester.getSession(), "unknown")).isEmpty(); } @Test - public void test_no_result() { - assertThat(underTest.getTaskCharacteristics(dbTester.getSession(), "task")).isEmpty(); + public void selectByTaskUuids() { + CeTaskCharacteristicDto dto1 = new CeTaskCharacteristicDto() + .setKey("key1") + .setValue("value1") + .setUuid("uuid1") + .setTaskUuid("task1"); + CeTaskCharacteristicDto dto2 = new CeTaskCharacteristicDto() + .setKey("key2") + .setValue("value2") + .setUuid("uuid2") + .setTaskUuid("task2"); + underTest.insert(dbTester.getSession(), asList(dto1, dto2)); + dbTester.getSession().commit(); + assertThat(underTest.selectByTaskUuids(dbTester.getSession(), asList("task1", "task2"))) + .extracting(CeTaskCharacteristicDto::getTaskUuid, CeTaskCharacteristicDto::getUuid, CeTaskCharacteristicDto::getKey, CeTaskCharacteristicDto::getValue) + .containsOnly( + tuple("task1", "uuid1", "key1", "value1"), + tuple("task2", "uuid2", "key2", "value2")); + assertThat(underTest.selectByTaskUuids(dbTester.getSession(), singletonList("unknown"))).isEmpty(); } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java index b1ac6073762..bf3c7923f67 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java @@ -217,8 +217,7 @@ public class ActivityAction implements CeWsAction { } java.util.Optional activity = dbClient.ceActivityDao().selectByUuid(dbSession, textQuery); - return activity.map(ceActivityDto -> Optional.of(formatter.formatActivity(dbSession, ceActivityDto))).orElseGet(Optional::absent); - + return activity.map(ceActivityDto -> Optional.of(formatter.formatActivity(dbSession, ceActivityDto, null))).orElseGet(Optional::absent); } private CeTaskQuery buildQuery(DbSession dbSession, ActivityWsRequest request, @Nullable ComponentDto component) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ComponentAction.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ComponentAction.java index 013516ad983..ae371a6b37c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ComponentAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/ComponentAction.java @@ -20,6 +20,7 @@ package org.sonar.server.ce.ws; import java.util.List; +import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; @@ -62,11 +63,13 @@ public class ComponentAction implements CeWsAction { WebService.NewAction action = controller.createAction("component") .setDescription("Get the pending tasks, in-progress tasks and the last executed task of a given component (usually a project).
" + "Requires the following permission: 'Browse' on the specified component.
" + - "Either '%s' or '%s' must be provided, not both.
" + - "Since 6.1, field \"logs\" is deprecated and its value is always false.", + "Either '%s' or '%s' must be provided, not both.", PARAM_COMPONENT_ID, PARAM_COMPONENT_KEY) .setSince("5.2") .setResponseExample(getClass().getResource("component-example.json")) + .setChangelog( + new Change("6.1", "field \"logs\" is deprecated and its value is always false"), + new Change("6.6", "field \"incremental\" is added")) .setHandler(this); action.createParam(PARAM_COMPONENT_ID) @@ -92,7 +95,7 @@ public class ComponentAction implements CeWsAction { ProjectResponse.Builder wsResponseBuilder = ProjectResponse.newBuilder(); wsResponseBuilder.addAllQueue(formatter.formatQueue(dbSession, queueDtos)); if (activityDtos.size() == 1) { - wsResponseBuilder.setCurrent(formatter.formatActivity(dbSession, activityDtos.get(0))); + wsResponseBuilder.setCurrent(formatter.formatActivity(dbSession, activityDtos.get(0), null)); } writeProtobuf(wsResponseBuilder.build(), wsRequest, wsResponse); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskAction.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskAction.java index a39958add89..ed086869839 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskAction.java @@ -28,6 +28,7 @@ import java.util.Optional; import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; @@ -72,6 +73,7 @@ public class TaskAction implements CeWsAction { "Since 6.1, field \"logs\" is deprecated and its value is always false.") .setResponseExample(getClass().getResource("task-example.json")) .setSince("5.2") + .setChangelog(new Change("6.6", "field \"incremental\" is added")) .setHandler(this); action @@ -94,7 +96,7 @@ public class TaskAction implements CeWsAction { if (queueDto.isPresent()) { com.google.common.base.Optional component = loadComponent(dbSession, queueDto.get().getComponentUuid()); checkPermission(component); - wsTaskResponse.setTask(wsTaskFormatter.formatQueue(dbSession, queueDto.get(), component)); + wsTaskResponse.setTask(wsTaskFormatter.formatQueue(dbSession, queueDto.get())); } else { CeActivityDto ceActivityDto = WsUtils.checkFoundWithOptional(dbClient.ceActivityDao().selectByUuid(dbSession, taskUuid), "No activity found for task '%s'", taskUuid); com.google.common.base.Optional component = loadComponent(dbSession, ceActivityDto.getComponentUuid()); @@ -102,7 +104,7 @@ public class TaskAction implements CeWsAction { Set additionalFields = AdditionalField.getFromRequest(wsRequest); maskErrorStacktrace(ceActivityDto, additionalFields); wsTaskResponse.setTask( - wsTaskFormatter.formatActivity(dbSession, ceActivityDto, component, extractScannerContext(dbSession, ceActivityDto, additionalFields))); + wsTaskFormatter.formatActivity(dbSession, ceActivityDto, extractScannerContext(dbSession, ceActivityDto, additionalFields))); } writeProtobuf(wsTaskResponse.build(), wsRequest, wsResponse); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java index 16aead9298a..a148896ab15 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java @@ -19,8 +19,8 @@ */ package org.sonar.server.ce.ws; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.utils.DateUtils; @@ -37,14 +38,13 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeQueueDto; +import org.sonar.db.ce.CeTaskCharacteristicDto; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; import org.sonar.db.organization.OrganizationDto; import org.sonarqube.ws.WsCe; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; -import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.core.util.Protobuf.setNullable; @@ -64,20 +64,15 @@ public class TaskFormatter { } public List formatQueue(DbSession dbSession, List dtos) { - ComponentDtoCache cache = ComponentDtoCache.forQueueDtos(dbClient, dbSession, dtos); + DtoCache cache = DtoCache.forQueueDtos(dbClient, dbSession, dtos); return dtos.stream().map(input -> formatQueue(input, cache)).collect(MoreCollectors.toList(dtos.size())); } public WsCe.Task formatQueue(DbSession dbSession, CeQueueDto queue) { - return formatQueue(queue, ComponentDtoCache.forQueueDtos(dbClient, dbSession, singletonList(queue))); + return formatQueue(queue, DtoCache.forQueueDtos(dbClient, dbSession, singletonList(queue))); } - public WsCe.Task formatQueue(DbSession dbSession, CeQueueDto dto, Optional component) { - checkArgument(Objects.equals(dto.getComponentUuid(), component.transform(ComponentDto::uuid).orNull())); - return formatQueue(dto, ComponentDtoCache.forComponentDto(dbClient, dbSession, component)); - } - - private WsCe.Task formatQueue(CeQueueDto dto, ComponentDtoCache componentDtoCache) { + private WsCe.Task formatQueue(CeQueueDto dto, DtoCache componentDtoCache) { WsCe.Task.Builder builder = WsCe.Task.newBuilder(); String organizationKey = componentDtoCache.getOrganizationKey(dto.getComponentUuid()); // FIXME organization field should be set from the CeQueueDto rather than from the ComponentDto @@ -94,26 +89,22 @@ public class TaskFormatter { builder.setSubmittedAt(formatDateTime(new Date(dto.getCreatedAt()))); setNullable(dto.getStartedAt(), builder::setStartedAt, DateUtils::formatDateTime); setNullable(computeExecutionTimeMs(dto), builder::setExecutionTimeMs); + builder.setIncremental(componentDtoCache.hasIncrementalCharacteristic(dto.getUuid())); return builder.build(); } - public WsCe.Task formatActivity(DbSession dbSession, CeActivityDto activity) { - return formatActivity(activity, ComponentDtoCache.forActivityDtos(dbClient, dbSession, singletonList(activity)), null); - } - - public WsCe.Task formatActivity(DbSession dbSession, CeActivityDto dto, Optional component, - @Nullable String scannerContext) { - return formatActivity(dto, ComponentDtoCache.forComponentDto(dbClient, dbSession, component), scannerContext); + public WsCe.Task formatActivity(DbSession dbSession, CeActivityDto dto, @Nullable String scannerContext) { + return formatActivity(dto, DtoCache.forActivityDtos(dbClient, dbSession, singletonList(dto)), scannerContext); } public List formatActivity(DbSession dbSession, List dtos) { - ComponentDtoCache cache = ComponentDtoCache.forActivityDtos(dbClient, dbSession, dtos); + DtoCache cache = DtoCache.forActivityDtos(dbClient, dbSession, dtos); return dtos.stream() .map(input -> formatActivity(input, cache, null)) .collect(MoreCollectors.toList(dtos.size())); } - private static WsCe.Task formatActivity(CeActivityDto dto, ComponentDtoCache componentDtoCache, @Nullable String scannerContext) { + private static WsCe.Task formatActivity(CeActivityDto dto, DtoCache componentDtoCache, @Nullable String scannerContext) { WsCe.Task.Builder builder = WsCe.Task.newBuilder(); String organizationKey = componentDtoCache.getOrganizationKey(dto.getComponentUuid()); // FIXME organization field should be set from the CeActivityDto rather than from the ComponentDto @@ -126,8 +117,9 @@ public class TaskFormatter { String analysisUuid = dto.getAnalysisUuid(); if (analysisUuid != null) { builder.setAnalysisId(analysisUuid); - setNullable(componentDtoCache.getAnalysis(analysisUuid), analysis -> builder.setIncremental(analysis.getIncremental())); } + SnapshotDto analysis = analysisUuid == null ? null : componentDtoCache.getAnalysis(analysisUuid); + builder.setIncremental(analysis != null && analysis.getIncremental()); setNullable(analysisUuid, builder::setAnalysisId); setNullable(dto.getSubmitterLogin(), builder::setSubmitterLogin); builder.setSubmittedAt(formatDateTime(new Date(dto.getSubmittedAt()))); @@ -150,22 +142,28 @@ public class TaskFormatter { return builder; } - private static class ComponentDtoCache { + private static class DtoCache { private final Map componentsByUuid; private final Map organizationsByUuid; private final Map analysisByUuid; + private final Multimap characteristicsByTaskUuid; - private ComponentDtoCache(Map componentsByUuid, Map organizationsByUuid, Map analysisByUuid) { + private DtoCache(Map componentsByUuid, Map organizationsByUuid, Map analysisByUuid, + Multimap characteristicsByTaskUuid) { this.componentsByUuid = componentsByUuid; this.organizationsByUuid = organizationsByUuid; this.analysisByUuid = analysisByUuid; + this.characteristicsByTaskUuid = characteristicsByTaskUuid; } - static ComponentDtoCache forQueueDtos(DbClient dbClient, DbSession dbSession, Collection ceQueueDtos) { + static DtoCache forQueueDtos(DbClient dbClient, DbSession dbSession, Collection ceQueueDtos) { Map componentsByUuid = dbClient.componentDao().selectByUuids(dbSession, uuidOfCeQueueDtos(ceQueueDtos)) .stream() .collect(MoreCollectors.uniqueIndex(ComponentDto::uuid)); - return new ComponentDtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), Collections.emptyMap()); + Multimap characteristicsByTaskUuid = dbClient.ceTaskCharacteristicsDao() + .selectByTaskUuids(dbSession, ceQueueDtos.stream().map(CeQueueDto::getUuid).collect(Collectors.toList())) + .stream().collect(MoreCollectors.index(CeTaskCharacteristicDto::getTaskUuid)); + return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), Collections.emptyMap(), characteristicsByTaskUuid); } private static Set uuidOfCeQueueDtos(Collection ceQueueDtos) { @@ -176,7 +174,7 @@ public class TaskFormatter { .collect(MoreCollectors.toSet(ceQueueDtos.size())); } - static ComponentDtoCache forActivityDtos(DbClient dbClient, DbSession dbSession, Collection ceActivityDtos) { + static DtoCache forActivityDtos(DbClient dbClient, DbSession dbSession, Collection ceActivityDtos) { Map componentsByUuid = dbClient.componentDao().selectByUuids( dbSession, uuidOfCeActivityDtos(ceActivityDtos)) @@ -184,7 +182,8 @@ public class TaskFormatter { .collect(MoreCollectors.uniqueIndex(ComponentDto::uuid)); Set analysisUuids = ceActivityDtos.stream().map(CeActivityDto::getAnalysisUuid).filter(Objects::nonNull).collect(MoreCollectors.toSet()); Map analysisByUuid = dbClient.snapshotDao().selectByUuids(dbSession, analysisUuids).stream().collect(MoreCollectors.uniqueIndex(SnapshotDto::getUuid)); - return new ComponentDtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), analysisByUuid); + return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), analysisByUuid, + ImmutableMultimap.builder().build()); } private static Set uuidOfCeActivityDtos(Collection ceActivityDtos) { @@ -195,11 +194,6 @@ public class TaskFormatter { .collect(MoreCollectors.toSet(ceActivityDtos.size())); } - static ComponentDtoCache forComponentDto(DbClient dbClient, DbSession dbSession, Optional component) { - Map componentsByUuid = component.isPresent() ? ImmutableMap.of(component.get().uuid(), component.get()) : emptyMap(); - return new ComponentDtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), Collections.emptyMap()); - } - private static Map buildOrganizationsByUuid(DbClient dbClient, DbSession dbSession, Map componentsByUuid) { return dbClient.organizationDao().selectByUuids( dbSession, @@ -237,6 +231,12 @@ public class TaskFormatter { SnapshotDto getAnalysis(String analysisUuid) { return analysisByUuid.get(analysisUuid); } + + boolean hasIncrementalCharacteristic(String taskUuid) { + return characteristicsByTaskUuid.get(taskUuid).stream() + .filter(c -> c.getKey().equals(CeTaskCharacteristicDto.INCREMENTAL_KEY)) + .anyMatch(c -> c.getValue().equals("true")); + } } /** diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java index c6f20d7bc1e..d3a37c0d0ad 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java @@ -20,6 +20,7 @@ package org.sonar.server.ce.ws; import java.io.IOException; +import java.util.Collections; import java.util.Date; import java.util.List; import javax.annotation.Nullable; @@ -30,10 +31,12 @@ import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.ce.taskprocessor.CeTaskProcessor; +import org.sonar.core.util.Uuids; import org.sonar.db.DbTester; import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeActivityDto.Status; import org.sonar.db.ce.CeQueueDto; +import org.sonar.db.ce.CeTaskCharacteristicDto; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; @@ -60,6 +63,9 @@ import static org.sonar.api.utils.DateUtils.formatDate; import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.db.ce.CeActivityDto.Status.FAILED; import static org.sonar.db.ce.CeActivityDto.Status.SUCCESS; +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.CeTaskCharacteristicDto.INCREMENTAL_KEY; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_ID; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_QUERY; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_MAX_EXECUTED_AT; @@ -124,7 +130,7 @@ public class ActivityActionTest { ComponentDto project2 = db.components().insertPrivateProject(); insertActivity("T1", project1, SUCCESS); insertActivity("T2", project2, FAILED); - insertQueue("T3", project1, CeQueueDto.Status.IN_PROGRESS); + insertQueue("T3", project1, IN_PROGRESS); ActivityResponse activityResponse = call(ws.newRequest() .setParam("status", "FAILED,IN_PROGRESS")); @@ -141,7 +147,7 @@ public class ActivityActionTest { ComponentDto project2 = db.components().insertPrivateProject(); insertActivity("T1", project1, SUCCESS); insertActivity("T2", project2, FAILED); - insertQueue("T3", project1, CeQueueDto.Status.IN_PROGRESS); + insertQueue("T3", project1, IN_PROGRESS); ActivityResponse activityResponse = call(ws.newRequest() .setParam("status", "FAILED,IN_PROGRESS,SUCCESS") @@ -171,7 +177,7 @@ public class ActivityActionTest { // T2 is the current activity (the most recent one) insertActivity("T1", project, SUCCESS); insertActivity("T2", project, FAILED); - insertQueue("T3", project, CeQueueDto.Status.PENDING); + insertQueue("T3", project, PENDING); ActivityResponse activityResponse = call( ws.newRequest() @@ -188,7 +194,7 @@ public class ActivityActionTest { ComponentDto project2 = db.components().insertPrivateProject(); insertActivity("T1", project1, SUCCESS); insertActivity("T2", project2, FAILED); - insertQueue("T3", project1, CeQueueDto.Status.IN_PROGRESS); + insertQueue("T3", project1, IN_PROGRESS); assertPage(1, asList("T3")); assertPage(2, asList("T3", "T2")); @@ -269,12 +275,12 @@ public class ActivityActionTest { public void search_task_id_in_queue_ignoring_other_parameters() throws IOException { logInAsSystemAdministrator(); ComponentDto project = db.components().insertPrivateProject(); - insertQueue("T1", project, CeQueueDto.Status.IN_PROGRESS); + insertQueue("T1", project, IN_PROGRESS); ActivityResponse result = call( ws.newRequest() .setParam(Param.TEXT_QUERY, "T1") - .setParam(PARAM_STATUS, CeQueueDto.Status.PENDING.name())); + .setParam(PARAM_STATUS, PENDING.name())); assertThat(result.getTasksCount()).isEqualTo(1); assertThat(result.getTasks(0).getId()).isEqualTo("T1"); @@ -310,7 +316,7 @@ public class ActivityActionTest { @Test public void search_task_by_component_id() { ComponentDto project = db.components().insertPrivateProject(); - insertQueue("T1", project, CeQueueDto.Status.IN_PROGRESS); + insertQueue("T1", project, IN_PROGRESS); insertActivity("T1", project, SUCCESS); userSession.logIn().addProjectPermission(UserRole.ADMIN, project); @@ -334,7 +340,7 @@ public class ActivityActionTest { assertThat(activityResponse.getTasksList()) .extracting(Task::getId, Task::getIncremental) - .containsExactlyInAnyOrder(tuple("T1", true)); + .containsExactlyInAnyOrder(tuple("T1", true)); } @Test @@ -371,6 +377,27 @@ public class ActivityActionTest { .containsExactlyInAnyOrder(tuple("T1", true)); } + @Test + public void incremental_on_in_queue_analysis() { + ComponentDto project = db.components().insertPrivateProject(); + CeQueueDto queue1 = insertQueue("T1", project, PENDING); + insertCharacteristic(queue1, INCREMENTAL_KEY, "true"); + CeQueueDto queue2 = insertQueue("T2", project, IN_PROGRESS); + insertCharacteristic(queue2, INCREMENTAL_KEY, "true"); + userSession.logIn().addProjectPermission(UserRole.ADMIN, project); + + ActivityResponse activityResponse = call(ws.newRequest() + .setParam(PARAM_COMPONENT_ID, project.uuid()) + .setParam("status", "PENDING,FAILED,IN_PROGRESS")); + + assertThat(activityResponse.getTasksList()) + .extracting(Task::getId, Task::getIncremental) + .containsExactlyInAnyOrder( + tuple("T1", true), + tuple("T2", true) + ); + } + @Test public void fail_if_both_filters_on_component_id_and_name() { expectedException.expect(BadRequestException.class); @@ -480,11 +507,22 @@ public class ActivityActionTest { activityDto.setExecutionTimeMs(500L); activityDto.setExecutedAt(EXECUTED_AT); activityDto.setAnalysisUuid(analysis == null ? null : analysis.getUuid()); - db.getDbClient().ceActivityDao(). insert(db.getSession(), activityDto); + db.getDbClient().ceActivityDao().insert(db.getSession(), activityDto); db.commit(); return activityDto; } + private CeTaskCharacteristicDto insertCharacteristic(CeQueueDto queueDto, String key, String value) { + CeTaskCharacteristicDto dto = new CeTaskCharacteristicDto() + .setUuid(Uuids.createFast()) + .setTaskUuid(queueDto.getUuid()) + .setKey(key) + .setValue(value); + db.getDbClient().ceTaskCharacteristicsDao().insert(db.getSession(), Collections.singletonList(dto)); + db.commit(); + return dto; + } + private static ActivityResponse call(TestRequest request) { return request.executeProtobuf(ActivityResponse.class); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java index d153fa0f9d4..afecd31d24a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java @@ -19,15 +19,18 @@ */ package org.sonar.server.ce.ws; +import java.util.Collections; import javax.annotation.Nullable; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; +import org.sonar.core.util.Uuids; import org.sonar.db.DbTester; import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeQueueDto; +import org.sonar.db.ce.CeTaskCharacteristicDto; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; @@ -41,7 +44,9 @@ import org.sonarqube.ws.MediaTypes; import org.sonarqube.ws.WsCe; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Java6Assertions.tuple; import static org.sonar.db.ce.CeActivityDto.Status.SUCCESS; +import static org.sonar.db.ce.CeTaskCharacteristicDto.INCREMENTAL_KEY; import static org.sonar.server.ce.ws.ComponentAction.PARAM_COMPONENT_ID; import static org.sonar.server.ce.ws.ComponentAction.PARAM_COMPONENT_KEY; @@ -78,11 +83,11 @@ public class ComponentActionTest { SnapshotDto analysisProject1 = db.components().insertSnapshot(project1); ComponentDto project2 = db.components().insertPrivateProject(organization); userSession.addProjectPermission(UserRole.USER, project1); - insertActivity("T1", project1,CeActivityDto.Status.SUCCESS, analysisProject1); + insertActivity("T1", project1, CeActivityDto.Status.SUCCESS, analysisProject1); insertActivity("T2", project2, CeActivityDto.Status.FAILED, null); - insertActivity("T3", project1,CeActivityDto.Status.FAILED, null); - insertQueue("T4", project1,CeQueueDto.Status.IN_PROGRESS); - insertQueue("T5", project1,CeQueueDto.Status.PENDING); + insertActivity("T3", project1, CeActivityDto.Status.FAILED, null); + insertQueue("T4", project1, CeQueueDto.Status.IN_PROGRESS); + insertQueue("T5", project1, CeQueueDto.Status.PENDING); WsCe.ProjectResponse response = ws.newRequest() .setParam("componentId", project1.uuid()) @@ -98,6 +103,7 @@ public class ComponentActionTest { .extracting(WsCe.Task::getOrganization) .containsOnly(organization.getKey()); assertThat(response.getCurrent().getOrganization()).isEqualTo(organization.getKey()); + assertThat(response.getCurrent().getIncremental()).isFalse(); } @Test @@ -166,6 +172,28 @@ public class ComponentActionTest { .containsExactlyInAnyOrder("T1", true); } + @Test + public void incremental_on_in_queue_analysis() { + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); + userSession.addProjectPermission(UserRole.USER, project); + CeQueueDto queue1 = insertQueue("T1", project, CeQueueDto.Status.IN_PROGRESS); + insertCharacteristic(queue1, INCREMENTAL_KEY, "true"); + CeQueueDto queue2 = insertQueue("T2", project, CeQueueDto.Status.PENDING); + insertCharacteristic(queue2, INCREMENTAL_KEY, "true"); + + WsCe.ProjectResponse response = ws.newRequest() + .setParam("componentId", project.uuid()) + .executeProtobuf(WsCe.ProjectResponse.class); + + assertThat(response.getQueueList()) + .extracting(WsCe.Task::getId, WsCe.Task::getIncremental) + .containsOnly( + tuple("T1", true), + tuple("T2", true) + ); + } + @Test public void fail_with_404_when_component_does_not_exist() throws Exception { expectedException.expect(NotFoundException.class); @@ -228,4 +256,15 @@ public class ComponentActionTest { db.getSession().commit(); return activityDto; } + + private CeTaskCharacteristicDto insertCharacteristic(CeQueueDto queueDto, String key, String value) { + CeTaskCharacteristicDto dto = new CeTaskCharacteristicDto() + .setUuid(Uuids.createFast()) + .setTaskUuid(queueDto.getUuid()) + .setKey(key) + .setValue(value); + db.getDbClient().ceTaskCharacteristicsDao().insert(db.getSession(), Collections.singletonList(dto)); + db.commit(); + return dto; + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java index 6415597b482..038f227104b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java @@ -19,6 +19,7 @@ */ package org.sonar.server.ce.ws; +import java.util.Collections; import javax.annotation.Nullable; import org.junit.Before; import org.junit.Rule; @@ -27,11 +28,14 @@ import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.util.CloseableIterator; +import org.sonar.core.util.Uuids; import org.sonar.db.DbTester; import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeQueueDto; +import org.sonar.db.ce.CeTaskCharacteristicDto; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.SnapshotDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; @@ -54,18 +58,18 @@ public class TaskActionTest { public ExpectedException expectedException = ExpectedException.none(); @Rule - public DbTester dbTester = DbTester.create(System2.INSTANCE); + public DbTester db = DbTester.create(System2.INSTANCE); private OrganizationDto organizationDto; private ComponentDto project; - private TaskFormatter formatter = new TaskFormatter(dbTester.getDbClient(), System2.INSTANCE); - private TaskAction underTest = new TaskAction(dbTester.getDbClient(), formatter, userSession); + private TaskFormatter formatter = new TaskFormatter(db.getDbClient(), System2.INSTANCE); + private TaskAction underTest = new TaskAction(db.getDbClient(), formatter, userSession); private WsActionTester ws = new WsActionTester(underTest); @Before public void setUp() { - organizationDto = dbTester.organizations().insert(); - project = dbTester.components().insertPrivateProject(organizationDto); + organizationDto = db.organizations().insert(); + project = db.components().insertPrivateProject(organizationDto); } @Test @@ -92,6 +96,7 @@ public class TaskActionTest { assertThat(taskResponse.getTask().getComponentName()).isEqualTo(project.name()); assertThat(taskResponse.getTask().hasExecutionTimeMs()).isFalse(); assertThat(taskResponse.getTask().getLogs()).isFalse(); + assertThat(taskResponse.getTask().getIncremental()).isFalse(); } @Test @@ -116,6 +121,44 @@ public class TaskActionTest { assertThat(task.getLogs()).isFalse(); } + @Test + public void incremental_on_queued_task() { + logInAsRoot(); + + ComponentDto project = db.components().insertPrivateProject(); + CeQueueDto queueDto = createAndPersistQueueTask(project); + insertCharacteristic(queueDto, "incremental", "true"); + + WsCe.TaskResponse taskResponse = ws.newRequest() + .setParam("id", SOME_TASK_UUID) + .executeProtobuf(WsCe.TaskResponse.class); + + assertThat(taskResponse.getTask().getIncremental()).isTrue(); + } + + @Test + public void incremental_on_archived_task() { + logInAsRoot(); + + ComponentDto project = db.components().insertPrivateProject(); + SnapshotDto analysis = db.components().insertSnapshot(project, s -> s.setIncremental(true)); + CeQueueDto queueDto = new CeQueueDto() + .setTaskType(CeTaskTypes.REPORT) + .setUuid(SOME_TASK_UUID) + .setComponentUuid(project.uuid()); + CeActivityDto activityDto = new CeActivityDto(queueDto) + .setStatus(CeActivityDto.Status.FAILED) + .setExecutionTimeMs(500L) + .setAnalysisUuid(analysis.getUuid()); + persist(activityDto); + + WsCe.TaskResponse taskResponse = ws.newRequest() + .setParam("id", SOME_TASK_UUID) + .executeProtobuf(WsCe.TaskResponse.class); + + assertThat(taskResponse.getTask().getIncremental()).isTrue(); + } + @Test public void return_stacktrace_of_failed_activity_with_stacktrace_when_additionalField_is_set() { logInAsRoot(); @@ -344,20 +387,31 @@ public class TaskActionTest { return dto; } + private CeTaskCharacteristicDto insertCharacteristic(CeQueueDto queueDto, String key, String value) { + CeTaskCharacteristicDto dto = new CeTaskCharacteristicDto() + .setUuid(Uuids.createFast()) + .setTaskUuid(queueDto.getUuid()) + .setKey(key) + .setValue(value); + db.getDbClient().ceTaskCharacteristicsDao().insert(db.getSession(), Collections.singletonList(dto)); + db.commit(); + return dto; + } + private void persist(CeQueueDto queueDto) { - dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto); - dbTester.commit(); + db.getDbClient().ceQueueDao().insert(db.getSession(), queueDto); + db.commit(); } private CeActivityDto persist(CeActivityDto activityDto) { - dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto); - dbTester.commit(); + db.getDbClient().ceActivityDao().insert(db.getSession(), activityDto); + db.commit(); return activityDto; } private void persistScannerContext(String taskUuid, String scannerContext) { - dbTester.getDbClient().ceScannerContextDao().insert(dbTester.getSession(), taskUuid, CloseableIterator.from(singleton(scannerContext).iterator())); - dbTester.commit(); + db.getDbClient().ceScannerContextDao().insert(db.getSession(), taskUuid, CloseableIterator.from(singleton(scannerContext).iterator())); + db.commit(); } private void logInAsSystemAdministrator() { diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java index 3e99deaa393..44cc1612ab5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.ce.ws; -import com.google.common.base.Optional; import java.io.IOException; import java.util.Collections; import java.util.Date; @@ -160,7 +159,7 @@ public class TaskFormatterTest { public void formatActivity() { CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED); - WsCe.Task wsTask = underTest.formatActivity(db.getSession(), dto); + WsCe.Task wsTask = underTest.formatActivity(db.getSession(), dto, null); assertThat(wsTask.getType()).isEqualTo(CeTaskTypes.REPORT); assertThat(wsTask.getId()).isEqualTo("UUID"); @@ -177,7 +176,7 @@ public class TaskFormatterTest { CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED); String expected = "scanner context baby!"; - WsCe.Task wsTask = underTest.formatActivity(db.getSession(), dto, Optional.absent(), expected); + WsCe.Task wsTask = underTest.formatActivity(db.getSession(), dto, expected); assertThat(wsTask.hasScannerContext()).isTrue(); assertThat(wsTask.getScannerContext()).isEqualTo(expected); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java index 7b08a477f8b..931a9790968 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java @@ -19,25 +19,9 @@ */ package org.sonar.server.computation.queue; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.entry; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; -import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; -import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; -import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS; -import static org.sonar.db.permission.OrganizationPermission.SCAN; - import java.util.HashMap; +import java.util.List; import java.util.Map; - import org.apache.commons.io.IOUtils; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; @@ -56,6 +40,7 @@ import org.sonar.core.util.SequenceUuidFactory; import org.sonar.core.util.UuidFactory; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.ce.CeTaskCharacteristicDto; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; @@ -69,6 +54,22 @@ import org.sonar.server.favorite.FavoriteUpdater; import org.sonar.server.permission.PermissionTemplateService; import org.sonar.server.tester.UserSessionRule; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.argThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; +import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; +import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS; +import static org.sonar.db.permission.OrganizationPermission.SCAN; + public class ReportSubmitterTest { private static final String PROJECT_KEY = "MY_PROJECT"; @@ -140,8 +141,10 @@ public class ReportSubmitterTest { verify(queue).submit(submittedTask.capture()); String taskUuid = submittedTask.getValue().getUuid(); - Map insertedCharacteristics = db.getDbClient().ceTaskCharacteristicsDao().getTaskCharacteristics(db.getSession(), taskUuid); - assertThat(insertedCharacteristics).containsOnly(entry("incremental", "true"), entry("pr", "mypr")); + List insertedCharacteristics = db.getDbClient().ceTaskCharacteristicsDao().selectByTaskUuid(db.getSession(), taskUuid); + assertThat(insertedCharacteristics) + .extracting(CeTaskCharacteristicDto::getKey, CeTaskCharacteristicDto::getValue) + .containsOnly(tuple("incremental", "true"), tuple("pr", "mypr")); } @Test diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/ce/CeService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/ce/CeService.java index ad610ee4a04..c223da8dd3a 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/ce/CeService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/ce/CeService.java @@ -21,6 +21,7 @@ package org.sonarqube.ws.client.ce; import org.sonarqube.ws.WsCe; import org.sonarqube.ws.WsCe.ActivityResponse; +import org.sonarqube.ws.WsCe.ProjectResponse; import org.sonarqube.ws.WsCe.TaskTypesWsResponse; import org.sonarqube.ws.WsCe.WorkerCountResponse; import org.sonarqube.ws.client.BaseService; @@ -95,4 +96,11 @@ public class CeService extends BaseService { return call(new GetRequest(path(ACTION_WORKER_COUNT)), WorkerCountResponse.parser()); } + public ProjectResponse component(String componentKey) { + return call( + new GetRequest(path("component")) + .setParam(PARAM_COMPONENT_KEY, componentKey), + ProjectResponse.parser()); + } + } diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/ce/CeServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/ce/CeServiceTest.java index 16d443a7276..5e65034cd41 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/ce/CeServiceTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/ce/CeServiceTest.java @@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.data.MapEntry.entry; import static org.mockito.Mockito.mock; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_ID; +import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_KEY; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_MAX_EXECUTED_AT; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_MIN_SUBMITTED_AT; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_ONLY_CURRENTS; @@ -141,4 +142,16 @@ public class CeServiceTest { assertThat(serviceTester.getGetRequest().getPath()).isEqualTo("api/ce/worker_count"); assertThat(serviceTester.getGetParser()).isSameAs(WsCe.WorkerCountResponse.parser()); } + + @Test + public void component() { + underTest.component("my_component"); + GetRequest result = serviceTester.getGetRequest(); + + assertThat(serviceTester.getGetParser()).isSameAs(WsCe.ProjectResponse.parser()); + serviceTester.assertThat(result) + .hasPath("component") + .hasParam(PARAM_COMPONENT_KEY, "my_component") + .andNoOtherParam(); + } } -- 2.39.5