]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22649 Create DB populator for creating generated data
authorAlain Kermis <alain.kermis@sonarsource.com>
Wed, 11 Sep 2024 15:10:25 +0000 (17:10 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 19 Sep 2024 20:03:00 +0000 (20:03 +0000)
26 files changed:
server/sonar-db-dao/build.gradle
server/sonar-db-dao/src/it/java/org/sonar/db/MyBatisIT.java
server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeTaskInputDaoIT.java
server/sonar-db-dao/src/it/java/org/sonar/db/notification/NotificationQueueDaoIT.java
server/sonar-db-dao/src/it/java/org/sonar/db/plugin/PluginDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfBuilder.java
server/sonar-db-dao/src/test/java/org/sonar/db/createdb/PopulateDb.java [new file with mode: 0644]
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ProjectLinkDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/event/EventDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/favorite/FavoriteDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/notification/NotificationDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/plugin/PluginDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/InternalComponentPropertyDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/PropertyDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/source/FileSourceTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserTesting.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDeliveryDbTester.java

index 527bac05be99a78ed13e94095131d1be3885a0a1..85c4221c4d20fa0b8e87492a27e778d7d68d94fb 100644 (file)
@@ -73,6 +73,11 @@ task createDB(type:JavaExec) {
     }
 }
 
+task populateDB(type: JavaExec) {
+  mainClass = 'org.sonar.db.createdb.PopulateDb'
+  classpath = sourceSets.test.runtimeClasspath
+}
+
 task testJar(type: Jar) {
   archiveClassifier = 'tests'
   from sourceSets.test.output
index c79693bec345c41173fd26d47b17f6d8df1a9ed5..9610a36c11b8bde4a12dbb015584a6ac13726453 100644 (file)
 package org.sonar.db;
 
 import org.apache.ibatis.session.Configuration;
-import org.hamcrest.core.Is;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.sonar.db.rule.RuleMapper;
 
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
 
 class MyBatisIT {
   private static SQDatabase database;
@@ -50,9 +48,10 @@ class MyBatisIT {
     underTest.start();
 
     Configuration conf = underTest.getSessionFactory().getConfiguration();
-    assertThat(conf.isUseGeneratedKeys(), Is.is(true));
-    assertThat(conf.hasMapper(RuleMapper.class), Is.is(true));
-    assertThat(conf.isLazyLoadingEnabled(), Is.is(false));
+
+    assertThat(conf.isUseGeneratedKeys()).isFalse();
+    assertThat(conf.hasMapper(RuleMapper.class)).isTrue();
+    assertThat(conf.isLazyLoadingEnabled()).isFalse();
   }
 
   @Test
@@ -60,8 +59,8 @@ class MyBatisIT {
     underTest.start();
 
     try (DbSession session = underTest.openSession(false)) {
-      assertThat(session.getConnection(), notNullValue());
-      assertThat(session.getMapper(RuleMapper.class), notNullValue());
+      assertThat(session.getConnection()).isNotNull();
+      assertThat(session.getMapper(RuleMapper.class)).isNotNull();
     }
   }
 }
index 891a945d0548f9fcb180883f23659ff31c56b014..9fa3d59f68b874cbff2658b19308cb41ab87e935 100644 (file)
@@ -76,7 +76,6 @@ class CeTaskInputDaoIT {
   @Test
   void selectData_returns_absent_if_uuid_exists_but_data_is_null() {
     insertData(A_UUID);
-    dbTester.commit();
 
     Optional<DbInputStream> result = underTest.selectData(dbTester.getSession(), A_UUID);
     assertThat(result).isNotPresent();
@@ -105,6 +104,5 @@ class CeTaskInputDaoIT {
 
   private void insertData(String uuid) {
     dbTester.executeInsert(TABLE_NAME, "task_uuid", uuid, "created_at", NOW, "updated_at", NOW);
-    dbTester.commit();
   }
 }
index e810d0f10a513cf91da8be63df7e5e3e76915283..2bcb7f4560ce3985e6b80b13e026120d5cf08ae1 100644 (file)
@@ -75,7 +75,6 @@ class NotificationQueueDaoIT {
       .mapToObj(i -> toNotificationQueueDto(new Notification("foo_" + i)))
       .collect(toList());
     dao.insert(notifs);
-    db.commit();
 
     List<String> uuids = selectAllUuid();
 
@@ -100,7 +99,6 @@ class NotificationQueueDaoIT {
       .mapToObj(i -> toNotificationQueueDto(new Notification("foo_" + i)))
       .collect(toList());
     dao.insert(notifs);
-    db.commit();
 
     assertThat(dao.selectOldest(3))
       .extracting(NotificationQueueDto::getUuid)
index f6b8496db466d3a9627844cb7a5ab02f3dbe7471..ed48e64d5549267ec3b2b4907ef4660472411aa0 100644 (file)
@@ -111,6 +111,5 @@ class PluginDaoIT {
       "removed", removed,
       "created_at", createdAt,
       "updated_at", updatedAt);
-    db.commit();
   }
 }
index 0bde18cd641214edbb4d11f928a2ec179be396cf..60401c9a4ff157b836ca83ab74ece7527f5364fb 100644 (file)
@@ -39,7 +39,7 @@ class MyBatisConfBuilder {
   MyBatisConfBuilder(Database database) {
     this.conf = new Configuration();
     this.conf.setEnvironment(new Environment("production", createTransactionFactory(), database.getDataSource()));
-    this.conf.setUseGeneratedKeys(true);
+    this.conf.setUseGeneratedKeys(false);
     this.conf.setLazyLoadingEnabled(false);
     this.conf.setJdbcTypeForNull(JdbcType.NULL);
     Dialect dialect = database.getDialect();
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/createdb/PopulateDb.java b/server/sonar-db-dao/src/test/java/org/sonar/db/createdb/PopulateDb.java
new file mode 100644 (file)
index 0000000..a43dc4a
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.db.createdb;
+
+import com.google.common.collect.Streams;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.rules.RuleType;
+import org.sonar.api.utils.System2;
+import org.sonar.core.metric.SoftwareQualitiesMetrics;
+import org.sonar.core.util.UuidFactoryImpl;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.ProjectData;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.component.SnapshotTesting;
+import org.sonar.db.dismissmessage.MessageType;
+import org.sonar.db.issue.IssueDto;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.db.permission.GroupPermissionDto;
+import org.sonar.db.portfolio.PortfolioDto;
+import org.sonar.db.project.ProjectDto;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.TokenType;
+import org.sonar.db.user.UserDto;
+import org.sonar.db.webhook.WebhookDto;
+
+import static org.sonar.db.component.BranchType.BRANCH;
+
+public class PopulateDb {
+
+  private static final Logger LOG = LoggerFactory.getLogger(PopulateDb.class);
+
+  public static final int NB_PROJECT_WISHED = 4;
+  public static final int NB_WORKER = 2;
+  public static final int BRANCH_PER_PROJECT = 7;
+  public static final int FILE_PER_BRANCH = 377;
+  public static final int ISSUE_PER_FILE = 3;
+  public static final int SNAPSHOT_PER_BRANCH = 13;
+  public static final int WEBHOOK_DELIVERIES_PER_COMPONENT = 1;
+  public static final int NB_USER = 100;
+  public static final int NUMBER_OF_PORTFOLIOS = 100;
+  public static final int MAX_PROJECT_PER_PORTFOLIO = 10;
+
+  public static void main(String[] args) throws InterruptedException {
+    LOG.info("Population procedure starting");
+
+    System.setProperty("sonar.jdbc.url", "jdbc:postgresql://localhost:5432/sonarqube");
+    System.setProperty("sonar.jdbc.username", "sonarqube");
+    System.setProperty("sonar.jdbc.password", "sonarqube");
+    System.setProperty("sonar.jdbc.dialect", "postgresql");
+    System.setProperty("sonar.jdbc.maximumPoolSize", "" + (NB_WORKER + 1));
+    final DbTester dbTester = createDbTester();
+
+    LOG.info("Database infrastructure is set up");
+
+    // read base data
+    final Map<String, MetricDto> metricDtosByKey;
+    final List<ProjectDto> allProjects;
+    final List<PortfolioDto> allPortfolios;
+    final Set<RuleDto> enabledRules;
+    final GroupDto adminGroupDto;
+
+    DbSession initSession = dbTester.getSession();
+    metricDtosByKey = dbTester.getDbClient().metricDao().selectAll(initSession).stream().collect(
+      Collectors.toMap(MetricDto::getKey, Function.identity())
+    );
+    allProjects = Collections.synchronizedList(new ArrayList<>(dbTester.getDbClient().projectDao().selectProjects(initSession)));
+    enabledRules = new HashSet<>(dbTester.getDbClient().ruleDao().selectEnabled(dbTester.getSession()));
+    adminGroupDto = dbTester.getDbClient().groupDao().selectByName(dbTester.getSession(), "sonar-administrators")
+      .orElseThrow(() -> new IllegalStateException("group with name \"sonar-administrators\" is expected to exist"));
+    SqContext sqContext = new SqContext(allProjects, enabledRules, metricDtosByKey, adminGroupDto, dbTester);
+    LOG.info("Existing data has been collected");
+
+
+    ExecutorService executorService = Executors.newFixedThreadPool(NB_WORKER);
+    final AtomicInteger nbProjectsGenerated = new AtomicInteger(0);
+    LOG.info("Starting generation of {} projects", NB_PROJECT_WISHED);
+    IntStream.rangeClosed(1, NB_PROJECT_WISHED)
+      .map(i -> i + allProjects.size())
+      .mapToObj(i -> new ProjectStructure("project " + i, BRANCH_PER_PROJECT, FILE_PER_BRANCH, ISSUE_PER_FILE, ISSUE_PER_FILE, SNAPSHOT_PER_BRANCH, WEBHOOK_DELIVERIES_PER_COMPONENT))
+      .forEach(projectStructure -> {
+        executorService.submit(() -> {
+          LOG.info("Worker-{}: Starting generation of project: {}", Thread.currentThread().getName(), projectStructure);
+          try {
+            sqContext.dbTester.getSession(true);
+            allProjects.add(generateProject(
+              sqContext, projectStructure
+            ));
+          } catch (Exception e) {
+            LOG.error("Worker-" + Thread.currentThread().getName() + ": Error while generating project", e);
+            return;
+          }
+          nbProjectsGenerated.incrementAndGet();
+          LOG.info("Worker-{}: Project generation completed: {}", Thread.currentThread().getName(), projectStructure.projectName);
+        });
+      });
+
+    executorService.shutdown();
+    executorService.awaitTermination(100, TimeUnit.DAYS);
+    LOG.info("Ending generation of {}/{} projects", nbProjectsGenerated.get(), NB_PROJECT_WISHED);
+
+    createUsers(sqContext, NB_USER);
+
+    allPortfolios = new ArrayList<>(dbTester.getDbClient().portfolioDao().selectAll(initSession));
+    allPortfolios.addAll(createPortfolios(sqContext, new PortfolioGenerationSettings(allPortfolios.size(), NUMBER_OF_PORTFOLIOS, MAX_PROJECT_PER_PORTFOLIO)));
+
+    // close database connection
+    dbTester.getDbClient().getDatabase().stop();
+  }
+
+  private static List<PortfolioDto> createPortfolios(SqContext sqContext, PortfolioGenerationSettings portfolioGenerationSettings) {
+    List<PortfolioDto> generatedPortfolios = new ArrayList<>();
+    int startIndex = portfolioGenerationSettings.currentPortfoliosSize + 1;
+    int limit = startIndex + portfolioGenerationSettings.numberOfPortolios;
+
+    for (int portfolioIndex = startIndex; portfolioIndex < limit; portfolioIndex++) {
+      PortfolioDto portfolioDto = generatePortfolio(sqContext, "portfolio " + portfolioIndex);
+      generatedPortfolios.add(portfolioDto);
+      for (int projectIndex = 0; projectIndex < Math.min(portfolioGenerationSettings.maxProjectPerPortfolio, sqContext.projects.size()); projectIndex++) {
+        sqContext.dbTester.getDbClient().portfolioDao().addProject(sqContext.dbTester.getSession(), portfolioDto.getUuid(), sqContext.projects.get(projectIndex).getUuid());
+      }
+    }
+
+    return generatedPortfolios;
+  }
+
+  private static PortfolioDto generatePortfolio(SqContext sqContext, String portfolioName) {
+    PortfolioDto portfolioDto = sqContext.dbTester.components().insertPublicPortfolioDto(
+      c -> c.setName(portfolioName),
+      // Selection mode is set to MANUAL as we are picking the portfolio projects manually
+      p -> p.setSelectionMode(PortfolioDto.SelectionMode.MANUAL));
+
+    insertPortfolioAdminRights(sqContext, portfolioDto);
+    return portfolioDto;
+  }
+
+  private static void insertPortfolioAdminRights(SqContext sqContext, PortfolioDto portfolioComponentDto) {
+    GroupPermissionDto dto = new GroupPermissionDto()
+      .setUuid(Uuids.createFast())
+      .setGroupUuid(sqContext.adminGroup.getUuid())
+      .setEntityUuid(portfolioComponentDto.getUuid())
+      .setRole("admin");
+
+    sqContext.dbTester.getDbClient().groupPermissionDao().insert(sqContext.dbTester.getSession(), dto, portfolioComponentDto, null);
+  }
+
+  private static void createUsers(SqContext sqContext, int nbUser) {
+    for (int i = 0; i < nbUser; i++) {
+      UserDto userDto = sqContext.dbTester.users().insertUserRealistic();
+      ProjectDto projectDto = ThreadLocalRandom.current().nextBoolean() ? null : sqContext.projects.get(ThreadLocalRandom.current().nextInt(sqContext.projects.size()));
+      if (i % 60 == 0 && projectDto != null) {
+        createUserTokensDto(sqContext, userDto, projectDto);
+      }
+      if (i % 50 == 5 && projectDto != null) {
+        createUserDismissedMessages(sqContext, userDto, projectDto);
+      }
+    }
+  }
+
+  private static void createUserDismissedMessages(SqContext sqContext, UserDto userDto, ProjectDto projectDto) {
+    MessageType type = ThreadLocalRandom.current().nextBoolean() ? MessageType.GENERIC : MessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE;
+    sqContext.dbTester.users().insertUserDismissedMessageOnProject(userDto, projectDto, type);
+  }
+
+  private static void createUserTokensDto(SqContext sqContext, UserDto userDto, ProjectDto randomProject) {
+    long now = System.currentTimeMillis();
+    Long expirationDate = ThreadLocalRandom.current().nextBoolean() ? now + 123_123 : null;
+    sqContext.dbTester.users().insertToken(userDto, a -> a.setCreatedAt(now).setExpirationDate(expirationDate).setProjectKey(randomProject.getKey())
+      .setLastConnectionDate(now).setType(randomProject.getKey() != null ? TokenType.PROJECT_ANALYSIS_TOKEN.name() : TokenType.USER_TOKEN.name()));
+  }
+
+  private record SqContext(List<ProjectDto> projects, Set<RuleDto> rules, Map<String, MetricDto> metricDtosByKey, GroupDto adminGroup,
+                           DbTester dbTester) {
+    public RuleDto findNotSecurityHotspotRule() {
+      return rules.stream().filter(r -> r.getType() != RuleType.SECURITY_HOTSPOT.getDbConstant()).findAny().orElseThrow();
+    }
+  }
+
+  private static @NotNull DbTester createDbTester() {
+    return DbTester.createWithDifferentUuidFactory(UuidFactoryImpl.INSTANCE);
+  }
+
+  private record ProjectStructure(String projectName, int branchPerProject, int filePerBranch, int issuePerFile, int issueChangePerIssue,
+                                  int snapshotPerBranch, int webhookDeliveriesPerBranch) {
+  }
+
+  private record PortfolioGenerationSettings(int currentPortfoliosSize, int numberOfPortolios, int maxProjectPerPortfolio) {
+  }
+
+  private record BranchAndComponentDto(BranchDto branch, ComponentDto compo) {
+  }
+
+  private static ProjectDto generateProject(SqContext sqContext, ProjectStructure pj) {
+    final ProjectData projectCompoDto = sqContext.dbTester.components().insertPublicProject(p -> p.setName(pj.projectName));
+
+    sqContext.dbTester.forceCommit();
+    final WebhookDto projectWebHook = sqContext.dbTester.webhooks().insertWebhook(projectCompoDto.getProjectDto());
+    Streams.concat(
+        // main branch
+        Stream.of(new BranchAndComponentDto(
+          projectCompoDto.getMainBranchDto(),
+          projectCompoDto.getMainBranchComponent())),
+        // other branches
+        Stream.generate(() -> {
+          BranchDto branchDto = ComponentTesting.newBranchDto(projectCompoDto.getProjectDto().getUuid(), BRANCH);
+          return new BranchAndComponentDto(
+            branchDto,
+            sqContext.dbTester.components().insertProjectBranch(projectCompoDto.getProjectDto(), branchDto));
+        }))
+      // until there are enough branches generated
+      .limit(pj.branchPerProject)
+      // for every branch (main included)
+      .forEach(branchAndComponentDto -> {
+
+        // create live measure for the branch
+        projectLiveMeasureMetrics.stream()
+          .map(sqContext.metricDtosByKey::get)
+          .forEach(metricDto -> sqContext.dbTester().measures().insertLiveMeasureWithSensibleValues(branchAndComponentDto.compo, metricDto));
+
+        // create snapshots for the current branch
+        long time = System2.INSTANCE.now();
+        List<SnapshotDto> snapshots = new ArrayList<>();
+        // for every snapshot on the current branch
+        for (int snapshotNum = 0; snapshotNum < pj.snapshotPerBranch; snapshotNum++) {
+          SnapshotDto snapshotDto = SnapshotTesting.newAnalysis(branchAndComponentDto.branch);
+          snapshotDto.setLast(false);
+          snapshotDto.setCreatedAt(time);
+          time -= 10_000_000;
+          snapshots.add(snapshotDto);
+          // insert project measure for the snapshot
+          projectProjectMeasureMetrics.stream()
+            .map(sqContext.metricDtosByKey::get)
+            .forEach(metricDto -> sqContext.dbTester().measures().insertMeasureWithSensibleValues(branchAndComponentDto.compo, snapshotDto, metricDto));
+        }
+        SnapshotDto lastSnapshotDto = snapshots.get(0);
+        lastSnapshotDto.setLast(true);
+        sqContext.dbTester.components().insertSnapshots(snapshots.toArray(new SnapshotDto[0]));
+
+        // create webhook deliveries for every branch and only the last snapshot
+        for (int whdNum = 0; whdNum < pj.webhookDeliveriesPerBranch; whdNum++) {
+          sqContext.dbTester.webhookDelivery().insert(whd -> whd
+            .setAnalysisUuid(lastSnapshotDto.getUuid())
+            .setProjectUuid(projectCompoDto.getProjectDto().getUuid())
+            .setWebhookUuid(projectWebHook.getUuid()));
+        }
+
+        // for every file in branch
+        for (int fileNum = 0; fileNum < pj.filePerBranch; fileNum++) {
+          ComponentDto fileComponentDto = sqContext.dbTester.components().insertFile(branchAndComponentDto.compo);
+          sqContext.dbTester.fileSources().insertFileSource(fileComponentDto, pj.issuePerFile,
+            fs -> fs.setSourceData(fs.getSourceData()));
+          // for every issue in file
+          for (int issueNum = 0; issueNum < pj.issuePerFile; issueNum++) {
+            IssueDto issueDto = sqContext.dbTester.issues().insertIssue(sqContext.findNotSecurityHotspotRule(), branchAndComponentDto.compo, fileComponentDto);
+            // for every issue change in issue
+            for (int issueChangeNum = 0; issueChangeNum < pj.issueChangePerIssue; issueChangeNum++) {
+              sqContext.dbTester.issues().insertChange(issueDto);
+            }
+          }
+          // create live measure for this file
+          fileLiveMeasureMetrics.stream()
+            .map(sqContext.metricDtosByKey::get)
+            .forEach(metricDto -> sqContext.dbTester().measures().insertLiveMeasureWithSensibleValues(fileComponentDto, metricDto));
+        }
+
+        sqContext.dbTester.forceCommit();
+      });
+
+    return projectCompoDto.getProjectDto();
+  }
+
+  private static final List<String> projectLiveMeasureMetrics = List.of(
+    CoreMetrics.ACCEPTED_ISSUES_KEY,
+    CoreMetrics.ALERT_STATUS_KEY,
+    CoreMetrics.ANALYSIS_FROM_SONARQUBE_9_4_KEY,
+    CoreMetrics.BLOCKER_VIOLATIONS_KEY,
+    CoreMetrics.BUGS_KEY,
+    CoreMetrics.CODE_SMELLS_KEY,
+    CoreMetrics.COMMENT_LINES_KEY,
+    CoreMetrics.COMMENT_LINES_DENSITY_KEY,
+    CoreMetrics.CONFIRMED_ISSUES_KEY,
+    CoreMetrics.CRITICAL_VIOLATIONS_KEY,
+    CoreMetrics.DEVELOPMENT_COST_KEY,
+    CoreMetrics.DUPLICATED_BLOCKS_KEY,
+    CoreMetrics.DUPLICATED_FILES_KEY,
+    CoreMetrics.DUPLICATED_LINES_KEY,
+    CoreMetrics.DUPLICATED_LINES_DENSITY_KEY,
+    CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+    SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY,
+    CoreMetrics.FALSE_POSITIVE_ISSUES_KEY,
+    CoreMetrics.FILES_KEY,
+    CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES_KEY,
+    CoreMetrics.INFO_VIOLATIONS_KEY,
+    CoreMetrics.LAST_COMMIT_DATE_KEY,
+    CoreMetrics.LINES_KEY,
+    CoreMetrics.MAINTAINABILITY_ISSUES_KEY,
+    CoreMetrics.MAJOR_VIOLATIONS_KEY,
+    CoreMetrics.MINOR_VIOLATIONS_KEY,
+    CoreMetrics.NCLOC_KEY,
+    CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY,
+    CoreMetrics.OPEN_ISSUES_KEY,
+    CoreMetrics.QUALITY_GATE_DETAILS_KEY,
+    CoreMetrics.QUALITY_PROFILES_KEY,
+    CoreMetrics.RELIABILITY_ISSUES_KEY,
+    CoreMetrics.RELIABILITY_RATING_KEY,
+    CoreMetrics.RELIABILITY_REMEDIATION_EFFORT_KEY,
+    CoreMetrics.REOPENED_ISSUES_KEY,
+    CoreMetrics.SECURITY_HOTSPOTS_KEY,
+    CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY,
+    CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY,
+    CoreMetrics.SECURITY_ISSUES_KEY,
+    CoreMetrics.SECURITY_RATING_KEY,
+    CoreMetrics.SECURITY_REMEDIATION_EFFORT_KEY,
+    CoreMetrics.SECURITY_REVIEW_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY,
+    CoreMetrics.SQALE_DEBT_RATIO_KEY,
+    CoreMetrics.TECHNICAL_DEBT_KEY,
+    CoreMetrics.SQALE_RATING_KEY,
+    CoreMetrics.VIOLATIONS_KEY,
+    CoreMetrics.VULNERABILITIES_KEY
+  );
+
+  private static final List<String> fileLiveMeasureMetrics = List.of(
+    CoreMetrics.CODE_SMELLS_KEY,
+    CoreMetrics.COMMENT_LINES_KEY,
+    CoreMetrics.COMMENT_LINES_DENSITY_KEY,
+    CoreMetrics.DEVELOPMENT_COST_KEY,
+    CoreMetrics.FILES_KEY,
+    CoreMetrics.LAST_COMMIT_DATE_KEY,
+    CoreMetrics.LINES_KEY,
+    CoreMetrics.MAINTAINABILITY_ISSUES_KEY,
+    CoreMetrics.MAJOR_VIOLATIONS_KEY,
+    CoreMetrics.NCLOC_KEY,
+    CoreMetrics.NCLOC_DATA_KEY,
+    CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY,
+    CoreMetrics.OPEN_ISSUES_KEY,
+    CoreMetrics.RELIABILITY_ISSUES_KEY,
+    CoreMetrics.RELIABILITY_RATING_KEY,
+    CoreMetrics.SECURITY_ISSUES_KEY,
+    CoreMetrics.SECURITY_RATING_KEY,
+    CoreMetrics.SECURITY_REVIEW_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY,
+    CoreMetrics.SQALE_DEBT_RATIO_KEY,
+    CoreMetrics.TECHNICAL_DEBT_KEY,
+    CoreMetrics.SQALE_RATING_KEY,
+    CoreMetrics.VIOLATIONS_KEY);
+
+  private static final List<String> projectProjectMeasureMetrics = List.of(
+    CoreMetrics.ACCEPTED_ISSUES_KEY,
+    CoreMetrics.ALERT_STATUS_KEY,
+    CoreMetrics.ANALYSIS_FROM_SONARQUBE_9_4_KEY,
+    CoreMetrics.BLOCKER_VIOLATIONS_KEY,
+    CoreMetrics.BUGS_KEY,
+    CoreMetrics.CODE_SMELLS_KEY,
+    CoreMetrics.COMMENT_LINES_KEY,
+    CoreMetrics.COMMENT_LINES_DENSITY_KEY,
+    CoreMetrics.CONFIRMED_ISSUES_KEY,
+    CoreMetrics.CRITICAL_VIOLATIONS_KEY,
+    CoreMetrics.DEVELOPMENT_COST_KEY,
+    CoreMetrics.DUPLICATED_BLOCKS_KEY,
+    CoreMetrics.DUPLICATED_FILES_KEY,
+    CoreMetrics.DUPLICATED_LINES_KEY,
+    CoreMetrics.DUPLICATED_LINES_DENSITY_KEY,
+    CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY,
+    SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY,
+    CoreMetrics.FALSE_POSITIVE_ISSUES_KEY,
+    CoreMetrics.FILES_KEY,
+    CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES_KEY,
+    CoreMetrics.INFO_VIOLATIONS_KEY,
+    CoreMetrics.LAST_COMMIT_DATE_KEY,
+    CoreMetrics.LINES_KEY,
+    CoreMetrics.MAINTAINABILITY_ISSUES_KEY,
+    CoreMetrics.MAJOR_VIOLATIONS_KEY,
+    CoreMetrics.MINOR_VIOLATIONS_KEY,
+    CoreMetrics.NCLOC_KEY,
+    CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY,
+    CoreMetrics.OPEN_ISSUES_KEY,
+    CoreMetrics.QUALITY_GATE_DETAILS_KEY,
+    CoreMetrics.QUALITY_PROFILES_KEY,
+    CoreMetrics.RELIABILITY_ISSUES_KEY,
+    CoreMetrics.RELIABILITY_RATING_KEY,
+    CoreMetrics.RELIABILITY_REMEDIATION_EFFORT_KEY,
+    CoreMetrics.REOPENED_ISSUES_KEY,
+    CoreMetrics.SECURITY_HOTSPOTS_KEY,
+    CoreMetrics.SECURITY_ISSUES_KEY,
+    CoreMetrics.SECURITY_RATING_KEY,
+    CoreMetrics.SECURITY_REMEDIATION_EFFORT_KEY,
+    CoreMetrics.SECURITY_REVIEW_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT_KEY,
+    SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY,
+    CoreMetrics.SQALE_DEBT_RATIO_KEY,
+    CoreMetrics.TECHNICAL_DEBT_KEY,
+    CoreMetrics.SQALE_RATING_KEY,
+    CoreMetrics.VIOLATIONS_KEY,
+    CoreMetrics.VULNERABILITIES_KEY
+  );
+}
index b87dcd2db918dcc0d2a228b10b490ac17f8a82ad..041cf9ffc84a37756982ed814e28345a28621b27 100644 (file)
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Stream;
 import javax.annotation.Nullable;
+import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.extension.AfterEachCallback;
 import org.junit.jupiter.api.extension.BeforeEachCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
@@ -61,15 +62,15 @@ import org.sonar.db.webhook.WebhookDeliveryDbTester;
 
 /**
  * This class should be called using @Rule.
- * Data is truncated between each tests. The schema is created between each test.
+ * Data is truncated between each test. The schema is created between each test.
  */
 public class DbTester extends AbstractDbTester<TestDbImpl> implements BeforeEachCallback, AfterEachCallback {
 
-  private final UuidFactory uuidFactory = new SequenceUuidFactory();
+  private final UuidFactory uuidFactory;
   private final System2 system2;
   private final AuditPersister auditPersister;
   private DbClient client;
-  private DbSession session = null;
+  ThreadLocal<DbSessionContext> session = new ThreadLocal<>();
   private final UserDbTester userTester;
   private final ComponentDbTester componentTester;
   private final ProjectLinkDbTester projectLinkTester;
@@ -94,8 +95,9 @@ public class DbTester extends AbstractDbTester<TestDbImpl> implements BeforeEach
   private final AuditDbTester auditDbTester;
   private final AnticipatedTransitionDbTester anticipatedTransitionDbTester;
 
-  private DbTester(System2 system2, @Nullable String schemaPath, AuditPersister auditPersister, MyBatisConfExtension... confExtensions) {
+  private DbTester(UuidFactory uuidFactory, System2 system2, @Nullable String schemaPath, AuditPersister auditPersister, MyBatisConfExtension... confExtensions) {
     super(TestDbImpl.create(schemaPath, confExtensions));
+    this.uuidFactory = uuidFactory;
     this.system2 = system2;
     this.auditPersister = auditPersister;
 
@@ -138,11 +140,15 @@ public class DbTester extends AbstractDbTester<TestDbImpl> implements BeforeEach
   }
 
   public static DbTester create(System2 system2, AuditPersister auditPersister) {
-    return new DbTester(system2, null, auditPersister);
+    return new DbTester(new SequenceUuidFactory(), system2, null, auditPersister);
   }
 
   public static DbTester createWithExtensionMappers(System2 system2, Class<?> firstMapperClass, Class<?>... otherMapperClasses) {
-    return new DbTester(system2, null, new NoOpAuditPersister(), new DbTesterMyBatisConfExtension(firstMapperClass, otherMapperClasses));
+    return new DbTester(new SequenceUuidFactory(), system2, null, new NoOpAuditPersister(), new DbTesterMyBatisConfExtension(firstMapperClass, otherMapperClasses));
+  }
+
+  public static DbTester createWithDifferentUuidFactory(UuidFactory uuidFactory) {
+    return new DbTester(uuidFactory, System2.INSTANCE, null, new NoOpAuditPersister());
   }
 
   private void initDbClient() {
@@ -269,22 +275,33 @@ public class DbTester extends AbstractDbTester<TestDbImpl> implements BeforeEach
 
   @Override
   protected void after() {
-    if (session != null) {
-      session.rollback();
-      session.close();
+    if (session.get() != null) {
+      session.get().dbSession().rollback();
+      session.get().dbSession().close();
+      session.remove();
     }
     db.stop();
   }
 
   public DbSession getSession() {
-    if (session == null) {
-      session = db.getMyBatis().openSession(false);
+    return getSession(false);
+  }
+
+  public DbSession getSession(boolean batched) {
+    if (session.get() == null) {
+      session.set(new DbSessionContext(db.getMyBatis().openSession(batched), batched));
     }
-    return session;
+    return session.get().dbSession;
+  }
+
+  public void forceCommit() {
+    getSession().commit(true);
   }
 
   public void commit() {
-    getSession().commit();
+    if(session.get() != null && !session.get().isBatched()) {
+      getSession().commit();
+    }
   }
 
   public DbClient getDbClient() {
@@ -311,6 +328,8 @@ public class DbTester extends AbstractDbTester<TestDbImpl> implements BeforeEach
     return ((HikariDataSource) db.getDatabase().getDataSource()).getJdbcUrl();
   }
 
+  private record DbSessionContext(@NotNull DbSession dbSession, boolean isBatched){}
+
   private static class DbSessionConnectionSupplier implements ConnectionSupplier {
     private final DbSession dbSession;
 
index 039ec579da0136d8da071b2f31af2fc54eefa0fa..466faaa43387844126e5cb51e6a2076540a14806 100644 (file)
@@ -21,28 +21,25 @@ package org.sonar.db.audit;
 
 import java.util.List;
 import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 
 public class AuditDbTester {
 
   private final DbTester db;
   private final DbClient dbClient;
-  private final DbSession dbSession;
 
   public AuditDbTester(DbTester db) {
     this.db = db;
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
   }
 
   public final void insertRandomAuditEntry(long createdAt) {
     AuditDto auditDto = AuditTesting.newAuditDto(createdAt);
-    dbClient.auditDao().insert(dbSession, auditDto);
+    dbClient.auditDao().insert(db.getSession(), auditDto);
     db.commit();
   }
 
   public final List<AuditDto> selectAll() {
-    return dbClient.auditDao().selectOlderThan(dbSession, Long.MAX_VALUE);
+    return dbClient.auditDao().selectOlderThan(db.getSession(), Long.MAX_VALUE);
   }
 }
index cd8bbb1f5e31bdc058e3fd35f580209ece9e807b..5a31ff436c5127f4d6ec70e5c763b8f104a8c65a 100644 (file)
@@ -47,12 +47,10 @@ import static org.sonar.db.portfolio.PortfolioDto.SelectionMode.NONE;
 public class ComponentDbTester {
   private final DbTester db;
   private final DbClient dbClient;
-  private final DbSession dbSession;
 
   public ComponentDbTester(DbTester db) {
     this.db = db;
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
   }
 
   public SnapshotDto insertProjectAndSnapshot(ComponentDto component) {
@@ -67,7 +65,7 @@ public class ComponentDbTester {
   }
 
   public SnapshotDto insertPortfolioAndSnapshot(ComponentDto component) {
-    dbClient.componentDao().insert(dbSession, component, true);
+    dbClient.componentDao().insert(db.getSession(), component, true);
     return insertSnapshot(component);
   }
 
@@ -86,23 +84,23 @@ public class ComponentDbTester {
   }
 
   public BranchDto getBranchDto(ComponentDto branch) {
-    return db.getDbClient().branchDao().selectByUuid(dbSession, branch.uuid())
+    return db.getDbClient().branchDao().selectByUuid(db.getSession(), branch.uuid())
       .orElseThrow(() -> new IllegalStateException("Project has invalid configuration"));
   }
 
   public ProjectDto getProjectDtoByMainBranch(ComponentDto mainBranch) {
-    return db.getDbClient().projectDao().selectByBranchUuid(dbSession, mainBranch.uuid())
+    return db.getDbClient().projectDao().selectByBranchUuid(db.getSession(), mainBranch.uuid())
       .orElseThrow(() -> new IllegalStateException("Project has invalid configuration"));
   }
 
   public ComponentDto getComponentDto(ProjectDto project) {
-    BranchDto branchDto = db.getDbClient().branchDao().selectMainBranchByProjectUuid(dbSession, project.getUuid()).get();
-    return db.getDbClient().componentDao().selectByUuid(dbSession, branchDto.getUuid())
+    BranchDto branchDto = db.getDbClient().branchDao().selectMainBranchByProjectUuid(db.getSession(), project.getUuid()).get();
+    return db.getDbClient().componentDao().selectByUuid(db.getSession(), branchDto.getUuid())
       .orElseThrow(() -> new IllegalStateException("Can't find project"));
   }
 
   public ComponentDto getComponentDto(BranchDto branch) {
-    return db.getDbClient().componentDao().selectByUuid(dbSession, branch.getUuid())
+    return db.getDbClient().componentDao().selectByUuid(db.getSession(), branch.getUuid())
       .orElseThrow(() -> new IllegalStateException("Can't find branch"));
   }
 
@@ -160,6 +158,10 @@ public class ComponentDbTester {
     return insertComponent(ComponentTesting.newFileDto(projectComponent));
   }
 
+  public final ComponentDto insertFile(ComponentDto projectComponent) {
+    return insertComponent(ComponentTesting.newFileDto(projectComponent));
+  }
+
   public final ProjectData insertPrivateProject(String uuid, Consumer<ComponentDto> dtoPopulator) {
     return insertComponentAndBranchAndProject(ComponentTesting.newPrivateProjectDto(), true, defaults(), dtoPopulator, p -> p.setUuid(uuid));
 
@@ -260,7 +262,12 @@ public class ComponentDbTester {
   }
 
   public PortfolioDto getPortfolioDto(ComponentDto portfolio) {
-    return db.getDbClient().portfolioDao().selectByUuid(dbSession, portfolio.uuid())
+    return db.getDbClient().portfolioDao().selectByUuid(db.getSession(), portfolio.uuid())
+      .orElseThrow(() -> new IllegalStateException("Portfolio has invalid configuration"));
+  }
+
+  public PortfolioDto getPortfolioDto(PortfolioDto portfolio) {
+    return db.getDbClient().portfolioDao().selectByUuid(db.getSession(), portfolio.getUuid())
       .orElseThrow(() -> new IllegalStateException("Portfolio has invalid configuration"));
   }
 
@@ -270,7 +277,7 @@ public class ComponentDbTester {
 
     PortfolioDto portfolioDto = toPortfolioDto(componentDto, System2.INSTANCE.now());
     portfolioPopulator.accept(portfolioDto);
-    dbClient.portfolioDao().insertWithAudit(dbSession, portfolioDto);
+    dbClient.portfolioDao().insertWithAudit(db.getSession(), portfolioDto);
     db.commit();
     return componentDto;
   }
@@ -302,15 +309,15 @@ public class ComponentDbTester {
 
   public void addPortfolioReference(String portfolioUuid, String... referencerUuids) {
     for (String uuid : referencerUuids) {
-      EntityDto entityDto = dbClient.entityDao().selectByUuid(dbSession, uuid)
+      EntityDto entityDto = dbClient.entityDao().selectByUuid(db.getSession(), uuid)
         .orElseThrow();
       switch (entityDto.getQualifier()) {
         case APP -> {
-          BranchDto appMainBranch = dbClient.branchDao().selectMainBranchByProjectUuid(dbSession, entityDto.getUuid())
+          BranchDto appMainBranch = dbClient.branchDao().selectMainBranchByProjectUuid(db.getSession(), entityDto.getUuid())
             .orElseThrow();
-          dbClient.portfolioDao().addReferenceBranch(dbSession, portfolioUuid, uuid, appMainBranch.getUuid());
+          dbClient.portfolioDao().addReferenceBranch(db.getSession(), portfolioUuid, uuid, appMainBranch.getUuid());
         }
-        case VIEW, SUBVIEW -> dbClient.portfolioDao().addReference(dbSession, portfolioUuid, uuid);
+        case VIEW, SUBVIEW -> dbClient.portfolioDao().addReference(db.getSession(), portfolioUuid, uuid);
         default -> throw new IllegalStateException("Unexpected value: " + entityDto.getQualifier());
       }
     }
@@ -331,7 +338,7 @@ public class ComponentDbTester {
 
   public void addPortfolioProject(String portfolioUuid, String... projectUuids) {
     for (String uuid : projectUuids) {
-      dbClient.portfolioDao().addProject(dbSession, portfolioUuid, uuid);
+      dbClient.portfolioDao().addProject(db.getSession(), portfolioUuid, uuid);
     }
     db.commit();
   }
@@ -342,7 +349,7 @@ public class ComponentDbTester {
 
   public void addPortfolioProject(ComponentDto portfolio, ProjectDto... projects) {
     for (ProjectDto project : projects) {
-      dbClient.portfolioDao().addProject(dbSession, portfolio.uuid(), project.getUuid());
+      dbClient.portfolioDao().addProject(db.getSession(), portfolio.uuid(), project.getUuid());
     }
     db.commit();
   }
@@ -354,7 +361,7 @@ public class ComponentDbTester {
 
   public void addPortfolioProject(PortfolioDto portfolioDto, ProjectDto... projects) {
     for (ProjectDto project : projects) {
-      dbClient.portfolioDao().addProject(dbSession, portfolioDto.getUuid(), project.getUuid());
+      dbClient.portfolioDao().addProject(db.getSession(), portfolioDto.getUuid(), project.getUuid());
     }
     db.commit();
   }
@@ -368,7 +375,7 @@ public class ComponentDbTester {
   }
 
   public void addPortfolioProjectBranch(String portfolioUuid, String projectUuid, String branchUuid) {
-    PortfolioProjectDto portfolioProject = dbClient.portfolioDao().selectPortfolioProjectOrFail(dbSession, portfolioUuid, projectUuid);
+    PortfolioProjectDto portfolioProject = dbClient.portfolioDao().selectPortfolioProjectOrFail(db.getSession(), portfolioUuid, projectUuid);
     dbClient.portfolioDao().addBranch(db.getSession(), portfolioProject.getUuid(), branchUuid);
     db.commit();
   }
@@ -421,13 +428,13 @@ public class ComponentDbTester {
 
     ProjectDto projectDto = toProjectDto(component, System2.INSTANCE.now());
     projectDtoPopulator.accept(projectDto);
-    dbClient.projectDao().insert(dbSession, projectDto);
+    dbClient.projectDao().insert(db.getSession(), projectDto);
 
     BranchDto branchDto = ComponentTesting.newMainBranchDto(component, projectDto.getUuid());
     branchDto.setExcludeFromPurge(true);
     branchPopulator.accept(branchDto);
     branchDto.setIsMain(true);
-    dbClient.branchDao().insert(dbSession, branchDto);
+    dbClient.branchDao().insert(db.getSession(), branchDto);
 
     db.commit();
     return new ProjectData(getProjectDtoByMainBranch(component), branchDto, component);
@@ -435,14 +442,14 @@ public class ComponentDbTester {
 
   public void addApplicationProject(ProjectDto application, ProjectDto... projects) {
     for (ProjectDto project : projects) {
-      dbClient.applicationProjectsDao().addProject(dbSession, application.getUuid(), project.getUuid());
+      dbClient.applicationProjectsDao().addProject(db.getSession(), application.getUuid(), project.getUuid());
     }
     db.commit();
   }
 
   public void addApplicationProject(ProjectData application, ProjectData... projects) {
     for (ProjectData project : projects) {
-      dbClient.applicationProjectsDao().addProject(dbSession, application.getProjectDto().getUuid(), project.getProjectDto().getUuid());
+      dbClient.applicationProjectsDao().addProject(db.getSession(), application.getProjectDto().getUuid(), project.getProjectDto().getUuid());
     }
     db.commit();
   }
@@ -456,7 +463,7 @@ public class ComponentDbTester {
 
   public void addProjectBranchToApplicationBranch(BranchDto applicationBranch, BranchDto... projectBranches) {
     for (BranchDto projectBranch : projectBranches) {
-      dbClient.applicationProjectsDao().addProjectBranchToAppBranch(dbSession, applicationBranch, projectBranch);
+      dbClient.applicationProjectsDao().addProjectBranchToAppBranch(db.getSession(), applicationBranch, projectBranch);
     }
     db.commit();
   }
@@ -477,19 +484,19 @@ public class ComponentDbTester {
   private ComponentDto insertComponentImpl(ComponentDto component, @Nullable Boolean isPrivate, Consumer<ComponentDto> dtoPopulator) {
     dtoPopulator.accept(component);
     checkState(isPrivate == null || component.isPrivate() == isPrivate, "Illegal modification of private flag");
-    dbClient.componentDao().insert(dbSession, component, true);
+    dbClient.componentDao().insert(db.getSession(), component, true);
     db.commit();
 
     return component;
   }
 
   public void insertComponents(ComponentDto... components) {
-    dbClient.componentDao().insert(dbSession, asList(components), true);
+    dbClient.componentDao().insert(db.getSession(), asList(components), true);
     db.commit();
   }
 
   public SnapshotDto insertSnapshot(SnapshotDto snapshotDto) {
-    SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, snapshotDto);
+    SnapshotDto snapshot = dbClient.snapshotDao().insert(db.getSession(), snapshotDto);
     db.commit();
     return snapshot;
   }
@@ -522,7 +529,7 @@ public class ComponentDbTester {
    */
   @Deprecated
   public SnapshotDto insertSnapshot(ProjectDto project, Consumer<SnapshotDto> consumer) {
-    BranchDto mainBranchDto = db.getDbClient().branchDao().selectMainBranchByProjectUuid(dbSession, project.getUuid()).orElseThrow();
+    BranchDto mainBranchDto = db.getDbClient().branchDao().selectMainBranchByProjectUuid(db.getSession(), project.getUuid()).orElseThrow();
     SnapshotDto snapshotDto = SnapshotTesting.newAnalysis(mainBranchDto.getUuid());
     consumer.accept(snapshotDto);
     return insertSnapshot(snapshotDto);
@@ -540,7 +547,7 @@ public class ComponentDbTester {
   }
 
   public void insertSnapshots(SnapshotDto... snapshotDtos) {
-    dbClient.snapshotDao().insert(dbSession, asList(snapshotDtos));
+    dbClient.snapshotDao().insert(db.getSession(), asList(snapshotDtos));
     db.commit();
   }
 
@@ -564,7 +571,7 @@ public class ComponentDbTester {
     checkArgument(branchDto.getProjectUuid().equals(project.getUuid()));
     ComponentDto branch = ComponentTesting.newBranchComponent(project, branchDto);
     insertComponent(branch);
-    dbClient.branchDao().insert(dbSession, branchDto);
+    dbClient.branchDao().insert(db.getSession(), branchDto);
     db.commit();
     return branch;
   }
@@ -572,7 +579,7 @@ public class ComponentDbTester {
   public final ComponentDto insertProjectBranch(ComponentDto project, BranchDto branchDto) {
     ComponentDto branch = ComponentTesting.newBranchComponent(project, branchDto);
     insertComponent(branch);
-    dbClient.branchDao().insert(dbSession, branchDto);
+    dbClient.branchDao().insert(db.getSession(), branchDto);
     db.commit();
     return branch;
   }
index 853997999f4ed9e5e34c1a24ef96b8c038d3b57e..8e8203c70d2d1d4650b068c0a9f47bc92aa09066 100644 (file)
@@ -32,12 +32,10 @@ import static org.sonar.db.component.ProjectLinkTesting.newProvidedLinkDto;
 public class ProjectLinkDbTester {
   private final DbTester db;
   private final DbClient dbClient;
-  private final DbSession dbSession;
 
   public ProjectLinkDbTester(DbTester db) {
     this.db = db;
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
   }
   
   @SafeVarargs
@@ -53,7 +51,7 @@ public class ProjectLinkDbTester {
   @SafeVarargs
   private final ProjectLinkDto insertLink(ProjectDto project, ProjectLinkDto componentLink, Consumer<ProjectLinkDto>... dtoPopulators) {
     Arrays.stream(dtoPopulators).forEach(dtoPopulator -> dtoPopulator.accept(componentLink));
-    dbClient.projectLinkDao().insert(dbSession, componentLink.setProjectUuid(project.getUuid()));
+    dbClient.projectLinkDao().insert(db.getSession(), componentLink.setProjectUuid(project.getUuid()));
     db.commit();
     return componentLink;
   }
index ed57482d95fa005c761792b7302a7981f258f88b..d87187e4f9fb01806954acfed63992ea50d0a59f 100644 (file)
@@ -33,16 +33,14 @@ import org.sonar.db.event.EventComponentChangeDto.ChangeCategory;
 public class EventDbTester {
   private final DbTester db;
   private final DbClient dbClient;
-  private final DbSession dbSession;
 
   public EventDbTester(DbTester db) {
     this.db = db;
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
   }
 
   public EventDto insertEvent(EventDto event) {
-    dbClient.eventDao().insert(dbSession, event);
+    dbClient.eventDao().insert(db.getSession(), event);
     db.commit();
 
     return event;
@@ -50,7 +48,7 @@ public class EventDbTester {
 
   public EventDto insertEvent(SnapshotDto analysis) {
     EventDto event = EventTesting.newEvent(analysis);
-    dbClient.eventDao().insert(dbSession, event);
+    dbClient.eventDao().insert(db.getSession(), event);
     db.commit();
 
     return event;
@@ -69,7 +67,7 @@ public class EventDbTester {
       .setComponentBranchKey(Optional.ofNullable(branch).map(BranchDto::getKey).orElse(null));
     EventPurgeData eventPurgeData = new EventPurgeData(analysis.getRootComponentUuid(), analysis.getUuid());
     
-    dbClient.eventComponentChangeDao().insert(dbSession, eventComponentChange, eventPurgeData);
+    dbClient.eventComponentChangeDao().insert(db.getSession(), eventComponentChange, eventPurgeData);
     db.commit();
 
     return eventComponentChange;
index baad4a6eb5e0a3cb4a198dd112c01053c87b35f7..26f53bf9e095b8cd8fa53c8837f73323d3b0faec 100644 (file)
@@ -31,20 +31,20 @@ public class FavoriteDbTester {
   private static final String PROP_FAVORITE_KEY = "favourite";
 
   private final DbClient dbClient;
-  private final DbSession dbSession;
+  private final DbTester db;
 
   public FavoriteDbTester(DbTester db) {
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
+    this.db = db;
   }
 
   public void add(EntityDto entity, String userUuid, String userLogin) {
-    dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto()
+    dbClient.propertiesDao().saveProperty(db.getSession(), new PropertyDto()
         .setKey(PROP_FAVORITE_KEY)
         .setUserUuid(userUuid)
         .setEntityUuid(entity.getUuid()),
       userLogin, entity.getKey(), entity.getName(), entity.getQualifier());
-    dbSession.commit();
+    db.commit();
   }
 
   public boolean hasFavorite(EntityDto entity, String userUuid) {
@@ -52,7 +52,7 @@ public class FavoriteDbTester {
       .setKey(PROP_FAVORITE_KEY)
       .setEntityUuid(entity.getUuid())
       .setUserUuid(userUuid)
-      .build(), dbSession);
+      .build(), db.getSession());
 
     return !result.isEmpty();
   }
@@ -61,7 +61,7 @@ public class FavoriteDbTester {
     List<PropertyDto> result = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
       .setKey(PROP_FAVORITE_KEY)
       .setEntityUuid(entity.getUuid())
-      .build(), dbSession);
+      .build(), db.getSession());
     return result.isEmpty();
   }
 }
index 1c6cf9abcd32288f127894e697751267178af414..4cff115a957d0d4d52f7952651133f94840955a6 100644 (file)
  */
 package org.sonar.db.measure;
 
+import java.time.Instant;
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.BiConsumer;
 import java.util.function.Consumer;
+import org.sonar.api.measures.CoreMetrics;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -36,19 +42,28 @@ import static org.sonar.db.metric.MetricTesting.newMetricDto;
 
 public class MeasureDbTester {
   private final DbClient dbClient;
-  private final DbSession dbSession;
+  private final DbTester db;
 
   public MeasureDbTester(DbTester db) {
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
+    this.db = db;
+  }
+
+  @SafeVarargs
+  public final ProjectMeasureDto insertMeasureWithSensibleValues(ComponentDto component, SnapshotDto analysis, MetricDto metricDto, Consumer<ProjectMeasureDto>... consumers) {
+    ProjectMeasureDto measureDto = createProjectMeasure(metricDto, analysis, component);
+    Arrays.stream(consumers).forEach(c -> c.accept(measureDto));
+    dbClient.projectMeasureDao().insert(db.getSession(), measureDto);
+    db.commit();
+    return measureDto;
   }
 
   @SafeVarargs
   public final ProjectMeasureDto insertProjectMeasure(ComponentDto component, SnapshotDto analysis, MetricDto metricDto, Consumer<ProjectMeasureDto>... consumers) {
     ProjectMeasureDto projectMeasureDto = newProjectMeasureDto(metricDto, component, analysis);
     Arrays.stream(consumers).forEach(c -> c.accept(projectMeasureDto));
-    dbClient.projectMeasureDao().insert(dbSession, projectMeasureDto);
-    dbSession.commit();
+    dbClient.projectMeasureDao().insert(db.getSession(), projectMeasureDto);
+    db.commit();
     return projectMeasureDto;
   }
 
@@ -56,17 +71,26 @@ public class MeasureDbTester {
   public final ProjectMeasureDto insertProjectMeasure(BranchDto branchDto, SnapshotDto analysis, MetricDto metricDto, Consumer<ProjectMeasureDto>... consumers) {
     ProjectMeasureDto projectMeasureDto = MeasureTesting.newProjectMeasureDto(metricDto, branchDto.getUuid(), analysis);
     Arrays.stream(consumers).forEach(c -> c.accept(projectMeasureDto));
-    dbClient.projectMeasureDao().insert(dbSession, projectMeasureDto);
-    dbSession.commit();
+    dbClient.projectMeasureDao().insert(db.getSession(), projectMeasureDto);
+    db.commit();
     return projectMeasureDto;
   }
 
+  @SafeVarargs
+  public final LiveMeasureDto insertLiveMeasureWithSensibleValues(ComponentDto component, MetricDto metric, Consumer<LiveMeasureDto>... consumers) {
+    LiveMeasureDto dto = createLiveMeasure(metric, component);
+    Arrays.stream(consumers).forEach(c -> c.accept(dto));
+    dbClient.liveMeasureDao().insert(db.getSession(), dto);
+    db.commit();
+    return dto;
+  }
+
   @SafeVarargs
   public final LiveMeasureDto insertLiveMeasure(ComponentDto component, MetricDto metric, Consumer<LiveMeasureDto>... consumers) {
     LiveMeasureDto dto = newLiveMeasure(component, metric);
     Arrays.stream(consumers).forEach(c -> c.accept(dto));
-    dbClient.liveMeasureDao().insert(dbSession, dto);
-    dbSession.commit();
+    dbClient.liveMeasureDao().insert(db.getSession(), dto);
+    db.commit();
     return dto;
   }
 
@@ -74,8 +98,8 @@ public class MeasureDbTester {
   public final LiveMeasureDto insertLiveMeasure(BranchDto branchDto, MetricDto metric, Consumer<LiveMeasureDto>... consumers) {
     LiveMeasureDto dto = newLiveMeasure(branchDto, metric);
     Arrays.stream(consumers).forEach(c -> c.accept(dto));
-    dbClient.liveMeasureDao().insert(dbSession, dto);
-    dbSession.commit();
+    dbClient.liveMeasureDao().insert(db.getSession(), dto);
+    db.commit();
     return dto;
   }
 
@@ -89,9 +113,120 @@ public class MeasureDbTester {
   public final MetricDto insertMetric(Consumer<MetricDto>... consumers) {
     MetricDto metricDto = newMetricDto();
     Arrays.stream(consumers).forEach(c -> c.accept(metricDto));
-    dbClient.metricDao().insert(dbSession, metricDto);
-    dbSession.commit();
+    dbClient.metricDao().insert(db.getSession(), metricDto);
+    db.commit();
     return metricDto;
   }
 
+  public static LiveMeasureDto createLiveMeasure(MetricDto metricDto, ComponentDto componentDto) {
+    BiConsumer<MetricDto, MeasureAdapter> populator = specificLiveMeasurePopulator.getOrDefault(metricDto.getKey(), defaultLiveMeasurePopulator);
+    LiveMeasureDto liveMeasureDto = newLiveMeasure(componentDto, metricDto);
+    populator.accept(metricDto, new MeasureAdapter(liveMeasureDto));
+    return liveMeasureDto;
+  }
+
+  public static ProjectMeasureDto createProjectMeasure(MetricDto metricDto, SnapshotDto snapshotDto, ComponentDto projectComponentDto) {
+    BiConsumer<MetricDto, MeasureAdapter> populator = specificLiveMeasurePopulator.getOrDefault(metricDto.getKey(), defaultLiveMeasurePopulator);
+    ProjectMeasureDto measureDto = newProjectMeasureDto(metricDto, projectComponentDto, snapshotDto);
+    populator.accept(metricDto, new MeasureAdapter(measureDto));
+    return measureDto;
+  }
+
+  private static final Consumer<MeasureAdapter> ratingMeasurePopulator =
+    m -> {
+      int rating = ThreadLocalRandom.current().nextInt(1, 5);
+      char textValue = (char) ('A' + rating - 1);
+      m.setValue((double) rating).setData("" + textValue);
+    };
+
+  private static final Map<String, BiConsumer<MetricDto, MeasureAdapter>> specificLiveMeasurePopulator = new HashMap<>() {
+    {
+      put(CoreMetrics.DEVELOPMENT_COST_KEY, (metric, m) -> m.setData("" + Math.round(ThreadLocalRandom.current().nextDouble(100, 10_000))));
+      put(CoreMetrics.LAST_COMMIT_DATE_KEY,
+        (metric, m) -> m.setValue((double) Instant.now().minusSeconds(Math.round(ThreadLocalRandom.current().nextDouble(100_000, 1_000_000))).toEpochMilli()));
+      put(CoreMetrics.SQALE_RATING_KEY, (metric, m) -> ratingMeasurePopulator.accept(m));
+      put(CoreMetrics.RELIABILITY_RATING_KEY, (metric, m) -> ratingMeasurePopulator.accept(m));
+      put(CoreMetrics.SECURITY_REVIEW_RATING_KEY, (metric, m) -> ratingMeasurePopulator.accept(m));
+      put(CoreMetrics.SECURITY_RATING_KEY, (metric, m) -> ratingMeasurePopulator.accept(m));
+      put(CoreMetrics.ALERT_STATUS_KEY, (metric, m) -> {
+        boolean isOk = ThreadLocalRandom.current().nextDouble() > 0.5;
+        m.setData(isOk ? "OK" : "ERROR");
+        m.setAlert(isOk ? "OK" : "ERROR");
+      });
+      put(CoreMetrics.QUALITY_GATE_DETAILS_KEY, (metric, m) -> m.setData("{\"level\":\"OK\",\"conditions\":[],\"ignoredConditions\":false}"));
+      put(CoreMetrics.QUALITY_PROFILES_KEY, (metric, m) -> m.setData("[{\"key\":\"62969160-dcda-40a0-9981-772b7820d587\",\"language\":\"xml\",\"name\":\"Sonar way\",\"rulesUpdatedAt\":\"2024-09-11T14:40:55+0000\"}]"));
+      put(CoreMetrics.RELIABILITY_ISSUES_KEY, (metric, m) -> m.setData("{\"LOW\":0,\"MEDIUM\":1,\"HIGH\":0,\"total\":1}"));
+      put(CoreMetrics.MAINTAINABILITY_ISSUES_KEY, (metric, m) -> m.setData("{\"LOW\":0,\"MEDIUM\":1,\"HIGH\":0,\"total\":1}"));
+      put(CoreMetrics.SECURITY_ISSUES_KEY, (metric, m) -> m.setData("{\"LOW\":0,\"MEDIUM\":1,\"HIGH\":0,\"total\":1}"));
+    }
+  };
+
+  private static final BiConsumer<MetricDto, MeasureAdapter> defaultLiveMeasurePopulator =
+    (metric, m) -> {
+      int min, max;
+      if (metric.getWorstValue() != null && metric.getBestValue() != null) {
+        min = (int) Math.min(metric.getBestValue(), metric.getWorstValue());
+        max = (int) Math.max(metric.getBestValue(), metric.getWorstValue());
+      } else if (metric.getDirection() != 0) {
+        int worst, best;
+        if (metric.getWorstValue() != null) {
+          worst = metric.getWorstValue().intValue();
+          best = -metric.getDirection() * 100;
+        } else if (metric.getBestValue() != null) {
+          best = metric.getBestValue().intValue();
+          worst = best - metric.getDirection() * 100;
+        } else {
+          worst = 0;
+          best = -metric.getDirection() * 100;
+        }
+        min = Math.min(best, worst);
+        max = Math.max(best, worst);
+      } else {
+        min = 0;
+        max = 100;
+      }
+
+      m.setValue((double) Math.round(ThreadLocalRandom.current().nextDouble(min, max)));
+    };
+
+  private static class MeasureAdapter {
+    private final ProjectMeasureDto projectMeasure;
+    private final LiveMeasureDto liveMeasure;
+
+    private MeasureAdapter(LiveMeasureDto liveMeasure) {
+      this.projectMeasure = null;
+      this.liveMeasure = liveMeasure;
+    }
+
+    private MeasureAdapter(ProjectMeasureDto projectMeasure) {
+      this.projectMeasure = projectMeasure;
+      this.liveMeasure = null;
+    }
+
+    public MeasureAdapter setValue(Double value) {
+      if (projectMeasure != null) {
+        projectMeasure.setValue(value);
+      } else if (liveMeasure != null) {
+        liveMeasure.setValue(value);
+      }
+      return this;
+    }
+
+    public MeasureAdapter setData(String data) {
+      if (projectMeasure != null) {
+        projectMeasure.setData(data);
+      } else if (liveMeasure != null) {
+        liveMeasure.setData(data);
+      }
+      return this;
+    }
+
+    public MeasureAdapter setAlert(String value) {
+      if (projectMeasure != null) {
+        projectMeasure.setAlertText(value).setAlertStatus(value);
+      }
+      return this;
+    }
+  }
+
 }
index f0ff519a0a8ec7225b995a8f1de3ca748d2448c1..3db9b97f1e5026dce7eb47e10da526d3e12cec34 100644 (file)
@@ -34,11 +34,11 @@ public class NotificationDbTester {
   private static final String PROP_NOTIFICATION_PREFIX = "notification";
 
   private final DbClient dbClient;
-  private final DbSession dbSession;
+  private final DbTester db;
 
   public NotificationDbTester(DbTester db) {
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
+    this.db = db;
   }
 
   public void assertExists(String channel, String dispatcher, String userUuid, @Nullable ProjectDto project) {
@@ -46,7 +46,7 @@ public class NotificationDbTester {
         .setKey(String.join(".", PROP_NOTIFICATION_PREFIX, dispatcher, channel))
         .setEntityUuid(project == null ? null : project.getUuid())
         .setUserUuid(userUuid)
-        .build(), dbSession).stream()
+        .build(), db.getSession()).stream()
       .filter(prop -> project == null ? prop.getEntityUuid() == null : prop.getEntityUuid() != null)
       .toList();
     assertThat(result).hasSize(1);
@@ -58,7 +58,7 @@ public class NotificationDbTester {
       .setKey(String.join(".", PROP_NOTIFICATION_PREFIX, dispatcher, channel))
       .setEntityUuid(project == null ? null : project.getUuid())
       .setUserUuid(userUuid)
-      .build(), dbSession);
+      .build(), db.getSession());
     assertThat(result).isEmpty();
   }
 }
index 1cc5d189af63c23d5ba554f7398213b3d0b92a82..99334c52628cf66f1687b874c4c0569bf5ca67b8 100644 (file)
@@ -34,23 +34,21 @@ import static org.sonar.db.permission.template.PermissionTemplateTesting.newPerm
 public class PermissionTemplateDbTester {
   private final DbTester db;
   private final DbClient dbClient;
-  private final DbSession dbSession;
 
   public PermissionTemplateDbTester(DbTester db) {
     this.db = db;
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
   }
 
   public void setDefaultTemplates(String projectDefaultTemplateUuid, @Nullable String applicationDefaultTemplateUuid, @Nullable String portfoliosDefaultTemplateUuid) {
-    db.getDbClient().internalPropertiesDao().save(dbSession, "defaultTemplate.prj", projectDefaultTemplateUuid);
+    db.getDbClient().internalPropertiesDao().save(db.getSession(), "defaultTemplate.prj", projectDefaultTemplateUuid);
     if (applicationDefaultTemplateUuid != null) {
-      db.getDbClient().internalPropertiesDao().save(dbSession, "defaultTemplate.app", applicationDefaultTemplateUuid);
+      db.getDbClient().internalPropertiesDao().save(db.getSession(), "defaultTemplate.app", applicationDefaultTemplateUuid);
     }
     if (portfoliosDefaultTemplateUuid != null) {
-      db.getDbClient().internalPropertiesDao().save(dbSession, "defaultTemplate.port", portfoliosDefaultTemplateUuid);
+      db.getDbClient().internalPropertiesDao().save(db.getSession(), "defaultTemplate.port", portfoliosDefaultTemplateUuid);
     }
-    dbSession.commit();
+    db.commit();
   }
 
   public void setDefaultTemplates(PermissionTemplateDto projectDefaultTemplate, @Nullable PermissionTemplateDto applicationDefaultTemplate,
@@ -66,7 +64,7 @@ public class PermissionTemplateDbTester {
   }
 
   public PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
-    PermissionTemplateDto templateInDb = dbClient.permissionTemplateDao().insert(dbSession, template);
+    PermissionTemplateDto templateInDb = dbClient.permissionTemplateDao().insert(db.getSession(), template);
     db.commit();
     return templateInDb;
   }
@@ -76,7 +74,7 @@ public class PermissionTemplateDbTester {
   }
 
   public void addGroupToTemplate(String templateUuid, @Nullable String groupUuid, String permission, String templateName, @Nullable String groupName) {
-    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, templateUuid, groupUuid, permission, templateName, groupName);
+    dbClient.permissionTemplateDao().insertGroupPermission(db.getSession(), templateUuid, groupUuid, permission, templateName, groupName);
     db.commit();
   }
 
@@ -89,7 +87,7 @@ public class PermissionTemplateDbTester {
   }
 
   public void addUserToTemplate(String templateUuid, String userUuid, String permission, String templateName, String userLogin) {
-    dbClient.permissionTemplateDao().insertUserPermission(dbSession, templateUuid, userUuid, permission, templateName, userLogin);
+    dbClient.permissionTemplateDao().insertUserPermission(db.getSession(), templateUuid, userUuid, permission, templateName, userLogin);
     db.commit();
   }
 
@@ -98,7 +96,7 @@ public class PermissionTemplateDbTester {
   }
 
   public void addProjectCreatorToTemplate(String templateUuid, String permission, String templateName) {
-    dbClient.permissionTemplateCharacteristicDao().insert(dbSession, newPermissionTemplateCharacteristicDto()
+    dbClient.permissionTemplateCharacteristicDao().insert(db.getSession(), newPermissionTemplateCharacteristicDto()
         .setWithProjectCreator(true)
         .setTemplateUuid(templateUuid)
         .setPermission(permission),
index 8b3c7f6ad03f9651194716b9ba76e35a1e45e1bf..8e13b0d233bc2da27662dc499850db85175e1475 100644 (file)
@@ -27,19 +27,19 @@ import org.sonar.db.DbTester;
 
 public class PluginDbTester {
   private final DbClient dbClient;
-  private final DbSession dbSession;
+  private final DbTester db;
 
   public PluginDbTester(DbTester db) {
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
+    this.db = db;
   }
 
   @SafeVarargs
   public final PluginDto insertPlugin(Consumer<PluginDto>... consumers) {
     PluginDto pluginDto = PluginTesting.newPluginDto();
     Arrays.stream(consumers).forEach(c -> c.accept(pluginDto));
-    dbClient.pluginDao().insert(dbSession, pluginDto);
-    dbSession.commit();
+    dbClient.pluginDao().insert(db.getSession(), pluginDto);
+    db.commit();
     return pluginDto;
   }
 
index 227179d52bdfe71cbfd0a45f9d5d2fd982d27a92..f5bb41bc3dbc81edc2a7b883e90d022f922fa831 100644 (file)
@@ -27,20 +27,18 @@ import org.sonar.db.DbTester;
 public class InternalComponentPropertyDbTester {
   private final DbTester db;
   private final DbClient dbClient;
-  private final DbSession dbSession;
 
   public InternalComponentPropertyDbTester(DbTester db) {
     this.db = db;
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
   }
 
   public void insertProperty(String componentUuid, String key, String value) {
-    dbClient.internalComponentPropertiesDao().insertOrUpdate(dbSession, componentUuid, key, value);
+    dbClient.internalComponentPropertiesDao().insertOrUpdate(db.getSession(), componentUuid, key, value);
     db.commit();
   }
 
   public Optional<InternalComponentPropertyDto> getProperty(String componentUuid, String key) {
-    return dbClient.internalComponentPropertiesDao().selectByComponentUuidAndKey(dbSession, componentUuid, key);
+    return dbClient.internalComponentPropertiesDao().selectByComponentUuidAndKey(db.getSession(), componentUuid, key);
   }
 }
index c0f2ba6336b3bc7c879d7f553c5c1045a9e1ab6c..38f5755c6e54bda9e7748d57ac5e56f67f474097 100644 (file)
@@ -38,17 +38,15 @@ import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto;
 public class PropertyDbTester {
   private final DbTester db;
   private final DbClient dbClient;
-  private final DbSession dbSession;
 
   public PropertyDbTester(DbTester db) {
     this.db = db;
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
   }
 
   public PropertyDto insertProperty(PropertyDto property, @Nullable String componentKey,
     @Nullable String componentName, @Nullable String qualifier, @Nullable String userLogin) {
-    dbClient.propertiesDao().saveProperty(dbSession, property, userLogin, componentKey, componentName, qualifier);
+    dbClient.propertiesDao().saveProperty(db.getSession(), property, userLogin, componentKey, componentName, qualifier);
     db.commit();
 
     return property;
@@ -62,9 +60,9 @@ public class PropertyDbTester {
   public void insertProperties(List<PropertyDto> properties, @Nullable String userLogin, @Nullable String projectKey,
     @Nullable String projectName, @Nullable String qualifier) {
     for (PropertyDto propertyDto : properties) {
-      dbClient.propertiesDao().saveProperty(dbSession, propertyDto, userLogin, projectKey, projectName, qualifier);
+      dbClient.propertiesDao().saveProperty(db.getSession(), propertyDto, userLogin, projectKey, projectName, qualifier);
     }
-    dbSession.commit();
+    db.commit();
   }
 
   public void insertProperty(String propKey, String propValue, @Nullable String componentUuid) {
@@ -109,6 +107,6 @@ public class PropertyDbTester {
       .setKey(key)
       .build();
 
-    return dbClient.propertiesDao().selectByQuery(query, dbSession).stream().findFirst();
+    return dbClient.propertiesDao().selectByQuery(query, db.getSession()).stream().findFirst();
   }
 }
index 2da309dde91742b42d6ec6f76f4dfed7e0cb3dda..f721e7104ed08c6244ffad97e3802e28d12eeaef 100644 (file)
@@ -41,21 +41,19 @@ public class QualityGateDbTester {
 
   private final DbTester db;
   private final DbClient dbClient;
-  private final DbSession dbSession;
 
   public QualityGateDbTester(DbTester db) {
     this.db = db;
     this.dbClient = db.getDbClient();
-    this.dbSession = db.getSession();
   }
 
   public QualityGateDto insertBuiltInQualityGate() {
-    QualityGateDto builtin = dbClient.qualityGateDao().insert(dbSession, new QualityGateDto()
+    QualityGateDto builtin = dbClient.qualityGateDao().insert(db.getSession(), new QualityGateDto()
       .setName("Sonar way")
       .setUuid(Uuids.createFast())
       .setBuiltIn(true)
       .setCreatedAt(new Date()));
-    dbSession.commit();
+    db.commit();
     return builtin;
   }
 
@@ -66,13 +64,13 @@ public class QualityGateDbTester {
       .setUuid(Uuids.createFast())
       .setBuiltIn(false);
     Arrays.stream(dtoPopulators).forEach(dtoPopulator -> dtoPopulator.accept(qualityGate));
-    dbClient.qualityGateDao().insert(dbSession, qualityGate);
+    dbClient.qualityGateDao().insert(db.getSession(), qualityGate);
     db.commit();
-    return dbClient.qualityGateDao().selectByUuid(dbSession, qualityGate.getUuid());
+    return dbClient.qualityGateDao().selectByUuid(db.getSession(), qualityGate.getUuid());
   }
 
   public void associateProjectToQualityGate(ProjectDto project, QualityGateDto qualityGate) {
-    dbClient.projectQgateAssociationDao().insertProjectQGateAssociation(dbSession, project.getUuid(), qualityGate.getUuid());
+    dbClient.projectQgateAssociationDao().insertProjectQGateAssociation(db.getSession(), project.getUuid(), qualityGate.getUuid());
     db.commit();
   }
 
@@ -85,7 +83,7 @@ public class QualityGateDbTester {
 
   public void setDefaultQualityGate(QualityGateDto qualityGate) {
     dbClient.propertiesDao().saveProperty(new PropertyDto().setKey(DEFAULT_QUALITY_GATE_PROPERTY_NAME).setValue(qualityGate.getUuid()));
-    dbSession.commit();
+    db.commit();
   }
 
   @SafeVarargs
@@ -96,33 +94,33 @@ public class QualityGateDbTester {
       .setOperator("GT")
       .setErrorThreshold(randomNumeric(10));
     Arrays.stream(dtoPopulators).forEach(dtoPopulator -> dtoPopulator.accept(condition));
-    dbClient.gateConditionDao().insert(condition, dbSession);
+    dbClient.gateConditionDao().insert(condition, db.getSession());
     db.commit();
     return condition;
   }
 
   public Optional<String> selectQGateUuidByProjectUuid(String projectUuid) {
-    return dbClient.projectQgateAssociationDao().selectQGateUuidByProjectUuid(dbSession, projectUuid);
+    return dbClient.projectQgateAssociationDao().selectQGateUuidByProjectUuid(db.getSession(), projectUuid);
   }
 
   public void addGroupPermission(QualityGateDto qualityGateDto, GroupDto group) {
-    dbClient.qualityGateGroupPermissionsDao().insert(dbSession, new QualityGateGroupPermissionsDto()
+    dbClient.qualityGateGroupPermissionsDao().insert(db.getSession(), new QualityGateGroupPermissionsDto()
         .setUuid(Uuids.createFast())
         .setGroupUuid(group.getUuid())
         .setQualityGateUuid(qualityGateDto.getUuid()),
       qualityGateDto.getName(),
       group.getName()
     );
-    dbSession.commit();
+    db.commit();
   }
 
   public void addUserPermission(QualityGateDto qualityGateDto, UserDto user) {
-    dbClient.qualityGateUserPermissionDao().insert(dbSession, new QualityGateUserPermissionsDto()
+    dbClient.qualityGateUserPermissionDao().insert(db.getSession(), new QualityGateUserPermissionsDto()
         .setUuid(Uuids.createFast())
         .setUserUuid(user.getUuid())
         .setQualityGateUuid(qualityGateDto.getUuid()),
       qualityGateDto.getName(),
       user.getLogin());
-    dbSession.commit();
+    db.commit();
   }
 }
index d5110f56132301a4f4acaef61e5aa73d1c469213..0863a4a6de527ea9ad86b594e3bd873615f110bb 100644 (file)
@@ -40,15 +40,15 @@ import static org.sonar.db.qualityprofile.ActiveRuleDto.createFor;
 public class QualityProfileDbTester {
   private final Random random = new SecureRandom();
   private final DbClient dbClient;
-  private final DbSession dbSession;
+  private final DbTester db;
 
   public QualityProfileDbTester(DbTester dbTester) {
     this.dbClient = dbTester.getDbClient();
-    this.dbSession = dbTester.getSession();
+    this.db = dbTester;
   }
 
   public Optional<QProfileDto> selectByUuid(String uuid) {
-    return Optional.ofNullable(dbClient.qualityProfileDao().selectByUuid(dbSession, uuid));
+    return Optional.ofNullable(dbClient.qualityProfileDao().selectByUuid(db.getSession(), uuid));
   }
 
   /**
@@ -67,24 +67,24 @@ public class QualityProfileDbTester {
     QProfileDto profile = QualityProfileTesting.newQualityProfileDto();
     consumer.accept(profile);
 
-    dbClient.qualityProfileDao().insert(dbSession, profile);
-    dbSession.commit();
+    dbClient.qualityProfileDao().insert(db.getSession(), profile);
+    db.commit();
     return profile;
   }
 
   public QualityProfileDbTester insert(QProfileDto profile, QProfileDto... others) {
-    dbClient.qualityProfileDao().insert(dbSession, profile);
-    Arrays.stream(others).forEach(p -> dbClient.qualityProfileDao().insert(dbSession, p));
-    dbSession.commit();
+    dbClient.qualityProfileDao().insert(db.getSession(), profile);
+    Arrays.stream(others).forEach(p -> dbClient.qualityProfileDao().insert(db.getSession(), p));
+    db.commit();
     return this;
   }
 
   public QualityProfileDbTester associateWithProject(ProjectDto project, QProfileDto profile, QProfileDto... otherProfiles) {
-    dbClient.qualityProfileDao().insertProjectProfileAssociation(dbSession, project, profile);
+    dbClient.qualityProfileDao().insertProjectProfileAssociation(db.getSession(), project, profile);
     for (QProfileDto p : otherProfiles) {
-      dbClient.qualityProfileDao().insertProjectProfileAssociation(dbSession, project, p);
+      dbClient.qualityProfileDao().insertProjectProfileAssociation(db.getSession(), project, p);
     }
-    dbSession.commit();
+    db.commit();
     return this;
   }
 
@@ -100,38 +100,38 @@ public class QualityProfileDbTester {
       .setCreatedAt(random.nextLong(Long.MAX_VALUE))
       .setUpdatedAt(random.nextLong(Long.MAX_VALUE));
     consumer.accept(activeRule);
-    dbClient.activeRuleDao().insert(dbSession, activeRule);
-    dbSession.commit();
+    dbClient.activeRuleDao().insert(db.getSession(), activeRule);
+    db.commit();
     return activeRule;
   }
 
   public QualityProfileDbTester setAsDefault(QProfileDto profile, QProfileDto... others) {
-    dbClient.defaultQProfileDao().insertOrUpdate(dbSession, DefaultQProfileDto.from(profile));
+    dbClient.defaultQProfileDao().insertOrUpdate(db.getSession(), DefaultQProfileDto.from(profile));
     for (QProfileDto other : others) {
-      dbClient.defaultQProfileDao().insertOrUpdate(dbSession, DefaultQProfileDto.from(other));
+      dbClient.defaultQProfileDao().insertOrUpdate(db.getSession(), DefaultQProfileDto.from(other));
     }
-    dbSession.commit();
+    db.commit();
     return this;
   }
 
   public void addUserPermission(QProfileDto profile, UserDto user) {
     checkArgument(!profile.isBuiltIn(), "Built-In profile cannot be used");
-    dbClient.qProfileEditUsersDao().insert(dbSession, new QProfileEditUsersDto()
+    dbClient.qProfileEditUsersDao().insert(db.getSession(), new QProfileEditUsersDto()
         .setUuid(Uuids.createFast())
         .setUserUuid(user.getUuid())
         .setQProfileUuid(profile.getKee()),
       profile.getName(), user.getLogin()
     );
-    dbSession.commit();
+    db.commit();
   }
 
   public void addGroupPermission(QProfileDto profile, GroupDto group) {
     checkArgument(!profile.isBuiltIn(), "Built-In profile cannot be used");
-    dbClient.qProfileEditGroupsDao().insert(dbSession, new QProfileEditGroupsDto()
+    dbClient.qProfileEditGroupsDao().insert(db.getSession(), new QProfileEditGroupsDto()
         .setUuid(Uuids.createFast())
         .setGroupUuid(group.getUuid())
         .setQProfileUuid(profile.getKee()),
       profile.getName(), group.getName());
-    dbSession.commit();
+    db.commit();
   }
 }
index 3926b3452ea6fb915091284d4d4c788f2c365de4..06210cfb73fb96493cbfc733201ed87fec29d5b9 100644 (file)
@@ -93,8 +93,6 @@ public class FileSourceTester {
         .setLineHits(RANDOM.nextInt(4))
         .setConditions(RANDOM.nextInt(4))
         .setCoveredConditions(RANDOM.nextInt(4))
-        .setHighlighting(randomAlphanumeric(40))
-        .setSymbols(randomAlphanumeric(30))
         .addAllDuplication(Arrays.asList(RANDOM.nextInt(200), RANDOM.nextInt(200)))
         .build();
     }
index 004b5fd2caada7a8be7d922f8f08a381a098a008..1edb93d4e99fe7732fd6108ff6afdb3e7df0262f 100644 (file)
@@ -69,6 +69,10 @@ public class UserDbTester {
 
   // USERS
 
+  public UserDto insertUserRealistic() {
+    return insertUser(UserTesting.newUserDtoRealistic());
+  }
+
   public UserDto insertUser() {
     return insertUser(UserTesting.newUserDto());
   }
index ae148ef54d87deb80d63db93c46f78fc3cd63950..72ec8b153511786940dc848d64a54c0c38389b43 100644 (file)
 package org.sonar.db.user;
 
 import java.security.SecureRandom;
+import java.util.Collections;
 import java.util.Locale;
 import java.util.Random;
 import javax.annotation.Nullable;
 
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
+import static org.apache.commons.lang.math.RandomUtils.nextBoolean;
+import static org.apache.commons.lang.math.RandomUtils.nextInt;
 import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
 
 public class UserTesting {
 
   private static final Random RANDOM = new SecureRandom();
 
+  private static final String[] realisticIdentityProviders = {"github", "google", "microsoft"};
+
   public static UserDto newUserDto() {
     return new UserDto()
       .setUuid(randomAlphanumeric(40))
@@ -50,6 +55,34 @@ public class UserTesting {
       .setUpdatedAt(RANDOM.nextLong(Long.MAX_VALUE));
   }
 
+  public static UserDto newUserDtoRealistic() {
+    long timeNow = System.currentTimeMillis();
+    String loginAndAndId = randomAlphanumeric(30);
+    String realisticIdentityProvider = realisticIdentityProviders[nextInt(realisticIdentityProviders.length)];
+    boolean isExternal = nextBoolean();
+    String externalIdAndLogin = isExternal ? loginAndAndId + "_" + realisticIdentityProvider : loginAndAndId;
+    return new UserDto().setUuid(randomAlphanumeric(40))
+      .setActive(nextBoolean())
+      .setLocal(!isExternal)
+      .setLogin(loginAndAndId)
+      .setName(loginAndAndId + " " + loginAndAndId)
+      .setEmail(loginAndAndId + "@" + loginAndAndId + ".com")
+      .setScmAccounts(singletonList(loginAndAndId + "@github"))
+      .setExternalId(externalIdAndLogin)
+      .setExternalLogin(externalIdAndLogin)
+      .setExternalIdentityProvider(isExternal ? realisticIdentityProvider : "sonarqube")
+      .setSalt("ZLqSawNE/T7QNk+FLsSWiJ7D9qM=")
+      .setHashMethod("PBKDF2")
+      // password is "admin2"
+      .setCryptedPassword("100000$arHk2+TbNYyFeUgAsDBz7O5M+W0Y3NKJGgvz0KsURHzfXaTXlLT0WYI3DWwXOgHLgyFidVJ4HF22h7zbJoaa8g==")
+      .setCreatedAt(timeNow)
+      .setUpdatedAt(timeNow)
+      .setLastConnectionDate(nextBoolean() ? timeNow : null)
+      .setResetPassword(nextBoolean() && nextBoolean() && nextBoolean())
+      .setHomepageParameter(nextInt(10) + "")
+      .setHomepageType("projects");
+  }
+
   public static UserDto newUserDto(String login, String name, @Nullable String email) {
     return newUserDto()
       .setName(name)
index c1545beb2e1d1e31a4be87df2cd2a25f687f435b..79dd5e2bced97f492e945ffdadc10ed02fad1ec3 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.db.webhook;
 
 import java.util.Optional;
 import javax.annotation.Nullable;
-import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.project.ProjectDto;
 
@@ -45,14 +44,12 @@ public class WebhookDbTester {
   }
 
   public WebhookDto insert(WebhookDto dto, @Nullable String projectKey, @Nullable String projectName) {
-    DbSession dbSession = dbTester.getSession();
-    dbTester.getDbClient().webhookDao().insert(dbSession, dto, projectKey, projectName);
-    dbSession.commit();
+    dbTester.getDbClient().webhookDao().insert(dbTester.getSession(), dto, projectKey, projectName);
+    dbTester.commit();
     return dto;
   }
 
   public Optional<WebhookDto> selectWebhook(String uuid) {
-    DbSession dbSession = dbTester.getSession();
-    return dbTester.getDbClient().webhookDao().selectByUuid(dbSession, uuid);
+    return dbTester.getDbClient().webhookDao().selectByUuid(dbTester.getSession(), uuid);
   }
 }
index f379a2f34d52ed18d303589ce520d9745fb64ed9..3794f2301b7782ab078b7d65cff8a281c7694d55 100644 (file)
@@ -36,7 +36,7 @@ public class WebhookDeliveryDbTester {
 
   public WebhookDeliveryLiteDto insert(WebhookDeliveryDto dto) {
     dbTester.getDbClient().webhookDeliveryDao().insert(dbTester.getSession(), dto);
-    dbTester.getSession().commit();
+    dbTester.commit();
     return dto;
   }
 
@@ -45,7 +45,7 @@ public class WebhookDeliveryDbTester {
     WebhookDeliveryDto dto = newDto();
     stream(dtoPopulators).forEach(dtoPopulator -> dtoPopulator.accept(dto));
     dbTester.getDbClient().webhookDeliveryDao().insert(dbTester.getSession(), dto);
-    dbTester.getSession().commit();
+    dbTester.commit();
     return dto;
   }
 
@@ -57,7 +57,7 @@ public class WebhookDeliveryDbTester {
     dto.setProjectUuid(Objects.requireNonNull(projectUuid, "Project uuid of webhook cannot be null"));
     dto.setWebhookUuid(webhook.getUuid());
     dbTester.getDbClient().webhookDeliveryDao().insert(dbTester.getSession(), dto);
-    dbTester.getSession().commit();
+    dbTester.commit();
     return dto;
   }