Bladeren bron

SONAR-15919 add ruleset changes

tags/9.4.0.54424
Pierre 2 jaren geleden
bovenliggende
commit
0c8ff1bac5
42 gewijzigde bestanden met toevoegingen van 1027 en 83 verwijderingen
  1. 12
    0
      server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java
  2. 6
    0
      server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMember.java
  3. 16
    0
      server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberImpl.java
  4. 12
    6
      server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImpl.java
  5. 45
    0
      server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/DistributedRuleActivatorEventsDistributor.java
  6. 33
    0
      server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/QualityProfileChangeEventService.java
  7. 206
    0
      server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/QualityProfileChangeEventServiceImpl.java
  8. 12
    2
      server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java
  9. 30
    0
      server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/RuleActivatorEventsDistributor.java
  10. 42
    0
      server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/StandaloneRuleActivatorEventsDistributor.java
  11. 32
    9
      server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java
  12. 2
    0
      server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/RuleActivatorTest.java
  13. 1
    0
      server/sonar-webserver-pushapi/build.gradle
  14. 17
    0
      server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/ServerPushClient.java
  15. 8
    0
      server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClient.java
  16. 87
    1
      server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java
  17. 2
    2
      server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintPushAction.java
  18. 2
    1
      server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistryTest.java
  19. 4
    1
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileResetImpl.java
  20. 17
    3
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileRulesImpl.java
  21. 6
    1
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileTreeImpl.java
  22. 21
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/AddProjectAction.java
  23. 19
    1
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/RemoveProjectAction.java
  24. 3
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileComparisonTest.java
  25. 14
    3
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileResetImplTest.java
  26. 101
    36
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileRuleImplTest.java
  27. 10
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileRulesImplTest.java
  28. 14
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileTreeImplTest.java
  29. 3
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationTest.java
  30. 12
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/AddProjectActionTest.java
  31. 3
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionTest.java
  32. 4
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java
  33. 5
    2
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/InheritanceActionTest.java
  34. 4
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java
  35. 11
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/RemoveProjectActionTest.java
  36. 4
    1
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
  37. 4
    0
      server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/ServletRequest.java
  38. 7
    0
      server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
  39. 38
    0
      sonar-core/src/main/java/org/sonar/core/util/ParamChange.java
  40. 25
    0
      sonar-core/src/main/java/org/sonar/core/util/RuleActivationListener.java
  41. 68
    0
      sonar-core/src/main/java/org/sonar/core/util/RuleChange.java
  42. 65
    0
      sonar-core/src/main/java/org/sonar/core/util/RuleSetChangeEvent.java

+ 12
- 0
server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java Bestand weergeven

@@ -40,6 +40,8 @@ import org.junit.After;
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.process.cluster.hz.DistributedAnswer;
import org.sonar.process.cluster.hz.DistributedCall;
import org.sonar.process.cluster.hz.DistributedCallback;
@@ -194,6 +196,16 @@ public class AppNodesClusterHostsConsistencyTest {
callback.onComplete((Map<Member, T>) hostsPerMember);
}

@Override
public void subscribeRuleActivationTopic(RuleActivationListener listener) {

}

@Override
public void publishEvent(RuleSetChangeEvent event) {

}

@Override
public void close() {


+ 6
- 0
server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMember.java Bestand weergeven

@@ -26,6 +26,8 @@ import java.util.Map;
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.process.ProcessId;

public interface HazelcastMember extends AutoCloseable {
@@ -106,6 +108,10 @@ public interface HazelcastMember extends AutoCloseable {
*/
<T> void callAsync(DistributedCall<T> callable, MemberSelector memberSelector, DistributedCallback<T> callback);

void subscribeRuleActivationTopic(RuleActivationListener listener);

void publishEvent(RuleSetChangeEvent event);

@Override
void close();
}

+ 16
- 0
server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberImpl.java Bestand weergeven

@@ -27,6 +27,8 @@ import com.hazelcast.core.HazelcastInstanceNotActiveException;
import com.hazelcast.core.IExecutorService;
import com.hazelcast.core.MultiExecutionCallback;
import com.hazelcast.cp.IAtomicReference;
import com.hazelcast.topic.ITopic;
import com.hazelcast.topic.MessageListener;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@@ -37,6 +39,8 @@ import java.util.concurrent.TimeoutException;
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;

class HazelcastMemberImpl implements HazelcastMember {

@@ -125,6 +129,18 @@ class HazelcastMemberImpl implements HazelcastMember {
});
}

@Override
public void subscribeRuleActivationTopic(RuleActivationListener listener) {
ITopic<RuleSetChangeEvent> topic = hzInstance.getTopic("ruleActivated");
MessageListener<RuleSetChangeEvent> hzListener = message -> listener.listen(message.getMessageObject());
topic.addMessageListener(hzListener);
}

@Override
public void publishEvent(RuleSetChangeEvent event) {
hzInstance.getTopic("ruleActivated").publish(event);
}

@Override
public void close() {
try {

+ 12
- 6
server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImpl.java Bestand weergeven

@@ -40,11 +40,14 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate {
private final DbClient dbClient;
private final RuleActivator ruleActivator;
private final ActiveRuleIndexer activeRuleIndexer;
private final QualityProfileChangeEventService qualityProfileChangeEventService;

public BuiltInQProfileUpdateImpl(DbClient dbClient, RuleActivator ruleActivator, ActiveRuleIndexer activeRuleIndexer) {
public BuiltInQProfileUpdateImpl(DbClient dbClient, RuleActivator ruleActivator, ActiveRuleIndexer activeRuleIndexer,
QualityProfileChangeEventService qualityProfileChangeEventService) {
this.dbClient = dbClient;
this.ruleActivator = ruleActivator;
this.activeRuleIndexer = activeRuleIndexer;
this.qualityProfileChangeEventService = qualityProfileChangeEventService;
}

public List<ActiveRuleChange> update(DbSession dbSession, BuiltInQProfile builtInDefinition, RulesProfileDto initialRuleProfile) {
@@ -56,8 +59,8 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate {

// all rules, including those which are removed from built-in profile
Set<String> ruleUuids = Stream.concat(
deactivatedRuleUuids.stream(),
builtInDefinition.getActiveRules().stream().map(BuiltInQProfile.ActiveRule::getRuleUuid))
deactivatedRuleUuids.stream(),
builtInDefinition.getActiveRules().stream().map(BuiltInQProfile.ActiveRule::getRuleUuid))
.collect(toSet());

Collection<RuleActivation> activations = new ArrayList<>();
@@ -69,13 +72,16 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate {

RuleActivationContext context = ruleActivator.createContextForBuiltInProfile(dbSession, initialRuleProfile, ruleUuids);
List<ActiveRuleChange> changes = new ArrayList<>();
for (RuleActivation activation : activations) {
changes.addAll(ruleActivator.activate(dbSession, activation, context));
}

changes.addAll(ruleActivator.activate(dbSession, activations, context));

// these rules are no longer part of the built-in profile
deactivatedRuleUuids.forEach(ruleUuid -> changes.addAll(ruleActivator.deactivate(dbSession, context, ruleUuid, false)));

if (!changes.isEmpty()) {
qualityProfileChangeEventService.distributeRuleChangeEvent(context.getProfiles(), changes, initialRuleProfile.getLanguage());
}

activeRuleIndexer.commitAndIndex(dbSession, changes);
return changes;
}

+ 45
- 0
server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/DistributedRuleActivatorEventsDistributor.java Bestand weergeven

@@ -0,0 +1,45 @@
/*
* 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.qualityprofile;

import org.sonar.api.server.ServerSide;
import org.sonar.core.util.RuleActivationListener;
import org.sonar.core.util.RuleSetChangeEvent;
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(RuleSetChangeEvent event) {
hazelcastMember.publishEvent(event);
}
}

+ 33
- 0
server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/QualityProfileChangeEventService.java Bestand weergeven

@@ -0,0 +1,33 @@
/*
* 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.qualityprofile;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.qualityprofile.QProfileDto;

public interface QualityProfileChangeEventService {

void publishRuleActivationToSonarLintClients(ProjectDto project, Optional<QProfileDto> activatedProfile, Optional<QProfileDto> deactivatedProfile);

void distributeRuleChangeEvent(Collection<QProfileDto> profiles, List<ActiveRuleChange> activeRuleChanges, String language);
}

+ 206
- 0
server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/QualityProfileChangeEventServiceImpl.java Bestand weergeven

@@ -0,0 +1,206 @@
/*
* 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.qualityprofile;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
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.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.qualityprofile.ActiveRuleParamDto;
import org.sonar.db.qualityprofile.ProjectQprofileAssociationDto;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleQuery;

@ServerSide
public class QualityProfileChangeEventServiceImpl implements QualityProfileChangeEventService {

private final DbClient dbClient;
private final RuleIndex ruleIndex;
private final RuleActivatorEventsDistributor eventsDistributor;

public QualityProfileChangeEventServiceImpl(DbClient dbClient, RuleIndex ruleIndex, RuleActivatorEventsDistributor eventsDistributor) {
this.dbClient = dbClient;
this.ruleIndex = ruleIndex;
this.eventsDistributor = eventsDistributor;
}

@Override
public void publishRuleActivationToSonarLintClients(ProjectDto project, Optional<QProfileDto> activatedProfile, Optional<QProfileDto> deactivatedProfile) {
List<RuleChange> activatedRules = new ArrayList<>();
List<RuleChange> deactivatedRules = new ArrayList<>();

try (DbSession dbSession = dbClient.openSession(false)) {

if (activatedProfile.isPresent()) {
RuleQuery query = new RuleQuery().setQProfile(activatedProfile.get()).setActivation(true).setIncludeExternal(true);
// .setLanguages() ?
Iterator<String> searchIdResult = ruleIndex.searchAll(query);
List<String> uuids = new ArrayList<>();
while (searchIdResult.hasNext()) {
uuids.add(searchIdResult.next());
}

List<RuleDto> ruleDtos = dbClient.ruleDao().selectByUuids(dbSession, uuids);
Map<String, List<ActiveRuleParamDto>> paramsByRuleUuid = dbClient.activeRuleDao().selectParamsByActiveRuleUuids(dbSession, uuids)
.stream().collect(Collectors.groupingBy(ActiveRuleParamDto::getActiveRuleUuid));

for (RuleDto ruleDto : ruleDtos) {
RuleChange ruleChange = toRuleChange(ruleDto, paramsByRuleUuid);
activatedRules.add(ruleChange);
}
}

if (deactivatedProfile.isPresent()) {
RuleQuery query = new RuleQuery().setQProfile(deactivatedProfile.get()).setActivation(true).setIncludeExternal(true);
// .setLanguages() ?
Iterator<String> searchIdResult = ruleIndex.searchAll(query);
List<String> uuids = new ArrayList<>();
while (searchIdResult.hasNext()) {
uuids.add(searchIdResult.next());
}

List<RuleDto> ruleDtos = dbClient.ruleDao().selectByUuids(dbSession, uuids);
Map<String, List<ActiveRuleParamDto>> paramsByRuleUuid = dbClient.activeRuleDao().selectParamsByActiveRuleUuids(dbSession, uuids)
.stream().collect(Collectors.groupingBy(ActiveRuleParamDto::getActiveRuleUuid));

for (RuleDto ruleDto : ruleDtos) {
RuleChange ruleChange = toRuleChange(ruleDto, paramsByRuleUuid);
deactivatedRules.add(ruleChange);
}
}

}

RuleSetChangeEvent event = new RuleSetChangeEvent(new String[]{project.getKey()}, activatedRules.toArray(new RuleChange[0]), deactivatedRules.toArray(new RuleChange[0]));
eventsDistributor.pushEvent(event);
}

@NotNull
private RuleChange toRuleChange(RuleDto ruleDto, Map<String, List<ActiveRuleParamDto>> paramsByRuleUuid) {
RuleChange ruleChange = new RuleChange();
ruleChange.setKey(ruleDto.getRuleKey());
ruleChange.setLanguage(ruleDto.getLanguage());
ruleChange.setSeverity(ruleDto.getSeverityString());

List<ParamChange> paramChanges = new ArrayList<>();
List<ActiveRuleParamDto> activeRuleParamDtos = paramsByRuleUuid.getOrDefault(ruleDto.getUuid(), new ArrayList<>());
for (ActiveRuleParamDto activeRuleParam : activeRuleParamDtos) {
paramChanges.add(new ParamChange(activeRuleParam.getKey(), activeRuleParam.getValue()));
}
ruleChange.setParams(paramChanges.toArray(new ParamChange[0]));

String templateUuid = ruleDto.getTemplateUuid();
if (templateUuid != null && !"".equals(templateUuid)) {
try (DbSession dbSession = dbClient.openSession(false)) {
RuleDto templateRule = dbClient.ruleDao().selectByUuid(templateUuid, dbSession)
.orElseThrow(() -> new IllegalStateException(String.format("unknow Template Rule '%s'", templateUuid)));
ruleChange.setTemplateKey(templateRule.getRuleKey());
}
}

return ruleChange;
}

public void distributeRuleChangeEvent(Collection<QProfileDto> profiles, List<ActiveRuleChange> activeRuleChanges, String language) {
if (activeRuleChanges.isEmpty()) {
return;
}

Set<RuleChange> activatedRules = new HashSet<>();
Set<RuleChange> deactivatedRules = new HashSet<>();

for (ActiveRuleChange arc : activeRuleChanges) {

RuleChange ruleChange = new RuleChange();
ruleChange.setKey(arc.getActiveRule().getRuleKey().rule());
ruleChange.setSeverity(arc.getSeverity());
ruleChange.setLanguage(language);

Optional<String> templateKey = templateKey(arc);
templateKey.ifPresent(ruleChange::setTemplateKey);

// params
List<ParamChange> paramChanges = new ArrayList<>();
for (Map.Entry<String, String> entry : arc.getParameters().entrySet()) {
paramChanges.add(new ParamChange(entry.getKey(), entry.getValue()));
}
ruleChange.setParams(paramChanges.toArray(new ParamChange[0]));

switch (arc.getType()) {
case ACTIVATED:
case UPDATED:
activatedRules.add(ruleChange);
break;
case DEACTIVATED:
deactivatedRules.add(ruleChange);
break;
}
}

Set<String> projectKeys = getProjectKeys(profiles);

RuleSetChangeEvent event = new RuleSetChangeEvent(projectKeys.toArray(new String[0]), activatedRules.toArray(new RuleChange[0]), deactivatedRules.toArray(new RuleChange[0]));
eventsDistributor.pushEvent(event);

}

private Optional<String> templateKey(ActiveRuleChange arc) {
try (DbSession dbSession = dbClient.openSession(false)) {
String ruleUuid = arc.getRuleUuid();
RuleDto rule = dbClient.ruleDao().selectByUuid(ruleUuid, dbSession).orElseThrow(() -> new IllegalStateException("unknow rule"));
String templateUuid = rule.getTemplateUuid();
if (templateUuid != null && !"".equals(templateUuid)) {
RuleDto templateRule = dbClient.ruleDao().selectByUuid(templateUuid, dbSession)
.orElseThrow(() -> new IllegalStateException(String.format("unknow Template Rule '%s'", templateUuid)));
return Optional.of(templateRule.getRuleKey());
}
}
return Optional.empty();
}

private Set<String> getProjectKeys(Collection<QProfileDto> profiles) {
Set<String> projectKeys = new HashSet<>();
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());
}
}
return projectKeys;
}
}

}

+ 12
- 2
server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/RuleActivator.java Bestand weergeven

@@ -52,6 +52,7 @@ import org.sonar.server.user.UserSession;
import org.sonar.server.util.TypeValidations;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.stream.Collectors.toList;
import static org.sonar.server.exceptions.BadRequestException.checkRequest;

/**
@@ -72,9 +73,17 @@ public class RuleActivator {
this.userSession = userSession;
}


public List<ActiveRuleChange> activate(DbSession dbSession, Collection<RuleActivation> activations, RuleActivationContext context) {
return activations.stream().map(a -> activate(dbSession, a, context))
.flatMap(List::stream)
.collect(toList());
}

public List<ActiveRuleChange> activate(DbSession dbSession, RuleActivation activation, RuleActivationContext context) {
context.reset(activation.getRuleUuid());
return doActivate(dbSession, activation, context);
List<ActiveRuleChange> activeRuleChanges = doActivate(dbSession, activation, context);
return activeRuleChanges;
}

private List<ActiveRuleChange> doActivate(DbSession dbSession, RuleActivation activation, RuleActivationContext context) {
@@ -357,7 +366,8 @@ public class RuleActivator {

public List<ActiveRuleChange> deactivate(DbSession dbSession, RuleActivationContext context, String ruleUuid, boolean force) {
context.reset(ruleUuid);
return doDeactivate(dbSession, context, force);
List<ActiveRuleChange> activeRuleChanges = doDeactivate(dbSession, context, force);
return activeRuleChanges;
}

private List<ActiveRuleChange> doDeactivate(DbSession dbSession, RuleActivationContext context, boolean force) {

+ 30
- 0
server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/RuleActivatorEventsDistributor.java Bestand weergeven

@@ -0,0 +1,30 @@
/*
* 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.qualityprofile;

import org.sonar.core.util.RuleActivationListener;
import org.sonar.core.util.RuleSetChangeEvent;

public interface RuleActivatorEventsDistributor {

void subscribe(RuleActivationListener listener);

void pushEvent(RuleSetChangeEvent event);
}

+ 42
- 0
server/sonar-webserver-auth/src/main/java/org/sonar/server/qualityprofile/StandaloneRuleActivatorEventsDistributor.java Bestand weergeven

@@ -0,0 +1,42 @@
/*
* 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.qualityprofile;

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;

@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(RuleSetChangeEvent event) {
listeners.forEach(l -> l.listen(event));
}
}

+ 32
- 9
server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java Bestand weergeven

@@ -56,7 +56,12 @@ import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.sonar.api.rules.RulePriority.BLOCKER;
import static org.sonar.api.rules.RulePriority.CRITICAL;
import static org.sonar.api.rules.RulePriority.MAJOR;
@@ -78,9 +83,11 @@ public class BuiltInQProfileUpdateImplTest {
private System2 system2 = new TestSystem2().setNow(NOW);
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class);
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession);

private BuiltInQProfileUpdateImpl underTest = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivator, activeRuleIndexer);
private BuiltInQProfileUpdateImpl underTest = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivator, activeRuleIndexer,
qualityProfileChangeEventService);

private RulesProfileDto persistedProfile;

@@ -105,13 +112,14 @@ public class BuiltInQProfileUpdateImplTest {
newQp.done();
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile("xoo", "Sonar way"), rule1, rule2);

underTest.update(db.getSession(), builtIn, persistedProfile);
List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, persistedProfile);

List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
assertThat(activeRules).hasSize(2);
assertThatRuleIsNewlyActivated(activeRules, rule1, CRITICAL);
assertThatRuleIsNewlyActivated(activeRules, rule2, MAJOR);
assertThatProfileIsMarkedAsUpdated(persistedProfile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

@Test
@@ -125,12 +133,13 @@ public class BuiltInQProfileUpdateImplTest {

activateRuleInDb(persistedProfile, rule, BLOCKER);

underTest.update(db.getSession(), builtIn, persistedProfile);
List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, persistedProfile);

List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
assertThat(activeRules).hasSize(1);
assertThatRuleIsUpdated(activeRules, rule, CRITICAL);
assertThatProfileIsMarkedAsUpdated(persistedProfile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

@Test
@@ -150,6 +159,7 @@ public class BuiltInQProfileUpdateImplTest {
assertThat(activeRules).hasSize(1);
assertThatRuleIsUntouched(activeRules, rule, CRITICAL);
assertThatProfileIsNotMarkedAsUpdated(persistedProfile);
verifyNoInteractions(qualityProfileChangeEventService);
}

@Test
@@ -166,12 +176,13 @@ public class BuiltInQProfileUpdateImplTest {
// so rule1 must be deactivated
activateRuleInDb(persistedProfile, rule1, CRITICAL);

underTest.update(db.getSession(), builtIn, persistedProfile);
List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, persistedProfile);

List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
assertThat(activeRules).hasSize(1);
assertThatRuleIsDeactivated(activeRules, rule1);
assertThatProfileIsMarkedAsUpdated(persistedProfile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

@Test
@@ -193,7 +204,7 @@ public class BuiltInQProfileUpdateImplTest {
activateRuleInDb(persistedProfile, rule1, BLOCKER);
activateRuleInDb(persistedProfile, rule3, BLOCKER);

underTest.update(db.getSession(), builtIn, persistedProfile);
List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, persistedProfile);

List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
assertThat(activeRules).hasSize(2);
@@ -201,6 +212,7 @@ public class BuiltInQProfileUpdateImplTest {
assertThatRuleIsNewlyActivated(activeRules, rule2, MAJOR);
assertThatRuleIsDeactivated(activeRules, rule3);
assertThatProfileIsMarkedAsUpdated(persistedProfile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

// SONAR-10473
@@ -222,9 +234,10 @@ public class BuiltInQProfileUpdateImplTest {
rule.setSeverity(Severity.MINOR);
db.rules().update(rule);

underTest.update(db.getSession(), builtIn, persistedProfile);
List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, persistedProfile);
activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
assertThatRuleIsNewlyActivated(activeRules, rule, MINOR);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

@Test
@@ -237,20 +250,22 @@ public class BuiltInQProfileUpdateImplTest {
newQp.activateRule(rule.getRepositoryKey(), rule.getRuleKey());
newQp.done();
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(newQp.language(), newQp.name()), rule);
underTest.update(db.getSession(), builtIn, persistedProfile);
List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, persistedProfile);

List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
assertThat(activeRules).hasSize(1);
assertThatRuleHasParams(db, activeRules.get(0), tuple("min", "10"));
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));

// emulate an upgrade of analyzer that changes the default value of parameter min
ruleParam.setDefaultValue("20");
db.getDbClient().ruleDao().updateRuleParam(db.getSession(), rule, ruleParam);

underTest.update(db.getSession(), builtIn, persistedProfile);
changes = underTest.update(db.getSession(), builtIn, persistedProfile);
activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
assertThat(activeRules).hasSize(1);
assertThatRuleHasParams(db, activeRules.get(0), tuple("min", "20"));
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

@Test
@@ -272,6 +287,7 @@ public class BuiltInQProfileUpdateImplTest {
assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap());
assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
assertThatRuleIsActivated(grandchildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

// SONAR-14559
@@ -299,6 +315,7 @@ public class BuiltInQProfileUpdateImplTest {

List<ActiveRuleDto> childActiveRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), RulesProfileDto.from(childProfile));
assertThatRuleIsUpdated(childActiveRules, rule, RulePriority.BLOCKER, INHERITED);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

@Test
@@ -327,6 +344,7 @@ public class BuiltInQProfileUpdateImplTest {

assertThatRuleHasParams(db, parentActiveRuleDto, tuple("min", "10"));
assertThatRuleHasParams(db, childActiveRuleDto, tuple("min", "10"));
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));
}

@Test
@@ -345,6 +363,7 @@ public class BuiltInQProfileUpdateImplTest {
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(profile.getLanguage(), profile.getName()), rule);
List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(profile));
assertThat(changes).hasSize(2).extracting(ActiveRuleChange::getType).containsOnly(ActiveRuleChange.Type.ACTIVATED);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));

// second run, without any input changes
RuleActivator ruleActivatorWithoutDescendants = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession) {
@@ -355,8 +374,10 @@ public class BuiltInQProfileUpdateImplTest {
};
}
};
changes = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivatorWithoutDescendants, activeRuleIndexer).update(db.getSession(), builtIn, RulesProfileDto.from(profile));
changes = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivatorWithoutDescendants, activeRuleIndexer, qualityProfileChangeEventService)
.update(db.getSession(), builtIn, RulesProfileDto.from(profile));
assertThat(changes).isEmpty();
verifyNoMoreInteractions(qualityProfileChangeEventService);
}

@Test
@@ -376,6 +397,7 @@ public class BuiltInQProfileUpdateImplTest {
BuiltInQProfile builtIn = builtInProfileRepository.create(context.profile(profile.getLanguage(), profile.getName()), rule);
List<ActiveRuleChange> changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(profile));
assertThat(changes).hasSize(3).extracting(ActiveRuleChange::getType).containsOnly(ActiveRuleChange.Type.ACTIVATED);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));

// second run to deactivate the rule
context = new BuiltInQualityProfilesDefinition.Context();
@@ -384,6 +406,7 @@ public class BuiltInQProfileUpdateImplTest {
builtIn = builtInProfileRepository.create(context.profile(profile.getLanguage(), profile.getName()), rule);
changes = underTest.update(db.getSession(), builtIn, RulesProfileDto.from(profile));
assertThat(changes).hasSize(3).extracting(ActiveRuleChange::getType).containsOnly(ActiveRuleChange.Type.DEACTIVATED);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(persistedProfile.getLanguage()));

assertThatRuleIsDeactivated(profile, rule);
assertThatRuleIsDeactivated(childProfile, rule);

+ 2
- 0
server/sonar-webserver-auth/src/test/java/org/sonar/server/qualityprofile/RuleActivatorTest.java Bestand weergeven

@@ -50,6 +50,7 @@ import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.mock;
import static org.sonar.server.qualityprofile.ActiveRuleInheritance.INHERITED;
import static org.sonar.server.qualityprofile.ActiveRuleInheritance.OVERRIDES;

@@ -69,6 +70,7 @@ public class RuleActivatorTest {
private final System2 system2 = new TestSystem2().setNow(NOW);
private final TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));

private final QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private final RuleActivator underTest = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession);

@Test

+ 1
- 0
server/sonar-webserver-pushapi/build.gradle Bestand weergeven

@@ -8,6 +8,7 @@ dependencies {
compile 'javax.servlet:javax.servlet-api'
compile project(':server:sonar-webserver-auth')
compile project(':server:sonar-webserver-ws')
compile project(':server:sonar-webserver-webapi')

testCompile 'junit:junit'
testCompile 'org.assertj:assertj-core'

+ 17
- 0
server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/ServerPushClient.java Bestand weergeven

@@ -20,6 +20,7 @@
package org.sonar.server.pushapi;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -34,6 +35,17 @@ public abstract class ServerPushClient {
private static final Logger LOG = Loggers.get(ServerPushClient.class);
private static final int DEFAULT_HEARTBEAT_PERIOD = 60;




private static final byte[] CRLF = new byte[] {'\r', '\n'};
private static final byte[] DATA_END = new byte[] {'\n', '\n'};
private static final byte[] DATA_FIELD = "data: ".getBytes(StandardCharsets.UTF_8);





protected final AsyncContext asyncContext;

private final ScheduledExecutorService executorService;
@@ -50,6 +62,11 @@ public abstract class ServerPushClient {
startedHeartbeat = executorService.schedule(heartbeatTask, DEFAULT_HEARTBEAT_PERIOD, TimeUnit.SECONDS);
}

public void writeAndFlush(String payload) throws IOException {
output().write(payload.getBytes(StandardCharsets.UTF_8));
flush();
}

public void writeAndFlush(char character) {
write(character);
flush();

+ 8
- 0
server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClient.java Bestand weergeven

@@ -39,6 +39,14 @@ public class SonarLintClient extends ServerPushClient {
this.languages = languages;
}

public Set<String> getLanguages() {
return languages;
}

public Set<String> getClientProjectKeys() {
return projectKeys;
}

@Override
public boolean equals(Object o) {
if (this == o) {

+ 87
- 1
server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistry.java Bestand weergeven

@@ -19,25 +19,46 @@
*/
package org.sonar.server.pushapi.sonarlint;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import org.json.JSONArray;
import org.json.JSONObject;
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.ParamChange;
import org.sonar.core.util.RuleActivationListener;
import org.sonar.core.util.RuleChange;
import org.sonar.core.util.RuleSetChangeEvent;
import org.sonar.server.qualityprofile.RuleActivatorEventsDistributor;

import static java.util.Arrays.asList;

@ServerSide
public class SonarLintClientsRegistry {
public class SonarLintClientsRegistry implements RuleActivationListener {

private static final Logger LOG = Loggers.get(SonarLintClientsRegistry.class);

private final RuleActivatorEventsDistributor ruleActivatorEventsDistributor;

public SonarLintClientsRegistry(RuleActivatorEventsDistributor ruleActivatorEventsDistributor) {
this.ruleActivatorEventsDistributor = ruleActivatorEventsDistributor;
}


private final List<SonarLintClient> clients = new CopyOnWriteArrayList<>();

public void registerClient(SonarLintClient sonarLintClient) {
clients.add(sonarLintClient);
sonarLintClient.scheduleHeartbeat();
sonarLintClient.addListener(new SonarLintClientEventsListener(sonarLintClient));
ruleActivatorEventsDistributor.subscribe(this);

LOG.debug("Registering new SonarLint client");
}

@@ -50,6 +71,71 @@ public class SonarLintClientsRegistry {
return clients.size();
}

@Override
public void listen(RuleSetChangeEvent ruleChangeEvent) {
LOG.info("Generating a RuleSetChangeEvent");
// TODO filter on languages here as well
broadcastMessage(ruleChangeEvent, f -> f.getClientProjectKeys().isEmpty() || !Collections.disjoint(f.getClientProjectKeys(), asList(ruleChangeEvent.getProjects())));
}


public void broadcastMessage(RuleSetChangeEvent message, Predicate<SonarLintClient> filter) {
String jsonString = getJSONString(message);
clients.stream().filter(filter).forEach(c -> {
try {
c.writeAndFlush(jsonString);
} catch (IOException e) {
LOG.error("Unable to send message to a client: " + e.getMessage());
}
});
}


public String getJSONString(RuleSetChangeEvent ruleSetChangeEvent) {
JSONObject result = new JSONObject();
result.put("event", ruleSetChangeEvent.getEvent());

JSONObject data = new JSONObject();
data.put("projects", ruleSetChangeEvent.getProjects());

JSONArray activatedRulesJson = new JSONArray();
for (RuleChange rule : ruleSetChangeEvent.getActivatedRules()) {
activatedRulesJson.put(toJson(rule));
}
data.put("activatedRules", activatedRulesJson);

JSONArray deactivatedRulesJson = new JSONArray();
for (RuleChange rule : ruleSetChangeEvent.getDeactivatedRules()) {
deactivatedRulesJson.put(toJson(rule));
}
data.put("deactivatedRules", deactivatedRulesJson);

result.put("data", data);
return result.toString();
}

private 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 JSONObject toJson(ParamChange paramChange) {
JSONObject param = new JSONObject();
param.put("key", paramChange.getKey());
param.put("value", paramChange.getValue());
return param;
}

class SonarLintClientEventsListener implements AsyncListener {
private final SonarLintClient client;


+ 2
- 2
server/sonar-webserver-pushapi/src/main/java/org/sonar/server/pushapi/sonarlint/SonarLintPushAction.java Bestand weergeven

@@ -84,7 +84,7 @@ public class SonarLintPushAction extends ServerPushAction {

if (!isServerSideEventsRequest(servletRequest)) {
servletResponse.stream().setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
return;
return; // TODO fixme this is not closing the connexion properly
}

setHeadersForResponse(servletResponse);
@@ -92,7 +92,7 @@ public class SonarLintPushAction extends ServerPushAction {
AsyncContext asyncContext = servletRequest.startAsync();
asyncContext.setTimeout(0);

var sonarLintClient = new SonarLintClient(asyncContext, params.getProjectKeys(), params.getLanguages());
SonarLintClient sonarLintClient = new SonarLintClient(asyncContext, params.getProjectKeys(), params.getLanguages());

clientsRegistry.registerClient(sonarLintClient);
}

+ 2
- 1
server/sonar-webserver-pushapi/src/test/java/org/sonar/server/pushapi/sonarlint/SonarLintClientsRegistryTest.java Bestand weergeven

@@ -23,6 +23,7 @@ import java.util.Set;
import javax.servlet.AsyncContext;
import org.junit.Before;
import org.junit.Test;
import org.sonar.server.qualityprofile.StandaloneRuleActivatorEventsDistributor;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -39,7 +40,7 @@ public class SonarLintClientsRegistryTest {

@Before
public void before() {
underTest = new SonarLintClientsRegistry();
underTest = new SonarLintClientsRegistry(mock(StandaloneRuleActivatorEventsDistributor.class));
}

@Test

+ 4
- 1
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileResetImpl.java Bestand weergeven

@@ -41,11 +41,13 @@ public class QProfileResetImpl implements QProfileReset {
private final DbClient db;
private final RuleActivator activator;
private final ActiveRuleIndexer activeRuleIndexer;
private final QualityProfileChangeEventService qualityProfileChangeEventService;

public QProfileResetImpl(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer) {
public QProfileResetImpl(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QualityProfileChangeEventService qualityProfileChangeEventService) {
this.db = db;
this.activator = activator;
this.activeRuleIndexer = activeRuleIndexer;
this.qualityProfileChangeEventService = qualityProfileChangeEventService;
}

@Override
@@ -87,6 +89,7 @@ public class QProfileResetImpl implements QProfileReset {
// ignore, probably a rule inherited from parent that can't be deactivated
}
}
qualityProfileChangeEventService.distributeRuleChangeEvent(List.of(profile), changes, profile.getLanguage());
activeRuleIndexer.commitAndIndex(dbSession, changes);
return result;
}

+ 17
- 3
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileRulesImpl.java Bestand weergeven

@@ -44,12 +44,15 @@ public class QProfileRulesImpl implements QProfileRules {
private final RuleActivator ruleActivator;
private final RuleIndex ruleIndex;
private final ActiveRuleIndexer activeRuleIndexer;
private final QualityProfileChangeEventService qualityProfileChangeEventService;

public QProfileRulesImpl(DbClient db, RuleActivator ruleActivator, RuleIndex ruleIndex, ActiveRuleIndexer activeRuleIndexer) {
public QProfileRulesImpl(DbClient db, RuleActivator ruleActivator, RuleIndex ruleIndex, ActiveRuleIndexer activeRuleIndexer,
QualityProfileChangeEventService qualityProfileChangeEventService) {
this.db = db;
this.ruleActivator = ruleActivator;
this.ruleIndex = ruleIndex;
this.activeRuleIndexer = activeRuleIndexer;
this.qualityProfileChangeEventService = qualityProfileChangeEventService;
}

@Override
@@ -63,6 +66,7 @@ public class QProfileRulesImpl implements QProfileRules {
for (RuleActivation activation : activations) {
changes.addAll(ruleActivator.activate(dbSession, activation, context));
}
qualityProfileChangeEventService.distributeRuleChangeEvent(List.of(profile), changes, profile.getLanguage());
activeRuleIndexer.commitAndIndex(dbSession, changes);
return changes;
}
@@ -70,10 +74,12 @@ public class QProfileRulesImpl implements QProfileRules {
@Override
public BulkChangeResult bulkActivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery, @Nullable String severity) {
verifyNotBuiltIn(profile);
return doBulk(dbSession, profile, ruleQuery, (context, ruleDefinition) -> {
BulkChangeResult bulkChangeResult = doBulk(dbSession, profile, ruleQuery, (context, ruleDefinition) -> {
RuleActivation activation = RuleActivation.create(ruleDefinition.getUuid(), severity, null);
return ruleActivator.activate(dbSession, activation, context);
});
qualityProfileChangeEventService.distributeRuleChangeEvent(List.of(profile), bulkChangeResult.getChanges(), profile.getLanguage());
return bulkChangeResult;
}

@Override
@@ -85,6 +91,9 @@ public class QProfileRulesImpl implements QProfileRules {
for (String ruleUuid : ruleUuids) {
changes.addAll(ruleActivator.deactivate(dbSession, context, ruleUuid, false));
}

qualityProfileChangeEventService.distributeRuleChangeEvent(List.of(profile), changes, profile.getLanguage());

activeRuleIndexer.commitAndIndex(dbSession, changes);
return changes;
}
@@ -92,7 +101,12 @@ public class QProfileRulesImpl implements QProfileRules {
@Override
public BulkChangeResult bulkDeactivateAndCommit(DbSession dbSession, QProfileDto profile, RuleQuery ruleQuery) {
verifyNotBuiltIn(profile);
return doBulk(dbSession, profile, ruleQuery, (context, ruleDefinition) -> ruleActivator.deactivate(dbSession, context, ruleDefinition.getUuid(), false));
BulkChangeResult bulkChangeResult = doBulk(dbSession, profile, ruleQuery, (context, ruleDefinition) ->
ruleActivator.deactivate(dbSession, context, ruleDefinition.getUuid(), false));

qualityProfileChangeEventService.distributeRuleChangeEvent(List.of(profile), bulkChangeResult.getChanges(), profile.getLanguage());

return bulkChangeResult;
}

@Override

+ 6
- 1
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileTreeImpl.java Bestand weergeven

@@ -41,12 +41,14 @@ public class QProfileTreeImpl implements QProfileTree {
private final RuleActivator ruleActivator;
private final System2 system2;
private final ActiveRuleIndexer activeRuleIndexer;
private final QualityProfileChangeEventService qualityProfileChangeEventService;

public QProfileTreeImpl(DbClient db, RuleActivator ruleActivator, System2 system2, ActiveRuleIndexer activeRuleIndexer) {
public QProfileTreeImpl(DbClient db, RuleActivator ruleActivator, System2 system2, ActiveRuleIndexer activeRuleIndexer, QualityProfileChangeEventService qualityProfileChangeEventService) {
this.db = db;
this.ruleActivator = ruleActivator;
this.system2 = system2;
this.activeRuleIndexer = activeRuleIndexer;
this.qualityProfileChangeEventService = qualityProfileChangeEventService;
}

@Override
@@ -92,6 +94,7 @@ public class QProfileTreeImpl implements QProfileTree {
// TODO return errors
}
}
qualityProfileChangeEventService.distributeRuleChangeEvent(List.of(profile), changes, profile.getLanguage());
return changes;
}

@@ -120,6 +123,8 @@ public class QProfileTreeImpl implements QProfileTree {
changes.add(new ActiveRuleChange(ActiveRuleChange.Type.UPDATED, activeRule, context.getRule().get()).setInheritance(null));
}
}

qualityProfileChangeEventService.distributeRuleChangeEvent(List.of(profile), changes, profile.getLanguage());
return changes;
}


+ 21
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/AddProjectAction.java Bestand weergeven

@@ -19,6 +19,7 @@
*/
package org.sonar.server.qualityprofile.ws;

import java.util.Optional;
import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
@@ -30,8 +31,11 @@ import org.sonar.db.DbSession;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.user.UserSession;

import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ADD_PROJECT;
@@ -44,13 +48,16 @@ public class AddProjectAction implements QProfileWsAction {
private final Languages languages;
private final ComponentFinder componentFinder;
private final QProfileWsSupport wsSupport;
private final QualityProfileChangeEventService qualityProfileChangeEventService;

public AddProjectAction(DbClient dbClient, UserSession userSession, Languages languages, ComponentFinder componentFinder, QProfileWsSupport wsSupport) {
public AddProjectAction(DbClient dbClient, UserSession userSession, Languages languages, ComponentFinder componentFinder,
QProfileWsSupport wsSupport, QualityProfileChangeEventService qualityProfileChangeEventService) {
this.dbClient = dbClient;
this.userSession = userSession;
this.languages = languages;
this.componentFinder = componentFinder;
this.wsSupport = wsSupport;
this.qualityProfileChangeEventService = qualityProfileChangeEventService;
}

@Override
@@ -80,24 +87,36 @@ public class AddProjectAction implements QProfileWsAction {
userSession.checkLoggedIn();

try (DbSession dbSession = dbClient.openSession(false)) {

ProjectDto project = loadProject(dbSession, request);
QProfileDto profile = wsSupport.getProfile(dbSession, QProfileReference.fromName(request));
checkPermissions(dbSession, profile, project);

QProfileDto currentProfile = dbClient.qualityProfileDao().selectAssociatedToProjectAndLanguage(dbSession, project, profile.getLanguage());

Optional<QProfileDto> deactivatedProfile = empty();

if (currentProfile == null) {
QProfileDto defaultProfile = dbClient.qualityProfileDao().selectDefaultProfile(dbSession, profile.getLanguage());
if (defaultProfile != null) {
deactivatedProfile = of(defaultProfile);
}

// project uses the default profile
dbClient.qualityProfileDao().insertProjectProfileAssociation(dbSession, project, profile);
dbSession.commit();
} else if (!profile.getKee().equals(currentProfile.getKee())) {
deactivatedProfile = of(currentProfile);
dbClient.qualityProfileDao().updateProjectProfileAssociation(dbSession, project, profile.getKee(), currentProfile.getKee());
dbSession.commit();
}
Optional<QProfileDto> activatedProfile = of(profile);
qualityProfileChangeEventService.publishRuleActivationToSonarLintClients(project, activatedProfile, deactivatedProfile);
}

response.noContent();
}


private ProjectDto loadProject(DbSession dbSession, Request request) {
String projectKey = request.mandatoryParam(PARAM_PROJECT);
return componentFinder.getProjectByKey(dbSession, projectKey);

+ 19
- 1
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/RemoveProjectAction.java Bestand weergeven

@@ -19,6 +19,7 @@
*/
package org.sonar.server.qualityprofile.ws;

import java.util.Optional;
import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
@@ -30,8 +31,11 @@ import org.sonar.db.DbSession;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.user.UserSession;

import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_REMOVE_PROJECT;
@@ -44,13 +48,16 @@ public class RemoveProjectAction implements QProfileWsAction {
private final Languages languages;
private final ComponentFinder componentFinder;
private final QProfileWsSupport wsSupport;
private final QualityProfileChangeEventService qualityProfileChangeEventService;

public RemoveProjectAction(DbClient dbClient, UserSession userSession, Languages languages, ComponentFinder componentFinder, QProfileWsSupport wsSupport) {
public RemoveProjectAction(DbClient dbClient, UserSession userSession, Languages languages, ComponentFinder componentFinder,
QProfileWsSupport wsSupport, QualityProfileChangeEventService qualityProfileChangeEventService) {
this.dbClient = dbClient;
this.userSession = userSession;
this.languages = languages;
this.componentFinder = componentFinder;
this.wsSupport = wsSupport;
this.qualityProfileChangeEventService = qualityProfileChangeEventService;
}

@Override
@@ -86,6 +93,17 @@ public class RemoveProjectAction implements QProfileWsAction {
dbClient.qualityProfileDao().deleteProjectProfileAssociation(dbSession, project, profile);
dbSession.commit();

Optional<QProfileDto> deactivatedProfile = of(profile);
Optional<QProfileDto> activatedProfile = empty();

// publish change for rules in the default quality profile
QProfileDto defaultProfile = dbClient.qualityProfileDao().selectDefaultProfile(dbSession, profile.getLanguage());
if (defaultProfile != null) {
activatedProfile = of(defaultProfile);
}

qualityProfileChangeEventService.publishRuleActivationToSonarLintClients(project, activatedProfile, deactivatedProfile);

response.noContent();
}
}

+ 3
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileComparisonTest.java Bestand weergeven

@@ -49,6 +49,7 @@ import org.sonar.server.util.TypeValidations;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

public class QProfileComparisonTest {

@@ -74,8 +75,9 @@ public class QProfileComparisonTest {
dbSession = db.openSession(false);
RuleIndex ruleIndex = new RuleIndex(es.client(), System2.INSTANCE);
ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db, es.client());
QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db, new TypeValidations(singletonList(new IntegerTypeValidation())), userSession);
qProfileRules = new QProfileRulesImpl(db, ruleActivator, ruleIndex, activeRuleIndexer);
qProfileRules = new QProfileRulesImpl(db, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);
comparison = new QProfileComparison(db);

xooRule1 = RuleTesting.newXooX1().setSeverity("MINOR").getDefinition();

+ 14
- 3
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileResetImplTest.java Bestand weergeven

@@ -41,7 +41,12 @@ import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.internal.verification.VerificationModeFactory.times;
import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;

public class QProfileResetImplTest {
@@ -55,11 +60,12 @@ public class QProfileResetImplTest {

private System2 system2 = new AlwaysIncreasingSystem2();
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class);
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession);
private QProfileTree qProfileTree = new QProfileTreeImpl(db.getDbClient(), ruleActivator, system2, activeRuleIndexer);
private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, null, activeRuleIndexer);
private QProfileResetImpl underTest = new QProfileResetImpl(db.getDbClient(), ruleActivator, activeRuleIndexer);
private QProfileTree qProfileTree = new QProfileTreeImpl(db.getDbClient(), ruleActivator, system2, activeRuleIndexer, mock(QualityProfileChangeEventService.class));
private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, null, activeRuleIndexer, qualityProfileChangeEventService);
private QProfileResetImpl underTest = new QProfileResetImpl(db.getDbClient(), ruleActivator, activeRuleIndexer, mock(QualityProfileChangeEventService.class));

@Test
public void reset() {
@@ -77,6 +83,7 @@ public class QProfileResetImplTest {
assertThat(result.getChanges())
.extracting(ActiveRuleChange::getKey, ActiveRuleChange::getType)
.containsExactlyInAnyOrder(tuple(ActiveRuleKey.of(profile, newRule.getKey()), ACTIVATED));
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

@Test
@@ -94,6 +101,7 @@ public class QProfileResetImplTest {
assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), childProfile))
.extracting(OrgActiveRuleDto::getRuleKey)
.containsExactlyInAnyOrder(newRule.getKey(), existingRule.getKey());
verify(qualityProfileChangeEventService, times(2)).distributeRuleChangeEvent(any(), any(), eq(childProfile.getLanguage()));
}

@Test
@@ -106,6 +114,7 @@ public class QProfileResetImplTest {
})
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(String.format("Operation forbidden for built-in Quality Profile '%s'", profile.getKee()));
verifyNoInteractions(qualityProfileChangeEventService);
}

@Test
@@ -118,5 +127,7 @@ public class QProfileResetImplTest {
})
.isInstanceOf(NullPointerException.class)
.hasMessage("Quality profile must be persisted");

verifyNoInteractions(qualityProfileChangeEventService);
}
}

+ 101
- 36
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileRuleImplTest.java Bestand weergeven

@@ -61,6 +61,11 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.sonar.api.rule.Severity.BLOCKER;
import static org.sonar.api.rule.Severity.CRITICAL;
import static org.sonar.api.rule.Severity.MAJOR;
@@ -81,9 +86,10 @@ public class QProfileRuleImplTest {
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client());
private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient());
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);

private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession);
private QProfileRules underTest = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer);
private QProfileRules underTest = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);

@Test
public void system_activates_rule_without_parameters() {
@@ -94,6 +100,7 @@ public class QProfileRuleImplTest {

assertThatRuleIsActivated(profile, rule, changes, BLOCKER, null, emptyMap());
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

@Test
@@ -106,6 +113,7 @@ public class QProfileRuleImplTest {

assertThatRuleIsActivated(profile, rule, changes, BLOCKER, null, emptyMap());
assertThatProfileIsUpdatedByUser(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

@Test
@@ -119,6 +127,7 @@ public class QProfileRuleImplTest {

assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "10"));
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

@Test
@@ -132,6 +141,7 @@ public class QProfileRuleImplTest {

assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "15"));
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

@Test
@@ -144,6 +154,7 @@ public class QProfileRuleImplTest {

assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap());
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

/**
@@ -160,6 +171,7 @@ public class QProfileRuleImplTest {

assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "10"));
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

/**
@@ -179,6 +191,7 @@ public class QProfileRuleImplTest {
assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null,
of(paramWithoutDefault.getName(), "-10", paramWithDefault.getName(), paramWithDefault.getDefaultValue()));
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

@Test
@@ -192,6 +205,7 @@ public class QProfileRuleImplTest {

assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

@Test
@@ -202,14 +216,16 @@ public class QProfileRuleImplTest {

// initial activation
RuleActivation activation = RuleActivation.create(rule.getUuid(), MAJOR, null);
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

// update
RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "20"));
List<ActiveRuleChange> changes = activate(profile, updateActivation);
changes = activate(profile, updateActivation);

assertThatRuleIsUpdated(profile, rule, CRITICAL, null, of(param.getName(), "20"));
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -221,14 +237,16 @@ public class QProfileRuleImplTest {

// initial activation -> param "max" has a default value
RuleActivation activation = RuleActivation.create(rule.getUuid());
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);

// update param "min", which has no default value
RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(paramWithoutDefault.getName(), "3"));
List<ActiveRuleChange> changes = activate(profile, updateActivation);
changes = activate(profile, updateActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

assertThatRuleIsUpdated(profile, rule, MAJOR, null, of(paramWithDefault.getName(), "10", paramWithoutDefault.getName(), "3"));
assertThatProfileIsUpdatedBySystem(profile);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -239,14 +257,16 @@ public class QProfileRuleImplTest {

// initial activation -> param "max" has a default value
RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(paramWithDefault.getName(), "20"));
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

// reset to default_value
RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(paramWithDefault.getName(), ""));
List<ActiveRuleChange> changes = activate(profile, updateActivation);
changes = activate(profile, updateActivation);

assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(paramWithDefault.getName(), "10"));
assertThat(changes).hasSize(1);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -258,14 +278,16 @@ public class QProfileRuleImplTest {

// initial activation -> param "max" has a default value
RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), "20"));
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

// remove parameter
RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), ""));
List<ActiveRuleChange> changes = activate(profile, updateActivation);
changes = activate(profile, updateActivation);

assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(paramWithDefault.getName(), paramWithDefault.getDefaultValue()));
assertThat(changes).hasSize(1);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -279,6 +301,7 @@ public class QProfileRuleImplTest {
List<ActiveRuleChange> changes = activate(profile, activation);
db.getDbClient().activeRuleDao().deleteParametersByRuleProfileUuids(db.getSession(), asList(profile.getRulesProfileUuid()));
assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap());
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

// contrary to activerule, the param is supposed to be inserted but not updated
RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(param.getName(), ""));
@@ -286,6 +309,7 @@ public class QProfileRuleImplTest {

assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
assertThat(changes).hasSize(1);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -295,13 +319,15 @@ public class QProfileRuleImplTest {

// initial activation
RuleActivation activation = RuleActivation.create(rule.getUuid());
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

// update with exactly the same severity and params
activation = RuleActivation.create(rule.getUuid());
List<ActiveRuleChange> changes = activate(profile, activation);
changes = activate(profile, activation);

assertThat(changes).isEmpty();
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -312,13 +338,16 @@ public class QProfileRuleImplTest {

// initial activation -> param "max" has a default value
RuleActivation activation = RuleActivation.create(rule.getUuid(), BLOCKER, of(param.getName(), "20"));
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));


// update without any severity or params => keep
RuleActivation update = RuleActivation.create(rule.getUuid());
List<ActiveRuleChange> changes = activate(profile, update);
changes = activate(profile, update);

assertThat(changes).isEmpty();
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -328,6 +357,7 @@ public class QProfileRuleImplTest {
RuleActivation activation = RuleActivation.create(rule.getUuid());

expectFailure("java rule " + rule.getKey() + " cannot be activated on js profile " + profile.getKee(), () -> activate(profile, activation));
verifyNoInteractions(qualityProfileChangeEventService);
}

@Test
@@ -337,6 +367,7 @@ public class QProfileRuleImplTest {
RuleActivation activation = RuleActivation.create(rule.getUuid());

expectFailure("Rule was removed: " + rule.getKey(), () -> activate(profile, activation));
verifyNoInteractions(qualityProfileChangeEventService);
}

@Test
@@ -346,6 +377,7 @@ public class QProfileRuleImplTest {
RuleActivation activation = RuleActivation.create(rule.getUuid());

expectFailure("Rule template can't be activated on a Quality profile: " + rule.getKey(), () -> activate(profile, activation));
verifyNoInteractions(qualityProfileChangeEventService);
}

@Test
@@ -356,6 +388,7 @@ public class QProfileRuleImplTest {

RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(param.getName(), "foo"));
expectFailure("Value 'foo' must be an integer.", () -> activate(profile, activation));
verifyNoInteractions(qualityProfileChangeEventService);
}

@Test
@@ -368,13 +401,15 @@ public class QProfileRuleImplTest {

// initial activation
RuleActivation activation = RuleActivation.create(customRule.getUuid(), MAJOR, emptyMap());
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
assertThatRuleIsActivated(profile, customRule, null, MAJOR, null, of("format", "txt"));
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

// update -> parameter is not changed
RuleActivation updateActivation = RuleActivation.create(customRule.getUuid(), BLOCKER, of("format", "xml"));
activate(profile, updateActivation);
changes = activate(profile, updateActivation);
assertThatRuleIsActivated(profile, customRule, null, BLOCKER, null, of("format", "txt"));
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -383,13 +418,15 @@ public class QProfileRuleImplTest {
RuleDefinitionDto rule = createRule();
QProfileDto profile = createProfile(rule);
RuleActivation activation = RuleActivation.create(rule.getUuid());
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

List<ActiveRuleChange> changes = deactivate(profile, rule);
changes = deactivate(profile, rule);
verifyNoActiveRules();
assertThatProfileIsUpdatedByUser(profile);
assertThat(changes).hasSize(1);
assertThat(changes.get(0).getType()).isEqualTo(ActiveRuleChange.Type.DEACTIVATED);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -397,12 +434,14 @@ public class QProfileRuleImplTest {
RuleDefinitionDto rule = createRule();
QProfileDto profile = createProfile(rule);
RuleActivation activation = RuleActivation.create(rule.getUuid());
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

List<ActiveRuleChange> changes = deactivate(profile, rule);
changes = deactivate(profile, rule);
verifyNoActiveRules();
assertThatProfileIsUpdatedBySystem(profile);
assertThatChangeIsDeactivation(changes, rule);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

private void assertThatChangeIsDeactivation(List<ActiveRuleChange> changes, RuleDefinitionDto rule) {
@@ -420,6 +459,7 @@ public class QProfileRuleImplTest {
List<ActiveRuleChange> changes = deactivate(profile, rule);
verifyNoActiveRules();
assertThat(changes).isEmpty();
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
}

@Test
@@ -427,14 +467,16 @@ public class QProfileRuleImplTest {
RuleDefinitionDto rule = createRule();
QProfileDto profile = createProfile(rule);
RuleActivation activation = RuleActivation.create(rule.getUuid());
activate(profile, activation);
List<ActiveRuleChange> changes = activate(profile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));

rule.setStatus(RuleStatus.REMOVED);
db.getDbClient().ruleDao().update(db.getSession(), rule);

List<ActiveRuleChange> changes = deactivate(profile, rule);
changes = deactivate(profile, rule);
verifyNoActiveRules();
assertThatChangeIsDeactivation(changes, rule);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
}

@Test
@@ -448,6 +490,7 @@ public class QProfileRuleImplTest {
assertThatProfileHasNoActiveRules(parentProfile);
assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
assertThatRuleIsActivated(grandChildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(childProfile.getLanguage()));
}

@Test
@@ -460,17 +503,20 @@ public class QProfileRuleImplTest {

System.out.println("ACTIVATE ON " + childProfile.getName());
RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
activate(childProfile, initialActivation);
List<ActiveRuleChange> changes = activate(childProfile, initialActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));

System.out.println("---------------");
System.out.println("ACTIVATE ON " + childProfile.getName());
RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
List<ActiveRuleChange> changes = activate(childProfile, updateActivation);
changes = activate(childProfile, updateActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));

assertThatProfileHasNoActiveRules(parentProfile);
assertThatRuleIsUpdated(childProfile, rule, CRITICAL, null, of(param.getName(), "bar"));
assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, INHERITED, of(param.getName(), "bar"));
assertThat(changes).hasSize(2);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
}

@Test
@@ -482,15 +528,17 @@ public class QProfileRuleImplTest {
QProfileDto grandChildProfile = createChildProfile(childProfile);

RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
activate(childProfile, initialActivation);
List<ActiveRuleChange> changes = activate(childProfile, initialActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));

RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
List<ActiveRuleChange> changes = activate(grandChildProfile, overrideActivation);
changes = activate(grandChildProfile, overrideActivation);

assertThatProfileHasNoActiveRules(parentProfile);
assertThatRuleIsUpdated(childProfile, rule, MAJOR, null, of(param.getName(), "foo"));
assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
assertThat(changes).hasSize(1);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
}

@Test
@@ -502,19 +550,22 @@ public class QProfileRuleImplTest {
QProfileDto grandChildProfile = createChildProfile(childProfile);

RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
activate(childProfile, initialActivation);
List<ActiveRuleChange> changes = activate(childProfile, initialActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));

RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
activate(grandChildProfile, overrideActivation);
changes = activate(grandChildProfile, overrideActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(grandChildProfile.getLanguage()));

// update child --> do not touch grandChild
RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), BLOCKER, of(param.getName(), "baz"));
List<ActiveRuleChange> changes = activate(childProfile, updateActivation);
changes = activate(childProfile, updateActivation);

assertThatProfileHasNoActiveRules(parentProfile);
assertThatRuleIsUpdated(childProfile, rule, BLOCKER, null, of(param.getName(), "baz"));
assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
assertThat(changes).hasSize(1);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
}

@Test
@@ -526,19 +577,22 @@ public class QProfileRuleImplTest {
QProfileDto grandChildProfile = createChildProfile(childProfile);

RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
activate(parentProfile, initialActivation);
List<ActiveRuleChange> changes = activate(parentProfile, initialActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));

RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
activate(grandChildProfile, overrideActivation);
changes = activate(grandChildProfile, overrideActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(grandChildProfile.getLanguage()));

// reset parent --> touch child but not grandChild
RuleActivation updateActivation = RuleActivation.createReset(rule.getUuid());
List<ActiveRuleChange> changes = activate(parentProfile, updateActivation);
changes = activate(parentProfile, updateActivation);

assertThatRuleIsUpdated(parentProfile, rule, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
assertThatRuleIsUpdated(childProfile, rule, rule.getSeverityString(), INHERITED, of(param.getName(), param.getDefaultValue()));
assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
assertThat(changes).hasSize(2);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
}

@Test
@@ -549,14 +603,16 @@ public class QProfileRuleImplTest {
QProfileDto childProfile = createChildProfile(parentProfile);

RuleActivation childActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
activate(childProfile, childActivation);
List<ActiveRuleChange> changes = activate(childProfile, childActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));

RuleActivation parentActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
List<ActiveRuleChange> changes = activate(parentProfile, parentActivation);
changes = activate(parentProfile, parentActivation);

assertThatRuleIsUpdated(parentProfile, rule, CRITICAL, null, of(param.getName(), "bar"));
assertThatRuleIsUpdated(childProfile, rule, MAJOR, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "foo"));
assertThat(changes).hasSize(2);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
}

@Test
@@ -567,13 +623,15 @@ public class QProfileRuleImplTest {
QProfileDto childProfile = createChildProfile(parentProfile);

RuleActivation parentActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
activate(parentProfile, parentActivation);
List<ActiveRuleChange> changes = activate(parentProfile, parentActivation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));

RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
List<ActiveRuleChange> changes = activate(childProfile, overrideActivation);
changes = activate(childProfile, overrideActivation);

assertThatRuleIsUpdated(childProfile, rule, MAJOR, INHERITED, of(param.getName(), "foo"));
assertThat(changes).isEmpty();
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
}

@Test
@@ -586,11 +644,13 @@ public class QProfileRuleImplTest {
List<ActiveRuleChange> changes = activate(parentProfile, activation);
assertThatRuleIsActivated(parentProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));

changes = deactivate(parentProfile, rule);
assertThatProfileHasNoActiveRules(parentProfile);
assertThatProfileHasNoActiveRules(childProfile);
assertThat(changes).hasSize(2);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
}

@Test
@@ -603,14 +663,17 @@ public class QProfileRuleImplTest {
List<ActiveRuleChange> changes = activate(parentProfile, activation);
assertThatRuleIsActivated(parentProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));

activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
activate(childProfile, activation);
changes = activate(childProfile, activation);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));

changes = deactivate(parentProfile, rule);
assertThatProfileHasNoActiveRules(parentProfile);
assertThatProfileHasNoActiveRules(childProfile);
assertThat(changes).hasSize(2);
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
}

@Test
@@ -627,6 +690,7 @@ public class QProfileRuleImplTest {
assertThatThrownBy(() -> deactivate(childProfile, rule))
.isInstanceOf(BadRequestException.class)
.hasMessageContaining("Cannot deactivate inherited rule");
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(parentProfile.getLanguage()));
}

@Test
@@ -651,6 +715,7 @@ public class QProfileRuleImplTest {
assertThatRuleIsUpdated(childProfile, rule, CRITICAL, INHERITED, emptyMap());
assertThatRuleIsUpdated(parentProfile, rule, CRITICAL, null, emptyMap());
assertThat(changes).hasSize(1);

}

@Test

+ 10
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileRulesImplTest.java Bestand weergeven

@@ -43,6 +43,10 @@ import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class QProfileRulesImplTest {

@@ -55,9 +59,11 @@ public class QProfileRulesImplTest {

private RuleIndex ruleIndex = new RuleIndex(es.client(), System2.INSTANCE);
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client());
private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), new TypeValidations(singletonList(new IntegerTypeValidation())), userSession);
private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), new TypeValidations(singletonList(new IntegerTypeValidation())),
userSession);
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);

private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer);
private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);

@Test
public void activate_one_rule() {
@@ -70,6 +76,7 @@ public class QProfileRulesImplTest {
assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), qProfile))
.extracting(ActiveRuleDto::getRuleKey, ActiveRuleDto::getSeverityString)
.containsExactlyInAnyOrder(tuple(rule.getKey(), Severity.CRITICAL));
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(qProfile.getLanguage()));
}

@Test
@@ -85,5 +92,6 @@ public class QProfileRulesImplTest {
assertThat(db.getDbClient().qProfileChangeDao().selectByQuery(db.getSession(), new QProfileChangeQuery(qProfile.getKee())))
.extracting(QProfileChangeDto::getUserUuid, QProfileChangeDto::getDataAsMap)
.containsExactlyInAnyOrder(tuple(user.getUuid(), ImmutableMap.of("ruleUuid", rule.getUuid(), "severity", Severity.CRITICAL)));
verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(qProfile.getLanguage()));
}
}

+ 14
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileTreeImplTest.java Bestand weergeven

@@ -47,6 +47,12 @@ import static java.util.Collections.emptyMap;
import static java.util.Collections.singleton;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.sonar.api.rule.Severity.BLOCKER;
import static org.sonar.server.qualityprofile.ActiveRuleInheritance.INHERITED;

@@ -61,9 +67,10 @@ public class QProfileTreeImplTest {
public UserSessionRule userSession = UserSessionRule.standalone();
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client());
private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession);
private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, null, activeRuleIndexer);
private QProfileTree underTest = new QProfileTreeImpl(db.getDbClient(), ruleActivator, System2.INSTANCE, activeRuleIndexer);
private QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, null, activeRuleIndexer, qualityProfileChangeEventService);
private QProfileTree underTest = new QProfileTreeImpl(db.getDbClient(), ruleActivator, System2.INSTANCE, activeRuleIndexer, mock(QualityProfileChangeEventService.class));

@Test
public void set_itself_as_parent_fails() {
@@ -133,11 +140,13 @@ public class QProfileTreeImplTest {
assertThat(changes).hasSize(1);
assertThatRuleIsActivated(profile2, rule1, changes, rule1.getSeverityString(), INHERITED, emptyMap());
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap());
verify(qualityProfileChangeEventService, times(2)).distributeRuleChangeEvent(any(), any(), eq(profile2.getLanguage()));

changes = underTest.removeParentAndCommit(db.getSession(), profile2);
assertThat(changes).hasSize(1);
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap());
assertThatRuleIsNotPresent(profile2, rule1);
verify(qualityProfileChangeEventService, times(2)).distributeRuleChangeEvent(any(), any(), eq(profile2.getLanguage()));
}

@Test
@@ -156,6 +165,7 @@ public class QProfileTreeImplTest {
assertThat(changes).hasSize(1);
assertThatRuleIsActivated(profile2, rule1, changes, rule1.getSeverityString(), INHERITED, emptyMap());
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap());
verify(qualityProfileChangeEventService, times(2)).distributeRuleChangeEvent(any(), any(), eq(profile2.getLanguage()));

RuleActivation activation = RuleActivation.create(rule1.getUuid(), BLOCKER, null);
changes = activate(profile2, activation);
@@ -168,6 +178,7 @@ public class QProfileTreeImplTest {
// Not testing changes here since severity is not set in changelog
assertThatRuleIsActivated(profile2, rule1, null, BLOCKER, null, emptyMap());
assertThatRuleIsActivated(profile2, rule2, null, rule2.getSeverityString(), null, emptyMap());
verify(qualityProfileChangeEventService, times(3)).distributeRuleChangeEvent(anyList(), any(), eq(profile2.getLanguage()));
}

@Test
@@ -183,6 +194,7 @@ public class QProfileTreeImplTest {

QProfileDto childProfile = createProfile(rule1);
List<ActiveRuleChange> changes = underTest.setParentAndCommit(db.getSession(), childProfile, parentProfile);
verify(qualityProfileChangeEventService, times(2)).distributeRuleChangeEvent(any(), any(), eq(childProfile.getLanguage()));

assertThatRuleIsNotPresent(childProfile, rule1);
assertThatRuleIsActivated(childProfile, rule2, changes, rule2.getSeverityString(), INHERITED, emptyMap());

+ 3
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationTest.java Bestand weergeven

@@ -90,12 +90,13 @@ public class RegisterQualityProfilesNotificationTest {
private DbClient dbClient = db.getDbClient();
private TypeValidations typeValidations = mock(TypeValidations.class);
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class);
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private ServerRuleFinder ruleFinder = new DefaultRuleFinder(dbClient);
private BuiltInQProfileInsert builtInQProfileInsert = new BuiltInQProfileInsertImpl(dbClient, ruleFinder, system2, UuidFactoryFast.getInstance(),
typeValidations, activeRuleIndexer);
private RuleActivator ruleActivator = new RuleActivator(system2, dbClient, typeValidations, userSessionRule);
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, mock(RuleIndex.class), activeRuleIndexer);
private BuiltInQProfileUpdate builtInQProfileUpdate = new BuiltInQProfileUpdateImpl(dbClient, ruleActivator, activeRuleIndexer);
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, mock(RuleIndex.class), activeRuleIndexer, qualityProfileChangeEventService);
private BuiltInQProfileUpdate builtInQProfileUpdate = new BuiltInQProfileUpdateImpl(dbClient, ruleActivator, activeRuleIndexer, qualityProfileChangeEventService);
private BuiltInQualityProfilesUpdateListener builtInQualityProfilesNotification = mock(BuiltInQualityProfilesUpdateListener.class);
private RegisterQualityProfiles underTest = new RegisterQualityProfiles(builtInQProfileRepositoryRule, dbClient,
builtInQProfileInsert, builtInQProfileUpdate, builtInQualityProfilesNotification, system2);

+ 12
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/AddProjectActionTest.java Bestand weergeven

@@ -36,14 +36,19 @@ import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.language.LanguageTesting;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;

import static java.lang.String.format;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES;

public class AddProjectActionTest {
@@ -59,7 +64,8 @@ public class AddProjectActionTest {
private final DbClient dbClient = db.getDbClient();
private final Languages languages = LanguageTesting.newLanguages(LANGUAGE_1, LANGUAGE_2);
private final QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession);
private final AddProjectAction underTest = new AddProjectAction(dbClient, userSession, languages, TestComponentFinder.from(db), wsSupport);
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private final AddProjectAction underTest = new AddProjectAction(dbClient, userSession, languages, TestComponentFinder.from(db), wsSupport, qualityProfileChangeEventService);
private final WsActionTester tester = new WsActionTester(underTest);

@Test
@@ -88,6 +94,7 @@ public class AddProjectActionTest {
assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);

assertProjectIsAssociatedToProfile(project, profile);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, of(profile), empty());
}

@Test
@@ -101,6 +108,7 @@ public class AddProjectActionTest {
call(project, qualityProfile);

assertProjectIsAssociatedToProfile(project, qualityProfile);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, of(qualityProfile), empty());
}

@Test
@@ -117,6 +125,7 @@ public class AddProjectActionTest {

assertProjectIsNotAssociatedToProfile(project, profile1);
assertProjectIsAssociatedToProfile(project, profile2);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, of(profile2), of(profile1));
}

@Test
@@ -132,6 +141,7 @@ public class AddProjectActionTest {

assertProjectIsAssociatedToProfile(project, profile3Language1);
assertProjectIsAssociatedToProfile(project, profile2Language2);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, of(profile3Language1), of(profile1Language1));
}

@Test
@@ -143,6 +153,7 @@ public class AddProjectActionTest {
call(project, profile);

assertProjectIsAssociatedToProfile(project, profile);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, of(profile), empty());
}

@Test

+ 3
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionTest.java Bestand weergeven

@@ -49,6 +49,7 @@ import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.language.LanguageTesting;
import org.sonar.server.qualityprofile.QProfileTreeImpl;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.rule.index.RuleIndex;
@@ -64,6 +65,7 @@ import static java.util.Arrays.asList;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE;
@@ -98,7 +100,7 @@ public class ChangeParentActionTest {
activeRuleIndexer = new ActiveRuleIndexer(dbClient, esClient);
TypeValidations typeValidations = new TypeValidations(Collections.emptyList());
RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSession);
qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer);
qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer, mock(QualityProfileChangeEventService.class));
ChangeParentAction underTest = new ChangeParentAction(
dbClient,
qProfileTree,

+ 4
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/CreateActionTest.java Bestand weergeven

@@ -46,6 +46,7 @@ import org.sonar.server.qualityprofile.QProfileExporters;
import org.sonar.server.qualityprofile.QProfileFactoryImpl;
import org.sonar.server.qualityprofile.QProfileRules;
import org.sonar.server.qualityprofile.QProfileRulesImpl;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.rule.index.RuleIndex;
@@ -62,6 +63,7 @@ import org.sonarqube.ws.Qualityprofiles.CreateWsResponse.QualityProfile;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.db.permission.GlobalPermission.SCAN;
import static org.sonar.server.language.LanguageTesting.newLanguages;
@@ -87,8 +89,9 @@ public class CreateActionTest {
private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), dbClient);
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(dbClient, es.client());
private ProfileImporter[] profileImporters = createImporters();
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, null, userSession);
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer);
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);
private QProfileExporters qProfileExporters = new QProfileExporters(dbClient, null, qProfileRules, profileImporters);

private CreateAction underTest = new CreateAction(dbClient, new QProfileFactoryImpl(dbClient, UuidFactoryFast.getInstance(), System2.INSTANCE, activeRuleIndexer),

+ 5
- 2
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/InheritanceActionTest.java Bestand weergeven

@@ -45,6 +45,7 @@ import org.sonar.server.qualityprofile.QProfileRules;
import org.sonar.server.qualityprofile.QProfileRulesImpl;
import org.sonar.server.qualityprofile.QProfileTree;
import org.sonar.server.qualityprofile.QProfileTreeImpl;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.qualityprofile.RuleActivation;
import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
@@ -59,6 +60,7 @@ import static java.util.Arrays.asList;
import static java.util.Collections.singleton;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.MediaTypes.PROTOBUF;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
@@ -80,9 +82,10 @@ public class InheritanceActionTest {
private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(dbClient, esClient);

private RuleIndex ruleIndex = new RuleIndex(esClient, System2.INSTANCE);
private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, new TypeValidations(new ArrayList<>()), userSession);
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer);
private QProfileTree qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer);
private QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);
private QProfileTree qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer, mock(QualityProfileChangeEventService.class));

private WsActionTester ws = new WsActionTester(new InheritanceAction(
dbClient,

+ 4
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsMediumTest.java Bestand weergeven

@@ -43,6 +43,7 @@ import org.sonar.server.es.SearchOptions;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.qualityprofile.QProfileRules;
import org.sonar.server.qualityprofile.QProfileRulesImpl;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.rule.index.RuleIndex;
@@ -56,6 +57,7 @@ import org.sonar.server.ws.WsActionTester;
import static java.util.Collections.emptyList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
@@ -81,8 +83,9 @@ public class QProfilesWsMediumTest {
private final RuleIndexer ruleIndexer = new RuleIndexer(es.client(), dbClient);
private final ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(dbClient, es.client());
private final TypeValidations typeValidations = new TypeValidations(emptyList());
private final QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private final RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSessionRule);
private final QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer);
private final QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);
private final QProfileWsSupport qProfileWsSupport = new QProfileWsSupport(dbClient, userSessionRule);
private final RuleQueryFactory ruleQueryFactory = new RuleQueryFactory(dbClient);


+ 11
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/RemoveProjectActionTest.java Bestand weergeven

@@ -22,6 +22,7 @@ package org.sonar.server.qualityprofile.ws;
import java.net.HttpURLConnection;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.server.ws.WebService;
@@ -38,14 +39,18 @@ import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.language.LanguageTesting;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;

import static java.lang.String.format;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.verify;
import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES;

public class RemoveProjectActionTest {
@@ -61,8 +66,9 @@ public class RemoveProjectActionTest {
private final Languages languages = LanguageTesting.newLanguages(LANGUAGE_1, LANGUAGE_2);
private final QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession);

private final QualityProfileChangeEventService qualityProfileChangeEventService = Mockito.mock(QualityProfileChangeEventService.class);
private final RemoveProjectAction underTest = new RemoveProjectAction(dbClient, userSession, languages,
new ComponentFinder(dbClient, new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT)), wsSupport);
new ComponentFinder(dbClient, new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT)), wsSupport, qualityProfileChangeEventService);
private final WsActionTester ws = new WsActionTester(underTest);

@Test
@@ -97,6 +103,7 @@ public class RemoveProjectActionTest {

assertProjectIsNotAssociatedToProfile(project, profileLang1);
assertProjectIsAssociatedToProfile(project, profileLang2);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, empty(), of(profileLang1));
}

@Test
@@ -110,6 +117,7 @@ public class RemoveProjectActionTest {
assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);

assertProjectIsNotAssociatedToProfile(project, profile);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, empty(), of(profile));
}

@Test
@@ -122,6 +130,7 @@ public class RemoveProjectActionTest {
call(project, profile);

assertProjectIsNotAssociatedToProfile(project, profile);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, empty(), of(profile));
}

@Test
@@ -136,6 +145,7 @@ public class RemoveProjectActionTest {
call(project, profile);

assertProjectIsNotAssociatedToProfile(project, profile);
verify(qualityProfileChangeEventService).publishRuleActivationToSonarLintClients(project, empty(), of(profile));
}

@Test

+ 4
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java Bestand weergeven

@@ -48,6 +48,7 @@ import org.sonar.server.language.LanguageTesting;
import org.sonar.server.qualityprofile.ActiveRuleChange;
import org.sonar.server.qualityprofile.QProfileRules;
import org.sonar.server.qualityprofile.QProfileRulesImpl;
import org.sonar.server.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.qualityprofile.RuleActivation;
import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
@@ -105,12 +106,14 @@ public class SearchActionTest {
private final ActiveRuleCompleter activeRuleCompleter = new ActiveRuleCompleter(db.getDbClient(), languages);
private final RuleQueryFactory ruleQueryFactory = new RuleQueryFactory(db.getDbClient());
private final MacroInterpreter macroInterpreter = mock(MacroInterpreter.class);
private final QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
private final RuleMapper ruleMapper = new RuleMapper(languages, macroInterpreter);
private final SearchAction underTest = new SearchAction(ruleIndex, activeRuleCompleter, ruleQueryFactory, db.getDbClient(), ruleMapper,
new RuleWsSupport(db.getDbClient(), userSession));
private final TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
private final RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db.getDbClient(), typeValidations, userSession);
private final QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer);
private final QProfileRules qProfileRules = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer,
qualityProfileChangeEventService);
private final WsActionTester ws = new WsActionTester(underTest);

@Before

+ 4
- 0
server/sonar-webserver-ws/src/main/java/org/sonar/server/ws/ServletRequest.java Bestand weergeven

@@ -69,6 +69,10 @@ public class ServletRequest extends ValidatingRequest {
MediaTypes.DEFAULT));
}

public HttpServletRequest getHttpRequest() {
return source;
}

@Override
public BufferedReader getReader() {
try {

+ 7
- 0
server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java Bestand weergeven

@@ -189,6 +189,7 @@ import org.sonar.server.qualitygate.ws.QualityGateWsModule;
import org.sonar.server.qualityprofile.BuiltInQPChangeNotificationHandler;
import org.sonar.server.qualityprofile.BuiltInQPChangeNotificationTemplate;
import org.sonar.server.qualityprofile.BuiltInQProfileRepositoryImpl;
import org.sonar.server.qualityprofile.DistributedRuleActivatorEventsDistributor;
import org.sonar.server.qualityprofile.QProfileBackuperImpl;
import org.sonar.server.qualityprofile.QProfileComparison;
import org.sonar.server.qualityprofile.QProfileCopier;
@@ -198,7 +199,9 @@ import org.sonar.server.qualityprofile.QProfileParser;
import org.sonar.server.qualityprofile.QProfileResetImpl;
import org.sonar.server.qualityprofile.QProfileRulesImpl;
import org.sonar.server.qualityprofile.QProfileTreeImpl;
import org.sonar.server.qualityprofile.QualityProfileChangeEventServiceImpl;
import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.qualityprofile.StandaloneRuleActivatorEventsDistributor;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.qualityprofile.ws.QProfilesWsModule;
import org.sonar.server.root.ws.RootWsModule;
@@ -274,6 +277,9 @@ public class PlatformLevel4 extends PlatformLevel {

addIfCluster(NodeHealthModule.class);

addIfCluster(DistributedRuleActivatorEventsDistributor.class);
addIfStandalone(StandaloneRuleActivatorEventsDistributor.class);

add(
ClusterVerification.class,
LogServerId.class,
@@ -304,6 +310,7 @@ public class PlatformLevel4 extends PlatformLevel {
QProfileTreeImpl.class,
QProfileRulesImpl.class,
RuleActivator.class,
QualityProfileChangeEventServiceImpl.class,
QProfileExporters.class,
QProfileFactoryImpl.class,
QProfileCopier.class,

+ 38
- 0
sonar-core/src/main/java/org/sonar/core/util/ParamChange.java Bestand weergeven

@@ -0,0 +1,38 @@
/*
* 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.core.util;

public class ParamChange {
String key;
String value;

public ParamChange(String key, String value) {
this.key = key;
this.value = value;
}

public String getKey() {
return key;
}

public String getValue() {
return value;
}
}

+ 25
- 0
sonar-core/src/main/java/org/sonar/core/util/RuleActivationListener.java Bestand weergeven

@@ -0,0 +1,25 @@
/*
* 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.core.util;

public interface RuleActivationListener {

void listen(RuleSetChangeEvent event);
}

+ 68
- 0
sonar-core/src/main/java/org/sonar/core/util/RuleChange.java Bestand weergeven

@@ -0,0 +1,68 @@
/*
* 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.core.util;

public class RuleChange {
String key;
String language;
String templateKey;
String severity;
ParamChange[] params = new ParamChange[0];

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}

public String getLanguage() {
return language;
}

public void setLanguage(String language) {
this.language = language;
}

public String getTemplateKey() {
return templateKey;
}

public void setTemplateKey(String templateKey) {
this.templateKey = templateKey;
}

public String getSeverity() {
return severity;
}

public void setSeverity(String severity) {
this.severity = severity;
}

public ParamChange[] getParams() {
return params;
}

public void setParams(ParamChange[] params) {
this.params = params;
}
}

+ 65
- 0
sonar-core/src/main/java/org/sonar/core/util/RuleSetChangeEvent.java Bestand weergeven

@@ -0,0 +1,65 @@
/*
* 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.core.util;

import java.io.Serializable;

public class RuleSetChangeEvent implements Serializable {

private final String event = "RuleSetChange";

private String[] projects;
private RuleChange[] activatedRules;
private RuleChange[] deactivatedRules;

public RuleSetChangeEvent(String[] projects, RuleChange[] activatedRules, RuleChange[] deactivatedRules) {
this.projects = projects;
this.activatedRules = activatedRules;
this.deactivatedRules = deactivatedRules;
}

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;
}

public String[] getProjects() {
return projects;
}

public RuleChange[] getActivatedRules() {
return activatedRules;
}

public RuleChange[] getDeactivatedRules() {
return deactivatedRules;
}
}

Laden…
Annuleren
Opslaan