aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-05-16 16:46:50 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-05-19 11:31:11 +0200
commit0bab6ec48f16ad6b83c80997cfa6fb69edd3930d (patch)
treee263a4a3717057ed03bbbe4accb6dc4f568c9f6a /sonar-batch
parent11ef0dc4eacb45f3caad754ea5d190b77b033a3a (diff)
downloadsonarqube-0bab6ec48f16ad6b83c80997cfa6fb69edd3930d.tar.gz
sonarqube-0bab6ec48f16ad6b83c80997cfa6fb69edd3930d.zip
SONAR-5216 Store and display used quality profiles for multi-language analysis
Diffstat (limited to 'sonar-batch')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/QProfileDecorator.java59
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java31
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java119
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java29
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/QProfileDecoratorTest.java103
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java30
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java72
7 files changed, 425 insertions, 18 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileDecorator.java
new file mode 100644
index 00000000000..7c31d566b4c
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileDecorator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.rule;
+
+import org.sonar.api.batch.Decorator;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.ResourceUtils;
+
+/**
+ * Aggregate which Quality profiles have been used on the current module.
+ */
+public class QProfileDecorator implements Decorator {
+
+ public boolean shouldExecuteOnProject(Project project) {
+ return project.getModules().size() > 0;
+ }
+
+ @Override
+ public void decorate(Resource resource, DecoratorContext context) {
+ if (!ResourceUtils.isProject(resource)) {
+ return;
+ }
+ UsedQProfiles profiles = UsedQProfiles.empty();
+ for (Measure childProfilesMeasure : context.getChildrenMeasures(CoreMetrics.PROFILES)) {
+ UsedQProfiles childProfiles = UsedQProfiles.fromJSON(childProfilesMeasure.getData());
+ profiles = profiles.merge(childProfiles);
+ }
+
+ Measure detailsMeasure = new Measure(CoreMetrics.PROFILES, profiles.toJSON());
+ context.saveMeasure(detailsMeasure);
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName();
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
index e931163b31e..7b44ab64926 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
@@ -19,7 +19,7 @@
*/
package org.sonar.batch.rule;
-import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.FileSystem;
@@ -28,6 +28,8 @@ import org.sonar.api.measures.Measure;
import org.sonar.api.resources.Project;
import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import java.util.List;
+
/**
* Stores which Quality profiles have been used on the current module.
*/
@@ -44,25 +46,32 @@ public class QProfileSensor implements Sensor {
}
public boolean shouldExecuteOnProject(Project project) {
- return true;
+ // Should be only executed on leaf modules
+ return project.getModules().isEmpty();
}
public void analyse(Project project, SensorContext context) {
+ List<ModuleQProfiles.QProfile> profiles = Lists.newArrayList();
for (String language : fs.languages()) {
ModuleQProfiles.QProfile qProfile = moduleQProfiles.findByLanguage(language);
if (qProfile != null) {
dao.updateUsedColumn(qProfile.id(), true);
+ profiles.add(qProfile);
}
}
- if (fs.languages().size() == 1) {
- String language = Iterables.getOnlyElement(fs.languages());
- ModuleQProfiles.QProfile qProfile = moduleQProfiles.findByLanguage(language);
- if (qProfile != null) {
- Measure measure = new Measure(CoreMetrics.PROFILE, qProfile.name()).setValue((double)qProfile.id());
- Measure measureVersion = new Measure(CoreMetrics.PROFILE_VERSION, qProfile.version().doubleValue());
- context.saveMeasure(measure);
- context.saveMeasure(measureVersion);
- }
+ if (profiles.size() > 0) {
+ UsedQProfiles used = UsedQProfiles.fromProfiles(profiles);
+ Measure detailsMeasure = new Measure(CoreMetrics.PROFILES, used.toJSON());
+ context.saveMeasure(detailsMeasure);
+ }
+
+ // For backward compatibility
+ if (profiles.size() == 1) {
+ ModuleQProfiles.QProfile qProfile = profiles.get(0);
+ Measure measure = new Measure(CoreMetrics.PROFILE, qProfile.name()).setValue((double) qProfile.id());
+ Measure measureVersion = new Measure(CoreMetrics.PROFILE_VERSION, qProfile.version().doubleValue());
+ context.saveMeasure(measure);
+ context.saveMeasure(measureVersion);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java b/sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java
new file mode 100644
index 00000000000..13893c64811
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/UsedQProfiles.java
@@ -0,0 +1,119 @@
+/*
+ * 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.rule;
+
+import com.google.common.collect.Maps;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.batch.rule.ModuleQProfiles.QProfile;
+
+import javax.annotation.concurrent.Immutable;
+
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Map;
+
+@Immutable
+public class UsedQProfiles {
+
+ private Map<String, Map<Integer, ModuleQProfiles.QProfile>> profilesByLanguage = Maps.newLinkedHashMap();
+
+ private UsedQProfiles() {
+ }
+
+ public static final UsedQProfiles fromProfiles(Iterable<QProfile> profiles) {
+ UsedQProfiles result = new UsedQProfiles();
+ for (QProfile qProfile : profiles) {
+ result.add(qProfile);
+ }
+ return result;
+ }
+
+ public static final UsedQProfiles empty() {
+ return new UsedQProfiles();
+ }
+
+ public static final UsedQProfiles fromProfiles(QProfile... profiles) {
+ return fromProfiles(Arrays.asList(profiles));
+ }
+
+ public static final UsedQProfiles fromJSON(String json) {
+ UsedQProfiles result = new UsedQProfiles();
+ JsonArray root = new JsonParser().parse(json).getAsJsonArray();
+ for (JsonElement elt : root) {
+ JsonObject profile = elt.getAsJsonObject();
+ result.add(new QProfile(profile.get("id").getAsInt(), profile.get("name").getAsString(), profile.get("language").getAsString(), profile.get("version").getAsInt()));
+ }
+ return result;
+ }
+
+ public final String toJSON() {
+ StringWriter json = new StringWriter();
+ JsonWriter writer = JsonWriter.of(json);
+ writer.beginArray();
+ for (String languageKey : profilesByLanguage.keySet()) {
+ for (ModuleQProfiles.QProfile qProfile : profilesByLanguage.get(languageKey).values()) {
+ writer.beginObject()
+ .prop("id", qProfile.id())
+ .prop("name", qProfile.name())
+ .prop("version", qProfile.version())
+ .prop("language", qProfile.language())
+ .endObject();
+ }
+ }
+ writer.endArray();
+ writer.close();
+ return json.toString();
+ }
+
+ public final UsedQProfiles merge(UsedQProfiles other) {
+ return empty().mergeInPlace(this).mergeInPlace(other);
+ }
+
+ private void add(ModuleQProfiles.QProfile profile) {
+ if (!profilesByLanguage.containsKey(profile.language())) {
+ profilesByLanguage.put(profile.language(), Maps.<Integer, ModuleQProfiles.QProfile>newLinkedHashMap());
+ }
+ QProfile alreadyAdded = profilesByLanguage.get(profile.language()).get(profile.id());
+ if (alreadyAdded == null
+ // Keep only latest version
+ || profile.version() > alreadyAdded.version()) {
+ profilesByLanguage.get(profile.language()).put(profile.id(), profile);
+ }
+ }
+
+ private UsedQProfiles addAll(Iterable<QProfile> profiles) {
+ for (QProfile profile : profiles) {
+ this.add(profile);
+ }
+ return this;
+ }
+
+ private UsedQProfiles mergeInPlace(UsedQProfiles other) {
+ for (Map<Integer, QProfile> byIds : other.profilesByLanguage.values()) {
+ this.addAll(byIds.values());
+ }
+ return this;
+ }
+
+}
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 1db4a9a5054..c2fb81ba982 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
@@ -28,7 +28,12 @@ import org.sonar.api.batch.rule.CheckFactory;
import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.batch.*;
+import org.sonar.batch.DefaultProjectClasspath;
+import org.sonar.batch.DefaultSensorContext;
+import org.sonar.batch.DefaultTimeMachine;
+import org.sonar.batch.ProjectTree;
+import org.sonar.batch.ResourceFilters;
+import org.sonar.batch.ViolationFilters;
import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
import org.sonar.batch.bootstrap.ExtensionInstaller;
import org.sonar.batch.bootstrap.ExtensionMatcher;
@@ -52,8 +57,25 @@ import org.sonar.batch.phases.PhasesTimeProfiler;
import org.sonar.batch.qualitygate.GenerateQualityGateEvents;
import org.sonar.batch.qualitygate.QualityGateProvider;
import org.sonar.batch.qualitygate.QualityGateVerifier;
-import org.sonar.batch.rule.*;
-import org.sonar.batch.scan.filesystem.*;
+import org.sonar.batch.rule.ActiveRulesProvider;
+import org.sonar.batch.rule.ModuleQProfiles;
+import org.sonar.batch.rule.QProfileDecorator;
+import org.sonar.batch.rule.QProfileSensor;
+import org.sonar.batch.rule.QProfileVerifier;
+import org.sonar.batch.rule.RulesProfileProvider;
+import org.sonar.batch.scan.filesystem.ComponentIndexer;
+import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
+import org.sonar.batch.scan.filesystem.DeprecatedFileFilters;
+import org.sonar.batch.scan.filesystem.ExclusionFilters;
+import org.sonar.batch.scan.filesystem.FileIndexer;
+import org.sonar.batch.scan.filesystem.FileSystemLogger;
+import org.sonar.batch.scan.filesystem.InputFileBuilderFactory;
+import org.sonar.batch.scan.filesystem.LanguageDetectionFactory;
+import org.sonar.batch.scan.filesystem.ModuleFileSystemInitializer;
+import org.sonar.batch.scan.filesystem.ModuleInputFileCache;
+import org.sonar.batch.scan.filesystem.PreviousFileHashLoader;
+import org.sonar.batch.scan.filesystem.ProjectFileSystemAdapter;
+import org.sonar.batch.scan.filesystem.StatusDetectionFactory;
import org.sonar.batch.scan.report.JsonReport;
import org.sonar.core.component.ScanPerspectives;
import org.sonar.core.measure.MeasurementFilters;
@@ -134,6 +156,7 @@ public class ModuleScanContainer extends ComponentContainer {
new ActiveRulesProvider(),
new RulesProfileProvider(),
QProfileSensor.class,
+ QProfileDecorator.class,
CheckFactory.class,
// report
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileDecoratorTest.java
new file mode 100644
index 00000000000..30c8023002b
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileDecoratorTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.rule;
+
+import org.junit.Test;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.test.IsMeasure;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class QProfileDecoratorTest {
+
+ Project project = mock(Project.class);
+ Project moduleA = mock(Project.class);
+ Project moduleB = mock(Project.class);
+ DecoratorContext decoratorContext = mock(DecoratorContext.class);
+
+ @Test
+ public void don_t_run_on_leaf() throws Exception {
+ QProfileDecorator decorator = new QProfileDecorator();
+ when(project.getModules()).thenReturn(Collections.<Project>emptyList());
+ assertThat(decorator.shouldExecuteOnProject(project)).isFalse();
+
+ when(project.getModules()).thenReturn(Arrays.asList(moduleA, moduleB));
+ assertThat(decorator.shouldExecuteOnProject(project)).isTrue();
+ }
+
+ @Test
+ public void aggregate() throws Exception {
+ Measure measureModuleA = new Measure(CoreMetrics.PROFILES, "[{\"id\":2,\"name\":\"Java Two\",\"version\":20,\"language\":\"java\"}]");
+ Measure measureModuleB = new Measure(CoreMetrics.PROFILES, "[{\"id\":3,\"name\":\"Php One\",\"version\":30,\"language\":\"php\"}]");
+ when(decoratorContext.getChildrenMeasures(CoreMetrics.PROFILES)).thenReturn(Arrays.asList(measureModuleA, measureModuleB));
+
+ when(project.getScope()).thenReturn(Scopes.PROJECT);
+
+ QProfileDecorator decorator = new QProfileDecorator();
+ decorator.decorate(project, decoratorContext);
+
+ verify(decoratorContext).saveMeasure(
+ argThat(new IsMeasure(CoreMetrics.PROFILES,
+ "[{\"id\":2,\"name\":\"Java Two\",\"version\":20,\"language\":\"java\"},{\"id\":3,\"name\":\"Php One\",\"version\":30,\"language\":\"php\"}]")));
+ }
+
+ @Test
+ public void aggregate_several_profile_same_language() throws Exception {
+ Measure measureModuleA = new Measure(CoreMetrics.PROFILES, "[{\"id\":2,\"name\":\"Java Two\",\"version\":20,\"language\":\"java\"}]");
+ Measure measureModuleB = new Measure(CoreMetrics.PROFILES, "[{\"id\":3,\"name\":\"Java Three\",\"version\":30,\"language\":\"java\"}]");
+ when(decoratorContext.getChildrenMeasures(CoreMetrics.PROFILES)).thenReturn(Arrays.asList(measureModuleA, measureModuleB));
+
+ when(project.getScope()).thenReturn(Scopes.PROJECT);
+
+ QProfileDecorator decorator = new QProfileDecorator();
+ decorator.decorate(project, decoratorContext);
+
+ verify(decoratorContext).saveMeasure(
+ argThat(new IsMeasure(CoreMetrics.PROFILES,
+ "[{\"id\":2,\"name\":\"Java Two\",\"version\":20,\"language\":\"java\"},{\"id\":3,\"name\":\"Java Three\",\"version\":30,\"language\":\"java\"}]")));
+ }
+
+ @Test
+ public void aggregate_several_profile_same_id() throws Exception {
+ Measure measureModuleA = new Measure(CoreMetrics.PROFILES, "[{\"id\":2,\"name\":\"Java Two\",\"version\":20,\"language\":\"java\"}]");
+ Measure measureModuleB = new Measure(CoreMetrics.PROFILES, "[{\"id\":2,\"name\":\"Java Two\",\"version\":30,\"language\":\"java\"}]");
+ when(decoratorContext.getChildrenMeasures(CoreMetrics.PROFILES)).thenReturn(Arrays.asList(measureModuleA, measureModuleB));
+
+ when(project.getScope()).thenReturn(Scopes.PROJECT);
+
+ QProfileDecorator decorator = new QProfileDecorator();
+ decorator.decorate(project, decoratorContext);
+
+ verify(decoratorContext).saveMeasure(
+ argThat(new IsMeasure(CoreMetrics.PROFILES,
+ "[{\"id\":2,\"name\":\"Java Two\",\"version\":30,\"language\":\"java\"}]")));
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
index f12d753fb5f..85f2509d874 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
@@ -31,7 +31,11 @@ import org.sonar.core.qualityprofile.db.QualityProfileDao;
import java.util.Collections;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.*;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
public class QProfileSensorTest extends AbstractDaoTestCase {
@@ -76,9 +80,6 @@ public class QProfileSensorTest extends AbstractDaoTestCase {
sensor.analyse(project, sensorContext);
checkTable("mark_profiles_as_used", "rules_profiles");
-
- // no measures on multi-language modules
- verifyZeroInteractions(sensorContext);
}
@Test
@@ -97,5 +98,26 @@ public class QProfileSensorTest extends AbstractDaoTestCase {
verify(sensorContext).saveMeasure(argThat(new IsMeasure(CoreMetrics.PROFILE, "Java Two")));
verify(sensorContext).saveMeasure(argThat(new IsMeasure(CoreMetrics.PROFILE_VERSION, 20.0)));
+ verify(sensorContext).saveMeasure(
+ argThat(new IsMeasure(CoreMetrics.PROFILES, "[{\"id\":2,\"name\":\"Java Two\",\"version\":20,\"language\":\"java\"}]")));
+ }
+
+ @Test
+ public void store_measures_on_multi_lang_module() throws Exception {
+ setupData("shared");
+
+ QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+ when(moduleQProfiles.findByLanguage("java")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(2)));
+ when(moduleQProfiles.findByLanguage("php")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(3)));
+ when(moduleQProfiles.findByLanguage("abap")).thenReturn(null);
+ fs.addLanguages("java", "php");
+
+ QProfileSensor sensor = new QProfileSensor(moduleQProfiles, fs, dao);
+ assertThat(sensor.shouldExecuteOnProject(project)).isTrue();
+ sensor.analyse(project, sensorContext);
+
+ verify(sensorContext).saveMeasure(
+ argThat(new IsMeasure(CoreMetrics.PROFILES,
+ "[{\"id\":2,\"name\":\"Java Two\",\"version\":20,\"language\":\"java\"},{\"id\":3,\"name\":\"Php One\",\"version\":30,\"language\":\"php\"}]")));
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.java
new file mode 100644
index 00000000000..b3cab37a325
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/UsedQProfilesTest.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.batch.rule;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class UsedQProfilesTest {
+
+ @Test
+ public void serialization() throws Exception {
+
+ ModuleQProfiles.QProfile java = new ModuleQProfiles.QProfile(1, "Sonar Way", "java", 1);
+ ModuleQProfiles.QProfile php = new ModuleQProfiles.QProfile(2, "Sonar Way", "php", 1);
+
+ UsedQProfiles used = UsedQProfiles.fromProfiles(java, php);
+ assertThat(used.toJSON()).isEqualTo(
+ "[{\"id\":1,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"java\"},{\"id\":2,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"php\"}]");
+ }
+
+ @Test
+ public void deserialization() throws Exception {
+ UsedQProfiles used = UsedQProfiles
+ .fromJSON("[{\"id\":1,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"java\"},{\"id\":2,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"php\"}]");
+
+ assertThat(used.toJSON()).isEqualTo(
+ "[{\"id\":1,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"java\"},{\"id\":2,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"php\"}]");
+ }
+
+ @Test
+ public void merge() throws Exception {
+ UsedQProfiles first = UsedQProfiles
+ .fromJSON("[{\"id\":1,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"java\"}]");
+
+ UsedQProfiles second = UsedQProfiles
+ .fromJSON("[{\"id\":2,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"php\"}]");
+
+ assertThat(first.merge(second).toJSON()).isEqualTo(
+ "[{\"id\":1,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"java\"},{\"id\":2,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"php\"}]");
+ }
+
+ @Test
+ public void merge_no_duplicate_ids() throws Exception {
+ UsedQProfiles first = UsedQProfiles
+ .fromJSON("[{\"id\":1,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"java\"},{\"id\":2,\"name\":\"Sonar Way\",\"version\":2,\"language\":\"php\"}]");
+
+ UsedQProfiles second = UsedQProfiles
+ .fromJSON("[{\"id\":1,\"name\":\"Sonar Way\",\"version\":2,\"language\":\"java\"},{\"id\":2,\"name\":\"Sonar Way\",\"version\":1,\"language\":\"php\"}]");
+
+ assertThat(first.merge(second).toJSON()).isEqualTo(
+ "[{\"id\":1,\"name\":\"Sonar Way\",\"version\":2,\"language\":\"java\"},{\"id\":2,\"name\":\"Sonar Way\",\"version\":2,\"language\":\"php\"}]");
+ }
+
+}