summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Ross2013-06-25 16:30:16 (EDT)
committer Thomas Watson2013-06-26 14:27:26 (EDT)
commit88580f7595f0f7b09de84ddc0eb281b81da6857d (patch)
tree1a69d36871954a1b871548adde91e8e33181ced4
parent0d2350aba3c0396ca306570a642f48fdb706d8d2 (diff)
downloadrt.equinox.framework-88580f7595f0f7b09de84ddc0eb281b81da6857d.zip
rt.equinox.framework-88580f7595f0f7b09de84ddc0eb281b81da6857d.tar.gz
rt.equinox.framework-88580f7595f0f7b09de84ddc0eb281b81da6857d.tar.bz2
[Bug 407416] Test framework discards bundles at load time when storage hooks invalidate.
A new package and initial infrastructure for framework hook tests was created. Two storage hook tests have been added. One tests that bundles are discarded if a storage hook throws IllegalStateException from the validate() method. The other ensure that bundles are not discarded when storage hook validation succeeds.
-rw-r--r--bundles/org.eclipse.osgi.tests/.classpath1
-rw-r--r--bundles/org.eclipse.osgi.tests/build.properties5
-rw-r--r--bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/MANIFEST.MF3
-rw-r--r--bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHookConfigurator.java59
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AbstractFrameworkHookTests.java135
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/StorageHookTests.java104
-rw-r--r--bundles/org.eclipse.osgi/META-INF/MANIFEST.MF2
7 files changed, 308 insertions, 1 deletions
diff --git a/bundles/org.eclipse.osgi.tests/.classpath b/bundles/org.eclipse.osgi.tests/.classpath
index 1035af6..af3abe1 100644
--- a/bundles/org.eclipse.osgi.tests/.classpath
+++ b/bundles/org.eclipse.osgi.tests/.classpath
@@ -109,5 +109,6 @@
<classpathentry kind="src" output="bundle_tests/test.logging.a" path="bundles_src/test.logging.a"/>
<classpathentry kind="src" output="bundle_tests/geturl" path="bundles_src/geturl"/>
<classpathentry kind="src" output="bundle_tests/test.bug375784" path="bundles_src/test.bug375784"/>
+ <classpathentry kind="src" output="bundle_tests/storage.hooks.a" path="bundles_src/storage.hooks.a"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/bundles/org.eclipse.osgi.tests/build.properties b/bundles/org.eclipse.osgi.tests/build.properties
index 538bdd0..1a0453f 100644
--- a/bundles/org.eclipse.osgi.tests/build.properties
+++ b/bundles/org.eclipse.osgi.tests/build.properties
@@ -229,6 +229,8 @@ source.bundle_tests/geturl.jar = bundles_src/geturl/
manifest.bundle_tests/geturl.jar = META-INF/MANIFEST.MF
source.bundle_tests/test.bug375784.jar = bundles_src/test.bug306181b/
manifest.bundle_tests/test.bug375784.jar = META-INF/MANIFEST.MF
+source.bundle_tests/storage.hooks.a.jar = bundles_src/storage.hooks.a/
+manifest.bundle_tests/storage.hooks.a.jar = META-INF/MANIFEST.MF
jars.compile.order = bundle_tests/ext.framework.b.jar,\
osgitests.jar,\
@@ -336,4 +338,5 @@ jars.compile.order = bundle_tests/ext.framework.b.jar,\
bundle_tests/test.bug306181b.jar,\
bundle_tests/test.logging.a.jar,\
bundle_tests/geturl.jar,\
- bundle_tests/test.bug375784.jar
+ bundle_tests/test.bug375784.jar,\
+ bundle_tests/storage.hooks.a.jar
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..adedac0
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: storage.hooks.a
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHookConfigurator.java b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHookConfigurator.java
new file mode 100644
index 0000000..d2423ee
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/bundles_src/storage.hooks.a/org/eclipse/osgi/tests/hooks/framework/storage/a/TestHookConfigurator.java
@@ -0,0 +1,59 @@
+package org.eclipse.osgi.tests.hooks.framework.storage.a;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.util.Dictionary;
+import org.eclipse.osgi.internal.hookregistry.*;
+import org.eclipse.osgi.storage.BundleInfo.Generation;
+
+public class TestHookConfigurator implements HookConfigurator {
+ private static class TestStorageHookFactory extends StorageHookFactory<Object, Object, TestStorageHookFactory.TestStorageHook> {
+ private static class TestStorageHook extends StorageHookFactory.StorageHook<Object, Object> {
+ public TestStorageHook(Generation generation, Class clazz) {
+ super(generation, clazz);
+ }
+
+ @Override
+ public void initialize(Dictionary manifest) {
+ // Nothing.
+ }
+
+ @Override
+ public void load(Object loadContext, DataInputStream is) {
+ // Nothing.
+ }
+
+ @Override
+ public void save(Object saveContext, DataOutputStream os) {
+ // Nothing.
+ }
+
+ @Override
+ public void validate() throws IllegalStateException {
+ TestHookConfigurator.validateCalled = true;
+ if (TestHookConfigurator.invalid)
+ throw new IllegalStateException();
+ }
+ }
+
+ public TestStorageHookFactory() {
+ }
+
+ @Override
+ public int getStorageVersion() {
+ return 0;
+ }
+
+ @Override
+ public TestStorageHook createStorageHook(Generation generation) {
+ return new TestStorageHook(generation, TestStorageHookFactory.class);
+ }
+ }
+
+ public static volatile boolean invalid;
+ public static volatile boolean validateCalled;
+
+ public void addHooks(HookRegistry hookRegistry) {
+ hookRegistry.addStorageHookFactory(new TestStorageHookFactory());
+ }
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AbstractFrameworkHookTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AbstractFrameworkHookTests.java
new file mode 100644
index 0000000..31c4f9a
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/AbstractFrameworkHookTests.java
@@ -0,0 +1,135 @@
+package org.eclipse.osgi.tests.hooks.framework;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Enumeration;
+import java.util.Map;
+import org.eclipse.core.runtime.adaptor.EclipseStarter;
+import org.eclipse.core.tests.harness.CoreTest;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.launch.EquinoxFactory;
+import org.eclipse.osgi.tests.OSGiTestsActivator;
+import org.eclipse.osgi.tests.bundles.BundleInstaller;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+
+public abstract class AbstractFrameworkHookTests extends CoreTest {
+ protected static class BasicURLClassLoader extends URLClassLoader {
+ public BasicURLClassLoader(URL[] urls, ClassLoader parent) {
+ super(urls, parent);
+ }
+
+ @Override
+ public URL getResource(String name) {
+ if (isLocalResource(name))
+ return findResource(name);
+ return super.getResource(name);
+ }
+
+ @Override
+ public void addURL(URL url) {
+ super.addURL(url);
+ }
+
+ @Override
+ public Enumeration<URL> getResources(String name) throws IOException {
+ if (isLocalResource(name))
+ return findResources(name);
+ return super.getResources(name);
+ }
+
+ @Override
+ protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ if (name.startsWith("org.eclipse")) {
+ Class<?> result = findLoadedClass(name);
+ if (result == null)
+ result = findClass(name);
+ return result;
+ }
+ return super.loadClass(name, resolve);
+ }
+
+ private boolean isLocalResource(String name) {
+ return name.startsWith("org/eclipse") || name.equals(HookRegistry.HOOK_CONFIGURATORS_FILE);
+ }
+ }
+
+ protected static final String BUNDLES_ROOT = "bundle_tests";
+
+ protected BasicURLClassLoader classLoader;
+ protected BundleInstaller bundleInstaller;
+
+ public BundleContext getContext() {
+ return OSGiTestsActivator.getContext();
+ }
+
+ protected void assertBundleDiscarded(String location, Framework framework) {
+ assertNull("Bundle " + location + " was not discarded", framework.getBundleContext().getBundle(location));
+ }
+
+ protected void assertBundleNotDiscarded(String location, Framework framework) {
+ assertNotNull("Bundle " + location + " was discarded", framework.getBundleContext().getBundle(location));
+ }
+
+ protected Framework createFramework(Map<String, String> configuration) throws Exception {
+ FrameworkFactory factory = (FrameworkFactory) classLoader.loadClass(EquinoxFactory.class.getName()).newInstance();
+ Framework framework = factory.newFramework(configuration);
+ return framework;
+ }
+
+ protected void initAndStart(Framework framework) throws Exception {
+ framework.init();
+ framework.start();
+ }
+
+ protected Framework restart(Framework framework, Map<String, String> configuration) throws Exception {
+ stop(framework);
+ framework = createFramework(configuration);
+ initAndStart(framework);
+ return framework;
+ }
+
+ protected void setUp() throws Exception {
+ setUpBundleInstaller();
+ setUpClassLoader();
+ }
+
+ protected void stop(Framework framework) throws Exception {
+ framework.stop();
+ FrameworkEvent event = framework.waitForStop(5000);
+ assertEquals("The framework was not stopped", FrameworkEvent.STOPPED, event.getType());
+ }
+
+ protected void stopQuietly(Framework framework) {
+ if (framework == null)
+ return;
+ try {
+ stop(framework);
+ } catch (Exception e) {
+ // Ignore.
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ bundleInstaller.shutdown();
+ }
+
+ private void setUpBundleInstaller() throws Exception {
+ bundleInstaller = new BundleInstaller(BUNDLES_ROOT, getContext());
+ bundleInstaller.refreshPackages(null);
+ }
+
+ private void setUpClassLoader() throws Exception {
+ BundleContext context = getContext();
+ String osgiFramework = context.getProperty(EclipseStarter.PROP_FRAMEWORK);
+ URL[] urls;
+ if ("folder".equals(context.getProperty(EclipseStarter.PROP_FRAMEWORK_SHAPE)))
+ urls = new URL[] {new URL(osgiFramework), new URL(osgiFramework + "bin/")};
+ else
+ urls = new URL[] {new URL(osgiFramework)};
+ classLoader = new BasicURLClassLoader(urls, getClass().getClassLoader());
+ }
+}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/StorageHookTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/StorageHookTests.java
new file mode 100644
index 0000000..a5c00e2
--- /dev/null
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/StorageHookTests.java
@@ -0,0 +1,104 @@
+package org.eclipse.osgi.tests.hooks.framework;
+
+import java.io.File;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
+import org.eclipse.osgi.tests.OSGiTestsActivator;
+import org.osgi.framework.Constants;
+import org.osgi.framework.launch.Framework;
+
+/*
+ * The framework must discard bundles that are not valid according to storage
+ * hooks. See bug 407416.
+ */
+public class StorageHookTests extends AbstractFrameworkHookTests {
+ private static final String HOOK_CONFIGURATOR_BUNDLE = "storage.hooks.a";
+ private static final String HOOK_CONFIGURATOR_CLASS = "org.eclipse.osgi.tests.hooks.framework.storage.a.TestHookConfigurator";
+ private static final String HOOK_CONFIGURATOR_FIELD_INVALID = "invalid";
+ private static final String HOOK_CONFIGURATOR_FIELD_VALIDATE_CALLED = "validateCalled";
+
+ private Map<String, String> configuration;
+ private Framework framework;
+ private String location;
+
+ /*
+ * Bundles must be discarded if a storage hook throws an
+ * IllegalStateException during validation.
+ */
+ public void testBundleDiscardedWhenClasspathStorageHookInvalidates() throws Exception {
+ initAndStartFramework();
+ installBundle();
+ setStorageHookInvalid(true);
+ restartFramework();
+ assertStorageHookValidateCalled();
+ assertBundleDiscarded();
+ }
+
+ /*
+ * Bundles must not be discarded when a storage hook says they are valid.
+ */
+ public void testBundleNotDiscardedWhenClasspathStorageHookValidates() throws Exception {
+ initAndStartFramework();
+ installBundle();
+ setStorageHookInvalid(false);
+ restartFramework();
+ assertStorageHookValidateCalled();
+ assertBundleNotDiscarded();
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ String loc = bundleInstaller.getBundleLocation(HOOK_CONFIGURATOR_BUNDLE);
+ location = loc.substring(loc.indexOf("file:"));
+ classLoader.addURL(new URL(location));
+ File file = OSGiTestsActivator.getContext().getDataFile(getName());
+ configuration = new HashMap<String, String>();
+ configuration.put(Constants.FRAMEWORK_STORAGE, file.getAbsolutePath());
+ configuration.put(HookRegistry.PROP_HOOK_CONFIGURATORS_INCLUDE, HOOK_CONFIGURATOR_CLASS);
+ framework = createFramework(configuration);
+ resetStorageHook();
+ }
+
+ protected void tearDown() throws Exception {
+ stopQuietly(framework);
+ super.tearDown();
+ }
+
+ private void assertBundleDiscarded() {
+ assertBundleDiscarded(location, framework);
+ }
+
+ private void assertBundleNotDiscarded() {
+ assertBundleNotDiscarded(location, framework);
+ }
+
+ private void assertStorageHookValidateCalled() throws Exception {
+ Class<?> clazz = classLoader.loadClass(HOOK_CONFIGURATOR_CLASS);
+ assertTrue("Storage hook not called by framework", clazz.getField(HOOK_CONFIGURATOR_FIELD_VALIDATE_CALLED).getBoolean(null));
+ }
+
+ private void initAndStartFramework() throws Exception {
+ initAndStart(framework);
+ }
+
+ private void installBundle() throws Exception {
+ framework.getBundleContext().installBundle(location);
+ }
+
+ private void resetStorageHook() throws Exception {
+ Class<?> clazz = classLoader.loadClass(HOOK_CONFIGURATOR_CLASS);
+ clazz.getField(HOOK_CONFIGURATOR_FIELD_INVALID).set(null, false);
+ clazz.getField(HOOK_CONFIGURATOR_FIELD_VALIDATE_CALLED).set(null, false);
+ }
+
+ private void restartFramework() throws Exception {
+ framework = restart(framework, configuration);
+ }
+
+ private void setStorageHookInvalid(boolean value) throws Exception {
+ Class<?> clazz = classLoader.loadClass(HOOK_CONFIGURATOR_CLASS);
+ clazz.getField(HOOK_CONFIGURATOR_FIELD_INVALID).set(null, value);
+ }
+}
diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
index 798730f..db40083 100644
--- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
@@ -14,6 +14,7 @@ Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.ru
org.eclipse.osgi.framework.util;x-internal:=true,
org.eclipse.osgi.internal.debug;x-internal:=true,
org.eclipse.osgi.internal.framework;x-internal:=true,
+ org.eclipse.osgi.internal.hookregistry;x-friends:="org.eclipse.osgi.tests",
org.eclipse.osgi.internal.loader;x-internal:=true,
org.eclipse.osgi.internal.loader.buddy;x-internal:=true,
org.eclipse.osgi.internal.loader.classpath;x-internal:=true,
@@ -37,6 +38,7 @@ Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.ru
org.eclipse.osgi.service.security;version="1.0",
org.eclipse.osgi.service.urlconversion;version="1.0",
org.eclipse.osgi.signedcontent;version="1.0",
+ org.eclipse.osgi.storage;x-friends:="org.eclipse.osgi.tests",
org.eclipse.osgi.storage.bundlefile;x-internal:=true,
org.eclipse.osgi.storage.url.reference;x-internal:=true,
org.eclipse.osgi.storagemanager;version="1.0",