aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamien Urruty <damien.urruty@sonarsource.com>2022-02-24 14:51:07 +0100
committersonartech <sonartech@sonarsource.com>2022-02-25 20:02:53 +0000
commit0253f591bd017cb9a9c8e365fa074a7bc4b0a2a0 (patch)
treee9b2794b0904a2aa999273c1d1075e6aba86e08b
parent9828d4922ec6064d0c7814b285a639ef1f838de4 (diff)
downloadsonarqube-0253f591bd017cb9a9c8e365fa074a7bc4b0a2a0.tar.gz
sonarqube-0253f591bd017cb9a9c8e365fa074a7bc4b0a2a0.zip
SONAR-15919 Rename RuleSetChangedEvent and fix payload format
-rw-r--r--server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java4
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMember.java4
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberImpl.java8
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/DistributedRuleActivatorEventsDistributor.java4
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/QualityProfileChangeEventServiceImpl.java6
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/RuleActivatorEventsDistributor.java6
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/qualityprofile/StandaloneRuleActivatorEventsDistributor.java4
-rw-r--r--server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java42
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistryTest.java34
-rw-r--r--server/sonar-webserver-pushapi/src/test/java/org/sonar/server/qualityprofile/builtin/QualityProfileChangeEventServiceImplTest.java46
-rw-r--r--server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event-data.json35
-rw-r--r--server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event.json38
-rw-r--r--sonar-core/src/main/java/org/sonar/core/util/RuleActivationListener.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/util/RuleSetChangedEvent.java (renamed from sonar-core/src/main/java/org/sonar/core/util/RuleSetChangeEvent.java)28
-rw-r--r--sonar-core/src/test/java/org/sonar/core/util/RuleSetChangedEventTest.java (renamed from sonar-core/src/test/java/org/sonar/core/util/RuleSetChangeEventTest.java)8
-rw-r--r--sonar-testing-harness/src/main/java/org/sonar/test/EventAssert.java123
-rw-r--r--sonar-testing-harness/src/test/java/org/sonar/test/EventAssertTest.java111
-rw-r--r--sonar-testing-harness/src/test/resources/org/sonar/test/EventAssertTest/sample.json1
18 files changed, 363 insertions, 143 deletions
diff --git a/server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java b/server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java
index cf0c8a1cd9e..3c4b5235f5c 100644
--- a/server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java
+++ b/server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java
@@ -41,7 +41,7 @@ import org.junit.Before;
import org.junit.Test;
import org.sonar.application.config.TestAppSettings;
import org.sonar.core.util.RuleActivationListener;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
import org.sonar.process.cluster.hz.DistributedAnswer;
import org.sonar.process.cluster.hz.DistributedCall;
import org.sonar.process.cluster.hz.DistributedCallback;
@@ -202,7 +202,7 @@ public class AppNodesClusterHostsConsistencyTest {
}
@Override
- public void publishEvent(RuleSetChangeEvent event) {
+ public void publishEvent(RuleSetChangedEvent event) {
}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMember.java b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMember.java
index 320a867eb29..2f0ec8cb8e0 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMember.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMember.java
@@ -27,7 +27,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import org.sonar.core.util.RuleActivationListener;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
import org.sonar.process.ProcessId;
public interface HazelcastMember extends AutoCloseable {
@@ -110,7 +110,7 @@ public interface HazelcastMember extends AutoCloseable {
void subscribeRuleActivationTopic(RuleActivationListener listener);
- void publishEvent(RuleSetChangeEvent event);
+ void publishEvent(RuleSetChangedEvent event);
@Override
void close();
diff --git a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberImpl.java b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberImpl.java
index 9b223cb0c61..89a9b75f994 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberImpl.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberImpl.java
@@ -40,7 +40,7 @@ import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;
import org.slf4j.LoggerFactory;
import org.sonar.core.util.RuleActivationListener;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
class HazelcastMemberImpl implements HazelcastMember {
@@ -131,13 +131,13 @@ class HazelcastMemberImpl implements HazelcastMember {
@Override
public void subscribeRuleActivationTopic(RuleActivationListener listener) {
- ITopic<RuleSetChangeEvent> topic = hzInstance.getTopic("ruleActivated");
- MessageListener<RuleSetChangeEvent> hzListener = message -> listener.listen(message.getMessageObject());
+ ITopic<RuleSetChangedEvent> topic = hzInstance.getTopic("ruleActivated");
+ MessageListener<RuleSetChangedEvent> hzListener = message -> listener.listen(message.getMessageObject());
topic.addMessageListener(hzListener);
}
@Override
- public void publishEvent(RuleSetChangeEvent event) {
+ public void publishEvent(RuleSetChangedEvent event) {
hzInstance.getTopic("ruleActivated").publish(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
index 7e63b06c112..c5b4b9fae9d 100644
--- 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
@@ -21,7 +21,7 @@ package org.sonar.server.pushapi.qualityprofile;
import org.sonar.api.server.ServerSide;
import org.sonar.core.util.RuleActivationListener;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
import org.sonar.process.cluster.hz.HazelcastMember;
@ServerSide
@@ -39,7 +39,7 @@ public class DistributedRuleActivatorEventsDistributor implements RuleActivatorE
}
@Override
- public void pushEvent(RuleSetChangeEvent event) {
+ 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 809483f1355..c5386a36ef7 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
@@ -33,7 +33,7 @@ import org.jetbrains.annotations.NotNull;
import org.sonar.api.server.ServerSide;
import org.sonar.core.util.ParamChange;
import org.sonar.core.util.RuleChange;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.project.ProjectDto;
@@ -73,7 +73,7 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
return;
}
- RuleSetChangeEvent event = new RuleSetChangeEvent(new String[] {project.getKey()}, activatedRules.toArray(new RuleChange[0]), deactivatedRules.toArray(new RuleChange[0]));
+ RuleSetChangedEvent event = new RuleSetChangedEvent(new String[] {project.getKey()}, activatedRules.toArray(new RuleChange[0]), deactivatedRules.toArray(new RuleChange[0]));
eventsDistributor.pushEvent(event);
}
@@ -173,7 +173,7 @@ public class QualityProfileChangeEventServiceImpl implements QualityProfileChang
return;
}
- RuleSetChangeEvent event = new RuleSetChangeEvent(projectKeys.toArray(new String[0]), activatedRules.toArray(new RuleChange[0]), deactivatedRules.toArray(new RuleChange[0]));
+ RuleSetChangedEvent event = new RuleSetChangedEvent(projectKeys.toArray(new String[0]), activatedRules.toArray(new RuleChange[0]), deactivatedRules.toArray(new RuleChange[0]));
eventsDistributor.pushEvent(event);
}
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
index 366ffc66d81..0d8a6c26c8b 100644
--- 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
@@ -20,11 +20,11 @@
package org.sonar.server.pushapi.qualityprofile;
import org.sonar.core.util.RuleActivationListener;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
public interface RuleActivatorEventsDistributor {
void subscribe(RuleActivationListener listener);
- void pushEvent(RuleSetChangeEvent event);
-} \ No newline at end of file
+ void pushEvent(RuleSetChangedEvent event);
+}
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
index 656ec753076..3207154ac2e 100644
--- 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
@@ -23,7 +23,7 @@ import java.util.ArrayList;
import java.util.List;
import org.sonar.api.server.ServerSide;
import org.sonar.core.util.RuleActivationListener;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
@ServerSide
public class StandaloneRuleActivatorEventsDistributor implements RuleActivatorEventsDistributor {
@@ -36,7 +36,7 @@ public class StandaloneRuleActivatorEventsDistributor implements RuleActivatorEv
}
@Override
- public void pushEvent(RuleSetChangeEvent event) {
+ 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/sonarlint/SonarLintClientsRegistry.java b/server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java
index 5b73339991d..fa712ace19c 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
@@ -36,7 +36,7 @@ import org.sonar.api.utils.log.Loggers;
import org.sonar.core.util.ParamChange;
import org.sonar.core.util.RuleActivationListener;
import org.sonar.core.util.RuleChange;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.pushapi.qualityprofile.RuleActivatorEventsDistributor;
@@ -89,29 +89,29 @@ public class SonarLintClientsRegistry implements RuleActivationListener {
}
@Override
- public void listen(RuleSetChangeEvent ruleChangeEvent) {
- broadcastMessage(ruleChangeEvent, getFilterForEvent(ruleChangeEvent));
+ public void listen(RuleSetChangedEvent ruleSetChangedEvent) {
+ broadcastMessage(ruleSetChangedEvent, getFilterForEvent(ruleSetChangedEvent));
}
- private static Predicate<SonarLintClient> getFilterForEvent(RuleSetChangeEvent ruleChangeEvent) {
- List<String> affectedProjects = asList(ruleChangeEvent.getProjects());
+ private 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(ruleChangeEvent.getLanguage());
+ return !Collections.disjoint(clientProjectKeys, affectedProjects) && languages.contains(ruleSetChangedEvent.getLanguage());
};
}
- public void broadcastMessage(RuleSetChangeEvent message, Predicate<SonarLintClient> filter) {
+ 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(message.getProjects()));
+ projectKeysInterestingForClient.retainAll(Set.of(event.getProjects()));
try {
sonarLintClientPermissionsValidator.validateUserCanReceivePushEventForProjects(c.getUserUuid(), projectKeysInterestingForClient);
- RuleSetChangeEvent personalizedEvent = new RuleSetChangeEvent(projectKeysInterestingForClient.toArray(String[]::new), message.getActivatedRules(),
- message.getDeactivatedRules());
- String jsonString = getJSONString(personalizedEvent);
- c.writeAndFlush(jsonString);
+ RuleSetChangedEvent personalizedEvent = new RuleSetChangedEvent(projectKeysInterestingForClient.toArray(String[]::new), event.getActivatedRules(),
+ event.getDeactivatedRules());
+ String message = getMessage(personalizedEvent);
+ c.writeAndFlush(message);
} catch (ForbiddenException forbiddenException) {
LOG.debug("Client is no longer authenticated: " + forbiddenException.getMessage());
unregisterClient(c);
@@ -121,28 +121,28 @@ public class SonarLintClientsRegistry implements RuleActivationListener {
}
});
}
+ private static String getMessage(RuleSetChangedEvent ruleSetChangedEvent) {
+ return "event: " + ruleSetChangedEvent.getEvent() + "\n"
+ + "data: " + toJson(ruleSetChangedEvent);
+ }
- public String getJSONString(RuleSetChangeEvent ruleSetChangeEvent) {
- JSONObject result = new JSONObject();
- result.put("event", ruleSetChangeEvent.getEvent());
-
+ private static String toJson(RuleSetChangedEvent ruleSetChangedEvent) {
JSONObject data = new JSONObject();
- data.put("projects", ruleSetChangeEvent.getProjects());
+ data.put("projects", ruleSetChangedEvent.getProjects());
JSONArray activatedRulesJson = new JSONArray();
- for (RuleChange rule : ruleSetChangeEvent.getActivatedRules()) {
+ for (RuleChange rule : ruleSetChangedEvent.getActivatedRules()) {
activatedRulesJson.put(toJson(rule));
}
data.put("activatedRules", activatedRulesJson);
JSONArray deactivatedRulesJson = new JSONArray();
- for (RuleChange rule : ruleSetChangeEvent.getDeactivatedRules()) {
+ for (RuleChange rule : ruleSetChangedEvent.getDeactivatedRules()) {
deactivatedRulesJson.put(toJson(rule));
}
data.put("deactivatedRules", deactivatedRulesJson);
- result.put("data", data);
- return result.toString();
+ return data.toString();
}
private static JSONObject toJson(RuleChange rule) {
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 0e222a9aeb0..d82e71a2fcb 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
@@ -30,7 +30,7 @@ import org.mockito.ArgumentCaptor;
import org.sonar.api.rule.Severity;
import org.sonar.core.util.ParamChange;
import org.sonar.core.util.RuleChange;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.pushapi.qualityprofile.StandaloneRuleActivatorEventsDistributor;
@@ -45,7 +45,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
-import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonar.test.EventAssert.assertThatEvent;
public class SonarLintClientsRegistryTest {
@@ -105,15 +105,15 @@ public class SonarLintClientsRegistryTest {
RuleChange[] activatedRules = {javaRule};
RuleChange[] deactivatedRules = {javaRule};
- RuleSetChangeEvent ruleChangeEvent = new RuleSetChangeEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules);
- underTest.listen(ruleChangeEvent);
+ RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules);
+ underTest.listen(ruleSetChangedEvent);
ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
verify(outputStream).write(captor.capture());
- String json = new String(captor.getValue());
- assertJson(json)
- .withStrictArrayOrder()
- .isSimilarTo(getClass().getResource("rule-change-event.json"));
+ String message = new String(captor.getValue());
+ assertThatEvent(message)
+ .hasType("RuleSetChanged")
+ .hasJsonData(getClass().getResource("rule-change-event-data.json"));
}
@Test
@@ -129,8 +129,8 @@ public class SonarLintClientsRegistryTest {
RuleChange[] activatedRules = {};
RuleChange[] deactivatedRules = {javaRuleChange};
- RuleSetChangeEvent ruleChangeEvent = new RuleSetChangeEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules);
- underTest.listen(ruleChangeEvent);
+ RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules);
+ underTest.listen(ruleSetChangedEvent);
verifyNoInteractions(outputStream);
}
@@ -149,8 +149,8 @@ public class SonarLintClientsRegistryTest {
RuleChange[] activatedRules = {};
RuleChange[] deactivatedRules = {javaRuleChange};
- RuleSetChangeEvent ruleChangeEvent = new RuleSetChangeEvent(eventProjectKeys.toArray(String[]::new), activatedRules, deactivatedRules);
- underTest.listen(ruleChangeEvent);
+ RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(eventProjectKeys.toArray(String[]::new), activatedRules, deactivatedRules);
+ underTest.listen(ruleSetChangedEvent);
ArgumentCaptor<Set<String>> argument = ArgumentCaptor.forClass(Set.class);
verify(permissionsValidator).validateUserCanReceivePushEventForProjects(anyString(), argument.capture());
@@ -162,13 +162,13 @@ public class SonarLintClientsRegistryTest {
RuleChange javaRuleChange = createRuleChange();
RuleChange[] activatedRules = {};
RuleChange[] deactivatedRules = {javaRuleChange};
- RuleSetChangeEvent ruleChangeEvent = new RuleSetChangeEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules);
+ RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules);
SonarLintClient sonarLintClient = createSampleSLClient();
underTest.registerClient(sonarLintClient);
doThrow(new ForbiddenException("Access forbidden")).when(permissionsValidator).validateUserCanReceivePushEventForProjects(anyString(), anySet());
- underTest.listen(ruleChangeEvent);
+ underTest.listen(ruleSetChangedEvent);
verify(sonarLintClient).close();
}
@@ -178,18 +178,18 @@ public class SonarLintClientsRegistryTest {
RuleChange javaRuleChange = createRuleChange();
RuleChange[] activatedRules = {};
RuleChange[] deactivatedRules = {javaRuleChange};
- RuleSetChangeEvent ruleChangeEvent = new RuleSetChangeEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules);
+ RuleSetChangedEvent ruleSetChangedEvent = new RuleSetChangedEvent(exampleKeys.toArray(String[]::new), activatedRules, deactivatedRules);
SonarLintClient sonarLintClient = createSampleSLClient();
underTest.registerClient(sonarLintClient);
doThrow(new IOException("Broken pipe")).when(sonarLintClient).writeAndFlush(anyString());
- underTest.listen(ruleChangeEvent);
+ underTest.listen(ruleSetChangedEvent);
underTest.registerClient(sonarLintClient);
doThrow(new IllegalStateException("Things went wrong")).when(sonarLintClient).writeAndFlush(anyString());
- underTest.listen(ruleChangeEvent);
+ underTest.listen(ruleSetChangedEvent);
verify(sonarLintClient, times(2)).close();
}
diff --git a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/qualityprofile/builtin/QualityProfileChangeEventServiceImplTest.java b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/qualityprofile/builtin/QualityProfileChangeEventServiceImplTest.java
index 4d731df20c9..b72c6961979 100644
--- a/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/qualityprofile/builtin/QualityProfileChangeEventServiceImplTest.java
+++ b/server/sonar-webserver-pushapi/src/test/java/org/sonar/server/qualityprofile/builtin/QualityProfileChangeEventServiceImplTest.java
@@ -27,7 +27,7 @@ import org.mockito.ArgumentCaptor;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.util.ParamChange;
import org.sonar.core.util.RuleChange;
-import org.sonar.core.util.RuleSetChangeEvent;
+import org.sonar.core.util.RuleSetChangedEvent;
import org.sonar.db.DbTester;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.qualityprofile.ActiveRuleDto;
@@ -87,27 +87,27 @@ public class QualityProfileChangeEventServiceImplTest {
underTest.distributeRuleChangeEvent(profiles, of(activeRuleChange), "xoo");
- ArgumentCaptor<RuleSetChangeEvent> eventCaptor = ArgumentCaptor.forClass(RuleSetChangeEvent.class);
+ ArgumentCaptor<RuleSetChangedEvent> eventCaptor = ArgumentCaptor.forClass(RuleSetChangedEvent.class);
verify(eventsDistributor).pushEvent(eventCaptor.capture());
- RuleSetChangeEvent ruleSetChangeEvent = eventCaptor.getValue();
- assertThat(ruleSetChangeEvent).isNotNull();
- assertThat(ruleSetChangeEvent).extracting(RuleSetChangeEvent::getEvent,
- RuleSetChangeEvent::getLanguage, RuleSetChangeEvent::getProjects)
- .containsExactly("RuleSetChange", "xoo", new String[]{project.getKey()});
+ RuleSetChangedEvent ruleSetChangedEvent = eventCaptor.getValue();
+ assertThat(ruleSetChangedEvent).isNotNull();
+ assertThat(ruleSetChangedEvent).extracting(RuleSetChangedEvent::getEvent,
+ RuleSetChangedEvent::getLanguage, RuleSetChangedEvent::getProjects)
+ .containsExactly("RuleSetChanged", "xoo", new String[]{project.getKey()});
- assertThat(ruleSetChangeEvent.getActivatedRules())
+ assertThat(ruleSetChangedEvent.getActivatedRules())
.extracting(RuleChange::getKey, RuleChange::getLanguage,
RuleChange::getSeverity, RuleChange::getTemplateKey)
.containsExactly(tuple(rule1.getRuleKey(), "xoo", null, "template-key"));
- assertThat(ruleSetChangeEvent.getActivatedRules()[0].getParams()).hasSize(1);
- ParamChange actualParamChange = ruleSetChangeEvent.getActivatedRules()[0].getParams()[0];
+ 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(ruleSetChangeEvent.getDeactivatedRules()).isEmpty();
+ assertThat(ruleSetChangedEvent.getDeactivatedRules()).isEmpty();
}
@@ -136,35 +136,35 @@ public class QualityProfileChangeEventServiceImplTest {
underTest.publishRuleActivationToSonarLintClients(projectDao, activatedQualityProfile, deactivatedQualityProfile);
- ArgumentCaptor<RuleSetChangeEvent> eventCaptor = ArgumentCaptor.forClass(RuleSetChangeEvent.class);
+ ArgumentCaptor<RuleSetChangedEvent> eventCaptor = ArgumentCaptor.forClass(RuleSetChangedEvent.class);
verify(eventsDistributor).pushEvent(eventCaptor.capture());
- RuleSetChangeEvent ruleSetChangeEvent = eventCaptor.getValue();
- assertThat(ruleSetChangeEvent).isNotNull();
- assertThat(ruleSetChangeEvent).extracting(RuleSetChangeEvent::getEvent,
- RuleSetChangeEvent::getLanguage, RuleSetChangeEvent::getProjects)
- .containsExactly("RuleSetChange", "xoo", new String[]{null});
+ 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(ruleSetChangeEvent.getActivatedRules())
+ assertThat(ruleSetChangedEvent.getActivatedRules())
.extracting(RuleChange::getKey, RuleChange::getLanguage,
RuleChange::getSeverity, RuleChange::getTemplateKey)
.containsExactly(tuple(rule1.getRuleKey(), "xoo", rule1.getSeverityString(), null));
- assertThat(ruleSetChangeEvent.getActivatedRules()[0].getParams()).hasSize(1);
- ParamChange actualParamChange = ruleSetChangeEvent.getActivatedRules()[0].getParams()[0];
+ 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(ruleSetChangeEvent.getDeactivatedRules())
+ assertThat(ruleSetChangedEvent.getDeactivatedRules())
.extracting(RuleChange::getKey, RuleChange::getLanguage,
RuleChange::getSeverity, RuleChange::getTemplateKey)
.containsExactly(tuple(rule2.getRuleKey(), "xoo", rule2.getSeverityString(), null));
- assertThat(ruleSetChangeEvent.getDeactivatedRules()[0].getParams()).hasSize(1);
- ParamChange actualParamChangeDeactivated = ruleSetChangeEvent.getDeactivatedRules()[0].getParams()[0];
+ assertThat(ruleSetChangedEvent.getDeactivatedRules()[0].getParams()).hasSize(1);
+ ParamChange actualParamChangeDeactivated = ruleSetChangedEvent.getDeactivatedRules()[0].getParams()[0];
assertThat(actualParamChangeDeactivated)
.extracting(ParamChange::getKey, ParamChange::getValue)
.containsExactly(activeRuleParam2.getKey(), activeRuleParam2.getValue());
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
new file mode 100644
index 00000000000..b70bd0dd2ab
--- /dev/null
+++ b/server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event-data.json
@@ -0,0 +1,35 @@
+{
+ "projects": [
+ "project2",
+ "project1",
+ "project3"
+ ],
+ "activatedRules": [
+ {
+ "key": "rule-key",
+ "templateKey": "template-key",
+ "severity": "CRITICAL",
+ "language": "java",
+ "params": [
+ {
+ "value": "param-value",
+ "key": "param-key"
+ }
+ ]
+ }
+ ],
+ "deactivatedRules": [
+ {
+ "key": "rule-key",
+ "templateKey": "template-key",
+ "severity": "CRITICAL",
+ "language": "java",
+ "params": [
+ {
+ "value": "param-value",
+ "key": "param-key"
+ }
+ ]
+ }
+ ]
+}
diff --git a/server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event.json b/server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event.json
deleted file mode 100644
index b60f1b83245..00000000000
--- a/server/sonar-webserver-pushapi/src/test/resources/org/sonar/server/pushapi/sonarlint/rule-change-event.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "data": {
- "projects": [
- "project2",
- "project1",
- "project3"
- ],
- "activatedRules": [
- {
- "key": "rule-key",
- "templateKey": "template-key",
- "severity": "CRITICAL",
- "language": "java",
- "params": [
- {
- "value": "param-value",
- "key": "param-key"
- }
- ]
- }
- ],
- "deactivatedRules": [
- {
- "key": "rule-key",
- "templateKey": "template-key",
- "severity": "CRITICAL",
- "language": "java",
- "params": [
- {
- "value": "param-value",
- "key": "param-key"
- }
- ]
- }
- ]
- },
- "event": "RuleSetChange"
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/util/RuleActivationListener.java b/sonar-core/src/main/java/org/sonar/core/util/RuleActivationListener.java
index d234d200d71..3a50054ca98 100644
--- a/sonar-core/src/main/java/org/sonar/core/util/RuleActivationListener.java
+++ b/sonar-core/src/main/java/org/sonar/core/util/RuleActivationListener.java
@@ -21,5 +21,5 @@ package org.sonar.core.util;
public interface RuleActivationListener {
- void listen(RuleSetChangeEvent event);
-} \ No newline at end of file
+ void listen(RuleSetChangedEvent event);
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/util/RuleSetChangeEvent.java b/sonar-core/src/main/java/org/sonar/core/util/RuleSetChangedEvent.java
index 5c9825a0522..5f3c3f95982 100644
--- a/sonar-core/src/main/java/org/sonar/core/util/RuleSetChangeEvent.java
+++ b/sonar-core/src/main/java/org/sonar/core/util/RuleSetChangedEvent.java
@@ -21,37 +21,25 @@ package org.sonar.core.util;
import java.io.Serializable;
-public class RuleSetChangeEvent implements Serializable {
+public class RuleSetChangedEvent implements Serializable {
- private static final String EVENT = "RuleSetChange";
+ private static final String EVENT = "RuleSetChanged";
- private String[] projects;
- private String language;
- private RuleChange[] activatedRules;
- private RuleChange[] deactivatedRules;
+ private final String[] projects;
+ private final String language;
+ private final RuleChange[] activatedRules;
+ private final RuleChange[] deactivatedRules;
- public RuleSetChangeEvent(String[] projects, RuleChange[] activatedRules, RuleChange[] deactivatedRules) {
+ public RuleSetChangedEvent(String[] projects, RuleChange[] activatedRules, RuleChange[] deactivatedRules) {
this.projects = projects;
this.activatedRules = activatedRules;
this.deactivatedRules = deactivatedRules;
if (activatedRules.length == 0 && deactivatedRules.length == 0) {
- throw new IllegalArgumentException("Can't create RuleSetChangeEvent without any rules that have changed");
+ throw new IllegalArgumentException("Can't create RuleSetChangedEvent without any rules that have changed");
}
this.language = activatedRules.length > 0 ? activatedRules[0].getLanguage() : deactivatedRules[0].getLanguage();
}
- public void setProjects(String[] projects) {
- this.projects = projects;
- }
-
- public void setActivatedRules(RuleChange[] activatedRules) {
- this.activatedRules = activatedRules;
- }
-
- public void setDeactivatedRules(RuleChange[] deactivatedRules) {
- this.deactivatedRules = deactivatedRules;
- }
-
public String getEvent() {
return EVENT;
}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/RuleSetChangeEventTest.java b/sonar-core/src/test/java/org/sonar/core/util/RuleSetChangedEventTest.java
index 71166586600..637d324ef5b 100644
--- a/sonar-core/src/test/java/org/sonar/core/util/RuleSetChangeEventTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/util/RuleSetChangedEventTest.java
@@ -24,14 +24,14 @@ import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
-public class RuleSetChangeEventTest {
+public class RuleSetChangedEventTest {
@Test
public void getLanguage_givenNoDeactivatedRules_languageIsCorrectlyIdentified() {
String[] projects = {"sonarqube"};
RuleChange[] activatedRules = {createRuleChange("java")};
RuleChange[] deactivatedRules = {};
- RuleSetChangeEvent event = new RuleSetChangeEvent(projects, activatedRules, deactivatedRules);
+ RuleSetChangedEvent event = new RuleSetChangedEvent(projects, activatedRules, deactivatedRules);
String language = event.getLanguage();
@@ -43,7 +43,7 @@ public class RuleSetChangeEventTest {
String[] projects = {"sonarqube"};
RuleChange[] activatedRules = {};
RuleChange[] deactivatedRules = {createRuleChange("java")};
- RuleSetChangeEvent event = new RuleSetChangeEvent(projects, activatedRules, deactivatedRules);
+ RuleSetChangedEvent event = new RuleSetChangedEvent(projects, activatedRules, deactivatedRules);
String language = event.getLanguage();
@@ -56,7 +56,7 @@ public class RuleSetChangeEventTest {
RuleChange[] activatedRules = {};
RuleChange[] deactivatedRules = {};
- assertThatThrownBy(() -> new RuleSetChangeEvent(projects, activatedRules, deactivatedRules))
+ assertThatThrownBy(() -> new RuleSetChangedEvent(projects, activatedRules, deactivatedRules))
.isInstanceOf(IllegalArgumentException.class);
}
diff --git a/sonar-testing-harness/src/main/java/org/sonar/test/EventAssert.java b/sonar-testing-harness/src/main/java/org/sonar/test/EventAssert.java
new file mode 100644
index 00000000000..5de4aa1ba23
--- /dev/null
+++ b/sonar-testing-harness/src/main/java/org/sonar/test/EventAssert.java
@@ -0,0 +1,123 @@
+/*
+ * 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.test;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import static org.junit.Assert.fail;
+import static org.sonar.test.JsonAssert.assertJson;
+
+/**
+ * Assertion methods to compare server-sent events messages.
+ *
+ * <h3>Usage</h3>
+ * <pre>
+ * String actual = "";
+ * String expected = "event: E\ndata: D";
+ * EventAssert.assertEvent(actual).hasType("E");
+ * </pre>
+ *
+ * @since 9.4
+ */
+public class EventAssert {
+
+ private static final String EVENT = "event";
+ private static final String DATA = "data";
+ private static final String ID = "id";
+ private static final String RETRY = "retry";
+
+ private static final Set<String> ALLOWED_FIELDS = new HashSet<>(Arrays.asList(EVENT, DATA, ID, RETRY));
+
+ private final String eventPayload;
+
+ private EventAssert(String eventPayload) {
+ this.eventPayload = eventPayload;
+ }
+
+ public static EventAssert assertThatEvent(String eventPayload) {
+ return new EventAssert(eventPayload);
+ }
+
+ public EventAssert isValid() {
+ extractFields();
+ return this;
+ }
+
+ public EventAssert hasField(String name) {
+ isValid();
+ if (!extractFields().containsKey(name)) {
+ fail("Expected event to contain field '" + name + "'. Actual event was: '" + eventPayload + "'");
+ }
+ return this;
+ }
+
+ public EventAssert hasType(String value) {
+ return hasField(EVENT, value);
+ }
+
+ public EventAssert hasData(String value) {
+ return hasField(DATA, value);
+ }
+
+ public EventAssert hasField(String name, String value) {
+ isValid();
+ hasField(name);
+ String actual = extractFields().get(name);
+ if (!Objects.equals(actual, value)) {
+ fail("Expected field '" + name + "' to contain '" + value + "' but was '" + actual + "'");
+ }
+ return this;
+ }
+
+ public EventAssert hasJsonData(URL url) {
+ isValid();
+ hasField(DATA);
+ assertJson(extractFields().get(DATA))
+ .withStrictArrayOrder()
+ .isSimilarTo(url);
+ return this;
+ }
+
+ private Map<String, String> extractFields() {
+ Map<String, String> fields = new HashMap<>();
+ Arrays.stream(eventPayload.split("\n")).forEach(line -> {
+ String trimmed = line.trim();
+ if (!trimmed.isEmpty()) {
+ int fieldDelimiterIndex = line.indexOf(':');
+ if (fieldDelimiterIndex != -1) {
+ String fieldName = line.substring(0, fieldDelimiterIndex);
+ if (!ALLOWED_FIELDS.contains(fieldName)) {
+ fail("Unknown field in event: '" + fieldName + "'");
+ }
+ fields.put(fieldName, line.substring(fieldDelimiterIndex + 1).trim());
+ } else {
+ fail("Invalid line in event: '" + line + "'");
+ }
+ }
+ });
+ return fields;
+ }
+}
diff --git a/sonar-testing-harness/src/test/java/org/sonar/test/EventAssertTest.java b/sonar-testing-harness/src/test/java/org/sonar/test/EventAssertTest.java
new file mode 100644
index 00000000000..ac2cce1c2dc
--- /dev/null
+++ b/sonar-testing-harness/src/test/java/org/sonar/test/EventAssertTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.test;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.sonar.test.EventAssert.assertThatEvent;
+
+public class EventAssertTest {
+ @Test
+ public void isValid_no_field() {
+ assertThatThrownBy(() -> assertThatEvent("line without field").isValid())
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Invalid line in event: 'line without field'");
+ }
+ @Test
+ public void isValid_unknown_field() {
+ assertThatThrownBy(() -> assertThatEvent("field: value").isValid())
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Unknown field in event: 'field'");
+ }
+
+ @Test
+ public void isValid_correct() {
+ assertThatEvent("").isValid();
+ assertThatEvent("\n\n").isValid();
+ assertThatEvent("data: D").isValid();
+ assertThatEvent("event: E\ndata: D").isValid();
+ }
+
+ @Test
+ public void hasField_invalid() {
+ assertThatThrownBy(() -> assertThatEvent("line without field").hasField("event"))
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Invalid line in event: 'line without field'");
+ }
+
+ @Test
+ public void hasField_no_field() {
+ assertThatThrownBy(() -> assertThatEvent("event: E").hasField("data"))
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Expected event to contain field 'data'. Actual event was: 'event: E'");
+ }
+
+ @Test
+ public void hasField_correct() {
+ assertThatEvent("event: E\ndata: D").hasField("data");
+ assertThatEvent("event: E\ndata: D").hasField("event");
+ }
+
+ @Test
+ public void hasType_invalid() {
+ assertThatThrownBy(() -> assertThatEvent("line without field").hasType("E"))
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Invalid line in event: 'line without field'");
+ }
+
+ @Test
+ public void hasType_without_type() {
+ assertThatThrownBy(() -> assertThatEvent("data: D").hasType("E"))
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Expected event to contain field 'event'. Actual event was: 'data: D'");
+ }
+
+ @Test
+ public void hasType_correct() {
+ assertThatEvent("event: E\ndata: D").hasType("E");
+ }
+
+ @Test
+ public void hasData_invalid() {
+ assertThatThrownBy(() -> assertThatEvent("line without field").hasData("D"))
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Invalid line in event: 'line without field'");
+ }
+
+ @Test
+ public void hasData_correct() {
+ assertThatEvent("data:D").hasData("D");
+ }
+
+ @Test
+ public void hasJsonData_invalid() {
+ assertThatThrownBy(() -> assertThatEvent("line without field").hasJsonData(getClass().getResource("EventAssertTest/sample.json")))
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Invalid line in event: 'line without field'");
+ }
+
+ @Test
+ public void hasJsonData_correct() {
+ assertThatEvent("data: {}").hasJsonData(getClass().getResource("EventAssertTest/sample.json"));
+ }
+}
diff --git a/sonar-testing-harness/src/test/resources/org/sonar/test/EventAssertTest/sample.json b/sonar-testing-harness/src/test/resources/org/sonar/test/EventAssertTest/sample.json
new file mode 100644
index 00000000000..0967ef424bc
--- /dev/null
+++ b/sonar-testing-harness/src/test/resources/org/sonar/test/EventAssertTest/sample.json
@@ -0,0 +1 @@
+{}