aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-pushapi
diff options
context:
space:
mode:
authorBelen Pruvost <belen.pruvost@sonarsource.com>2022-07-28 16:55:41 +0200
committersonartech <sonartech@sonarsource.com>2022-07-28 20:02:56 +0000
commit7ed0c0a19b7a0da9c6c907cab9a57a4d723dd03e (patch)
tree243c1417f126cc6f954c9c3352cf4c7f6ad61794 /server/sonar-webserver-pushapi
parentca7e8a8d9687f93d1e4ddad5748aee2d66f57252 (diff)
downloadsonarqube-7ed0c0a19b7a0da9c6c907cab9a57a4d723dd03e.tar.gz
sonarqube-7ed0c0a19b7a0da9c6c907cab9a57a4d723dd03e.zip
SONAR-16647 - Move previous SSE events to DB queue
Diffstat (limited to 'server/sonar-webserver-pushapi')
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/DistributedIssueChangeEventsDistributor.java45
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeBroadcastUtils.java75
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImpl.java35
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventsDistributor.java30
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/StandaloneIssueChangeEventsDistributor.java42
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/DistributedRuleActivatorEventsDistributor.java45
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java52
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleActivatorEventsDistributor.java30
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleSetChangeBroadcastUtils.java94
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/StandaloneRuleActivatorEventsDistributor.java42
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/polling/PushEventPollScheduler.java12
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java85
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintPushEvent.java12
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/DistributedIssueChangeEventsDistributorTest.java48
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeBroadcastUtilsTest.java62
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImplTest.java128
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/StandaloneIssueChangeEventsDistributorTest.java41
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java90
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/RuleSetChangeBroadcastUtilsTest.java81
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistryTest.java158
-rw-r--r--server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event-data.json24
21 files changed, 256 insertions, 975 deletions
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/DistributedIssueChangeEventsDistributor.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/DistributedIssueChangeEventsDistributor.java
deleted file mode 100644
index ae5bbc7e5dc..00000000000
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/DistributedIssueChangeEventsDistributor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.issues;
-
-import org.sonar.api.server.ServerSide;
-import org.sonar.core.util.issue.IssueChangeListener;
-import org.sonar.core.util.issue.IssueChangedEvent;
-import org.sonar.process.cluster.hz.HazelcastMember;
-
-@ServerSide
-public class DistributedIssueChangeEventsDistributor implements IssueChangeEventsDistributor {
-
- private HazelcastMember hazelcastMember;
-
- public DistributedIssueChangeEventsDistributor(HazelcastMember hazelcastMember) {
- this.hazelcastMember = hazelcastMember;
- }
-
- @Override
- public void subscribe(IssueChangeListener listener) {
- hazelcastMember.subscribeIssueChangeTopic(listener);
- }
-
- @Override
- public void pushEvent(IssueChangedEvent event) {
- hazelcastMember.publishEvent(event);
- }
-}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeBroadcastUtils.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeBroadcastUtils.java
deleted file mode 100644
index b784f0eead5..00000000000
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeBroadcastUtils.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.issues;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.sonar.core.util.issue.Issue;
-import org.sonar.core.util.issue.IssueChangedEvent;
-import org.sonar.server.pushapi.sonarlint.SonarLintClient;
-
-import static java.util.Arrays.asList;
-
-public class IssueChangeBroadcastUtils {
- private IssueChangeBroadcastUtils() {
-
- }
-
- public static Predicate<SonarLintClient> getFilterForEvent(IssueChangedEvent issueChangedEvent) {
- List<String> affectedProjects = asList(issueChangedEvent.getProjectKey());
- return client -> {
- Set<String> clientProjectKeys = client.getClientProjectKeys();
- return !Collections.disjoint(clientProjectKeys, affectedProjects);
- };
- }
-
- public static String getMessage(IssueChangedEvent issueChangedEvent) {
- return "event: " + issueChangedEvent.getEvent() + "\n"
- + "data: " + toJson(issueChangedEvent);
- }
-
- private static String toJson(IssueChangedEvent issueChangedEvent) {
- JSONObject data = new JSONObject();
- data.put("projectKey", issueChangedEvent.getProjectKey());
-
- JSONArray issuesJson = new JSONArray();
- for (Issue issue : issueChangedEvent.getIssues()) {
- issuesJson.put(toJson(issue));
- }
- data.put("issues", issuesJson);
- data.put("userSeverity", issueChangedEvent.getUserSeverity());
- data.put("userType", issueChangedEvent.getUserType());
- data.put("resolved", issueChangedEvent.getResolved());
-
- return data.toString();
- }
-
- private static JSONObject toJson(Issue issue) {
- JSONObject ruleJson = new JSONObject();
- ruleJson.put("issueKey", issue.getIssueKey());
- ruleJson.put("branchName", issue.getBranchName());
- return ruleJson;
- }
-
-}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImpl.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImpl.java
index 54dc1c71ba1..2e0e7f9b223 100644
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImpl.java
+++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImpl.java
@@ -19,6 +19,8 @@
*/
package org.sonar.server.pushapi.issues;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
@@ -31,9 +33,13 @@ import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.FieldDiffs.Diff;
import org.sonar.core.util.issue.Issue;
import org.sonar.core.util.issue.IssueChangedEvent;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.pushevent.PushEventDto;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.elasticsearch.common.Strings.isNullOrEmpty;
import static org.sonar.api.issue.DefaultTransitions.CONFIRM;
import static org.sonar.api.issue.DefaultTransitions.FALSE_POSITIVE;
@@ -43,6 +49,9 @@ import static org.sonar.db.component.BranchType.BRANCH;
@ServerSide
public class IssueChangeEventServiceImpl implements IssueChangeEventService {
+ private static final Gson GSON = new GsonBuilder().create();
+
+ private static final String EVENT_NAME = "IssueChanged";
private static final String FALSE_POSITIVE_KEY = "FALSE-POSITIVE";
private static final String WONT_FIX_KEY = "WONTFIX";
@@ -50,10 +59,10 @@ public class IssueChangeEventServiceImpl implements IssueChangeEventService {
private static final String SEVERITY_KEY = "severity";
private static final String TYPE_KEY = "type";
- private final IssueChangeEventsDistributor eventsDistributor;
+ private final DbClient dbClient;
- public IssueChangeEventServiceImpl(IssueChangeEventsDistributor eventsDistributor) {
- this.eventsDistributor = eventsDistributor;
+ public IssueChangeEventServiceImpl(DbClient dbClient) {
+ this.dbClient = dbClient;
}
@Override
@@ -69,7 +78,8 @@ public class IssueChangeEventServiceImpl implements IssueChangeEventService {
IssueChangedEvent event = new IssueChangedEvent(projectKey, new Issue[]{changedIssue},
resolved, severity, type);
- eventsDistributor.pushEvent(event);
+
+ persistEvent(event, issue.projectUuid());
}
@Override
@@ -96,7 +106,7 @@ public class IssueChangeEventServiceImpl implements IssueChangeEventService {
IssueChangedEvent event = getIssueChangedEvent(projectKey, issuesInProject, issueChanges);
if (event != null) {
- eventsDistributor.pushEvent(event);
+ persistEvent(event, entry.getValue().projectUuid());
}
}
}
@@ -151,4 +161,19 @@ public class IssueChangeEventServiceImpl implements IssueChangeEventService {
return transitionOrStatus.equals(WONT_FIX) || transitionOrStatus.equals(FALSE_POSITIVE) ||
transitionOrStatus.equals(FALSE_POSITIVE_KEY) || transitionOrStatus.equals(WONT_FIX_KEY);
}
+
+ private void persistEvent(IssueChangedEvent event, String entry) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ PushEventDto eventDto = new PushEventDto()
+ .setName(EVENT_NAME)
+ .setProjectUuid(entry)
+ .setPayload(serializeIssueToPushEvent(event));
+ dbClient.pushEventDao().insert(dbSession, eventDto);
+ dbSession.commit();
+ }
+ }
+
+ private static byte[] serializeIssueToPushEvent(IssueChangedEvent event) {
+ return GSON.toJson(event).getBytes(UTF_8);
+ }
}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventsDistributor.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventsDistributor.java
deleted file mode 100644
index 486cc87068f..00000000000
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/IssueChangeEventsDistributor.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.issues;
-
-import org.sonar.core.util.issue.IssueChangeListener;
-import org.sonar.core.util.issue.IssueChangedEvent;
-
-public interface IssueChangeEventsDistributor {
-
- void subscribe(IssueChangeListener listener);
-
- void pushEvent(IssueChangedEvent event);
-}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/StandaloneIssueChangeEventsDistributor.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/StandaloneIssueChangeEventsDistributor.java
deleted file mode 100644
index 53aa3f34054..00000000000
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/issues/StandaloneIssueChangeEventsDistributor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.issues;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.sonar.api.server.ServerSide;
-import org.sonar.core.util.issue.IssueChangeListener;
-import org.sonar.core.util.issue.IssueChangedEvent;
-
-@ServerSide
-public class StandaloneIssueChangeEventsDistributor implements IssueChangeEventsDistributor {
-
- private List<IssueChangeListener> listeners = new ArrayList<>();
-
- @Override
- public void subscribe(IssueChangeListener listener) {
- listeners.add(listener);
- }
-
- @Override
- public void pushEvent(IssueChangedEvent event) {
- listeners.forEach(l -> l.listen(event));
- }
-}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/DistributedRuleActivatorEventsDistributor.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/DistributedRuleActivatorEventsDistributor.java
deleted file mode 100644
index a45ff9ce87f..00000000000
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/DistributedRuleActivatorEventsDistributor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.qualityprofile;
-
-import org.sonar.api.server.ServerSide;
-import org.sonar.core.util.rule.RuleActivationListener;
-import org.sonar.core.util.rule.RuleSetChangedEvent;
-import org.sonar.process.cluster.hz.HazelcastMember;
-
-@ServerSide
-public class DistributedRuleActivatorEventsDistributor implements RuleActivatorEventsDistributor {
-
- private HazelcastMember hazelcastMember;
-
- public DistributedRuleActivatorEventsDistributor(HazelcastMember hazelcastMember) {
- this.hazelcastMember = hazelcastMember;
- }
-
- @Override
- public void subscribe(RuleActivationListener listener) {
- hazelcastMember.subscribeRuleActivationTopic(listener);
- }
-
- @Override
- public void pushEvent(RuleSetChangedEvent event) {
- hazelcastMember.publishEvent(event);
- }
-}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java
index 76fc0799986..bb4bd7a0461 100644
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java
+++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java
@@ -19,8 +19,11 @@
*/
package org.sonar.server.pushapi.qualityprofile;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -39,6 +42,7 @@ import org.sonar.core.util.rule.RuleSetChangedEvent;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.project.ProjectDto;
+import org.sonar.db.pushevent.PushEventDto;
import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.ActiveRuleParamDto;
import org.sonar.db.qualityprofile.OrgActiveRuleDto;
@@ -47,6 +51,7 @@ import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.server.qualityprofile.ActiveRuleChange;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.function.Predicate.not;
import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
@@ -54,17 +59,18 @@ import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.UPDATED;
@ServerSide
public class QualityProfileChangeEventServiceImpl implements QualityProfileChangeEventService {
+ private static final Gson GSON = new GsonBuilder().create();
+ private static final String EVENT_NAME = "RuleSetChanged";
private final DbClient dbClient;
- private final RuleActivatorEventsDistributor eventsDistributor;
- public QualityProfileChangeEventServiceImpl(DbClient dbClient, RuleActivatorEventsDistributor eventsDistributor) {
+ public QualityProfileChangeEventServiceImpl(DbClient dbClient) {
this.dbClient = dbClient;
- this.eventsDistributor = eventsDistributor;
}
@Override
- public void publishRuleActivationToSonarLintClients(ProjectDto project, @Nullable QProfileDto activatedProfile, @Nullable QProfileDto deactivatedProfile) {
+ public void publishRuleActivationToSonarLintClients(ProjectDto project, @Nullable QProfileDto activatedProfile,
+ @Nullable QProfileDto deactivatedProfile) {
List<RuleChange> activatedRules = new ArrayList<>();
Set<String> deactivatedRules = new HashSet<>();
@@ -81,9 +87,8 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
}
String language = activatedProfile != null ? activatedProfile.getLanguage() : deactivatedProfile.getLanguage();
- RuleSetChangedEvent event = new RuleSetChangedEvent(new String[] {project.getKey()}, activatedRules.toArray(new RuleChange[0]), deactivatedRules.toArray(new String[0]),
- language);
- eventsDistributor.pushEvent(event);
+
+ persistPushEvent(project.getKey(), activatedRules.toArray(new RuleChange[0]), deactivatedRules, language, project.getUuid());
}
private List<RuleChange> createRuleChanges(@NotNull QProfileDto profileDto) {
@@ -193,15 +198,29 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
.map(RuleKey::toString)
.collect(Collectors.toSet());
- Set<String> projectKeys = getProjectKeys(profiles);
+ Map<String, String> projectKeyAndUuids = getProjectKeyAndUuids(profiles);
if (activatedRules.isEmpty() && deactivatedRules.isEmpty()) {
return;
}
- RuleSetChangedEvent event = new RuleSetChangedEvent(projectKeys.toArray(new String[0]), activatedRules.toArray(new RuleChange[0]), deactivatedRules.toArray(new String[0]),
- language);
- eventsDistributor.pushEvent(event);
+ for (Map.Entry<String, String> entry : projectKeyAndUuids.entrySet()) {
+ persistPushEvent(entry.getKey(), activatedRules.toArray(new RuleChange[0]), deactivatedRules, language, entry.getValue());
+ }
+ }
+
+ private void persistPushEvent(String projectKey, RuleChange[] activatedRules, Set<String> deactivatedRules, String language, String projectUuid) {
+ RuleSetChangedEvent event = new RuleSetChangedEvent(projectKey, activatedRules, deactivatedRules.toArray(new String[0]));
+
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ PushEventDto eventDto = new PushEventDto()
+ .setName(EVENT_NAME)
+ .setProjectUuid(projectUuid)
+ .setLanguage(language)
+ .setPayload(serializeIssueToPushEvent(event));
+ dbClient.pushEventDao().insert(dbSession, eventDto);
+ dbSession.commit();
+ }
}
private Optional<String> templateKey(ActiveRuleChange arc) {
@@ -219,17 +238,20 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
return Optional.empty();
}
- private Set<String> getProjectKeys(Collection<QProfileDto> profiles) {
- Set<String> projectKeys = new HashSet<>();
+ private Map<String, String> getProjectKeyAndUuids(Collection<QProfileDto> profiles) {
+ Map<String, String> projectKeyAndUuids = new HashMap<>();
try (DbSession dbSession = dbClient.openSession(false)) {
for (QProfileDto profileDto : profiles) {
List<ProjectQprofileAssociationDto> associationDtos = dbClient.qualityProfileDao().selectSelectedProjects(dbSession, profileDto, null);
for (ProjectQprofileAssociationDto associationDto : associationDtos) {
- projectKeys.add(associationDto.getProjectKey());
+ projectKeyAndUuids.put(associationDto.getProjectKey(), associationDto.getProjectUuid());
}
}
- return projectKeys;
+ return projectKeyAndUuids;
}
}
+ private static byte[] serializeIssueToPushEvent(RuleSetChangedEvent event) {
+ return GSON.toJson(event).getBytes(UTF_8);
+ }
}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleActivatorEventsDistributor.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleActivatorEventsDistributor.java
deleted file mode 100644
index 8914610b28a..00000000000
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleActivatorEventsDistributor.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.qualityprofile;
-
-import org.sonar.core.util.rule.RuleActivationListener;
-import org.sonar.core.util.rule.RuleSetChangedEvent;
-
-public interface RuleActivatorEventsDistributor {
-
- void subscribe(RuleActivationListener listener);
-
- void pushEvent(RuleSetChangedEvent event);
-}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleSetChangeBroadcastUtils.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleSetChangeBroadcastUtils.java
deleted file mode 100644
index 159d67fa593..00000000000
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleSetChangeBroadcastUtils.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.qualityprofile;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.sonar.core.util.ParamChange;
-import org.sonar.core.util.rule.RuleChange;
-import org.sonar.core.util.rule.RuleSetChangedEvent;
-import org.sonar.server.pushapi.sonarlint.SonarLintClient;
-
-import static java.util.Arrays.asList;
-
-public class RuleSetChangeBroadcastUtils {
- private RuleSetChangeBroadcastUtils() {
- }
-
- public static Predicate<SonarLintClient> getFilterForEvent(RuleSetChangedEvent ruleSetChangedEvent) {
- List<String> affectedProjects = asList(ruleSetChangedEvent.getProjects());
- return client -> {
- Set<String> clientProjectKeys = client.getClientProjectKeys();
- Set<String> languages = client.getLanguages();
- return !Collections.disjoint(clientProjectKeys, affectedProjects) && languages.contains(ruleSetChangedEvent.getLanguage());
- };
- }
-
- public static String getMessage(RuleSetChangedEvent ruleSetChangedEvent) {
- return "event: " + ruleSetChangedEvent.getEvent() + "\n"
- + "data: " + toJson(ruleSetChangedEvent);
- }
-
- private static String toJson(RuleSetChangedEvent ruleSetChangedEvent) {
- JSONObject data = new JSONObject();
- data.put("projects", ruleSetChangedEvent.getProjects());
-
- JSONArray activatedRulesJson = new JSONArray();
- for (RuleChange rule : ruleSetChangedEvent.getActivatedRules()) {
- activatedRulesJson.put(toJson(rule));
- }
- data.put("activatedRules", activatedRulesJson);
-
- JSONArray deactivatedRulesJson = new JSONArray();
- for (String ruleKey : ruleSetChangedEvent.getDeactivatedRules()) {
- deactivatedRulesJson.put(ruleKey);
- }
- data.put("deactivatedRules", deactivatedRulesJson);
-
- return data.toString();
- }
-
- private static JSONObject toJson(RuleChange rule) {
- JSONObject ruleJson = new JSONObject();
- ruleJson.put("key", rule.getKey());
- ruleJson.put("language", rule.getLanguage());
- ruleJson.put("severity", rule.getSeverity());
- ruleJson.put("templateKey", rule.getTemplateKey());
-
- JSONArray params = new JSONArray();
- for (ParamChange paramChange : rule.getParams()) {
- params.put(toJson(paramChange));
- }
- ruleJson.put("params", params);
- return ruleJson;
- }
-
- private static JSONObject toJson(ParamChange paramChange) {
- JSONObject param = new JSONObject();
- param.put("key", paramChange.getKey());
- param.put("value", paramChange.getValue());
- return param;
- }
-
-}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/StandaloneRuleActivatorEventsDistributor.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/StandaloneRuleActivatorEventsDistributor.java
deleted file mode 100644
index 64a5d15e10a..00000000000
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/StandaloneRuleActivatorEventsDistributor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.qualityprofile;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.sonar.api.server.ServerSide;
-import org.sonar.core.util.rule.RuleActivationListener;
-import org.sonar.core.util.rule.RuleSetChangedEvent;
-
-@ServerSide
-public class StandaloneRuleActivatorEventsDistributor implements RuleActivatorEventsDistributor {
-
- private List<RuleActivationListener> listeners = new ArrayList<>();
-
- @Override
- public void subscribe(RuleActivationListener listener) {
- listeners.add(listener);
- }
-
- @Override
- public void pushEvent(RuleSetChangedEvent event) {
- listeners.forEach(l -> l.listen(event));
- }
-}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/polling/PushEventPollScheduler.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/polling/PushEventPollScheduler.java
index 3f94d26d4f2..d7b0f9d01ab 100644
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/polling/PushEventPollScheduler.java
+++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/scheduler/polling/PushEventPollScheduler.java
@@ -49,6 +49,7 @@ public class PushEventPollScheduler implements Startable {
private static final Logger LOG = Loggers.get(PushEventPollScheduler.class);
private static final String INITIAL_DELAY_IN_SECONDS = "sonar.pushevents.polling.initial.delay";
+ private static final String LAST_TIMESTAMP_IN_SECONDS = "sonar.pushevents.polling.last.timestamp";
private static final String PERIOD_IN_SECONDS = "sonar.pushevents.polling.period";
private static final String PAGE_SIZE = "sonar.pushevents.polling.page.size";
@@ -91,7 +92,7 @@ public class PushEventPollScheduler implements Startable {
}
if (lastPullTimestamp == null) {
- lastPullTimestamp = system2.now();
+ lastPullTimestamp = getLastPullTimestamp();
}
var projectKeys = getClientsProjectKeys(clients);
@@ -120,7 +121,8 @@ public class PushEventPollScheduler implements Startable {
LOG.debug("Could not find key for project with uuid [{}]", pushEventDto.getProjectUuid());
return Optional.empty();
}
- return Optional.of(new SonarLintPushEvent(pushEventDto.getName(), pushEventDto.getPayload(), resolvedProjectKey));
+ return Optional.of(new SonarLintPushEvent(pushEventDto.getName(), pushEventDto.getPayload(), resolvedProjectKey,
+ pushEventDto.getLanguage()));
}
private static Set<String> getClientsProjectKeys(List<SonarLintClient> clients) {
@@ -154,8 +156,12 @@ public class PushEventPollScheduler implements Startable {
return config.getLong(PERIOD_IN_SECONDS).orElse(40L);
}
+ public long getLastPullTimestamp() {
+ // execute every 40 seconds
+ return config.getLong(LAST_TIMESTAMP_IN_SECONDS).orElse(system2.now());
+ }
+
public long getPageSize() {
- // 20 events per 40 seconds
return config.getLong(PAGE_SIZE).orElse(20L);
}
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java
index 5905f91bb4a..ede8477eea3 100644
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java
+++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java
@@ -24,62 +24,32 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.function.Predicate;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.issue.IssueChangeListener;
-import org.sonar.core.util.issue.IssueChangedEvent;
-import org.sonar.core.util.rule.RuleActivationListener;
-import org.sonar.core.util.rule.RuleSetChangedEvent;
import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.pushapi.issues.IssueChangeBroadcastUtils;
-import org.sonar.server.pushapi.issues.IssueChangeEventsDistributor;
-import org.sonar.server.pushapi.qualityprofile.RuleActivatorEventsDistributor;
-import org.sonar.server.pushapi.qualityprofile.RuleSetChangeBroadcastUtils;
@ServerSide
-public class SonarLintClientsRegistry implements RuleActivationListener, IssueChangeListener {
+public class SonarLintClientsRegistry {
private static final Logger LOG = Loggers.get(SonarLintClientsRegistry.class);
private final SonarLintClientPermissionsValidator sonarLintClientPermissionsValidator;
private final List<SonarLintClient> clients = new CopyOnWriteArrayList<>();
- private final RuleActivatorEventsDistributor ruleEventsDistributor;
- private final IssueChangeEventsDistributor issueChangeEventsDistributor;
- private boolean registeredToEvents = false;
-
- public SonarLintClientsRegistry(IssueChangeEventsDistributor issueChangeEventsDistributor,
- RuleActivatorEventsDistributor ruleActivatorEventsDistributor, SonarLintClientPermissionsValidator permissionsValidator) {
- this.issueChangeEventsDistributor = issueChangeEventsDistributor;
+ public SonarLintClientsRegistry(SonarLintClientPermissionsValidator permissionsValidator) {
this.sonarLintClientPermissionsValidator = permissionsValidator;
- this.ruleEventsDistributor = ruleActivatorEventsDistributor;
}
public void registerClient(SonarLintClient sonarLintClient) {
- ensureListeningToEvents();
clients.add(sonarLintClient);
sonarLintClient.scheduleHeartbeat();
sonarLintClient.addListener(new SonarLintClientEventsListener(sonarLintClient));
LOG.debug("Registering new SonarLint client");
}
- private synchronized void ensureListeningToEvents() {
- if (registeredToEvents) {
- return;
- }
- try {
- ruleEventsDistributor.subscribe(this);
- issueChangeEventsDistributor.subscribe(this);
- registeredToEvents = true;
- } catch (RuntimeException e) {
- LOG.warn("Can not listen to rule activation or issue events for server push. Web Server might not have started fully yet.", e);
- }
- }
-
public void unregisterClient(SonarLintClient client) {
client.close();
clients.remove(client);
@@ -94,18 +64,8 @@ public class SonarLintClientsRegistry implements RuleActivationListener, IssueCh
return clients.size();
}
- @Override
- public void listen(RuleSetChangedEvent ruleSetChangedEvent) {
- broadcastMessage(ruleSetChangedEvent, RuleSetChangeBroadcastUtils.getFilterForEvent(ruleSetChangedEvent));
- }
-
- @Override
- public void listen(IssueChangedEvent issueChangedEvent) {
- broadcastMessage(issueChangedEvent, IssueChangeBroadcastUtils.getFilterForEvent(issueChangedEvent));
- }
-
public void broadcastMessage(SonarLintPushEvent event) {
- clients.stream().filter(client -> client.getClientProjectKeys().contains(event.getProjectKey()))
+ clients.stream().filter(client -> isRelevantEvent(event, client))
.forEach(c -> {
Set<String> clientProjectKeys = new HashSet<>(c.getClientProjectKeys());
clientProjectKeys.retainAll(Set.of(event.getProjectKey()));
@@ -122,42 +82,9 @@ public class SonarLintClientsRegistry implements RuleActivationListener, IssueCh
});
}
- public void broadcastMessage(RuleSetChangedEvent event, Predicate<SonarLintClient> filter) {
- clients.stream().filter(filter).forEach(c -> {
- Set<String> projectKeysInterestingForClient = new HashSet<>(c.getClientProjectKeys());
- projectKeysInterestingForClient.retainAll(Set.of(event.getProjects()));
- try {
- sonarLintClientPermissionsValidator.validateUserCanReceivePushEventForProjects(c.getUserUuid(), projectKeysInterestingForClient);
- RuleSetChangedEvent personalizedEvent = new RuleSetChangedEvent(projectKeysInterestingForClient.toArray(String[]::new), event.getActivatedRules(),
- event.getDeactivatedRules(), event.getLanguage());
- String message = RuleSetChangeBroadcastUtils.getMessage(personalizedEvent);
- c.writeAndFlush(message);
- } catch (ForbiddenException forbiddenException) {
- logClientUnauthenticated(forbiddenException);
- unregisterClient(c);
- } catch (IllegalStateException | IOException e) {
- logUnexpectedError(e);
- unregisterClient(c);
- }
- });
- }
-
- public void broadcastMessage(IssueChangedEvent event, Predicate<SonarLintClient> filter) {
- clients.stream().filter(filter).forEach(c -> {
- Set<String> projectKeysInterestingForClient = new HashSet<>(c.getClientProjectKeys());
- projectKeysInterestingForClient.retainAll(Set.of(event.getProjectKey()));
- try {
- sonarLintClientPermissionsValidator.validateUserCanReceivePushEventForProjects(c.getUserUuid(), projectKeysInterestingForClient);
- String message = IssueChangeBroadcastUtils.getMessage(event);
- c.writeAndFlush(message);
- } catch (ForbiddenException forbiddenException) {
- logClientUnauthenticated(forbiddenException);
- unregisterClient(c);
- } catch (IllegalStateException | IOException e) {
- logUnexpectedError(e);
- unregisterClient(c);
- }
- });
+ private static boolean isRelevantEvent(SonarLintPushEvent event, SonarLintClient client) {
+ return client.getClientProjectKeys().contains(event.getProjectKey())
+ && (!event.getName().equals("RuleSetChanged") || client.getLanguages().contains(event.getLanguage()));
}
private static void logUnexpectedError(Exception e) {
diff --git a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintPushEvent.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintPushEvent.java
index 5484fb17602..9e7ee98f044 100644
--- a/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintPushEvent.java
+++ b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintPushEvent.java
@@ -19,6 +19,9 @@
*/
package org.sonar.server.pushapi.sonarlint;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
import static java.nio.charset.StandardCharsets.UTF_8;
public class SonarLintPushEvent {
@@ -26,17 +29,24 @@ public class SonarLintPushEvent {
private final String name;
private final byte[] data;
private final String projectKey;
+ private final String language;
- public SonarLintPushEvent(String name, byte[] data, String projectKey) {
+ public SonarLintPushEvent(String name, byte[] data, String projectKey, @Nullable String language) {
this.name = name;
this.data = data;
this.projectKey = projectKey;
+ this.language = language;
}
public String getProjectKey() {
return projectKey;
}
+ @CheckForNull
+ public String getLanguage() {
+ return language;
+ }
+
public String getName() {
return name;
}
diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/DistributedIssueChangeEventsDistributorTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/DistributedIssueChangeEventsDistributorTest.java
deleted file mode 100644
index b08a831cb47..00000000000
--- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/DistributedIssueChangeEventsDistributorTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.issues;
-
-import org.junit.Test;
-import org.sonar.core.util.issue.IssueChangeListener;
-import org.sonar.core.util.issue.IssueChangedEvent;
-import org.sonar.process.cluster.hz.HazelcastMember;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class DistributedIssueChangeEventsDistributorTest {
- HazelcastMember hazelcastMember = mock(HazelcastMember.class);
- IssueChangeListener issueChangeListener = mock(IssueChangeListener.class);
- IssueChangedEvent event = mock(IssueChangedEvent.class);
-
- public final DistributedIssueChangeEventsDistributor underTest = new DistributedIssueChangeEventsDistributor(hazelcastMember);
-
- @Test
- public void subscribe_subscribesHazelCastMember() {
- underTest.subscribe(issueChangeListener);
- verify(hazelcastMember).subscribeIssueChangeTopic(issueChangeListener);
- }
-
- @Test
- public void pushEvent_publishesEvent() {
- underTest.pushEvent(event);
- verify(hazelcastMember).publishEvent(event);
- }
-}
diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeBroadcastUtilsTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeBroadcastUtilsTest.java
deleted file mode 100644
index 8e65c839b02..00000000000
--- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeBroadcastUtilsTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.issues;
-
-import java.util.Set;
-import java.util.function.Predicate;
-import javax.servlet.AsyncContext;
-import org.junit.Test;
-import org.sonar.core.util.issue.Issue;
-import org.sonar.core.util.issue.IssueChangedEvent;
-import org.sonar.server.pushapi.sonarlint.SonarLintClient;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class IssueChangeBroadcastUtilsTest {
-
- private final String PROJECT_KEY = "projectKey";
- private final String USER_UUID = "userUUID";
- private final AsyncContext asyncContext = mock(AsyncContext.class);
-
- @Test
- public void getsFilterForEvent() {
- Issue[] issues = new Issue[]{ new Issue("issue-1", "branch-1")};
- IssueChangedEvent issueChangedEvent = new IssueChangedEvent(PROJECT_KEY, issues, true, "BLOCKER", "BUG");
- Predicate<SonarLintClient> predicate = IssueChangeBroadcastUtils.getFilterForEvent(issueChangedEvent);
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of(PROJECT_KEY), Set.of(), USER_UUID))).isTrue();
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of(), Set.of(), USER_UUID))).isFalse();
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of("another-project"), Set.of(), USER_UUID))).isFalse();
- }
-
- @Test
- public void getsMessageForEvent() {
- Issue[] issues = new Issue[]{ new Issue("issue-1", "branch-1")};
- IssueChangedEvent issueChangedEvent = new IssueChangedEvent(PROJECT_KEY, issues, true, "BLOCKER", "BUG");
- String message = IssueChangeBroadcastUtils.getMessage(issueChangedEvent);
-
- assertThat(message).isEqualTo("event: IssueChangedEvent\n" +
- "data: {\"projectKey\":\""+ PROJECT_KEY+"\"," +
- "\"userType\":\"BUG\"," +
- "\"issues\":[{\"issueKey\":\"issue-1\",\"branchName\":\"branch-1\"}]," +
- "\"userSeverity\":\"BLOCKER\"," +
- "\"resolved\":true}");
- }
-}
diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImplTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImplTest.java
index 91d543e2e73..d8749bc4752 100644
--- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImplTest.java
+++ b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/IssueChangeEventServiceImplTest.java
@@ -19,34 +19,30 @@
*/
package org.sonar.server.pushapi.issues;
+import java.nio.charset.StandardCharsets;
+import java.util.Deque;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import org.sonar.api.rules.RuleType;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.FieldDiffs;
-import org.sonar.core.util.issue.IssueChangedEvent;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.project.ProjectDto;
+import org.sonar.db.pushevent.PushEventDto;
import org.sonar.db.rule.RuleDto;
import org.sonarqube.ws.Common;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.sonar.api.issue.DefaultTransitions.CONFIRM;
import static org.sonar.api.issue.DefaultTransitions.FALSE_POSITIVE;
import static org.sonar.api.issue.DefaultTransitions.REOPEN;
@@ -64,9 +60,7 @@ public class IssueChangeEventServiceImplTest {
@Rule
public DbTester db = DbTester.create();
- IssueChangeEventsDistributor eventsDistributor = mock(IssueChangeEventsDistributor.class);
-
- public final IssueChangeEventServiceImpl underTest = new IssueChangeEventServiceImpl(eventsDistributor);
+ public final IssueChangeEventServiceImpl underTest = new IssueChangeEventServiceImpl(db.getDbClient());
@Test
public void distributeIssueChangeEvent_singleIssueChange_severityChange() {
@@ -74,9 +68,9 @@ public class IssueChangeEventServiceImplTest {
ProjectDto project = db.getDbClient().projectDao().selectByUuid(db.getSession(), componentDto.uuid()).get();
BranchDto branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), project.getUuid()).get();
RuleDto rule = db.rules().insert();
- IssueDto issue = db.issues().insert(rule, project, componentDto, i-> i.setSeverity(MAJOR.name()));
+ IssueDto issue = db.issues().insert(rule, project, componentDto, i -> i.setSeverity(MAJOR.name()));
- assertIssueDistribution(project, branch, issue, BLOCKER.name(), null, null, null, 1);
+ assertPushEventIsPersisted(project, branch, issue, BLOCKER.name(), null, null, null, 1);
}
@Test
@@ -85,9 +79,9 @@ public class IssueChangeEventServiceImplTest {
ProjectDto project = db.getDbClient().projectDao().selectByUuid(db.getSession(), componentDto.uuid()).get();
BranchDto branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), project.getUuid()).get();
RuleDto rule = db.rules().insert();
- IssueDto issue = db.issues().insert(rule, project, componentDto, i-> i.setSeverity(MAJOR.name()));
+ IssueDto issue = db.issues().insert(rule, project, componentDto, i -> i.setSeverity(MAJOR.name()));
- assertIssueDistribution(project, branch, issue, null, Common.RuleType.BUG.name(), null, null, 1);
+ assertPushEventIsPersisted(project, branch, issue, null, Common.RuleType.BUG.name(), null, null, 1);
}
@Test
@@ -96,16 +90,16 @@ public class IssueChangeEventServiceImplTest {
ProjectDto project = db.getDbClient().projectDao().selectByUuid(db.getSession(), componentDto.uuid()).get();
BranchDto branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), project.getUuid()).get();
RuleDto rule = db.rules().insert();
- IssueDto issue = db.issues().insert(rule, project, componentDto, i-> i.setSeverity(MAJOR.name()));
-
- assertIssueDistribution(project, branch, issue, null, null, WONT_FIX, true, 1);
- assertIssueDistribution(project, branch, issue, null, null, REOPEN, false, 2);
- assertIssueDistribution(project, branch, issue, null, null, FALSE_POSITIVE, true, 3);
- assertIssueDistribution(project, branch, issue, null, null, REOPEN, false, 4);
- assertIssueDistribution(project, branch, issue, null, null, RESOLVE, false, 5);
- assertIssueDistribution(project, branch, issue, null, null, REOPEN, false, 6);
- assertNoIssueDistribution(project, branch, issue, null, null, CONFIRM);
- assertNoIssueDistribution(project, branch, issue, null, null, UNCONFIRM);
+ IssueDto issue = db.issues().insert(rule, project, componentDto, i -> i.setSeverity(MAJOR.name()));
+
+ assertPushEventIsPersisted(project, branch, issue, null, null, WONT_FIX, true, 1);
+ assertPushEventIsPersisted(project, branch, issue, null, null, REOPEN, false, 2);
+ assertPushEventIsPersisted(project, branch, issue, null, null, FALSE_POSITIVE, true, 3);
+ assertPushEventIsPersisted(project, branch, issue, null, null, REOPEN, false, 4);
+ assertPushEventIsPersisted(project, branch, issue, null, null, RESOLVE, false, 5);
+ assertPushEventIsPersisted(project, branch, issue, null, null, REOPEN, false, 6);
+ assertNoIssueDistribution(project, branch, issue, null, null, CONFIRM, 7);
+ assertNoIssueDistribution(project, branch, issue, null, null, UNCONFIRM, 8);
}
@Test
@@ -114,9 +108,9 @@ public class IssueChangeEventServiceImplTest {
ProjectDto project = db.getDbClient().projectDao().selectByUuid(db.getSession(), componentDto.uuid()).get();
BranchDto branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), project.getUuid()).get();
RuleDto rule = db.rules().insert();
- IssueDto issue = db.issues().insert(rule, project, componentDto, i-> i.setSeverity(MAJOR.name()));
+ IssueDto issue = db.issues().insert(rule, project, componentDto, i -> i.setSeverity(MAJOR.name()));
- assertIssueDistribution(project, branch, issue, BLOCKER.name(), Common.RuleType.BUG.name(), WONT_FIX, true, 1);
+ assertPushEventIsPersisted(project, branch, issue, BLOCKER.name(), Common.RuleType.BUG.name(), WONT_FIX, true, 1);
}
@Test
@@ -126,17 +120,17 @@ public class IssueChangeEventServiceImplTest {
ComponentDto componentDto1 = db.components().insertPublicProject();
ProjectDto project1 = db.getDbClient().projectDao().selectByUuid(db.getSession(), componentDto1.uuid()).get();
BranchDto branch1 = db.getDbClient().branchDao().selectByUuid(db.getSession(), project1.getUuid()).get();
- IssueDto issue1 = db.issues().insert(rule, project1, componentDto1, i-> i.setSeverity(MAJOR.name()).setType(RuleType.BUG));
+ IssueDto issue1 = db.issues().insert(rule, project1, componentDto1, i -> i.setSeverity(MAJOR.name()).setType(RuleType.BUG));
ComponentDto componentDto2 = db.components().insertPublicProject();
ProjectDto project2 = db.getDbClient().projectDao().selectByUuid(db.getSession(), componentDto2.uuid()).get();
BranchDto branch2 = db.getDbClient().branchDao().selectByUuid(db.getSession(), project2.getUuid()).get();
- IssueDto issue2 = db.issues().insert(rule, project2, componentDto2, i-> i.setSeverity(MAJOR.name()).setType(RuleType.BUG));
+ IssueDto issue2 = db.issues().insert(rule, project2, componentDto2, i -> i.setSeverity(MAJOR.name()).setType(RuleType.BUG));
ComponentDto componentDto3 = db.components().insertPublicProject();
ProjectDto project3 = db.getDbClient().projectDao().selectByUuid(db.getSession(), componentDto3.uuid()).get();
BranchDto branch3 = db.getDbClient().branchDao().selectByUuid(db.getSession(), project3.getUuid()).get();
- IssueDto issue3 = db.issues().insert(rule, project3, componentDto3, i-> i.setSeverity(MAJOR.name()).setType(RuleType.BUG));
+ IssueDto issue3 = db.issues().insert(rule, project3, componentDto3, i -> i.setSeverity(MAJOR.name()).setType(RuleType.BUG));
DefaultIssue defaultIssue1 = issue1.toDefaultIssue().setCurrentChangeWithoutAddChange(new FieldDiffs()
.setDiff("resolution", null, null)
@@ -159,18 +153,35 @@ public class IssueChangeEventServiceImplTest {
underTest.distributeIssueChangeEvent(issues, projectsByUuid, branchesByProjectUuid);
- ArgumentCaptor<IssueChangedEvent> eventCaptor = ArgumentCaptor.forClass(IssueChangedEvent.class);
- verify(eventsDistributor, times(2)).pushEvent(eventCaptor.capture());
+ Deque<PushEventDto> issueChangedEvents = db.getDbClient().pushEventDao()
+ .selectChunkByProjectUuids(db.getSession(), Set.of(project1.getUuid(), project2.getUuid()),
+ 1l, null, 3);
- List<IssueChangedEvent> issueChangedEvents = eventCaptor.getAllValues();
assertThat(issueChangedEvents).hasSize(2);
assertThat(issueChangedEvents)
- .extracting(IssueChangedEvent::getEvent, IssueChangedEvent::getProjectKey,
- IssueChangedEvent::getUserSeverity, IssueChangedEvent::getUserType, IssueChangedEvent::getResolved)
+ .extracting(PushEventDto::getName, PushEventDto::getProjectUuid)
.containsExactlyInAnyOrder(
- tuple("IssueChangedEvent", project1.getKey(), CRITICAL.name(), CODE_SMELL.name(), false),
- tuple("IssueChangedEvent", project2.getKey(), CRITICAL.name(), CODE_SMELL.name(), true));
+ tuple("IssueChanged", project1.getUuid()),
+ tuple("IssueChanged", project2.getUuid()));
+
+ Optional<PushEventDto> project1Event = issueChangedEvents.stream().filter(e -> e.getProjectUuid().equals(project1.getUuid())).findFirst();
+ Optional<PushEventDto> project2Event = issueChangedEvents.stream().filter(e -> e.getProjectUuid().equals(project2.getUuid())).findFirst();
+
+ assertThat(project1Event).isPresent();
+ assertThat(project2Event).isPresent();
+
+ String firstPayload = new String(project1Event.get().getPayload(), StandardCharsets.UTF_8);
+ assertThat(firstPayload)
+ .contains("\"userSeverity\":\"" + CRITICAL.name() + "\"",
+ "\"userType\":\"" + CODE_SMELL.name() + "\"",
+ "\"resolved\":" + false);
+
+ String secondPayload = new String(project2Event.get().getPayload(), StandardCharsets.UTF_8);
+ assertThat(secondPayload)
+ .contains("\"userSeverity\":\"" + CRITICAL.name() + "\"",
+ "\"userType\":\"" + CODE_SMELL.name() + "\"",
+ "\"resolved\":" + true);
}
@Test
@@ -183,7 +194,7 @@ public class IssueChangeEventServiceImplTest {
.setMergeBranchUuid(project.uuid()));
BranchDto branch1 = db.getDbClient().branchDao().selectByUuid(db.getSession(), pullRequest.uuid()).get();
ComponentDto file = db.components().insertComponent(newFileDto(pullRequest));
- IssueDto issue1 = db.issues().insert(rule, pullRequest, file, i-> i.setSeverity(MAJOR.name()).setType(RuleType.BUG));
+ IssueDto issue1 = db.issues().insert(rule, pullRequest, file, i -> i.setSeverity(MAJOR.name()).setType(RuleType.BUG));
DefaultIssue defaultIssue1 = issue1.toDefaultIssue().setCurrentChangeWithoutAddChange(new FieldDiffs()
.setDiff("resolution", null, null)
@@ -198,29 +209,40 @@ public class IssueChangeEventServiceImplTest {
underTest.distributeIssueChangeEvent(issues, projectsByUuid, branchesByProjectUuid);
- verifyNoInteractions(eventsDistributor);
}
- private void assertIssueDistribution(ProjectDto project, BranchDto branch, IssueDto issue, @Nullable String severity,
- @Nullable String type, @Nullable String transition, Boolean resolved, int times) {
+ private void assertNoIssueDistribution(ProjectDto project, BranchDto branch, IssueDto issue, @Nullable String severity,
+ @Nullable String type, @Nullable String transition, int page) {
underTest.distributeIssueChangeEvent(issue.toDefaultIssue(), severity, type, transition, branch, project.getKey());
- ArgumentCaptor<IssueChangedEvent> eventCaptor = ArgumentCaptor.forClass(IssueChangedEvent.class);
- verify(eventsDistributor, times(times)).pushEvent(eventCaptor.capture());
-
- IssueChangedEvent issueChangedEvent = eventCaptor.getValue();
- assertThat(issueChangedEvent).isNotNull();
- assertThat(issueChangedEvent).extracting(IssueChangedEvent::getEvent, IssueChangedEvent::getProjectKey,
- IssueChangedEvent::getUserSeverity, IssueChangedEvent::getUserType, IssueChangedEvent::getResolved)
- .containsExactly("IssueChangedEvent", project.getKey(), severity, type, resolved);
+ Deque<PushEventDto> events = db.getDbClient().pushEventDao()
+ .selectChunkByProjectUuids(db.getSession(), Set.of(project.getUuid()), 1l, null, page);
+ assertThat(events).hasSizeLessThan(page);
}
- private void assertNoIssueDistribution(ProjectDto project, BranchDto branch, IssueDto issue, @Nullable String severity,
- @Nullable String type, @Nullable String transition) {
+ private void assertPushEventIsPersisted(ProjectDto project, BranchDto branch, IssueDto issue, @Nullable String severity,
+ @Nullable String type, @Nullable String transition, Boolean resolved, int page) {
underTest.distributeIssueChangeEvent(issue.toDefaultIssue(), severity, type, transition, branch, project.getKey());
- ArgumentCaptor<IssueChangedEvent> eventCaptor = ArgumentCaptor.forClass(IssueChangedEvent.class);
- verifyNoMoreInteractions(eventsDistributor);
+ Deque<PushEventDto> events = db.getDbClient().pushEventDao()
+ .selectChunkByProjectUuids(db.getSession(), Set.of(project.getUuid()), 1l, null, page);
+ assertThat(events).isNotEmpty();
+ assertThat(events).extracting(PushEventDto::getName, PushEventDto::getProjectUuid)
+ .contains(tuple("IssueChanged", project.getUuid()));
+
+ String payload = new String(events.getLast().getPayload(), StandardCharsets.UTF_8);
+ if (severity != null) {
+ assertThat(payload).contains("\"userSeverity\":\"" + severity + "\"");
+ }
+
+ if (type != null) {
+ assertThat(payload).contains("\"userType\":\"" + type + "\"");
+ }
+
+ if (resolved != null) {
+ assertThat(payload).contains("\"resolved\":" + resolved);
+ }
+
}
}
diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/StandaloneIssueChangeEventsDistributorTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/StandaloneIssueChangeEventsDistributorTest.java
deleted file mode 100644
index b3b9e0b84d9..00000000000
--- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/issues/StandaloneIssueChangeEventsDistributorTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.issues;
-
-import org.junit.Test;
-import org.sonar.core.util.issue.IssueChangeListener;
-import org.sonar.core.util.issue.IssueChangedEvent;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class StandaloneIssueChangeEventsDistributorTest {
- IssueChangeListener issueChangeListener = mock(IssueChangeListener.class);
- IssueChangedEvent event = mock(IssueChangedEvent.class);
-
- public final StandaloneIssueChangeEventsDistributor underTest = new StandaloneIssueChangeEventsDistributor();
-
- @Test
- public void subscribe_and_push_publishesToListener() {
- underTest.subscribe(issueChangeListener);
- underTest.pushEvent(event);
- verify(issueChangeListener).listen(event);
- }
-}
diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java
index 3484c38d878..1cab5c35a69 100644
--- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java
+++ b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImplTest.java
@@ -19,17 +19,17 @@
*/
package org.sonar.server.pushapi.qualityprofile;
+import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
+import java.util.Deque;
+import java.util.Set;
import org.junit.Rule;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import org.sonar.api.rule.RuleKey;
-import org.sonar.core.util.ParamChange;
-import org.sonar.core.util.rule.RuleChange;
-import org.sonar.core.util.rule.RuleSetChangedEvent;
import org.sonar.db.DbTester;
import org.sonar.db.project.ProjectDto;
+import org.sonar.db.pushevent.PushEventDto;
import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.ActiveRuleParamDto;
import org.sonar.db.qualityprofile.QProfileDto;
@@ -37,14 +37,11 @@ import org.sonar.db.qualityprofile.QualityProfileTesting;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleParamDto;
import org.sonar.server.qualityprofile.ActiveRuleChange;
+import org.sonarqube.ws.Common;
import static java.util.List.of;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection;
import static org.sonar.db.rule.RuleTesting.newCustomRule;
import static org.sonar.db.rule.RuleTesting.newTemplateRule;
import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
@@ -54,9 +51,7 @@ public class QualityProfileChangeEventServiceImplTest {
@Rule
public DbTester db = DbTester.create();
- RuleActivatorEventsDistributor eventsDistributor = mock(RuleActivatorEventsDistributor.class);
-
- public final QualityProfileChangeEventServiceImpl underTest = new QualityProfileChangeEventServiceImpl(db.getDbClient(), eventsDistributor);
+ public final QualityProfileChangeEventServiceImpl underTest = new QualityProfileChangeEventServiceImpl(db.getDbClient());
@Test
public void distributeRuleChangeEvent() {
@@ -84,33 +79,27 @@ public class QualityProfileChangeEventServiceImplTest {
underTest.distributeRuleChangeEvent(profiles, of(activeRuleChange), "xoo");
- ArgumentCaptor<RuleSetChangedEvent> eventCaptor = ArgumentCaptor.forClass(RuleSetChangedEvent.class);
- verify(eventsDistributor).pushEvent(eventCaptor.capture());
-
- RuleSetChangedEvent ruleSetChangedEvent = eventCaptor.getValue();
- assertThat(ruleSetChangedEvent).isNotNull();
- assertThat(ruleSetChangedEvent).extracting(RuleSetChangedEvent::getEvent,
- RuleSetChangedEvent::getLanguage, RuleSetChangedEvent::getProjects)
- .containsExactly("RuleSetChanged", "xoo", new String[]{project.getKey()});
-
- assertThat(ruleSetChangedEvent.getActivatedRules())
- .extracting(RuleChange::getKey, RuleChange::getLanguage,
- RuleChange::getSeverity, RuleChange::getTemplateKey)
- .containsExactly(tuple("repo:ruleKey", "xoo", null, "xoo:template-key"));
+ Deque<PushEventDto> events = db.getDbClient().pushEventDao()
+ .selectChunkByProjectUuids(db.getSession(), Set.of(project.getUuid()), 1l, null, 1);
- assertThat(ruleSetChangedEvent.getActivatedRules()[0].getParams()).hasSize(1);
- ParamChange actualParamChange = ruleSetChangedEvent.getActivatedRules()[0].getParams()[0];
- assertThat(actualParamChange)
- .extracting(ParamChange::getKey, ParamChange::getValue)
- .containsExactly("paramChangeKey", "paramChangeValue");
+ assertThat(events).isNotEmpty().hasSize(1);
+ assertThat(events.getFirst())
+ .extracting(PushEventDto::getName, PushEventDto::getLanguage)
+ .contains("RuleSetChanged", "xoo");
- assertThat(ruleSetChangedEvent.getDeactivatedRules()).isEmpty();
+ String ruleSetChangedEvent = new String(events.getFirst().getPayload(), StandardCharsets.UTF_8);
+ assertThat(ruleSetChangedEvent)
+ .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," +
+ "\"language\":\"xoo\"," +
+ "\"templateKey\":\"xoo:template-key\"," +
+ "\"params\":[{\"key\":\"paramChangeKey\",\"value\":\"paramChangeValue\"}]}]," +
+ "\"deactivatedRules\":[]");
}
@Test
public void publishRuleActivationToSonarLintClients() {
- ProjectDto projectDao = new ProjectDto();
+ ProjectDto projectDao = new ProjectDto().setUuid("project-uuid");
QProfileDto activatedQualityProfile = QualityProfileTesting.newQualityProfileDto();
activatedQualityProfile.setLanguage("xoo");
db.qualityProfiles().insert(activatedQualityProfile);
@@ -134,30 +123,21 @@ public class QualityProfileChangeEventServiceImplTest {
underTest.publishRuleActivationToSonarLintClients(projectDao, activatedQualityProfile, deactivatedQualityProfile);
- ArgumentCaptor<RuleSetChangedEvent> eventCaptor = ArgumentCaptor.forClass(RuleSetChangedEvent.class);
- verify(eventsDistributor).pushEvent(eventCaptor.capture());
-
- RuleSetChangedEvent ruleSetChangedEvent = eventCaptor.getValue();
- assertThat(ruleSetChangedEvent).isNotNull();
- assertThat(ruleSetChangedEvent).extracting(RuleSetChangedEvent::getEvent,
- RuleSetChangedEvent::getLanguage, RuleSetChangedEvent::getProjects)
- .containsExactly("RuleSetChanged", "xoo", new String[]{null});
-
- // activated rule
- assertThat(ruleSetChangedEvent.getActivatedRules())
- .extracting(RuleChange::getKey, RuleChange::getLanguage,
- RuleChange::getSeverity, RuleChange::getTemplateKey)
- .containsExactly(tuple("repo:ruleKey", "xoo", rule1.getSeverityString(), null));
-
- assertThat(ruleSetChangedEvent.getActivatedRules()[0].getParams()).hasSize(1);
- ParamChange actualParamChange = ruleSetChangedEvent.getActivatedRules()[0].getParams()[0];
- assertThat(actualParamChange)
- .extracting(ParamChange::getKey, ParamChange::getValue)
- .containsExactly(activeRuleParam1.getKey(), activeRuleParam1.getValue());
-
- // deactivated rule
- assertThat(ruleSetChangedEvent.getDeactivatedRules())
- .containsExactly("repo2:ruleKey2");
+ Deque<PushEventDto> events = db.getDbClient().pushEventDao()
+ .selectChunkByProjectUuids(db.getSession(), Set.of(projectDao.getUuid()), 1l, null, 1);
+
+ assertThat(events).isNotEmpty().hasSize(1);
+ assertThat(events.getFirst())
+ .extracting(PushEventDto::getName, PushEventDto::getLanguage)
+ .contains("RuleSetChanged", "xoo");
+
+ String ruleSetChangedEvent = new String(events.getFirst().getPayload(), StandardCharsets.UTF_8);
+
+ assertThat(ruleSetChangedEvent)
+ .contains("\"activatedRules\":[{\"key\":\"repo:ruleKey\"," +
+ "\"language\":\"xoo\",\"severity\":\"" + Common.Severity.forNumber(rule1.getSeverity()).name() + "\"," +
+ "\"params\":[{\"key\":\"" + activeRuleParam1.getKey() + "\",\"value\":\"" + activeRuleParam1.getValue() + "\"}]}]," +
+ "\"deactivatedRules\":[\"repo2:ruleKey2\"]");
}
}
diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/RuleSetChangeBroadcastUtilsTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/RuleSetChangeBroadcastUtilsTest.java
deleted file mode 100644
index e36a5df6fc5..00000000000
--- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/qualityprofile/RuleSetChangeBroadcastUtilsTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.pushapi.qualityprofile;
-
-import java.util.Set;
-import java.util.function.Predicate;
-import javax.servlet.AsyncContext;
-import org.junit.Test;
-import org.sonar.api.rule.Severity;
-import org.sonar.core.util.ParamChange;
-import org.sonar.core.util.rule.RuleChange;
-import org.sonar.core.util.rule.RuleSetChangedEvent;
-import org.sonar.server.pushapi.sonarlint.SonarLintClient;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class RuleSetChangeBroadcastUtilsTest {
-
- private final static String JAVA_KEY = "java";
- private final static String PROJECT_KEY_1 = "projectKey1";
- private final static String PROJECT_KEY_2 = "projectKey2";
- private final static String USER_UUID = "userUUID";
- private final static String[] DEACTIVATED_RULES = {"repo2:rule-key2"};
-
- private final static Set<String> EXAMPLE_KEYS = Set.of(PROJECT_KEY_1, PROJECT_KEY_2);
-
- private final AsyncContext asyncContext = mock(AsyncContext.class);
-
- @Test
- public void getsFilterForEvent() {
- RuleChange javaRule = new RuleChange();
- javaRule.setLanguage(JAVA_KEY);
- javaRule.setParams(new ParamChange[]{new ParamChange("param-key", "param-value")});
- javaRule.setTemplateKey("repo:template-key");
- javaRule.setSeverity(Severity.CRITICAL);
- javaRule.setKey("repo:rule-key");
-
- RuleChange[] activatedRules = {javaRule};
- RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(EXAMPLE_KEYS.toArray(String[]::new), activatedRules,
- DEACTIVATED_RULES, JAVA_KEY);
- Predicate<SonarLintClient> predicate = RuleSetChangeBroadcastUtils.getFilterForEvent(ruleSetChangedEvent);
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of(PROJECT_KEY_1), Set.of(JAVA_KEY), USER_UUID))).isTrue();
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of(PROJECT_KEY_2), Set.of(JAVA_KEY), USER_UUID))).isTrue();
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of(PROJECT_KEY_1), Set.of(), USER_UUID))).isFalse();
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of(), Set.of(JAVA_KEY), USER_UUID))).isFalse();
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of("another-project"), Set.of(), USER_UUID))).isFalse();
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of(""), Set.of("another-language"), USER_UUID))).isFalse();
- assertThat(predicate.test(new SonarLintClient(asyncContext, Set.of("another-project"), Set.of("another-language"), USER_UUID))).isFalse();
- }
-
- @Test
- public void getsMessageForEvent() {
- RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(new String[]{PROJECT_KEY_1}, new RuleChange[0],
- DEACTIVATED_RULES, JAVA_KEY);
-
- String message = RuleSetChangeBroadcastUtils.getMessage(ruleSetChangedEvent);
-
- assertThat(message).isEqualTo("event: RuleSetChanged\n" +
- "data: {\"activatedRules\":[]," +
- "\"projects\":[\"" + PROJECT_KEY_1 + "\"]," +
- "\"deactivatedRules\":[\"repo2:rule-key2\"]}");
- }
-}
diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistryTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistryTest.java
index 517c8a39b65..2f5867216dc 100644
--- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistryTest.java
+++ b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistryTest.java
@@ -28,15 +28,7 @@ import javax.servlet.ServletResponse;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
-import org.sonar.api.rule.Severity;
-import org.sonar.core.util.ParamChange;
-import org.sonar.core.util.issue.Issue;
-import org.sonar.core.util.issue.IssueChangedEvent;
-import org.sonar.core.util.rule.RuleChange;
-import org.sonar.core.util.rule.RuleSetChangedEvent;
import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.pushapi.issues.StandaloneIssueChangeEventsDistributor;
-import org.sonar.server.pushapi.qualityprofile.StandaloneRuleActivatorEventsDistributor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -52,6 +44,7 @@ import static org.mockito.Mockito.when;
import static org.sonar.test.EventAssert.assertThatEvent;
public class SonarLintClientsRegistryTest {
+ private static final String EVENT_NAME = "RuleSetChanged";
private final AsyncContext defaultAsyncContext = mock(AsyncContext.class);
@@ -62,14 +55,12 @@ public class SonarLintClientsRegistryTest {
private final ServletOutputStream outputStream = mock(ServletOutputStream.class);
private final SonarLintClientPermissionsValidator permissionsValidator = mock(SonarLintClientPermissionsValidator.class);
- private final StandaloneRuleActivatorEventsDistributor ruleEventsDistributor = mock(StandaloneRuleActivatorEventsDistributor.class);
- private final StandaloneIssueChangeEventsDistributor issueChangeEventsDistributor = mock(StandaloneIssueChangeEventsDistributor.class);
private SonarLintClientsRegistry underTest;
@Before
public void before() {
- underTest = new SonarLintClientsRegistry(issueChangeEventsDistributor, ruleEventsDistributor, permissionsValidator);
+ underTest = new SonarLintClientsRegistry(permissionsValidator);
}
@Test
@@ -100,7 +91,7 @@ public class SonarLintClientsRegistryTest {
}
@Test
- public void listen_givenOneClientInterestedInJavaEvents_sendOneJavaEvent() throws IOException {
+ public void listen_givenOneClientInterestedInJavaEvents_sendAllJavaEvents() throws IOException {
Set<String> javaLanguageKey = Set.of("java");
when(defaultAsyncContext.getResponse()).thenReturn(response);
when(response.getOutputStream()).thenReturn(outputStream);
@@ -108,19 +99,36 @@ public class SonarLintClientsRegistryTest {
underTest.registerClient(sonarLintClient);
- RuleChange javaRule = createRuleChange();
+ SonarLintPushEvent event1 = new SonarLintPushEvent(EVENT_NAME, "data".getBytes(StandardCharsets.UTF_8), "project1", "java");
+ SonarLintPushEvent event2 = new SonarLintPushEvent(EVENT_NAME, "data".getBytes(StandardCharsets.UTF_8), "project2", "java");
+ SonarLintPushEvent event3 = new SonarLintPushEvent(EVENT_NAME, "data".getBytes(StandardCharsets.UTF_8), "project3", "java");
- RuleChange[] activatedRules = {javaRule};
- String[] deactivatedRules = {"repo2:rule-key2"};
- RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules, "java");
- underTest.listen(ruleSetChangedEvent);
+ underTest.broadcastMessage(event1);
ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
verify(outputStream).write(captor.capture());
String message = new String(captor.getValue());
assertThatEvent(message)
- .hasType("RuleSetChanged")
- .hasJsonData(getClass().getResource("rule-change-event-data.json"));
+ .hasType(EVENT_NAME);
+
+ clearInvocations(outputStream);
+
+ underTest.broadcastMessage(event2);
+
+ verify(outputStream).write(captor.capture());
+ message = new String(captor.getValue());
+ assertThatEvent(message)
+ .hasType(EVENT_NAME);
+
+ clearInvocations(outputStream);
+
+
+ underTest.broadcastMessage(event3);
+
+ verify(outputStream).write(captor.capture());
+ message = new String(captor.getValue());
+ assertThatEvent(message)
+ .hasType(EVENT_NAME);
}
@Test
@@ -132,10 +140,9 @@ public class SonarLintClientsRegistryTest {
underTest.registerClient(sonarLintClient);
- RuleChange[] activatedRules = {};
- String[] deactivatedRules = {"repo:rule-key"};
- RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules, "java");
- underTest.listen(ruleSetChangedEvent);
+ SonarLintPushEvent event = new SonarLintPushEvent(EVENT_NAME, "data".getBytes(StandardCharsets.UTF_8), "project1", "java");
+
+ underTest.broadcastMessage(event);
verifyNoInteractions(outputStream);
}
@@ -144,74 +151,56 @@ public class SonarLintClientsRegistryTest {
public void listen_givenOneClientInterestedInProjA_DontCheckPermissionsForProjB() throws IOException {
when(defaultAsyncContext.getResponse()).thenReturn(response);
when(response.getOutputStream()).thenReturn(outputStream);
- Set<String> clientProjectKeys = Set.of("projA");
- Set<String> eventProjectKeys = Set.of("projA", "projB");
- SonarLintClient sonarLintClient = new SonarLintClient(defaultAsyncContext, clientProjectKeys, Set.of("java"), USER_UUID);
+ SonarLintClient sonarLintClient = new SonarLintClient(defaultAsyncContext, Set.of("projA"), Set.of("java"), USER_UUID);
underTest.registerClient(sonarLintClient);
- RuleChange[] activatedRules = {};
- String[] deactivatedRules = {"repo:rule-key"};
- RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(eventProjectKeys.toArray(String[]::new), activatedRules, deactivatedRules, "java");
- underTest.listen(ruleSetChangedEvent);
+ SonarLintPushEvent event1 = new SonarLintPushEvent(EVENT_NAME, "data".getBytes(StandardCharsets.UTF_8), "projA", "java");
+ SonarLintPushEvent event2 = new SonarLintPushEvent(EVENT_NAME, "data".getBytes(StandardCharsets.UTF_8), "projB", "java");
ArgumentCaptor<Set<String>> argument = ArgumentCaptor.forClass(Set.class);
- verify(permissionsValidator).validateUserCanReceivePushEventForProjects(anyString(), argument.capture());
- assertThat(argument.getValue()).isEqualTo(clientProjectKeys);
- }
-
- @Test
- public void listen_givenUserNotPermittedToReceiveRuleSetChangedEvent_closeConnection() {
- RuleChange[] activatedRules = {};
- String[] deactivatedRules = {"repo:rule-key"};
- RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules, "java");
- SonarLintClient sonarLintClient = createSampleSLClient();
- underTest.registerClient(sonarLintClient);
- doThrow(new ForbiddenException("Access forbidden")).when(permissionsValidator).validateUserCanReceivePushEventForProjects(anyString(), anySet());
+ underTest.broadcastMessage(event1);
+ underTest.broadcastMessage(event2);
- underTest.listen(ruleSetChangedEvent);
-
- verify(sonarLintClient).close();
+ verify(permissionsValidator, times(1)).validateUserCanReceivePushEventForProjects(anyString(), argument.capture());
+ assertThat(argument.getValue()).hasSize(1).contains("projA");
}
@Test
- public void listen_givenUserNotPermittedToReceiveIssueChangeEvent_closeConnection() {
- Issue[] issues = new Issue[] {new Issue("issue-1", "branch-1")};
- IssueChangedEvent issueChangedEvent = new IssueChangedEvent("project1", issues, true, "BLOCKER", "BUG");
-
+ public void listen_givenUserNotPermittedToReceiveEvent_closeConnection() {
SonarLintClient sonarLintClient = createSampleSLClient();
underTest.registerClient(sonarLintClient);
doThrow(new ForbiddenException("Access forbidden")).when(permissionsValidator).validateUserCanReceivePushEventForProjects(anyString(), anySet());
- underTest.listen(issueChangedEvent);
+ SonarLintPushEvent event = new SonarLintPushEvent(EVENT_NAME, "data".getBytes(StandardCharsets.UTF_8), "project1", "java");
+
+ underTest.broadcastMessage(event);
verify(sonarLintClient).close();
}
@Test
public void listen_givenUnregisteredClient_closeConnection() throws IOException {
- RuleChange[] activatedRules = {};
- String[] deactivatedRules = {"repo:rule-key"};
- RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules, "java");
-
SonarLintClient sonarLintClient = createSampleSLClient();
underTest.registerClient(sonarLintClient);
doThrow(new IOException("Broken pipe")).when(sonarLintClient).writeAndFlush(anyString());
- underTest.listen(ruleSetChangedEvent);
+ SonarLintPushEvent event = new SonarLintPushEvent(EVENT_NAME, "data".getBytes(StandardCharsets.UTF_8), "project1", "java");
+
+ underTest.broadcastMessage(event);
underTest.registerClient(sonarLintClient);
doThrow(new IllegalStateException("Things went wrong")).when(sonarLintClient).writeAndFlush(anyString());
- underTest.listen(ruleSetChangedEvent);
+ underTest.broadcastMessage(event);
verify(sonarLintClient, times(2)).close();
}
@Test
public void broadcast_push_event_to_clients() throws IOException {
- SonarLintPushEvent event = new SonarLintPushEvent("event", "data".getBytes(StandardCharsets.UTF_8), "project2");
+ SonarLintPushEvent event = new SonarLintPushEvent("event", "data".getBytes(StandardCharsets.UTF_8), "project2", null);
SonarLintClient sonarLintClient = createSampleSLClient();
underTest.registerClient(sonarLintClient);
@@ -224,7 +213,7 @@ public class SonarLintClientsRegistryTest {
@Test
public void broadcast_skips_push_if_event_project_does_not_match_with_client() throws IOException {
- SonarLintPushEvent event = new SonarLintPushEvent("event", "data".getBytes(StandardCharsets.UTF_8), "project4");
+ SonarLintPushEvent event = new SonarLintPushEvent("event", "data".getBytes(StandardCharsets.UTF_8), "project4", null);
SonarLintClient sonarLintClient = createSampleSLClient();
underTest.registerClient(sonarLintClient);
@@ -238,7 +227,7 @@ public class SonarLintClientsRegistryTest {
@Test
public void broadcast_givenUserNotPermittedToReceiveSonarLintPushEvent_closeConnection() {
- SonarLintPushEvent event = new SonarLintPushEvent("event", "data".getBytes(StandardCharsets.UTF_8), "project1");
+ SonarLintPushEvent event = new SonarLintPushEvent("event", "data".getBytes(StandardCharsets.UTF_8), "project1", null);
SonarLintClient sonarLintClient = createSampleSLClient();
underTest.registerClient(sonarLintClient);
@@ -251,7 +240,7 @@ public class SonarLintClientsRegistryTest {
@Test
public void broadcast_givenUnregisteredClient_closeConnection() throws IOException {
- SonarLintPushEvent event = new SonarLintPushEvent("event", "data".getBytes(StandardCharsets.UTF_8), "project1");
+ SonarLintPushEvent event = new SonarLintPushEvent("event", "data".getBytes(StandardCharsets.UTF_8), "project1", null);
SonarLintClient sonarLintClient = createSampleSLClient();
underTest.registerClient(sonarLintClient);
@@ -268,42 +257,11 @@ public class SonarLintClientsRegistryTest {
}
@Test
- public void registerClient_whenCalledFirstTime_registerAlsoToListenToEvents() {
- underTest.registerClient(createSampleSLClient());
-
- verify(ruleEventsDistributor).subscribe(underTest);
- verify(issueChangeEventsDistributor).subscribe(underTest);
- }
-
- @Test
- public void registerClient_whenCalledSecondTime_doNotRegisterToEvents() {
- underTest.registerClient(createSampleSLClient());
- clearInvocations(ruleEventsDistributor);
- clearInvocations(issueChangeEventsDistributor);
-
- underTest.registerClient(createSampleSLClient());
- verifyNoInteractions(ruleEventsDistributor);
- verifyNoInteractions(issueChangeEventsDistributor);
- }
-
- @Test
- public void registerClient_whenExceptionAndCalledSecondTime_registerToRuleEvents() {
- doThrow(new RuntimeException()).when(ruleEventsDistributor).subscribe(any());
- underTest.registerClient(createSampleSLClient());
- clearInvocations(ruleEventsDistributor);
-
- underTest.registerClient(createSampleSLClient());
- verify(ruleEventsDistributor).subscribe(underTest);
- }
-
- @Test
- public void registerClient_whenExceptionAndCalledSecondTime_registerToIssueChangeEvents() {
- doThrow(new RuntimeException()).when(issueChangeEventsDistributor).subscribe(any());
- underTest.registerClient(createSampleSLClient());
- clearInvocations(issueChangeEventsDistributor);
+ public void registerClient_whenCalledFirstTime_addsAsyncListenerToClient() {
+ SonarLintClient client = mock(SonarLintClient.class);
+ underTest.registerClient(client);
- underTest.registerClient(createSampleSLClient());
- verify(issueChangeEventsDistributor).subscribe(underTest);
+ verify(client).addListener(any());
}
private SonarLintClient createSampleSLClient() {
@@ -313,14 +271,4 @@ public class SonarLintClientsRegistryTest {
when(mock.getUserUuid()).thenReturn("userUuid");
return mock;
}
-
- private RuleChange createRuleChange() {
- RuleChange javaRule = new RuleChange();
- javaRule.setLanguage("java");
- javaRule.setParams(new ParamChange[] {new ParamChange("param-key", "param-value")});
- javaRule.setTemplateKey("repo:template-key");
- javaRule.setSeverity(Severity.CRITICAL);
- javaRule.setKey("repo:rule-key");
- return javaRule;
- }
}
diff --git a/server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event-data.json b/server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event-data.json
deleted file mode 100644
index 81d1dc7920b..00000000000
--- a/server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event-data.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "projects": [
- "project2",
- "project1",
- "project3"
- ],
- "activatedRules": [
- {
- "key": "repo:rule-key",
- "templateKey": "repo:template-key",
- "severity": "CRITICAL",
- "language": "java",
- "params": [
- {
- "value": "param-value",
- "key": "param-key"
- }
- ]
- }
- ],
- "deactivatedRules": [
- "repo2:rule-key2"
- ]
-}