]> source.dussan.org Git - sonarqube.git/blob
2548ecd1b83a849490c07a9ae06c50178f35d9e5
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2021 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.measure.ws;
21
22 import java.util.List;
23 import java.util.stream.LongStream;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.junit.rules.ExpectedException;
28 import org.sonar.api.measures.Metric.ValueType;
29 import org.sonar.api.server.ws.WebService;
30 import org.sonar.api.server.ws.WebService.Param;
31 import org.sonar.api.utils.System2;
32 import org.sonar.api.web.UserRole;
33 import org.sonar.core.util.stream.MoreCollectors;
34 import org.sonar.db.DbClient;
35 import org.sonar.db.DbSession;
36 import org.sonar.db.DbTester;
37 import org.sonar.db.component.ComponentDto;
38 import org.sonar.db.component.SnapshotDto;
39 import org.sonar.db.measure.MeasureDto;
40 import org.sonar.db.metric.MetricDto;
41 import org.sonar.server.component.TestComponentFinder;
42 import org.sonar.server.exceptions.ForbiddenException;
43 import org.sonar.server.exceptions.NotFoundException;
44 import org.sonar.server.measure.ws.SearchHistoryAction.SearchHistoryRequest;
45 import org.sonar.server.tester.UserSessionRule;
46 import org.sonar.server.ws.TestRequest;
47 import org.sonar.server.ws.WsActionTester;
48 import org.sonarqube.ws.Common.Paging;
49 import org.sonarqube.ws.Measures.SearchHistoryResponse;
50 import org.sonarqube.ws.Measures.SearchHistoryResponse.HistoryMeasure;
51 import org.sonarqube.ws.Measures.SearchHistoryResponse.HistoryValue;
52
53 import static java.lang.Double.parseDouble;
54 import static java.lang.String.format;
55 import static java.util.Arrays.asList;
56 import static java.util.Collections.singletonList;
57 import static java.util.Optional.ofNullable;
58 import static org.assertj.core.api.Assertions.assertThat;
59 import static org.assertj.core.api.Assertions.tuple;
60 import static org.sonar.api.utils.DateUtils.formatDateTime;
61 import static org.sonar.api.utils.DateUtils.parseDateTime;
62 import static org.sonar.db.component.BranchType.PULL_REQUEST;
63 import static org.sonar.db.component.ComponentTesting.newFileDto;
64 import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
65 import static org.sonar.db.component.SnapshotDto.STATUS_UNPROCESSED;
66 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
67 import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
68 import static org.sonar.db.metric.MetricTesting.newMetricDto;
69 import static org.sonar.server.component.ws.MeasuresWsParameters.PARAM_BRANCH;
70 import static org.sonar.server.component.ws.MeasuresWsParameters.PARAM_COMPONENT;
71 import static org.sonar.server.component.ws.MeasuresWsParameters.PARAM_FROM;
72 import static org.sonar.server.component.ws.MeasuresWsParameters.PARAM_METRICS;
73 import static org.sonar.server.component.ws.MeasuresWsParameters.PARAM_PULL_REQUEST;
74 import static org.sonar.server.component.ws.MeasuresWsParameters.PARAM_TO;
75 import static org.sonar.test.JsonAssert.assertJson;
76
77 public class SearchHistoryActionTest {
78
79   @Rule
80   public UserSessionRule userSession = UserSessionRule.standalone();
81   @Rule
82   public ExpectedException expectedException = ExpectedException.none();
83   @Rule
84   public DbTester db = DbTester.create();
85
86   private final DbClient dbClient = db.getDbClient();
87   private final DbSession dbSession = db.getSession();
88
89   private final WsActionTester ws = new WsActionTester(new SearchHistoryAction(dbClient, TestComponentFinder.from(db), userSession));
90
91   private ComponentDto project;
92   private SnapshotDto analysis;
93   private MetricDto complexityMetric;
94   private MetricDto nclocMetric;
95   private MetricDto newViolationMetric;
96   private MetricDto stringMetric;
97
98   @Before
99   public void setUp() {
100     project = newPrivateProjectDto();
101     analysis = db.components().insertProjectAndSnapshot(project);
102     userSession.addProjectPermission(UserRole.USER, project);
103     nclocMetric = insertNclocMetric();
104     complexityMetric = insertComplexityMetric();
105     newViolationMetric = insertNewViolationMetric();
106     stringMetric = insertStringMetric();
107   }
108
109   @Test
110   public void empty_response() {
111     project = db.components().insertPrivateProject();
112     userSession.addProjectPermission(UserRole.USER, project);
113     SearchHistoryRequest request = SearchHistoryRequest.builder()
114       .setComponent(project.getDbKey())
115       .setMetrics(singletonList(complexityMetric.getKey()))
116       .build();
117
118     SearchHistoryResponse result = call(request);
119
120     assertThat(result.getMeasuresList()).hasSize(1);
121     assertThat(result.getMeasures(0).getHistoryCount()).isZero();
122
123     assertThat(result.getPaging()).extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal)
124       // pagination is applied to the number of analyses
125       .containsExactly(1, 100, 0);
126   }
127
128   @Test
129   public void analyses_but_no_measure() {
130     project = db.components().insertPrivateProject();
131     analysis = db.components().insertSnapshot(project);
132     userSession.addProjectPermission(UserRole.USER, project);
133
134     SearchHistoryRequest request = SearchHistoryRequest.builder()
135       .setComponent(project.getDbKey())
136       .setMetrics(singletonList(complexityMetric.getKey()))
137       .build();
138
139     SearchHistoryResponse result = call(request);
140
141     assertThat(result.getPaging()).extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal).containsExactly(1, 100, 1);
142     assertThat(result.getMeasuresList()).hasSize(1);
143     assertThat(result.getMeasures(0).getHistoryList()).extracting(HistoryValue::hasDate, HistoryValue::hasValue).containsExactly(tuple(true, false));
144   }
145
146   @Test
147   public void return_metrics() {
148     dbClient.measureDao().insert(dbSession, newMeasureDto(complexityMetric, project, analysis).setValue(42.0d));
149     db.commit();
150
151     SearchHistoryRequest request = SearchHistoryRequest.builder()
152       .setComponent(project.getDbKey())
153       .setMetrics(asList(complexityMetric.getKey(), nclocMetric.getKey(), newViolationMetric.getKey()))
154       .build();
155
156     SearchHistoryResponse result = call(request);
157
158     assertThat(result.getMeasuresList()).hasSize(3)
159       .extracting(HistoryMeasure::getMetric)
160       .containsExactly(complexityMetric.getKey(), nclocMetric.getKey(), newViolationMetric.getKey());
161   }
162
163   @Test
164   public void return_measures() {
165     SnapshotDto laterAnalysis = dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(analysis.getCreatedAt() + 42_000));
166     ComponentDto file = db.components().insertComponent(newFileDto(project));
167     dbClient.measureDao().insert(dbSession,
168       newMeasureDto(complexityMetric, project, analysis).setValue(101d),
169       newMeasureDto(complexityMetric, project, laterAnalysis).setValue(100d),
170       newMeasureDto(complexityMetric, file, analysis).setValue(42d),
171       newMeasureDto(nclocMetric, project, analysis).setValue(201d),
172       newMeasureDto(newViolationMetric, project, analysis).setVariation(5d),
173       newMeasureDto(newViolationMetric, project, laterAnalysis).setVariation(10d));
174     db.commit();
175
176     SearchHistoryRequest request = SearchHistoryRequest.builder()
177       .setComponent(project.getDbKey())
178       .setMetrics(asList(complexityMetric.getKey(), nclocMetric.getKey(), newViolationMetric.getKey()))
179       .build();
180     SearchHistoryResponse result = call(request);
181
182     assertThat(result.getPaging()).extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal)
183       .containsExactly(1, 100, 2);
184     assertThat(result.getMeasuresList()).extracting(HistoryMeasure::getMetric).hasSize(3)
185       .containsExactly(complexityMetric.getKey(), nclocMetric.getKey(), newViolationMetric.getKey());
186     String analysisDate = formatDateTime(analysis.getCreatedAt());
187     String laterAnalysisDate = formatDateTime(laterAnalysis.getCreatedAt());
188     // complexity measures
189     HistoryMeasure complexityMeasures = result.getMeasures(0);
190     assertThat(complexityMeasures.getMetric()).isEqualTo(complexityMetric.getKey());
191     assertThat(complexityMeasures.getHistoryList()).extracting(HistoryValue::getDate, HistoryValue::getValue)
192       .containsExactly(tuple(analysisDate, "101"), tuple(laterAnalysisDate, "100"));
193     // ncloc measures
194     HistoryMeasure nclocMeasures = result.getMeasures(1);
195     assertThat(nclocMeasures.getMetric()).isEqualTo(nclocMetric.getKey());
196     assertThat(nclocMeasures.getHistoryList()).extracting(HistoryValue::getDate, HistoryValue::getValue, HistoryValue::hasValue).containsExactly(
197       tuple(analysisDate, "201", true), tuple(laterAnalysisDate, "", false));
198     // new_violation measures
199     HistoryMeasure newViolationMeasures = result.getMeasures(2);
200     assertThat(newViolationMeasures.getMetric()).isEqualTo(newViolationMetric.getKey());
201     assertThat(newViolationMeasures.getHistoryList()).extracting(HistoryValue::getDate, HistoryValue::getValue)
202       .containsExactly(tuple(analysisDate, "5"), tuple(laterAnalysisDate, "10"));
203   }
204
205   @Test
206   public void pagination_applies_to_analyses() {
207     project = db.components().insertPrivateProject();
208     userSession.addProjectPermission(UserRole.USER, project);
209     List<String> analysisDates = LongStream.rangeClosed(1, 9)
210       .mapToObj(i -> dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(i * 1_000_000_000)))
211       .peek(a -> dbClient.measureDao().insert(dbSession, newMeasureDto(complexityMetric, project, a).setValue(101d)))
212       .map(a -> formatDateTime(a.getCreatedAt()))
213       .collect(MoreCollectors.toList());
214     db.commit();
215
216     SearchHistoryRequest request = SearchHistoryRequest.builder()
217       .setComponent(project.getDbKey())
218       .setMetrics(asList(complexityMetric.getKey(), nclocMetric.getKey(), newViolationMetric.getKey()))
219       .setPage(2)
220       .setPageSize(3)
221       .build();
222     SearchHistoryResponse result = call(request);
223
224     assertThat(result.getPaging()).extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal).containsExactly(2, 3, 9);
225     assertThat(result.getMeasures(0).getHistoryList()).extracting(HistoryValue::getDate).containsExactly(
226       analysisDates.get(3), analysisDates.get(4), analysisDates.get(5));
227   }
228
229   @Test
230   public void inclusive_from_and_to_dates() {
231     project = db.components().insertPrivateProject();
232     userSession.addProjectPermission(UserRole.USER, project);
233     List<String> analysisDates = LongStream.rangeClosed(1, 9)
234       .mapToObj(i -> dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(System2.INSTANCE.now() + i * 1_000_000_000L)))
235       .peek(a -> dbClient.measureDao().insert(dbSession, newMeasureDto(complexityMetric, project, a).setValue(Double.valueOf(a.getCreatedAt()))))
236       .map(a -> formatDateTime(a.getCreatedAt()))
237       .collect(MoreCollectors.toList());
238     db.commit();
239
240     SearchHistoryRequest request = SearchHistoryRequest.builder()
241       .setComponent(project.getDbKey())
242       .setMetrics(asList(complexityMetric.getKey(), nclocMetric.getKey(), newViolationMetric.getKey()))
243       .setFrom(analysisDates.get(1))
244       .setTo(analysisDates.get(3))
245       .build();
246     SearchHistoryResponse result = call(request);
247
248     assertThat(result.getPaging()).extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal).containsExactly(1, 100, 3);
249     assertThat(result.getMeasures(0).getHistoryList()).extracting(HistoryValue::getDate).containsExactly(
250       analysisDates.get(1), analysisDates.get(2), analysisDates.get(3));
251   }
252
253   @Test
254   public void return_best_values_for_files() {
255     dbClient.metricDao().insert(dbSession, newMetricDto().setKey("optimized").setValueType(ValueType.INT.name()).setOptimizedBestValue(true).setBestValue(456d));
256     dbClient.metricDao().insert(dbSession, newMetricDto().setKey("new_optimized").setValueType(ValueType.INT.name()).setOptimizedBestValue(true).setBestValue(789d));
257     db.commit();
258     ComponentDto file = db.components().insertComponent(newFileDto(project));
259
260     SearchHistoryRequest request = SearchHistoryRequest.builder()
261       .setComponent(file.getDbKey())
262       .setMetrics(asList("optimized", "new_optimized"))
263       .build();
264     SearchHistoryResponse result = call(request);
265
266     assertThat(result.getMeasuresCount()).isEqualTo(2);
267     assertThat(result.getMeasuresList().get(0).getHistoryList()).extracting(HistoryValue::getValue).containsExactly("789");
268     assertThat(result.getMeasuresList().get(1).getHistoryList()).extracting(HistoryValue::getValue).containsExactly("456");
269
270     // Best value is not applied to project
271     request = SearchHistoryRequest.builder()
272       .setComponent(project.getDbKey())
273       .setMetrics(asList("optimized", "new_optimized"))
274       .build();
275     result = call(request);
276     assertThat(result.getMeasuresList().get(0).getHistoryCount()).isEqualTo(1);
277     assertThat(result.getMeasuresList().get(0).getHistory(0).hasDate()).isTrue();
278     assertThat(result.getMeasuresList().get(0).getHistory(0).hasValue()).isFalse();
279   }
280
281   @Test
282   public void do_not_return_unprocessed_analyses() {
283     dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setStatus(STATUS_UNPROCESSED));
284     db.commit();
285
286     SearchHistoryRequest request = SearchHistoryRequest.builder()
287       .setComponent(project.getDbKey())
288       .setMetrics(asList(complexityMetric.getKey(), nclocMetric.getKey(), newViolationMetric.getKey()))
289       .build();
290     SearchHistoryResponse result = call(request);
291
292     // one analysis in setUp method
293     assertThat(result.getPaging().getTotal()).isEqualTo(1);
294   }
295
296   @Test
297   public void branch() {
298     ComponentDto project = db.components().insertPrivateProject();
299     userSession.addProjectPermission(UserRole.USER, project);
300     ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("my_branch"));
301     ComponentDto file = db.components().insertComponent(newFileDto(branch));
302     SnapshotDto analysis = db.components().insertSnapshot(branch);
303     MeasureDto measure = db.measures().insertMeasure(file, analysis, nclocMetric, m -> m.setValue(2d));
304
305     SearchHistoryResponse result = ws.newRequest()
306       .setParam(PARAM_COMPONENT, file.getKey())
307       .setParam(PARAM_BRANCH, "my_branch")
308       .setParam(PARAM_METRICS, "ncloc")
309       .executeProtobuf(SearchHistoryResponse.class);
310
311     assertThat(result.getMeasuresList()).extracting(HistoryMeasure::getMetric).hasSize(1);
312     HistoryMeasure historyMeasure = result.getMeasures(0);
313     assertThat(historyMeasure.getMetric()).isEqualTo(nclocMetric.getKey());
314     assertThat(historyMeasure.getHistoryList())
315       .extracting(m -> parseDouble(m.getValue()))
316       .containsExactlyInAnyOrder(measure.getValue());
317   }
318
319   @Test
320   public void pull_request() {
321     ComponentDto project = db.components().insertPrivateProject();
322     userSession.addProjectPermission(UserRole.USER, project);
323     ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("pr-123").setBranchType(PULL_REQUEST));
324     ComponentDto file = db.components().insertComponent(newFileDto(branch));
325     SnapshotDto analysis = db.components().insertSnapshot(branch);
326     MeasureDto measure = db.measures().insertMeasure(file, analysis, nclocMetric, m -> m.setValue(2d));
327
328     SearchHistoryResponse result = ws.newRequest()
329       .setParam(PARAM_COMPONENT, file.getKey())
330       .setParam(PARAM_PULL_REQUEST, "pr-123")
331       .setParam(PARAM_METRICS, "ncloc")
332       .executeProtobuf(SearchHistoryResponse.class);
333
334     assertThat(result.getMeasuresList()).extracting(HistoryMeasure::getMetric).hasSize(1);
335     HistoryMeasure historyMeasure = result.getMeasures(0);
336     assertThat(historyMeasure.getMetric()).isEqualTo(nclocMetric.getKey());
337     assertThat(historyMeasure.getHistoryList())
338       .extracting(m -> parseDouble(m.getValue()))
339       .containsExactlyInAnyOrder(measure.getValue());
340   }
341
342   @Test
343   public void fail_when_using_branch_db_key() {
344     ComponentDto project = db.components().insertPrivateProject();
345     userSession.logIn().addProjectPermission(UserRole.USER, project);
346     ComponentDto branch = db.components().insertProjectBranch(project);
347
348     expectedException.expect(NotFoundException.class);
349     expectedException.expectMessage(format("Component key '%s' not found", branch.getDbKey()));
350
351     ws.newRequest()
352       .setParam(PARAM_COMPONENT, branch.getDbKey())
353       .setParam(PARAM_METRICS, "ncloc")
354       .execute();
355   }
356
357   @Test
358   public void fail_if_unknown_metric() {
359     SearchHistoryRequest request = SearchHistoryRequest.builder()
360       .setComponent(project.getDbKey())
361       .setMetrics(asList(complexityMetric.getKey(), nclocMetric.getKey(), "METRIC_42", "42_METRIC"))
362       .build();
363
364     expectedException.expect(IllegalArgumentException.class);
365     expectedException.expectMessage("Metrics 42_METRIC, METRIC_42 are not found");
366
367     call(request);
368   }
369
370   @Test
371   public void fail_if_not_enough_permissions() {
372     userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
373     SearchHistoryRequest request = SearchHistoryRequest.builder()
374       .setComponent(project.getDbKey())
375       .setMetrics(singletonList(complexityMetric.getKey()))
376       .build();
377
378     expectedException.expect(ForbiddenException.class);
379
380     call(request);
381   }
382
383   @Test
384   public void fail_if_unknown_component() {
385     SearchHistoryRequest request = SearchHistoryRequest.builder()
386       .setComponent("__UNKNOWN__")
387       .setMetrics(singletonList(complexityMetric.getKey()))
388       .build();
389
390     expectedException.expect(NotFoundException.class);
391
392     call(request);
393   }
394
395   @Test
396   public void fail_when_component_is_removed() {
397     ComponentDto project = db.components().insertComponent(newPrivateProjectDto());
398     db.components().insertComponent(newFileDto(project).setDbKey("file-key").setEnabled(false));
399     userSession.addProjectPermission(UserRole.USER, project);
400
401     expectedException.expect(NotFoundException.class);
402     expectedException.expectMessage("Component key 'file-key' not found");
403
404     ws.newRequest()
405       .setParam(PARAM_COMPONENT, "file-key")
406       .setParam(PARAM_METRICS, "ncloc")
407       .execute();
408   }
409
410   @Test
411   public void fail_if_branch_does_not_exist() {
412     ComponentDto project = db.components().insertPrivateProject();
413     ComponentDto file = db.components().insertComponent(newFileDto(project));
414     userSession.addProjectPermission(UserRole.USER, project);
415     db.components().insertProjectBranch(project, b -> b.setKey("my_branch"));
416
417     expectedException.expect(NotFoundException.class);
418     expectedException.expectMessage(String.format("Component '%s' on branch '%s' not found", file.getKey(), "another_branch"));
419
420     ws.newRequest()
421       .setParam(PARAM_COMPONENT, file.getKey())
422       .setParam(PARAM_BRANCH, "another_branch")
423       .setParam(PARAM_METRICS, "ncloc")
424       .execute();
425   }
426
427   @Test
428   public void definition() {
429     WebService.Action definition = ws.getDef();
430
431     assertThat(definition.key()).isEqualTo("search_history");
432     assertThat(definition.responseExampleAsString()).isNotEmpty();
433     assertThat(definition.isPost()).isFalse();
434     assertThat(definition.isInternal()).isFalse();
435     assertThat(definition.since()).isEqualTo("6.3");
436     assertThat(definition.params()).hasSize(8);
437
438     Param branch = definition.param("branch");
439     assertThat(branch.since()).isEqualTo("6.6");
440     assertThat(branch.isInternal()).isFalse();
441     assertThat(branch.isRequired()).isFalse();
442   }
443
444   @Test
445   public void json_example() {
446     project = db.components().insertPrivateProject();
447     userSession.addProjectPermission(UserRole.USER, project);
448     long now = parseDateTime("2017-01-23T17:00:53+0100").getTime();
449     LongStream.rangeClosed(0, 2)
450       .mapToObj(i -> dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(now + i * 24 * 1_000 * 60 * 60)))
451       .forEach(analysis -> dbClient.measureDao().insert(dbSession,
452         newMeasureDto(complexityMetric, project, analysis).setValue(45d),
453         newMeasureDto(newViolationMetric, project, analysis).setVariation(46d),
454         newMeasureDto(nclocMetric, project, analysis).setValue(47d)));
455     db.commit();
456
457     String result = ws.newRequest()
458       .setParam(PARAM_COMPONENT, project.getDbKey())
459       .setParam(PARAM_METRICS, String.join(",", asList(complexityMetric.getKey(), nclocMetric.getKey(), newViolationMetric.getKey())))
460       .execute().getInput();
461
462     assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
463   }
464
465   @Test
466   public void measure_without_values() {
467     dbClient.measureDao().insert(dbSession, newMeasureDto(stringMetric, project, analysis).setValue(null).setData(null));
468     db.commit();
469
470     SearchHistoryRequest request = SearchHistoryRequest.builder()
471       .setComponent(project.getDbKey())
472       .setMetrics(singletonList(stringMetric.getKey()))
473       .build();
474     SearchHistoryResponse result = call(request);
475
476     HistoryMeasure measure = result.getMeasuresList().stream()
477       .filter(m -> m.getMetric().equals(stringMetric.getKey()))
478       .findFirst()
479       .get();
480     assertThat(measure.getHistoryList()).hasSize(1);
481     assertThat(measure.getHistory(0).hasValue()).isFalse();
482   }
483
484   private SearchHistoryResponse call(SearchHistoryRequest request) {
485     TestRequest testRequest = ws.newRequest();
486
487     testRequest.setParam(PARAM_COMPONENT, request.getComponent());
488     testRequest.setParam(PARAM_METRICS, String.join(",", request.getMetrics()));
489     ofNullable(request.getFrom()).ifPresent(from -> testRequest.setParam(PARAM_FROM, from));
490     ofNullable(request.getTo()).ifPresent(to -> testRequest.setParam(PARAM_TO, to));
491     ofNullable(request.getPage()).ifPresent(p -> testRequest.setParam(Param.PAGE, String.valueOf(p)));
492     ofNullable(request.getPageSize()).ifPresent(ps -> testRequest.setParam(Param.PAGE_SIZE, String.valueOf(ps)));
493
494     return testRequest.executeProtobuf(SearchHistoryResponse.class);
495   }
496
497   private static MetricDto newMetricDtoWithoutOptimization() {
498     return newMetricDto()
499       .setWorstValue(null)
500       .setOptimizedBestValue(false)
501       .setBestValue(null)
502       .setUserManaged(false);
503   }
504
505   private MetricDto insertNclocMetric() {
506     MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
507       .setKey("ncloc")
508       .setShortName("Lines of code")
509       .setDescription("Non Commenting Lines of Code")
510       .setDomain("Size")
511       .setValueType("INT")
512       .setDirection(-1)
513       .setQualitative(false)
514       .setHidden(false)
515       .setUserManaged(false));
516     db.commit();
517     return metric;
518   }
519
520   private MetricDto insertComplexityMetric() {
521     MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
522       .setKey("complexity")
523       .setShortName("Complexity")
524       .setDescription("Cyclomatic complexity")
525       .setDomain("Complexity")
526       .setValueType("INT")
527       .setDirection(-1)
528       .setQualitative(false)
529       .setHidden(false)
530       .setUserManaged(false));
531     db.commit();
532     return metric;
533   }
534
535   private MetricDto insertNewViolationMetric() {
536     MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
537       .setKey("new_violations")
538       .setShortName("New issues")
539       .setDescription("New Issues")
540       .setDomain("Issues")
541       .setValueType("INT")
542       .setDirection(-1)
543       .setQualitative(true)
544       .setHidden(false)
545       .setUserManaged(false));
546     db.commit();
547     return metric;
548   }
549
550   private MetricDto insertStringMetric() {
551     MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDtoWithoutOptimization()
552       .setKey("a_string")
553       .setShortName("A String")
554       .setValueType("STRING"));
555     db.commit();
556     return metric;
557   }
558 }