| /******************************************************************************* |
| * Copyright (c) 2011, 2015 VMware Inc. and others |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * SpringSource, a division of VMware - initial API and implementation and/or initial documentation |
| *******************************************************************************/ |
| |
| package org.eclipse.equinox.region.internal.tests.hook; |
| |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.util.*; |
| import org.eclipse.equinox.region.*; |
| import org.eclipse.equinox.region.internal.tests.RegionReflectionUtils; |
| import org.eclipse.virgo.teststubs.osgi.framework.*; |
| import org.junit.*; |
| import org.osgi.framework.*; |
| import org.osgi.framework.hooks.service.EventHook; |
| |
| /** |
| * This testcase was based on {@link RegionBundleFindHookTests}. |
| */ |
| public class RegionServiceEventHookTests { |
| |
| private static final String BUNDLE_X = "X"; |
| |
| private static final Version BUNDLE_VERSION = new Version("0"); |
| |
| private long bundleId; |
| |
| private static final String REGION_A = "RegionA"; |
| |
| private static final String BUNDLE_A = "BundleA"; |
| |
| private static final String REGION_B = "RegionB"; |
| |
| private static final String BUNDLE_B = "BundleB"; |
| |
| private static final String REGION_C = "RegionC"; |
| |
| private static final String BUNDLE_C = "BundleC"; |
| |
| private static final String REGION_D = "RegionD"; |
| |
| private static final String BUNDLE_D = "BundleD"; |
| |
| private static final String DUPLICATE = "Duplicate"; |
| private static final String DUPLICATE_FIlTER = DUPLICATE + "*"; |
| |
| private RegionDigraph digraph; |
| |
| @SuppressWarnings("deprecation") |
| private EventHook serviceEventHook; |
| |
| private Map<String, Region> regions; |
| |
| private Map<String, Bundle> bundles; |
| |
| private Map<String, ServiceReference<Object>> serviceReferences; |
| |
| private ThreadLocal<Region> threadLocal; |
| |
| @Before |
| public void setUp() throws Exception { |
| this.bundleId = 1L; |
| this.regions = new HashMap<String, Region>(); |
| this.bundles = new HashMap<String, Bundle>(); |
| this.serviceReferences = new HashMap<String, ServiceReference<Object>>(); |
| |
| StubBundle stubSystemBundle = new StubBundle(0L, "osgi.framework", new Version("0"), "loc"); |
| StubBundleContext stubBundleContext = new StubBundleContext(); |
| stubBundleContext.addInstalledBundle(stubSystemBundle); |
| this.threadLocal = new ThreadLocal<Region>(); |
| this.digraph = RegionReflectionUtils.newStandardRegionDigraph(stubBundleContext, this.threadLocal); |
| this.serviceEventHook = RegionReflectionUtils.newRegionServiceEventHook(this.digraph); |
| |
| // Create regions A, B, C, D containing bundles A, B, C, D, respectively. |
| createRegion(REGION_A, BUNDLE_A); |
| createRegion(REGION_B, BUNDLE_B); |
| createRegion(REGION_C, BUNDLE_C); |
| createRegion(REGION_D, BUNDLE_D); |
| |
| createBundle(BUNDLE_X); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| // nothing |
| } |
| |
| @Test |
| public void testEventInSameRegion() { |
| Collection<BundleContext> contexts = bundleContexts(BUNDLE_A); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_A), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_A))); |
| } |
| |
| @Test |
| public void testEventInDisconnectedRegion() { |
| Collection<BundleContext> contexts = bundleContexts(BUNDLE_A); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_B), contexts); |
| assertFalse(contexts.contains(bundleContext(BUNDLE_A))); |
| } |
| |
| @Test |
| public void testEventConnectedRegionAllowed() throws BundleException, InvalidSyntaxException { |
| RegionFilter filter = createFilter(BUNDLE_B); |
| region(REGION_A).connectRegion(region(REGION_B), filter); |
| |
| Collection<BundleContext> contexts = bundleContexts(BUNDLE_A); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_B), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_A))); |
| } |
| |
| @Test |
| public void testEventConnectedRegionFiltering() throws BundleException, InvalidSyntaxException { |
| region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_B)); |
| Bundle x = createBundle(BUNDLE_X); |
| region(REGION_B).addBundle(x); |
| |
| Collection<BundleContext> contexts = bundleContexts(BUNDLE_A, BUNDLE_B, BUNDLE_X); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_X), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_B))); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_X))); |
| assertFalse(contexts.contains(bundleContext(BUNDLE_A))); |
| } |
| |
| @Test |
| public void testEventTransitive() throws BundleException, InvalidSyntaxException { |
| region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_C)); |
| region(REGION_B).connectRegion(region(REGION_C), createFilter(BUNDLE_C)); |
| region(REGION_C).addBundle(bundle(BUNDLE_X)); |
| |
| Collection<BundleContext> contexts = bundleContexts(BUNDLE_A, BUNDLE_B, BUNDLE_X); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_C), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_B))); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_X))); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_A))); |
| |
| contexts = bundleContexts(BUNDLE_A, BUNDLE_B, BUNDLE_X); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_X), contexts); |
| assertFalse(contexts.contains(bundleContext(BUNDLE_B))); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_X))); |
| assertFalse(contexts.contains(bundleContext(BUNDLE_A))); |
| } |
| |
| @Test |
| public void testEventTransitiveDups() throws BundleException, InvalidSyntaxException { |
| region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_C)); |
| region(REGION_A).connectRegion(region(REGION_C), createFilter(DUPLICATE_FIlTER)); |
| region(REGION_A).connectRegion(region(REGION_D), createFilter(DUPLICATE_FIlTER)); |
| region(REGION_B).connectRegion(region(REGION_C), createFilter(DUPLICATE_FIlTER)); |
| region(REGION_C).connectRegion(region(REGION_D), createFilter(DUPLICATE_FIlTER)); |
| region(REGION_D).connectRegion(region(REGION_A), createFilter(DUPLICATE_FIlTER)); |
| |
| Collection<BundleContext> contexts = bundleContexts(BUNDLE_A); |
| this.serviceEventHook.event(serviceEvent(DUPLICATE + bundle(BUNDLE_A).getBundleId()), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_A))); |
| |
| contexts = bundleContexts(BUNDLE_A); |
| this.serviceEventHook.event(serviceEvent(DUPLICATE + bundle(BUNDLE_B).getBundleId()), contexts); |
| assertFalse(contexts.contains(bundleContext(BUNDLE_A))); |
| |
| contexts = bundleContexts(BUNDLE_A); |
| this.serviceEventHook.event(serviceEvent(DUPLICATE + bundle(BUNDLE_C).getBundleId()), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_A))); |
| |
| contexts = bundleContexts(BUNDLE_A); |
| this.serviceEventHook.event(serviceEvent(DUPLICATE + bundle(BUNDLE_D).getBundleId()), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_A))); |
| } |
| |
| @Test |
| public void testEventInCyclicGraph() throws BundleException, InvalidSyntaxException { |
| region(REGION_D).addBundle(bundle(BUNDLE_X)); |
| |
| region(REGION_A).connectRegion(region(REGION_B), createFilter(BUNDLE_D, BUNDLE_X)); |
| region(REGION_B).connectRegion(region(REGION_A), createFilter()); |
| |
| region(REGION_B).connectRegion(region(REGION_D), createFilter(BUNDLE_D)); |
| region(REGION_D).connectRegion(region(REGION_B), createFilter()); |
| |
| region(REGION_B).connectRegion(region(REGION_C), createFilter(BUNDLE_X)); |
| region(REGION_C).connectRegion(region(REGION_B), createFilter()); |
| |
| region(REGION_C).connectRegion(region(REGION_D), createFilter(BUNDLE_X)); |
| region(REGION_D).connectRegion(region(REGION_C), createFilter()); |
| |
| region(REGION_A).connectRegion(region(REGION_C), createFilter()); |
| region(REGION_C).connectRegion(region(REGION_A), createFilter()); |
| |
| region(REGION_D).connectRegion(region(REGION_A), createFilter()); |
| region(REGION_A).connectRegion(region(REGION_D), createFilter()); |
| |
| Collection<BundleContext> contexts = bundleContexts(BUNDLE_A, BUNDLE_B); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_B), contexts); |
| assertFalse(contexts.contains(bundleContext(BUNDLE_A))); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_B))); |
| |
| contexts = bundleContexts(BUNDLE_A, BUNDLE_B); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_C), contexts); |
| assertFalse(contexts.contains(bundleContext(BUNDLE_A))); |
| assertFalse(contexts.contains(bundleContext(BUNDLE_B))); |
| |
| contexts = bundleContexts(BUNDLE_A, BUNDLE_B); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_D), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_A))); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_B))); |
| |
| contexts = bundleContexts(BUNDLE_A, BUNDLE_B); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_X), contexts); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_A))); |
| assertTrue(contexts.contains(bundleContext(BUNDLE_B))); |
| } |
| |
| @Test |
| public void testEventFromSystemBundle() { |
| Bundle systemBundle = new StubBundle(0L, "sys", BUNDLE_VERSION, ""); |
| Collection<BundleContext> contexts = new ArrayList<BundleContext>(Arrays.asList(systemBundle.getBundleContext())); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_A), contexts); |
| assertTrue(contexts.contains(systemBundle.getBundleContext())); |
| } |
| |
| @Test |
| public void testEventFromBundleInNoRegion() { |
| Bundle stranger = createBundle("stranger"); |
| Collection<BundleContext> contexts = new ArrayList<BundleContext>(Arrays.asList(stranger.getBundleContext())); |
| this.serviceEventHook.event(serviceEvent(BUNDLE_A), contexts); |
| assertTrue(contexts.isEmpty()); |
| } |
| |
| private Region createRegion(String regionName, String... bundleSymbolicNames) throws BundleException { |
| Region region = this.digraph.createRegion(regionName); |
| for (String bundleSymbolicName : bundleSymbolicNames) { |
| Bundle stubBundle = createBundle(bundleSymbolicName); |
| region.addBundle(stubBundle); |
| } |
| this.regions.put(regionName, region); |
| return region; |
| } |
| |
| private Region region(String regionName) { |
| return this.regions.get(regionName); |
| } |
| |
| private RegionFilter createFilter(final String... referenceNames) throws InvalidSyntaxException { |
| Collection<String> filters = new ArrayList<String>(referenceNames.length); |
| for (String referenceName : referenceNames) { |
| filters.add('(' + Constants.OBJECTCLASS + '=' + referenceName + ')'); |
| } |
| RegionFilterBuilder builder = digraph.createRegionFilterBuilder(); |
| for (String filter : filters) { |
| builder.allow(RegionFilter.VISIBLE_SERVICE_NAMESPACE, filter); |
| } |
| String negateFilter = "(!(|" + "(" + RegionFilter.VISIBLE_ALL_NAMESPACE_ATTRIBUTE + "=" + RegionFilter.VISIBLE_SERVICE_NAMESPACE + ")" + "(" + RegionFilter.VISIBLE_ALL_NAMESPACE_ATTRIBUTE + "=" + RegionFilter.VISIBLE_BUNDLE_NAMESPACE + ")" + "))"; |
| builder.allow(RegionFilter.VISIBLE_ALL_NAMESPACE, negateFilter); |
| return builder.build(); |
| } |
| |
| private Bundle createBundle(String bundleSymbolicName) { |
| Bundle stubBundle = new StubBundle(this.bundleId++, bundleSymbolicName, BUNDLE_VERSION, "loc:" + bundleSymbolicName); |
| this.bundles.put(bundleSymbolicName, stubBundle); |
| createServiceReference(stubBundle, bundleSymbolicName); |
| return stubBundle; |
| } |
| |
| private StubServiceReference<Object> createServiceReference(Bundle stubBundle, String referenceName) { |
| StubServiceRegistration<Object> stubServiceRegistration = new StubServiceRegistration<Object>((StubBundleContext) stubBundle.getBundleContext(), referenceName); |
| StubServiceReference<Object> stubServiceReference = new StubServiceReference<Object>(stubServiceRegistration); |
| this.serviceReferences.put(referenceName, stubServiceReference); |
| |
| StubServiceRegistration<Object> dupServiceRegistration = new StubServiceRegistration<Object>((StubBundleContext) stubBundle.getBundleContext(), DUPLICATE + stubBundle.getBundleId()); |
| StubServiceReference<Object> dupServiceReference = new StubServiceReference<Object>(dupServiceRegistration); |
| this.serviceReferences.put(DUPLICATE + stubBundle.getBundleId(), dupServiceReference); |
| return stubServiceReference; |
| } |
| |
| private Collection<BundleContext> bundleContexts(String... bundleSymbolicNames) { |
| Collection<BundleContext> contexts = new ArrayList<BundleContext>(); |
| for (String symbolicName : bundleSymbolicNames) { |
| contexts.add(bundleContext(symbolicName)); |
| } |
| return contexts; |
| } |
| |
| private BundleContext bundleContext(String bundleSymbolicName) { |
| return bundle(bundleSymbolicName).getBundleContext(); |
| } |
| |
| private Bundle bundle(String bundleSymbolicName) { |
| Bundle bundleA = this.bundles.get(bundleSymbolicName); |
| return bundleA; |
| } |
| |
| private ServiceEvent serviceEvent(String referenceName) { |
| return new ServiceEvent(ServiceEvent.REGISTERED, serviceReference(referenceName)); |
| } |
| |
| private ServiceReference<Object> serviceReference(String referenceName) { |
| return this.serviceReferences.get(referenceName); |
| } |
| |
| } |