package org.sonar.server.measure.ws; | package org.sonar.server.measure.ws; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.function.Function; | |||||
import org.sonar.db.component.ComponentDto; | import org.sonar.db.component.ComponentDto; | ||||
import org.sonar.db.measure.MeasureDto; | import org.sonar.db.measure.MeasureDto; | ||||
import org.sonar.db.metric.MetricDto; | import org.sonar.db.metric.MetricDto; | ||||
import org.sonarqube.ws.WsMeasures; | |||||
import org.sonarqube.ws.WsMeasures.Component; | |||||
import org.sonarqube.ws.WsMeasures.SearchWsResponse; | |||||
import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.measureDtoToWsMeasure; | import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.measureDtoToWsMeasure; | ||||
// static methods only | // static methods only | ||||
} | } | ||||
static WsMeasures.Component.Builder componentDtoToWsComponent(ComponentDto component, Map<MetricDto, MeasureDto> measuresByMetric, | |||||
static Component.Builder componentDtoToWsComponent(ComponentDto component, Map<MetricDto, MeasureDto> measuresByMetric, | |||||
Map<String, ComponentDto> referenceComponentsByUuid) { | Map<String, ComponentDto> referenceComponentsByUuid) { | ||||
WsMeasures.Component.Builder wsComponent = componentDtoToWsComponent(component); | |||||
Component.Builder wsComponent = componentDtoToWsComponent(component); | |||||
ComponentDto referenceComponent = referenceComponentsByUuid.get(component.getCopyResourceUuid()); | ComponentDto referenceComponent = referenceComponentsByUuid.get(component.getCopyResourceUuid()); | ||||
if (referenceComponent != null) { | if (referenceComponent != null) { | ||||
return wsComponent; | return wsComponent; | ||||
} | } | ||||
static WsMeasures.Component dbToWsComponent(ComponentDto dbComponent, Iterable<WsMeasures.Measure> measures) { | |||||
return componentDtoToWsComponent(dbComponent).addAllMeasures(measures).build(); | |||||
static Function<ComponentDto, SearchWsResponse.Component> dbToWsComponent() { | |||||
return dbComponent -> SearchWsResponse.Component.newBuilder() | |||||
.setId(dbComponent.uuid()) | |||||
.setKey(dbComponent.key()) | |||||
.setName(dbComponent.name()) | |||||
.build(); | |||||
} | } | ||||
static WsMeasures.Component.Builder componentDtoToWsComponent(ComponentDto component) { | |||||
WsMeasures.Component.Builder wsComponent = WsMeasures.Component.newBuilder() | |||||
static Component.Builder componentDtoToWsComponent(ComponentDto component) { | |||||
Component.Builder wsComponent = Component.newBuilder() | |||||
.setId(component.uuid()) | .setId(component.uuid()) | ||||
.setKey(component.key()) | .setKey(component.key()) | ||||
.setName(component.name()) | .setName(component.name()) |
import org.sonar.db.measure.MeasureDto; | import org.sonar.db.measure.MeasureDto; | ||||
import org.sonar.db.metric.MetricDto; | import org.sonar.db.metric.MetricDto; | ||||
import org.sonarqube.ws.WsMeasures; | import org.sonarqube.ws.WsMeasures; | ||||
import org.sonarqube.ws.WsMeasures.Measure; | |||||
import static org.sonar.server.measure.ws.MeasureValueFormatter.formatMeasureValue; | import static org.sonar.server.measure.ws.MeasureValueFormatter.formatMeasureValue; | ||||
import static org.sonar.server.measure.ws.MeasureValueFormatter.formatNumericalValue; | import static org.sonar.server.measure.ws.MeasureValueFormatter.formatNumericalValue; | ||||
// static methods | // static methods | ||||
} | } | ||||
static WsMeasures.Measure measureDtoToWsMeasure(MetricDto metricDto, MeasureDto measureDto) { | |||||
/** | |||||
* @see #measureDtoToWsMeasure(MetricDto, MeasureDto) | |||||
* add component uuid to the WS Measure object | |||||
* | |||||
*/ | |||||
static Measure dbToWsMeasure(MeasureDto dbMeasure, MetricDto dbMetric) { | |||||
return map(dbMetric, dbMeasure).setComponent(dbMeasure.getComponentUuid()).build(); | |||||
} | |||||
static Measure measureDtoToWsMeasure(MetricDto metricDto, MeasureDto measureDto) { | |||||
return map(metricDto, measureDto).build(); | |||||
} | |||||
private static Measure.Builder map(MetricDto dbMetric, MeasureDto dbMeasure) { | |||||
try { | try { | ||||
WsMeasures.Measure.Builder measure = WsMeasures.Measure.newBuilder(); | |||||
measure.setMetric(metricDto.getKey()); | |||||
Measure.Builder measure = Measure.newBuilder(); | |||||
measure.setMetric(dbMetric.getKey()); | |||||
// a measure value can be null, new_violations metric for example | // a measure value can be null, new_violations metric for example | ||||
if (measureDto.getValue() != null | |||||
|| measureDto.getData() != null) { | |||||
measure.setValue(formatMeasureValue(measureDto, metricDto)); | |||||
if (dbMeasure.getValue() != null | |||||
|| dbMeasure.getData() != null) { | |||||
measure.setValue(formatMeasureValue(dbMeasure, dbMetric)); | |||||
} | } | ||||
WsMeasures.PeriodValue.Builder periodBuilder = WsMeasures.PeriodValue.newBuilder(); | WsMeasures.PeriodValue.Builder periodBuilder = WsMeasures.PeriodValue.newBuilder(); | ||||
for (int i = 1; i <= 5; i++) { | for (int i = 1; i <= 5; i++) { | ||||
if (measureDto.getVariation(i) != null) { | |||||
if (dbMeasure.getVariation(i) != null) { | |||||
measure.getPeriodsBuilder().addPeriodsValue(periodBuilder | measure.getPeriodsBuilder().addPeriodsValue(periodBuilder | ||||
.clear() | .clear() | ||||
.setIndex(i) | .setIndex(i) | ||||
.setValue(formatNumericalValue(measureDto.getVariation(i), metricDto))); | |||||
.setValue(formatNumericalValue(dbMeasure.getVariation(i), dbMetric))); | |||||
} | } | ||||
} | } | ||||
return measure.build(); | |||||
return measure; | |||||
} catch (Exception e) { | } catch (Exception e) { | ||||
throw new IllegalStateException(String.format("Error while mapping a measure of metric key '%s' and parameters %s", metricDto.getKey(), measureDto.toString()), e); | |||||
throw new IllegalStateException(String.format("Error while mapping a measure of metric key '%s' and parameters %s", dbMetric.getKey(), dbMeasure.toString()), e); | |||||
} | } | ||||
} | } | ||||
} | } |
import org.sonar.db.measure.MeasureQuery; | import org.sonar.db.measure.MeasureQuery; | ||||
import org.sonar.db.metric.MetricDto; | import org.sonar.db.metric.MetricDto; | ||||
import org.sonarqube.ws.WsMeasures; | import org.sonarqube.ws.WsMeasures; | ||||
import org.sonarqube.ws.WsMeasures.Measure; | |||||
import org.sonarqube.ws.WsMeasures.SearchWsResponse; | import org.sonarqube.ws.WsMeasures.SearchWsResponse; | ||||
import org.sonarqube.ws.WsMeasures.SearchWsResponse.Component; | |||||
import org.sonarqube.ws.client.measure.SearchRequest; | import org.sonarqube.ws.client.measure.SearchRequest; | ||||
import static com.google.common.base.Preconditions.checkArgument; | import static com.google.common.base.Preconditions.checkArgument; | ||||
import static com.google.common.collect.Maps.immutableEntry; | |||||
import static java.util.Comparator.comparing; | |||||
import static java.util.Objects.requireNonNull; | import static java.util.Objects.requireNonNull; | ||||
import static java.util.function.Function.identity; | import static java.util.function.Function.identity; | ||||
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; | import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; | ||||
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02; | import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02; | ||||
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03; | import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03; | ||||
import static org.sonar.server.measure.ws.ComponentDtoToWsComponent.dbToWsComponent; | import static org.sonar.server.measure.ws.ComponentDtoToWsComponent.dbToWsComponent; | ||||
import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.measureDtoToWsMeasure; | |||||
import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.dbToWsMeasure; | |||||
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; | import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter; | ||||
import static org.sonar.server.measure.ws.MetricDtoWithBestValue.buildBestMeasure; | import static org.sonar.server.measure.ws.MetricDtoWithBestValue.buildBestMeasure; | ||||
import static org.sonar.server.measure.ws.MetricDtoWithBestValue.isEligibleForBestValue; | import static org.sonar.server.measure.ws.MetricDtoWithBestValue.isEligibleForBestValue; | ||||
} | } | ||||
SearchWsResponse build() { | SearchWsResponse build() { | ||||
this.request = setRequest(); | |||||
this.request = createRequest(); | |||||
this.components = searchComponents(); | this.components = searchComponents(); | ||||
this.metrics = searchMetrics(); | this.metrics = searchMetrics(); | ||||
this.measures = searchMeasures(); | this.measures = searchMeasures(); | ||||
return dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids); | return dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids); | ||||
} | } | ||||
private SearchRequest setRequest() { | |||||
private SearchRequest createRequest() { | |||||
request = SearchRequest.builder() | request = SearchRequest.builder() | ||||
.setMetricKeys(httpRequest.mandatoryParamAsStrings(PARAM_METRIC_KEYS)) | .setMetricKeys(httpRequest.mandatoryParamAsStrings(PARAM_METRIC_KEYS)) | ||||
.setComponentIds(httpRequest.paramAsStrings(PARAM_COMPONENT_IDS)) | .setComponentIds(httpRequest.paramAsStrings(PARAM_COMPONENT_IDS)) | ||||
.setComponentKeys(httpRequest.paramAsStrings(PARAM_COMPONENT_KEYS)) | .setComponentKeys(httpRequest.paramAsStrings(PARAM_COMPONENT_KEYS)) | ||||
.build(); | .build(); | ||||
this.components = searchComponents(); | |||||
this.metrics = searchMetrics(); | |||||
return request; | return request; | ||||
} | } | ||||
requireNonNull(components); | requireNonNull(components); | ||||
requireNonNull(metrics); | requireNonNull(metrics); | ||||
Set<String> projectUuids = components.stream().map(ComponentDto::projectUuid).collect(Collectors.toSet()); | |||||
dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids).stream() | |||||
.map(SnapshotDtoToWsPeriods::snapshotToWsPeriods); | |||||
return dbClient.measureDao().selectByQuery(dbSession, MeasureQuery.builder() | return dbClient.measureDao().selectByQuery(dbSession, MeasureQuery.builder() | ||||
.setComponentUuids(components.stream().map(ComponentDto::uuid).collect(Collectors.toList())) | .setComponentUuids(components.stream().map(ComponentDto::uuid).collect(Collectors.toList())) | ||||
.setMetricIds(metrics.stream().map(MetricDto::getId).collect(Collectors.toList())) | .setMetricIds(metrics.stream().map(MetricDto::getId).collect(Collectors.toList())) | ||||
requireNonNull(components); | requireNonNull(components); | ||||
requireNonNull(snapshots); | requireNonNull(snapshots); | ||||
Map<Integer, MetricDto> metricsById = metrics.stream().collect(Collectors.toMap(MetricDto::getId, identity())); | |||||
List<Measure> wsMeasures = buildWsMeasures(); | |||||
List<Component> wsComponents = buildWsComponents(); | |||||
ImmutableMultimap<String, WsMeasures.Measure> wsMeasuresByComponentUuid = Stream | |||||
.concat(measures.stream(), buildBestMeasures().stream()) | |||||
.collect(Collectors.toMap(identity(), MeasureDto::getComponentUuid)) | |||||
.entrySet().stream() | |||||
.map(entry -> immutableEntry( | |||||
measureDtoToWsMeasure(metricsById.get(entry.getKey().getMetricId()), entry.getKey()), | |||||
entry.getValue())) | |||||
.sorted((e1, e2) -> e1.getKey().getMetric().compareTo(e2.getKey().getMetric())) | |||||
.collect(Collector.of( | |||||
ImmutableMultimap::<String, WsMeasures.Measure>builder, | |||||
(result, entry) -> result.put(entry.getValue(), entry.getKey()), | |||||
(result1, result2) -> { | |||||
throw new IllegalStateException("Parallel execution forbidden while building WS measures"); | |||||
}, | |||||
ImmutableMultimap.Builder::build)); | |||||
return SearchWsResponse.newBuilder() | |||||
.addAllMeasures(wsMeasures) | |||||
.addAllComponents(wsComponents) | |||||
.build(); | |||||
} | |||||
private List<Component> buildWsComponents() { | |||||
return components.stream() | return components.stream() | ||||
.map(dbComponent -> dbToWsComponent(dbComponent, wsMeasuresByComponentUuid.get(dbComponent.uuid()))) | |||||
.sorted((c1, c2) -> c1.getName().compareTo(c2.getName())) | |||||
.collect(Collector.of( | |||||
SearchWsResponse::newBuilder, | |||||
SearchWsResponse.Builder::addComponents, | |||||
(result1, result2) -> { | |||||
throw new IllegalStateException("Parallel execution forbidden while building SearchWsResponse"); | |||||
}, | |||||
SearchWsResponse.Builder::build)); | |||||
.map(dbToWsComponent()) | |||||
.sorted(comparing(Component::getName)) | |||||
.collect(Collectors.toList()); | |||||
} | |||||
private List<Measure> buildWsMeasures() { | |||||
Map<String, String> componentNamesByUuid = components.stream().collect(Collectors.toMap(ComponentDto::uuid, ComponentDto::name)); | |||||
Map<Integer, MetricDto> metricsById = metrics.stream().collect(Collectors.toMap(MetricDto::getId, identity())); | |||||
Function<MeasureDto, MetricDto> dbMeasureToDbMetric = dbMeasure -> metricsById.get(dbMeasure.getMetricId()); | |||||
Function<Measure, String> byMetricKey = Measure::getMetric; | |||||
Function<Measure, String> byComponentName = wsMeasure -> componentNamesByUuid.get(wsMeasure.getComponent()); | |||||
return Stream | |||||
.concat(measures.stream(), buildBestMeasures().stream()) | |||||
.map(dbMeasure -> dbToWsMeasure(dbMeasure, dbMeasureToDbMetric.apply(dbMeasure))) | |||||
.sorted(comparing(byMetricKey).thenComparing(byComponentName)) | |||||
.collect(Collectors.toList()); | |||||
} | } | ||||
private List<MeasureDto> buildBestMeasures() { | private List<MeasureDto> buildBestMeasures() { |
{ | { | ||||
"components": [ | |||||
"measures": [ | |||||
{ | { | ||||
"id": "AVIwDXE-bJbJqrw6wFv5", | |||||
"key": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl/ElementImpl.java", | |||||
"name": "ElementImpl.java", | |||||
"qualifier": "FIL", | |||||
"path": "src/main/java/com/sonarsource/markdown/impl/ElementImpl.java", | |||||
"language": "java", | |||||
"measures": [ | |||||
"metric": "complexity", | |||||
"component": "AVIwDXE-bJbJqrw6wFv5", | |||||
"value": "12" | |||||
}, | |||||
{ | |||||
"metric": "complexity", | |||||
"component": "project-id", | |||||
"value": "42" | |||||
}, | |||||
{ | |||||
"metric": "complexity", | |||||
"component": "AVIwDXE-bJbJqrw6wFv8", | |||||
"value": "35", | |||||
"periods": [ | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
} | |||||
] | |||||
}, | |||||
{ | |||||
"metric": "ncloc", | |||||
"component": "AVIwDXE-bJbJqrw6wFv5", | |||||
"value": "114" | |||||
}, | |||||
{ | |||||
"metric": "ncloc", | |||||
"component": "project-id", | |||||
"value": "1984" | |||||
}, | |||||
{ | |||||
"metric": "ncloc", | |||||
"component": "AVIwDXE-bJbJqrw6wFv8", | |||||
"value": "217", | |||||
"periods": [ | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
} | |||||
] | |||||
}, | |||||
{ | |||||
"metric": "new_violations", | |||||
"component": "AVIwDXE-bJbJqrw6wFv5", | |||||
"periods": [ | |||||
{ | { | ||||
"metric": "complexity", | |||||
"value": "12" | |||||
"index": 1, | |||||
"value": "25" | |||||
}, | }, | ||||
{ | { | ||||
"metric": "ncloc", | |||||
"value": "114" | |||||
"index": 2, | |||||
"value": "0" | |||||
}, | }, | ||||
{ | { | ||||
"metric": "new_violations", | |||||
"periods": [ | |||||
{ | |||||
"index": 1, | |||||
"value": "25" | |||||
}, | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
}, | |||||
{ | |||||
"index": 3, | |||||
"value": "25" | |||||
} | |||||
] | |||||
"index": 3, | |||||
"value": "25" | |||||
} | } | ||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"id": "AVIwDXE_bJbJqrw6wFwJ", | |||||
"key": "com.sonarsource:java-markdown:src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java", | |||||
"name": "ElementImplTest.java", | |||||
"qualifier": "UTS", | |||||
"path": "src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java", | |||||
"language": "java", | |||||
"measures": [ | |||||
"metric": "new_violations", | |||||
"component": "AVIwDXE_bJbJqrw6wFwJ", | |||||
"periods": [ | |||||
{ | |||||
"index": 1, | |||||
"value": "0" | |||||
}, | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
}, | |||||
{ | { | ||||
"metric": "new_violations", | |||||
"periods": [ | |||||
{ | |||||
"index": 1, | |||||
"value": "0" | |||||
}, | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
}, | |||||
{ | |||||
"index": 3, | |||||
"value": "0" | |||||
} | |||||
] | |||||
"index": 3, | |||||
"value": "0" | |||||
} | } | ||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"id": "project-id", | |||||
"key": "MY_PROJECT", | |||||
"name": "My Project", | |||||
"description": "My Project Description", | |||||
"qualifier": "TRK", | |||||
"measures": [ | |||||
"metric": "new_violations", | |||||
"component": "project-id", | |||||
"periods": [ | |||||
{ | { | ||||
"metric": "complexity", | |||||
"value": "42" | |||||
"index": 1, | |||||
"value": "255" | |||||
}, | }, | ||||
{ | { | ||||
"metric": "ncloc", | |||||
"value": "1984" | |||||
"index": 2, | |||||
"value": "0" | |||||
}, | }, | ||||
{ | { | ||||
"metric": "new_violations", | |||||
"periods": [ | |||||
{ | |||||
"index": 1, | |||||
"value": "255" | |||||
}, | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
}, | |||||
{ | |||||
"index": 3, | |||||
"value": "255" | |||||
} | |||||
] | |||||
"index": 3, | |||||
"value": "255" | |||||
} | } | ||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"id": "AVIwDXE-bJbJqrw6wFv8", | |||||
"key": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl", | |||||
"name": "src/main/java/com/sonarsource/markdown/impl", | |||||
"qualifier": "DIR", | |||||
"path": "src/main/java/com/sonarsource/markdown/impl", | |||||
"measures": [ | |||||
"metric": "new_violations", | |||||
"component": "AVIwDXE-bJbJqrw6wFv8", | |||||
"periods": [ | |||||
{ | { | ||||
"metric": "complexity", | |||||
"value": "35", | |||||
"periods": [ | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
} | |||||
] | |||||
"index": 1, | |||||
"value": "25" | |||||
}, | }, | ||||
{ | { | ||||
"metric": "ncloc", | |||||
"value": "217", | |||||
"periods": [ | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
} | |||||
] | |||||
"index": 2, | |||||
"value": "0" | |||||
}, | }, | ||||
{ | { | ||||
"metric": "new_violations", | |||||
"periods": [ | |||||
{ | |||||
"index": 1, | |||||
"value": "25" | |||||
}, | |||||
{ | |||||
"index": 2, | |||||
"value": "0" | |||||
}, | |||||
{ | |||||
"index": 3, | |||||
"value": "25" | |||||
} | |||||
] | |||||
"index": 3, | |||||
"value": "25" | |||||
} | } | ||||
] | ] | ||||
} | } | ||||
], | |||||
"components": [ | |||||
{ | |||||
"id": "AVIwDXE-bJbJqrw6wFv5", | |||||
"key": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl/ElementImpl.java", | |||||
"name": "ElementImpl.java" | |||||
}, | |||||
{ | |||||
"id": "AVIwDXE_bJbJqrw6wFwJ", | |||||
"key": "com.sonarsource:java-markdown:src/test/java/com/sonarsource/markdown/impl/ElementImplTest.java", | |||||
"name": "ElementImplTest.java" | |||||
}, | |||||
{ | |||||
"id": "project-id", | |||||
"key": "MY_PROJECT", | |||||
"name": "My Project" | |||||
}, | |||||
{ | |||||
"id": "AVIwDXE-bJbJqrw6wFv8", | |||||
"key": "com.sonarsource:java-markdown:src/main/java/com/sonarsource/markdown/impl", | |||||
"name": "src/main/java/com/sonarsource/markdown/impl" | |||||
} | |||||
] | ] | ||||
} | } |
import org.sonar.server.exceptions.BadRequestException; | import org.sonar.server.exceptions.BadRequestException; | ||||
import org.sonar.server.ws.TestRequest; | import org.sonar.server.ws.TestRequest; | ||||
import org.sonar.server.ws.WsActionTester; | import org.sonar.server.ws.WsActionTester; | ||||
import org.sonarqube.ws.WsMeasures; | |||||
import org.sonarqube.ws.WsMeasures.Component; | |||||
import org.sonarqube.ws.WsMeasures.Measure; | |||||
import org.sonarqube.ws.WsMeasures.SearchWsResponse; | import org.sonarqube.ws.WsMeasures.SearchWsResponse; | ||||
import static com.google.common.collect.Lists.newArrayList; | import static com.google.common.collect.Lists.newArrayList; | ||||
.getInput(); | .getInput(); | ||||
assertJson(result).withStrictArrayOrder().isSimilarTo(ws.getDef().responseExampleAsString()); | assertJson(result).withStrictArrayOrder().isSimilarTo(ws.getDef().responseExampleAsString()); | ||||
} | } | ||||
@Test | @Test | ||||
SearchWsResponse result = callByComponentUuids(singletonList(dbComponent.uuid()), singletonList("complexity")); | SearchWsResponse result = callByComponentUuids(singletonList(dbComponent.uuid()), singletonList("complexity")); | ||||
assertThat(result.getComponentsCount()).isEqualTo(1); | assertThat(result.getComponentsCount()).isEqualTo(1); | ||||
Component wsComponent = result.getComponents(0); | |||||
assertThat(wsComponent.getMeasuresCount()).isEqualTo(0); | |||||
SearchWsResponse.Component wsComponent = result.getComponents(0); | |||||
assertThat(wsComponent.getId()).isEqualTo(dbComponent.uuid()); | assertThat(wsComponent.getId()).isEqualTo(dbComponent.uuid()); | ||||
assertThat(wsComponent.getKey()).isEqualTo(dbComponent.key()); | assertThat(wsComponent.getKey()).isEqualTo(dbComponent.key()); | ||||
assertThat(wsComponent.getQualifier()).isEqualTo(dbComponent.qualifier()); | |||||
assertThat(wsComponent.getName()).isEqualTo(dbComponent.name()); | assertThat(wsComponent.getName()).isEqualTo(dbComponent.name()); | ||||
assertThat(wsComponent.getDescription()).isEqualTo(dbComponent.description()); | |||||
assertThat(wsComponent.getProjectId()).isEqualTo(""); | |||||
assertThat(wsComponent.getLanguage()).isEqualTo(""); | |||||
assertThat(wsComponent.getPath()).isEqualTo(""); | |||||
assertThat(wsComponent.getRefId()).isEqualTo(""); | |||||
assertThat(wsComponent.getRefKey()).isEqualTo(""); | |||||
} | |||||
@Test | |||||
public void search_by_component_uuid() { | |||||
ComponentDto project = componentDb.insertProject(); | |||||
insertComplexityMetric(); | |||||
SearchWsResponse result = callByComponentUuids(singletonList(project.uuid()), singletonList("complexity")); | |||||
assertThat(result.getComponentsCount()).isEqualTo(1); | |||||
assertThat(result.getComponents(0).getId()).isEqualTo(project.uuid()); | |||||
} | } | ||||
@Test | @Test | ||||
SearchWsResponse result = callByComponentUuids(newArrayList(directoryDto.uuid(), file.uuid()), newArrayList("ncloc", "coverage", "new_violations")); | SearchWsResponse result = callByComponentUuids(newArrayList(directoryDto.uuid(), file.uuid()), newArrayList("ncloc", "coverage", "new_violations")); | ||||
// directory is not eligible for best value | // directory is not eligible for best value | ||||
assertThat(result.getComponentsList().get(0).getMeasuresList()).extracting("metric").containsOnly("coverage"); | |||||
assertThat(result.getMeasuresList().stream() | |||||
.filter(measure -> directoryDto.uuid().equals(measure.getComponent())) | |||||
.map(Measure::getMetric)) | |||||
.containsOnly("coverage"); | |||||
// file measures | // file measures | ||||
List<WsMeasures.Measure> fileMeasures = result.getComponentsList().get(1).getMeasuresList(); | |||||
assertThat(fileMeasures).extracting("metric").containsOnly("ncloc", "coverage", "new_violations"); | |||||
assertThat(fileMeasures).extracting("value").containsOnly("100", "15.5", ""); | |||||
List<Measure> fileMeasures = result.getMeasuresList().stream().filter(measure -> file.uuid().equals(measure.getComponent())).collect(Collectors.toList()); | |||||
assertThat(fileMeasures).extracting(Measure::getMetric).containsOnly("ncloc", "coverage", "new_violations"); | |||||
assertThat(fileMeasures).extracting(Measure::getValue).containsOnly("100", "15.5", ""); | |||||
} | } | ||||
@Test | @Test |
// WS api/measures/search | // WS api/measures/search | ||||
message SearchWsResponse { | message SearchWsResponse { | ||||
repeated Component components = 1; | |||||
repeated Measure measures = 1; | |||||
repeated Component components = 2; | |||||
message Component { | |||||
optional string id = 1; | |||||
optional string key = 2; | |||||
optional string name = 3; | |||||
} | |||||
} | } | ||||
message Component { | message Component { | ||||
optional string id = 1; | optional string id = 1; | ||||
optional string key = 2; | optional string key = 2; | ||||
optional string refId = 3; | |||||
optional string refKey = 4; | |||||
optional string projectId = 5; | |||||
optional string name = 6; | |||||
optional string name = 3; | |||||
optional string refId = 4; | |||||
optional string refKey = 5; | |||||
optional string projectId = 6; | |||||
optional string description = 7; | optional string description = 7; | ||||
optional string qualifier = 8; | optional string qualifier = 8; | ||||
optional string path = 9; | optional string path = 9; | ||||
message Measure { | message Measure { | ||||
optional string metric = 1; | optional string metric = 1; | ||||
optional string value = 2; | |||||
optional PeriodsValue periods = 3; | |||||
optional string component = 2; | |||||
optional string value = 3; | |||||
optional PeriodsValue periods = 4; | |||||
} | } | ||||
message PeriodsValue { | message PeriodsValue { |