This is an automated email from the ASF dual-hosted git repository.
davidb pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-analyser.git
The following commit(s) were added to refs/heads/master by this push:
new 604b53c SLING-9489 Make it possible to compare parts of feature models
604b53c is described below
commit 604b53c3ed25fc1ea5ecc23ab036ae2ea2eae4c6
Author: David Bosschaert <[email protected]>
AuthorDate: Thu Jun 18 09:54:05 2020 +0100
SLING-9489 Make it possible to compare parts of feature models
---
pom.xml | 2 +-
readme.md | 18 +-
.../apache/sling/feature/analyser/Analyser.java | 11 +
.../sling/feature/analyser/package-info.java | 2 +-
.../feature/analyser/task/AnalyserTaskContext.java | 3 +
.../analyser/task/impl/CheckCompareFeatures.java | 145 +++++++++++
.../sling/feature/analyser/task/package-info.java | 2 +-
...apache.sling.feature.analyser.task.AnalyserTask | 3 +-
.../task/impl/CheckApisJarsPropertiesTest.java | 6 +
.../task/impl/CheckCompareFeaturesTest.java | 277 +++++++++++++++++++++
.../analyser/task/impl/CheckRepoinitTest.java | 6 +
11 files changed, 470 insertions(+), 5 deletions(-)
diff --git a/pom.xml b/pom.xml
index ceef91d..dc7dc85 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
</parent>
<artifactId>org.apache.sling.feature.analyser</artifactId>
- <version>1.2.7-SNAPSHOT</version>
+ <version>1.3.0-SNAPSHOT</version>
<name>Apache Sling Feature Model Analyser</name>
<description>
diff --git a/readme.md b/readme.md
index 1be6ebc..015355f 100644
--- a/readme.md
+++ b/readme.md
@@ -25,11 +25,27 @@ information as part of the check, to ensure that bundles
don't import packages o
* `bundle-resources`: Gives a warning if a bundle contains resources specified
with `Sling-Bundle-Resources`.
-* `requirements-capabilities`: Checks bundle requirements/capabilities for
consistency and completeness.
+* `compare-features`: Compares the artifacts in the bundles sections or in an
extension between two feature models. For more information see
[below](#compare-features).
+* `requirements-capabilities`: Checks bundle requirements/capabilities for
consistency and completeness.
* `apis-jar`: validates that the `sourceId` property of a bundle, if defined,
is a comma-separated value list of artifact ids.
Additional analysers in relation to Feature Model API Regions can be found
here:
https://github.com/apache/sling-org-apache-sling-feature-extension-apiregions
For further documentation see:
https://github.com/apache/sling-org-apache-sling-feature/blob/master/readme.md
+
+## `compare-features`
+
+This analyser compares certain sections of two feature models.
+
+This analyser requires additional configuration:
+
+ Configuration key | Allowed values | Description
+ ----- | ----- | -----
+`compare-type` | `ARTIFACTS` | The types of entities being compared. Currently
only artifacts can be compared.
+`compare-with` | Maven ID, e.g. `mygroup:myart:1.2.3` | The _golden_ feature
to compare the features selected for the analyser with.
+`compare-extension` | extension name | If this configuration is absent, the
feature's bundles are compared. Otherwise the extensions with the specified
name are compared. These extensions must be of type `ARTIFACTS`.
+`compare-mode` | `SAME` or `DIFFERENT` | Whether the sections must be the same
or must be different. Defaults to `SAME`.
+`compare-metadata` | `true` or `false` | Whether to include the artifact
metadata in the comparison. Defaults to `false`.
+
diff --git a/src/main/java/org/apache/sling/feature/analyser/Analyser.java
b/src/main/java/org/apache/sling/feature/analyser/Analyser.java
index 2186ede..d14c33e 100644
--- a/src/main/java/org/apache/sling/feature/analyser/Analyser.java
+++ b/src/main/java/org/apache/sling/feature/analyser/Analyser.java
@@ -34,6 +34,7 @@ import org.apache.sling.feature.ExecutionEnvironmentExtension;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.analyser.task.AnalyserTask;
import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+import org.apache.sling.feature.builder.FeatureProvider;
import org.apache.sling.feature.scanner.BundleDescriptor;
import org.apache.sling.feature.scanner.FeatureDescriptor;
import org.apache.sling.feature.scanner.Scanner;
@@ -105,6 +106,11 @@ public class Analyser {
}
public AnalyserResult analyse(final Feature feature, final ArtifactId fwk)
throws Exception {
+ return analyse(feature, fwk, null);
+ }
+
+ public AnalyserResult analyse(final Feature feature, final ArtifactId fwk,
+ final FeatureProvider featureProvider) throws Exception {
logger.info("Starting analyzing feature '{}'...", feature.getId());
final FeatureDescriptor featureDesc = scanner.scan(feature);
@@ -143,6 +149,11 @@ public class Analyser {
}
@Override
+ public FeatureProvider getFeatureProvider() {
+ return featureProvider;
+ }
+
+ @Override
public BundleDescriptor getFrameworkDescriptor() {
return fwkDesc;
}
diff --git a/src/main/java/org/apache/sling/feature/analyser/package-info.java
b/src/main/java/org/apache/sling/feature/analyser/package-info.java
index 3042a56..2edfaae 100644
--- a/src/main/java/org/apache/sling/feature/analyser/package-info.java
+++ b/src/main/java/org/apache/sling/feature/analyser/package-info.java
@@ -17,7 +17,7 @@
* under the License.
*/
[email protected]("1.0.0")
[email protected]("1.1.0")
package org.apache.sling.feature.analyser;
diff --git
a/src/main/java/org/apache/sling/feature/analyser/task/AnalyserTaskContext.java
b/src/main/java/org/apache/sling/feature/analyser/task/AnalyserTaskContext.java
index 414c69f..af5ec38 100644
---
a/src/main/java/org/apache/sling/feature/analyser/task/AnalyserTaskContext.java
+++
b/src/main/java/org/apache/sling/feature/analyser/task/AnalyserTaskContext.java
@@ -17,6 +17,7 @@
package org.apache.sling.feature.analyser.task;
import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.FeatureProvider;
import org.apache.sling.feature.scanner.BundleDescriptor;
import org.apache.sling.feature.scanner.FeatureDescriptor;
import org.osgi.annotation.versioning.ProviderType;
@@ -38,6 +39,8 @@ public interface AnalyserTaskContext {
*/
FeatureDescriptor getFeatureDescriptor();
+ FeatureProvider getFeatureProvider();
+
/**
* The framework descriptor
* @return the descriptor
diff --git
a/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckCompareFeatures.java
b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckCompareFeatures.java
new file mode 100644
index 0000000..af5b450
--- /dev/null
+++
b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckCompareFeatures.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.feature.analyser.task.impl;
+
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Artifacts;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.analyser.task.AnalyserTask;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+
+import java.util.Map;
+
+public class CheckCompareFeatures implements AnalyserTask {
+
+ @Override
+ public String getId() {
+ return "compare-features";
+ }
+
+ @Override
+ public String getName() {
+ return "Comparing Features";
+ }
+
+ @Override
+ public void execute(AnalyserTaskContext ctx) throws Exception {
+ Map<String, String> cfg = ctx.getConfiguration();
+ String aid = cfg.get("compare-with");
+ if (aid == null) {
+ throw new Exception("Missing 'compare-with' configuration for
compare-features analyser.");
+ }
+
+ String ext = cfg.get("compare-extension");
+ String mode = cfg.getOrDefault("compare-mode", "SAME");
+ String type = cfg.getOrDefault("compare-type", "ARTIFACTS");
+ if (!"ARTIFACTS".equals(type)) {
+ throw new Exception("The only supported value for 'compare-type'
right now is ARTIFACTS");
+ }
+
+ boolean strictMetadata = !cfg.getOrDefault("compare-metadata",
"false").equalsIgnoreCase("false");
+
+ Feature feat =
ctx.getFeatureProvider().provide(ArtifactId.fromMvnId(aid));
+ if (feat == null)
+ throw new Exception("Feature not found: " + aid);
+
+ Artifacts mainArts = getArtifactsToCompare(feat, ext);
+ Artifacts compArts = getArtifactsToCompare(ctx.getFeature(), ext);
+
+ String violationMessage = null;
+ switch (mode) {
+ case "SAME":
+ violationMessage = assertArtifactsSame(mainArts, compArts,
strictMetadata);
+ break;
+ case "DIFFERENT":
+ violationMessage = assertArtifactsSame(mainArts, compArts,
strictMetadata);
+ if (violationMessage == null) {
+ violationMessage = "Artifacts are not different";
+ } else {
+ violationMessage = null;
+ }
+ break;
+ default:
+ throw new Exception("Unknown comparison mode: " + mode);
+ }
+
+ if (violationMessage != null) {
+ String origin;
+ if (ext == null) {
+ origin = "bundles";
+ } else {
+ origin = "extension " + ext;
+ }
+
+ ctx.reportError("Compare " + origin + " in feature " +
feat.getId() + " and "
+ + ctx.getFeature().getId() + " failed: " +
violationMessage);
+ }
+ }
+
+ static String assertArtifactsSame(Artifacts mainArts, Artifacts compArts,
boolean strictMetadata) {
+ if (mainArts.size() != compArts.size()) {
+ return "Compared artifacts are of different sizes";
+ }
+
+ for (Artifact a : mainArts) {
+ Artifact a2 = findArtifact(compArts, a.getId());
+ if (a2 == null) {
+ return "Artifact " + a.getId() + " not found.";
+ }
+
+ if (strictMetadata) {
+ Map<String, String> md1 = a.getMetadata();
+ Map<String, String> md2 = a2.getMetadata();
+ if (!md1.equals(md2)) {
+ return "Metadata of " + a.getId() + " is different: " +
md1 + " vs " + md2;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static Artifact findArtifact(Artifacts list, ArtifactId
artifactId) {
+ for (Artifact a : list) {
+ if (a.getId().equals(artifactId))
+ return a;
+ }
+ return null;
+ }
+
+ static Artifacts getArtifactsToCompare(Feature feat, String ext) throws
Exception {
+ Artifacts artifacts;
+ if (ext == null) {
+ // compare bundles
+ artifacts = feat.getBundles();
+ } else {
+ // compare extensions
+ Extension extension = feat.getExtensions().getByName(ext);
+ if (extension == null) {
+ throw new Exception("Extension " + ext + " not found in
feature " + feat.getId());
+ }
+ if (ExtensionType.ARTIFACTS != extension.getType()) {
+ throw new Exception("Extension " + extension + " is not of
type ARTIFACTS.");
+ }
+
+ artifacts = extension.getArtifacts();
+ }
+ return artifacts;
+ }
+}
diff --git
a/src/main/java/org/apache/sling/feature/analyser/task/package-info.java
b/src/main/java/org/apache/sling/feature/analyser/task/package-info.java
index d265303..614898f 100644
--- a/src/main/java/org/apache/sling/feature/analyser/task/package-info.java
+++ b/src/main/java/org/apache/sling/feature/analyser/task/package-info.java
@@ -17,7 +17,7 @@
* under the License.
*/
[email protected]("1.0.0")
[email protected]("1.1.0")
package org.apache.sling.feature.analyser.task;
diff --git
a/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask
b/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask
index bfbe662..773f53e 100644
---
a/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask
+++
b/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask
@@ -6,4 +6,5 @@
org.apache.sling.feature.analyser.task.impl.CheckRequirementsCapabilities
org.apache.sling.feature.analyser.task.impl.CheckContentPackageForInstallables
org.apache.sling.feature.analyser.task.impl.CheckContentPackagesDependencies
org.apache.sling.feature.analyser.task.impl.CheckApisJarsProperties
-org.apache.sling.feature.analyser.task.impl.CheckRepoinit
\ No newline at end of file
+org.apache.sling.feature.analyser.task.impl.CheckCompareFeatures
+org.apache.sling.feature.analyser.task.impl.CheckRepoinit
diff --git
a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsPropertiesTest.java
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsPropertiesTest.java
index 34ea6f6..983b43f 100644
---
a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsPropertiesTest.java
+++
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckApisJarsPropertiesTest.java
@@ -30,6 +30,7 @@ import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+import org.apache.sling.feature.builder.FeatureProvider;
import org.apache.sling.feature.scanner.BundleDescriptor;
import org.apache.sling.feature.scanner.FeatureDescriptor;
import org.junit.Test;
@@ -77,6 +78,11 @@ public class CheckApisJarsPropertiesTest {
return Collections.emptyMap();
}
+ @Override
+ public FeatureProvider getFeatureProvider() {
+ return null;
+ }
+
public List<String> getErrors() {
return errors;
}
diff --git
a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckCompareFeaturesTest.java
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckCompareFeaturesTest.java
new file mode 100644
index 0000000..825fd30
--- /dev/null
+++
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckCompareFeaturesTest.java
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.feature.analyser.task.impl;
+
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Artifacts;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionState;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+import org.apache.sling.feature.builder.FeatureProvider;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class CheckCompareFeaturesTest {
+ @Test
+ public void testAssertEmptyArtifactsSame() {
+ Artifacts a1 = new Artifacts();
+ Artifacts a2 = new Artifacts();
+
+ assertNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, true));
+ assertNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, false));
+ }
+
+ @Test
+ public void testAssertDiffSizeArtifactsNotSame() {
+ Artifacts a1 = new Artifacts();
+ Artifacts a2 = new Artifacts();
+ a2.add(new Artifact(ArtifactId.fromMvnId("a:b:1")));
+
+ assertNotNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, true));
+ assertNotNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, false));
+ }
+
+ @Test
+ public void testAssertDiffSizeArtifactsNotSame2() {
+ Artifacts a1 = new Artifacts();
+ a1.add(new Artifact(ArtifactId.fromMvnId("a:b:1")));
+ Artifacts a2 = new Artifacts();
+ a2.add(new Artifact(ArtifactId.fromMvnId("a:b:2")));
+
+ assertNotNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, true));
+ assertNotNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, false));
+ }
+
+ @Test
+ public void testAssertArtifactsSame() {
+ Artifacts a1 = new Artifacts();
+ a1.add(new Artifact(ArtifactId.fromMvnId("a:b:1")));
+ a1.add(new Artifact(ArtifactId.fromMvnId("a:b:2")));
+ Artifacts a2 = new Artifacts();
+ a2.add(new Artifact(ArtifactId.fromMvnId("a:b:2")));
+ a2.add(new Artifact(ArtifactId.fromMvnId("a:b:1")));
+
+ assertNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, true));
+ assertNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, false));
+ }
+
+ @Test
+ public void testAssertArtifactsSameDifferentMetadata() {
+ Artifact art1 = new Artifact(ArtifactId.fromMvnId("a:b:1"));
+ art1.getMetadata().put("foo", "bar");
+ Artifacts a1 = new Artifacts();
+ a1.add(art1);
+
+ Artifact art2 = new Artifact(ArtifactId.fromMvnId("a:b:1"));
+ Artifacts a2 = new Artifacts();
+ a2.add(art2);
+
+ assertNotNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, true));
+ assertNull(CheckCompareFeatures.assertArtifactsSame(a1, a2, false));
+ }
+
+ @Test
+ public void testFindArtifactsToCompare() throws Exception {
+ Feature f = new Feature(ArtifactId.fromMvnId("x:y:123"));
+ f.getBundles().add(new
Artifact(ArtifactId.fromMvnId("grp:bundle1:1")));
+ Extension ext = new Extension(ExtensionType.TEXT, "textext",
ExtensionState.REQUIRED);
+ ext.setText("hello");
+ f.getExtensions().add(ext);
+ Extension ext2 = new Extension(ExtensionType.ARTIFACTS, "artext",
ExtensionState.REQUIRED);
+ ext2.getArtifacts().add(new
Artifact(ArtifactId.fromMvnId("grp:extart1:2")));
+ ext2.getArtifacts().add(new
Artifact(ArtifactId.fromMvnId("grp:extart2:5")));
+ f.getExtensions().add(ext2);
+
+ Artifacts arts1 = CheckCompareFeatures.getArtifactsToCompare(f, null);
+ assertEquals(arts1, f.getBundles());
+
+ Artifacts arts2 = CheckCompareFeatures.getArtifactsToCompare(f,
"artext");
+ assertEquals(ext2.getArtifacts(), arts2);
+
+ try {
+ CheckCompareFeatures.getArtifactsToCompare(f, "textext");
+ fail("Expected an exception, because textext is not of type
Artifacts");
+ } catch (Exception ex) {
+ // good
+ }
+
+ try {
+ CheckCompareFeatures.getArtifactsToCompare(f, "nonexisting");
+ fail("Expected an exception, because a non-existing extension was
requested");
+ } catch (Exception ex) {
+ // good
+ }
+ }
+
+ @Test
+ public void testExecute1() throws Exception {
+ Feature f = new Feature(ArtifactId.fromMvnId("g:a:123"));
+ f.getBundles().add(new Artifact(ArtifactId.fromMvnId("g:b:1")));
+ Feature fc = new Feature(ArtifactId.fromMvnId("g:b:456"));
+ fc.getBundles().add(new Artifact(ArtifactId.fromMvnId("g:b:1")));
+
+ AnalyserTaskContext ctx = testExecute(f, fc);
+
+ Mockito.verify(ctx, Mockito.never()).reportError(Mockito.anyString());
+ }
+
+ @Test
+ public void testExecute2() throws Exception {
+ Feature f = new Feature(ArtifactId.fromMvnId("g:a:123"));
+ f.getBundles().add(new Artifact(ArtifactId.fromMvnId("g:b:1")));
+ Feature fc = new Feature(ArtifactId.fromMvnId("g:b:456"));
+
+ AnalyserTaskContext ctx = testExecute(f, fc);
+
+ Mockito.verify(ctx).reportError(Mockito.anyString());
+ }
+
+ @Test
+ public void testExecute3() throws Exception {
+ Feature f1 = new Feature(ArtifactId.fromMvnId("g:a:123"));
+ Extension e1 = new Extension(ExtensionType.ARTIFACTS, "myarts",
ExtensionState.REQUIRED);
+ e1.getArtifacts().add(new Artifact(ArtifactId.fromMvnId("g:c:1")));
+ e1.getArtifacts().add(new Artifact(ArtifactId.fromMvnId("g:c:2")));
+ f1.getExtensions().add(e1);
+
+ Feature f2 = new Feature(ArtifactId.fromMvnId("g:b:456"));
+ Extension e2 = new Extension(ExtensionType.ARTIFACTS, "myarts",
ExtensionState.REQUIRED);
+ e2.getArtifacts().add(new Artifact(ArtifactId.fromMvnId("g:c:2")));
+ e2.getArtifacts().add(new Artifact(ArtifactId.fromMvnId("g:c:1")));
+ f2.getExtensions().add(e2);
+
+ AnalyserTaskContext ctx = testExecute(f1, f2, "myarts");
+
+ Mockito.verify(ctx, Mockito.never()).reportError(Mockito.anyString());
+ }
+
+ @Test
+ public void testExecute4() throws Exception {
+ Feature f1 = new Feature(ArtifactId.fromMvnId("g:a:123"));
+ Extension e1 = new Extension(ExtensionType.ARTIFACTS, "myarts",
ExtensionState.REQUIRED);
+ f1.getExtensions().add(e1);
+
+ Feature f2 = new Feature(ArtifactId.fromMvnId("g:b:456"));
+ Extension e2 = new Extension(ExtensionType.ARTIFACTS, "myarts",
ExtensionState.REQUIRED);
+ e2.getArtifacts().add(new Artifact(ArtifactId.fromMvnId("g:c:2")));
+ f2.getExtensions().add(e2);
+
+ AnalyserTaskContext ctx = testExecute("SAME", f1, f2, "myarts");
+
+ Mockito.verify(ctx).reportError(Mockito.anyString());
+ }
+
+ @Test
+ public void testAssertEmptyArtifactsNotDifferent() throws Exception {
+ Feature f = new Feature(ArtifactId.fromMvnId("g:a:123"));
+ Feature fc = new Feature(ArtifactId.fromMvnId("g:b:456"));
+
+ AnalyserTaskContext ctx = testExecute("DIFFERENT", f, fc);
+
+ Mockito.verify(ctx).reportError(Mockito.anyString());
+ }
+
+ @Test
+ public void testAssertDiffSizeArtifactsDifferent() throws Exception {
+ Artifact art1 = new Artifact(ArtifactId.fromMvnId("a:b:1"));
+ art1.getMetadata().put("foo", "bar");
+
+ Artifact art2 = new Artifact(ArtifactId.fromMvnId("a:b:1"));
+
+ Feature f = new Feature(ArtifactId.fromMvnId("g:a:123"));
+ f.getBundles().add(art1);
+ Feature fc = new Feature(ArtifactId.fromMvnId("g:b:456"));
+ fc.getBundles().add(art2);
+
+ @SuppressWarnings("unchecked")
+ AnalyserTaskContext ctx = testExecute("DIFFERENT", f, fc, null,
+ new AbstractMap.SimpleEntry<>("compare-metadata", "false"));
+ Mockito.verify(ctx).reportError(Mockito.anyString());
+
+ @SuppressWarnings("unchecked")
+ AnalyserTaskContext ctx2 = testExecute("DIFFERENT", f, fc, null,
+ new AbstractMap.SimpleEntry<>("compare-metadata", "true"));
+ Mockito.verify(ctx2, Mockito.never()).reportError(Mockito.anyString());
+ }
+
+ private AnalyserTaskContext testExecute(String mode, Feature f, Feature
fc) throws Exception {
+ return testExecute(mode, f, fc, null);
+ }
+
+ private AnalyserTaskContext testExecute(Feature f, Feature fc) throws
Exception {
+ return testExecute(null, f, fc, null);
+ }
+
+ private AnalyserTaskContext testExecute(Feature f, Feature fc, String
extension) throws Exception {
+ return testExecute(null, f, fc, extension);
+ }
+
+ @SuppressWarnings("unchecked")
+ private AnalyserTaskContext testExecute(String mode, Feature f, Feature
fc, String extension) throws Exception {
+ return testExecute(mode, f, fc, extension, new Map.Entry[0]);
+ }
+
+ private AnalyserTaskContext testExecute(String mode, Feature f, Feature
fc, String extension,
+ @SuppressWarnings("unchecked") Map.Entry<String, String> ...
cfgEntries) throws Exception {
+ Map<String, String> cfg = new HashMap<>();
+ cfg.put("compare-with", f.getId().toMvnId());
+
+ if (mode != null) {
+ cfg.put("compare-mode", mode);
+ }
+
+ if (extension != null) {
+ cfg.put("compare-extension", extension);
+ }
+
+ for (Map.Entry<String, String> entry : cfgEntries) {
+ cfg.put(entry.getKey(), entry.getValue());
+ }
+
+ CheckCompareFeatures cfe = new CheckCompareFeatures();
+
+ FeatureProvider fp = new FeatureProvider() {
+ @Override
+ public Feature provide(ArtifactId id) {
+ if ("g:a:123".equals(id.toMvnId())) {
+ return f;
+ }
+ return null;
+ }
+ };
+
+ AnalyserTaskContext ctx = Mockito.mock(AnalyserTaskContext.class);
+ Mockito.when(ctx.getConfiguration()).thenReturn(cfg);
+ Mockito.when(ctx.getFeatureProvider()).thenReturn(fp);
+ Mockito.when(ctx.getFeature()).thenReturn(fc);
+
+ cfe.execute(ctx);
+ return ctx;
+ }
+}
diff --git
a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoinitTest.java
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoinitTest.java
index 517e1fa..1355e52 100644
---
a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoinitTest.java
+++
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoinitTest.java
@@ -32,6 +32,7 @@ import org.apache.sling.feature.ExtensionType;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.analyser.task.AnalyserTask;
import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+import org.apache.sling.feature.builder.FeatureProvider;
import org.apache.sling.feature.scanner.BundleDescriptor;
import org.apache.sling.feature.scanner.FeatureDescriptor;
import org.junit.Test;
@@ -131,6 +132,11 @@ public class CheckRepoinitTest {
}
@Override
+ public FeatureProvider getFeatureProvider() {
+ return null;
+ }
+
+ @Override
public void reportWarning(String message) {
}