]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10408 Web service api/qualityprofiles/copy is too slow
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Wed, 16 Oct 2019 20:45:30 +0000 (15:45 -0500)
committerSonarTech <sonartech@sonarsource.com>
Mon, 21 Oct 2019 18:21:09 +0000 (20:21 +0200)
13 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileExportDao.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuper.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileBackuperImpl.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileCopier.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileParser.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/QProfileCopierTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualityprofile/ws/RestoreActionTest.java

index 34a87233d2cb4ead6186e0e158d759cf94a2d8d3..16816e4152c4e8b71bfc594b889abc0e25ca1c5a 100644 (file)
@@ -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<ExportRuleDto> selectRulesByProfile(DbSession dbSession, QProfileDto profile) {
     List<ExportRuleDto> exportRules = mapper(dbSession).selectByProfileUuid(profile.getKee());
 
-    Set<Integer> activeRuleIds = exportRules.stream().map(ExportRuleDto::getActiveRuleId).collect(Collectors.toSet());
+    Map<Integer, ExportRuleDto> exportRulesById = exportRules.stream().collect(Collectors.toMap(ExportRuleDto::getActiveRuleId, x -> x));
+    Map<Integer, List<ExportRuleParamDto>> rulesParams = selectParamsByActiveRuleIds(dbSession, exportRulesById.keySet());
 
-    Map<Integer, List<ExportRuleParamDto>> activeRulesParam = selectParamsByActiveRuleIds(dbSession, activeRuleIds);
-
-    exportRules.forEach(exportRuleDto ->
-      exportRuleDto.setParams(activeRulesParam.get(exportRuleDto.getActiveRuleId()))
-    );
+    rulesParams.forEach((id, rules) -> exportRulesById.get(id).setParams(rules));
     return exportRules;
   }
 
index 93658d2aa270480159d373fd0ef00597a79530f3..323a4aa72ecfff9d4d8744b56fcc4c8cdeecc21a 100644 (file)
@@ -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");
index dd418601955d48faa21f89b23f54fd3315385b69..23be874d95a230f21fde1814085ad2b9cc78c4aa 100644 (file)
@@ -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);
 }
index ec95957feb02f996784166da3f72c06c1bae1050..0f4ac2cc8b05e29baffbcb03efffe14583b5b6fd 100644 (file)
@@ -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<ExportRuleDto> 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<ExportRuleDto> exportRules, String profileName, String profileLang) {
+    List<ImportedRule> 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<QProfileName, QProfileDto> profileLoader) {
     ImportedQProfile qProfile = qProfileParser.readXml(backup);
+    return restore(dbSession, qProfile, profileLoader);
+  }
 
+  private QProfileRestoreSummary restore(DbSession dbSession, ImportedQProfile qProfile, Function<QProfileName, QProfileDto> 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();
     }
   }
index 4b65da3c12c77233807b9b6f7b7d4639de309d48..d364768b3038d0ab0c5284a6f6aeec3d9a44b519 100644 (file)
  */
 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));
     }
   }
 }
index cfecdfdfa28594c9263e621dedc3ccbb055a0913..90e91a3750cbdc8382e44d315a599da0024a2277 100644 (file)
@@ -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
index 580f13aa45eebf6ce668fb6cb57959152221c7b4..3456fbe62607ccb2247def1fc5ee185d58e7bf2a 100644 (file)
@@ -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) {
index a74e2b8574c2d32c648c881e9a5147a5a7659ee2..541c00bc3dddcd6a9d4db52e59b60f9a3bf60425 100644 (file)
@@ -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<ImportedRule> rules = Lists.newArrayList();
+    List<ImportedRule> rules = new ArrayList<>();
     String profileName = null;
     String profileLang = null;
     try {
index 942de489af8ff3a0759c03f2599428aaee4a4329..58bd3b1d697b36aa2bb574e6c2b1437f33b27e22 100644 (file)
@@ -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<QProfileDto> profiles) {
       throw new UnsupportedOperationException();
index a084f72f5b60f126edaf31809d2a418d7518d043..c295b125452afb49ce4070bf29eabbf7e6901488 100644 (file)
@@ -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);
-      }
-    }
-  }
 }
index 8551cdcb44f8db04749087cee83112391260b55d..47eab237d23fc998d0674d03c56264d893997798 100644 (file)
@@ -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;
     }
   }
 }
index ecf3bd8676aa6173d9cec962fd343d93758be37f..7b7fdb5db591ed2ba7fc843cba6285a1fc4312ea 100644 (file)
@@ -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();
+    }
   }
 }
index 053ec2197262dd5dc209ba57a67d5e6ab6f4c59b..b4c920a006a0ee166fb7bebbc802a6538a3dff45 100644 (file)
@@ -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();
+    }
   }
 }