aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Schwarz <daniel.schwarz@sonarsource.com>2017-10-02 16:38:15 +0200
committerDaniel Schwarz <bartfastiel@users.noreply.github.com>2017-10-04 13:32:03 +0200
commitec5005ad979eb7bc47f277b42992851d8a4fbebc (patch)
tree71440f6b2894deb38a29b3da785358167ce7d3aa
parentd70e1e972bc561b94d00af08b5835219aec48482 (diff)
downloadsonarqube-ec5005ad979eb7bc47f277b42992851d8a4fbebc.tar.gz
sonarqube-ec5005ad979eb7bc47f277b42992851d8a4fbebc.zip
SONAR-9498 merge ChangelogAction and ChangelogLoader
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java157
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogLoader.java196
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java1
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionMockTest.java127
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionDatabaseTest.java)139
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogLoaderTest.java159
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java2
8 files changed, 282 insertions, 501 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java
index 0b8c0d81f89..d53298df16f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogAction.java
@@ -19,9 +19,17 @@
*/
package org.sonar.server.qualityprofile.ws;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.api.resources.Languages;
+import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService.NewAction;
@@ -29,10 +37,14 @@ import org.sonar.api.server.ws.WebService.NewController;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.qualityprofile.QProfileChangeDto;
import org.sonar.db.qualityprofile.QProfileChangeQuery;
import org.sonar.db.qualityprofile.QProfileDto;
+import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.user.UserDto;
import static org.sonar.api.utils.DateUtils.parseEndingDateOrDateTime;
import static org.sonar.api.utils.DateUtils.parseStartingDateOrDateTime;
@@ -42,13 +54,11 @@ import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.
public class ChangelogAction implements QProfileWsAction {
- private final ChangelogLoader changelogLoader;
private final QProfileWsSupport wsSupport;
private final Languages languages;
private DbClient dbClient;
- public ChangelogAction(ChangelogLoader changelogLoader, QProfileWsSupport wsSupport, Languages languages, DbClient dbClient) {
- this.changelogLoader = changelogLoader;
+ public ChangelogAction(QProfileWsSupport wsSupport, Languages languages, DbClient dbClient) {
this.wsSupport = wsSupport;
this.languages = languages;
this.dbClient = dbClient;
@@ -98,18 +108,20 @@ public class ChangelogAction implements QProfileWsAction {
int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE);
query.setPage(page, pageSize);
- ChangelogLoader.Changelog changelog = changelogLoader.load(dbSession, query);
- writeResponse(response.newJsonWriter(), page, pageSize, changelog);
+ int total = dbClient.qProfileChangeDao().countForQProfileUuid(dbSession, query.getProfileUuid());
+
+ List<Change> changelogs = load(dbSession, query);
+ writeResponse(response.newJsonWriter(), total, page, pageSize, changelogs);
}
}
- private static void writeResponse(JsonWriter json, int page, int pageSize, ChangelogLoader.Changelog changelog) {
+ private static void writeResponse(JsonWriter json, int total, int page, int pageSize, List<Change> changelogs) {
json.beginObject();
- json.prop("total", changelog.getTotal());
+ json.prop("total", total);
json.prop(Param.PAGE, page);
json.prop(Param.PAGE_SIZE, pageSize);
json.name("events").beginArray();
- for (ChangelogLoader.Change change : changelog.getChanges()) {
+ for (Change change : changelogs) {
json.beginObject()
.prop("date", DateUtils.formatDateTime(change.getCreatedAt()))
.prop("authorLogin", change.getUserLogin())
@@ -124,7 +136,7 @@ public class ChangelogAction implements QProfileWsAction {
json.endObject().close();
}
- private static void writeParameters(JsonWriter json, ChangelogLoader.Change change) {
+ private static void writeParameters(JsonWriter json, Change change) {
json.name("params").beginObject()
.prop("severity", change.getSeverity());
for (Map.Entry<String, String> param : change.getParams().entrySet()) {
@@ -133,4 +145,131 @@ public class ChangelogAction implements QProfileWsAction {
json.endObject();
}
+
+ /**
+ * @return non-null list of changes, by descending order of date
+ */
+ public List<Change> load(DbSession dbSession, QProfileChangeQuery query) {
+ List<QProfileChangeDto> dtos = dbClient.qProfileChangeDao().selectByQuery(dbSession, query);
+ List<Change> changes = dtos.stream()
+ .map(Change::from)
+ .collect(MoreCollectors.toList(dtos.size()));
+ completeUserAndRuleNames(dbSession, changes);
+ return changes;
+ }
+
+ private void completeUserAndRuleNames(DbSession dbSession, List<Change> changes) {
+ Set<String> logins = changes.stream().filter(c -> c.userLogin != null).map(c -> c.userLogin).collect(MoreCollectors.toSet());
+ Map<String, String> userNamesByLogins = dbClient.userDao()
+ .selectByLogins(dbSession, logins)
+ .stream()
+ .collect(java.util.stream.Collectors.toMap(UserDto::getLogin, UserDto::getName));
+
+ Set<RuleKey> ruleKeys = changes.stream().filter(c -> c.ruleKey != null).map(c -> c.ruleKey).collect(MoreCollectors.toSet());
+ Map<RuleKey, String> ruleNamesByKeys = dbClient.ruleDao()
+ .selectDefinitionByKeys(dbSession, Lists.newArrayList(ruleKeys))
+ .stream()
+ .collect(java.util.stream.Collectors.toMap(RuleDefinitionDto::getKey, RuleDefinitionDto::getName));
+
+ changes.forEach(c -> {
+ c.userName = userNamesByLogins.get(c.userLogin);
+ c.ruleName = ruleNamesByKeys.get(c.ruleKey);
+ });
+ }
+
+
+ static class Change {
+ private String key;
+ private String type;
+ private long at;
+ private String severity;
+ private String userLogin;
+ private String userName;
+ private String inheritance;
+ private RuleKey ruleKey;
+ private String ruleName;
+ private final Map<String, String> params = new HashMap<>();
+
+ private Change() {
+ }
+
+ @VisibleForTesting
+ Change(String key, String type, long at, @Nullable String severity, @Nullable String userLogin,
+ @Nullable String userName, @Nullable String inheritance, @Nullable RuleKey ruleKey, @Nullable String ruleName) {
+ this.key = key;
+ this.type = type;
+ this.at = at;
+ this.severity = severity;
+ this.userLogin = userLogin;
+ this.userName = userName;
+ this.inheritance = inheritance;
+ this.ruleKey = ruleKey;
+ this.ruleName = ruleName;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ @CheckForNull
+ public String getSeverity() {
+ return severity;
+ }
+
+ @CheckForNull
+ public String getUserLogin() {
+ return userLogin;
+ }
+
+ @CheckForNull
+ public String getUserName() {
+ return userName;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ @CheckForNull
+ public String getInheritance() {
+ return inheritance;
+ }
+
+ public RuleKey getRuleKey() {
+ return ruleKey;
+ }
+
+ @CheckForNull
+ public String getRuleName() {
+ return ruleName;
+ }
+
+ public long getCreatedAt() {
+ return at;
+ }
+
+ public Map<String, String> getParams() {
+ return params;
+ }
+
+ private static Change from(QProfileChangeDto dto) {
+ Map<String, String> data = dto.getDataAsMap();
+ Change change = new Change();
+ change.key = dto.getUuid();
+ change.userLogin = dto.getLogin();
+ change.type = dto.getChangeType();
+ change.at = dto.getCreatedAt();
+ // see content of data in class org.sonar.server.qualityprofile.ActiveRuleChange
+ change.severity = data.get("severity");
+ String ruleKey = data.get("ruleKey");
+ if (ruleKey != null) {
+ change.ruleKey = RuleKey.parse(ruleKey);
+ }
+ change.inheritance = data.get("inheritance");
+ data.entrySet().stream()
+ .filter(entry -> entry.getKey().startsWith("param_"))
+ .forEach(entry -> change.params.put(entry.getKey().replace("param_", ""), entry.getValue()));
+ return change;
+ }
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogLoader.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogLoader.java
deleted file mode 100644
index 2146563002e..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogLoader.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.qualityprofile.ws;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.ServerSide;
-import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.qualityprofile.QProfileChangeDto;
-import org.sonar.db.qualityprofile.QProfileChangeQuery;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.user.UserDto;
-
-import static java.util.Objects.requireNonNull;
-
-@ServerSide
-public class ChangelogLoader {
-
- private final DbClient dbClient;
-
- public ChangelogLoader(DbClient dbClient) {
- this.dbClient = dbClient;
- }
-
- /**
- * @return non-null list of changes, by descending order of date
- */
- public Changelog load(DbSession dbSession, QProfileChangeQuery query) {
- List<QProfileChangeDto> dtos = dbClient.qProfileChangeDao().selectByQuery(dbSession, query);
- List<Change> changes = dtos.stream()
- .map(Change::from)
- .collect(MoreCollectors.toList(dtos.size()));
- completeUserAndRuleNames(dbSession, changes);
-
- int total = dbClient.qProfileChangeDao().countForQProfileUuid(dbSession, query.getProfileUuid());
- return new Changelog(total, changes);
- }
-
- private void completeUserAndRuleNames(DbSession dbSession, List<Change> changes) {
- Set<String> logins = changes.stream().filter(c -> c.userLogin != null).map(c -> c.userLogin).collect(MoreCollectors.toSet());
- Map<String, String> userNamesByLogins = dbClient.userDao()
- .selectByLogins(dbSession, logins)
- .stream()
- .collect(java.util.stream.Collectors.toMap(UserDto::getLogin, UserDto::getName));
-
- Set<RuleKey> ruleKeys = changes.stream().filter(c -> c.ruleKey != null).map(c -> c.ruleKey).collect(MoreCollectors.toSet());
- Map<RuleKey, String> ruleNamesByKeys = dbClient.ruleDao()
- .selectDefinitionByKeys(dbSession, Lists.newArrayList(ruleKeys))
- .stream()
- .collect(java.util.stream.Collectors.toMap(RuleDefinitionDto::getKey, RuleDefinitionDto::getName));
-
- changes.forEach(c -> {
- c.userName = userNamesByLogins.get(c.userLogin);
- c.ruleName = ruleNamesByKeys.get(c.ruleKey);
- });
- }
-
- static class Change {
- private String key;
- private String type;
- private long at;
- private String severity;
- private String userLogin;
- private String userName;
- private String inheritance;
- private RuleKey ruleKey;
- private String ruleName;
- private final Map<String, String> params = new HashMap<>();
-
- private Change() {
- }
-
- @VisibleForTesting
- Change(String key, String type, long at, @Nullable String severity, @Nullable String userLogin,
- @Nullable String userName, @Nullable String inheritance, @Nullable RuleKey ruleKey, @Nullable String ruleName) {
- this.key = key;
- this.type = type;
- this.at = at;
- this.severity = severity;
- this.userLogin = userLogin;
- this.userName = userName;
- this.inheritance = inheritance;
- this.ruleKey = ruleKey;
- this.ruleName = ruleName;
- }
-
- public String getKey() {
- return key;
- }
-
- @CheckForNull
- public String getSeverity() {
- return severity;
- }
-
- @CheckForNull
- public String getUserLogin() {
- return userLogin;
- }
-
- @CheckForNull
- public String getUserName() {
- return userName;
- }
-
- public String getType() {
- return type;
- }
-
- @CheckForNull
- public String getInheritance() {
- return inheritance;
- }
-
- public RuleKey getRuleKey() {
- return ruleKey;
- }
-
- @CheckForNull
- public String getRuleName() {
- return ruleName;
- }
-
- public long getCreatedAt() {
- return at;
- }
-
- public Map<String, String> getParams() {
- return params;
- }
-
- private static Change from(QProfileChangeDto dto) {
- Map<String, String> data = dto.getDataAsMap();
- Change change = new Change();
- change.key = dto.getUuid();
- change.userLogin = dto.getLogin();
- change.type = dto.getChangeType();
- change.at = dto.getCreatedAt();
- // see content of data in class org.sonar.server.qualityprofile.ActiveRuleChange
- change.severity = data.get("severity");
- String ruleKey = data.get("ruleKey");
- if (ruleKey != null) {
- change.ruleKey = RuleKey.parse(ruleKey);
- }
- change.inheritance = data.get("inheritance");
- data.entrySet().stream()
- .filter(entry -> entry.getKey().startsWith("param_"))
- .forEach(entry -> change.params.put(entry.getKey().replace("param_", ""), entry.getValue()));
- return change;
- }
- }
-
- static class Changelog {
- private final int total;
- private final List<Change> changes;
-
- Changelog(int total, List<Change> changes) {
- this.total = total;
- this.changes = requireNonNull(changes);
- }
-
- public int getTotal() {
- return total;
- }
-
- public List<Change> getChanges() {
- return changes;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java
index 6f5aa204f81..ae82298bb81 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfilesWsModule.java
@@ -34,7 +34,6 @@ public class QProfilesWsModule extends Module {
CompareAction.class,
CopyAction.class,
ChangelogAction.class,
- ChangelogLoader.class,
ChangeParentAction.class,
CreateAction.class,
DeleteAction.class,
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionMockTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionMockTest.java
deleted file mode 100644
index 736b0b76e09..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionMockTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.qualityprofile.ws;
-
-import java.util.Collections;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.resources.Languages;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.qualityprofile.QProfileChangeQuery;
-import org.sonar.db.rule.RuleTesting;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualityprofile.QProfileTesting;
-import org.sonar.server.ws.WsTester;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.utils.DateUtils.parseDate;
-import static org.sonar.server.qualityprofile.QProfileTesting.XOO_P1_KEY;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_SINCE;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TO;
-
-public class ChangelogActionMockTest {
-
- private static final long A_DATE = 1_500_000_000_000L;
-
- @Rule
- public DbTester db = DbTester.create();
-
- private WsTester ws;
- private ChangelogLoader changelogLoader = mock(ChangelogLoader.class);
- private QProfileWsSupport wsSupport = mock(QProfileWsSupport.class);
- private OrganizationDto organization;
-
- @Before
- public void before() {
- ws = new WsTester(new QProfilesWs(mock(ActivateRulesAction.class),
- new ChangelogAction(changelogLoader, wsSupport, new Languages(), db.getDbClient())));
- organization = db.organizations().insert();
- }
-
- @Test
- public void changelog_empty() throws Exception {
- when(wsSupport.getProfile(any(DbSession.class), eq(QProfileReference.fromKey(XOO_P1_KEY)))).thenReturn(QProfileTesting.newXooP1(organization));
- when(changelogLoader.load(any(DbSession.class), any(QProfileChangeQuery.class))).thenReturn(new ChangelogLoader.Changelog(0, Collections.emptyList()));
-
- ws.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam(PARAM_KEY, XOO_P1_KEY)
- .execute().assertJson(getClass(), "changelog_empty.json");
- }
-
- @Test
- public void changelog_nominal() throws Exception {
- when(wsSupport.getProfile(any(DbSession.class), eq(QProfileReference.fromKey(XOO_P1_KEY)))).thenReturn(QProfileTesting.newXooP1(organization));
- ChangelogLoader.Change change1 = new ChangelogLoader.Change("C1", "ACTIVATED", A_DATE, null, null, null, null, null, null);
- ChangelogLoader.Change change2 = new ChangelogLoader.Change("C2", "ACTIVATED", A_DATE + 10, null, null, null, null, null, null);
- List<ChangelogLoader.Change> changes = asList(change1, change2);
- when(changelogLoader.load(any(DbSession.class), any(QProfileChangeQuery.class))).thenReturn(new ChangelogLoader.Changelog(10, changes));
-
- ws.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam(PARAM_KEY, XOO_P1_KEY)
- .execute().assertJson(getClass(), "changelog_nominal.json");
- }
-
- @Test
- public void changelog_with_all_fields() throws Exception {
- when(wsSupport.getProfile(any(DbSession.class), eq(QProfileReference.fromKey(XOO_P1_KEY)))).thenReturn(QProfileTesting.newXooP1(organization));
- ChangelogLoader.Change change1 = new ChangelogLoader.Change("C1", "ACTIVATED", A_DATE, "MAJOR", "marcel", "Marcel", "INHERITED", RuleTesting.XOO_X1, "X One");
- change1.getParams().put("foo", "foo_value");
- change1.getParams().put("bar", "bar_value");
- List<ChangelogLoader.Change> changes = asList(change1);
- when(changelogLoader.load(any(DbSession.class), any(QProfileChangeQuery.class))).thenReturn(new ChangelogLoader.Changelog(10, changes));
-
- ws.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam(PARAM_KEY, XOO_P1_KEY)
- .execute().assertJson(getClass(), "changelog_full.json");
- }
-
- @Test
- public void changelog_inclusive_for_dates() throws Exception {
- when(wsSupport.getProfile(any(DbSession.class), eq(QProfileReference.fromKey(XOO_P1_KEY)))).thenReturn(QProfileTesting.newXooP1(organization));
- when(changelogLoader.load(any(DbSession.class), any(QProfileChangeQuery.class))).thenReturn(new ChangelogLoader.Changelog(0, Collections.emptyList()));
-
- ws.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog")
- .setParam(PARAM_KEY, XOO_P1_KEY)
- .setParam(PARAM_SINCE, "2016-09-01")
- .setParam(PARAM_TO, "2016-09-01")
- .execute();
-
- ArgumentCaptor<QProfileChangeQuery> argumentCaptor = ArgumentCaptor.forClass(QProfileChangeQuery.class);
- verify(changelogLoader).load(any(DbSession.class), argumentCaptor.capture());
- assertThat(argumentCaptor.getValue().getFromIncluded()).isEqualTo(parseDate("2016-09-01").getTime());
- assertThat(argumentCaptor.getValue().getToExcluded()).isEqualTo(parseDate("2016-09-02").getTime());
- }
-
- @Test(expected = NotFoundException.class)
- public void fail_on_unknown_profile() throws Exception {
- when(wsSupport.getProfile(any(DbSession.class), eq(QProfileReference.fromKey(XOO_P1_KEY)))).thenThrow(new NotFoundException("Profile not found"));
-
- ws.newGetRequest(QProfilesWs.API_ENDPOINT, "changelog").setParam(PARAM_KEY, XOO_P1_KEY).execute();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionDatabaseTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java
index 8f6d7166b66..77c6b0da904 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionDatabaseTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java
@@ -19,54 +19,68 @@
*/
package org.sonar.server.qualityprofile.ws;
+import com.google.common.collect.ImmutableMap;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.function.Consumer;
+import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.resources.Languages;
+import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.System2;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.internal.TestSystem2;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualityprofile.QProfileChangeDto;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.db.qualityprofile.QualityProfileTesting;
+import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
+import org.sonar.server.qualityprofile.ActiveRule;
+import org.sonar.server.qualityprofile.ActiveRuleChange;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.JsonAssert;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
-import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
-public class ChangelogActionDatabaseTest {
+public class ChangelogActionTest {
+
+ private TestSystem2 system2 = new TestSystem2().setNow(1_500_000_000_000L);
@Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ public DbTester dbTester = DbTester.create(system2);
@Rule
public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public ExpectedException thrown = ExpectedException.none();
private WsActionTester ws;
- private ChangelogLoader changelogLoader;
private QProfileWsSupport wsSupport;
private OrganizationDto organization;
private DefaultOrganizationProvider defaultOrganizationProvider;
@Before
public void before() {
+ system2.setNow(DateUtils.parseDateTime("2011-04-25T01:15:42+0100").getTime());
defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester);
wsSupport = new QProfileWsSupport(dbTester.getDbClient(), userSession, defaultOrganizationProvider);
- changelogLoader = new ChangelogLoader(dbTester.getDbClient());
ws = new WsActionTester(
- new ChangelogAction(changelogLoader, wsSupport, new Languages(), dbTester.getDbClient()));
+ new ChangelogAction(wsSupport, new Languages(), dbTester.getDbClient()));
organization = dbTester.organizations().insert();
}
@@ -84,6 +98,47 @@ public class ChangelogActionDatabaseTest {
}
@Test
+ public void example() {
+ QProfileDto profile = dbTester.qualityProfiles().insert(organization);
+ String profileUuid = profile.getRulesProfileUuid();
+
+ system2.setNow(DateUtils.parseDateTime("2015-02-23T17:58:39+0100").getTime());
+ RuleDefinitionDto rule1 = dbTester.rules().insert(RuleKey.of("squid", "S2438"), r -> r.setName("\"Threads\" should not be used where \"Runnables\" are expected"));
+ UserDto user1 = dbTester.users().insertUser(u -> u.setLogin("anakin.skywalker").setName("Anakin Skywalker"));
+ insertChange(profile, c -> c.setRulesProfileUuid(profileUuid)
+ .setLogin(user1.getLogin())
+ .setChangeType(ActiveRuleChange.Type.ACTIVATED.name())
+ .setData(ImmutableMap.of("severity", "CRITICAL", "ruleKey", rule1.getKey().toString())));
+
+ system2.setNow(DateUtils.parseDateTime("2015-02-23T17:58:18+0100").getTime());
+ RuleDefinitionDto rule2 = dbTester.rules().insert(RuleKey.of("squid", "S2162"), r -> r.setName("\"equals\" methods should be symmetric and work for subclasses"));
+ UserDto user2 = dbTester.users().insertUser(u -> u.setLogin("padme.amidala").setName("Padme Amidala"));
+ QProfileChangeDto change2 = insertChange(profile, c -> c.setRulesProfileUuid(profileUuid)
+ .setLogin(user2.getLogin())
+ .setChangeType(ActiveRuleChange.Type.DEACTIVATED.name())
+ .setData(ImmutableMap.of("ruleKey", rule2.getKey().toString())));
+
+ system2.setNow(DateUtils.parseDateTime("2014-09-12T15:20:46+0200").getTime());
+ RuleDefinitionDto rule3 = dbTester.rules().insert(RuleKey.of("squid", "S00101"), r -> r.setName("Class names should comply with a naming convention"));
+ UserDto user3 = dbTester.users().insertUser(u -> u.setLogin("obiwan.kenobi").setName("Obiwan Kenobi"));
+ QProfileChangeDto change3 = insertChange(profile, c -> c.setRulesProfileUuid(profileUuid)
+ .setLogin(user3.getLogin())
+ .setChangeType(ActiveRuleChange.Type.ACTIVATED.name())
+ .setData(ImmutableMap.of("severity", "MAJOR", "param_format", "^[A-Z][a-zA-Z0-9]*$", "ruleKey", rule3.getKey().toString())));
+
+ dbTester.commit();
+
+ String response = ws.newRequest()
+ .setMethod("GET")
+ .setParam(PARAM_KEY, profile.getKee())
+ .setParam("ps", "10")
+ .execute()
+ .getInput();
+
+ assertJson(response).isSimilarTo(getClass().getResource("changelog-example.json"));
+ }
+
+ @Test
public void find_changelog_by_profile_key() throws Exception {
QProfileDto profile = dbTester.qualityProfiles().insert(organization);
@@ -176,4 +231,74 @@ public class ChangelogActionDatabaseTest {
assertThat(response).contains("\"total\":1");
}
+
+ @Test
+ public void sort_changelog_events_in_reverse_chronological_order() {
+ QProfileDto profile = dbTester.qualityProfiles().insert(organization);
+ system2.setNow(DateUtils.parseDateTime("2011-04-25T01:15:42+0100").getTime());
+ QProfileChangeDto change1 = insertChange(profile, ActiveRuleChange.Type.ACTIVATED, null, null);
+ system2.setNow(DateUtils.parseDateTime("2011-04-25T01:15:43+0100").getTime());
+ QProfileChangeDto change2 = insertChange(profile, ActiveRuleChange.Type.DEACTIVATED, "mazout", null);
+ dbTester.commit();
+
+ String response = ws.newRequest()
+ .setMethod("GET")
+ .setParam(PARAM_KEY, profile.getKee())
+ .execute()
+ .getInput();
+
+ assertThat(response).containsSequence("15:43", "15:42");
+ }
+
+ @Test
+ public void return_change_with_all_fields() {
+ QProfileDto profile = dbTester.qualityProfiles().insert(organization);
+ Map<String, Object> data = ImmutableMap.of(
+ "ruleKey", "java:S001",
+ "severity", "MINOR",
+ "inheritance", ActiveRule.Inheritance.INHERITED.name(),
+ "param_foo", "foo_value",
+ "param_bar", "bar_value");
+ QProfileChangeDto change = insertChange(profile, ActiveRuleChange.Type.ACTIVATED, "theLogin", data);
+ dbTester.commit();
+
+ String response = ws.newRequest()
+ .setMethod("GET")
+ .setParam(PARAM_KEY, profile.getKee())
+ .execute()
+ .getInput();
+
+ JsonAssert.assertJson(response).isSimilarTo("{\n" +
+ " \"total\": 1,\n" +
+ " \"p\": 1,\n" +
+ " \"ps\": 50,\n" +
+ " \"events\": [\n" +
+ " {\n" +
+ " \"date\": \"2011-04-25T02:15:42+0200\",\n" +
+ " \"authorLogin\": \"theLogin\",\n" +
+ " \"action\": \"ACTIVATED\",\n" +
+ " \"ruleKey\": \"java:S001\",\n" +
+ " \"params\": {\n" +
+ " \"severity\": \"MINOR\",\n" +
+ " \"bar\": \"bar_value\",\n" +
+ " \"foo\": \"foo_value\"\n" +
+ " }\n" +
+ " }\n" +
+ " ]\n" +
+ "}");
+ }
+
+ private QProfileChangeDto insertChange(QProfileDto profile, ActiveRuleChange.Type type, @Nullable String login, @Nullable Map<String, Object> data) {
+ return insertChange(profile, c -> c.setRulesProfileUuid(profile.getRulesProfileUuid())
+ .setLogin(login)
+ .setChangeType(type.name())
+ .setData(data));
+ }
+
+ private QProfileChangeDto insertChange(QProfileDto profile, Consumer<QProfileChangeDto>... consumers) {
+ QProfileChangeDto dto = new QProfileChangeDto();
+ Arrays.stream(consumers).forEach(c -> c.accept(dto));
+ dbTester.getDbClient().qProfileChangeDao().insert(dbTester.getSession(), dto);
+ return dto;
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogLoaderTest.java
deleted file mode 100644
index 2fbe940d5ec..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogLoaderTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.qualityprofile.ws;
-
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.qualityprofile.QProfileChangeDto;
-import org.sonar.db.qualityprofile.QProfileChangeQuery;
-import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.qualityprofile.ActiveRule;
-import org.sonar.server.qualityprofile.ActiveRuleChange;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.data.MapEntry.entry;
-
-public class ChangelogLoaderTest {
-
- private System2 system2 = new AlwaysIncreasingSystem2();
- @Rule
- public DbTester db = DbTester.create(system2);
- private DbSession dbSession = db.getSession();
-
- private ChangelogLoader underTest = new ChangelogLoader(db.getDbClient());
-
- @Test
- public void return_changes_in_reverse_chronological_order() {
- QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
- QProfileChangeDto change1 = insertChange(profile, ActiveRuleChange.Type.ACTIVATED, null, null);
- QProfileChangeDto change2 = insertChange(profile, ActiveRuleChange.Type.DEACTIVATED, "mazout", null);
-
- QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee());
- ChangelogLoader.Changelog changes = underTest.load(dbSession, query);
-
- assertThat(changes.getChanges())
- .extracting(ChangelogLoader.Change::getKey)
- .containsExactly(change2.getUuid(), change1.getUuid());
- }
-
- @Test
- public void return_change_with_only_required_fields() {
- QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
- QProfileChangeDto inserted = insertChange(profile, ActiveRuleChange.Type.ACTIVATED, null, null);
-
- QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee());
- ChangelogLoader.Change change = underTest.load(dbSession, query).getChanges().get(0);
-
- assertThat(change.getKey()).isEqualTo(inserted.getUuid());
- assertThat(change.getCreatedAt()).isEqualTo(inserted.getCreatedAt());
- assertThat(change.getType()).isEqualTo(inserted.getChangeType());
- // optional fields are null or empty
- assertThat(change.getInheritance()).isNull();
- assertThat(change.getRuleKey()).isNull();
- assertThat(change.getRuleName()).isNull();
- assertThat(change.getSeverity()).isNull();
- assertThat(change.getUserLogin()).isNull();
- assertThat(change.getUserName()).isNull();
- assertThat(change.getParams()).isEmpty();
- }
-
- @Test
- public void return_change_with_all_fields() {
- QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
- Map<String, Object> data = ImmutableMap.of(
- "ruleKey", "java:S001",
- "severity", "MINOR",
- "inheritance", ActiveRule.Inheritance.INHERITED.name(),
- "param_foo", "foo_value",
- "param_bar", "bar_value");
- QProfileChangeDto inserted = insertChange(profile, ActiveRuleChange.Type.ACTIVATED, "theLogin", data);
-
- QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee());
- ChangelogLoader.Change change = underTest.load(dbSession, query).getChanges().get(0);
-
- assertThat(change.getKey()).isEqualTo(inserted.getUuid());
- assertThat(change.getCreatedAt()).isEqualTo(inserted.getCreatedAt());
- assertThat(change.getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED.name());
- assertThat(change.getInheritance()).isEqualTo(ActiveRule.Inheritance.INHERITED.name());
- assertThat(change.getRuleKey().toString()).isEqualTo("java:S001");
- assertThat(change.getRuleName()).isNull();
- assertThat(change.getSeverity()).isEqualTo("MINOR");
- assertThat(change.getUserLogin()).isEqualTo("theLogin");
- assertThat(change.getUserName()).isNull();
- assertThat(change.getParams()).containsOnly(entry("foo", "foo_value"), entry("bar", "bar_value"));
- }
-
- @Test
- public void return_name_of_rule() {
- QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
- RuleDefinitionDto rule = db.rules().insert();
- Map<String, Object> data = ImmutableMap.of("ruleKey", rule.getKey().toString());
- insertChange(profile, ActiveRuleChange.Type.ACTIVATED, null, data);
-
- QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee());
- ChangelogLoader.Change change = underTest.load(dbSession, query).getChanges().get(0);
-
- assertThat(change.getRuleKey()).isEqualTo(rule.getKey());
- assertThat(change.getRuleName()).isEqualTo(rule.getName());
- }
-
- @Test
- public void return_name_of_user() {
- QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization());
- UserDto user = db.users().insertUser();
- insertChange(profile, ActiveRuleChange.Type.ACTIVATED, user.getLogin(), null);
-
- QProfileChangeQuery query = new QProfileChangeQuery(profile.getKee());
- ChangelogLoader.Change change = underTest.load(dbSession, query).getChanges().get(0);
-
- assertThat(change.getUserLogin()).isEqualTo(user.getLogin());
- assertThat(change.getUserName()).isEqualTo(user.getName());
- }
-
- @Test
- public void return_empty_changelog() {
- QProfileChangeQuery query = new QProfileChangeQuery("P1");
-
- ChangelogLoader.Changelog changelog = underTest.load(dbSession, query);
-
- assertThat(changelog.getTotal()).isEqualTo(0);
- assertThat(changelog.getChanges()).isEmpty();
- }
-
- private QProfileChangeDto insertChange(QProfileDto profile, ActiveRuleChange.Type type, @Nullable String login, @Nullable Map<String, Object> data) {
- QProfileChangeDto dto = new QProfileChangeDto()
- .setRulesProfileUuid(profile.getRulesProfileUuid())
- .setLogin(login)
- .setChangeType(type.name())
- .setData(data);
- db.getDbClient().qProfileChangeDao().insert(dbSession, dto);
- return dto;
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.java
index d16a500bae3..fb239e4392e 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsModuleTest.java
@@ -29,6 +29,6 @@ public class QProfilesWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new QProfilesWsModule().configure(container);
- assertThat(container.size()).isEqualTo(33 + 2);
+ assertThat(container.size()).isEqualTo(32 + 2);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
index 0ffe1990556..978c940b864 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
@@ -64,7 +64,7 @@ public class QProfilesWsTest {
new SearchAction(userSession, languages, dbClient, wsSupport, null),
new SetDefaultAction(languages, null, null, wsSupport),
new ProjectsAction(null, userSession, wsSupport),
- new ChangelogAction(null, wsSupport, languages, dbClient),
+ new ChangelogAction(wsSupport, languages, dbClient),
new ChangeParentAction(dbClient, null, languages, wsSupport, userSession),
new CompareAction(null, null, languages),
new DeleteAction(languages, null, null, userSession, wsSupport),