diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2015-03-13 21:53:40 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-03-17 12:16:34 +0100 |
commit | 874614a2c6ba28185879abc248748ae087a23b46 (patch) | |
tree | ba9eb832765e8d3a7b3879e581fae2468facbe89 /sonar-batch | |
parent | 7485c34dead228336791067e3a6b03cbb3dcaaa2 (diff) | |
download | sonarqube-874614a2c6ba28185879abc248748ae087a23b46.tar.gz sonarqube-874614a2c6ba28185879abc248748ae087a23b46.zip |
SONAR-6276 SONAR-6288 Feed events and version in analysis report and drop ability to create custom event on batch side
Diffstat (limited to 'sonar-batch')
21 files changed, 248 insertions, 491 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java index 666a6d1a95e..0358d1428f6 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java @@ -27,7 +27,6 @@ import org.sonar.batch.maven.MavenProjectBootstrapper; import org.sonar.batch.maven.MavenProjectBuilder; import org.sonar.batch.maven.MavenProjectConverter; import org.sonar.batch.scan.report.*; -import org.sonar.batch.scan.sensor.VersionEventsSensor; import org.sonar.batch.scm.ScmConfiguration; import org.sonar.batch.scm.ScmSensor; import org.sonar.batch.source.LinesSensor; @@ -60,7 +59,6 @@ public class BatchComponents { ScmSensor.class, LinesSensor.class, - VersionEventsSensor.class, // Issues tracking IssueTracking.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/deprecated/DeprecatedSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/deprecated/DeprecatedSensorContext.java index 0e421a788e0..2a70c13ac9d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/deprecated/DeprecatedSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/deprecated/DeprecatedSensorContext.java @@ -23,7 +23,6 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.batch.AnalysisMode; -import org.sonar.api.batch.Event; import org.sonar.api.batch.SensorContext; import org.sonar.api.batch.SonarIndex; import org.sonar.api.batch.fs.FileSystem; @@ -43,12 +42,8 @@ import org.sonar.api.utils.SonarException; import org.sonar.batch.sensor.DefaultSensorContext; import org.sonar.batch.sensor.coverage.CoverageExclusions; -import javax.annotation.Nullable; - import java.io.Serializable; import java.util.Collection; -import java.util.Date; -import java.util.List; import java.util.Set; public class DeprecatedSensorContext extends DefaultSensorContext implements SensorContext { @@ -234,21 +229,6 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen // useless since 4.2. } - @Override - public List<Event> getEvents(Resource resource) { - return index.getEvents(resource); - } - - @Override - public Event createEvent(Resource resource, String name, String description, String category, @Nullable Date date) { - return index.addEvent(resource, name, description, category, date); - } - - @Override - public void deleteEvent(Event event) { - index.deleteEvent(event); - } - private Resource resourceOrProject(Resource resource) { if (resource == null) { return project; diff --git a/sonar-batch/src/main/java/org/sonar/batch/deprecated/components/PastSnapshotFinderByPreviousVersion.java b/sonar-batch/src/main/java/org/sonar/batch/deprecated/components/PastSnapshotFinderByPreviousVersion.java index fcb0fce8ffb..5b71a2c457d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/deprecated/components/PastSnapshotFinderByPreviousVersion.java +++ b/sonar-batch/src/main/java/org/sonar/batch/deprecated/components/PastSnapshotFinderByPreviousVersion.java @@ -21,42 +21,38 @@ package org.sonar.batch.deprecated.components; import org.sonar.api.BatchExtension; import org.sonar.api.CoreProperties; -import org.sonar.api.batch.Event; import org.sonar.api.database.DatabaseSession; import org.sonar.api.database.model.Snapshot; import org.sonar.batch.components.PastSnapshot; - -import java.util.List; +import org.sonar.core.event.db.EventMapper; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; import static org.sonar.api.utils.DateUtils.longToDate; public class PastSnapshotFinderByPreviousVersion implements BatchExtension { private final DatabaseSession session; + private final MyBatis mybatis; - public PastSnapshotFinderByPreviousVersion(DatabaseSession session) { + public PastSnapshotFinderByPreviousVersion(DatabaseSession session, MyBatis mybatis) { this.session = session; + this.mybatis = mybatis; } public PastSnapshot findByPreviousVersion(Snapshot projectSnapshot) { String currentVersion = projectSnapshot.getVersion(); Integer resourceId = projectSnapshot.getResourceId(); + Long snapshotId; + try (DbSession dbSession = mybatis.openSession(false)) { + snapshotId = dbSession.getMapper(EventMapper.class).findSnapshotIdOfPreviousVersion(resourceId, currentVersion); + } - String hql = "select e from " + Event.class.getSimpleName() + " e " + - " join e.resource component where e.name<>:version AND e.category='Version' AND component.id=:resourceId ORDER BY e.date DESC"; - - List<Event> events = session.createQuery(hql) - .setParameter("version", currentVersion) - .setParameter("resourceId", resourceId) - .setMaxResults(1) - .getResultList(); - - if (events.isEmpty()) { + if (snapshotId == null) { return new PastSnapshot(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION); } - Event previousVersionEvent = events.get(0); - Snapshot snapshot = session.getSingleResult(Snapshot.class, "id", previousVersionEvent.getSnapshot().getId()); + Snapshot snapshot = session.getSingleResult(Snapshot.class, "id", snapshotId.intValue()); return new PastSnapshot(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, longToDate(snapshot.getCreatedAtMs()), snapshot).setModeParameter(snapshot.getVersion()); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/deprecated/decorator/DefaultDecoratorContext.java b/sonar-batch/src/main/java/org/sonar/batch/deprecated/decorator/DefaultDecoratorContext.java index 67bd33d7a29..47d75f4434d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/deprecated/decorator/DefaultDecoratorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/deprecated/decorator/DefaultDecoratorContext.java @@ -23,16 +23,10 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.Event; import org.sonar.api.batch.SonarIndex; import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; import org.sonar.api.design.Dependency; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasuresFilter; -import org.sonar.api.measures.MeasuresFilters; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.MetricFinder; +import org.sonar.api.measures.*; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.rules.Violation; @@ -44,7 +38,6 @@ import org.sonar.batch.sensor.coverage.CoverageExclusions; import java.util.Arrays; import java.util.Collection; -import java.util.Date; import java.util.List; import java.util.Set; @@ -223,21 +216,6 @@ public class DefaultDecoratorContext implements DecoratorContext { } @Override - public List<Event> getEvents() { - return sonarIndex.getEvents(resource); - } - - @Override - public Event createEvent(String name, String description, String category, Date date) { - return sonarIndex.addEvent(resource, name, description, category, date); - } - - @Override - public void deleteEvent(Event event) { - sonarIndex.deleteEvent(event); - } - - @Override public DefaultDecoratorContext saveViolation(Violation violation, boolean force) { if (violation.getResource() == null) { violation.setResource(resource); diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java index d2f26e4cecf..ff223b4b9f4 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java @@ -28,7 +28,6 @@ import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.batch.Event; import org.sonar.api.batch.SonarIndex; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.measure.Metric; @@ -90,7 +89,6 @@ public class DefaultIndex extends SonarIndex { private final MeasureCache measureCache; private final ResourceKeyMigration migration; private final DependencyPersister dependencyPersister; - private final EventPersister eventPersister; // caches private Project currentProject; private Map<Resource, Bucket> buckets = Maps.newLinkedHashMap(); @@ -101,11 +99,10 @@ public class DefaultIndex extends SonarIndex { private ModuleIssues moduleIssues; public DefaultIndex(ResourceCache resourceCache, DependencyPersister dependencyPersister, - EventPersister eventPersister, ProjectTree projectTree, MetricFinder metricFinder, + ProjectTree projectTree, MetricFinder metricFinder, ResourceKeyMigration migration, MeasureCache measureCache) { this.resourceCache = resourceCache; this.dependencyPersister = dependencyPersister; - this.eventPersister = eventPersister; this.projectTree = projectTree; this.metricFinder = metricFinder; this.migration = migration; @@ -115,7 +112,6 @@ public class DefaultIndex extends SonarIndex { public DefaultIndex(ResourceCache resourceCache, DependencyPersister dependencyPersister, ProjectTree projectTree, MetricFinder metricFinder, MeasureCache measureCache) { this.resourceCache = resourceCache; this.dependencyPersister = dependencyPersister; - this.eventPersister = null; this.projectTree = projectTree; this.metricFinder = metricFinder; this.migration = null; @@ -407,47 +403,6 @@ public class DefaultIndex extends SonarIndex { moduleIssues.initAndAddViolation(violation); } - // - // - // - // EVENTS - // - // - // - - @Override - public List<Event> getEvents(Resource resource) { - // currently events are not cached in memory - Resource reload = getResource(resource); - if (reload == null) { - return Collections.emptyList(); - } - if (eventPersister == null) { - throw new UnsupportedOperationException("Event are not available in preview mode"); - } - return eventPersister.getEvents(reload); - } - - @Override - public void deleteEvent(Event event) { - if (eventPersister != null) { - eventPersister.deleteEvent(event); - } - } - - @Override - public Event addEvent(Resource resource, String name, String description, String category, @Nullable Date date) { - Event event = new Event(name, description, category); - if (date != null) { - event.setDate(date); - } - - if (eventPersister != null) { - eventPersister.saveEvent(resource, event); - } - return null; - } - @Override public String getSource(Resource reference) { Resource resource = getResource(reference); diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/EventPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/EventPersister.java deleted file mode 100644 index 3b68e8cda48..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/index/EventPersister.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.batch.index; - -import org.sonar.api.batch.Event; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.resources.Resource; -import org.sonar.api.utils.System2; - -import java.util.Date; -import java.util.List; - -import static com.google.common.base.Preconditions.checkState; - -public class EventPersister { - private final System2 system2; - private DatabaseSession session; - private ResourceCache resourceCache; - - public EventPersister(DatabaseSession session, ResourceCache resourceCache, System2 system2) { - this.session = session; - this.resourceCache = resourceCache; - this.system2 = system2; - } - - public List<Event> getEvents(Resource resource) { - return session.getResults(Event.class, "componentUuid", resource.getUuid()); - } - - public void deleteEvent(Event event) { - session.removeWithoutFlush(event); - session.commit(); - } - - public void saveEvent(Resource resource, Event event) { - BatchResource batchResource = resourceCache.get(resource.getEffectiveKey()); - checkState(batchResource != null, "Unknown component: " + resource); - - event.setCreatedAt(new Date(system2.now())); - if (event.getDate() == null) { - event.setSnapshot(batchResource.snapshot()); - event.setComponentUuid(batchResource.resource().getUuid()); - } else { - event.setComponentUuid(batchResource.resource().getUuid()); - } - - session.save(event); - session.commit(); - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/qualitygate/GenerateQualityGateEvents.java b/sonar-batch/src/main/java/org/sonar/batch/qualitygate/GenerateQualityGateEvents.java index 824610b5d01..ee3f9f34a76 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/qualitygate/GenerateQualityGateEvents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/qualitygate/GenerateQualityGateEvents.java @@ -29,6 +29,8 @@ import org.sonar.api.notifications.NotificationManager; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; +import org.sonar.batch.protocol.Constants.EventCategory; +import org.sonar.batch.report.EventCache; import java.util.List; @@ -36,12 +38,14 @@ public class GenerateQualityGateEvents implements Decorator { private final QualityGate qualityGate; private final TimeMachine timeMachine; - private NotificationManager notificationManager; + private final NotificationManager notificationManager; + private final EventCache eventCache; - public GenerateQualityGateEvents(QualityGate qualityGate, TimeMachine timeMachine, NotificationManager notificationManager) { + public GenerateQualityGateEvents(QualityGate qualityGate, TimeMachine timeMachine, NotificationManager notificationManager, EventCache eventCache) { this.qualityGate = qualityGate; this.timeMachine = timeMachine; this.notificationManager = notificationManager; + this.eventCache = eventCache; } @Override @@ -122,6 +126,6 @@ public class GenerateQualityGateEvents implements Decorator { } private void createEvent(DecoratorContext context, String name, String description) { - context.createEvent(name, description, Event.CATEGORY_ALERT, null); + eventCache.createEvent(context.getResource(), name, description, EventCategory.ALERT, null); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java index 4f93d6fbcaf..506a7f23765 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java @@ -30,9 +30,10 @@ import org.sonar.batch.index.BatchResource; import org.sonar.batch.index.ResourceCache; import org.sonar.batch.protocol.Constants; import org.sonar.batch.protocol.Constants.ComponentLinkType; -import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.*; +import org.sonar.batch.protocol.output.BatchReport.Component.Builder; import org.sonar.batch.protocol.output.BatchReport.ComponentLink; -import org.sonar.batch.protocol.output.BatchReportWriter; +import org.sonar.batch.protocol.output.BatchReport.Event; import javax.annotation.CheckForNull; @@ -43,10 +44,12 @@ public class ComponentsPublisher implements ReportPublisher { private final ResourceCache resourceCache; private final ProjectReactor reactor; + private final EventCache eventCache; - public ComponentsPublisher(ProjectReactor reactor, ResourceCache resourceCache) { + public ComponentsPublisher(ProjectReactor reactor, ResourceCache resourceCache, EventCache eventCache) { this.reactor = reactor; this.resourceCache = resourceCache; + this.eventCache = eventCache; } @Override @@ -91,6 +94,38 @@ public class ComponentsPublisher implements ReportPublisher { for (BatchResource child : batchResource.children()) { builder.addChildRef(child.batchId()); } + writeLinks(r, builder); + writeVersion(r, builder); + writeEvents(batchResource, builder); + writer.writeComponent(builder.build()); + + for (BatchResource child : batchResource.children()) { + recursiveWriteComponent(child, writer); + } + } + + private void writeEvents(BatchResource batchResource, Builder builder) { + if (isRealProjectOrModule(batchResource.resource())) { + for (Event event : eventCache.getEvents(batchResource.batchId())) { + builder.addEvent(event); + } + } + } + + private void writeVersion(Resource r, BatchReport.Component.Builder builder) { + if (isRealProjectOrModule(r)) { + ProjectDefinition def = getProjectDefinition(reactor, r.getKey()); + String version = getVersion(def); + builder.setVersion(version); + } + } + + private String getVersion(ProjectDefinition def) { + String version = def.getVersion(); + return StringUtils.isNotBlank(version) ? version : getVersion(def.getParent()); + } + + private void writeLinks(Resource r, BatchReport.Component.Builder builder) { if (isRealProjectOrModule(r)) { ProjectDefinition def = getProjectDefinition(reactor, r.getKey()); ComponentLink.Builder linkBuilder = ComponentLink.newBuilder(); @@ -101,11 +136,6 @@ public class ComponentsPublisher implements ReportPublisher { writeProjectLink(builder, def, linkBuilder, CoreProperties.LINKS_SOURCES, ComponentLinkType.SCM); writeProjectLink(builder, def, linkBuilder, CoreProperties.LINKS_SOURCES_DEV, ComponentLinkType.SCM_DEV); } - writer.writeComponent(builder.build()); - - for (BatchResource child : batchResource.children()) { - recursiveWriteComponent(child, writer); - } } // Exclude views diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/EventCache.java b/sonar-batch/src/main/java/org/sonar/batch/report/EventCache.java new file mode 100644 index 00000000000..2cb2814d2ee --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/report/EventCache.java @@ -0,0 +1,67 @@ +/* + * 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.batch.report; + +import org.sonar.api.BatchComponent; +import org.sonar.api.resources.Resource; +import org.sonar.batch.index.ResourceCache; +import org.sonar.batch.protocol.Constants.EventCategory; +import org.sonar.batch.protocol.output.BatchReport.Event; + +import javax.annotation.Nullable; + +import java.util.*; + +public class EventCache implements BatchComponent { + + private final Map<Integer, List<Event>> eventsByComponentBatchId = new HashMap<>(); + private final ResourceCache resourceCache; + + public EventCache(ResourceCache resourceCache) { + this.resourceCache = resourceCache; + } + + public void createEvent(Resource resource, String name, String description, EventCategory category, @Nullable String data) { + org.sonar.batch.protocol.output.BatchReport.Event.Builder eventBuilder = org.sonar.batch.protocol.output.BatchReport.Event.newBuilder(); + eventBuilder.setName(name); + eventBuilder.setDescription(description); + eventBuilder.setCategory(category); + if (data != null) { + eventBuilder.setEventData(data); + } + int componentBatchId = resourceCache.get(resource).batchId(); + eventBuilder.setComponentRef(componentBatchId); + addEvent(componentBatchId, eventBuilder.build()); + } + + private void addEvent(int componentBatchId, Event e) { + if (!eventsByComponentBatchId.containsKey(componentBatchId)) { + eventsByComponentBatchId.put(componentBatchId, new ArrayList<Event>()); + } + eventsByComponentBatchId.get(componentBatchId).add(e); + } + + public List<Event> getEvents(int componentBatchId) { + if (eventsByComponentBatchId.containsKey(componentBatchId)) { + return eventsByComponentBatchId.get(componentBatchId); + } + return Collections.emptyList(); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java index f3d7bffc035..4ebc91e489b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java +++ b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileEventsDecorator.java @@ -21,22 +21,14 @@ package org.sonar.batch.rule; import com.google.common.collect.ImmutableSortedMap; import org.apache.commons.lang.time.DateUtils; -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.batch.Event; -import org.sonar.api.batch.TimeMachine; -import org.sonar.api.batch.TimeMachineQuery; +import org.sonar.api.batch.*; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Language; -import org.sonar.api.resources.Languages; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; +import org.sonar.api.resources.*; import org.sonar.api.utils.KeyValueFormat; -import org.sonar.batch.index.EventPersister; +import org.sonar.batch.protocol.Constants.EventCategory; +import org.sonar.batch.report.EventCache; import org.sonar.core.UtcDateUtils; import javax.annotation.CheckForNull; @@ -49,12 +41,12 @@ public class QProfileEventsDecorator implements Decorator { private final TimeMachine timeMachine; private final Languages languages; - private final EventPersister eventPersister; + private final EventCache eventCache; - public QProfileEventsDecorator(TimeMachine timeMachine, Languages languages, EventPersister eventPersister) { + public QProfileEventsDecorator(TimeMachine timeMachine, Languages languages, EventCache eventCache) { this.timeMachine = timeMachine; this.languages = languages; - this.eventPersister = eventPersister; + this.eventCache = eventCache; } @DependsUpon @@ -112,18 +104,13 @@ public class QProfileEventsDecorator implements Decorator { } private void markAsChanged(DecoratorContext context, QProfile previousProfile, QProfile profile) { - // DecoratorContext does not allow to set event data, so SonarIndex must be used - Event event = new Event(); - event.setName(String.format("Changes in %s", profileLabel(profile))); - event.setCategory(Event.CATEGORY_PROFILE); Date from = previousProfile.getRulesUpdatedAt(); String data = KeyValueFormat.format(ImmutableSortedMap.of( "key", profile.getKey(), "from", UtcDateUtils.formatDateTime(fixDate(from)), "to", UtcDateUtils.formatDateTime(fixDate(profile.getRulesUpdatedAt())))); - event.setData(data); - eventPersister.saveEvent(context.getResource(), event); + eventCache.createEvent(context.getResource(), String.format("Changes in %s", profileLabel(profile)), null, EventCategory.PROFILE, data); } /** @@ -134,11 +121,11 @@ public class QProfileEventsDecorator implements Decorator { } private void markAsRemoved(DecoratorContext context, QProfile profile) { - context.createEvent(String.format("Stop using %s", profileLabel(profile)), null, Event.CATEGORY_PROFILE, null); + eventCache.createEvent(context.getResource(), String.format("Stop using %s", profileLabel(profile)), null, EventCategory.PROFILE, null); } private void markAsAdded(DecoratorContext context, QProfile profile) { - context.createEvent(String.format("Use %s", profileLabel(profile)), null, Event.CATEGORY_PROFILE, null); + eventCache.createEvent(context.getResource(), String.format("Use %s", profileLabel(profile)), null, EventCategory.PROFILE, null); } @CheckForNull diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java index 2e7a68eb8da..a092c3a9f36 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java @@ -54,7 +54,6 @@ import org.sonar.batch.issue.tracking.IssueTrackingDecorator; import org.sonar.batch.language.LanguageDistributionDecorator; import org.sonar.batch.phases.*; import org.sonar.batch.qualitygate.GenerateQualityGateEvents; -import org.sonar.batch.qualitygate.QualityGateProvider; import org.sonar.batch.qualitygate.QualityGateVerifier; import org.sonar.batch.report.ComponentsPublisher; import org.sonar.batch.report.IssuesPublisher; @@ -179,8 +178,7 @@ public class ModuleScanContainer extends ComponentContainer { private void addDataBaseComponents() { add(DecoratorsExecutor.class, - // quality gates - new QualityGateProvider(), + // Quality Gate QualityGateVerifier.class, GenerateQualityGateEvents.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index 89b5aed9596..8c4f5e6272d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -50,6 +50,8 @@ import org.sonar.batch.issue.tracking.ServerIssueRepository; import org.sonar.batch.mediumtest.ScanTaskObservers; import org.sonar.batch.phases.GraphPersister; import org.sonar.batch.profiling.PhasesSumUpTimeProfiler; +import org.sonar.batch.qualitygate.QualityGateProvider; +import org.sonar.batch.report.EventCache; import org.sonar.batch.repository.ProjectRepositoriesProvider; import org.sonar.batch.repository.ProjectScmRepositoryLoader; import org.sonar.batch.repository.language.DefaultLanguagesRepository; @@ -177,6 +179,12 @@ public class ProjectScanContainer extends ComponentContainer { DependencyPersister.class, DependencyCache.class, + // Quality Gate + new QualityGateProvider(), + + // Events + EventCache.class, + ProjectSettings.class, ScanTaskObservers.class); @@ -184,7 +192,6 @@ public class ProjectScanContainer extends ComponentContainer { private void addDataBaseComponents() { add( - EventPersister.class, MeasurePersister.class, DuplicationPersister.class, ResourcePersister.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/sensor/VersionEventsSensor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/sensor/VersionEventsSensor.java deleted file mode 100644 index 351eca3facd..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/sensor/VersionEventsSensor.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.batch.scan.sensor; - -import org.apache.commons.lang.StringUtils; -import org.sonar.api.batch.AnalysisMode; -import org.sonar.api.batch.Event; -import org.sonar.api.batch.RequiresDB; -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; - -import java.util.Iterator; - -@RequiresDB -public class VersionEventsSensor implements Sensor { - - private final AnalysisMode analysisMode; - - public VersionEventsSensor(AnalysisMode analysisMode) { - this.analysisMode = analysisMode; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return !analysisMode.isPreview(); - } - - @Override - public void analyse(Project project, SensorContext context) { - if (StringUtils.isBlank(project.getAnalysisVersion())) { - return; - } - deleteDeprecatedEvents(project, context); - context.createEvent(project, project.getAnalysisVersion(), null, Event.CATEGORY_VERSION, null); - } - - private void deleteDeprecatedEvents(Project project, SensorContext context) { - String version = project.getAnalysisVersion(); - for (Iterator<Event> it = context.getEvents(project).iterator(); it.hasNext();) { - Event event = it.next(); - if (event.isVersionCategory() && version.equals(event.getName())) { - it.remove(); - context.deleteEvent(event); - } - } - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/sensor/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/scan/sensor/package-info.java deleted file mode 100644 index b8fb1b58126..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/sensor/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - */ -@ParametersAreNonnullByDefault -package org.sonar.batch.scan.sensor; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-batch/src/test/java/org/sonar/batch/deprecated/components/PastSnapshotFinderByPreviousVersionTest.java b/sonar-batch/src/test/java/org/sonar/batch/deprecated/components/PastSnapshotFinderByPreviousVersionTest.java index d932060914a..83c8b98a8b9 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/deprecated/components/PastSnapshotFinderByPreviousVersionTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/deprecated/components/PastSnapshotFinderByPreviousVersionTest.java @@ -19,21 +19,27 @@ */ package org.sonar.batch.deprecated.components; -import org.sonar.batch.components.PastSnapshot; - -import org.sonar.batch.deprecated.components.PastSnapshotFinderByPreviousVersion; +import org.junit.Before; import org.junit.Test; import org.sonar.api.CoreProperties; import org.sonar.api.database.model.Snapshot; +import org.sonar.batch.components.PastSnapshot; import org.sonar.jpa.test.AbstractDbUnitTestCase; + import static org.assertj.core.api.Assertions.assertThat; public class PastSnapshotFinderByPreviousVersionTest extends AbstractDbUnitTestCase { + private PastSnapshotFinderByPreviousVersion finder; + + @Before + public void before() throws Exception { + finder = new PastSnapshotFinderByPreviousVersion(getSession(), getMyBatis()); + } + @Test public void shouldFindByPreviousVersion() { setupData("with-previous-version"); - PastSnapshotFinderByPreviousVersion finder = new PastSnapshotFinderByPreviousVersion(getSession()); Snapshot currentProjectSnapshot = getSession().getSingleResult(Snapshot.class, "id", 1003); PastSnapshot foundSnapshot = finder.findByPreviousVersion(currentProjectSnapshot); @@ -45,7 +51,6 @@ public class PastSnapshotFinderByPreviousVersionTest extends AbstractDbUnitTestC @Test public void shouldFindByPreviousVersionWhenPreviousVersionDeleted() { setupData("with-previous-version-deleted"); - PastSnapshotFinderByPreviousVersion finder = new PastSnapshotFinderByPreviousVersion(getSession()); Snapshot currentProjectSnapshot = getSession().getSingleResult(Snapshot.class, "id", 1003); PastSnapshot foundSnapshot = finder.findByPreviousVersion(currentProjectSnapshot); @@ -57,7 +62,6 @@ public class PastSnapshotFinderByPreviousVersionTest extends AbstractDbUnitTestC @Test public void testWithNoPreviousVersion() { setupData("no-previous-version"); - PastSnapshotFinderByPreviousVersion finder = new PastSnapshotFinderByPreviousVersion(getSession()); Snapshot currentProjectSnapshot = getSession().getSingleResult(Snapshot.class, "id", 1003); PastSnapshot foundSnapshot = finder.findByPreviousVersion(currentProjectSnapshot); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java index 0c62cc64ac4..908a8194c93 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java @@ -65,7 +65,7 @@ public class DefaultIndexTest { ProjectTree projectTree = mock(ProjectTree.class); ResourceCache resourceCache = new ResourceCache(); - index = new DefaultIndex(resourceCache, null, null, projectTree, metricFinder, + index = new DefaultIndex(resourceCache, null, projectTree, metricFinder, mock(ResourceKeyMigration.class), mock(MeasureCache.class)); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java index 92299c87f20..0d9be3369a4 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java @@ -221,7 +221,7 @@ public class ResourcePersisterTest extends AbstractDbUnitTestCase { when(projectTree.getProjectDefinition(moduleB)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB"))); when(projectTree.getProjectDefinition(moduleB1)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB/moduleB1"))); - DefaultIndex index = new DefaultIndex(resourceCache, null, null, projectTree, mock(MetricFinder.class), + DefaultIndex index = new DefaultIndex(resourceCache, null, projectTree, mock(MetricFinder.class), mock(ResourceKeyMigration.class), mock(MeasureCache.class)); diff --git a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/GenerateQualityGateEventsTest.java b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/GenerateQualityGateEventsTest.java index e7e2c332838..0385d0796ae 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/GenerateQualityGateEventsTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/GenerateQualityGateEventsTest.java @@ -22,7 +22,6 @@ package org.sonar.batch.qualitygate; import org.junit.Before; import org.junit.Test; import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.Event; import org.sonar.api.batch.TimeMachine; import org.sonar.api.batch.TimeMachineQuery; import org.sonar.api.measures.CoreMetrics; @@ -32,21 +31,18 @@ import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationManager; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; import org.sonar.api.test.ProjectTestBuilder; +import org.sonar.batch.protocol.Constants.EventCategory; +import org.sonar.batch.report.EventCache; import java.util.Arrays; -import java.util.Date; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; public class GenerateQualityGateEventsTest { private GenerateQualityGateEvents decorator; @@ -55,6 +51,7 @@ public class GenerateQualityGateEventsTest { private TimeMachine timeMachine; private NotificationManager notificationManager; private Project project; + private EventCache eventCache; @Before public void setup() { @@ -62,8 +59,10 @@ public class GenerateQualityGateEventsTest { timeMachine = mock(TimeMachine.class); qualityGate = mock(QualityGate.class); notificationManager = mock(NotificationManager.class); - decorator = new GenerateQualityGateEvents(qualityGate, timeMachine, notificationManager); + eventCache = mock(EventCache.class); + decorator = new GenerateQualityGateEvents(qualityGate, timeMachine, notificationManager, eventCache); project = new ProjectTestBuilder().build(); + when(context.getResource()).thenReturn(project); } @Test @@ -85,7 +84,7 @@ public class GenerateQualityGateEventsTest { @Test public void shouldNotDecorateIfNotRootProject() { decorator.decorate(File.create("Foo"), context); - verify(context, never()).createEvent(anyString(), anyString(), anyString(), (Date) isNull()); + verify(eventCache, never()).createEvent(any(Resource.class), anyString(), anyString(), any(EventCategory.class), anyString()); } @Test @@ -94,7 +93,7 @@ public class GenerateQualityGateEventsTest { decorator.decorate(project, context); - verify(context).createEvent(Metric.Level.ERROR.getColorName(), "desc", Event.CATEGORY_ALERT, null); + verify(eventCache).createEvent(project, Metric.Level.ERROR.getColorName(), "desc", EventCategory.ALERT, null); verifyNotificationSent("Red", "desc", "ERROR", "true"); } @@ -104,7 +103,7 @@ public class GenerateQualityGateEventsTest { decorator.decorate(project, context); - verify(context).createEvent(Metric.Level.WARN.getColorName(), "desc", Event.CATEGORY_ALERT, null); + verify(eventCache).createEvent(project, Metric.Level.WARN.getColorName(), "desc", EventCategory.ALERT, null); verifyNotificationSent("Orange", "desc", "WARN", "true"); } @@ -115,7 +114,7 @@ public class GenerateQualityGateEventsTest { decorator.decorate(project, context); - verify(context).createEvent("Red (was Orange)", "desc", Event.CATEGORY_ALERT, null); + verify(eventCache).createEvent(project, "Red (was Orange)", "desc", EventCategory.ALERT, null); verifyNotificationSent("Red (was Orange)", "desc", "ERROR", "false"); } @@ -126,7 +125,7 @@ public class GenerateQualityGateEventsTest { decorator.decorate(project, context); - verify(context).createEvent("Green (was Red)", null, Event.CATEGORY_ALERT, null); + verify(eventCache).createEvent(project, "Green (was Red)", null, EventCategory.ALERT, null); verifyNotificationSent("Green (was Red)", null, "OK", "false"); } @@ -137,7 +136,7 @@ public class GenerateQualityGateEventsTest { decorator.decorate(project, context); - verify(context).createEvent("Red (was Green)", "desc", Event.CATEGORY_ALERT, null); + verify(eventCache).createEvent(project, "Red (was Green)", "desc", EventCategory.ALERT, null); verifyNotificationSent("Red (was Green)", "desc", "ERROR", "true"); } @@ -148,7 +147,7 @@ public class GenerateQualityGateEventsTest { decorator.decorate(project, context); - verify(context).createEvent("Orange (was Red)", "desc", Event.CATEGORY_ALERT, null); + verify(eventCache).createEvent(project, "Orange (was Red)", "desc", EventCategory.ALERT, null); verifyNotificationSent("Orange (was Red)", "desc", "WARN", "false"); } @@ -156,7 +155,7 @@ public class GenerateQualityGateEventsTest { public void shouldNotCreateEventWhenNoAlertStatus() { decorator.decorate(project, context); - verify(context, never()).createEvent(anyString(), anyString(), anyString(), (Date) isNull()); + verify(eventCache, never()).createEvent(any(Resource.class), anyString(), anyString(), any(EventCategory.class), anyString()); verify(notificationManager, never()).scheduleForSending(any(Notification.class)); } @@ -167,7 +166,7 @@ public class GenerateQualityGateEventsTest { decorator.decorate(project, context); - verify(context, never()).createEvent(anyString(), anyString(), anyString(), (Date) isNull()); + verify(eventCache, never()).createEvent(any(Resource.class), anyString(), anyString(), any(EventCategory.class), anyString()); verify(notificationManager, never()).scheduleForSending(any(Notification.class)); } @@ -178,7 +177,7 @@ public class GenerateQualityGateEventsTest { decorator.decorate(project, context); - verify(context, never()).createEvent(anyString(), anyString(), anyString(), (Date) isNull()); + verify(eventCache, never()).createEvent(any(Resource.class), anyString(), anyString(), any(EventCategory.class), anyString()); verify(notificationManager, never()).scheduleForSending(any(Notification.class)); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java index 43c2e697baa..fb0c2aa4b5f 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java @@ -33,14 +33,17 @@ import org.sonar.api.resources.Project; import org.sonar.api.utils.DateUtils; import org.sonar.batch.index.ResourceCache; import org.sonar.batch.protocol.Constants.ComponentLinkType; +import org.sonar.batch.protocol.Constants.EventCategory; import org.sonar.batch.protocol.output.BatchReport.Component; -import org.sonar.batch.protocol.output.BatchReportReader; -import org.sonar.batch.protocol.output.BatchReportWriter; -import org.sonar.batch.protocol.output.FileStructure; +import org.sonar.batch.protocol.output.BatchReport.Event; +import org.sonar.batch.protocol.output.*; import java.io.File; +import java.util.Arrays; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class ComponentsPublisherTest { @@ -50,12 +53,15 @@ public class ComponentsPublisherTest { private ProjectReactor reactor; private ResourceCache resourceCache; private ComponentsPublisher publisher; + private EventCache eventCache; @Before public void prepare() { reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo")); + reactor.getRoot().properties().put(CoreProperties.PROJECT_VERSION_PROPERTY, "1.0"); resourceCache = new ResourceCache(); - publisher = new ComponentsPublisher(reactor, resourceCache); + eventCache = mock(EventCache.class); + publisher = new ComponentsPublisher(reactor, resourceCache, eventCache); } @Test @@ -73,22 +79,22 @@ public class ComponentsPublisherTest { reactor.getRoot().addSubProject(ProjectDefinition.create().setKey("module1")); Directory dir = Directory.create("src"); - dir.setEffectiveKey("foo:src"); + dir.setEffectiveKey("module1:src"); dir.setId(3).setUuid("DIR_UUID"); resourceCache.add(dir, module1).setSnapshot(new Snapshot().setId(13)); org.sonar.api.resources.File file = org.sonar.api.resources.File.create("src/Foo.java", Java.INSTANCE, false); - file.setEffectiveKey("foo:src/Foo.java"); + file.setEffectiveKey("module1:src/Foo.java"); file.setId(4).setUuid("FILE_UUID"); resourceCache.add(file, dir).setSnapshot(new Snapshot().setId(14)); org.sonar.api.resources.File fileWithoutLang = org.sonar.api.resources.File.create("src/make", null, false); - fileWithoutLang.setEffectiveKey("foo:src/make"); + fileWithoutLang.setEffectiveKey("module1:src/make"); fileWithoutLang.setId(5).setUuid("FILE_WITHOUT_LANG_UUID"); resourceCache.add(fileWithoutLang, dir).setSnapshot(new Snapshot().setId(15)); org.sonar.api.resources.File testFile = org.sonar.api.resources.File.create("test/FooTest.java", Java.INSTANCE, true); - testFile.setEffectiveKey("foo:test/FooTest.java"); + testFile.setEffectiveKey("module1:test/FooTest.java"); testFile.setId(6).setUuid("TEST_FILE_UUID"); resourceCache.add(testFile, dir).setSnapshot(new Snapshot().setId(16)); @@ -108,8 +114,11 @@ public class ComponentsPublisherTest { BatchReportReader reader = new BatchReportReader(outputDir); Component rootProtobuf = reader.readComponent(1); + assertThat(rootProtobuf.getVersion()).isEqualTo("1.0"); assertThat(rootProtobuf.getLinkCount()).isEqualTo(0); + Component module1Protobuf = reader.readComponent(2); + assertThat(module1Protobuf.getVersion()).isEqualTo("1.0"); } @Test @@ -131,12 +140,12 @@ public class ComponentsPublisherTest { reactor.getRoot().addSubProject(moduleDef); Directory dir = Directory.create("src"); - dir.setEffectiveKey("foo:src"); + dir.setEffectiveKey("module1:my_branch:my_branch:src"); dir.setId(3).setUuid("DIR_UUID"); resourceCache.add(dir, module1).setSnapshot(new Snapshot().setId(13)); org.sonar.api.resources.File file = org.sonar.api.resources.File.create("src/Foo.java", Java.INSTANCE, false); - file.setEffectiveKey("foo:src/Foo.java"); + file.setEffectiveKey("module1:my_branch:my_branch:src/Foo.java"); file.setId(4).setUuid("FILE_UUID"); resourceCache.add(file, dir).setSnapshot(new Snapshot().setId(14)); @@ -146,13 +155,52 @@ public class ComponentsPublisherTest { BatchReportReader reader = new BatchReportReader(outputDir); Component rootProtobuf = reader.readComponent(1); + assertThat(rootProtobuf.getVersion()).isEqualTo("1.0"); assertThat(rootProtobuf.getLinkCount()).isEqualTo(1); assertThat(rootProtobuf.getLink(0).getType()).isEqualTo(ComponentLinkType.HOME); assertThat(rootProtobuf.getLink(0).getHref()).isEqualTo("http://home"); Component module1Protobuf = reader.readComponent(2); + assertThat(module1Protobuf.getVersion()).isEqualTo("1.0"); assertThat(module1Protobuf.getLinkCount()).isEqualTo(1); assertThat(module1Protobuf.getLink(0).getType()).isEqualTo(ComponentLinkType.CI); assertThat(module1Protobuf.getLink(0).getHref()).isEqualTo("http://ci"); } + + @Test + public void add_components_with_events() throws Exception { + // inputs + Project root = new Project("foo").setName("Root project") + .setAnalysisDate(DateUtils.parseDate(("2012-12-12"))); + root.setId(1).setUuid("PROJECT_UUID"); + resourceCache.add(root, null).setSnapshot(new Snapshot().setId(11)); + + Project module1 = new Project("module1").setName("Module1"); + module1.setParent(root); + module1.setId(2).setUuid("MODULE_UUID"); + resourceCache.add(module1, root).setSnapshot(new Snapshot().setId(12)); + ProjectDefinition moduleDef = ProjectDefinition.create().setKey("module1"); + reactor.getRoot().addSubProject(moduleDef); + + when(eventCache.getEvents(2)).thenReturn(Arrays.asList(Event.newBuilder().setName("name").setCategory(EventCategory.ALERT).setComponentRef(2).build())); + + Directory dir = Directory.create("src"); + dir.setEffectiveKey("module1:src"); + dir.setId(3).setUuid("DIR_UUID"); + resourceCache.add(dir, module1).setSnapshot(new Snapshot().setId(13)); + + File outputDir = temp.newFolder(); + BatchReportWriter writer = new BatchReportWriter(outputDir); + publisher.publish(writer); + + BatchReportReader reader = new BatchReportReader(outputDir); + Component rootProtobuf = reader.readComponent(1); + assertThat(rootProtobuf.getVersion()).isEqualTo("1.0"); + assertThat(rootProtobuf.getEventCount()).isEqualTo(0); + + Component module1Protobuf = reader.readComponent(2); + assertThat(module1Protobuf.getVersion()).isEqualTo("1.0"); + assertThat(module1Protobuf.getEventCount()).isEqualTo(1); + assertThat(module1Protobuf.getEvent(0).getCategory()).isEqualTo(EventCategory.ALERT); + } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileEventsDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileEventsDecoratorTest.java index 9142cf4da6d..b2c1ca57dcb 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileEventsDecoratorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileEventsDecoratorTest.java @@ -38,11 +38,9 @@ */ package org.sonar.batch.rule; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; +import org.junit.Before; import org.junit.Test; import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.Event; import org.sonar.api.batch.TimeMachine; import org.sonar.api.batch.TimeMachineQuery; import org.sonar.api.measures.CoreMetrics; @@ -51,17 +49,14 @@ import org.sonar.api.resources.Java; import org.sonar.api.resources.Languages; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; -import org.sonar.batch.index.EventPersister; +import org.sonar.batch.protocol.Constants.EventCategory; +import org.sonar.batch.report.EventCache; import java.util.Arrays; -import java.util.Date; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -77,8 +72,13 @@ public class QProfileEventsDecoratorTest { DecoratorContext decoratorContext = mock(DecoratorContext.class); TimeMachine timeMachine = mock(TimeMachine.class); Languages languages = mock(Languages.class); - EventPersister eventPersister = mock(EventPersister.class); - QProfileEventsDecorator decorator = new QProfileEventsDecorator(timeMachine, languages, eventPersister); + EventCache eventCache = mock(EventCache.class); + QProfileEventsDecorator decorator = new QProfileEventsDecorator(timeMachine, languages, eventCache); + + @Before + public void prepare() { + when(decoratorContext.getResource()).thenReturn(project); + } @Test public void basic_tests() { @@ -98,7 +98,7 @@ public class QProfileEventsDecoratorTest { decorator.decorate(project, decoratorContext); - verify(decoratorContext, never()).createEvent(anyString(), anyString(), anyString(), any(Date.class)); + verify(eventCache, never()).createEvent(any(Resource.class), anyString(), anyString(), any(EventCategory.class), anyString()); } @Test @@ -115,20 +115,8 @@ public class QProfileEventsDecoratorTest { decorator.decorate(project, decoratorContext); - verify(eventPersister).saveEvent(any(Resource.class), argThat(new BaseMatcher<Event>() { - @Override - public void describeTo(Description description) { - } - - @Override - public boolean matches(Object item) { - Event event = (Event) item; - return event.getCategory().equals(Event.CATEGORY_PROFILE) && - "Changes in 'Java One' (Java)".equals(event.getName()) && - // "from" and "to" must have one second more because of lack of ms precision - "from=2014-01-15T12:00:01+0000;key=J1;to=2014-02-20T12:00:01+0000".equals(event.getData()); - } - })); + // "from" and "to" must have one second more because of lack of ms precision + verify(eventCache).createEvent(project, "Changes in 'Java One' (Java)", null, EventCategory.PROFILE, "from=2014-01-15T12:00:01+0000;key=J1;to=2014-02-20T12:00:01+0000"); } @Test @@ -145,10 +133,7 @@ public class QProfileEventsDecoratorTest { decorator.decorate(project, decoratorContext); - verify(decoratorContext).createEvent( - eq("Stop using 'Java One' (Java)"), - eq((String) null), - same(Event.CATEGORY_PROFILE), any(Date.class)); + verify(eventCache).createEvent(project, "Stop using 'Java One' (Java)", null, EventCategory.PROFILE, null); } @Test @@ -161,6 +146,6 @@ public class QProfileEventsDecoratorTest { decorator.decorate(project, decoratorContext); - verify(decoratorContext, never()).createEvent(anyString(), anyString(), anyString(), any(Date.class)); + verify(eventCache, never()).createEvent(any(Resource.class), anyString(), anyString(), any(EventCategory.class), anyString()); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/sensor/VersionEventsSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/sensor/VersionEventsSensorTest.java deleted file mode 100644 index d70932f673c..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/sensor/VersionEventsSensorTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.batch.scan.sensor; - -import org.sonar.batch.scan.sensor.VersionEventsSensor; - -import com.google.common.collect.Lists; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.batch.AnalysisMode; -import org.sonar.api.batch.Event; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; - -import java.util.Date; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class VersionEventsSensorTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void shouldExecuteOnProject() throws Exception { - AnalysisMode analysisMode = mock(AnalysisMode.class); - assertThat(new VersionEventsSensor(analysisMode).shouldExecuteOnProject(null)).isTrue(); - when(analysisMode.isPreview()).thenReturn(true); - assertThat(new VersionEventsSensor(analysisMode).shouldExecuteOnProject(null)).isFalse(); - } - - @Test - public void testToString() throws Exception { - assertThat(new VersionEventsSensor(null).toString(), is("VersionEventsSensor")); - } - - @Test - public void shouldDoNothingIfNoVersion() { - VersionEventsSensor sensor = new VersionEventsSensor(null); - SensorContext context = mock(SensorContext.class); - Project project = mock(Project.class); - when(project.getAnalysisVersion()).thenReturn(null); - - sensor.analyse(project, context); - - verify(context, never()).createEvent(any(Resource.class), anyString(), anyString(), anyString(), any(Date.class)); - verify(context, never()).deleteEvent(any(Event.class)); - } - - @Test - public void shouldCreateVersionEvent() { - VersionEventsSensor sensor = new VersionEventsSensor(null); - SensorContext context = mock(SensorContext.class); - - Project project = mock(Project.class); - when(project.getAnalysisVersion()).thenReturn("1.5-SNAPSHOT"); - - sensor.analyse(project, context); - - verify(context).createEvent(eq(project), eq("1.5-SNAPSHOT"), (String) isNull(), eq(Event.CATEGORY_VERSION), (Date) isNull()); - } - - @Test - public void shouldHaveOnlyOneEventByVersion() { - Event sameVersionEvent = mockVersionEvent("1.5-SNAPSHOT"); - Event otherEvent = mockVersionEvent("1.4"); - Event anotherEvent = mockVersionEvent("1.3-SNAPSHOT"); - - VersionEventsSensor sensor = new VersionEventsSensor(null); - SensorContext context = mock(SensorContext.class); - - Project project = mock(Project.class); - when(project.getAnalysisVersion()).thenReturn("1.5-SNAPSHOT"); - - when(context.getEvents(project)).thenReturn(Lists.newArrayList(sameVersionEvent, otherEvent, anotherEvent)); - - sensor.analyse(project, context); - - verify(context).deleteEvent(sameVersionEvent); - verify(context).createEvent(eq(project), eq("1.5-SNAPSHOT"), (String) isNull(), eq(Event.CATEGORY_VERSION), (Date) isNull()); - } - - private Event mockVersionEvent(String version) { - Event event = mock(Event.class); - when(event.isVersionCategory()).thenReturn(true); - when(event.getName()).thenReturn(version); - return event; - } - -} |