CQ-4081: Initial import
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.classpath b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.classpath
new file mode 100644
index 0000000..8a8f166
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<classpath>

+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>

+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>

+	<classpathentry kind="src" path="src"/>

+	<classpathentry kind="output" path="bin"/>

+</classpath>

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.project b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.project
new file mode 100644
index 0000000..314edad
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<projectDescription>

+	<name>org.eclipse.e4.enterprise.installer.test.integration.fixture</name>

+	<comment></comment>

+	<projects>

+	</projects>

+	<buildSpec>

+		<buildCommand>

+			<name>org.eclipse.jdt.core.javabuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>org.eclipse.pde.ManifestBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>org.eclipse.pde.SchemaBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+	</buildSpec>

+	<natures>

+		<nature>org.eclipse.pde.PluginNature</nature>

+		<nature>org.eclipse.jdt.core.javanature</nature>

+	</natures>

+</projectDescription>

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.settings/org.eclipse.jdt.core.prefs b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..b0ecde1
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+#Tue Apr 21 16:18:59 CDT 2009

+eclipse.preferences.version=1

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5

+org.eclipse.jdt.core.compiler.compliance=1.5

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error

+org.eclipse.jdt.core.compiler.source=1.5

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/META-INF/MANIFEST.MF b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..e4491eb
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/META-INF/MANIFEST.MF
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Rcpexample Plug-in
+Bundle-SymbolicName: org.eclipse.e4.enterprise.installer.test.integration.fixture;singleton:=true
+Bundle-Version: 4.6.0.qualifier
+Bundle-Activator: org.eclipse.e4.enterprise.installer.test.integration.fixture.Activator
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.update.configurator,
+ org.eclipse.update.core,
+ org.eclipse.e4.enterprise.installer,
+ org.eclipse.e4.enterprise.installer.ui.swt,
+ org.eclipse.e4.core.metaconfig
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/README b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/README
new file mode 100644
index 0000000..8ecda35
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/README
@@ -0,0 +1,66 @@
+What is this?

+

+Test fixtures for testing updating from version X to version Y.

+

+products/*  -- Minimal platform with installer

+sites/*     -- Update site to update platform to specified destination version

+			   (don't want to use full update site because we don't want to update the bootstrapper)

+

+The table below summarizes for each release if the "driver bundle" is the RCP Example 

+or the Bootstrapper and which API was the "default" API path through the installer 

+for that release:

+

+4.0.0 - RCP Example  -> BundleUpdater#update(String) 

+4.1.1 - RCP Example  -> BundleUpdater#update(String) 

+4.2.0 - Bootstrapper -> BundleUpdaterHelper#updateWithProgressDialog() -> BundleUpdater#update(String)

+4.3.0 - Bootstrapper -> BundleUpdaterHelper#updateWithProgressDialog() -> BundleUpdater#update(String)

+4.4.1 - Bootstrapper -> BundleUpdaterHelper#updateWithProgressDialog() -> BundleUpdater#update(URL, File)

+

+The installer test verifies the following:

+

+Given versions V(4.0.0) to V(4.n), for all V(x), the installer test ensures that we can 

+successfully update from V(x) to V(x+1), V(x+2), ..., V(n).

+

+In each case, we do *not* update the "driver bundle" (ie: the RCP example bundle or the 

+bootstrapper), but only the installer, and verify that the resulting installation works.  We

+also test some other minimal invariants.  This results in the following observation from the 

+above table:

+

+For versions 4.0.0-4.3.0, the default installer execution path always went through 

+#update(String).  For versions subsequent to 4.3.0, the default installer execution path goes

+through #update(URL, File).

+

+Consequently, the platform fixture for versions 4.0.0-4.3.0 will only execute the #update(String)

+code path.  Similarly, versions after 4.3.0 (noninclusive) will only execute the #update(URL, File)

+code path.  Since the various #update methods are only convenience methods that delegate to

+the "real" #update method and don't do any work of their own, this seems like a reasonable 

+compromise over testing all permutations of #update methods for each pair of version upgrades.

+

+Lastly, version 4.4.0 removed all permutations of the legacy #update(String) method.  For testability

+and to ease customer migration, 4.4.1 adds back a single #update(String) method but marks it as

+@deprecated.  This will enable all customers who used the default installer code path up through 4.3.0

+to upgrade to 4.4.1 without needing to also upgrade their bootstrapper.  They can then upgrade

+their bootstrapper separately when needed.

+

+-------------------------------

+

+In order to run the Integration tests contained within this plug-in you need to;

+

+1) Open up install.product and export to a directory somewhere

+

+2) Open up the InstallerIntegrationTest class (under org.eclipse.e4.enterprise.installer.test.integration)

+

+3) Change the EXPORT_DIR constant to match the directory where you exported in Step 1)

+	(Don't include any eclipse sub directory)

+

+4) Right click InstallerIntegrationTest and click "Run as Junit test"

+

+---------

+

+Problems writing an integration test for upgrade problem:

+

+1) Unlike all the other tests, this test must start with a fixture that is at a specific version.

+

+What this is *really* chasing is: Can we upgrade from any prior version of the platform to the current

+version and guarantee that (1) it works, and (2) there is some minimal consistent behavior.

+

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/about.html b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/about.html
new file mode 100644
index 0000000..f77f378
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/about.html
@@ -0,0 +1,22 @@
+<h1>About This Content</h1>
+
+23 June, 2010
+
+<h2>License</h2>
+
+<p>The Eclipse Foundation makes available all content in this plug-in
+("Content"). Unless otherwise indicated below, the Content is provided
+to you under the terms and conditions of the Eclipse Public License
+Version 1.0 ("EPL"). A copy of the EPL is available at
+http://www.eclipse.org/legal/epl-v10.html. For purposes of the EPL,
+"Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse
+Foundation, the Content is being redistributed by another party
+("Redistributor") and different terms and conditions may apply to your
+use of any object code in the Content. Check the Redistributor’s
+license that was provided with the Content. If no such license exists,
+contact the Redistributor. Unless otherwise indicated below, the terms
+and conditions of the EPL still apply to any source code in the
+Content and such source code may be obtained at
+http://www.eclipse.org.</p>
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/build.properties b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/build.properties
new file mode 100644
index 0000000..efe57e0
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/build.properties
@@ -0,0 +1,6 @@
+source.. = src/

+output.. = bin/

+bin.includes = plugin.xml,\

+               META-INF/,\

+               .

+src.includes = src/

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/icons/alt_window_16.gif b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/icons/alt_window_16.gif
new file mode 100644
index 0000000..05626b1
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/icons/alt_window_16.gif
Binary files differ
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/icons/alt_window_32.gif b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/icons/alt_window_32.gif
new file mode 100644
index 0000000..b432f88
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/icons/alt_window_32.gif
Binary files differ
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/integration.product b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/integration.product
new file mode 100644
index 0000000..7b8fcaf
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/integration.product
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<?pde version="3.4"?>

+

+<product name="Installer RCP Application Example" id="org.eclipse.e4.enterprise.installer.test.integration.rcpmain.product" application="org.eclipse.e4.enterprise.installer.test.integration.rcpmain.application" version="1.0" useFeatures="true">

+

+   <configIni use="default">

+   </configIni>

+

+   <launcherArgs>

+      <vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts</vmArgsMac>

+   </launcherArgs>

+

+   <launcher>

+      <solaris/>

+      <win useIco="false">

+         <bmp/>

+      </win>

+   </launcher>

+

+   <vm>

+   </vm>

+

+   <plugins>

+   </plugins>

+

+   <features>

+      <feature id="org.eclipse.e4.enterprise.installer.feature" version="0.0.0"/>

+      <feature id="org.eclipse.e4.enterprise.config.feature" version="0.0.0"/>

+      <feature id="org.eclipse.rcp" version="0.0.0"/>

+      <feature id="org.eclipse.e4.enterprise.installer.test.integration.feature" version="0.0.0"/>

+   </features>

+

+</product>

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/plugin.xml b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/plugin.xml
new file mode 100644
index 0000000..f5b8391
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/plugin.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<?eclipse version="3.2"?>

+<plugin>

+

+   <extension

+         id="application"

+         point="org.eclipse.core.runtime.applications">

+      <application>

+         <run

+               class="org.eclipse.e4.enterprise.installer.test.integration.fixture.Application">

+         </run>

+      </application>

+   </extension>

+   <extension

+         point="org.eclipse.ui.perspectives">

+      <perspective

+            name="Perspective"

+            class="org.eclipse.e4.enterprise.installer.test.integration.fixture.Perspective"

+            id="org.eclipse.e4.enterprise.installer.test.integration.fixture.perspective">

+      </perspective>

+   </extension>

+   <extension

+         point="org.eclipse.ui.views">

+      <view

+            name="View"

+            class="org.eclipse.e4.enterprise.installer.test.integration.fixture.View"

+            id="org.eclipse.e4.enterprise.installer.test.integration.fixture.view">

+      </view>

+   </extension>

+   <extension

+         id="product"

+         point="org.eclipse.core.runtime.products">

+      <product

+            application="org.eclipse.e4.enterprise.installer.test.integration.rcpmain.application"

+            name="Installer RCP Application Example">

+         <property

+               name="appName"

+               value="Installer RCP Application Example">

+         </property>

+      </product>

+   </extension>

+

+</plugin>

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Activator.java b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Activator.java
new file mode 100644
index 0000000..ed96c37
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Activator.java
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * Copyright (c) David Orme 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:
+ *    David Orme - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.enterprise.installer.test.integration.fixture;

+

+import org.eclipse.e4.core.metaconfig.Configuration;
+import org.eclipse.jface.resource.ImageDescriptor;

+import org.eclipse.ui.plugin.AbstractUIPlugin;

+import org.osgi.framework.BundleContext;

+import org.osgi.util.tracker.ServiceTracker;

+

+

+/**

+ * The activator class controls the plug-in life cycle

+ */

+public class Activator extends AbstractUIPlugin {

+

+	// The plug-in ID

+	public static final String PLUGIN_ID = "org.eclipse.e4.enterprise.installer.test.integration.fixture";

+

+	// The shared instance

+	private static Activator plugin;

+	

+	/**

+	 * The constructor

+	 */

+	public Activator() {

+	}

+

+	private ServiceTracker configTracker;

+

+	/**

+	 * @return the current configuration file's Properties object.  May be null

+	 * if the configuration service is not loaded or is not included in the 

+	 * application.

+	 */

+	public Configuration getConfiguration() {

+		return (Configuration) configTracker.getService();

+	}

+	

+	/*

+	 * (non-Javadoc)

+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)

+	 */

+	public void start(BundleContext context) throws Exception {

+		super.start(context);

+		configTracker = new ServiceTracker(context, Configuration.class.getName(), null);

+		configTracker.open();

+		plugin = this;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)

+	 */

+	public void stop(BundleContext context) throws Exception {

+		plugin = null;

+		super.stop(context);

+	}

+

+	/**

+	 * Returns the shared instance

+	 *

+	 * @return the shared instance

+	 */

+	public static Activator getDefault() {

+		return plugin;

+	}

+

+	/**

+	 * Returns an image descriptor for the image file at the given

+	 * plug-in relative path

+	 *

+	 * @param path the path

+	 * @return the image descriptor

+	 */

+	public static ImageDescriptor getImageDescriptor(String path) {

+		return imageDescriptorFromPlugin(PLUGIN_ID, path);

+	}

+}

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Application.java b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Application.java
new file mode 100644
index 0000000..0a230a4
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Application.java
@@ -0,0 +1,172 @@
+/******************************************************************************
+ * Copyright (c) David Orme 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:
+ *    David Orme - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.enterprise.installer.test.integration.fixture;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.core.metaconfig.Configuration;
+import org.eclipse.e4.core.metaconfig.ConfigurationException;
+import org.eclipse.e4.enterprise.installer.InstallError;
+import org.eclipse.e4.enterprise.installer.ui.swt.BundleUpdaterHelper;
+import org.eclipse.e4.enterprise.installer.ui.swt.BundleUpdaterHelper.UpdateResult;
+import org.eclipse.e4.enterprise.installer.ui.swt.BundleUpdaterHelper.UpdateStatus;
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.update.configuration.IConfiguredSite;
+import org.eclipse.update.configuration.IInstallConfiguration;
+import org.eclipse.update.core.IFeatureReference;
+import org.eclipse.update.core.SiteManager;
+import org.eclipse.update.core.VersionedIdentifier;
+
+
+/**
+ * This class controls all aspects of the application's execution
+ */
+public class Application implements IApplication {
+	public static final String MESSAGE_LOCATION_KEY = "org.eclipse.e4.enterprise.installer.test.integration.MESSAGE_LOCATION";
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
+	 */
+	public Object start(IApplicationContext context) {
+		Activator activator = Activator.getDefault();
+		
+		activator.getLog().log(new Status(Status.INFO, "!STARTUP", "Startup at " + new Date()));
+		
+		Configuration configuration = activator.getConfiguration();
+		String messageLocationString = (String) configuration.getProperties().get(MESSAGE_LOCATION_KEY);
+		if (messageLocationString == null) {
+			messageLocationString = "messages.txt";
+		}
+		File messageLocationFile = new File(messageLocationString);
+		try {
+			UpdateStatus status = configureInstaller(configuration);
+			UpdateResult result = status.result;
+			switch (result) {
+			case FAILURE_INSTALL_ERROR:
+				logError(status.failureException.getMessage(), status.failureException);
+				return IApplication.EXIT_OK;
+			case FAILURE_USER_CANCELLED:
+			case SUCCESS_RESTART_NOT_REQUIRED:
+				//things are installed, any restarts have happened so now log which features are installed
+				logInstalledFeatures(messageLocationFile);
+				activator.getLog().log(new Status(Status.INFO, "!STARTUP", "No updates downloaded, continuing..."));
+				return IApplication.EXIT_OK;
+			case SUCCESS_RESTART_REQUIRED:
+				activator.getLog().log(new Status(Status.INFO, "!STARTUP", "Downloaded updates; Restarting..."));
+				return IApplication.EXIT_RESTART;
+			default:
+				logError("Should not get to this case!", new RuntimeException());
+				assert(false);
+			}
+		} catch (ConfigurationException e) {
+			// boom - something's gone wrong. 
+			// If this were a real app, we'd want to do something here. 
+			// Like log it or tell user or generally be unhappy.
+			//
+			// currently, we will "exit ok" (restart == false) , as opposed to asking for a restart.
+			// ... which for the purposes of this test, is fine.
+			String message = "Unable to access configuration";
+			logError(message, e);
+			return IApplication.EXIT_OK;
+		} catch (InstallError e) {
+			logError(e.getMessage(), e);
+			return IApplication.EXIT_OK;
+		} catch (IOException e) {
+			logError(e.getMessage(), e);
+			e.printStackTrace();
+		}
+		
+		return IApplication.EXIT_OK;
+	}
+
+	private static final String FEATURE_PREFIX_ECLIPSE = "org.eclipse";
+
+	private void logInstalledFeatures(File messageLocationFile) throws IOException, InstallError {
+
+		List<String> installedFeatures = getInstalledFeatures();
+		StringBuffer installedFeatureStrings = new StringBuffer("");
+
+		FileWriter writer = new FileWriter(messageLocationFile, false);
+		for (String feature : installedFeatures) {
+			if (feature.startsWith(FEATURE_PREFIX_ECLIPSE)) {
+				installedFeatureStrings.append(feature + "\r\n");
+			}
+		}
+
+		writer.write(installedFeatureStrings.toString());
+		writer.flush();
+		writer.close();
+	}
+	
+	public List<String> getInstalledFeatures() {
+		List<String> installedFeatures = new ArrayList<String>();
+		try {
+			IInstallConfiguration config = SiteManager.getLocalSite().getCurrentConfiguration();
+			IConfiguredSite[] sites = config.getConfiguredSites();
+			for (IConfiguredSite configuredSite : sites) {
+				IFeatureReference[] featureReferences = configuredSite.getConfiguredFeatures();
+				for (IFeatureReference featureReference : featureReferences) {
+					VersionedIdentifier versionedIdentifier = featureReference.getVersionedIdentifier();
+					String item = versionedIdentifier.getIdentifier() + versionedIdentifier.getVersion();
+					installedFeatures.add(item);
+				}
+			}
+		} catch (CoreException e) {
+			e.printStackTrace();
+		}
+		return installedFeatures;
+	}
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.equinox.app.IApplication#stop()
+	 */
+	public void stop() {
+		final IWorkbench workbench = PlatformUI.getWorkbench();
+		if (workbench == null)
+			return;
+		final Display display = workbench.getDisplay();
+		display.syncExec(new Runnable() {
+			public void run() {
+				if (!display.isDisposed())
+					workbench.close();
+			}
+		});
+		updateThread.interrupt();
+	}
+	
+	// Install updates, if available ----------------------------------------------------------------------
+	
+	private Thread updateThread;
+
+	private UpdateStatus configureInstaller(Configuration config) throws ConfigurationException, InstallError {
+		return new BundleUpdaterHelper().updateWithProgressDialog();
+	}
+
+	// For our example, we'll use the Eclipse logger, but you can use any logger you want.
+	void logError(String message, Throwable e) {
+		IStatus error = new Status(Status.ERROR, Activator.PLUGIN_ID, message, e);
+		Activator.getDefault().getLog().log(error);
+	}
+
+}
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationActionBarAdvisor.java b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationActionBarAdvisor.java
new file mode 100644
index 0000000..e49428a
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationActionBarAdvisor.java
@@ -0,0 +1,58 @@
+/******************************************************************************
+ * Copyright (c) David Orme 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:
+ *    David Orme - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.enterprise.installer.test.integration.fixture;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+
+/**
+ * An action bar advisor is responsible for creating, adding, and disposing of
+ * the actions added to a workbench window. Each window will be populated with
+ * new actions.
+ */
+public class ApplicationActionBarAdvisor extends ActionBarAdvisor {
+
+	// Actions - important to allocate these only in makeActions, and then use
+	// them
+	// in the fill methods. This ensures that the actions aren't recreated
+	// when fillActionBars is called with FILL_PROXY.
+	private IWorkbenchAction exitAction;
+
+	public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) {
+		super(configurer);
+	}
+
+	protected void makeActions(final IWorkbenchWindow window) {
+		// Creates the actions and registers them.
+		// Registering is needed to ensure that key bindings work.
+		// The corresponding commands keybindings are defined in the plugin.xml
+		// file.
+		// Registering also provides automatic disposal of the actions when
+		// the window is closed.
+
+		exitAction = ActionFactory.QUIT.create(window);
+		register(exitAction);
+	}
+
+	protected void fillMenuBar(IMenuManager menuBar) {
+		MenuManager fileMenu = new MenuManager("&File",
+				IWorkbenchActionConstants.M_FILE);
+		menuBar.add(fileMenu);
+		fileMenu.add(exitAction);
+	}
+
+}
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationWorkbenchAdvisor.java b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationWorkbenchAdvisor.java
new file mode 100644
index 0000000..275cd99
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationWorkbenchAdvisor.java
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) David Orme 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:
+ *    David Orme - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.enterprise.installer.test.integration.fixture;
+
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchAdvisor;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor {
+
+	private static final String PERSPECTIVE_ID = "org.eclipse.e4.enterprise.installer.test.integration.fixture.perspective";
+
+	public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
+			IWorkbenchWindowConfigurer configurer) {
+		return new ApplicationWorkbenchWindowAdvisor(configurer);
+	}
+
+	public String getInitialWindowPerspectiveId() {
+		return PERSPECTIVE_ID;
+	}
+
+}
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationWorkbenchWindowAdvisor.java b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationWorkbenchWindowAdvisor.java
new file mode 100644
index 0000000..46b8ced
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/ApplicationWorkbenchWindowAdvisor.java
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Copyright (c) David Orme 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:
+ *    David Orme - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.enterprise.installer.test.integration.fixture;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
+
+	public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
+		super(configurer);
+	}
+
+	public ActionBarAdvisor createActionBarAdvisor(
+			IActionBarConfigurer configurer) {
+		return new ApplicationActionBarAdvisor(configurer);
+	}
+
+	public void preWindowOpen() {
+		IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
+		configurer.setInitialSize(new Point(400, 300));
+		configurer.setShowCoolBar(false);
+		configurer.setShowStatusLine(false);
+		configurer.setTitle("Installer RCP Demo");
+	}
+}
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/BackgroundUpdater.java b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/BackgroundUpdater.java
new file mode 100644
index 0000000..b81c284
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/BackgroundUpdater.java
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * Copyright (c) David Orme 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:
+ *    David Orme - initial API and implementation
+ ******************************************************************************/
+/**

+ * 

+ */

+package org.eclipse.e4.enterprise.installer.test.integration.fixture;

+

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.jobs.Job;

+import org.eclipse.e4.enterprise.installer.BundleUpdater;

+import org.eclipse.e4.enterprise.installer.InstallError;

+import org.eclipse.ui.PlatformUI;

+

+

+class BackgroundUpdater implements Runnable {

+	private final Application application;

+	private BundleUpdater updater;

+	private String url;

+	private int hours;

+	

+	public BackgroundUpdater(Application application, BundleUpdater updater, String url, int hours) {

+		this.application = application;

+		this.updater = updater;

+		this.url = url;

+		this.hours = hours;

+	}

+	

+	public void run() {

+		while (true) {

+			try {

+				Thread.sleep(1000*60*60 * hours);  // update every hour

+			} catch (InterruptedException e) {

+				// Application is closing; return

+				return;

+			}

+			Job updateJob = new Job("Updating application") {

+				@Override

+				protected IStatus run(IProgressMonitor monitor) {

+					try {

+						monitor.beginTask("Updating application", 1);

+						if (updater.update(url)) {

+							PlatformUI.getWorkbench().restart();

+						}

+						monitor.worked(1);

+					} catch (InstallError e) {

+						BackgroundUpdater.this.application.logError(e.getMessage(), e);

+					}

+					return null;

+				}

+			};

+			updateJob.schedule();

+		}

+	}

+}

+

diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Perspective.java b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Perspective.java
new file mode 100644
index 0000000..2f7e28d
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/Perspective.java
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * Copyright (c) David Orme 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:
+ *    David Orme - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.enterprise.installer.test.integration.fixture;
+
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+public class Perspective implements IPerspectiveFactory {
+
+	public void createInitialLayout(IPageLayout layout) {
+		String editorArea = layout.getEditorArea();
+		layout.setEditorAreaVisible(false);
+		layout.setFixed(true);
+		
+		layout.addStandaloneView(View.ID,  false, IPageLayout.LEFT, 1.0f, editorArea);
+	}
+
+}
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/View.java b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/View.java
new file mode 100644
index 0000000..d596640
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/View.java
@@ -0,0 +1,94 @@
+/******************************************************************************
+ * Copyright (c) David Orme 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:
+ *    David Orme - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.enterprise.installer.test.integration.fixture;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.ui.part.ViewPart;
+import org.eclipse.update.configuration.IConfiguredSite;
+import org.eclipse.update.configuration.IInstallConfiguration;
+import org.eclipse.update.core.IFeatureReference;
+import org.eclipse.update.core.SiteManager;
+import org.eclipse.update.core.VersionedIdentifier;
+
+public class View extends ViewPart {
+	public static final String ID = "org.eclipse.e4.enterprise.installer.test.integration.fixture.view";
+
+	private IConfiguredSite[] sites;
+
+	private List installedFeatures;
+
+	public void createPartControl(Composite parent) {
+		parent.setLayout(new GridLayout());
+
+		// Layout the UI: Installed features list
+		new Label(parent, SWT.NULL).setText("Installed features");
+		installedFeatures = new List(parent, SWT.BORDER|SWT.V_SCROLL);
+		installedFeatures.add("Computing initial list...");
+		installedFeatures.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		
+		// Populate the installed features list and hook up the events
+		// This is demo code so we willingly mix presentation and behavior :-)
+
+		/*
+		 * NOTE: This is demo code so we create a Thread directly.  Production code should
+		 * use the Eclipse Jobs API.
+		 */
+		Thread backgroundInit = new Thread(new Runnable() {
+			public void run() {
+				try {
+					IInstallConfiguration config = SiteManager.getLocalSite().getCurrentConfiguration();
+					sites = config.getConfiguredSites();
+					populateInstalledFeaturesList(installedFeatures);
+				} catch (CoreException e) {
+					e.printStackTrace();
+				}
+			}
+			
+			private void populateInstalledFeaturesList(final List installedFeatures) {
+				// NOTE: Production code should use Eclipse's Jobs API to get on the Display thread...
+				Display.getDefault().asyncExec(new Runnable() {
+					public void run() {
+						installedFeatures.removeAll();
+					}
+				});
+				try {
+					for (IConfiguredSite configuredSite : sites) {
+						IFeatureReference[] featureReferences = configuredSite.getConfiguredFeatures();
+						for (IFeatureReference featureReference : featureReferences) {
+							VersionedIdentifier versionedIdentifier = featureReference.getVersionedIdentifier();
+							final String item = versionedIdentifier.getIdentifier() + versionedIdentifier.getVersion();
+							// NOTE: Production code should use Eclipse's Jobs API to get on the Display thread...
+							Display.getDefault().asyncExec(new Runnable() {
+								public void run() {
+									installedFeatures.add(item);
+								}
+							});
+						}
+					}
+				} catch (CoreException e) {
+					e.printStackTrace();
+				}
+			}
+		});
+		backgroundInit.start();
+	}
+
+	public void setFocus() {
+		installedFeatures.setFocus();
+	}
+}
diff --git a/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/layout.xswt b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/layout.xswt
new file mode 100644
index 0000000..66caa37
--- /dev/null
+++ b/tests/org.eclipse.e4.enterprise.installer.test.integration.fixture/src/org/eclipse/e4/enterprise/installer/test/integration/fixture/layout.xswt
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xswt xmlns:x="http://sweet_swt.sf.net/xswt">
+    <import xmlns="http://sweet_swt.sf.net/xswt">
+        <package name="java.lang"/>
+        <package name="org.eclipse.swt.widgets"/>
+        <package name="org.eclipse.swt.layout"/>
+    </import>
+    
+    <composite>
+        <layoutData x:class="gridData" grabExcessHorizontalSpace="true" grabExcessVerticalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.FILL"/>
+        <layout x:class="gridLayout" />
+        
+        <label x:style="WRAP" text="Something really really really bad happened and we could not update">
+	        <layoutData x:class="gridData" grabExcessHorizontalSpace="true" grabExcessVerticalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.FILL"/>
+        </label>
+        
+        <label x:style="SEPARATOR|HORIZONTAL">
+	        <layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL"/>
+        </label>
+        
+        <button text="OK">
+	        <layoutData x:class="gridData" horizontalAlignment="GridData.CENTER"/>
+        </button>
+    </composite>
+</xswt>