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