package org.sonar.server.qualityprofile.ws;
import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Stream;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.Request;
import org.sonar.db.qualityprofile.ActiveRuleCountQuery;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonarqube.ws.QualityProfiles.ShowWsResponse;
+import org.sonarqube.ws.QualityProfiles.ShowWsResponse.CompareToSonarWay;
import org.sonarqube.ws.QualityProfiles.ShowWsResponse.QualityProfile;
import static java.util.Collections.singletonList;
public class ShowAction implements QProfileWsAction {
+ private static final String SONAR_WAY = "Sonar way";
+ private static final String SONARQUBE_WAY = "SonarQube way";
+
private final DbClient dbClient;
private final QProfileWsSupport qProfileWsSupport;
private final Languages languages;
show.createParam(PARAM_COMPARE_TO_SONAR_WAY)
.setDescription("Add the number of missing rules from the related Sonar way profile in the response")
.setInternal(true)
+ .setDefaultValue("false")
.setBooleanPossibleValues();
}
long activeRuleCount = countActiveRulesByQuery(dbSession, profile, builder);
long deprecatedActiveRuleCount = countActiveRulesByQuery(dbSession, profile, builder.setRuleStatus(DEPRECATED));
long projectCount = countProjectsByOrganizationAndProfiles(dbSession, organization, profile);
- writeProtobuf(buildResponse(profile, isDefault, getLanguage(profile), activeRuleCount, deprecatedActiveRuleCount, projectCount), request, response);
+ CompareToSonarWay compareToSonarWay = getSonarWay(request, dbSession, organization, profile);
+ writeProtobuf(buildResponse(profile, isDefault, getLanguage(profile), activeRuleCount, deprecatedActiveRuleCount, projectCount, compareToSonarWay), request, response);
}
}
return language;
}
- private static ShowWsResponse buildResponse(QProfileDto profile, boolean isDefault, Language language, long activeRules, long deprecatedActiveRules, long projects) {
+ @CheckForNull
+ public CompareToSonarWay getSonarWay(Request request, DbSession dbSession, OrganizationDto organization, QProfileDto profile) {
+ if (!request.mandatoryParamAsBoolean(PARAM_COMPARE_TO_SONAR_WAY) || profile.isBuiltIn()) {
+ return null;
+ }
+ QProfileDto sonarWay = Stream.of(SONAR_WAY, SONARQUBE_WAY)
+ .map(name -> dbClient.qualityProfileDao().selectByNameAndLanguage(dbSession, organization, name, profile.getLanguage()))
+ .filter(Objects::nonNull)
+ .filter(QProfileDto::isBuiltIn)
+ .findFirst()
+ .orElse(null);
+
+ if (sonarWay == null) {
+ return null;
+ }
+
+ return CompareToSonarWay.newBuilder()
+ .setProfile(sonarWay.getKee())
+ .setProfileName(sonarWay.getName())
+ .build();
+ }
+
+ private static ShowWsResponse buildResponse(QProfileDto profile, boolean isDefault, Language language, long activeRules, long deprecatedActiveRules, long projects,
+ @Nullable CompareToSonarWay compareToSonarWay) {
+ ShowWsResponse.Builder showResponseBuilder = ShowWsResponse.newBuilder();
QualityProfile.Builder profileBuilder = QualityProfile.newBuilder()
.setKey(profile.getKee())
.setName(profile.getName())
setNullable(profile.getRulesUpdatedAt(), profileBuilder::setRulesUpdatedAt);
setNullable(profile.getLastUsed(), last -> profileBuilder.setLastUsed(formatDateTime(last)));
setNullable(profile.getUserUpdatedAt(), userUpdatedAt -> profileBuilder.setUserUpdatedAt(formatDateTime(userUpdatedAt)));
- return ShowWsResponse.newBuilder().setProfile(profileBuilder).build();
+ setNullable(compareToSonarWay, showResponseBuilder::setCompareToSonarWay);
+ return showResponseBuilder.setProfile(profileBuilder).build();
}
}
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.MediaTypes;
import org.sonarqube.ws.QualityProfiles.ShowWsResponse;
+import org.sonarqube.ws.QualityProfiles.ShowWsResponse.CompareToSonarWay;
import static java.util.stream.IntStream.range;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.language.LanguageTesting.newLanguage;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.QualityProfiles.ShowWsResponse.QualityProfile;
+import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_COMPARE_TO_SONAR_WAY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROFILE;
public class ShowActionTest {
assertThat(compareToSonarWay.isRequired()).isFalse();
assertThat(compareToSonarWay.isInternal()).isTrue();
assertThat(compareToSonarWay.description()).isNotEmpty();
+ assertThat(compareToSonarWay.defaultValue()).isEqualTo("false");
assertThat(compareToSonarWay.possibleValues()).contains("true", "false");
}
.containsExactly(13L, 3L, 7L);
}
+ @Test
+ public void compare_to_sonar_way_profile() {
+ QProfileDto sonarWayProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(true).setName("Sonar way").setLanguage(XOO1.getKey()));
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+
+ CompareToSonarWay result = call(ws.newRequest()
+ .setParam(PARAM_PROFILE, profile.getKee())
+ .setParam(PARAM_COMPARE_TO_SONAR_WAY, "true"))
+ .getCompareToSonarWay();
+
+ assertThat(result)
+ .extracting(CompareToSonarWay::getProfile, CompareToSonarWay::getProfileName)
+ .containsExactly(sonarWayProfile.getKee(), sonarWayProfile.getName());
+ }
+
+ @Test
+ public void no_comparison_when_sonar_way_does_not_exist() {
+ QProfileDto anotherSonarWayProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(true).setName("Another Sonar way").setLanguage(XOO1.getKey()));
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+
+ ShowWsResponse result = call(ws.newRequest()
+ .setParam(PARAM_PROFILE, profile.getKee())
+ .setParam(PARAM_COMPARE_TO_SONAR_WAY, "true"));
+
+ assertThat(result.hasCompareToSonarWay()).isFalse();
+ }
+
+ @Test
+ public void no_comparison_when_profile_is_built_in() {
+ QProfileDto sonarWayProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(true).setName("Sonar way").setLanguage(XOO1.getKey()));
+ QProfileDto anotherBuiltInProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(true).setLanguage(XOO1.getKey()));
+
+ ShowWsResponse result = call(ws.newRequest()
+ .setParam(PARAM_PROFILE, anotherBuiltInProfile.getKee())
+ .setParam(PARAM_COMPARE_TO_SONAR_WAY, "true"));
+
+ assertThat(result.hasCompareToSonarWay()).isFalse();
+ }
+
+ @Test
+ public void no_comparison_if_sonar_way_is_not_built_in() {
+ QProfileDto sonarWayProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(false).setName("Sonar way").setLanguage(XOO1.getKey()));
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+
+ ShowWsResponse result = call(ws.newRequest()
+ .setParam(PARAM_PROFILE, profile.getKee())
+ .setParam(PARAM_COMPARE_TO_SONAR_WAY, "true"));
+
+ assertThat(result.hasCompareToSonarWay()).isFalse();
+ }
+
+ @Test
+ public void no_comparison_when_param_is_false() {
+ QProfileDto sonarWayProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(true).setName("Sonar way").setLanguage(XOO1.getKey()));
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+
+ ShowWsResponse result = call(ws.newRequest()
+ .setParam(PARAM_PROFILE, profile.getKee())
+ .setParam(PARAM_COMPARE_TO_SONAR_WAY, "false"));
+
+ assertThat(result.hasCompareToSonarWay()).isFalse();
+ }
+
+ @Test
+ public void compare_to_sonarqube_way_profile() {
+ QProfileDto sonarWayProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(true).setName("SonarQube way").setLanguage(XOO1.getKey()));
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+
+ CompareToSonarWay result = call(ws.newRequest()
+ .setParam(PARAM_PROFILE, profile.getKee())
+ .setParam(PARAM_COMPARE_TO_SONAR_WAY, "true"))
+ .getCompareToSonarWay();
+
+ assertThat(result)
+ .extracting(CompareToSonarWay::getProfile, CompareToSonarWay::getProfileName)
+ .containsExactly(sonarWayProfile.getKee(), sonarWayProfile.getName());
+ }
+
+ @Test
+ public void compare_to_sonar_way_over_sonarqube_way() {
+ QProfileDto sonarWayProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(true).setName("Sonar way").setLanguage(XOO1.getKey()));
+ QProfileDto sonarQubeWayProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setIsBuiltIn(true).setName("SonarQube way").setLanguage(XOO1.getKey()));
+ QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
+
+ CompareToSonarWay result = call(ws.newRequest()
+ .setParam(PARAM_PROFILE, profile.getKee())
+ .setParam(PARAM_COMPARE_TO_SONAR_WAY, "true"))
+ .getCompareToSonarWay();
+
+ assertThat(result)
+ .extracting(CompareToSonarWay::getProfile, CompareToSonarWay::getProfileName)
+ .containsExactly(sonarWayProfile.getKee(), sonarWayProfile.getName());
+ }
+
@Test
public void fail_if_profile_language_is_not_supported() {
QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setKee("unknown-profile").setLanguage("kotlin"));