]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19407 Fix ComponentUuidFactory to load uuid for portfolio from `portfolio`...
authorBenjamin Campomenosi <benjamin.campomenosi@sonarsource.com>
Tue, 30 May 2023 10:07:04 +0000 (12:07 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 1 Jun 2023 20:02:59 +0000 (20:02 +0000)
server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryImplIT.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/ComponentUuidFactoryImpl.java
server/sonar-db-dao/src/it/java/org/sonar/db/portfolio/PortfolioDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/KeyWithUuidDto.java
server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/portfolio/PortfolioMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/portfolio/PortfolioMapper.xml
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentTesting.java

index 6b3ee0a9d707de433dd8370a981cd2fd6c396437..6da6104b03880a48e10b87eec033b94977b75f0e 100644 (file)
@@ -26,6 +26,8 @@ import org.sonar.ce.task.projectanalysis.analysis.Branch;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.BranchType;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.portfolio.PortfolioDto;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
@@ -84,4 +86,28 @@ public class ComponentUuidFactoryImplIT {
     // uuid is kept in memory for further calls with same key
     assertThat(underTest.getOrCreateForKey("foo")).isEqualTo(generatedKey);
   }
+
+  @Test
+  public void getOrCreateForKey_whenExistingComponentsInDbForPortfolioAndSubPortfolio_shouldLoadUuidsFromComponentTable() {
+    ComponentDto portfolioDto = db.components().insertPublicPortfolio("pft1", p -> p.setKey("root_portfolio"));
+    ComponentDto subView = db.components().insertSubView(portfolioDto, s -> s.setKey("sub_portfolio").setUuid("subPtf1"));
+    ComponentUuidFactory underTest = new ComponentUuidFactoryImpl(db.getDbClient(), db.getSession(), portfolioDto.getKey(), mockedBranch);
+
+    assertThat(underTest.getOrCreateForKey("root_portfolio")).isEqualTo(portfolioDto.uuid());
+    assertThat(underTest.getOrCreateForKey("sub_portfolio")).isEqualTo(subView.uuid());
+  }
+
+  @Test
+  public void getOrCreateForKey_whenNoExistingComponentsInDbForPortfolioAndSubPortfolio_shouldLoadUuidFromPortfolioTable() {
+    PortfolioDto portfolioDto = ComponentTesting.newPortfolioDto("uuid_ptf1", "ptf1", "Portfolio1", null);
+    db.getDbClient().portfolioDao().insert(db.getSession(), portfolioDto);
+    PortfolioDto subPortfolio = ComponentTesting.newPortfolioDto("subPtf1", "sub_ptf_1", "portfolio", portfolioDto);
+    db.getDbClient().portfolioDao().insert(db.getSession(), subPortfolio);
+
+    ComponentUuidFactory underTest = new ComponentUuidFactoryImpl(db.getDbClient(), db.getSession(), portfolioDto.getKey());
+
+    assertThat(underTest.getOrCreateForKey("ptf1")).isEqualTo(portfolioDto.getUuid());
+    assertThat(underTest.getOrCreateForKey("sub_ptf_1")).isEqualTo(subPortfolio.getUuid());
+  }
+
 }
index 9d3e6352744b289dfa584d2c159b6ca3df582cfb..c2bef0e1f0f2c632304f3090c92386c462420314 100644 (file)
@@ -32,9 +32,19 @@ import org.sonar.db.component.KeyWithUuidDto;
 public class ComponentUuidFactoryImpl implements ComponentUuidFactory {
   private final Map<String, String> uuidsByKey = new HashMap<>();
 
+  /** For the sake of consistency it is important that sub-portfolios have the same uuid as the associated component.
+   * As sub-portfolio have no component associated with their creation, it is necessary to look search for their uuid.
+   * see SONAR-19407 for more info
+   *
+   * @param dbClient
+   * @param dbSession
+   * @param rootKey
+   */
   public ComponentUuidFactoryImpl(DbClient dbClient, DbSession dbSession, String rootKey) {
-    List<KeyWithUuidDto> keys = dbClient.componentDao().selectUuidsByKeyFromProjectKey(dbSession, rootKey);
-    keys.forEach(dto -> uuidsByKey.put(dto.key(), dto.uuid()));
+    List<KeyWithUuidDto> projectKeys = dbClient.componentDao().selectUuidsByKeyFromProjectKey(dbSession, rootKey);
+    List<KeyWithUuidDto> portFolioKeys = dbClient.portfolioDao().selectUuidsByKey(dbSession, rootKey);
+    projectKeys.forEach(dto -> uuidsByKey.put(dto.key(), dto.uuid()));
+    portFolioKeys.forEach(dto -> uuidsByKey.putIfAbsent(dto.key(), dto.uuid()));
   }
 
   public ComponentUuidFactoryImpl(DbClient dbClient, DbSession dbSession, String rootKey, Branch branch) {
index 70865740051eb51b87410b8b2f9cba86f849b58f..c46c401c87f8573d1bde0b1f4a53630c6b56ec8a 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.db.portfolio;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.Set;
 import org.junit.Rule;
 import org.junit.Test;
@@ -29,6 +31,8 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.audit.AuditPersister;
 import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.KeyWithUuidDto;
 import org.sonar.db.component.ProjectData;
 import org.sonar.db.project.ApplicationProjectDto;
 import org.sonar.db.project.ProjectDto;
@@ -138,6 +142,27 @@ public class PortfolioDaoIT {
         tuple("NAME_name2", "KEY_name2", "name2", "DESCRIPTION_name2", "name2", null, "NONE", null));
   }
 
+  @Test
+  public void selectUuidsByKeyFromPortfolioKey_returns_all_uuidByKeyForPortfoliosLinkedToRootKey() {
+    PortfolioDto portfolio1 = ComponentTesting.newPortfolioDto("uuid1", "ptf1", "Portfolio 1", null);
+    PortfolioDto subPortfolio1 = ComponentTesting.newPortfolioDto("sub_uuid11", "sub_ptf1", "SubPortfolio 1", portfolio1);
+    PortfolioDto subSubPortfolio1 = ComponentTesting.newPortfolioDto("sub_uuid12", "sub_sub_ptf1", "SubSubPortfolio 1", portfolio1);
+    PortfolioDto portfolio2 = ComponentTesting.newPortfolioDto("uuid2", "ptf2", "Portfolio 2", null);
+    PortfolioDto subPortfolio2 = ComponentTesting.newPortfolioDto("sub_uuid21", "sub_ptd2", "SubPortfolio 2", portfolio2);
+    Arrays.asList(portfolio1, subPortfolio1, subSubPortfolio1, portfolio2, subPortfolio2)
+      .forEach(portfolio -> portfolioDao.insert(db.getSession(), portfolio));
+
+    List<KeyWithUuidDto> keyWithUuidDtos = portfolioDao.selectUuidsByKey(db.getSession(), portfolio1.getKey());
+
+    KeyWithUuidDto[] expectedKey = {
+      new KeyWithUuidDto(portfolio1.getKee(), portfolio1.getUuid()),
+      new KeyWithUuidDto(subPortfolio1.getKee(), subPortfolio1.getUuid()),
+      new KeyWithUuidDto(subSubPortfolio1.getKee(), subSubPortfolio1.getUuid())
+    };
+
+    assertThat(keyWithUuidDtos).containsExactlyInAnyOrder(expectedKey);
+  }
+
   @Test
   public void insert_fails_if_root_is_inconsistent_with_parent() {
     PortfolioDto portfolio = new PortfolioDto()
index f1fb7fa36a95d30e9b95870b4ad360ca42ce9776..97cd6cb128d37ab3a929749106f72815fbf37c10 100644 (file)
@@ -22,21 +22,9 @@ package org.sonar.db.component;
 import javax.annotation.concurrent.Immutable;
 
 @Immutable
-public class KeyWithUuidDto {
-
-  private final String kee;
-  private final String uuid;
-
-  public KeyWithUuidDto(String kee, String uuid) {
-    this.kee = kee;
-    this.uuid = uuid;
-  }
+public record KeyWithUuidDto(String kee, String uuid) {
 
   public String key() {
     return kee;
   }
-
-  public String uuid() {
-    return uuid;
-  }
 }
index 500701b1388b2cf53774bbacf01b5eaef74f6eb9..d2a4b97e99d98a79704016ba0c22fc26d1b435ba 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
 import org.sonar.db.audit.AuditPersister;
 import org.sonar.db.audit.model.ComponentNewValue;
+import org.sonar.db.component.KeyWithUuidDto;
 import org.sonar.db.project.ApplicationProjectDto;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -90,6 +91,10 @@ public class PortfolioDao implements Dao {
     return mapper(dbSession).selectByUuids(uuids);
   }
 
+  public List<KeyWithUuidDto> selectUuidsByKey(DbSession dbSession, String rootKey) {
+    return mapper(dbSession).selectUuidsByKey(rootKey);
+  }
+
   /*
    * Modify portfolios
    */
@@ -223,8 +228,8 @@ public class PortfolioDao implements Dao {
   }
 
   public PortfolioProjectDto selectPortfolioProjectOrFail(DbSession dbSession, String portfolioUuid, String projectUuid) {
-    return Optional.ofNullable(mapper(dbSession).selectPortfolioProject(portfolioUuid, projectUuid)).orElseThrow(() ->
-      new IllegalArgumentException(format("Project '%s' not selected in portfolio '%s'", projectUuid, portfolioUuid)));
+    return Optional.ofNullable(mapper(dbSession).selectPortfolioProject(portfolioUuid, projectUuid))
+      .orElseThrow(() -> new IllegalArgumentException(format("Project '%s' not selected in portfolio '%s'", projectUuid, portfolioUuid)));
   }
 
   public String addProject(DbSession dbSession, String portfolioUuid, String projectUuid) {
index cc44a51adbba058d6482eaf49659413109184178..93b7db68f5af08b6a839abe8a7e9b6a5bb4f2e05 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.apache.ibatis.annotations.Param;
+import org.sonar.db.component.KeyWithUuidDto;
 import org.sonar.db.project.ApplicationProjectDto;
 
 public interface PortfolioMapper {
@@ -111,4 +112,6 @@ public interface PortfolioMapper {
   List<ReferenceDto> selectAllReferencesToApplicationsInHierarchy(String rootUuid);
 
   List<PortfolioDto> selectRootOfReferencersToAppBranch(@Param("appUuid") String appUuid, @Param("appBranchKey") String appBranchKey);
+
+  List<KeyWithUuidDto> selectUuidsByKey(@Param("rootKey") String rootKey);
 }
index 5435920ae118911641e19e85ccb8e8abb077b6a6..136b85e5ba507cf836b1787f4e5a9b3cba7ec965 100644 (file)
         when b_qualifier = 'DIR' THEN 'DIR'
         when b_qualifier = 'FIL' THEN 'FIL'
         when b_qualifier = 'UTS' THEN 'FIL'
-        <!-- For the few cases where qualifier is not enough to guess the scope (like TRK), just assume the scope remains unchanged -->
-        else scope
+    <!-- For the few cases where qualifier is not enough to guess the scope (like TRK), just assume the scope remains unchanged -->
+    else scope
       end
     ),
     b_changed = ${_false},
index ea2c9dcb7356948e6b644ec44b621b98730bb751..0264a211032d1ab4dfbae3c596d0ead540878683 100644 (file)
     AND target.kee=#{referenceKey,jdbcType=VARCHAR}
   </select>
 
+   <select id="selectUuidsByKey" parameterType="string" resultType="KeyWithUuid">
+    SELECT ptf.kee, ptf.uuid
+    FROM portfolios ptf
+    INNER JOIN
+    portfolios root ON root.uuid = ptf.root_uuid
+    WHERE root.kee = #{rootKey,jdbcType=VARCHAR}
+   </select>
+
    <insert id="insert" parameterType="Portfolio">
     INSERT INTO portfolios (
       kee,
index 2b607e0c894e948352c758256f793327ac709c67..f1a34854528cc25e5cbb4d23963fd16880164387 100644 (file)
@@ -24,6 +24,7 @@ import javax.annotation.Nullable;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
 import org.sonar.core.util.Uuids;
+import org.sonar.db.portfolio.PortfolioDto;
 import org.sonar.db.project.ProjectDto;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -32,6 +33,7 @@ import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME;
 import static org.sonar.db.component.ComponentDto.UUID_PATH_OF_ROOT;
 import static org.sonar.db.component.ComponentDto.formatUuidPathFromParent;
 import static org.sonar.db.component.ComponentDto.generateBranchKey;
+import static org.sonar.db.portfolio.PortfolioDto.SelectionMode.NONE;
 
 public class ComponentTesting {
 
@@ -156,6 +158,19 @@ public class ComponentTesting {
       .setPrivate(false);
   }
 
+  public static PortfolioDto newPortfolioDto(String uuid, String key, String name, @Nullable PortfolioDto parent) {
+    return new PortfolioDto()
+      .setUuid(uuid)
+      .setKey(key)
+      .setParentUuid(parent == null ? null : parent.getUuid())
+      .setRootUuid(parent == null ? uuid : parent.getRootUuid())
+      .setSelectionMode(NONE.name())
+      .setCreatedAt(1L)
+      .setUpdatedAt(1L)
+      .setPrivate(false)
+      .setName(name);
+  }
+
   public static ComponentDto newApplication() {
     return newPortfolio(Uuids.createFast()).setQualifier(Qualifiers.APP);
   }