/*
 * 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 org.junit.Test;
import org.mockito.Mockito;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import static org.junit.Assert.assertEquals;

public class ResolverHookImplTest {
    @Test
    public void testProvidingFeatureHasNoRegionsSoEveryoneCanAccess() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle", new Version(1,0,0)), Collections.singletonList("b1"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "requiring.bundle", new Version(1,0,0)), Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b1", Collections.singleton("f1"));
        bfmap.put("b2", Collections.singleton("f2"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f2", Collections.singleton("r2"));

        Map<String, Set<String>> rpmap = new HashMap<>();

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.singleton("*"));

        // b2 is in r2, it requires a capability that is provided by b1.
        // b1 is in a feature, but that feature is not in any region so it can provide access.
        BundleRequirement req1 = mockRequirement("b2", bsnvermap);
        BundleCapability cap1 = mockCapability("org.apache.sling.test", "b1", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1));
        rh.filterMatches(req1, candidates1);
        assertEquals(Collections.singletonList(cap1), candidates1);
    }

    @Test
    public void testProvidingBundleHasNoFeatureSoEveryoneCanAccess() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle", new Version(1,0,0)), Collections.singletonList("b1"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "requiring.bundle", new Version(1,0,0)), Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b2", Collections.singleton("f2"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f2", Collections.singleton("r2"));

        Map<String, Set<String>> rpmap = new HashMap<>();

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.singleton("global"));

        // b2 is in r2, it requires a capability that is provided by b1.
        // b1 is not in any feature so it can provide access.
        BundleRequirement req1 = mockRequirement("b2", bsnvermap);
        BundleCapability cap1 = mockCapability("org.apache.sling.test", "b1", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1));
        rh.filterMatches(req1, candidates1);
        assertEquals(Collections.singletonList(cap1), candidates1);
    }

    @Test
    public void testProvidingFeatureHasNoRegionsSoEveryoneCanAccess3() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle", new Version(1,0,0)), Collections.singletonList("b1"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "requiring.bundle", new Version(1,0,0)), Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b1", Collections.singleton("f1"));
        bfmap.put("b2", Collections.singleton("f2"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f1", Collections.emptySet());
        frmap.put("f2", Collections.singleton("r2"));

        Map<String, Set<String>> rpmap = new HashMap<>();

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.singleton("global"));

        // b2 is in r2, it requires a capability that is provided by b1.
        // b1 is in a feature that has an empty region set, any region so it can provide access.
        BundleRequirement req1 = mockRequirement("b2", bsnvermap);
        BundleCapability cap1 = mockCapability("org.apache.sling.test", "b1", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1));
        rh.filterMatches(req1, candidates1);
        assertEquals(Collections.singletonList(cap1), candidates1);
    }

    @Test
    public void testProvidingFeatureHasNoExportsSoOtherFeatureCannotAccess() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle", new Version(1,0,0)), Collections.singletonList("b1"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "requiring.bundle", new Version(1,0,0)), Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b1", Collections.singleton("f1"));
        bfmap.put("b2", Collections.singleton("f2"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f1", Collections.singleton("r2"));
        frmap.put("f2", Collections.singleton("r2"));

        Map<String, Set<String>> rpmap = new HashMap<>();

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.singleton("global"));

        // b2 is in r2, it requires a capability that is provided by b1.
        // b1 is also in r2 but is not exporting the package in there, so b2 should not see the package.
        BundleRequirement req1 = mockRequirement("b2", bsnvermap);
        BundleCapability cap1 = mockCapability("org.apache.sling.test", "b1", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1));
        rh.filterMatches(req1, candidates1);
        assertEquals("The exported package is not exported in any region, and b1 is in r2 so b2 should not see the package as its feature-private",
                0, candidates1.size());
    }

    @Test
    public void testRegionHasPrecedenceOverGlobal() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.otherfeature", new Version(1,0,0)), Collections.singletonList("b10"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.infeature", new Version(1,0,0)), Collections.singletonList("b11"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.inglobal", new Version(1,0,0)), Collections.singletonList("b19"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "requiring.bundle", new Version(1,0,0)), Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b10", Collections.singleton("f10"));
        bfmap.put("b11", Collections.singleton("f11"));
        bfmap.put("b2", Collections.singleton("f2"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f10", new HashSet<>(Arrays.asList("r2", "r3")));
        frmap.put("f11", new HashSet<>(Arrays.asList("r1", "r2")));
        frmap.put("f2", Collections.singleton("r1"));

        Map<String, Set<String>> rpmap = new HashMap<>();
        rpmap.put("r1", Collections.singleton("org.foo.bar"));
        rpmap.put("r2", new HashSet<>(Arrays.asList("xxx", "yyy", "zzz")));
        rpmap.put("r3", new HashSet<>(Arrays.asList("org.foo.bar", "zzz")));

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.singleton("global"));

        // b2 needs to resolve to 'org.foo.bar' package. b2 is in region r1.
        // The package is provided by 3 bundles:
        //   b10 provides it but is not in a matching region
        //   b11 provides it and has a matching region
        //   b19 provides it in the global region
        // Only b11 should provide the capability. Even though b19 provides it from the global region, if there is an overlapping
        // specific region then the global region should not be used
        BundleRequirement req1 = mockRequirement("b2", bsnvermap);
        BundleCapability cap1 = mockCapability("org.foo.bar", "b10", bsnvermap);
        BundleCapability cap2 = mockCapability("org.foo.bar", "b11", bsnvermap);
        BundleCapability cap3 = mockCapability("org.foo.bar", "b19", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1, cap2, cap3));
        rh.filterMatches(req1, candidates1);

        assertEquals("Only the capability coming from bundle b11 should be selected, b10 is in a different region and b19 is in global "
                + "which should be excluded as there is a capability in a matching region.",
                Collections.singletonList(cap2), candidates1);
    }

    @Test
    public void testOwnFeatureHasPrecendenceOverGlobal() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.infeature", new Version(1,0,0)), Collections.singletonList("b11"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.inglobal", new Version(1,0,0)), Collections.singletonList("b19"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "requiring.bundle", new Version(1,0,0)), Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b11", Collections.singleton("f1"));
        bfmap.put("b2", Collections.singleton("f1"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f1", Collections.singleton("r1"));

        Map<String, Set<String>> rpmap = new HashMap<>();
        rpmap.put("r1", Collections.emptySet());

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.singleton("global"));

        // b2 needs to resolve 'org.foo.bar' and there are 2 candidates:
        // b11 is in the same feature as b2
        // b19 is in the no feature
        // In this case b11 should be selected as its in the same region
        BundleRequirement req1 = mockRequirement("b2", bsnvermap);
        BundleCapability cap1 = mockCapability("org.foo.bar", "b11", bsnvermap);
        BundleCapability cap2 = mockCapability("org.foo.bar", "b19", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1, cap2));
        rh.filterMatches(req1, candidates1);

        assertEquals("Only b11 should be selected as its from the same region as b2",
                Collections.singletonList(cap1), candidates1);
    }

    @Test
    public void testMultipleGlobalOptionsOnly() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.otherfeature", new Version(1,0,0)), Collections.singletonList("b10"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.inglobal1", new Version(1,0,0)), Collections.singletonList("b18"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.inglobal2", new Version(1,0,0)), Collections.singletonList("b19"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "requiring.bundle", new Version(1,0,0)), Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b10", Collections.singleton("f10"));
        bfmap.put("b2", Collections.singleton("f2"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f10", new HashSet<>(Arrays.asList("r2", "r3")));
        frmap.put("f2", Collections.singleton("r1"));

        Map<String, Set<String>> rpmap = new HashMap<>();
        rpmap.put("r1", Collections.emptySet());
        rpmap.put("r2", new HashSet<>(Arrays.asList("xxx", "yyy", "zzz")));
        rpmap.put("r3", new HashSet<>(Arrays.asList("org.foo.bar", "zzz")));

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.singleton("global"));

        // b2 needs to resolve to 'org.foo.bar' package. b2 is in region r1.
        // However nobody in r1 exports the package
        // The package is exported by b10 in r3 but b2 is not in that region.
        // The package is exported by b18 and b19 which are both in the global region
        // Both these candidates should remain available.
        BundleRequirement req1 = mockRequirement("b2", bsnvermap);
        BundleCapability cap1 = mockCapability("org.foo.bar", "b10", bsnvermap);
        BundleCapability cap2 = mockCapability("org.foo.bar", "b18", bsnvermap);
        BundleCapability cap3 = mockCapability("org.foo.bar", "b19", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1, cap2, cap3));
        rh.filterMatches(req1, candidates1);

        assertEquals("Since there are no specific candidates in a matching region, the candidates from "
                + "the global region should be allowed.",
                Arrays.asList(cap2, cap3), candidates1);
    }

    @Test
    public void testMultipleGlobalOptionsOnly2() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.inglobal1", new Version(1,0,0)), Collections.singletonList("b18"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "providing.bundle.inglobal2", new Version(1,0,0)), Collections.singletonList("b19"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>(
                "requiring.bundle", new Version(1,0,0)), Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        Map<String, Set<String>> frmap = new HashMap<>();
        Map<String, Set<String>> rpmap = new HashMap<>();

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.singleton("global"));

        // b2 needs to resolve to 'org.foo.bar' package. b2 is in no region.
        // b18 and b19 export the package in the global region. They should both be allowed.
        BundleRequirement req1 = mockRequirement("b2", bsnvermap);
        BundleCapability cap1 = mockCapability("org.foo.bar", "b18", bsnvermap);
        BundleCapability cap2 = mockCapability("org.foo.bar", "b19", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1, cap2));
        rh.filterMatches(req1, candidates1);

        assertEquals(Arrays.asList(cap1, cap2), candidates1);
    }

    @Test
    public void testFilterMatches() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("system.bundle", new Version(3,2,1)),
                Collections.singletonList("b0"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("a.b.c", new Version(0,0,0)),
                Collections.singletonList("b7"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("a.bundle", new Version(1,0,0)),
                Collections.singletonList("b8"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("some.other.bundle", new Version(9,9,9,"suffix")),
                Collections.singletonList("b9"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("a-bundle", new Version(1,0,0,"SNAPSHOT")),
                Collections.singletonList("b10"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("not.in.a.feature", new Version(0,0,1)),
                Collections.singletonList("b11"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("also.not.in.a.feature", new Version(0,0,1)),
                Collections.singletonList("b12"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("a.b.c", new Version(1,2,3)),
                Collections.singletonList("b17"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("x.y.z", new Version(9,9,9)),
                Collections.singletonList("b19"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("zzz", new Version(1,0,0)),
                Collections.singletonList("b20"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b7", Collections.singleton("f"));
        bfmap.put("b8", Collections.singleton("f1"));
        bfmap.put("b9", Collections.singleton("f2"));
        bfmap.put("b10", Collections.singleton("f2"));
        bfmap.put("b17", Collections.singleton("f3"));
        bfmap.put("b19", Collections.singleton("f3"));
        bfmap.put("b20", Collections.singleton("f4"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f", new HashSet<>(Arrays.asList("r1", "r2", RegionEnforcer.GLOBAL_REGION)));
        frmap.put("f1", Collections.singleton("r1"));
        frmap.put("f2", Collections.singleton("r2"));
        frmap.put("f3", Collections.singleton("r3"));
        frmap.put("f4", Collections.singleton("r3"));

        Map<String, Set<String>> rpmap = new HashMap<>();
        rpmap.put("r0", Collections.singleton("org.bar"));
        rpmap.put("r1", new HashSet<>(Arrays.asList("org.blah", "org.foo")));
        rpmap.put(RegionEnforcer.GLOBAL_REGION, Collections.singleton("org.bar.tar"));
        rpmap.put("r3", Collections.singleton("xyz"));

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.emptySet());

        // Check that we can get the capability from another bundle in the same region
        // where that region exports the package
        // Bundle 7 is in feature f with regions r1, r2. Bundle 8 is in feature f1 with regions r1
        // r1 exports the org.foo package
        BundleRequirement req0 = mockRequirement("b7", bsnvermap);
        BundleCapability bc0 = mockCapability("org.foo", "b8", bsnvermap);
        List<BundleCapability> candidates0 = new ArrayList<>(Arrays.asList(bc0));
        rh.filterMatches(req0, candidates0);
        assertEquals(Collections.singletonList(bc0), candidates0);

        // Check that we cannot get the capability from another bundle in the same region
        // but that region doesn't export the pacakge.
        // Bundle 7 is in feature f with regions r1, r2. Bundle 9 is in feature f2 with regions r2
        // r2 does not export any packages
        BundleRequirement req1 = mockRequirement("b7", bsnvermap);
        BundleCapability bc1 = mockCapability("org.foo", "b9", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(bc1));
        rh.filterMatches(req1, candidates1);
        assertEquals(Collections.emptyList(), candidates1);

        // Check that we cannot get the capability from another bundle in a different region
        // Bundle 9 is in feature f2 with region r2
        // Bundle 17 is in feature f3 with region r3
        BundleRequirement req2 = mockRequirement("b9", bsnvermap);
        BundleCapability bc2 = mockCapability("org.bar", "b17", bsnvermap);
        Collection<BundleCapability> c2 = new ArrayList<>(Arrays.asList(bc2));
        rh.filterMatches(req2, c2);
        assertEquals(0, c2.size());

        // Check that we can get the capability from the same bundle
        BundleRequirement req3 = mockRequirement("b9", bsnvermap);
        BundleCapability bc3 = mockCapability("abc.xyz", "b9", bsnvermap);
        Collection<BundleCapability> c3 = new ArrayList<>(Arrays.asList(bc3));
        rh.filterMatches(req3, c3);
        assertEquals(Collections.singletonList(bc3), c3);

        // Check that we can get the capability from the another bundle in the same feature
        BundleRequirement req4 = mockRequirement("b9", bsnvermap);
        BundleCapability bc4 = mockCapability("some.cool.package", "b10", bsnvermap);
        Collection<BundleCapability> c4 = new ArrayList<>(Arrays.asList(bc4));
        rh.filterMatches(req4, c4);
        assertEquals(Collections.singletonList(bc4), c4);

        // Check that we can get the capability from another bundle where the capability
        // is globally visible b7 exposes org.bar.tar in the global region, so b17 can see it
        BundleRequirement req5 = mockRequirement("b17", bsnvermap);
        BundleCapability bc5 = mockCapability("org.bar.tar", "b7", bsnvermap);
        Collection<BundleCapability> c5 = new ArrayList<>(Arrays.asList(bc5));
        rh.filterMatches(req5, c5);
        assertEquals(Collections.singletonList(bc5), c5);

        // Check that we cannot get at a capability in a region from a bundle not in a feature
        BundleRequirement req6 = mockRequirement(6, "bundle.not.in.feature", new Version(2,0,0));
        BundleCapability bc6 = mockCapability("org.foo", "b9", bsnvermap);
        Collection<BundleCapability> c6 = new ArrayList<>(Arrays.asList(bc6));
        rh.filterMatches(req6, c6);
        assertEquals(0, c6.size());

        // Check that capabilities in non-package namespaces are ignored
        BundleRequirement req7 = Mockito.mock(BundleRequirement.class);
        Mockito.when(req7.getNamespace()).thenReturn("some.other.namespace");
        BundleCapability bc7 = mockCapability("org.bar", "b17", bsnvermap);
        Collection<BundleCapability> c7 = new ArrayList<>(Arrays.asList(bc7));
        rh.filterMatches(req7, c7);
        assertEquals(Collections.singletonList(bc7), c7);

        // Check that we can get the capability from another provider in the same region
        BundleRequirement req8 = mockRequirement("b20", bsnvermap);
        BundleCapability bc8 = mockCapability("xyz", "b19", bsnvermap);
        Collection<BundleCapability> c8 = new ArrayList<>(Arrays.asList(bc8));
        rh.filterMatches(req8, c8);
        assertEquals(Collections.singletonList(bc8), c8);

        // A requirement from a bundle that has no feature cannot access one in a region
        // b17 provides package xyz which is in region r3, but b11 is not in any region.
        BundleRequirement req9 = mockRequirement("b11", bsnvermap);
        BundleCapability bc9 = mockCapability("xyz", "b17", bsnvermap);
        Collection<BundleCapability> c9 = new ArrayList<>(Arrays.asList(bc9));
        rh.filterMatches(req9, c9);
        assertEquals(0, c9.size());

        // A requirement from a bundle that has no feature can still access one in the global region
        // b7 exposes org.bar.tar in the global region, so b11 can see it
        BundleRequirement req10 = mockRequirement("b11", bsnvermap);
        BundleCapability bc10 = mockCapability("org.bar.tar", "b7", bsnvermap);
        Collection<BundleCapability> c10 = new ArrayList<>(Arrays.asList(bc10));
        rh.filterMatches(req10, c10);
        assertEquals(Collections.singletonList(bc10), c10);

        // A requirement from a bundle that has no feature can be satisfied by a capability
        // from a bundle that has no feature
        BundleRequirement req11 = mockRequirement("b11", bsnvermap);
        BundleCapability bc11 = mockCapability("ding.dong", "b12", bsnvermap);
        Collection<BundleCapability> c11 = new ArrayList<>(Arrays.asList(bc11));
        rh.filterMatches(req11, c11);
        assertEquals(Collections.singletonList(bc11), c11);

        // A capability from the system bundle is always accessible
        BundleRequirement req12 = mockRequirement("b11", bsnvermap);
        BundleCapability bc12 = mockCapability("ping.pong", "b0", bsnvermap);
        Collection<BundleCapability> c12 = new ArrayList<>(Arrays.asList(bc12));
        rh.filterMatches(req12, c12);
        assertEquals(Collections.singletonList(bc12), c12);

        // Check that anyone can get a capability from a bundle not in a feature
        BundleRequirement req13 = mockRequirement("b9", bsnvermap);
        BundleCapability bc13 = mockCapability("some.package", 999, "no.in.any.feature", new Version(1,0,0));
        Collection<BundleCapability> c13 = new ArrayList<>(Arrays.asList(bc13));
        rh.filterMatches(req13, c13);
        assertEquals(Collections.singletonList(bc13), c13);
    }

    @Test
    public void testMultipleRegionsNoneMatching() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("bundle.1", new Version(1,0,0)),
                Collections.singletonList("b1"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("bundle.2", new Version(1,0,0)),
                Collections.singletonList("b2"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b1", Collections.singleton("f1"));
        bfmap.put("b2", Collections.singleton("f2"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f1", new HashSet<>(Arrays.asList(
                RegionEnforcer.GLOBAL_REGION, "org.foo.blah")));
        frmap.put("f2", new HashSet<>(Arrays.asList("org.foo.bar",
                RegionEnforcer.GLOBAL_REGION, "org.foo.blah")));

        Map<String, Set<String>> rpmap = new HashMap<>();
        rpmap.put("org.foo.bar", Collections.singleton("org.test"));
        rpmap.put(RegionEnforcer.GLOBAL_REGION, Collections.singleton("org.something"));
        rpmap.put("org.foo.blah", Collections.singleton("org.something"));

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap, Collections.emptySet());

        BundleRequirement req0 = mockRequirement("b1", bsnvermap);
        BundleCapability cap0 = mockCapability("org.test", "b2", bsnvermap);
        List<BundleCapability> candidates0 = new ArrayList<>(Arrays.asList(cap0));
        rh.filterMatches(req0, candidates0);
        assertEquals(Collections.emptyList(), candidates0);
    }

    @Test
    public void testGetRegionsForPackage() {
        Set<String> regions = new HashSet<>(Arrays.asList("r1", "r2", "r3"));
        Map<String, Set<String>> featureRegionMap = Collections.singletonMap("f2", regions);
        Map<String, Set<String>> regionPackageMap = new HashMap<>();

        regionPackageMap.put("r2", Collections.singleton("a.b.c"));
        Set<String> pkgs = new HashSet<>();
        pkgs.add("org.foo.bar");
        pkgs.add("org.foo.zar");
        regionPackageMap.put("r3", pkgs);

        ResolverHookImpl rh = new ResolverHookImpl(
                Collections.<Map.Entry<String, Version>, List<String>>emptyMap(),
                Collections.<String, Set<String>>emptyMap(), featureRegionMap, regionPackageMap, Collections.emptySet());

        assertEquals(Collections.emptyList(), rh.getRegionsForPackage(null, "f1"));
        assertEquals(Collections.emptyList(), rh.getRegionsForPackage("org.foo", "f1"));
        assertEquals(Collections.emptyList(), rh.getRegionsForPackage(null, "f2"));
        assertEquals(Collections.emptyList(), rh.getRegionsForPackage("org.foo", "f2"));

        assertEquals(Collections.singletonList("r3"), rh.getRegionsForPackage("org.foo.bar", "f2"));
        assertEquals(Collections.singletonList("r2"), rh.getRegionsForPackage("a.b.c", "f2"));
    }

    @Test
    public void testDefaultRegions() {
        Map<Entry<String, Version>, List<String>> bsnvermap = new HashMap<>();
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("b98", new Version(1, 0, 0)),
                Collections.singletonList("b98"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("b99", new Version(1, 2, 3)),
                Collections.singletonList("b99"));
        bsnvermap.put(new AbstractMap.SimpleEntry<String,Version>("b100", new Version(4, 5, 6)),
                Collections.singletonList("b100"));

        Map<String, Set<String>> bfmap = new HashMap<>();
        bfmap.put("b98", Collections.singleton("f2"));
        bfmap.put("b100", Collections.singleton("f1"));

        Map<String, Set<String>> frmap = new HashMap<>();
        frmap.put("f1", Collections.singleton("r1"));
        frmap.put("f2", Collections.singleton("r2"));

        Map<String, Set<String>> rpmap = new HashMap<>();
        rpmap.put("r1", Collections.singleton("org.test"));
        rpmap.put("r2", Collections.singleton("org.test"));

        ResolverHookImpl rh = new ResolverHookImpl(bsnvermap, bfmap, frmap, rpmap,
                new HashSet<>(Arrays.asList("r1", "r3")));

        // b99 is not in any region itself and tries to resolve to b100 which is in r1
        // b99 can resolve to b100 because 'r1' is listed as a default region in the
        // ResolverHook.
        BundleRequirement req = mockRequirement("b99", bsnvermap);
        BundleCapability cap = mockCapability("org.test", "b100", bsnvermap);
        List<BundleCapability> candidates = new ArrayList<>(Arrays.asList(cap));
        rh.filterMatches(req, candidates);
        assertEquals("b99 should be able to wire to b100, as the default region is r1, which is what b100 is in. ",
                Collections.singletonList(cap), candidates);

        // b99 is not in any region and tries to resolve to b98, which is in r2
        // b99 can't resolve because b2 is not in the default regions and it's not in
        // any other regions itself.
        BundleRequirement req1 = mockRequirement("b99", bsnvermap);
        BundleCapability cap1 = mockCapability("org.test", "b98", bsnvermap);
        List<BundleCapability> candidates1 = new ArrayList<>(Arrays.asList(cap1));
        rh.filterMatches(req1, candidates1);
        assertEquals("b99 should not be able to wire to b98, as this is in region r2, which is not in the default regions r1 and r3",
                0, candidates1.size());
    }

    private BundleCapability mockCapability(String pkgName, String bid, Map<Entry<String, Version>, List<String>> bsnvermap) {
        for (Map.Entry<Map.Entry<String, Version>, List<String>> entry : bsnvermap.entrySet()) {
            if (entry.getValue().contains(bid)) {
                // Remove first letter and use rest as bundle ID
                long id = Long.parseLong(bid.substring(1));
                return mockCapability(pkgName, id, entry.getKey().getKey(), entry.getKey().getValue());
            }
        }
        throw new IllegalStateException("Bundle not found " + bid);
    }

    private BundleCapability mockCapability(String pkg, long bundleID, String bsn, Version version) {
        Map<String, Object> attrs =
                Collections.<String, Object>singletonMap(PackageNamespace.PACKAGE_NAMESPACE, pkg);

        Bundle bundle = Mockito.mock(Bundle.class);
        Mockito.when(bundle.getBundleId()).thenReturn(bundleID);
        Mockito.when(bundle.getSymbolicName()).thenReturn(bsn);
        Mockito.when(bundle.getVersion()).thenReturn(version);

        BundleRevision br = Mockito.mock(BundleRevision.class);
        Mockito.when(br.getBundle()).thenReturn(bundle);


        BundleCapability cap = Mockito.mock(BundleCapability.class);
        Mockito.when(cap.getAttributes()).thenReturn(attrs);
        Mockito.when(cap.getRevision()).thenReturn(br);
        return cap;
    }

    private BundleRequirement mockRequirement(String bid, Map<Map.Entry<String, Version>, List<String>> bsnvermap) {
        for (Map.Entry<Map.Entry<String, Version>, List<String>> entry : bsnvermap.entrySet()) {
            if (entry.getValue().contains(bid)) {
                // Remove first letter and use rest as bundle ID
                long id = Long.parseLong(bid.substring(1));
                return mockRequirement(id, entry.getKey().getKey(), entry.getKey().getValue());
            }
        }
        throw new IllegalStateException("Bundle not found " + bid);
    }

    private BundleRequirement mockRequirement(long bundleID, String bsn, Version version) {
        Bundle bundle = Mockito.mock(Bundle.class);
        Mockito.when(bundle.getBundleId()).thenReturn(bundleID);
        Mockito.when(bundle.getSymbolicName()).thenReturn(bsn);
        Mockito.when(bundle.getVersion()).thenReturn(version);

        BundleRevision br = Mockito.mock(BundleRevision.class);
        Mockito.when(br.getBundle()).thenReturn(bundle);

        BundleRequirement req = Mockito.mock(BundleRequirement.class);
        Mockito.when(req.getNamespace()).thenReturn(PackageNamespace.PACKAGE_NAMESPACE);
        Mockito.when(req.getRevision()).thenReturn(br);

        return req;
    }
}
