blob: 53ed1ce79e0eda099dac4dcf457b23577ef252db [file] [log] [blame]
/*
* 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.builder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.apache.felix.utils.resource.CapabilityImpl;
import org.apache.felix.utils.resource.RequirementImpl;
import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Configuration;
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.MatchingRequirement;
import org.apache.sling.feature.Prototype;
import org.junit.Test;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
public class FeatureBuilderTest {
private static final Map<String, Feature> FEATURES = new HashMap<>();
static {
final Feature f1 = new Feature(ArtifactId.parse("g/a/1"));
f1.getVariables().put("varx", "myvalx");
f1.getFrameworkProperties().put("foo", "2");
f1.getFrameworkProperties().put("bar", "X");
f1.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/foo-bar/4.5.6", 3));
f1.getBundles().add(BuilderUtilTest.createBundle("group/testnewversion_low/2", 5));
f1.getBundles().add(BuilderUtilTest.createBundle("group/testnewversion_high/2", 5));
f1.getBundles().add(BuilderUtilTest.createBundle("group/testnewstartlevel/1", 5));
f1.getBundles().add(BuilderUtilTest.createBundle("group/testnewstartlevelandversion/1", 5));
final Configuration c1 = new Configuration("org.apache.sling.foo");
c1.getProperties().put("prop", "value");
f1.getConfigurations().add(c1);
FEATURES.put(f1.getId().toMvnId(), f1);
}
static {
final Feature f2 = new Feature(ArtifactId.parse("g/a/2"));
f2.getBundles().add(BuilderUtilTest.createBundle("group/testmulti/1", 4));
f2.getBundles().add(BuilderUtilTest.createBundle("group/testmulti/2", 8));
f2.getBundles().add(BuilderUtilTest.createBundle("group/someart/1.2.3", 4));
FEATURES.put(f2.getId().toMvnId(), f2);
}
static {
final Feature f3 = new Feature(ArtifactId.parse("g/a/3"));
f3.getBundles().add(BuilderUtilTest.createBundle("group/testmulti/2", 8));
f3.getBundles().add(BuilderUtilTest.createBundle("group/someart/1.2.3", 4));
FEATURES.put(f3.getId().toMvnId(), f3);
}
private final FeatureProvider provider = new FeatureProvider() {
@Override
public Feature provide(final ArtifactId id) {
return FEATURES.get(id.getGroupId() + ":" + id.getArtifactId() + ":" + id.getVersion());
}
};
private void equals(final Feature expected, final Feature actuals) {
assertFalse(expected.isAssembled());
assertTrue(actuals.isAssembled());
assertEquals(expected.getId(), actuals.getId());
assertEquals(expected.getTitle(), actuals.getTitle());
assertEquals(expected.getDescription(), actuals.getDescription());
assertEquals(expected.getVendor(), actuals.getVendor());
assertEquals(expected.getLicense(), actuals.getLicense());
// variables
assertEquals(expected.getVariables(), actuals.getVariables());
// bundles
final List<Artifact> expectedBundles = expected.getBundles();
final List<Artifact> actualsBundles = actuals.getBundles();
assertEquals(expectedBundles.size(), actualsBundles.size());
for (int i = 0; i < expectedBundles.size(); i++) {
final Artifact eb = expectedBundles.get(i);
final Artifact ab = actualsBundles.get(i);
assertEquals(eb.getId(), ab.getId());
assertEquals("Start order of bundle " + eb, eb.getStartOrder(), ab.getStartOrder());
assertEquals("Metadata of bundle " + eb, eb.getMetadata(), ab.getMetadata());
}
// configurations
assertEquals(expected.getConfigurations().size(), actuals.getConfigurations().size());
for(final Configuration cfg : expected.getConfigurations()) {
final Configuration found = actuals.getConfigurations().getConfiguration(cfg.getPid());
assertNotNull("Configuration " + cfg, found);
assertEquals("Configuration " + cfg, cfg.getProperties(), found.getProperties());
}
// frameworkProperties
assertEquals(expected.getFrameworkProperties(), actuals.getFrameworkProperties());
// requirements
assertEquals(expected.getRequirements().size(), actuals.getRequirements().size());
for(final Requirement r : expected.getRequirements()) {
boolean found = false;
for(final Requirement i : actuals.getRequirements()) {
if (Objects.equals(r.getResource(), i.getResource())
&& Objects.equals(r.getNamespace(), i.getNamespace())
&& Objects.equals(r.getAttributes(), i.getAttributes())
&& Objects.equals(i.getDirectives(), i.getDirectives())) {
found = true;
break;
}
}
assertTrue(found);
}
// capabilities
assertEquals(expected.getCapabilities().size(), actuals.getCapabilities().size());
for(final Capability r : expected.getCapabilities()) {
boolean found = false;
for(final Capability i : actuals.getCapabilities()) {
if (Objects.equals(r.getResource(), i.getResource())
&& Objects.equals(r.getNamespace(), i.getNamespace())
&& Objects.equals(r.getAttributes(), i.getAttributes())
&& Objects.equals(i.getDirectives(), i.getDirectives())) {
found = true;
break;
}
}
assertTrue(found);
}
// extensions
assertEquals(expected.getExtensions().size(), actuals.getExtensions().size());
for(final Extension ext : expected.getExtensions()) {
final Extension inner = actuals.getExtensions().getByName(ext.getName());
assertNotNull(inner);
assertEquals(ext.getType(), inner.getType());
switch ( ext.getType()) {
case JSON : assertEquals(ext.getJSON(), inner.getJSON());
break;
case TEXT : assertEquals(ext.getText(), inner.getText());
break;
case ARTIFACTS : assertEquals(ext.getArtifacts().size(), inner.getArtifacts().size());
for(final Artifact art : ext.getArtifacts()) {
boolean found = false;
for(final Artifact i : inner.getArtifacts()) {
if ( art.getId().equals(i.getId()) ) {
found = true;
assertEquals(art.getMetadata(), i.getMetadata());
break;
}
}
assertTrue(found);
}
}
}
// includes should always be empty
assertNull(actuals.getPrototype());
}
@Test public void testMergeMultipleVersions() {
Feature a = new Feature(ArtifactId.fromMvnId("g:a:1"));
Feature b = new Feature(ArtifactId.fromMvnId("g:b:1"));
a.getBundles().add(BuilderUtilTest.createBundle("o/a/1.0.0", 10));
a.getBundles().add(BuilderUtilTest.createBundle("o/a/2.0.0", 9));
a.getBundles().add(BuilderUtilTest.createBundle("o/a/3.0.0", 11));
b.getBundles().add(BuilderUtilTest.createBundle("o/a/4.0.0", 8));
b.getBundles().add(BuilderUtilTest.createBundle("o/a/5.0.0", 12));
b.getBundles().add(BuilderUtilTest.createBundle("o/a/6.0.0", 10));
Feature ab = new Feature(ArtifactId.fromMvnId("g:ab:1"));
ab.getBundles().add(BuilderUtilTest.createBundle("o/a/6.0.0", 8));
Feature assembled = FeatureBuilder.assemble(ArtifactId.fromMvnId("g:ab:1"), new BuilderContext(provider)
.addArtifactsOverride(ArtifactId.fromMvnId("o:a:HIGHEST")), a, b);
assembled.getExtensions().clear();
equals(ab, assembled );
ab = new Feature(ArtifactId.fromMvnId("g:ab:1"));
ab.getBundles().add(BuilderUtilTest.createBundle("o/a/6.0.0", 8));
assembled = FeatureBuilder.assemble(ArtifactId.fromMvnId("g:ab:1"), new BuilderContext(provider)
.addArtifactsOverride(ArtifactId.fromMvnId("o:a:LATEST")), a, b);
assembled.getExtensions().clear();
equals(ab, assembled );
ab = new Feature(ArtifactId.fromMvnId("g:ab:1"));
ab.getBundles().addAll(a.getBundles());
ab.getBundles().addAll(b.getBundles());
assembled = FeatureBuilder.assemble(ArtifactId.fromMvnId("g:ab:1"), new BuilderContext(provider)
.addArtifactsOverride(ArtifactId.fromMvnId("o:a:ALL")), a, b);
assembled.getExtensions().clear();
equals(ab, assembled );
a.getBundles().get(1).setStartOrder(1);
ab = new Feature(ArtifactId.fromMvnId("g:ab:1"));
ab.getBundles().add(BuilderUtilTest.createBundle("o/a/6.0.0", 1));
ab.getBundles().get(0).setStartOrder(1);
assembled = FeatureBuilder.assemble(ArtifactId.fromMvnId("g:ab:1"), new BuilderContext(provider)
.addArtifactsOverride(ArtifactId.fromMvnId("o:a:LATEST")), a, b);
assembled.getExtensions().clear();
equals(ab, assembled);
}
@Test public void testNoIncludesNoUpgrade() throws Exception {
final Feature base = new Feature(ArtifactId.parse("org.apache.sling/test-feature/1.1"));
final MatchingRequirement r1 = new MatchingRequirementImpl(null, "osgi.contract",
Collections.singletonMap("filter", "(&(osgi.contract=JavaServlet)(version=3.1))"), null);
base.getRequirements().add(r1);
Map<String, Object> attrs = new HashMap<>();
attrs.put("osgi.implementation", "osgi.http");
attrs.put("version:Version", "1.1");
final Capability c1 = new CapabilityImpl(null, "osgi.implementation",
Collections.singletonMap("uses", "javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"),
attrs);
base.getCapabilities().add(c1);
final Capability c2 = new CapabilityImpl(null, "osgi.service",
Collections.singletonMap("uses", "org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"),
Collections.singletonMap("objectClass:List<String>", "org.osgi.service.http.runtime.HttpServiceRuntime"));
base.getCapabilities().add(c2);
base.getFrameworkProperties().put("foo", "1");
base.getFrameworkProperties().put("brave", "something");
base.getFrameworkProperties().put("org.apache.felix.scr.directory", "launchpad/scr");
final Artifact a1 = new Artifact(ArtifactId.parse("org.apache.sling/oak-server/1.0.0"));
a1.getMetadata().put(Artifact.KEY_START_ORDER, "1");
a1.getMetadata().put("hash", "4632463464363646436");
base.getBundles().add(a1);
base.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/application-bundle/2.0.0", 1));
base.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/another-bundle/2.1.0", 1));
base.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/foo-xyz/1.2.3", 2));
final Configuration co1 = new Configuration("my.pid");
co1.getProperties().put("foo", 5L);
co1.getProperties().put("bar", "test");
co1.getProperties().put("number", 7);
base.getConfigurations().add(co1);
final Configuration co2 = new Configuration("my.factory.pid~name");
co2.getProperties().put("a.value", "yeah");
base.getConfigurations().add(co2);
assertFalse(base.isAssembled());
final Feature assembled = FeatureBuilder.assemble(base, new BuilderContext(provider));
equals(base, assembled);
}
@Test public void testSingleInclude() throws Exception {
final Feature base = new Feature(ArtifactId.parse("org.apache.sling/test-feature/1.1"));
final Prototype i1 = new Prototype(ArtifactId.parse("g/a/1"));
base.setPrototype(i1);
final MatchingRequirement r1 = new MatchingRequirementImpl(null, "osgi.contract",
Collections.singletonMap("filter", "(&(osgi.contract=JavaServlet)(version=3.1))"), null);
base.getRequirements().add(r1);
Map<String, Object> attrs = new HashMap<>();
attrs.put("osgi.implementation", "osgi.http");
attrs.put("version:Version", "1.1");
final Capability c1 = new CapabilityImpl(null, "osgi.implementation",
Collections.singletonMap("uses", "javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"),
attrs);
base.getCapabilities().add(c1);
i1.getFrameworkPropertiesRemovals().add("foo");
base.getFrameworkProperties().put("foo", "1");
base.getFrameworkProperties().put("brave", "something");
base.getFrameworkProperties().put("org.apache.felix.scr.directory", "launchpad/scr");
final Artifact a1 = new Artifact(ArtifactId.parse("org.apache.sling/oak-server/1.0.0"));
a1.getMetadata().put(Artifact.KEY_START_ORDER, "1");
a1.getMetadata().put("hash", "4632463464363646436");
base.getBundles().add(a1);
base.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/application-bundle/2.0.0", 1));
base.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/another-bundle/2.1.0", 1));
base.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/foo-xyz/1.2.3", 2));
base.getBundles().add(BuilderUtilTest.createBundle("group/testnewversion_low/1", 5));
base.getBundles().add(BuilderUtilTest.createBundle("group/testnewversion_high/5", 5));
base.getBundles().add(BuilderUtilTest.createBundle("group/testnewstartlevel/1", 10));
base.getBundles().add(BuilderUtilTest.createBundle("group/testnewstartlevelandversion/2", 10));
final Configuration co1 = new Configuration("my.pid");
co1.getProperties().put("foo", 5L);
co1.getProperties().put("bar", "test");
co1.getProperties().put("number", 7);
base.getConfigurations().add(co1);
final Configuration co2 = new Configuration("my.factory.pid~name");
co2.getProperties().put("a.value", "yeah");
base.getConfigurations().add(co2);
assertFalse(base.isAssembled());
// create the expected result
final Feature result = base.copy();
result.setPrototype(null);
result.getBundles().clear();
result.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/foo-bar/4.5.6", 3));
result.getBundles().add(BuilderUtilTest.createBundle("group/testnewversion_low/2", 5));
result.getBundles().add(BuilderUtilTest.createBundle("group/testnewversion_low/1", 5));
result.getBundles().add(BuilderUtilTest.createBundle("group/testnewversion_high/2", 5));
result.getBundles().add(BuilderUtilTest.createBundle("group/testnewversion_high/5", 5));
result.getBundles().add(BuilderUtilTest.createBundle("group/testnewstartlevel/1", 5));
result.getBundles().add(BuilderUtilTest.createBundle("group/testnewstartlevelandversion/1", 5));
result.getBundles().add(BuilderUtilTest.createBundle("group/testnewstartlevelandversion/2", 10));
result.getBundles().add(a1.copy(a1.getId()));
result.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/application-bundle/2.0.0", 1));
result.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/another-bundle/2.1.0", 1));
result.getBundles().add(BuilderUtilTest.createBundle("org.apache.sling/foo-xyz/1.2.3", 2));
result.getVariables().put("varx", "myvalx");
result.getFrameworkProperties().put("bar", "X");
final Configuration co3 = new Configuration("org.apache.sling.foo");
co3.getProperties().put("prop", "value");
result.getConfigurations().add(co3);
// assemble
final Feature assembled = FeatureBuilder.assemble(base, new BuilderContext(provider));
// and test
equals(result, assembled);
}
@Test public void testSingleIncludeMultiVersion() {
Feature base = new Feature(ArtifactId.fromMvnId("g:tgtart:1"));
Prototype i1 = new Prototype(ArtifactId.fromMvnId("g:a:3"));
base.setPrototype(i1);
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("g:myart:1")));
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("group:testmulti:1")));
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("group:testmulti:3")));
BuilderContext builderContext = new BuilderContext(provider);
Feature assembled = FeatureBuilder.assemble(base, builderContext);
Feature result = new Feature(ArtifactId.parse("g:tgtart:1"));
result.getBundles().add(BuilderUtilTest.createBundle("group/testmulti/2", 8));
Artifact b1 = new Artifact(ArtifactId.fromMvnId("group:testmulti:1"));
result.getBundles().add(b1);
Artifact b2 = new Artifact(ArtifactId.fromMvnId("group:testmulti:3"));
result.getBundles().add(b2);
Artifact b3 = new Artifact(ArtifactId.fromMvnId("group:someart:1.2.3"));
b3.setStartOrder(4);
result.getBundles().add(b3);
Artifact b0 = new Artifact(ArtifactId.fromMvnId("g:myart:1"));
result.getBundles().add(b0);
equals(result, assembled);
}
@Test public void testSingleIncludeMultiVersion2() {
Feature base = new Feature(ArtifactId.fromMvnId("g:tgtart:1"));
Prototype i1 = new Prototype(ArtifactId.fromMvnId("g:a:2"));
base.setPrototype(i1);
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("g:myart:1")));
BuilderContext builderContext = new BuilderContext(provider);
Feature assembled = FeatureBuilder.assemble(base, builderContext);
Feature result = new Feature(ArtifactId.parse("g:tgtart:1"));
Artifact b1 = new Artifact(ArtifactId.fromMvnId("group:testmulti:1"));
b1.setStartOrder(4);
result.getBundles().add(b1);
Artifact b2 = new Artifact(ArtifactId.fromMvnId("group:testmulti:2"));
b2.setStartOrder(8);
result.getBundles().add(b2);
Artifact b3 = new Artifact(ArtifactId.fromMvnId("group:someart:1.2.3"));
b3.setStartOrder(4);
result.getBundles().add(b3);
Artifact b0 = new Artifact(ArtifactId.fromMvnId("g:myart:1"));
result.getBundles().add(b0);
equals(result, assembled);
}
@Test public void testSingleIncludeMultiVersion3() {
Feature base = new Feature(ArtifactId.fromMvnId("g:tgtart:1"));
Prototype i1 = new Prototype(ArtifactId.fromMvnId("g:a:2"));
base.setPrototype(i1);
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("g:myart:1")));
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("group:testmulti:1")));
BuilderContext builderContext = new BuilderContext(provider);
Feature assembled = FeatureBuilder.assemble(base, builderContext);
Feature result = new Feature(ArtifactId.parse("g:tgtart:1"));
result.getBundles().add(BuilderUtilTest.createBundle("group/testmulti/2", 8));
Artifact b1 = new Artifact(ArtifactId.fromMvnId("group:testmulti:1"));
b1.setStartOrder(4);
result.getBundles().add(b1);
Artifact b3 = new Artifact(ArtifactId.fromMvnId("group:someart:1.2.3"));
b3.setStartOrder(4);
result.getBundles().add(b3);
Artifact b0 = new Artifact(ArtifactId.fromMvnId("g:myart:1"));
result.getBundles().add(b0);
equals(result, assembled);
}
@Test public void testSingleIncludeMultiVersion4() {
Feature base = new Feature(ArtifactId.fromMvnId("g:tgtart:1"));
Prototype i1 = new Prototype(ArtifactId.fromMvnId("g:a:2"));
base.setPrototype(i1);
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("g:myart:1")));
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("group:testmulti:1")));
base.getBundles().add(new Artifact(ArtifactId.fromMvnId("group:testmulti:3")));
BuilderContext builderContext = new BuilderContext(provider);
Feature assembled = FeatureBuilder.assemble(base, builderContext);
Feature result = new Feature(ArtifactId.parse("g:tgtart:1"));
result.getBundles().add(BuilderUtilTest.createBundle("group/testmulti/2", 8));
Artifact b1 = new Artifact(ArtifactId.fromMvnId("group:testmulti:1"));
b1.setStartOrder(4);
result.getBundles().add(b1);
Artifact b2 = new Artifact(ArtifactId.fromMvnId("group:testmulti:3"));
result.getBundles().add(b2);
Artifact b3 = new Artifact(ArtifactId.fromMvnId("group:someart:1.2.3"));
b3.setStartOrder(4);
result.getBundles().add(b3);
Artifact b0 = new Artifact(ArtifactId.fromMvnId("g:myart:1"));
result.getBundles().add(b0);
equals(result, assembled);
}
@Test public void testDeduplicationInclude() throws Exception {
final ArtifactId idA = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId idB = ArtifactId.fromMvnId("g:b:1.0.0");
final Feature a = new Feature(idA);
final Feature b = new Feature(idB);
// feature b includes feature a
final Prototype inc = new Prototype(idA);
b.setPrototype(inc);
// assemble application, it should only contain feature b as a is included by b
Feature[] features = FeatureBuilder.deduplicate(new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
return null;
}
}), a, b);
assertEquals(1, features.length);
assertEquals(idB, features[0].getId());
}
@Test public void testDeduplicationVersion() throws Exception {
final ArtifactId idA = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId idB = ArtifactId.fromMvnId("g:a:1.1.0");
final Feature a = new Feature(idA);
final Feature b = new Feature(idB);
// assemble application, it should only contain feature b as a is included by b
Feature[] features = FeatureBuilder.deduplicate(new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
return null;
}
}), a, b);
assertEquals(1, features.length);
assertEquals(idB, features[0].getId());
}
@Test public void testMergeIncludeDedup() throws Exception {
final ArtifactId idA = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId idB = ArtifactId.fromMvnId("g:b:1.0.0");
final Feature a = new Feature(idA);
ArtifactId b1ID = ArtifactId.fromMvnId("g:bundle1:1.2.3");
ArtifactId b2ID = ArtifactId.fromMvnId("g:bundle2:4.5.6");
Artifact b1 = new Artifact(b1ID);
Artifact b2 = new Artifact(b2ID);
a.getBundles().add(b1);
a.getBundles().add(b2);
final Feature b = new Feature(idB);
// feature b includes feature a and removes a bundle
final Prototype inc = new Prototype(idA);
b.setPrototype(inc);
inc.getBundleRemovals().add(b1ID);
// Merge all features together
ArtifactId c = ArtifactId.fromMvnId("g:c:1.0.0");
Feature fc = FeatureBuilder.assemble(c, new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
return null;
}
}), a, b);
// Test that the feature that acted as a prototype is not included in the merge.
assertEquals(1, fc.getBundles().size());
assertEquals(b2, fc.getBundles().iterator().next());
}
@Test public void testBundleRemoveWithExactVersion() throws Exception {
final ArtifactId bundleA1 = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId bundleA2 = ArtifactId.fromMvnId("g:a:1.1.0");
final ArtifactId bundleB = ArtifactId.fromMvnId("g:b:1.1.0");
final Feature a = new Feature(ArtifactId.fromMvnId("g:a-base:1"));
a.getBundles().add(new Artifact(bundleA1));
a.getBundles().add(new Artifact(bundleA2));
a.getBundles().add(new Artifact(bundleB));
final Feature b = new Feature(ArtifactId.fromMvnId("g:a-include:1"));
final Prototype inc = new Prototype(a.getId());
inc.getBundleRemovals().add(bundleA2);
b.setPrototype(inc);
// assemble feature include
Feature feature = FeatureBuilder.assemble(b, new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
if ( id.equals(a.getId()) ) {
return a;
}
return null;
}
}));
final Set<ArtifactId> set = new HashSet<>();
for(final Artifact c : feature.getBundles()) {
set.add(c.getId());
}
assertEquals(2, set.size());
assertTrue(set.contains(bundleA1));
assertTrue(set.contains(bundleB));
}
@Test public void testBundleRemoveWithAnyVersion() throws Exception {
final ArtifactId bundleA1 = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId bundleA2 = ArtifactId.fromMvnId("g:a:1.1.0");
final ArtifactId bundleB = ArtifactId.fromMvnId("g:b:1.1.0");
final Feature a = new Feature(ArtifactId.fromMvnId("g:a-base:1"));
a.getBundles().add(new Artifact(bundleA1));
a.getBundles().add(new Artifact(bundleA2));
a.getBundles().add(new Artifact(bundleB));
final Feature b = new Feature(ArtifactId.fromMvnId("g:a-include:1"));
final Prototype inc = new Prototype(a.getId());
inc.getBundleRemovals().add(ArtifactId.fromMvnId("g:a:0.0.0"));
b.setPrototype(inc);
// assemble feature include
Feature feature = FeatureBuilder.assemble(b, new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
if ( id.equals(a.getId()) ) {
return a;
}
return null;
}
}));
final Set<ArtifactId> set = new HashSet<>();
for(final Artifact c : feature.getBundles()) {
set.add(c.getId());
}
assertEquals(1, set.size());
assertTrue(set.contains(bundleB));
}
@Test public void testBundleRemoveNoMatch() throws Exception {
final ArtifactId bundleA1 = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId bundleA2 = ArtifactId.fromMvnId("g:a:1.1.0");
final ArtifactId bundleB = ArtifactId.fromMvnId("g:b:1.1.0");
final Feature a = new Feature(ArtifactId.fromMvnId("g:a-base:1"));
a.getBundles().add(new Artifact(bundleA1));
a.getBundles().add(new Artifact(bundleB));
final Feature b = new Feature(ArtifactId.fromMvnId("g:a-include:1"));
final Prototype inc = new Prototype(a.getId());
inc.getBundleRemovals().add(bundleA2);
b.setPrototype(inc);
try {
FeatureBuilder.assemble(b, new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
if ( id.equals(a.getId()) ) {
return a;
}
return null;
}
}));
fail();
} catch ( final IllegalStateException ise) {
// expected
}
}
@Test public void testExtensionArtifactRemoveWithExactVersion() throws Exception {
final ArtifactId bundleA1 = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId bundleA2 = ArtifactId.fromMvnId("g:a:1.1.0");
final ArtifactId bundleB = ArtifactId.fromMvnId("g:b:1.1.0");
final Feature a = new Feature(ArtifactId.fromMvnId("g:a-base:1"));
final Extension e = new Extension(ExtensionType.ARTIFACTS, "foo", ExtensionState.OPTIONAL);
e.getArtifacts().add(new Artifact(bundleA1));
e.getArtifacts().add(new Artifact(bundleA2));
e.getArtifacts().add(new Artifact(bundleB));
a.getExtensions().add(e);
final Feature b = new Feature(ArtifactId.fromMvnId("g:a-include:1"));
final Prototype inc = new Prototype(a.getId());
inc.getArtifactExtensionRemovals().put("foo", Arrays.asList(bundleA2));
b.setPrototype(inc);
// assemble feature include
Feature feature = FeatureBuilder.assemble(b, new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
if ( id.equals(a.getId()) ) {
return a;
}
return null;
}
}));
final Set<ArtifactId> set = new HashSet<>();
for(final Artifact c : feature.getExtensions().getByName("foo").getArtifacts()) {
set.add(c.getId());
}
assertEquals(2, set.size());
assertTrue(set.contains(bundleA1));
assertTrue(set.contains(bundleB));
}
@Test public void testExtensionArtifactRemoveWithAnyVersion() throws Exception {
final ArtifactId bundleA1 = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId bundleA2 = ArtifactId.fromMvnId("g:a:1.1.0");
final ArtifactId bundleB = ArtifactId.fromMvnId("g:b:1.1.0");
final Feature a = new Feature(ArtifactId.fromMvnId("g:a-base:1"));
final Extension e = new Extension(ExtensionType.ARTIFACTS, "foo", ExtensionState.OPTIONAL);
e.getArtifacts().add(new Artifact(bundleA1));
e.getArtifacts().add(new Artifact(bundleA2));
e.getArtifacts().add(new Artifact(bundleB));
a.getExtensions().add(e);
final Feature b = new Feature(ArtifactId.fromMvnId("g:a-include:1"));
final Prototype inc = new Prototype(a.getId());
inc.getArtifactExtensionRemovals().put("foo", Arrays.asList(ArtifactId.fromMvnId("g:a:0.0.0")));
b.setPrototype(inc);
// assemble feature include
Feature feature = FeatureBuilder.assemble(b, new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
if ( id.equals(a.getId()) ) {
return a;
}
return null;
}
}));
final Set<ArtifactId> set = new HashSet<>();
for(final Artifact c : feature.getExtensions().getByName("foo").getArtifacts()) {
set.add(c.getId());
}
assertEquals(1, set.size());
assertTrue(set.contains(bundleB));
}
@Test public void testExtensionArtifactRemoveNoMatch() throws Exception {
final ArtifactId bundleA1 = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId bundleA2 = ArtifactId.fromMvnId("g:a:1.1.0");
final ArtifactId bundleB = ArtifactId.fromMvnId("g:b:1.1.0");
final Feature a = new Feature(ArtifactId.fromMvnId("g:a-base:1"));
final Extension e = new Extension(ExtensionType.ARTIFACTS, "foo", ExtensionState.OPTIONAL);
e.getArtifacts().add(new Artifact(bundleA1));
e.getArtifacts().add(new Artifact(bundleB));
a.getExtensions().add(e);
final Feature b = new Feature(ArtifactId.fromMvnId("g:a-include:1"));
final Prototype inc = new Prototype(a.getId());
inc.getArtifactExtensionRemovals().put("foo", Arrays.asList(bundleA2));
b.setPrototype(inc);
try {
FeatureBuilder.assemble(b, new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
if ( id.equals(a.getId()) ) {
return a;
}
return null;
}
}));
fail();
} catch ( final IllegalStateException ise) {
// expected
}
}
@Test public void testIncludedFeatureProvided() throws Exception {
final ArtifactId idA = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId idB = ArtifactId.fromMvnId("g:b:1.0.0");
final Feature a = new Feature(idA);
final Feature b = new Feature(idB);
// feature b includes feature a
final Prototype inc = new Prototype(idA);
b.setPrototype(inc);
// assemble feature, it should only contain feature b as a is included by b
final Feature target = FeatureBuilder.assemble(ArtifactId.fromMvnId("g:F:1.0.0"), new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
return null;
}
}), a, b);
final Extension list = target.getExtensions().getByName(Extension.EXTENSION_NAME_ASSEMBLED_FEATURES);
assertNotNull(list);
assertEquals(1, list.getArtifacts().size());
assertEquals(idB, list.getArtifacts().get(0).getId());
}
@Test public void testHandleVars() throws Exception {
ArtifactId aid = new ArtifactId("gid", "aid", "1.2.3", null, null);
Feature feature = new Feature(aid);
Map<String,String> kvMap = feature.getVariables();
kvMap.put("var1", "bar");
kvMap.put("varvariable", "${myvar}");
kvMap.put("var.2", "2");
assertEquals("foobarfoo", FeatureBuilder.replaceVariables("foo${var1}foo", null, feature));
assertEquals("barbarbar", FeatureBuilder.replaceVariables("${var1}${var1}${var1}", null, feature));
assertEquals("${}test${myvar}2", FeatureBuilder.replaceVariables("${}test${varvariable}${var.2}", null, feature ));
assertEquals("${undefined}",FeatureBuilder.replaceVariables("${undefined}", null, feature));
}
@Test public void testHandleVarsWithConflict() throws Exception {
ArtifactId aid = new ArtifactId("gid", "aid", "1.2.3", null, null);
ArtifactId bid = new ArtifactId("gid", "bid", "2.0.0", null, null);
Feature aFeature = new Feature(aid);
Feature bFeature = new Feature(bid);
Map<String,String> kvMapA = aFeature.getVariables();
kvMapA.put("var1", "val1");
kvMapA.put("var2", "val2");
Map<String,String> kvMapB = bFeature.getVariables();
kvMapB.put("var1", "val1");
kvMapB.put("var2", "val2");
kvMapB.put("var3", "val3");
Map<String,String> override = new HashMap<>();
override.put("var3", "valo");
override.put("val4", "notused");
Feature cFeature = FeatureBuilder.assemble(new ArtifactId("gid", "cid", "3.0.0", null, null), new BuilderContext(new FeatureProvider()
{
@Override
public Feature provide(ArtifactId id)
{
return null;
}
}).addVariablesOverrides(override), aFeature, bFeature);
Map<String,String> vars = new HashMap<>();
vars.putAll(kvMapA);
vars.putAll(kvMapB);
assertFalse(cFeature.getVariables().equals(vars));
vars.put("var3", "valo");
assertTrue(cFeature.getVariables().equals(vars));
kvMapB.put("var2", "valm");
try {
FeatureBuilder.assemble(new ArtifactId("gid", "cid", "3.0.0", null, null), new BuilderContext(new FeatureProvider()
{
@Override
public Feature provide(ArtifactId id)
{
return null;
}
}).addVariablesOverrides(override), aFeature, bFeature);
fail("Excepted merge exception");
} catch (IllegalStateException expected) {}
override.put("var2", "valo");
cFeature = FeatureBuilder.assemble(new ArtifactId("gid", "cid", "3.0.0", null, null), new BuilderContext(new FeatureProvider()
{
@Override
public Feature provide(ArtifactId id)
{
return null;
}
}).addVariablesOverrides(override), aFeature, bFeature);
vars = new HashMap<>();
vars.putAll(kvMapA);
vars.putAll(kvMapB);
vars.put("var2", "valo");
vars.put("var3", "valo");
assertTrue(cFeature.getVariables().equals(vars));
override.put("var2", null);
cFeature = FeatureBuilder.assemble(new ArtifactId("gid", "cid", "3.0.0", null, null), new BuilderContext(new FeatureProvider()
{
@Override
public Feature provide(ArtifactId id)
{
return null;
}
}).addVariablesOverrides(override), aFeature, bFeature);
vars.put("var2", null);
assertTrue(cFeature.getVariables().equals(vars));
}
@Test
public void testFinalFlag() throws Exception {
// feature inclusion without final flag is already tested by other tests
final ArtifactId idA = ArtifactId.fromMvnId("g:a:1.0.0");
final ArtifactId idB = ArtifactId.fromMvnId("g:b:1.0.0");
final Feature a = new Feature(idA);
a.setFinal(true);
final Feature b = new Feature(idB);
// feature b includes feature a
final Prototype inc = new Prototype(idA);
b.setPrototype(inc);
// assemble feature, this should throw an exception
try {
FeatureBuilder.assemble(b, new BuilderContext(new FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
if (id.equals(idA)) {
return a;
}
return null;
}
}));
fail();
} catch (final IllegalStateException ise) {
assertTrue(ise.getMessage().contains(" final "));
}
}
@Test
public void testConfigurationMerge() {
Feature a = new Feature(ArtifactId.fromMvnId("g:a:1.0.0"));
a.getConfigurations().add(new Configuration("foo"));
Feature b = new Feature(ArtifactId.fromMvnId("g:b:1.0.0"));
b.getConfigurations().add(new Configuration("bar"));
Feature c = FeatureBuilder.assemble(ArtifactId.fromMvnId("g:c:1.0.0"), new BuilderContext(provider), a, b);
c.getExtensions().clear();
Feature test = new Feature(ArtifactId.fromMvnId("g:c:1.0.0"));
test.getConfigurations().add(new Configuration("foo"));
test.getConfigurations().add(new Configuration("bar"));
assertEquals(test, c);
b.getConfigurations().add(new Configuration("foo"));
try
{
FeatureBuilder.assemble(ArtifactId.fromMvnId("g:c:1.0.0"), new BuilderContext(provider), a, b);
fail();
} catch (IllegalStateException ex) {
}
b.getConfigurations().get(0).getProperties().put("foo", "bar");
c = FeatureBuilder.assemble(ArtifactId.fromMvnId("g:c:1.0.0"), new BuilderContext(provider).addConfigsOverrides(Collections.singletonMap("*", BuilderContext.CONFIG_USE_LATEST)), a, b);
test.getConfigurations().add(b.getConfigurations().get(0));
c.getExtensions().clear();
assertEquals(test, c);
}
private static class MatchingRequirementImpl extends RequirementImpl implements MatchingRequirement {
public MatchingRequirementImpl(Resource res, String ns, Map<String, String> dirs, Map<String, Object> attrs) {
super(res, ns, dirs, attrs);
}
}
}