From a2663cf617f1b19ff72f5110b27def7d46eb72c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 28 May 2015 15:46:22 +0200 Subject: [PATCH] SONAR-6589 replace usage of ComputationContext.getRoot with TreeRootHolder also, ComponentTree is now computed as a step in BuildComponentTreeStep --- .../computation/ComputationContext.java | 3 +- .../component/ComponentTreeBuilder.java | 3 +- .../component/MutableTreeRootHolder.java | 33 ++++ .../TreeRootHolder.java} | 13 +- .../component/TreeRootHolderImpl.java | 42 +++++ .../container/ComputeEngineContainerImpl.java | 3 + .../step/BuildComponentTreeStep.java | 72 ++++++++ .../computation/step/ComputationSteps.java | 3 + .../computation/step/ParseReportStep.java | 7 +- .../step/PersistComponentsStep.java | 7 +- .../computation/step/PersistTestsStep.java | 15 +- .../PopulateComponentsUuidAndKeyStep.java | 7 +- .../step/QualityProfileEventsStep.java | 22 +-- .../computation/batch/TreeRootHolderRule.java | 61 +++++++ .../component/MutableTreeRootHolderRule.java} | 11 +- .../component/TreeRootHolderImplTest.java | 47 +++++ .../step/BuildComponentTreeStepTest.java | 121 +++++++++++++ .../computation/step/ParseReportStepTest.java | 10 +- .../step/PersistComponentsStepTest.java | 166 +++++++++--------- .../step/PersistTestsStepTest.java | 23 +-- .../PopulateComponentsUuidAndKeyStepTest.java | 43 +++-- .../step/QualityProfileEventsStepTest.java | 89 ++++------ 22 files changed, 599 insertions(+), 202 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/component/MutableTreeRootHolder.java rename server/sonar-server/src/main/java/org/sonar/server/computation/{context/ComputationContext.java => component/TreeRootHolder.java} (76%) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolderImpl.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/batch/TreeRootHolderRule.java rename server/sonar-server/src/{main/java/org/sonar/server/computation/context/package-info.java => test/java/org/sonar/server/computation/component/MutableTreeRootHolderRule.java} (74%) create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/component/TreeRootHolderImplTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java index d6a2c75e3097..27fd4debf360 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java @@ -22,14 +22,13 @@ import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.ComponentTreeBuilder; -public class ComputationContext implements org.sonar.server.computation.context.ComputationContext { +public class ComputationContext { private final Component component; public ComputationContext(ComponentTreeBuilder componentTreeBuilder) { this.component = componentTreeBuilder.build(); } - @Override public Component getRoot() { return component; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentTreeBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentTreeBuilder.java index f2089cf75894..622185d5cc3d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentTreeBuilder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentTreeBuilder.java @@ -21,8 +21,7 @@ public interface ComponentTreeBuilder { /** - * Builds the tree of components for the specified ComputationContext and returns the Component of the root of this - * tree. + * Builds the tree of components and returns the Component of the root of this tree. */ Component build(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/MutableTreeRootHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/MutableTreeRootHolder.java new file mode 100644 index 000000000000..f4873dfc5674 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/MutableTreeRootHolder.java @@ -0,0 +1,33 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.computation.component; + +public interface MutableTreeRootHolder extends TreeRootHolder { + + /** + * Sets the root of the component tree in the TreeRootHolder. Settings a root more than once is allowed but it can + * never be set to {@code null}. + * + * @param newRoot a {@link Component}, can not be {@code null} + * + * @throws NullPointerException if {@code newRoot} is {@code null} + */ + void setRoot(Component newRoot); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolder.java similarity index 76% rename from server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java rename to server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolder.java index 9a0a838ae6cb..4b990fc98451 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolder.java @@ -17,12 +17,13 @@ * 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.server.computation.context; - -import org.sonar.server.computation.component.Component; - -public interface ComputationContext { +package org.sonar.server.computation.component; +public interface TreeRootHolder { + /** + * The root of the tree of Component representing the component in the current BatchReport. + * + * @throws IllegalStateException if the holder is empty (ie. there is no root yet) + */ Component getRoot(); - } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolderImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolderImpl.java new file mode 100644 index 000000000000..1be5c91b1b0a --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/TreeRootHolderImpl.java @@ -0,0 +1,42 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.computation.component; + +import java.util.Objects; + +/** + * Holds the reference to the root of the {@link Component} tree for the current CE run. + */ +public class TreeRootHolderImpl implements MutableTreeRootHolder { + private Component root; + + @Override + public void setRoot(Component newRoot) { + this.root = Objects.requireNonNull(newRoot); + } + + @Override + public Component getRoot() { + if (this.root == null) { + throw new IllegalStateException("Root has not been created yet"); + } + return this.root; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java index a6a62dc8d2f8..1f1f7336c6d2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java @@ -37,6 +37,7 @@ import org.sonar.server.computation.batch.BatchReportReaderImpl; import org.sonar.server.computation.batch.ReportExtractor; import org.sonar.server.computation.component.DbComponentsRefCache; +import org.sonar.server.computation.component.TreeRootHolderImpl; import org.sonar.server.computation.event.EventRepositoryImpl; import org.sonar.server.computation.component.ProjectSettingsRepository; import org.sonar.server.computation.issue.IssueCache; @@ -113,6 +114,8 @@ private static List componentClasses() { ReportExtractor.class, BatchReportReaderImpl.class, + TreeRootHolderImpl.class, + // repositories PlatformLanguageRepository.class, MeasureRepositoryImpl.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java new file mode 100644 index 000000000000..b97b66c095fb --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java @@ -0,0 +1,72 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.computation.step; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import javax.annotation.Nonnull; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.server.computation.ComputationContext; +import org.sonar.server.computation.batch.BatchReportReader; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.ComponentImpl; +import org.sonar.server.computation.component.MutableTreeRootHolder; + +/** + * Populates the {@link MutableTreeRootHolder} from the {@link BatchReportReader} + */ +public class BuildComponentTreeStep implements ComputationStep { + private final BatchReportReader reportReader; + private final MutableTreeRootHolder mutableTreeRootHolder; + + public BuildComponentTreeStep(BatchReportReader reportReader, MutableTreeRootHolder mutableTreeRootHolder) { + this.reportReader = reportReader; + this.mutableTreeRootHolder = mutableTreeRootHolder; + } + + @Override + public void execute(ComputationContext context) { + mutableTreeRootHolder.setRoot(buildComponentRoot()); + } + + private Component buildComponentRoot() { + int rootComponentRef = reportReader.readMetadata().getRootComponentRef(); + BatchReport.Component component = reportReader.readComponent(rootComponentRef); + return new ComponentImpl(component, buildChildren(component)); + } + + private Iterable buildChildren(BatchReport.Component component) { + return Iterables.transform( + component.getChildRefList(), + new Function() { + @Override + public Component apply(@Nonnull Integer componentRef) { + BatchReport.Component component = reportReader.readComponent(componentRef); + return new ComponentImpl(component, buildChildren(component)); + } + } + ); + } + + @Override + public String getDescription() { + return "Builds the Component tree"; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java index 831299548c62..7d409691a779 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java @@ -36,6 +36,9 @@ public class ComputationSteps { */ public List> orderedStepClasses() { return Arrays.asList( + // Builds Component tree + BuildComponentTreeStep.class, + PopulateComponentsUuidAndKeyStep.class, ValidateProjectStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java index 28edc2723447..5bd66a86445d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java @@ -26,22 +26,25 @@ import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor; +import org.sonar.server.computation.component.TreeRootHolder; import org.sonar.server.computation.issue.IssueComputation; public class ParseReportStep implements ComputationStep { private final IssueComputation issueComputation; private final BatchReportReader reportReader; + private final TreeRootHolder treeRootHolder; - public ParseReportStep(IssueComputation issueComputation, BatchReportReader reportReader) { + public ParseReportStep(IssueComputation issueComputation, BatchReportReader reportReader, TreeRootHolder treeRootHolder) { this.issueComputation = issueComputation; this.reportReader = reportReader; + this.treeRootHolder = treeRootHolder; } @Override public void execute(ComputationContext context) { IssueDepthTraversalTypeAwareVisitor visitor = new IssueDepthTraversalTypeAwareVisitor(); - visitor.visit(context.getRoot()); + visitor.visit(treeRootHolder.getRoot()); processDeletedComponents(visitor); issueComputation.afterReportProcessing(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentsStep.java index df2dfad32c9b..1e714fa01663 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistComponentsStep.java @@ -36,6 +36,7 @@ import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DbComponentsRefCache; +import org.sonar.server.computation.component.TreeRootHolder; import org.sonar.server.db.DbClient; public class PersistComponentsStep implements ComputationStep { @@ -43,18 +44,20 @@ public class PersistComponentsStep implements ComputationStep { private final DbClient dbClient; private final DbComponentsRefCache dbComponentsRefCache; private final BatchReportReader reportReader; + private final TreeRootHolder treeRootHolder; - public PersistComponentsStep(DbClient dbClient, DbComponentsRefCache dbComponentsRefCache, BatchReportReader reportReader) { + public PersistComponentsStep(DbClient dbClient, DbComponentsRefCache dbComponentsRefCache, BatchReportReader reportReader, TreeRootHolder treeRootHolder) { this.dbClient = dbClient; this.dbComponentsRefCache = dbComponentsRefCache; this.reportReader = reportReader; + this.treeRootHolder = treeRootHolder; } @Override public void execute(ComputationContext context) { DbSession session = dbClient.openSession(false); try { - Component root = context.getRoot(); + Component root = treeRootHolder.getRoot(); List components = dbClient.componentDao().selectComponentsFromProjectKey(session, root.getKey()); Map componentDtosByKey = componentDtosByKey(components); ComponentContext componentContext = new ComponentContext(session, componentDtosByKey); diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistTestsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistTestsStep.java index 07e9b997c95b..afc350228143 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistTestsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistTestsStep.java @@ -49,6 +49,7 @@ import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DbComponentsRefCache; import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor; +import org.sonar.server.computation.component.TreeRootHolder; import org.sonar.server.db.DbClient; import org.sonar.server.source.db.FileSourceDb; import org.sonar.server.source.db.FileSourceDb.Test.TestStatus; @@ -62,20 +63,22 @@ public class PersistTestsStep implements ComputationStep { private final System2 system; private final DbComponentsRefCache dbComponentsRefCache; private final BatchReportReader reportReader; + private final TreeRootHolder treeRootHolder; - public PersistTestsStep(DbClient dbClient, System2 system, DbComponentsRefCache dbComponentsRefCache, BatchReportReader reportReader) { + public PersistTestsStep(DbClient dbClient, System2 system, DbComponentsRefCache dbComponentsRefCache, BatchReportReader reportReader, TreeRootHolder treeRootHolder) { this.dbClient = dbClient; this.system = system; this.dbComponentsRefCache = dbComponentsRefCache; this.reportReader = reportReader; + this.treeRootHolder = treeRootHolder; } @Override public void execute(final ComputationContext context) { DbSession session = dbClient.openSession(true); try { - TestDepthTraversalTypeAwareVisitor visitor = new TestDepthTraversalTypeAwareVisitor(context, session, dbComponentsRefCache); - visitor.visit(context.getRoot()); + TestDepthTraversalTypeAwareVisitor visitor = new TestDepthTraversalTypeAwareVisitor(session, dbComponentsRefCache); + visitor.visit(treeRootHolder.getRoot()); session.commit(); if (visitor.hasUnprocessedCoverageDetails) { String projectKey = dbComponentsRefCache.getByRef(reportReader.readMetadata().getRootComponentRef()).getKey(); @@ -98,14 +101,14 @@ private class TestDepthTraversalTypeAwareVisitor extends DepthTraversalTypeAware final String projectUuid; boolean hasUnprocessedCoverageDetails = false; - public TestDepthTraversalTypeAwareVisitor(ComputationContext context, DbSession session, DbComponentsRefCache dbComponentsRefCache) { + public TestDepthTraversalTypeAwareVisitor(DbSession session, DbComponentsRefCache dbComponentsRefCache) { super(Component.Type.FILE, Order.PRE_ORDER); this.session = session; this.dbComponentsRefCache = dbComponentsRefCache; this.existingFileSourcesByUuid = new HashMap<>(); - this.projectUuid = context.getRoot().getUuid(); + this.projectUuid = treeRootHolder.getRoot().getUuid(); session.select("org.sonar.core.source.db.FileSourceMapper.selectHashesForProject", - ImmutableMap.of("projectUuid", context.getRoot().getUuid(), "dataType", Type.TEST), + ImmutableMap.of("projectUuid", treeRootHolder.getRoot().getUuid(), "dataType", Type.TEST), new ResultHandler() { @Override public void handleResult(ResultContext context) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PopulateComponentsUuidAndKeyStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PopulateComponentsUuidAndKeyStep.java index cb0f362f0bbb..e67d28f72cb1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PopulateComponentsUuidAndKeyStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PopulateComponentsUuidAndKeyStep.java @@ -33,6 +33,7 @@ import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.ComponentImpl; +import org.sonar.server.computation.component.TreeRootHolder; import org.sonar.server.db.DbClient; /** @@ -42,10 +43,12 @@ public class PopulateComponentsUuidAndKeyStep implements ComputationStep { private final DbClient dbClient; private final BatchReportReader reportReader; + private final TreeRootHolder treeRootHolder; - public PopulateComponentsUuidAndKeyStep(DbClient dbClient, BatchReportReader reportReader) { + public PopulateComponentsUuidAndKeyStep(DbClient dbClient, BatchReportReader reportReader, TreeRootHolder treeRootHolder) { this.dbClient = dbClient; this.reportReader = reportReader; + this.treeRootHolder = treeRootHolder; } @Override @@ -65,7 +68,7 @@ public void execute(ComputationContext context) { ComponentContext componentContext = new ComponentContext(reportReader, componentUuidsByKey, branch); - Component root = context.getRoot(); + Component root = treeRootHolder.getRoot(); processProject(componentContext, root, projectKey); processChildren(componentContext, root, root); session.commit(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java index ab85fb602af7..ffc212081c6d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java @@ -21,6 +21,9 @@ import com.google.common.base.Optional; import com.google.common.collect.ImmutableSortedMap; +import java.util.Date; +import java.util.Map; +import javax.annotation.Nullable; import org.apache.commons.lang.time.DateUtils; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.resources.Language; @@ -31,6 +34,7 @@ import org.sonar.server.computation.ComputationContext; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor; +import org.sonar.server.computation.component.TreeRootHolder; import org.sonar.server.computation.event.Event; import org.sonar.server.computation.event.EventRepository; import org.sonar.server.computation.language.LanguageRepository; @@ -38,19 +42,17 @@ import org.sonar.server.computation.qualityprofile.QPMeasureData; import org.sonar.server.computation.qualityprofile.QualityProfile; -import javax.annotation.Nullable; - -import java.util.Date; -import java.util.Map; - import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER; public class QualityProfileEventsStep implements ComputationStep { + private final TreeRootHolder treeRootHolder; private final MeasureRepository measureRepository; private final EventRepository eventRepository; private final LanguageRepository languageRepository; - public QualityProfileEventsStep(MeasureRepository measureRepository, EventRepository eventRepository, LanguageRepository languageRepository) { + public QualityProfileEventsStep(TreeRootHolder treeRootHolder, + MeasureRepository measureRepository, EventRepository eventRepository, LanguageRepository languageRepository) { + this.treeRootHolder = treeRootHolder; this.measureRepository = measureRepository; this.eventRepository = eventRepository; this.languageRepository = languageRepository; @@ -63,7 +65,7 @@ public void execute(ComputationContext context) { public void visitProject(Component tree) { executeForProject(tree); } - }.visit(context.getRoot()); + }.visit(treeRootHolder.getRoot()); } private void executeForProject(Component projectComponent) { @@ -108,9 +110,9 @@ private void markAsChanged(Component component, QualityProfile previousProfile, Date from = previousProfile.getRulesUpdatedAt(); String data = KeyValueFormat.format(ImmutableSortedMap.of( - "key", profile.getQpKey(), - "from", UtcDateUtils.formatDateTime(fixDate(from)), - "to", UtcDateUtils.formatDateTime(fixDate(profile.getRulesUpdatedAt())))); + "key", profile.getQpKey(), + "from", UtcDateUtils.formatDateTime(fixDate(from)), + "to", UtcDateUtils.formatDateTime(fixDate(profile.getRulesUpdatedAt())))); eventRepository.add(component, createQProfileEvent(component, profile, "Changes in %s", data)); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/batch/TreeRootHolderRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/batch/TreeRootHolderRule.java new file mode 100644 index 000000000000..b3ca3251dddb --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/batch/TreeRootHolderRule.java @@ -0,0 +1,61 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.computation.batch; + +import java.util.Objects; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.TreeRootHolder; + +public class TreeRootHolderRule implements TestRule, TreeRootHolder { + private Component root; + + @Override + public Statement apply(final Statement statement, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + statement.evaluate(); + } finally { + clear(); + } + } + }; + } + + private void clear() { + this.root = null; + } + + @Override + public Component getRoot() { + if (root == null) { + throw new IllegalStateException("Root has not been set in " + TreeRootHolder.class.getSimpleName()); + } + return root; + } + + public void setRoot(Component newRoot) { + this.root = Objects.requireNonNull(newRoot); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java b/server/sonar-server/src/test/java/org/sonar/server/computation/component/MutableTreeRootHolderRule.java similarity index 74% rename from server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java rename to server/sonar-server/src/test/java/org/sonar/server/computation/component/MutableTreeRootHolderRule.java index d15e656106af..eaf2a512a65c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/component/MutableTreeRootHolderRule.java @@ -17,8 +17,13 @@ * 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.server.computation.component; -@ParametersAreNonnullByDefault -package org.sonar.server.computation.context; +import org.sonar.server.computation.batch.TreeRootHolderRule; -import javax.annotation.ParametersAreNonnullByDefault; +public class MutableTreeRootHolderRule extends TreeRootHolderRule implements MutableTreeRootHolder { + @Override + public void setRoot(Component newRoot) { + super.setRoot(newRoot); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/component/TreeRootHolderImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/component/TreeRootHolderImplTest.java new file mode 100644 index 000000000000..1613b765545c --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/component/TreeRootHolderImplTest.java @@ -0,0 +1,47 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.computation.component; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +public class TreeRootHolderImplTest { + + TreeRootHolderImpl treeRootHolder = new TreeRootHolderImpl(); + Component component = mock(Component.class); + + @Test(expected = NullPointerException.class) + public void setRoot_throws_NPE_if_arg_is_null() { + treeRootHolder.setRoot(null); + } + + @Test(expected = IllegalStateException.class) + public void getRoot_throws_ISE_if_root_has_not_been_set_yet() { + treeRootHolder.getRoot(); + } + + @Test + public void verify_setRoot_getRoot() { + treeRootHolder.setRoot(component); + assertThat(treeRootHolder.getRoot()).isSameAs(component); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java new file mode 100644 index 000000000000..60eb895a58ba --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java @@ -0,0 +1,121 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.computation.step; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.batch.protocol.Constants; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReport.Metadata; +import org.sonar.server.computation.ComputationContext; +import org.sonar.server.computation.batch.BatchReportReaderRule; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.MutableTreeRootHolderRule; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.sonar.batch.protocol.Constants.ComponentType.DIRECTORY; +import static org.sonar.batch.protocol.Constants.ComponentType.FILE; +import static org.sonar.batch.protocol.Constants.ComponentType.MODULE; +import static org.sonar.batch.protocol.Constants.ComponentType.PROJECT; + +public class BuildComponentTreeStepTest { + private static final int ROOT_REF = 1; + private static final int MODULE_REF = 2; + private static final int DIR_REF_1 = 3; + private static final int FILE_1_REF = 4; + private static final int FILE_2_REF = 5; + private static final int DIR_REF_2 = 6; + private static final int FILE_3_REF = 7; + + @Rule + public BatchReportReaderRule reportReader = new BatchReportReaderRule(); + @Rule + public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule(); + + private BuildComponentTreeStep underTest = new BuildComponentTreeStep(reportReader, treeRootHolder); + + @Before + public void setUp() throws Exception { + reportReader.setMetadata(Metadata.newBuilder().setRootComponentRef(ROOT_REF).build()); + } + + @Test(expected = NullPointerException.class) + public void fails_if_root_component_does_not_exist_in_reportReader() { + underTest.execute(mock(ComputationContext.class)); + } + + @Test + public void verify_ref_and_type() { + for (Constants.ComponentType componentType : Constants.ComponentType.values()) { + int componentRef = 1; + reportReader.putComponent(component(componentRef, componentType)); + + underTest.execute(mock(ComputationContext.class)); + + Component root = treeRootHolder.getRoot(); + assertThat(root).isNotNull(); + assertThat(root.getType()).isEqualTo(Component.Type.valueOf(componentType.name())); + assertThat(root.getRef()).isEqualTo(ROOT_REF); + assertThat(root.getChildren()).isEmpty(); + } + } + + @Test + public void verify_tree_is_correctly_built() { + reportReader.putComponent(component(ROOT_REF, PROJECT, MODULE_REF)); + reportReader.putComponent(component(MODULE_REF, MODULE, DIR_REF_1, DIR_REF_2)); + reportReader.putComponent(component(DIR_REF_1, DIRECTORY, FILE_1_REF, FILE_2_REF)); + reportReader.putComponent(component(FILE_1_REF, FILE)); + reportReader.putComponent(component(FILE_2_REF, FILE)); + reportReader.putComponent(component(DIR_REF_2, DIRECTORY, FILE_3_REF)); + reportReader.putComponent(component(FILE_3_REF, FILE)); + + underTest.execute(mock(ComputationContext.class)); + + Component root = treeRootHolder.getRoot(); + assertThat(root).isNotNull(); + verifyComponent(root, Component.Type.PROJECT, ROOT_REF, 1); + Component module = root.getChildren().iterator().next(); + verifyComponent(module, Component.Type.MODULE, MODULE_REF, 2); + Component dir1 = module.getChildren().get(0); + verifyComponent(dir1, Component.Type.DIRECTORY, DIR_REF_1, 2); + verifyComponent(dir1.getChildren().get(0), Component.Type.FILE, FILE_1_REF, 0); + verifyComponent(dir1.getChildren().get(1), Component.Type.FILE, FILE_2_REF, 0); + Component dir2 = module.getChildren().get(1); + verifyComponent(dir2, Component.Type.DIRECTORY, DIR_REF_2, 1); + verifyComponent(dir2.getChildren().iterator().next(), Component.Type.FILE, FILE_3_REF, 0); + } + + private void verifyComponent(Component component, Component.Type type, int componentRef, int size) { + assertThat(component.getType()).isEqualTo(type); + assertThat(component.getRef()).isEqualTo(componentRef); + assertThat(component.getChildren()).hasSize(size); + } + + private static BatchReport.Component component(int componentRef, Constants.ComponentType componentType, int... children) { + BatchReport.Component.Builder builder = BatchReport.Component.newBuilder().setType(componentType).setRef(componentRef); + for (int child : children) { + builder.addChildRef(child); + } + return builder.build(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java index abedf2cac875..9e1487fcf789 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ParseReportStepTest.java @@ -32,8 +32,8 @@ import org.sonar.core.persistence.DbTester; import org.sonar.server.computation.ComputationContext; import org.sonar.server.computation.batch.BatchReportReaderRule; +import org.sonar.server.computation.batch.TreeRootHolderRule; import org.sonar.server.computation.component.Component; -import org.sonar.server.computation.component.ComponentTreeBuilders; import org.sonar.server.computation.component.DumbComponent; import org.sonar.server.computation.issue.IssueComputation; @@ -53,12 +53,14 @@ public class ParseReportStepTest extends BaseStepTest { public TemporaryFolder temp = new TemporaryFolder(); @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); @ClassRule public static DbTester dbTester = new DbTester(); IssueComputation issueComputation = mock(IssueComputation.class); - ParseReportStep sut = new ParseReportStep(issueComputation, reportReader); + ParseReportStep sut = new ParseReportStep(issueComputation, reportReader, treeRootHolder); @Test public void extract_report_from_db_and_browse_components() throws Exception { @@ -68,9 +70,9 @@ public void extract_report_from_db_and_browse_components() throws Exception { generateReport(); - ComputationContext context = new ComputationContext(ComponentTreeBuilders.from(root)); + treeRootHolder.setRoot(root); - sut.execute(context); + sut.execute(mock(ComputationContext.class)); assertThat(reportReader.readMetadata().getRootComponentRef()).isEqualTo(1); assertThat(reportReader.readMetadata().getDeletedComponentsCount()).isEqualTo(1); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistComponentsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistComponentsStepTest.java index 332114db14d1..aadd795b9fa8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistComponentsStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistComponentsStepTest.java @@ -35,14 +35,15 @@ import org.sonar.server.component.db.ComponentDao; import org.sonar.server.computation.ComputationContext; import org.sonar.server.computation.batch.BatchReportReaderRule; +import org.sonar.server.computation.batch.TreeRootHolderRule; import org.sonar.server.computation.component.Component; -import org.sonar.server.computation.component.ComponentTreeBuilders; import org.sonar.server.computation.component.DbComponentsRefCache; import org.sonar.server.computation.component.DumbComponent; import org.sonar.server.db.DbClient; import org.sonar.test.DbTests; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; @Category(DbTests.class) public class PersistComponentsStepTest extends BaseStepTest { @@ -53,6 +54,8 @@ public class PersistComponentsStepTest extends BaseStepTest { public static DbTester dbTester = new DbTester(); @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); DbSession session; DbClient dbClient; @@ -67,7 +70,7 @@ public void setup() throws Exception { dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao()); dbComponentsRefCache = new DbComponentsRefCache(); - sut = new PersistComponentsStep(dbClient, dbComponentsRefCache, reportReader); + sut = new PersistComponentsStep(dbClient, dbComponentsRefCache, reportReader, treeRootHolder); } @Override @@ -116,12 +119,11 @@ public void persist_components() throws Exception { .setLanguage("java") .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY", new DumbComponent(Component.Type.DIRECTORY, 3, "CDEF", "MODULE_KEY:src/main/java/dir", - new DumbComponent(Component.Type.FILE, 4, "DEFG", "MODULE_KEY:src/main/java/dir/Foo.java")))); - sut.execute(new ComputationContext( - ComponentTreeBuilders.from(root))); + new DumbComponent(Component.Type.FILE, 4, "DEFG", "MODULE_KEY:src/main/java/dir/Foo.java"))))); + sut.execute(mock(ComputationContext.class)); assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(4); @@ -209,10 +211,10 @@ public void persist_file_directly_attached_on_root_directory() throws Exception .setPath("pom.xml") .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, new DumbComponent(Component.Type.DIRECTORY, 2, "CDEF", PROJECT_KEY + ":/", - new DumbComponent(Component.Type.FILE, 3, "DEFG", PROJECT_KEY + ":pom.xml"))); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + new DumbComponent(Component.Type.FILE, 3, "DEFG", PROJECT_KEY + ":pom.xml")))); + sut.execute(mock(ComputationContext.class)); ComponentDto directory = dbClient.componentDao().selectNullableByKey(session, "PROJECT_KEY:/"); assertThat(directory).isNotNull(); @@ -251,10 +253,10 @@ public void persist_unit_test() throws Exception { .setIsTest(true) .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, new DumbComponent(Component.Type.DIRECTORY, 2, "CDEF", PROJECT_KEY + ":src/test/java/dir", - new DumbComponent(Component.Type.FILE, 3, "DEFG", PROJECT_KEY + ":src/test/java/dir/FooTest.java"))); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + new DumbComponent(Component.Type.FILE, 3, "DEFG", PROJECT_KEY + ":src/test/java/dir/FooTest.java")))); + sut.execute(mock(ComputationContext.class)); ComponentDto file = dbClient.componentDao().selectNullableByKey(session, PROJECT_KEY + ":src/test/java/dir/FooTest.java"); assertThat(file).isNotNull(); @@ -285,29 +287,29 @@ public void persist_only_new_components() throws Exception { .addChildRef(2) .build()); reportReader.putComponent(BatchReport.Component.newBuilder() - .setRef(2) - .setType(Constants.ComponentType.MODULE) - .setKey("MODULE_KEY") - .setName("Module") - .addChildRef(3) - .build()); + .setRef(2) + .setType(Constants.ComponentType.MODULE) + .setKey("MODULE_KEY") + .setName("Module") + .addChildRef(3) + .build()); reportReader.putComponent(BatchReport.Component.newBuilder() - .setRef(3) - .setType(Constants.ComponentType.DIRECTORY) - .setPath("src/main/java/dir") - .addChildRef(4) - .build()); + .setRef(3) + .setType(Constants.ComponentType.DIRECTORY) + .setPath("src/main/java/dir") + .addChildRef(4) + .build()); reportReader.putComponent(BatchReport.Component.newBuilder() - .setRef(4) - .setType(Constants.ComponentType.FILE) - .setPath("src/main/java/dir/Foo.java") - .build()); + .setRef(4) + .setType(Constants.ComponentType.FILE) + .setPath("src/main/java/dir/Foo.java") + .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY", new DumbComponent(Component.Type.DIRECTORY, 3, "CDEF", "MODULE_KEY:src/main/java/dir", - new DumbComponent(Component.Type.FILE, 4, "DEFG", "MODULE_KEY:src/main/java/dir/Foo.java")))); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + new DumbComponent(Component.Type.FILE, 4, "DEFG", "MODULE_KEY:src/main/java/dir/Foo.java"))))); + sut.execute(mock(ComputationContext.class)); assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(4); @@ -378,12 +380,12 @@ public void compute_parent_project_id() throws Exception { .setPath("src/main/java/dir") .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY", new DumbComponent(Component.Type.MODULE, 3, "CDEF", "SUB_MODULE_1_KEY", new DumbComponent(Component.Type.MODULE, 4, "DEFG", "SUB_MODULE_2_KEY", - new DumbComponent(Component.Type.DIRECTORY, 5, "EFGH", "SUB_MODULE_2_KEY:src/main/java/dir"))))); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + new DumbComponent(Component.Type.DIRECTORY, 5, "EFGH", "SUB_MODULE_2_KEY:src/main/java/dir")))))); + sut.execute(mock(ComputationContext.class)); assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(5); @@ -442,11 +444,11 @@ public void persist_multi_modules() throws Exception { .setName("Module B") .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_A", new DumbComponent(Component.Type.MODULE, 3, "DEFG", "SUB_MODULE_A")), - new DumbComponent(Component.Type.MODULE, 4, "CDEF", "MODULE_B")); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + new DumbComponent(Component.Type.MODULE, 4, "CDEF", "MODULE_B"))); + sut.execute(mock(ComputationContext.class)); assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(4); @@ -487,16 +489,16 @@ public void nothing_to_persist() throws Exception { session.commit(); reportReader.setMetadata(BatchReport.Metadata.newBuilder() - .setRootComponentRef(1) - .build()); + .setRootComponentRef(1) + .build()); reportReader.putComponent(BatchReport.Component.newBuilder() - .setRef(1) - .setType(Constants.ComponentType.PROJECT) - .setKey(PROJECT_KEY) - .setName("Project") - .addChildRef(2) - .build()); + .setRef(1) + .setType(Constants.ComponentType.PROJECT) + .setKey(PROJECT_KEY) + .setName("Project") + .addChildRef(2) + .build()); reportReader.putComponent(BatchReport.Component.newBuilder() .setRef(2) .setType(Constants.ComponentType.MODULE) @@ -505,22 +507,22 @@ public void nothing_to_persist() throws Exception { .addChildRef(3) .build()); reportReader.putComponent(BatchReport.Component.newBuilder() - .setRef(3) - .setType(Constants.ComponentType.DIRECTORY) - .setPath("src/main/java/dir") - .addChildRef(4) - .build()); + .setRef(3) + .setType(Constants.ComponentType.DIRECTORY) + .setPath("src/main/java/dir") + .addChildRef(4) + .build()); reportReader.putComponent(BatchReport.Component.newBuilder() - .setRef(4) - .setType(Constants.ComponentType.FILE) - .setPath("src/main/java/dir/Foo.java") - .build()); + .setRef(4) + .setType(Constants.ComponentType.FILE) + .setPath("src/main/java/dir/Foo.java") + .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY", new DumbComponent(Component.Type.DIRECTORY, 3, "CDEF", "MODULE_KEY:src/main/java/dir", - new DumbComponent(Component.Type.FILE, 4, "DEFG", "MODULE_KEY:src/main/java/dir/Foo.java")))); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + new DumbComponent(Component.Type.FILE, 4, "DEFG", "MODULE_KEY:src/main/java/dir/Foo.java"))))); + sut.execute(mock(ComputationContext.class)); assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(4); assertThat(dbClient.componentDao().selectNullableByKey(session, PROJECT_KEY).getId()).isEqualTo(project.getId()); @@ -574,27 +576,27 @@ public void update_module_name() throws Exception { session.commit(); reportReader.setMetadata(BatchReport.Metadata.newBuilder() - .setRootComponentRef(1) - .build()); + .setRootComponentRef(1) + .build()); reportReader.putComponent(BatchReport.Component.newBuilder() - .setRef(1) - .setType(Constants.ComponentType.PROJECT) - .setKey(PROJECT_KEY) - .setName("New project name") - .addChildRef(2) - .build()); + .setRef(1) + .setType(Constants.ComponentType.PROJECT) + .setKey(PROJECT_KEY) + .setName("New project name") + .addChildRef(2) + .build()); reportReader.putComponent(BatchReport.Component.newBuilder() - .setRef(2) - .setType(Constants.ComponentType.MODULE) - .setKey("MODULE_KEY") - .setName("New module name") - .setPath("New path") - .build()); + .setRef(2) + .setType(Constants.ComponentType.MODULE) + .setKey("MODULE_KEY") + .setName("New module name") + .setPath("New path") + .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, - new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY")); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY"))); + sut.execute(mock(ComputationContext.class)); ComponentDto projectReloaded = dbClient.componentDao().selectNullableByKey(session, PROJECT_KEY); assertThat(projectReloaded.name()).isEqualTo("New project name"); @@ -631,9 +633,9 @@ public void update_module_description() throws Exception { .setDescription("New module description") .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, - new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY")); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY"))); + sut.execute(mock(ComputationContext.class)); ComponentDto projectReloaded = dbClient.componentDao().selectNullableByKey(session, PROJECT_KEY); assertThat(projectReloaded.description()).isEqualTo("New project description"); @@ -669,9 +671,9 @@ public void update_module_path() throws Exception { .setPath("New path") .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, - new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY")); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY"))); + sut.execute(mock(ComputationContext.class)); ComponentDto moduleReloaded = dbClient.componentDao().selectNullableByKey(session, "MODULE_KEY"); assertThat(moduleReloaded.path()).isEqualTo("New path"); @@ -727,12 +729,12 @@ public void update_module_uuid_when_moving_a_module() throws Exception { .setPath("src/main/java/dir/Foo.java") .build()); - DumbComponent root = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, new DumbComponent(Component.Type.MODULE, 2, "EDCB", "MODULE_A", new DumbComponent(Component.Type.MODULE, 3, "BCDE", "MODULE_B", new DumbComponent(Component.Type.DIRECTORY, 4, "CDEF", "MODULE_B:src/main/java/dir", - new DumbComponent(Component.Type.FILE, 5, "DEFG", "MODULE_B:src/main/java/dir/Foo.java"))))); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + new DumbComponent(Component.Type.FILE, 5, "DEFG", "MODULE_B:src/main/java/dir/Foo.java")))))); + sut.execute(mock(ComputationContext.class)); assertThat(dbTester.countRowsOfTable("projects")).isEqualTo(5); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistTestsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistTestsStepTest.java index 9b274c7ac05d..66f396d66228 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistTestsStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistTestsStepTest.java @@ -39,8 +39,8 @@ import org.sonar.core.source.db.FileSourceDto; import org.sonar.server.computation.ComputationContext; import org.sonar.server.computation.batch.BatchReportReaderRule; +import org.sonar.server.computation.batch.TreeRootHolderRule; import org.sonar.server.computation.component.Component; -import org.sonar.server.computation.component.ComponentTreeBuilders; import org.sonar.server.computation.component.DbComponentsRefCache; import org.sonar.server.computation.component.DbComponentsRefCache.DbComponent; import org.sonar.server.computation.component.DumbComponent; @@ -69,10 +69,10 @@ public class PersistTestsStepTest extends BaseStepTest { @ClassRule public static DbTester db = new DbTester(); - @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); - + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); @Rule public LogTester log = new LogTester(); @@ -95,7 +95,7 @@ public void setup() throws Exception { when(system2.now()).thenReturn(now); dbComponentsRefCache = new DbComponentsRefCache(); - sut = new PersistTestsStep(dbClient, system2, dbComponentsRefCache, reportReader); + sut = new PersistTestsStep(dbClient, system2, dbComponentsRefCache, reportReader, treeRootHolder); initBasicReport(); @@ -106,6 +106,7 @@ public void setup() throws Exception { new DumbComponent(Component.Type.FILE, 5, MAIN_FILE_UUID_1, "MAIN_FILE1_KEY"), new DumbComponent(Component.Type.FILE, 6, MAIN_FILE_UUID_2, "MAIN_FILE2_KEY") )); + treeRootHolder.setRoot(root); } @After @@ -120,7 +121,7 @@ protected ComputationStep step() { @Test public void no_test_in_database_and_batch_report() { - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + sut.execute(mock(ComputationContext.class)); assertThat(dbClient.fileSourceDao().selectTest(TEST_FILE_UUID_1)).isNull(); assertThat(log.logs()).isEmpty(); @@ -137,7 +138,7 @@ public void insert_several_tests_in_a_report() { ); reportReader.putCoverageDetails(TEST_FILE_REF_1, coverageDetails); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + sut.execute(mock(ComputationContext.class)); assertThat(db.countRowsOfTable("file_sources")).isEqualTo(1); @@ -160,7 +161,7 @@ public void insert_all_data_of_a_test() { reportReader.putTests(TEST_FILE_REF_1, Arrays.asList(newTest(1))); reportReader.putCoverageDetails(TEST_FILE_REF_1, Arrays.asList(newCoverageDetail(1, MAIN_FILE_REF_1))); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + sut.execute(mock(ComputationContext.class)); FileSourceDto dto = dbClient.fileSourceDao().selectTest(TEST_FILE_UUID_1); assertThat(dto.getCreatedAt()).isEqualTo(now); @@ -186,7 +187,7 @@ public void insert_tests_without_coverage_details() { List batchTests = Arrays.asList(newTest(1)); reportReader.putTests(TEST_FILE_REF_1, batchTests); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + sut.execute(mock(ComputationContext.class)); FileSourceDto dto = dbClient.fileSourceDao().selectTest(TEST_FILE_UUID_1); assertThat(dto.getFileUuid()).isEqualTo(TEST_FILE_UUID_1); @@ -204,7 +205,7 @@ public void insert_coverage_details_not_taken_into_account() { reportReader.putCoverageDetails(TEST_FILE_REF_1, coverageDetails); reportReader.putCoverageDetails(TEST_FILE_REF_2, coverageDetails); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + sut.execute(mock(ComputationContext.class)); assertThat(log.logs(LoggerLevel.WARN)).hasSize(1); assertThat(log.logs(LoggerLevel.WARN).get(0)).isEqualTo("Some coverage tests are not taken into account during analysis of project 'PROJECT_KEY'"); @@ -221,7 +222,7 @@ public void aggregate_coverage_details() { newCoverageDetailWithLines(1, MAIN_FILE_REF_1, 1, 3), newCoverageDetailWithLines(1, MAIN_FILE_REF_1, 2, 4))); - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + sut.execute(mock(ComputationContext.class)); FileSourceDto dto = dbClient.fileSourceDao().selectTest(TEST_FILE_UUID_1); List coveredLines = dto.getTestData().get(0).getCoveredFile(0).getCoveredLineList(); @@ -254,7 +255,7 @@ public void update_existing_test() { reportReader.putCoverageDetails(TEST_FILE_REF_1, Arrays.asList(newCoverageDetail)); // ACT - sut.execute(new ComputationContext(ComponentTreeBuilders.from(root))); + sut.execute(mock(ComputationContext.class)); // ASSERT FileSourceDto dto = dbClient.fileSourceDao().selectTest(TEST_FILE_UUID_1); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PopulateComponentsUuidAndKeyStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PopulateComponentsUuidAndKeyStepTest.java index c91f974c6ce8..5196d77db7d6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PopulateComponentsUuidAndKeyStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PopulateComponentsUuidAndKeyStepTest.java @@ -38,12 +38,14 @@ import org.sonar.server.component.db.ComponentDao; import org.sonar.server.computation.ComputationContext; import org.sonar.server.computation.batch.BatchReportReaderRule; +import org.sonar.server.computation.batch.TreeRootHolderRule; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.ComponentTreeBuilders; import org.sonar.server.db.DbClient; import org.sonar.test.DbTests; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; @Category(DbTests.class) public class PopulateComponentsUuidAndKeyStepTest extends BaseStepTest { @@ -54,6 +56,8 @@ public class PopulateComponentsUuidAndKeyStepTest extends BaseStepTest { public static DbTester dbTester = new DbTester(); @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); DbClient dbClient; DbSession session; @@ -66,7 +70,7 @@ public void setup() throws Exception { session = dbTester.myBatis().openSession(false); dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao()); - sut = new PopulateComponentsUuidAndKeyStep(dbClient, reportReader); + sut = new PopulateComponentsUuidAndKeyStep(dbClient, reportReader, treeRootHolder); } @After @@ -109,10 +113,10 @@ public void compute_keys_and_uuids() throws Exception { .setPath("src/main/java/dir/Foo.java") .build()); - ComputationContext context = new ComputationContext(ComponentTreeBuilders.from(reportReader)); - sut.execute(context); + treeRootHolder.setRoot(ComponentTreeBuilders.from(reportReader).build()); + sut.execute(mock(ComputationContext.class)); - Map componentsByRef = getComponentsByRef(context.getRoot()); + Map componentsByRef = getComponentsByRef(treeRootHolder.getRoot()); assertThat(componentsByRef.get(1).getKey()).isEqualTo(PROJECT_KEY); assertThat(componentsByRef.get(1).getUuid()).isNotNull(); @@ -166,10 +170,11 @@ public void return_existing_uuids() throws Exception { .setPath("src/main/java/dir/Foo.java") .build()); - ComputationContext context = new ComputationContext(ComponentTreeBuilders.from(reportReader)); - sut.execute(context); - Map componentsByRef = getComponentsByRef(context.getRoot()); + treeRootHolder.setRoot(ComponentTreeBuilders.from(reportReader).build()); + sut.execute(mock(ComputationContext.class)); + + Map componentsByRef = getComponentsByRef(treeRootHolder.getRoot()); assertThat(componentsByRef.get(1).getKey()).isEqualTo(PROJECT_KEY); assertThat(componentsByRef.get(1).getUuid()).isEqualTo("ABCD"); @@ -223,10 +228,10 @@ public void use_latest_module_for_files_key() throws Exception { .setPath("src/main/java/dir/Foo.java") .build()); - ComputationContext context = new ComputationContext(ComponentTreeBuilders.from(reportReader)); - sut.execute(context); + treeRootHolder.setRoot(ComponentTreeBuilders.from(reportReader).build()); + sut.execute(mock(ComputationContext.class)); - Map componentsByRef = getComponentsByRef(context.getRoot()); + Map componentsByRef = getComponentsByRef(treeRootHolder.getRoot()); assertThat(componentsByRef.get(4).getKey()).isEqualTo("SUB_MODULE_KEY:src/main/java/dir"); assertThat(componentsByRef.get(5).getKey()).isEqualTo("SUB_MODULE_KEY:src/main/java/dir/Foo.java"); @@ -266,10 +271,10 @@ public void use_branch_to_generate_keys() throws Exception { .setPath("src/main/java/dir/Foo.java") .build()); - ComputationContext context = new ComputationContext(ComponentTreeBuilders.from(reportReader)); - sut.execute(context); + treeRootHolder.setRoot(ComponentTreeBuilders.from(reportReader).build()); + sut.execute(mock(ComputationContext.class)); - Map componentsByRef = getComponentsByRef(context.getRoot()); + Map componentsByRef = getComponentsByRef(treeRootHolder.getRoot()); assertThat(componentsByRef.get(1).getKey()).isEqualTo("PROJECT_KEY:origin/master"); assertThat(componentsByRef.get(2).getKey()).isEqualTo("MODULE_KEY:origin/master"); @@ -319,10 +324,10 @@ public void compute_keys_and_uuids_on_project_having_module_and_directory() thro .setPath("pom.xml") .build()); - ComputationContext context = new ComputationContext(ComponentTreeBuilders.from(reportReader)); - sut.execute(context); + treeRootHolder.setRoot(ComponentTreeBuilders.from(reportReader).build()); + sut.execute(mock(ComputationContext.class)); - Map componentsByRef = getComponentsByRef(context.getRoot()); + Map componentsByRef = getComponentsByRef(treeRootHolder.getRoot()); assertThat(componentsByRef.get(1).getKey()).isEqualTo(PROJECT_KEY); assertThat(componentsByRef.get(1).getUuid()).isNotNull(); @@ -379,10 +384,10 @@ public void compute_keys_and_uuids_on_multi_modules() throws Exception { .setPath("src/main/java/dir/Foo.java") .build()); - ComputationContext context = new ComputationContext(ComponentTreeBuilders.from(reportReader)); - sut.execute(context); + treeRootHolder.setRoot(ComponentTreeBuilders.from(reportReader).build()); + sut.execute(mock(ComputationContext.class)); - Map componentsByRef = getComponentsByRef(context.getRoot()); + Map componentsByRef = getComponentsByRef(treeRootHolder.getRoot()); assertThat(componentsByRef.get(1).getKey()).isEqualTo(PROJECT_KEY); assertThat(componentsByRef.get(1).getUuid()).isNotNull(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityProfileEventsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityProfileEventsStepTest.java index 201a6f85e80f..1a54ad06338d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityProfileEventsStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityProfileEventsStepTest.java @@ -27,6 +27,8 @@ import java.util.List; import java.util.Set; import javax.annotation.Nullable; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; @@ -38,8 +40,8 @@ import org.sonar.core.UtcDateUtils; import org.sonar.core.measure.db.MeasureDto; import org.sonar.server.computation.ComputationContext; +import org.sonar.server.computation.batch.TreeRootHolderRule; import org.sonar.server.computation.component.Component; -import org.sonar.server.computation.component.ComponentTreeBuilder; import org.sonar.server.computation.component.DumbComponent; import org.sonar.server.computation.event.Event; import org.sonar.server.computation.event.EventRepository; @@ -61,6 +63,8 @@ import static org.sonar.api.utils.DateUtils.parseDateTime; public class QualityProfileEventsStepTest { + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); private static final String QP_NAME_1 = "qp_1"; private static final String QP_NAME_2 = "qp_2"; @@ -73,36 +77,35 @@ public class QualityProfileEventsStepTest { private EventRepository eventRepository = mock(EventRepository.class); private ArgumentCaptor eventArgumentCaptor = ArgumentCaptor.forClass(Event.class); - private QualityProfileEventsStep underTest = new QualityProfileEventsStep(measureRepository, eventRepository, languageRepository); + private QualityProfileEventsStep underTest = new QualityProfileEventsStep(treeRootHolder, measureRepository, eventRepository, languageRepository); + + @Before + public void setUp() throws Exception { + treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "uuid", "key")); + } @Test public void no_effect_if_no_previous_measure() { - ComputationContext context = newNoChildRootContext(); - - when(measureRepository.findPrevious(context.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.absent()); + when(measureRepository.findPrevious(treeRootHolder.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.absent()); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); verifyNoMoreInteractions(eventRepository); } @Test(expected = IllegalStateException.class) public void ISE_if_no_current_measure() { - ComputationContext context = newNoChildRootContext(); + when(measureRepository.findPrevious(treeRootHolder.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.of(newMeasureDto())); + when(measureRepository.findCurrent(treeRootHolder.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.absent()); - when(measureRepository.findPrevious(context.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.of(newMeasureDto())); - when(measureRepository.findCurrent(context.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.absent()); - - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); } @Test public void no_event_if_no_qp_now_nor_before() { - ComputationContext context = newNoChildRootContext(); - - mockMeasures(context.getRoot(), null, null); + mockMeasures(treeRootHolder.getRoot(), null, null); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); verifyNoMoreInteractions(eventRepository); } @@ -110,14 +113,13 @@ public void no_event_if_no_qp_now_nor_before() { @Test public void added_event_if_one_new_qp() { QualityProfile qp = qp(QP_NAME_1, LANGUAGE_KEY_1); - ComputationContext context = newNoChildRootContext(); Language language = mockLanguageInRepository(LANGUAGE_KEY_1); - mockMeasures(context.getRoot(), null, arrayOf(qp)); + mockMeasures(treeRootHolder.getRoot(), null, arrayOf(qp)); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); - verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture()); + verify(eventRepository).add(eq(treeRootHolder.getRoot()), eventArgumentCaptor.capture()); verifyNoMoreInteractions(eventRepository); verifyEvent(eventArgumentCaptor.getValue(), "Use '" + qp.getQpName() + "' (" + language.getName() + ")", null); } @@ -125,14 +127,13 @@ public void added_event_if_one_new_qp() { @Test public void added_event_uses_language_key_in_message_if_language_not_found() { QualityProfile qp = qp(QP_NAME_1, LANGUAGE_KEY_1); - ComputationContext context = newNoChildRootContext(); mockLanguageNotInRepository(LANGUAGE_KEY_1); - mockMeasures(context.getRoot(), null, arrayOf(qp)); + mockMeasures(treeRootHolder.getRoot(), null, arrayOf(qp)); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); - verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture()); + verify(eventRepository).add(eq(treeRootHolder.getRoot()), eventArgumentCaptor.capture()); verifyNoMoreInteractions(eventRepository); verifyEvent(eventArgumentCaptor.getValue(), "Use '" + qp.getQpName() + "' (" + qp.getLanguageKey() + ")", null); } @@ -140,14 +141,13 @@ public void added_event_uses_language_key_in_message_if_language_not_found() { @Test public void no_more_used_event_if_qp_no_more_listed() { QualityProfile qp = qp(QP_NAME_1, LANGUAGE_KEY_1); - ComputationContext context = newNoChildRootContext(); - mockMeasures(context.getRoot(), arrayOf(qp), null); + mockMeasures(treeRootHolder.getRoot(), arrayOf(qp), null); Language language = mockLanguageInRepository(LANGUAGE_KEY_1); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); - verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture()); + verify(eventRepository).add(eq(treeRootHolder.getRoot()), eventArgumentCaptor.capture()); verifyNoMoreInteractions(eventRepository); verifyEvent(eventArgumentCaptor.getValue(), "Stop using '" + qp.getQpName() + "' (" + language.getName() + ")", null); } @@ -155,14 +155,13 @@ public void no_more_used_event_if_qp_no_more_listed() { @Test public void no_more_used_event_uses_language_key_in_message_if_language_not_found() { QualityProfile qp = qp(QP_NAME_1, LANGUAGE_KEY_1); - ComputationContext context = newNoChildRootContext(); - mockMeasures(context.getRoot(), arrayOf(qp), null); + mockMeasures(treeRootHolder.getRoot(), arrayOf(qp), null); mockLanguageNotInRepository(LANGUAGE_KEY_1); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); - verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture()); + verify(eventRepository).add(eq(treeRootHolder.getRoot()), eventArgumentCaptor.capture()); verifyNoMoreInteractions(eventRepository); verifyEvent(eventArgumentCaptor.getValue(), "Stop using '" + qp.getQpName() + "' (" + qp.getLanguageKey() + ")", null); } @@ -170,11 +169,10 @@ public void no_more_used_event_uses_language_key_in_message_if_language_not_foun @Test public void no_event_if_same_qp_with_same_date() { QualityProfile qp = qp(QP_NAME_1, LANGUAGE_KEY_1); - ComputationContext context = newNoChildRootContext(); - mockMeasures(context.getRoot(), arrayOf(qp), arrayOf(qp)); + mockMeasures(treeRootHolder.getRoot(), arrayOf(qp), arrayOf(qp)); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); verify(eventRepository, never()).add(any(Component.class), any(Event.class)); } @@ -183,14 +181,13 @@ public void no_event_if_same_qp_with_same_date() { public void changed_event_if_same_qp_but_no_same_date() { QualityProfile qp1 = qp(QP_NAME_1, LANGUAGE_KEY_1, parseDateTime("2011-04-25T01:05:13+0100")); QualityProfile qp2 = qp(QP_NAME_1, LANGUAGE_KEY_1, parseDateTime("2011-04-25T01:05:17+0100")); - ComputationContext context = newNoChildRootContext(); - mockMeasures(context.getRoot(), arrayOf(qp1), arrayOf(qp2)); + mockMeasures(treeRootHolder.getRoot(), arrayOf(qp1), arrayOf(qp2)); Language language = mockLanguageInRepository(LANGUAGE_KEY_1); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); - verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture()); + verify(eventRepository).add(eq(treeRootHolder.getRoot()), eventArgumentCaptor.capture()); verifyNoMoreInteractions(eventRepository); verifyEvent(eventArgumentCaptor.getValue(), "Changes in '" + qp2.getQpName() + "' (" + language.getName() + ")", @@ -200,7 +197,6 @@ public void changed_event_if_same_qp_but_no_same_date() { @Test public void verify_detection_with_complex_mix_of_qps() { - ComputationContext context = newNoChildRootContext(); final Set events = new HashSet<>(); doAnswer(new Answer() { @Override @@ -208,10 +204,10 @@ public Object answer(InvocationOnMock invocationOnMock) throws Throwable { events.add((Event) invocationOnMock.getArguments()[1]); return null; } - }).when(eventRepository).add(eq(context.getRoot()), any(Event.class)); + }).when(eventRepository).add(eq(treeRootHolder.getRoot()), any(Event.class)); mockMeasures( - context.getRoot(), arrayOf( + treeRootHolder.getRoot(), arrayOf( qp(QP_NAME_2, LANGUAGE_KEY_1), qp(QP_NAME_2, LANGUAGE_KEY_2), qp(QP_NAME_1, LANGUAGE_KEY_1, parseDateTime("2011-04-25T01:05:13+0100")) @@ -223,7 +219,7 @@ public Object answer(InvocationOnMock invocationOnMock) throws Throwable { )); mockNoLanguageInRepository(); - underTest.execute(context); + underTest.execute(mock(ComputationContext.class)); assertThat(events).extracting("name").containsOnly( "Stop using '" + QP_NAME_2 + "' (" + LANGUAGE_KEY_1 + ")", @@ -292,13 +288,4 @@ private static String toJson(@Nullable QualityProfile... qps) { return QPMeasureData.toJson(new QPMeasureData(qualityProfiles)); } - private ComputationContext newNoChildRootContext() { - return new ComputationContext(new ComponentTreeBuilder() { - @Override - public Component build() { - return new DumbComponent(Component.Type.PROJECT, 1, "uuid", "key"); - } - }); - } - }