From 0b3dcbf2c655af0b01005c03bcfb0debcf284f7f Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Wed, 16 Oct 2019 15:45:30 -0500 Subject: [PATCH] SONAR-10408 Web service api/qualityprofiles/copy is too slow --- .../QualityProfileExportDao.java | 10 +-- .../qualitygate/QualityGateUpdater.java | 5 -- .../qualityprofile/QProfileBackuper.java | 2 + .../qualityprofile/QProfileBackuperImpl.java | 40 +++++++++++- .../server/qualityprofile/QProfileCopier.java | 54 +++------------- .../qualityprofile/QProfileFactory.java | 3 + .../qualityprofile/QProfileFactoryImpl.java | 13 +++- .../server/qualityprofile/QProfileParser.java | 3 +- .../QProfileBackuperImplTest.java | 34 +++++++++-- .../qualityprofile/QProfileCopierTest.java | 61 ++++++------------- .../qualityprofile/ws/CopyActionTest.java | 51 ++++++++-------- .../qualityprofile/ws/ExportActionTest.java | 4 ++ .../qualityprofile/ws/RestoreActionTest.java | 4 ++ 13 files changed, 145 insertions(+), 139 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileExportDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileExportDao.java index 34a87233d2c..16816e4152c 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileExportDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileExportDao.java @@ -22,7 +22,6 @@ package org.sonar.db.qualityprofile; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import org.sonar.db.Dao; import org.sonar.db.DbSession; @@ -34,13 +33,10 @@ public class QualityProfileExportDao implements Dao { public List selectRulesByProfile(DbSession dbSession, QProfileDto profile) { List exportRules = mapper(dbSession).selectByProfileUuid(profile.getKee()); - Set activeRuleIds = exportRules.stream().map(ExportRuleDto::getActiveRuleId).collect(Collectors.toSet()); + Map exportRulesById = exportRules.stream().collect(Collectors.toMap(ExportRuleDto::getActiveRuleId, x -> x)); + Map> rulesParams = selectParamsByActiveRuleIds(dbSession, exportRulesById.keySet()); - Map> activeRulesParam = selectParamsByActiveRuleIds(dbSession, activeRuleIds); - - exportRules.forEach(exportRuleDto -> - exportRuleDto.setParams(activeRulesParam.get(exportRuleDto.getActiveRuleId())) - ); + rulesParams.forEach((id, rules) -> exportRulesById.get(id).setParams(rules)); return exportRules; } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java index 93658d2aa27..323a4aa72ec 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java @@ -70,11 +70,6 @@ public class QualityGateUpdater { checkQualityGateDoesNotAlreadyExist(dbSession, organizationDto, name); } - public void setDefault(DbSession dbSession, OrganizationDto organizationDto, QualityGateDto qualityGateDto) { - organizationDto.setDefaultQualityGateUuid(qualityGateDto.getUuid()); - dbClient.qualityGateDao().update(qualityGateDto, dbSession); - } - private void checkQualityGateDoesNotAlreadyExist(DbSession dbSession, OrganizationDto organizationDto, String name) { QualityGateDto existingQgate = dbClient.qualityGateDao().selectByOrganizationAndName(dbSession, organizationDto, name); checkArgument(existingQgate == null, IS_ALREADY_USED_MESSAGE, "Name"); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuper.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuper.java index dd418601955..23be874d95a 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuper.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuper.java @@ -44,4 +44,6 @@ public interface QProfileBackuper { * Restore backup on an existing profile. */ QProfileRestoreSummary restore(DbSession dbSession, Reader backup, QProfileDto profile); + + QProfileRestoreSummary copy(DbSession dbSession, QProfileDto from, QProfileDto to); } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java index ec95957feb0..0f4ac2cc8b0 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java @@ -21,6 +21,7 @@ package org.sonar.server.qualityprofile; import java.io.Reader; import java.io.Writer; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -39,6 +40,7 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.qualityprofile.ExportRuleDto; +import org.sonar.db.qualityprofile.ExportRuleParamDto; import org.sonar.db.qualityprofile.QProfileDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.server.rule.NewCustomRule; @@ -71,6 +73,35 @@ public class QProfileBackuperImpl implements QProfileBackuper { qProfileParser.writeXml(writer, profile, rulesToExport.iterator()); } + @Override + public QProfileRestoreSummary copy(DbSession dbSession, QProfileDto from, QProfileDto to) { + List rulesToExport = db.qualityProfileExportDao().selectRulesByProfile(dbSession, from); + rulesToExport.sort(BackupActiveRuleComparator.INSTANCE); + + ImportedQProfile qProfile = toImportedQProfile(rulesToExport, to.getName(), to.getLanguage()); + return restore(dbSession, qProfile, name -> to); + } + + private static ImportedQProfile toImportedQProfile(List exportRules, String profileName, String profileLang) { + List importedRules = new ArrayList<>(exportRules.size()); + + for (ExportRuleDto exportRuleDto : exportRules) { + ImportedRule importedRule = new ImportedRule(); + importedRule.setName(exportRuleDto.getName()); + importedRule.setDescription(exportRuleDto.getDescription()); + importedRule.setRuleKey(exportRuleDto.getRuleKey()); + importedRule.setSeverity(exportRuleDto.getSeverityString()); + if (importedRule.isCustomRule()) { + importedRule.setTemplateKey(exportRuleDto.getTemplateRuleKey()); + } + importedRule.setType(exportRuleDto.getRuleType().name()); + importedRule.setParameters(exportRuleDto.getParams().stream().collect(Collectors.toMap(ExportRuleParamDto::getKey, ExportRuleParamDto::getValue))); + importedRules.add(importedRule); + } + + return new ImportedQProfile(profileName, profileLang, importedRules); + } + @Override public QProfileRestoreSummary restore(DbSession dbSession, Reader backup, OrganizationDto organization, @Nullable String overriddenProfileName) { return restore(dbSession, backup, nameInBackup -> { @@ -93,7 +124,10 @@ public class QProfileBackuperImpl implements QProfileBackuper { private QProfileRestoreSummary restore(DbSession dbSession, Reader backup, Function profileLoader) { ImportedQProfile qProfile = qProfileParser.readXml(backup); + return restore(dbSession, qProfile, profileLoader); + } + private QProfileRestoreSummary restore(DbSession dbSession, ImportedQProfile qProfile, Function profileLoader) { QProfileName targetName = new QProfileName(qProfile.getProfileLang(), qProfile.getProfileName()); QProfileDto targetProfile = profileLoader.apply(targetName); @@ -174,9 +208,11 @@ public class QProfileBackuperImpl implements QProfileBackuper { @Override public int compare(ExportRuleDto o1, ExportRuleDto o2) { + RuleKey rk1 = o1.getRuleKey(); + RuleKey rk2 = o2.getRuleKey(); return new CompareToBuilder() - .append(o1.getRuleKey().repository(), o2.getRuleKey().repository()) - .append(o1.getRuleKey().rule(), o2.getRuleKey().rule()) + .append(rk1.repository(), rk2.repository()) + .append(rk1.rule(), rk2.rule()) .toComparison(); } } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java index 4b65da3c12c..d364768b303 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java @@ -19,84 +19,46 @@ */ package org.sonar.server.qualityprofile; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; -import org.apache.commons.io.FileUtils; import org.sonar.api.server.ServerSide; -import org.sonar.api.utils.TempFolder; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.qualityprofile.QProfileDto; -import static java.nio.charset.StandardCharsets.UTF_8; - @ServerSide public class QProfileCopier { - private final DbClient db; private final QProfileFactory factory; private final QProfileBackuper backuper; - private final TempFolder temp; - public QProfileCopier(DbClient db, QProfileFactory factory, QProfileBackuper backuper, TempFolder temp) { + public QProfileCopier(DbClient db, QProfileFactory factory, QProfileBackuper backuper) { this.db = db; this.factory = factory; this.backuper = backuper; - this.temp = temp; } public QProfileDto copyToName(DbSession dbSession, QProfileDto sourceProfile, String toName) { OrganizationDto organization = db.organizationDao().selectByUuid(dbSession, sourceProfile.getOrganizationUuid()) .orElseThrow(() -> new IllegalStateException("Organization with UUID [" + sourceProfile.getOrganizationUuid() + "] does not exist")); QProfileDto to = prepareTarget(dbSession, organization, sourceProfile, toName); - File backupFile = temp.newFile(); - try { - backup(dbSession, sourceProfile, backupFile); - restore(dbSession, backupFile, to); - return to; - } finally { - org.sonar.core.util.FileUtils.deleteQuietly(backupFile); - } + backuper.copy(dbSession, sourceProfile, to); + return to; } private QProfileDto prepareTarget(DbSession dbSession, OrganizationDto organization, QProfileDto sourceProfile, String toName) { + verify(sourceProfile.getName(), toName); QProfileName toProfileName = new QProfileName(sourceProfile.getLanguage(), toName); - verify(sourceProfile, toProfileName); QProfileDto toProfile = db.qualityProfileDao().selectByNameAndLanguage(dbSession, organization, toProfileName.getName(), toProfileName.getLanguage()); if (toProfile == null) { - toProfile = factory.checkAndCreateCustom(dbSession, organization, toProfileName); - toProfile.setParentKee(sourceProfile.getParentKee()); - db.qualityProfileDao().update(dbSession, toProfile); + toProfile = factory.createCustom(dbSession, organization, toProfileName, sourceProfile.getParentKee()); dbSession.commit(); } return toProfile; } - private void verify(QProfileDto fromProfile, QProfileName toProfileName) { - if (fromProfile.getName().equals(toProfileName.getName())) { - throw new IllegalArgumentException(String.format("Source and target profiles are equal: %s", - fromProfile.getName())); - } - } - - private void backup(DbSession dbSession, QProfileDto profile, File backupFile) { - try (Writer writer = new OutputStreamWriter(FileUtils.openOutputStream(backupFile), UTF_8)) { - backuper.backup(dbSession, profile, writer); - } catch (IOException e) { - throw new IllegalStateException("Fail to open temporary backup file: " + backupFile, e); - } - } - - private void restore(DbSession dbSession, File backupFile, QProfileDto profile) { - try (Reader reader = new InputStreamReader(FileUtils.openInputStream(backupFile), UTF_8)) { - backuper.restore(dbSession, reader, profile); - } catch (IOException e) { - throw new IllegalStateException("Fail to create temporary backup file: " + backupFile, e); + private static void verify(String fromProfileName, String toProfileName) { + if (fromProfileName.equals(toProfileName)) { + throw new IllegalArgumentException(String.format("Source and target profiles are equal: %s", toProfileName)); } } } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java index cfecdfdfa28..90e91a3750c 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java @@ -20,6 +20,7 @@ package org.sonar.server.qualityprofile; import java.util.Collection; +import javax.annotation.Nullable; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.qualityprofile.QProfileDto; @@ -39,6 +40,8 @@ public interface QProfileFactory { */ QProfileDto checkAndCreateCustom(DbSession dbSession, OrganizationDto organization, QProfileName name); + QProfileDto createCustom(DbSession dbSession, OrganizationDto organization, QProfileName name, @Nullable String parentKey); + /** * Deletes the specified profiles from database and Elasticsearch. * All information related to custom profiles are deleted. Only association diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java index 580f13aa45e..3456fbe6260 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java @@ -65,7 +65,7 @@ public class QProfileFactoryImpl implements QProfileFactory { requireNonNull(organization); QProfileDto profile = db.qualityProfileDao().selectByNameAndLanguage(dbSession, organization, name.getName(), name.getLanguage()); if (profile == null) { - profile = doCreate(dbSession, organization, name, false, false); + profile = doCreate(dbSession, organization, name, null, false, false); } else { checkArgument(!profile.isBuiltIn(), "Operation forbidden for built-in Quality Profile '%s' with language '%s'", profile.getName(), profile.getLanguage()); } @@ -78,10 +78,16 @@ public class QProfileFactoryImpl implements QProfileFactory { requireNonNull(organization); QProfileDto dto = db.qualityProfileDao().selectByNameAndLanguage(dbSession, organization, name.getName(), name.getLanguage()); checkRequest(dto == null, "Quality profile already exists: %s", name); - return doCreate(dbSession, organization, name, false, false); + return doCreate(dbSession, organization, name, null,false, false); } - private QProfileDto doCreate(DbSession dbSession, OrganizationDto organization, QProfileName name, boolean isDefault, boolean isBuiltIn) { + @Override + public QProfileDto createCustom(DbSession dbSession, OrganizationDto organization, QProfileName name, @Nullable String parentKey) { + requireNonNull(organization); + return doCreate(dbSession, organization, name, parentKey,false, false); + } + + private QProfileDto doCreate(DbSession dbSession, OrganizationDto organization, QProfileName name, @Nullable String parentKey, boolean isDefault, boolean isBuiltIn) { if (StringUtils.isEmpty(name.getName())) { throw BadRequestException.create("quality_profiles.profile_name_cant_be_blank"); } @@ -93,6 +99,7 @@ public class QProfileFactoryImpl implements QProfileFactory { .setOrganizationUuid(organization.getUuid()) .setLanguage(name.getLanguage()) .setIsBuiltIn(isBuiltIn) + .setParentKee(parentKey) .setRulesUpdatedAtAsDate(now); db.qualityProfileDao().insert(dbSession, dto); if (isDefault) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java index a74e2b8574c..541c00bc3dd 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java @@ -19,7 +19,6 @@ */ package org.sonar.server.qualityprofile; -import com.google.common.collect.Lists; import java.io.Reader; import java.io.Writer; import java.util.ArrayList; @@ -99,7 +98,7 @@ public class QProfileParser { } public ImportedQProfile readXml(Reader reader) { - List rules = Lists.newArrayList(); + List rules = new ArrayList<>(); String profileName = null; String profileLang = null; try { diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java index 942de489af8..58bd3b1d697 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import javax.annotation.Nullable; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -42,6 +43,7 @@ import org.sonar.db.qualityprofile.ActiveRuleDto; import org.sonar.db.qualityprofile.ActiveRuleParamDto; import org.sonar.db.qualityprofile.QProfileDto; import org.sonar.db.qualityprofile.QualityProfileTesting; +import org.sonar.db.qualityprofile.RulesProfileDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleMetadataDto; import org.sonar.db.rule.RuleParamDto; @@ -54,6 +56,7 @@ import static org.junit.rules.ExpectedException.none; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class QProfileBackuperImplTest { @@ -80,7 +83,7 @@ public class QProfileBackuperImplTest { @Test public void backup_generates_xml_file() { RuleDefinitionDto rule = createRule(); - QProfileDto profile = createProfile(rule); + QProfileDto profile = createProfile(rule.getLanguage()); ActiveRuleDto activeRule = activate(profile, rule); StringWriter writer = new StringWriter(); @@ -105,7 +108,7 @@ public class QProfileBackuperImplTest { public void backup_rules_having_parameters() { RuleDefinitionDto rule = createRule(); RuleParamDto param = db.rules().insertRuleParam(rule); - QProfileDto profile = createProfile(rule); + QProfileDto profile = createProfile(rule.getLanguage()); ActiveRuleDto activeRule = activate(profile, rule, param); StringWriter writer = new StringWriter(); @@ -127,7 +130,7 @@ public class QProfileBackuperImplTest { @Test public void backup_empty_profile() { RuleDefinitionDto rule = createRule(); - QProfileDto profile = createProfile(rule); + QProfileDto profile = createProfile(rule.getLanguage()); StringWriter writer = new StringWriter(); underTest.backup(db.getSession(), profile, writer); @@ -149,7 +152,7 @@ public class QProfileBackuperImplTest { .setStatus(RuleStatus.READY) .setTemplateId(templateRule.getId())); RuleParamDto param = db.rules().insertRuleParam(rule); - QProfileDto profile = createProfile(rule); + QProfileDto profile = createProfile(rule.getLanguage()); ActiveRuleDto activeRule = activate(profile, rule, param); StringWriter writer = new StringWriter(); @@ -296,6 +299,21 @@ public class QProfileBackuperImplTest { assertThat(activation.getParameter("bar")).isEqualTo("baz"); } + @Test + public void copy_profile() { + RuleDefinitionDto rule = createRule(); + RuleParamDto param = db.rules().insertRuleParam(rule); + QProfileDto from = createProfile(rule.getLanguage()); + ActiveRuleDto activeRule = activate(from, rule, param); + + QProfileDto to = createProfile(rule.getLanguage()); + QProfileRestoreSummary summary = underTest.copy(db.getSession(), from, to); + + assertThat(reset.calledActivations).extracting(RuleActivation::getRuleId).containsOnly(activeRule.getRuleId()); + assertThat(reset.calledActivations.get(0).getParameter(param.getName())).isEqualTo("20"); + assertThat(reset.calledProfile).isEqualTo(to); + } + @Test public void fail_to_restore_if_bad_xml_format() { OrganizationDto organization = db.organizations().insert(); @@ -374,8 +392,8 @@ public class QProfileBackuperImplTest { return db.rules().insertOrUpdateMetadata(metadataDto); } - private QProfileDto createProfile(RuleDefinitionDto rule) { - return db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(rule.getLanguage())); + private QProfileDto createProfile(String language) { + return db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(language)); } private ActiveRuleDto activate(QProfileDto profile, RuleDefinitionDto rule) { @@ -417,6 +435,10 @@ public class QProfileBackuperImplTest { throw new UnsupportedOperationException(); } + @Override public QProfileDto createCustom(DbSession dbSession, OrganizationDto organization, QProfileName name, @Nullable String parentKey) { + throw new UnsupportedOperationException(); + } + @Override public void delete(DbSession dbSession, Collection profiles) { throw new UnsupportedOperationException(); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileCopierTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileCopierTest.java index a084f72f5b6..c295b125452 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileCopierTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileCopierTest.java @@ -39,6 +39,11 @@ import org.sonar.db.qualityprofile.QualityProfileTesting; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; public class QProfileCopierTest { @@ -53,8 +58,8 @@ public class QProfileCopierTest { public JUnitTempFolder temp = new JUnitTempFolder(); private DummyProfileFactory profileFactory = new DummyProfileFactory(); - private DummyBackuper backuper = new DummyBackuper(); - private QProfileCopier underTest = new QProfileCopier(db.getDbClient(), profileFactory, backuper, temp); + private QProfileBackuper backuper = mock(QProfileBackuper.class); + private QProfileCopier underTest = new QProfileCopier(db.getDbClient(), profileFactory, backuper); @Test public void create_target_profile_and_copy_rules() { @@ -66,9 +71,8 @@ public class QProfileCopierTest { assertThat(target.getLanguage()).isEqualTo(source.getLanguage()); assertThat(target.getName()).isEqualTo("foo"); assertThat(target.getParentKee()).isNull(); - assertThat(backuper.backuped).isSameAs(source); - assertThat(backuper.restored.getName()).isEqualTo("foo"); - assertThat(backuper.restoredBackup).isEqualTo(BACKUP); + + verify(backuper).copy(db.getSession(), source, target); } @Test @@ -82,6 +86,8 @@ public class QProfileCopierTest { assertThat(target.getLanguage()).isEqualTo(source.getLanguage()); assertThat(target.getName()).isEqualTo("foo"); assertThat(target.getParentKee()).isEqualTo(parent.getKee()); + + verify(backuper).copy(db.getSession(), source, target); } @Test @@ -94,8 +100,7 @@ public class QProfileCopierTest { fail(); } catch (IllegalArgumentException e) { assertThat(e).hasMessage("Source and target profiles are equal: " + source.getName()); - assertThat(backuper.backuped).isNull(); - assertThat(backuper.restored).isNull(); + verifyZeroInteractions(backuper); } } @@ -110,9 +115,8 @@ public class QProfileCopierTest { assertThat(profileFactory.createdProfile).isNull(); assertThat(target.getLanguage()).isEqualTo(profile2.getLanguage()); assertThat(target.getName()).isEqualTo(profile2.getName()); - assertThat(backuper.backuped).isSameAs(profile1); - assertThat(backuper.restored.getName()).isEqualTo(profile2.getName()); - assertThat(backuper.restoredBackup).isEqualTo(BACKUP); + + verify(backuper).copy(eq(db.getSession()), eq(profile1), argThat(a -> a.getKee().equals(profile2.getKee()))); } private static class DummyProfileFactory implements QProfileFactory { @@ -125,9 +129,14 @@ public class QProfileCopierTest { @Override public QProfileDto checkAndCreateCustom(DbSession dbSession, OrganizationDto organization, QProfileName key) { + throw new UnsupportedOperationException(); + } + + @Override public QProfileDto createCustom(DbSession dbSession, OrganizationDto organization, QProfileName key, @Nullable String parentKey) { createdProfile = QualityProfileTesting.newQualityProfileDto() .setOrganizationUuid(organization.getUuid()) .setLanguage(key.getLanguage()) + .setParentKee(parentKey) .setName(key.getName()); return createdProfile; } @@ -137,36 +146,4 @@ public class QProfileCopierTest { throw new UnsupportedOperationException(); } } - - private static class DummyBackuper implements QProfileBackuper { - private QProfileDto backuped; - private String restoredBackup; - private QProfileDto restored; - - @Override - public void backup(DbSession dbSession, QProfileDto profile, Writer backupWriter) { - this.backuped = profile; - try { - backupWriter.write(BACKUP); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - @Override - public QProfileRestoreSummary restore(DbSession dbSession, Reader backup, OrganizationDto organization, @Nullable String overriddenProfileName) { - throw new UnsupportedOperationException(); - } - - @Override - public QProfileRestoreSummary restore(DbSession dbSession, Reader backup, QProfileDto profile) { - try { - this.restoredBackup = IOUtils.toString(backup); - this.restored = profile; - return null; - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - } } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java index 8551cdcb44f..47eab237d23 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java @@ -71,7 +71,7 @@ public class CopyActionTest { private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); private QProfileFactory profileFactory = new QProfileFactoryImpl(db.getDbClient(), new SequenceUuidFactory(), System2.INSTANCE, activeRuleIndexer); private TestBackuper backuper = new TestBackuper(); - private QProfileCopier profileCopier = new QProfileCopier(db.getDbClient(), profileFactory, backuper, tempDir); + private QProfileCopier profileCopier = new QProfileCopier(db.getDbClient(), profileFactory, backuper); private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); private Languages languages = LanguageTesting.newLanguages(A_LANGUAGE); private QProfileWsSupport wsSupport = new QProfileWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider); @@ -138,12 +138,12 @@ public class CopyActionTest { assertThat(loadedProfile.getKee()).isEqualTo(generatedUuid); assertThat(loadedProfile.getParentKee()).isNull(); - assertThat(backuper.backupedProfile.getKee()).isEqualTo(sourceProfile.getKee()); - assertThat(backuper.restoredProfile.getOrganizationUuid()).isEqualTo(sourceProfile.getOrganizationUuid()); - assertThat(backuper.restoredProfile.getLanguage()).isEqualTo(sourceProfile.getLanguage()); - assertThat(backuper.restoredProfile.getName()).isEqualTo("target-name"); - assertThat(backuper.restoredProfile.getKee()).isEqualTo(generatedUuid); - assertThat(backuper.restoredProfile.getParentKee()).isNull(); + assertThat(backuper.copiedProfile.getKee()).isEqualTo(sourceProfile.getKee()); + assertThat(backuper.toProfile.getOrganizationUuid()).isEqualTo(sourceProfile.getOrganizationUuid()); + assertThat(backuper.toProfile.getLanguage()).isEqualTo(sourceProfile.getLanguage()); + assertThat(backuper.toProfile.getName()).isEqualTo("target-name"); + assertThat(backuper.toProfile.getKee()).isEqualTo(generatedUuid); + assertThat(backuper.toProfile.getParentKee()).isNull(); } @Test @@ -170,8 +170,8 @@ public class CopyActionTest { QProfileDto loadedProfile = db.getDbClient().qualityProfileDao().selectByUuid(db.getSession(), targetProfile.getKee()); assertThat(loadedProfile).isNotNull(); - assertThat(backuper.backupedProfile.getKee()).isEqualTo(sourceProfile.getKee()); - assertThat(backuper.restoredProfile.getKee()).isEqualTo(targetProfile.getKee()); + assertThat(backuper.copiedProfile.getKee()).isEqualTo(sourceProfile.getKee()); + assertThat(backuper.toProfile.getKee()).isEqualTo(targetProfile.getKee()); } @Test @@ -201,12 +201,12 @@ public class CopyActionTest { assertThat(loadedProfile.getKee()).isEqualTo(generatedUuid); assertThat(loadedProfile.getParentKee()).isEqualTo(parentProfile.getKee()); - assertThat(backuper.backupedProfile.getKee()).isEqualTo(sourceProfile.getKee()); - assertThat(backuper.restoredProfile.getOrganizationUuid()).isEqualTo(sourceProfile.getOrganizationUuid()); - assertThat(backuper.restoredProfile.getLanguage()).isEqualTo(sourceProfile.getLanguage()); - assertThat(backuper.restoredProfile.getName()).isEqualTo("target-name"); - assertThat(backuper.restoredProfile.getKee()).isEqualTo(generatedUuid); - assertThat(backuper.restoredProfile.getParentKee()).isEqualTo(parentProfile.getKee()); + assertThat(backuper.copiedProfile.getKee()).isEqualTo(sourceProfile.getKee()); + assertThat(backuper.toProfile.getOrganizationUuid()).isEqualTo(sourceProfile.getOrganizationUuid()); + assertThat(backuper.toProfile.getLanguage()).isEqualTo(sourceProfile.getLanguage()); + assertThat(backuper.toProfile.getName()).isEqualTo("target-name"); + assertThat(backuper.toProfile.getKee()).isEqualTo(generatedUuid); + assertThat(backuper.toProfile.getParentKee()).isEqualTo(parentProfile.getKee()); } @Test @@ -289,15 +289,12 @@ public class CopyActionTest { private static class TestBackuper implements QProfileBackuper { - private QProfileDto backupedProfile; - private QProfileDto restoredProfile; + private QProfileDto copiedProfile; + private QProfileDto toProfile; @Override public void backup(DbSession dbSession, QProfileDto profile, Writer backupWriter) { - if (this.backupedProfile != null) { - throw new IllegalStateException("Already backup-ed/backed-up"); - } - this.backupedProfile = profile; + throw new UnsupportedOperationException(); } @Override @@ -307,11 +304,13 @@ public class CopyActionTest { @Override public QProfileRestoreSummary restore(DbSession dbSession, Reader backup, QProfileDto profile) { - if (this.restoredProfile != null) { - throw new IllegalStateException("Already restored"); - } - this.restoredProfile = profile; - return new QProfileRestoreSummary(profile, new BulkChangeResult()); + throw new UnsupportedOperationException(); + } + + @Override public QProfileRestoreSummary copy(DbSession dbSession, QProfileDto from, QProfileDto to) { + this.copiedProfile = from; + this.toProfile = to; + return null; } } } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java index ecf3bd8676a..7b7fdb5db59 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java @@ -367,5 +367,9 @@ public class ExportActionTest { public QProfileRestoreSummary restore(DbSession dbSession, Reader backup, QProfileDto profile) { throw new UnsupportedOperationException(); } + + @Override public QProfileRestoreSummary copy(DbSession dbSession, QProfileDto from, QProfileDto to) { + throw new UnsupportedOperationException(); + } } } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java index 053ec219726..b4c920a006a 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java @@ -233,5 +233,9 @@ public class RestoreActionTest { public QProfileRestoreSummary restore(DbSession dbSession, Reader backup, QProfileDto profile) { throw new UnsupportedOperationException(); } + + @Override public QProfileRestoreSummary copy(DbSession dbSession, QProfileDto from, QProfileDto to) { + throw new UnsupportedOperationException(); + } } } -- 2.39.5