action.createParam(PARAM_FROM)
.setDescription("Filter measures created after the given date (inclusive). Format: date or datetime ISO formats")
- .setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)");
+ .setExampleValue("2013-05-01T13:00:00+0100");
action.createParam(PARAM_TO)
- .setDescription("Filter issues created before the given date (inclusive). Format: date or datetime ISO formats")
- .setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)");
+ .setDescription("Filter measures created before the given date (inclusive). Format: date or datetime ISO formats")
+ .setExampleValue("2013-05-01");
action.addPagingParams(DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
}
import java.util.EnumSet;
import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Stream;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
import org.sonar.api.server.ws.Request;
import org.sonarqube.ws.client.projectanalysis.SearchRequest;
import static com.google.common.base.Preconditions.checkArgument;
-import static org.sonar.core.util.stream.MoreCollectors.toOneElement;
+import static org.sonar.api.utils.DateUtils.parseEndingDateOrDateTime;
+import static org.sonar.api.utils.DateUtils.parseStartingDateOrDateTime;
+import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE;
import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.projectanalysis.EventCategory.OTHER;
import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_CATEGORY;
+import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_FROM;
import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_PROJECT;
+import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_TO;
import static org.sonarqube.ws.client.projectanalysis.SearchRequest.DEFAULT_PAGE_SIZE;
public class SearchAction implements ProjectAnalysesWsAction {
.setDescription("Event category. Filter analyses that have at least one event of the category specified.")
.setPossibleValues(EnumSet.allOf(EventCategory.class))
.setExampleValue(OTHER.name());
+
+ action.createParam(PARAM_FROM)
+ .setDescription("Filter analyses created after the given date (inclusive). Format: date or datetime ISO formats")
+ .setExampleValue("2013-05-01")
+ .setSince("6.5");
+
+ action.createParam(PARAM_TO)
+ .setDescription("Filter analyses created before the given date (inclusive). Format: date or datetime ISO formats")
+ .setExampleValue("2013-05-01T13:00:00+0100")
+ .setSince("6.5");
}
@Override
public void handle(Request request, Response response) throws Exception {
- ProjectAnalyses.SearchResponse searchResponse = Stream.of(request)
- .map(toWsRequest())
- .map(this::search)
- .map(new SearchResponseBuilder().buildWsResponse())
- .collect(toOneElement());
+ SearchData searchData = load(toWsRequest(request));
+ ProjectAnalyses.SearchResponse searchResponse = new SearchResponseBuilder(searchData).build();
writeProtobuf(searchResponse, request, response);
}
- private static Function<Request, SearchRequest> toWsRequest() {
- return request -> {
- String category = request.param(PARAM_CATEGORY);
- return SearchRequest.builder()
- .setProject(request.mandatoryParam(PARAM_PROJECT))
- .setCategory(category == null ? null : EventCategory.valueOf(category))
- .setPage(request.mandatoryParamAsInt(Param.PAGE))
- .setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
- .build();
- };
+ private static SearchRequest toWsRequest(Request request) {
+ String category = request.param(PARAM_CATEGORY);
+ return SearchRequest.builder()
+ .setProject(request.mandatoryParam(PARAM_PROJECT))
+ .setCategory(category == null ? null : EventCategory.valueOf(category))
+ .setPage(request.mandatoryParamAsInt(Param.PAGE))
+ .setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
+ .setFrom(request.param(PARAM_FROM))
+ .setTo(request.param(PARAM_TO))
+ .build();
}
- private SearchResults search(SearchRequest request) {
+ private SearchData load(SearchRequest request) {
try (DbSession dbSession = dbClient.openSession(false)) {
- return Stream.of(SearchResults.builder(dbSession, request))
- .peek(addProject())
- .peek(checkPermission())
- .peek(addAnalyses())
- .peek(addEvents())
- .map(SearchResults.Builder::build)
- .collect(toOneElement());
+ SearchData.Builder searchResults = SearchData.builder(dbSession, request);
+ addProject(searchResults);
+ checkPermission(searchResults.getProject());
+ addAnalyses(searchResults);
+ addEvents(searchResults);
+ return searchResults.build();
}
}
- private Consumer<SearchResults.Builder> addAnalyses() {
- return data -> {
- SnapshotQuery dbQuery = new SnapshotQuery()
- .setComponentUuid(data.getProject().uuid())
- .setStatus(SnapshotDto.STATUS_PROCESSED)
- .setSort(BY_DATE, DESC);
- data.setAnalyses(dbClient.snapshotDao().selectAnalysesByQuery(data.getDbSession(), dbQuery));
- };
+ private void addAnalyses(SearchData.Builder data) {
+ SnapshotQuery dbQuery = new SnapshotQuery()
+ .setComponentUuid(data.getProject().uuid())
+ .setStatus(SnapshotDto.STATUS_PROCESSED)
+ .setSort(BY_DATE, DESC);
+ setNullable(data.getRequest().getFrom(), from -> dbQuery.setCreatedAfter(parseStartingDateOrDateTime(from).getTime()));
+ setNullable(data.getRequest().getTo(), to -> dbQuery.setCreatedBefore(parseEndingDateOrDateTime(to).getTime() + 1_000L));
+ data.setAnalyses(dbClient.snapshotDao().selectAnalysesByQuery(data.getDbSession(), dbQuery));
}
- private Consumer<SearchResults.Builder> addEvents() {
- return data -> {
- List<String> analyses = data.getAnalyses().stream().map(SnapshotDto::getUuid).collect(MoreCollectors.toList());
- data.setEvents(dbClient.eventDao().selectByAnalysisUuids(data.getDbSession(), analyses));
- };
+ private void addEvents(SearchData.Builder data) {
+ List<String> analyses = data.getAnalyses().stream().map(SnapshotDto::getUuid).collect(MoreCollectors.toList());
+ data.setEvents(dbClient.eventDao().selectByAnalysisUuids(data.getDbSession(), analyses));
}
- private Consumer<SearchResults.Builder> checkPermission() {
- return data -> userSession.checkComponentPermission(UserRole.USER, data.getProject());
+ private void checkPermission(ComponentDto project) {
+ userSession.checkComponentPermission(UserRole.USER, project);
}
- private Consumer<SearchResults.Builder> addProject() {
- return data -> {
- ComponentDto project = componentFinder.getByKey(data.getDbSession(), data.getRequest().getProject());
- checkArgument(Scopes.PROJECT.equals(project.scope()) && Qualifiers.PROJECT.equals(project.qualifier()), "A project is required");
- data.setProject(project);
- };
+ private void addProject(SearchData.Builder data) {
+ ComponentDto project = componentFinder.getByKey(data.getDbSession(), data.getRequest().getProject());
+ checkArgument(Scopes.PROJECT.equals(project.scope()) && Qualifiers.PROJECT.equals(project.qualifier()), "A project is required");
+ data.setProject(project);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.projectanalysis.ws;
+
+import com.google.common.collect.ListMultimap;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.sonar.api.utils.Paging;
+import org.sonar.core.util.stream.MoreCollectors;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.event.EventDto;
+import org.sonarqube.ws.client.projectanalysis.SearchRequest;
+
+import static java.util.Objects.requireNonNull;
+
+class SearchData {
+ final List<SnapshotDto> analyses;
+ final ListMultimap<String, EventDto> eventsByAnalysis;
+ final Paging paging;
+
+ private SearchData(Builder builder) {
+ this.analyses = builder.analyses;
+ this.eventsByAnalysis = buildEvents(builder.events);
+ this.paging = Paging
+ .forPageIndex(builder.getRequest().getPage())
+ .withPageSize(builder.getRequest().getPageSize())
+ .andTotal(builder.countAnalyses);
+ }
+
+ private ListMultimap<String, EventDto> buildEvents(List<EventDto> events) {
+ return events.stream().collect(MoreCollectors.index(EventDto::getAnalysisUuid));
+ }
+
+ static Builder builder(DbSession dbSession, SearchRequest request) {
+ return new Builder(dbSession, request);
+ }
+
+ static class Builder {
+ private final DbSession dbSession;
+ private final SearchRequest request;
+ private ComponentDto project;
+ private List<SnapshotDto> analyses;
+ private int countAnalyses;
+ private List<EventDto> events;
+
+ private Builder(DbSession dbSession, SearchRequest request) {
+ this.dbSession = dbSession;
+ this.request = request;
+ }
+
+ Builder setProject(ComponentDto project) {
+ this.project = project;
+ return this;
+ }
+
+ Builder setAnalyses(List<SnapshotDto> analyses) {
+ Stream<SnapshotDto> stream = analyses.stream();
+ // no filter by category, the pagination can be applied
+ if (request.getCategory() == null) {
+ stream = stream
+ .skip(Paging.offset(request.getPage(), request.getPageSize()))
+ .limit(request.getPageSize());
+ }
+
+ this.analyses = stream.collect(MoreCollectors.toList());
+ this.countAnalyses = analyses.size();
+ return this;
+ }
+
+ Builder setEvents(List<EventDto> events) {
+ this.events = events;
+ return this;
+ }
+
+ DbSession getDbSession() {
+ return dbSession;
+ }
+
+ SearchRequest getRequest() {
+ return request;
+ }
+
+ ComponentDto getProject() {
+ return project;
+ }
+
+ List<SnapshotDto> getAnalyses() {
+ return analyses;
+ }
+
+ private void filterByCategory() {
+ ListMultimap<String, String> eventCategoriesByAnalysisUuid = events.stream()
+ .collect(MoreCollectors.index(EventDto::getAnalysisUuid, EventDto::getCategory));
+ Predicate<SnapshotDto> byCategory = a -> eventCategoriesByAnalysisUuid.get(a.getUuid()).contains(request.getCategory().getLabel());
+ this.countAnalyses = (int) analyses.stream().filter(byCategory).count();
+ this.analyses = analyses.stream()
+ .filter(byCategory)
+ .skip(Paging.offset(request.getPage(), request.getPageSize()))
+ .limit(request.getPageSize())
+ .collect(MoreCollectors.toList());
+ }
+
+ SearchData build() {
+ requireNonNull(analyses);
+ requireNonNull(events);
+ if (request.getCategory() != null) {
+ filterByCategory();
+ }
+ return new SearchData(this);
+ }
+ }
+}
*/
package org.sonar.server.projectanalysis.ws;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Stream;
-import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.event.EventDto;
import org.sonarqube.ws.ProjectAnalyses.Analysis;
import static org.sonarqube.ws.client.projectanalysis.EventCategory.fromLabel;
class SearchResponseBuilder {
- private final Analysis.Builder analysisBuilder;
- private final Event.Builder eventBuilder;
+ private final Analysis.Builder wsAnalysis;
+ private final Event.Builder wsEvent;
+ private final SearchData searchData;
- SearchResponseBuilder() {
- this.analysisBuilder = Analysis.newBuilder();
- this.eventBuilder = Event.newBuilder();
+ SearchResponseBuilder(SearchData searchData) {
+ this.wsAnalysis = Analysis.newBuilder();
+ this.wsEvent = Event.newBuilder();
+ this.searchData = searchData;
}
- Function<SearchResults, SearchResponse> buildWsResponse() {
- return searchResults -> Stream.of(SearchResponse.newBuilder())
- .peek(addAnalyses(searchResults))
- .peek(addPagination(searchResults))
- .map(SearchResponse.Builder::build)
- .collect(MoreCollectors.toOneElement());
+ SearchResponse build() {
+ SearchResponse.Builder wsResponse = SearchResponse.newBuilder();
+ addAnalyses(wsResponse);
+ addPagination(wsResponse);
+ return wsResponse.build();
}
- private Consumer<SearchResponse.Builder> addAnalyses(SearchResults searchResults) {
- return response -> searchResults.analyses.stream()
- .map(dbToWsAnalysis())
- .peek(addEvents(searchResults))
- .forEach(response::addAnalyses);
+ private void addAnalyses(SearchResponse.Builder wsResponse) {
+ searchData.analyses.stream()
+ .map(this::dbToWsAnalysis)
+ .map(this::attachEvents)
+ .forEach(wsResponse::addAnalyses);
}
- private Function<SnapshotDto, Analysis.Builder> dbToWsAnalysis() {
- return dbAnalysis -> analysisBuilder.clear()
+ private Analysis.Builder dbToWsAnalysis(SnapshotDto dbAnalysis) {
+ return wsAnalysis.clear()
.setKey(dbAnalysis.getUuid())
.setDate(formatDateTime(dbAnalysis.getCreatedAt()));
}
- private Consumer<Analysis.Builder> addEvents(SearchResults searchResults) {
- return wsAnalysis -> searchResults.eventsByAnalysis.get(wsAnalysis.getKey()).stream()
- .map(dbToWsEvent())
- .forEach(wsAnalysis::addEvents);
+ private Analysis.Builder attachEvents(Analysis.Builder analysis) {
+ searchData.eventsByAnalysis.get(analysis.getKey())
+ .stream()
+ .map(this::dbToWsEvent)
+ .forEach(analysis::addEvents);
+ return analysis;
+
}
- private Function<EventDto, Event.Builder> dbToWsEvent() {
- return dbEvent -> {
- Event.Builder wsEvent = eventBuilder.clear()
- .setKey(dbEvent.getUuid());
- setNullable(dbEvent.getName(), wsEvent::setName);
- setNullable(dbEvent.getDescription(), wsEvent::setDescription);
- setNullable(dbEvent.getCategory(), cat -> wsEvent.setCategory(fromLabel(cat).name()));
- return wsEvent;
- };
+ private Event.Builder dbToWsEvent(EventDto dbEvent) {
+ wsEvent.clear().setKey(dbEvent.getUuid());
+ setNullable(dbEvent.getName(), wsEvent::setName);
+ setNullable(dbEvent.getDescription(), wsEvent::setDescription);
+ setNullable(dbEvent.getCategory(), cat -> wsEvent.setCategory(fromLabel(cat).name()));
+
+ return wsEvent;
}
- private static Consumer<SearchResponse.Builder> addPagination(SearchResults searchResults) {
- return response -> response.getPagingBuilder()
- .setPageIndex(searchResults.paging.pageIndex())
- .setPageSize(searchResults.paging.pageSize())
- .setTotal(searchResults.paging.total())
+ private void addPagination(SearchResponse.Builder wsResponse) {
+ wsResponse.getPagingBuilder()
+ .setPageIndex(searchData.paging.pageIndex())
+ .setPageSize(searchData.paging.pageSize())
+ .setTotal(searchData.paging.total())
.build();
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.projectanalysis.ws;
-
-import com.google.common.collect.ListMultimap;
-import java.util.List;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
-import org.sonar.api.utils.Paging;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.event.EventDto;
-import org.sonarqube.ws.client.projectanalysis.SearchRequest;
-
-import static java.util.Objects.requireNonNull;
-
-class SearchResults {
- final List<SnapshotDto> analyses;
- final ListMultimap<String, EventDto> eventsByAnalysis;
- final Paging paging;
-
- private SearchResults(Builder builder) {
- this.analyses = builder.analyses;
- this.eventsByAnalysis = buildEvents(builder.events);
- this.paging = Paging
- .forPageIndex(builder.getRequest().getPage())
- .withPageSize(builder.getRequest().getPageSize())
- .andTotal(builder.countAnalyses);
- }
-
- private ListMultimap<String, EventDto> buildEvents(List<EventDto> events) {
- return events.stream().collect(MoreCollectors.index(EventDto::getAnalysisUuid));
- }
-
- static Builder builder(DbSession dbSession, SearchRequest request) {
- return new Builder(dbSession, request);
- }
-
- static class Builder {
- private final DbSession dbSession;
- private final SearchRequest request;
- private ComponentDto project;
- private List<SnapshotDto> analyses;
- private int countAnalyses;
- private List<EventDto> events;
-
- private Builder(DbSession dbSession, SearchRequest request) {
- this.dbSession = dbSession;
- this.request = request;
- }
-
- Builder setProject(ComponentDto project) {
- this.project = project;
- return this;
- }
-
- Builder setAnalyses(List<SnapshotDto> analyses) {
- Stream<SnapshotDto> stream = analyses.stream();
- // no filter by category, the pagination can be applied
- if (request.getCategory() == null) {
- stream = stream
- .skip(Paging.offset(request.getPage(), request.getPageSize()))
- .limit(request.getPageSize());
- }
-
- this.analyses = stream.collect(MoreCollectors.toList());
- this.countAnalyses = analyses.size();
- return this;
- }
-
- Builder setEvents(List<EventDto> events) {
- this.events = events;
- return this;
- }
-
- DbSession getDbSession() {
- return dbSession;
- }
-
- SearchRequest getRequest() {
- return request;
- }
-
- ComponentDto getProject() {
- return project;
- }
-
- List<SnapshotDto> getAnalyses() {
- return analyses;
- }
-
- private void filterByCategory() {
- ListMultimap<String, String> eventCategoriesByAnalysisUuid = events.stream()
- .collect(MoreCollectors.index(EventDto::getAnalysisUuid, EventDto::getCategory));
- Predicate<SnapshotDto> byCategory = a -> eventCategoriesByAnalysisUuid.get(a.getUuid()).contains(request.getCategory().getLabel());
- this.countAnalyses = (int) analyses.stream().filter(byCategory).count();
- this.analyses = analyses.stream()
- .filter(byCategory)
- .skip(Paging.offset(request.getPage(), request.getPageSize()))
- .limit(request.getPageSize())
- .collect(MoreCollectors.toList());
- }
-
- SearchResults build() {
- requireNonNull(analyses);
- requireNonNull(events);
- if (request.getCategory() != null) {
- filterByCategory();
- }
- return new SearchResults(this);
- }
- }
-}
*/
package org.sonar.server.projectanalysis.ws;
+import java.util.Date;
import java.util.List;
import java.util.function.Function;
import java.util.stream.IntStream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.api.utils.DateUtils.formatDate;
+import static org.sonar.api.utils.DateUtils.formatDateTime;
import static org.sonar.api.utils.DateUtils.parseDateTime;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
import static org.sonarqube.ws.client.projectanalysis.EventCategory.QUALITY_GATE;
import static org.sonarqube.ws.client.projectanalysis.EventCategory.VERSION;
import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_CATEGORY;
+import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_FROM;
import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_PROJECT;
+import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_TO;
public class SearchActionTest {
.containsExactly(2, 1, 3);
}
+ @Test
+ public void filter_from_date() {
+ ComponentDto project = db.components().insertPrivateProject();
+ userSession.addProjectPermission(UserRole.USER, project);
+ SnapshotDto a1 = db.components().insertSnapshot(newAnalysis(project).setUuid("a1").setCreatedAt(1_000_000_000L));
+ SnapshotDto a2 = db.components().insertSnapshot(newAnalysis(project).setUuid("a2").setCreatedAt(2_000_000_000L));
+ SnapshotDto a3 = db.components().insertSnapshot(newAnalysis(project).setUuid("a3").setCreatedAt(3_000_000_000L));
+ SnapshotDto a4 = db.components().insertSnapshot(newAnalysis(project).setUuid("a4").setCreatedAt(4_000_000_000L));
+
+ SearchResponse result = call(SearchRequest.builder()
+ .setProject(project.key())
+ .setFrom(formatDateTime(2_000_000_000L))
+ .build());
+
+ assertThat(result.getAnalysesList())
+ .extracting(Analysis::getKey)
+ .containsOnly(a2.getUuid(), a3.getUuid(), a4.getUuid())
+ .doesNotContain(a1.getUuid());
+ }
+
+ @Test
+ public void filter_to_date() {
+ ComponentDto project = db.components().insertPrivateProject();
+ userSession.addProjectPermission(UserRole.USER, project);
+ SnapshotDto a1 = db.components().insertSnapshot(newAnalysis(project).setUuid("a1").setCreatedAt(1_000_000_000L));
+ SnapshotDto a2 = db.components().insertSnapshot(newAnalysis(project).setUuid("a2").setCreatedAt(2_000_000_000L));
+ SnapshotDto a3 = db.components().insertSnapshot(newAnalysis(project).setUuid("a3").setCreatedAt(3_000_000_000L));
+ SnapshotDto a4 = db.components().insertSnapshot(newAnalysis(project).setUuid("a4").setCreatedAt(4_000_000_000L));
+
+ SearchResponse result = call(SearchRequest.builder()
+ .setProject(project.key())
+ .setTo(formatDateTime(2_000_000_000L))
+ .build());
+
+ assertThat(result.getAnalysesList())
+ .extracting(Analysis::getKey)
+ .containsOnly(a1.getUuid(), a2.getUuid())
+ .doesNotContain(a3.getUuid(), a4.getUuid());
+ }
+
+ @Test
+ public void filter_by_dates_using_datetime_format() {
+ ComponentDto project = db.components().insertPrivateProject();
+ userSession.addProjectPermission(UserRole.USER, project);
+ SnapshotDto a1 = db.components().insertSnapshot(newAnalysis(project).setUuid("a1").setCreatedAt(1_000_000_000L));
+ SnapshotDto a2 = db.components().insertSnapshot(newAnalysis(project).setUuid("a2").setCreatedAt(2_000_000_000L));
+ SnapshotDto a3 = db.components().insertSnapshot(newAnalysis(project).setUuid("a3").setCreatedAt(3_000_000_000L));
+ SnapshotDto a4 = db.components().insertSnapshot(newAnalysis(project).setUuid("a4").setCreatedAt(4_000_000_000L));
+
+ SearchResponse result = call(SearchRequest.builder()
+ .setProject(project.key())
+ .setFrom(formatDateTime(2_000_000_000L))
+ .setTo(formatDateTime(3_000_000_000L))
+ .build());
+
+ assertThat(result.getAnalysesList())
+ .extracting(Analysis::getKey)
+ .containsOnly(a2.getUuid(), a3.getUuid())
+ .doesNotContain(a1.getUuid(), a4.getUuid());
+ }
+
+ @Test
+ public void filter_by_dates_using_date_format() {
+ ComponentDto project = db.components().insertPrivateProject();
+ userSession.addProjectPermission(UserRole.USER, project);
+ SnapshotDto a1 = db.components().insertSnapshot(newAnalysis(project).setUuid("a1").setCreatedAt(1_000_000_000L));
+ SnapshotDto a2 = db.components().insertSnapshot(newAnalysis(project).setUuid("a2").setCreatedAt(2_000_000_000L));
+ SnapshotDto a3 = db.components().insertSnapshot(newAnalysis(project).setUuid("a3").setCreatedAt(3_000_000_000L));
+ SnapshotDto a4 = db.components().insertSnapshot(newAnalysis(project).setUuid("a4").setCreatedAt(4_000_000_000L));
+
+ SearchResponse result = call(SearchRequest.builder()
+ .setProject(project.key())
+ .setFrom(formatDate(new Date(2_000_000_000L)))
+ .setTo(formatDate(new Date(3_000_000_000L)))
+ .build());
+
+ assertThat(result.getAnalysesList())
+ .extracting(Analysis::getKey)
+ .containsOnly(a2.getUuid(), a3.getUuid())
+ .doesNotContain(a1.getUuid(), a4.getUuid());
+ }
+
@Test
public void definition() {
WebService.Action definition = ws.getDef();
assertThat(definition.key()).isEqualTo("search");
assertThat(definition.since()).isEqualTo("6.3");
assertThat(definition.responseExampleAsString()).isNotEmpty();
- assertThat(definition.param(PARAM_PROJECT).isRequired()).isTrue();
- assertThat(definition.param(PARAM_CATEGORY)).isNotNull();
+ assertThat(definition.param("project").isRequired()).isTrue();
+ assertThat(definition.param("category")).isNotNull();
+
+ Param from = definition.param("from");
+ assertThat(from.since()).isEqualTo("6.5");
+
+ Param to = definition.param("to");
+ assertThat(to.since()).isEqualTo("6.5");
}
@Test
setNullable(wsRequest.getCategory(), category -> request.setParam(PARAM_CATEGORY, category.name()));
setNullable(wsRequest.getPage(), page -> request.setParam(Param.PAGE, String.valueOf(page)));
setNullable(wsRequest.getPageSize(), pageSize -> request.setParam(Param.PAGE_SIZE, String.valueOf(pageSize)));
+ setNullable(wsRequest.getFrom(), from -> request.setParam(PARAM_FROM, from));
+ setNullable(wsRequest.getTo(), to -> request.setParam(PARAM_TO, to));
return request.executeProtobuf(SearchResponse.class);
}
public static final String PARAM_NAME = "name";
public static final String PARAM_EVENT = "event";
public static final String PARAM_PROJECT = "project";
+ public static final String PARAM_FROM = "from";
+ public static final String PARAM_TO = "to";
private ProjectAnalysesWsParameters() {
// static access only
private final EventCategory category;
private final int page;
private final int pageSize;
+ private final String from;
+ private final String to;
private SearchRequest(Builder builder) {
this.project = builder.project;
this.category = builder.category;
this.page = builder.page;
this.pageSize = builder.pageSize;
+ this.from = builder.from;
+ this.to = builder.to;
}
public String getProject() {
return pageSize;
}
+ @CheckForNull
+ public String getFrom() {
+ return from;
+ }
+
+ @CheckForNull
+ public String getTo() {
+ return to;
+ }
+
public static Builder builder() {
return new Builder();
}
private EventCategory category;
private int page = 1;
private int pageSize = DEFAULT_PAGE_SIZE;
+ private String from;
+ private String to;
private Builder() {
// enforce static factory method
return this;
}
+ public Builder setFrom(@Nullable String from) {
+ this.from = from;
+ return this;
+ }
+
+ public Builder setTo(@Nullable String to) {
+ this.to = to;
+ return this;
+ }
+
public SearchRequest build() {
requireNonNull(project, "Project is required");
checkArgument(pageSize <= MAX_SIZE, "Page size must be lower than or equal to " + MAX_SIZE);
.setCategory(QUALITY_GATE)
.setPage(2)
.setPageSize(500)
+ .setFrom("2016-01-01")
+ .setTo("2017-07-01")
.build();
assertThat(result.getProject()).isEqualTo("P1");
assertThat(result.getPage()).isEqualTo(2);
assertThat(result.getPageSize()).isEqualTo(500);
assertThat(result.getCategory()).isEqualTo(QUALITY_GATE);
+ assertThat(result.getFrom()).isEqualTo("2016-01-01");
+ assertThat(result.getTo()).isEqualTo("2017-07-01");
}
@Test