blob: 218bfeb6a68f9255713266a86d98b24a31dc7a1d [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.apiregions.impl;
import static org.apache.sling.feature.apiregions.impl.RegionConfiguration.APIREGIONS_JOINGLOBAL;
import static org.apache.sling.feature.apiregions.impl.RegionConfiguration.BUNDLE_FEATURE_FILENAME;
import static org.apache.sling.feature.apiregions.impl.RegionConfiguration.DEFAULT_REGIONS;
import static org.apache.sling.feature.apiregions.impl.RegionConfiguration.FEATURE_REGION_FILENAME;
import static org.apache.sling.feature.apiregions.impl.RegionConfiguration.IDBSNVER_FILENAME;
import static org.apache.sling.feature.apiregions.impl.RegionConfiguration.PROPERTIES_FILE_LOCATION;
import static org.apache.sling.feature.apiregions.impl.RegionConfiguration.PROPERTIES_RESOURCE_PREFIX;
import static org.apache.sling.feature.apiregions.impl.RegionConfiguration.REGION_PACKAGE_FILENAME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import org.mockito.Mockito;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Version;
import org.osgi.framework.hooks.resolver.ResolverHook;
public class RegionConfigurationTest {
@Test
public void testRegionConfigurationNoConfiguration() throws Exception {
BundleContext ctx = Mockito.mock(BundleContext.class);
try {
new RegionConfiguration(ctx, new Hashtable<String, Object>());
fail("Expected exception. Configuration is enabled but is missing configuration");
} catch (Exception e) {
// good
}
}
@Test
public void testLoadBSNVerMap() throws Exception {
String e = getClass().getResource("/empty.properties").getFile();
String f = getClass().getResource("/idbsnver1.properties").getFile();
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + IDBSNVER_FILENAME)).thenReturn(f);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + BUNDLE_FEATURE_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + REGION_PACKAGE_FILENAME)).thenReturn(e);
Hashtable<String, Object> props = new Hashtable<>();
RegionConfiguration re = new RegionConfiguration(ctx, props);
assertEquals(2, re.bsnVerMap.size());
assertEquals(Collections.singletonList("g:b1:1"),
re.bsnVerMap.get(new AbstractMap.SimpleEntry<String,Version>("b1", new Version(1,0,0))));
assertEquals(new HashSet<>(Arrays.asList("g:b2:1.2.3", "g2:b2:1.2.4")),
new HashSet<>(re.bsnVerMap.get(new AbstractMap.SimpleEntry<String,Version>("b2", new Version(1,2,3)))));
assertEquals(new File(f).toURI().toString(), props.get(IDBSNVER_FILENAME));
}
@Test
public void testLoadBundleFeatureMap() throws Exception {
String e = getClass().getResource("/empty.properties").getFile();
String f = getClass().getResource("/bundles1.properties").getFile();
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + IDBSNVER_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + BUNDLE_FEATURE_FILENAME)).thenReturn(f);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + REGION_PACKAGE_FILENAME)).thenReturn(e);
Hashtable<String, Object> props = new Hashtable<>();
RegionConfiguration re = new RegionConfiguration(ctx, props);
assertEquals(3, re.bundleFeatureMap.size());
assertEquals(Collections.singleton("org.sling:something:1.2.3:slingosgifeature:myclassifier"),
re.bundleFeatureMap.get("org.sling:b1:1"));
assertEquals(Collections.singleton("org.sling:something:1.2.3:slingosgifeature:myclassifier"),
re.bundleFeatureMap.get("org.sling:b2:1"));
assertEquals(new HashSet<>(Arrays.asList("some.other:feature:123", "org.sling:something:1.2.3:slingosgifeature:myclassifier")),
re.bundleFeatureMap.get("org.sling:b3:1"));
assertEquals(new File(f).toURI().toString(), props.get(BUNDLE_FEATURE_FILENAME));
}
@Test
public void testLoadFeatureRegionMap() throws Exception {
String e = getClass().getResource("/empty.properties").getFile();
String f = getClass().getResource("/features1.properties").getFile();
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + IDBSNVER_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + BUNDLE_FEATURE_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).thenReturn(f);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + REGION_PACKAGE_FILENAME)).thenReturn(e);
Hashtable<String, Object> props = new Hashtable<>();
RegionConfiguration re = new RegionConfiguration(ctx, props);
assertEquals(2, re.featureRegionMap.size());
assertEquals(Collections.singleton("global"),
re.featureRegionMap.get("an.other:feature:123"));
assertEquals(new HashSet<>(Arrays.asList("global", "internal")),
re.featureRegionMap.get("org.sling:something:1.2.3"));
assertEquals(new File(f).toURI().toString(), props.get(FEATURE_REGION_FILENAME));
}
@Test
public void testLoadRegionPackageMap() throws Exception {
String e = getClass().getResource("/empty.properties").getFile();
String f = getClass().getResource("/regions1.properties").getFile();
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + IDBSNVER_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + BUNDLE_FEATURE_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + REGION_PACKAGE_FILENAME)).thenReturn(f);
Hashtable<String, Object> props = new Hashtable<>();
RegionConfiguration re = new RegionConfiguration(ctx, props);
assertEquals(2, re.regionPackageMap.size());
assertEquals(Collections.singleton("xyz"),
re.regionPackageMap.get("internal"));
assertEquals(new HashSet<>(Arrays.asList("a.b.c", "d.e.f", "test")),
re.regionPackageMap.get("global"));
assertEquals(new File(f).toURI().toString(), props.get(REGION_PACKAGE_FILENAME));
}
@Test
public void testJoinRegionsToGlobal() throws Exception {
String e = getClass().getResource("/empty.properties").getFile();
String f = getClass().getResource("/regions2.properties").getFile();
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(APIREGIONS_JOINGLOBAL)).thenReturn("obsolete,deprecated");
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + IDBSNVER_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + BUNDLE_FEATURE_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).thenReturn(e);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + REGION_PACKAGE_FILENAME)).thenReturn(f);
RegionConfiguration re = new RegionConfiguration(ctx, new Hashtable<String, Object>());
assertEquals(1, re.regionPackageMap.size());
assertEquals(new HashSet<>(Arrays.asList("xyz", "a.b.c", "d.e.f", "test")),
re.regionPackageMap.get("global"));
}
@Test
public void testBegin() throws Exception {
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + IDBSNVER_FILENAME)).
thenReturn(getClass().getResource("/idbsnver1.properties").getFile());
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + BUNDLE_FEATURE_FILENAME)).
thenReturn(getClass().getResource("/bundles1.properties").getFile());
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).
thenReturn(getClass().getResource("/features1.properties").getFile());
Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + REGION_PACKAGE_FILENAME)).
thenReturn(getClass().getResource("/regions1.properties").getFile());
RegionConfiguration re = new RegionConfiguration(ctx, new Hashtable<String, Object>());
assertTrue(re.bsnVerMap.size() > 0);
assertTrue(re.bundleFeatureMap.size() > 0);
assertTrue(re.featureRegionMap.size() > 0);
assertTrue(re.regionPackageMap.size() > 0);
ResolverHookImpl hook = (ResolverHookImpl) new RegionEnforcer(re).begin(null);
assertEquals(re.bsnVerMap, hook.configuration.bsnVerMap);
assertEquals(re.bundleFeatureMap, hook.configuration.bundleFeatureMap);
assertEquals(re.featureRegionMap, hook.configuration.featureRegionMap);
assertEquals(re.regionPackageMap, hook.configuration.regionPackageMap);
}
@Test
public void testURLs() throws Exception {
BundleContext ctx = Mockito.mock(BundleContext.class);
String location = new File(getClass().getResource("/props1/idbsnver.properties").
getFile()).getParentFile().toURI().toString();
Mockito.when(ctx.getProperty(PROPERTIES_FILE_LOCATION)).thenReturn(location);
RegionConfiguration re = new RegionConfiguration(ctx, new Hashtable<String, Object>());
assertTrue(re.bsnVerMap.size() > 0);
assertTrue(re.bundleFeatureMap.size() > 0);
assertTrue(re.featureRegionMap.size() > 0);
assertTrue(re.regionPackageMap.size() > 0);
}
@Test
public void testClassloaderURLs() throws Exception {
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(PROPERTIES_FILE_LOCATION)).
thenReturn("classloader://props1");
RegionConfiguration re = new RegionConfiguration(ctx, new Hashtable<String, Object>());
assertTrue(re.bsnVerMap.size() > 0);
assertTrue(re.bundleFeatureMap.size() > 0);
assertTrue(re.featureRegionMap.size() > 0);
assertTrue(re.regionPackageMap.size() > 0);
}
@Test
public void testOrderingOfRegionsInFeatures() throws Exception {
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(PROPERTIES_FILE_LOCATION)).
thenReturn("classloader://props2");
RegionConfiguration re = new RegionConfiguration(ctx, new Hashtable<String, Object>());
assertEquals(Arrays.asList("r0", "r1", "r2", "r3"),
new ArrayList<>(re.featureRegionMap.get("org.sling:something:1.2.3")));
}
@Test
public void testUnModifiableMaps() throws Exception {
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(PROPERTIES_FILE_LOCATION)).
thenReturn("classloader://props1");
RegionConfiguration re = new RegionConfiguration(ctx, new Hashtable<String, Object>());
assertTrue(re.bsnVerMap.size() > 0);
assertBSNVerMapUnmodifiable(re.bsnVerMap);
assertTrue(re.bundleFeatureMap.size() > 0);
assertMapUnmodifiable(re.bundleFeatureMap);
assertTrue(re.featureRegionMap.size() > 0);
assertMapUnmodifiable(re.featureRegionMap);
assertTrue(re.regionPackageMap.size() > 0);
assertMapUnmodifiable(re.regionPackageMap);
}
@Test
public void testDefaultRegions() throws Exception {
testDefaultRegions("foo.bar,foo.zar", new HashSet<>(Arrays.asList("foo.bar", "foo.zar")));
testDefaultRegions("test", Collections.singleton("test"));
testDefaultRegions("", Collections.emptySet());
testDefaultRegions(null, Collections.emptySet());
}
private void testDefaultRegions(String defProp, Set<String> expected)
throws IOException, URISyntaxException, NoSuchFieldException, IllegalAccessException {
BundleContext ctx = Mockito.mock(BundleContext.class);
Mockito.when(ctx.getProperty(DEFAULT_REGIONS)).thenReturn(defProp);
Mockito.when(ctx.getProperty(PROPERTIES_FILE_LOCATION)).
thenReturn("classloader://props1");
RegionConfiguration re = new RegionConfiguration(ctx, new Hashtable<String, Object>());
ResolverHook hook = new RegionEnforcer(re).begin(Collections.emptySet());
Field f = ResolverHookImpl.class.getDeclaredField("configuration");
f.setAccessible(true);
assertEquals(expected, ((RegionConfiguration)f.get(hook)).getDefaultRegions());
}
private void assertBSNVerMapUnmodifiable(Map<Map.Entry<String, Version>, List<String>> m) {
Map.Entry<Map.Entry<String, Version>, List<String>> entry = m.entrySet().iterator().next();
try {
List<String> c = entry.getValue();
c.add("test");
fail("Changing a value should have thrown an exception");
} catch (Exception ex) {
// good
}
try {
m.put(new AbstractMap.SimpleEntry<>("hi", Version.parseVersion("1.2.3")),
Collections.singletonList("xyz"));
fail("Adding a new value should have thrown an exception");
} catch (Exception ex) {
// good
}
}
private void assertMapUnmodifiable(Map<String, Set<String>> m) {
Map.Entry<String, Set<String>> entry = m.entrySet().iterator().next();
try {
Set<String> s = entry.getValue();
s.add("testing");
fail("Changing a value should have thrown an exception");
} catch (Exception ex) {
// good
}
try {
m.put("foo", Collections.<String>emptySet());
fail("Adding a new value should have thrown an exception");
} catch (Exception ex) {
// good
}
}
}