From a90049828d6c0dbb8d7b07af6b20d7a8e836a7d8 Mon Sep 17 00:00:00 2001 From: Alain Kermis Date: Wed, 11 Sep 2024 17:10:25 +0200 Subject: [PATCH] SONAR-22649 Create DB populator for creating generated data --- server/sonar-db-dao/build.gradle | 5 + .../src/it/java/org/sonar/db/MyBatisIT.java | 15 +- .../org/sonar/db/ce/CeTaskInputDaoIT.java | 2 - .../notification/NotificationQueueDaoIT.java | 2 - .../java/org/sonar/db/plugin/PluginDaoIT.java | 1 - .../java/org/sonar/db/MyBatisConfBuilder.java | 2 +- .../org/sonar/db/createdb/PopulateDb.java | 455 ++++++++++++++++++ .../java/org/sonar/db/DbTester.java | 45 +- .../org/sonar/db/audit/AuditDbTester.java | 7 +- .../sonar/db/component/ComponentDbTester.java | 67 +-- .../db/component/ProjectLinkDbTester.java | 4 +- .../org/sonar/db/event/EventDbTester.java | 8 +- .../sonar/db/favorite/FavoriteDbTester.java | 12 +- .../org/sonar/db/measure/MeasureDbTester.java | 159 +++++- .../db/notification/NotificationDbTester.java | 8 +- .../template/PermissionTemplateDbTester.java | 18 +- .../org/sonar/db/plugin/PluginDbTester.java | 8 +- .../InternalComponentPropertyDbTester.java | 6 +- .../sonar/db/property/PropertyDbTester.java | 10 +- .../db/qualitygate/QualityGateDbTester.java | 26 +- .../QualityProfileDbTester.java | 40 +- .../org/sonar/db/source/FileSourceTester.java | 2 - .../java/org/sonar/db/user/UserDbTester.java | 4 + .../java/org/sonar/db/user/UserTesting.java | 33 ++ .../org/sonar/db/webhook/WebhookDbTester.java | 9 +- .../db/webhook/WebhookDeliveryDbTester.java | 6 +- 26 files changed, 793 insertions(+), 161 deletions(-) create mode 100644 server/sonar-db-dao/src/test/java/org/sonar/db/createdb/PopulateDb.java diff --git a/server/sonar-db-dao/build.gradle b/server/sonar-db-dao/build.gradle index 527bac05be9..85c4221c4d2 100644 --- a/server/sonar-db-dao/build.gradle +++ b/server/sonar-db-dao/build.gradle @@ -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 diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/MyBatisIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/MyBatisIT.java index c79693bec34..9610a36c11b 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/MyBatisIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/MyBatisIT.java @@ -20,14 +20,12 @@ 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(); } } } diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeTaskInputDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeTaskInputDaoIT.java index 891a945d054..9fa3d59f68b 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeTaskInputDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/ce/CeTaskInputDaoIT.java @@ -76,7 +76,6 @@ class CeTaskInputDaoIT { @Test void selectData_returns_absent_if_uuid_exists_but_data_is_null() { insertData(A_UUID); - dbTester.commit(); Optional 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(); } } diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/notification/NotificationQueueDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/notification/NotificationQueueDaoIT.java index e810d0f10a5..2bcb7f4560c 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/notification/NotificationQueueDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/notification/NotificationQueueDaoIT.java @@ -75,7 +75,6 @@ class NotificationQueueDaoIT { .mapToObj(i -> toNotificationQueueDto(new Notification("foo_" + i))) .collect(toList()); dao.insert(notifs); - db.commit(); List 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) diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/plugin/PluginDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/plugin/PluginDaoIT.java index f6b8496db46..ed48e64d554 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/plugin/PluginDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/plugin/PluginDaoIT.java @@ -111,6 +111,5 @@ class PluginDaoIT { "removed", removed, "created_at", createdAt, "updated_at", updatedAt); - db.commit(); } } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfBuilder.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfBuilder.java index 0bde18cd641..60401c9a4ff 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfBuilder.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatisConfBuilder.java @@ -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 index 00000000000..a43dc4a409b --- /dev/null +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/createdb/PopulateDb.java @@ -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 metricDtosByKey; + final List allProjects; + final List allPortfolios; + final Set 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 createPortfolios(SqContext sqContext, PortfolioGenerationSettings portfolioGenerationSettings) { + List 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 projects, Set rules, Map 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 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 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 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 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 + ); +} diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java index b87dcd2db91..041cf9ffc84 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java @@ -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 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 session = new ThreadLocal<>(); private final UserDbTester userTester; private final ComponentDbTester componentTester; private final ProjectLinkDbTester projectLinkTester; @@ -94,8 +95,9 @@ public class DbTester extends AbstractDbTester 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 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 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 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; diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditDbTester.java index 039ec579da0..466faaa4338 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditDbTester.java @@ -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 selectAll() { - return dbClient.auditDao().selectOlderThan(dbSession, Long.MAX_VALUE); + return dbClient.auditDao().selectOlderThan(db.getSession(), Long.MAX_VALUE); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java index cd8bbb1f5e3..5a31ff436c5 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java @@ -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 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 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 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; } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ProjectLinkDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ProjectLinkDbTester.java index 853997999f4..8e8203c70d2 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ProjectLinkDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ProjectLinkDbTester.java @@ -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... 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; } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/event/EventDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/event/EventDbTester.java index ed57482d95f..d87187e4f9f 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/event/EventDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/event/EventDbTester.java @@ -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; diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/favorite/FavoriteDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/favorite/FavoriteDbTester.java index baad4a6eb5e..26f53bf9e09 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/favorite/FavoriteDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/favorite/FavoriteDbTester.java @@ -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 result = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() .setKey(PROP_FAVORITE_KEY) .setEntityUuid(entity.getUuid()) - .build(), dbSession); + .build(), db.getSession()); return result.isEmpty(); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java index 1c6cf9abcd3..4cff115a957 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java @@ -19,8 +19,14 @@ */ 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... 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... 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... 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... 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... 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... 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... 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 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 populator = specificLiveMeasurePopulator.getOrDefault(metricDto.getKey(), defaultLiveMeasurePopulator); + ProjectMeasureDto measureDto = newProjectMeasureDto(metricDto, projectComponentDto, snapshotDto); + populator.accept(metricDto, new MeasureAdapter(measureDto)); + return measureDto; + } + + private static final Consumer 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> 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 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; + } + } + } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/notification/NotificationDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/notification/NotificationDbTester.java index f0ff519a0a8..3db9b97f1e5 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/notification/NotificationDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/notification/NotificationDbTester.java @@ -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(); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java index 1cc5d189af6..99334c52628 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java @@ -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), diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/plugin/PluginDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/plugin/PluginDbTester.java index 8b3c7f6ad03..8e13b0d233b 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/plugin/PluginDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/plugin/PluginDbTester.java @@ -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... 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; } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/InternalComponentPropertyDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/InternalComponentPropertyDbTester.java index 227179d52bd..f5bb41bc3db 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/InternalComponentPropertyDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/InternalComponentPropertyDbTester.java @@ -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 getProperty(String componentUuid, String key) { - return dbClient.internalComponentPropertiesDao().selectByComponentUuidAndKey(dbSession, componentUuid, key); + return dbClient.internalComponentPropertiesDao().selectByComponentUuidAndKey(db.getSession(), componentUuid, key); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/PropertyDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/PropertyDbTester.java index c0f2ba6336b..38f5755c6e5 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/PropertyDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/property/PropertyDbTester.java @@ -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 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(); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java index 2da309dde91..f721e7104ed 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java @@ -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 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(); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java index d5110f56132..0863a4a6de5 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java @@ -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 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(); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/source/FileSourceTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/source/FileSourceTester.java index 3926b3452ea..06210cfb73f 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/source/FileSourceTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/source/FileSourceTester.java @@ -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(); } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java index 004b5fd2caa..1edb93d4e99 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java @@ -69,6 +69,10 @@ public class UserDbTester { // USERS + public UserDto insertUserRealistic() { + return insertUser(UserTesting.newUserDtoRealistic()); + } + public UserDto insertUser() { return insertUser(UserTesting.newUserDto()); } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserTesting.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserTesting.java index ae148ef54d8..72ec8b15351 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserTesting.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserTesting.java @@ -20,18 +20,23 @@ 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) diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDbTester.java index c1545beb2e1..79dd5e2bced 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDbTester.java @@ -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 selectWebhook(String uuid) { - DbSession dbSession = dbTester.getSession(); - return dbTester.getDbClient().webhookDao().selectByUuid(dbSession, uuid); + return dbTester.getDbClient().webhookDao().selectByUuid(dbTester.getSession(), uuid); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDeliveryDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDeliveryDbTester.java index f379a2f34d5..3794f2301b7 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDeliveryDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/webhook/WebhookDeliveryDbTester.java @@ -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; } -- 2.39.5