diff options
author | Thomas Watson | 2016-01-05 14:55:46 +0000 |
---|---|---|
committer | Thomas Watson | 2016-01-05 15:29:48 +0000 |
commit | e1aa6950b8be7c9e76b2df623d09eb8e25d1ef97 (patch) | |
tree | 2ca3b6daf3d5a8980a82444bec927b21041afbc4 /bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container | |
parent | de43c1f9a0b333cfb78be0dc5a1844dcae29e733 (diff) | |
download | rt.equinox.framework-e1aa6950b8be7c9e76b2df623d09eb8e25d1ef97.tar.gz rt.equinox.framework-e1aa6950b8be7c9e76b2df623d09eb8e25d1ef97.tar.xz rt.equinox.framework-e1aa6950b8be7c9e76b2df623d09eb8e25d1ef97.zip |
Bug 485217 - Update resolver implementation and default to using batch
resolves with a timeout
Diffstat (limited to 'bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container')
3 files changed, 112 insertions, 3 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/AbstractTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/AbstractTest.java index f49b085a0..846d8b97a 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/AbstractTest.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/AbstractTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2015 IBM Corporation and others. + * Copyright (c) 2013, 2016 IBM Corporation 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 @@ -86,6 +86,12 @@ public abstract class AbstractTest { return container.install(system, location, builder, null); } + protected Module installDummyModule(Map<String, String> manifest, String location, ModuleContainer container) throws BundleException { + ModuleRevisionBuilder builder = OSGiManifestBuilderFactory.createBuilder(manifest); + Module system = container.getModule(0); + return container.install(system, location, builder, null); + } + protected void registerService(Class<?> clazz, Object service) { serviceRegistrations.add(getSystemBundleContext().registerService(clazz.getName(), service, null)); } diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java index 5af409b98..a45d0825d 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2015 IBM Corporation and others. + * Copyright (c) 2013, 2016 IBM Corporation 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 @@ -21,6 +21,7 @@ import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent; import org.eclipse.osgi.container.builders.OSGiManifestBuilderFactory; import org.eclipse.osgi.container.namespaces.EclipsePlatformNamespace; import org.eclipse.osgi.internal.debug.Debug; +import org.eclipse.osgi.internal.framework.EquinoxConfiguration; import org.eclipse.osgi.report.resolution.ResolutionReport; import org.eclipse.osgi.tests.container.dummys.*; import org.eclipse.osgi.tests.container.dummys.DummyModuleDatabase.DummyContainerEvent; @@ -1748,6 +1749,93 @@ public class TestModuleContainer extends AbstractTest { } @Test + public void testUsesTimeout() throws BundleException { + // Always want to go to zero threads when idle + int coreThreads = 0; + // use the number of processors - 1 because we use the current thread when rejected + int maxThreads = Math.max(Runtime.getRuntime().availableProcessors() - 1, 1); + // idle timeout; make it short to get rid of threads quickly after resolve + int idleTimeout = 5; + // use sync queue to force thread creation + BlockingQueue<Runnable> queue = new SynchronousQueue<Runnable>(); + // try to name the threads with useful name + ThreadFactory threadFactory = new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r, "Resolver thread - UNIT TEST"); //$NON-NLS-1$ + t.setDaemon(true); + return t; + } + }; + // use a rejection policy that simply runs the task in the current thread once the max threads is reached + RejectedExecutionHandler rejectHandler = new RejectedExecutionHandler() { + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor exe) { + r.run(); + } + }; + ExecutorService executor = new ThreadPoolExecutor(coreThreads, maxThreads, idleTimeout, TimeUnit.SECONDS, queue, threadFactory, rejectHandler); + + Map<String, String> configuration = new HashMap<String, String>(); + configuration.put(EquinoxConfiguration.PROP_RESOLVER_BATCH_TIMEOUT, "5000"); + Map<String, String> debugOpts = Collections.singletonMap("org.eclipse.osgi/resolver/uses", "true"); + DummyContainerAdaptor adaptor = new DummyContainerAdaptor(new DummyCollisionHook(false), configuration, new DummyResolverHookFactory(), new DummyDebugOptions(debugOpts)); + adaptor.setResolverExecutor(executor); + ModuleContainer container = adaptor.getContainer(); + for (int i = 1; i <= 1000; i++) { + for (Map<String, String> manifest : getUsesTimeoutManifests("test" + i)) { + installDummyModule(manifest, manifest.get(Constants.BUNDLE_SYMBOLICNAME), container); + } + } + ResolutionReport report = container.resolve(container.getModules(), true); + Assert.assertNull("Found resolution errors.", report.getResolutionException()); + for (Module module : container.getModules()) { + Assert.assertEquals("Wrong state of module: " + module, State.RESOLVED, module.getState()); + } + executor.shutdown(); + System.gc(); + System.gc(); + System.gc(); + } + + private List<Map<String, String>> getUsesTimeoutManifests(String prefix) { + List<Map<String, String>> result = new ArrayList<Map<String, String>>(); + // x1 bundle + Map<String, String> x1Manifest = new HashMap<String, String>(); + x1Manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2"); + x1Manifest.put(Constants.BUNDLE_SYMBOLICNAME, prefix + ".x1"); + x1Manifest.put(Constants.EXPORT_PACKAGE, prefix + ".a; version=1.0; uses:=" + prefix + ".b"); + x1Manifest.put(Constants.IMPORT_PACKAGE, prefix + ".b; version=\"[1.1,1.2)\""); + result.add(x1Manifest); + // x2 bundle + Map<String, String> x2Manifest = new HashMap<String, String>(); + x2Manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2"); + x2Manifest.put(Constants.BUNDLE_SYMBOLICNAME, prefix + ".x2"); + x2Manifest.put(Constants.EXPORT_PACKAGE, prefix + ".a; version=1.1; uses:=" + prefix + ".b"); + x2Manifest.put(Constants.IMPORT_PACKAGE, prefix + ".b; version=\"[1.0,1.1)\""); + result.add(x2Manifest); + // y1 bundle + Map<String, String> y1Manifest = new HashMap<String, String>(); + y1Manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2"); + y1Manifest.put(Constants.BUNDLE_SYMBOLICNAME, prefix + ".y1"); + y1Manifest.put(Constants.EXPORT_PACKAGE, prefix + ".b; version=1.0"); + result.add(y1Manifest); + // y1 bundle + Map<String, String> y2Manifest = new HashMap<String, String>(); + y2Manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2"); + y2Manifest.put(Constants.BUNDLE_SYMBOLICNAME, prefix + ".y2"); + y2Manifest.put(Constants.EXPORT_PACKAGE, prefix + ".b; version=1.1"); + result.add(y2Manifest); + // z1 bundle + Map<String, String> z1Manifest = new HashMap<String, String>(); + z1Manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2"); + z1Manifest.put(Constants.BUNDLE_SYMBOLICNAME, prefix + ".z1"); + z1Manifest.put(Constants.IMPORT_PACKAGE, prefix + ".a, " + prefix + ".b"); + result.add(z1Manifest); + return result; + } + + @Test public void testOptionalSubstituted() throws BundleException, IOException { DummyContainerAdaptor adaptor = createDummyAdaptor(); ModuleContainer container = adaptor.getContainer(); diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/dummys/DummyContainerAdaptor.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/dummys/DummyContainerAdaptor.java index 4d91c7db6..645004e35 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/dummys/DummyContainerAdaptor.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/dummys/DummyContainerAdaptor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2015 IBM Corporation and others. + * Copyright (c) 2012, 2016 IBM Corporation 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 @@ -12,6 +12,7 @@ package org.eclipse.osgi.tests.container.dummys; import java.util.EnumSet; import java.util.Map; +import java.util.concurrent.Executor; import org.eclipse.osgi.container.*; import org.eclipse.osgi.container.Module.Settings; import org.eclipse.osgi.service.debug.DebugOptions; @@ -27,6 +28,7 @@ public class DummyContainerAdaptor extends ModuleContainerAdaptor { private final ModuleContainer container; private final ResolverHookFactory resolverHookFactory; private final DebugOptions debugOptions; + private volatile Executor resolverExecutor; public DummyContainerAdaptor(ModuleCollisionHook collisionHook, Map<String, String> configuration) { this(collisionHook, configuration, new DummyResolverHookFactory()); @@ -94,4 +96,17 @@ public class DummyContainerAdaptor extends ModuleContainerAdaptor { return this.debugOptions; } + public void setResolverExecutor(Executor executor) { + this.resolverExecutor = executor; + } + + @Override + public Executor getResolverExecutor() { + Executor current = this.resolverExecutor; + if (current != null) { + return current; + } + return super.getResolverExecutor(); + } + } |