CQ-4081: Initial import
diff --git a/tests/org.eclipse.e4.core.deeplink.test/.classpath b/tests/org.eclipse.e4.core.deeplink.test/.classpath
new file mode 100644
index 0000000..8a8f166
--- /dev/null
+++ b/tests/org.eclipse.e4.core.deeplink.test/.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.core.deeplink.test/.project b/tests/org.eclipse.e4.core.deeplink.test/.project
new file mode 100644
index 0000000..369feb5
--- /dev/null
+++ b/tests/org.eclipse.e4.core.deeplink.test/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<projectDescription>

+	<name>org.eclipse.e4.core.deeplink.test</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.core.deeplink.test/.settings/org.eclipse.jdt.core.prefs b/tests/org.eclipse.e4.core.deeplink.test/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..86c81bb
--- /dev/null
+++ b/tests/org.eclipse.e4.core.deeplink.test/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+#Wed Jan 13 23:46:14 CST 2010

+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.core.deeplink.test/META-INF/MANIFEST.MF b/tests/org.eclipse.e4.core.deeplink.test/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..f519bb8
--- /dev/null
+++ b/tests/org.eclipse.e4.core.deeplink.test/META-INF/MANIFEST.MF
@@ -0,0 +1,9 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Test Fragment
+Bundle-SymbolicName: org.eclipse.e4.core.deeplink.test
+Bundle-Version: 4.6.0.qualifier
+Fragment-Host: org.eclipse.e4.core.deeplink;bundle-version="4.5.0.qualifier"
+Require-Bundle: org.junit,
+ org.easymock
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/tests/org.eclipse.e4.core.deeplink.test/build.properties b/tests/org.eclipse.e4.core.deeplink.test/build.properties
new file mode 100644
index 0000000..41eb6ad
--- /dev/null
+++ b/tests/org.eclipse.e4.core.deeplink.test/build.properties
@@ -0,0 +1,4 @@
+source.. = src/

+output.. = bin/

+bin.includes = META-INF/,\

+               .

diff --git a/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/DeepLinkBundleListTest.java b/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/DeepLinkBundleListTest.java
new file mode 100644
index 0000000..c808074
--- /dev/null
+++ b/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/DeepLinkBundleListTest.java
@@ -0,0 +1,143 @@
+/******************************************************************************
+ * 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.core.deeplink;

+

+import junit.framework.TestCase;

+

+import org.easymock.EasyMock;

+import org.eclipse.e4.core.deeplink.DeepLinkBundleList;
+import org.osgi.framework.Bundle;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.BundleException;

+

+

+public class DeepLinkBundleListTest extends TestCase {

+	private DeepLinkBundleList testee = null;

+	

+	// Utility methods ------------------------------------------------------------

+	

+	private DeepLinkBundleList newStartupBundlesHack(Bundle[] availableBundles) throws Exception {

+		BundleContext context = EasyMock.createMock(BundleContext.class);

+		EasyMock.expect(context.getBundles()).andStubReturn(availableBundles);

+		EasyMock.replay(context);

+		return new DeepLinkBundleList(context);

+	}

+	

+	private Bundle newUnstartableBundle(String bundleName) {

+		Bundle bundle = EasyMock.createMock(Bundle.class);

+		EasyMock.expect(bundle.getSymbolicName()).andStubReturn(bundleName);

+		EasyMock.replay(bundle);

+		return bundle;

+	}

+

+	private Bundle newBundleToStart(String bundleName) throws BundleException {

+		Bundle bundle = EasyMock.createMock(Bundle.class);

+		EasyMock.expect(bundle.getSymbolicName()).andStubReturn(bundleName);

+		bundle.stop();

+		bundle.start();

+		EasyMock.replay(bundle);

+		return bundle;

+	}

+

+	// Verify that we started the Bundles we wanted to start and no others

+	private void verifyBundles(Bundle[] availableBundles) {

+		for (Bundle bundle : availableBundles) {

+			EasyMock.verify(bundle);

+		}

+	}

+

+	// Tests ----------------------------------------------------------------------

+	

+	/*

+	 * There's nothing sacred about the set of bundles to start.  But we do want the

+	 * test to notice if this set changes.

+	 */

+	public void testExpectedSetOfStartupBundles() throws Exception {

+		testee = newStartupBundlesHack(new Bundle[]{});

+		String[] bundlesToLoad = testee.loadTheseBundles;

+		assertEquals(4, bundlesToLoad.length);

+		assertEquals("org.eclipse.e4.enterprise.deeplink.handler", bundlesToLoad[0]);

+		assertEquals("org.eclipse.equinox.http.jetty", bundlesToLoad[1]);

+		assertEquals("org.eclipse.equinox.http.servlet", bundlesToLoad[2]);

+		assertEquals("org.eclipse.equinox.http.registry", bundlesToLoad[3]);

+	}

+

+	public void testStartupBundlesForHTTPServlets_noneMatch() throws Exception {

+		Bundle[] availableBundles = new Bundle[] {

+				newUnstartableBundle("a"),

+				newUnstartableBundle("b"),

+				newUnstartableBundle("c")

+		};

+		testee = newStartupBundlesHack(availableBundles);

+		

+		testee.startupBundlesForHttpServlets();

+

+		verifyBundles(availableBundles);

+	}

+

+	public void testStartupBundlesForHTTPServlets_allMatch() throws Exception {

+		Bundle[] availableBundles = new Bundle[] {

+				newBundleToStart("org.eclipse.e4.enterprise.deeplink.handler"),

+				newBundleToStart("org.eclipse.equinox.http.jetty"),

+				newBundleToStart("org.eclipse.equinox.http.servlet"),

+				newBundleToStart("org.eclipse.equinox.http.registry")

+		};

+		testee = newStartupBundlesHack(availableBundles);

+		

+		testee.startupBundlesForHttpServlets();

+

+		verifyBundles(availableBundles);

+	}

+

+	public void testStartupBundlesForHTTPServlets_someMatch_throwsException() throws Exception {

+		Bundle[] availableBundles = new Bundle[] {

+				newUnstartableBundle("a"),

+				newUnstartableBundle("b"),

+				newUnstartableBundle("c"),

+				newBundleToStart("org.eclipse.e4.enterprise.deeplink.handler"),

+//				newBundleToStart("org.eclipse.equinox.http.jetty"),  // commenting this out should cause exception below

+				newBundleToStart("org.eclipse.equinox.http.servlet"),

+				newBundleToStart("org.eclipse.equinox.http.registry")

+		};

+		testee = newStartupBundlesHack(availableBundles);

+

+		try {

+			testee.startupBundlesForHttpServlets();

+			// If the deep link handler is present, jetty, http.servlet, and http.reg must also be

+			fail("Should have detected that jetty is not available to start");

+		} catch (BundleException e) {

+			//success

+		}

+	}

+	

+	public void testStartupBundlesForHTTPServlets_someMatch_butNoDeepLink() throws Exception {

+		Bundle[] availableBundles = new Bundle[] {

+				newUnstartableBundle("a"),

+				newUnstartableBundle("b"),

+				newUnstartableBundle("c"),

+// The following two are intentionally commented out:

+//				newBundleToStart("org.eclipse.e4.enterprise.deeplink.handler"),

+//				newBundleToStart("org.eclipse.equinox.http.jetty"),

+				newBundleToStart("org.eclipse.equinox.http.servlet"),

+				newBundleToStart("org.eclipse.equinox.http.registry")

+		};

+		testee = newStartupBundlesHack(availableBundles);

+

+		try {

+			testee.startupBundlesForHttpServlets();

+			verifyBundles(availableBundles);

+			// success because we only enforce all/nothing if deeplink is specified

+		} catch (BundleException e) {

+			fail("Deep linking isn't available; client may specify anything else");

+		}

+	}

+	

+}

diff --git a/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/internal/DeeplinkPortAssignerTest.java b/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/internal/DeeplinkPortAssignerTest.java
new file mode 100644
index 0000000..89b30a9
--- /dev/null
+++ b/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/internal/DeeplinkPortAssignerTest.java
@@ -0,0 +1,106 @@
+/******************************************************************************
+ * 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.core.deeplink.internal;

+

+

+import org.eclipse.e4.core.deeplink.internal.DeepLinkProperties;
+import org.eclipse.e4.core.deeplink.internal.DeeplinkPortAssigner;
+

+

+import junit.framework.TestCase;

+

+public class DeeplinkPortAssignerTest extends TestCase {

+	

+	private static final String BASE_PORT_NUMBER_KEY = "base.port.number";

+	private static final int BASE_PORT_NUMBER = 9000;

+	private static final String MY_INSTALLATION = "myInstallation";

+	

+	private DeepLinkProperties props;

+

+	public void setUp() throws Exception {	

+		props = new DeepLinkProperties();

+		props.put(BASE_PORT_NUMBER_KEY, BASE_PORT_NUMBER);

+	}

+	

+

+	public void testPortNumberIsNotRegeneratedWhenRegeneratePortNumberIsFalse_andThrowsException() {

+		props.setInstallationPort("oneInstallation", BASE_PORT_NUMBER+2);

+		props.setInstallationPort(MY_INSTALLATION, BASE_PORT_NUMBER+2);

+		DeeplinkPortAssigner testee = new DeeplinkPortAssigner(props, false);

+

+		try{

+			testee.getPortNumberForInstallation(MY_INSTALLATION);

+			fail();

+		} catch (RuntimeException e) {

+			// pass();

+		}

+		

+	}

+	

+	

+	public void testPortForInstallationIsRegenerated_whenTheInstallationsPortIsAlreadyAssignedInTheProperties(){

+		props.setInstallationPort("oneInstallation", BASE_PORT_NUMBER+2);

+		props.setInstallationPort(MY_INSTALLATION, BASE_PORT_NUMBER+2);

+		DeeplinkPortAssigner testee = new DeeplinkPortAssigner(props, true);

+		

+		assertEquals(BASE_PORT_NUMBER, testee.getPortNumberForInstallation(MY_INSTALLATION));

+		assertEquals(Integer.toString(BASE_PORT_NUMBER), props.getInstallationPort(MY_INSTALLATION));

+	}

+	

+	public void testPortForInstallationIsGenereatedAndStored_whenRequestedInstallationDoesNotExist_andTwoExistingInstallationExistAlready() {

+		props.setProperty("yetAnotherInstallation", Integer.toString(BASE_PORT_NUMBER+2) );

+		DeeplinkPortAssigner testee = new DeeplinkPortAssigner(props, true);

+		assertEquals(BASE_PORT_NUMBER, testee.getPortNumberForInstallation("someInstallation"));

+		assertEquals(BASE_PORT_NUMBER+1, testee.getPortNumberForInstallation("moreInstallations"));

+		assertEquals(BASE_PORT_NUMBER+3, testee.getPortNumberForInstallation(MY_INSTALLATION));

+	}

+	

+	public void testWhenPropsIsNull_RuntimeExceptionThrows() {		

+		try {

+			new DeeplinkPortAssigner(null, true);

+			fail();

+		} catch (IllegalArgumentException e) {

+			// pass();

+		}		

+	}

+	

+	public void testPortForInstallationIsGenereatedAndStored_whenRequestedInstallationDoesNotExist_andAnExistingInstallationHasBasePortNumber() {

+

+		DeeplinkPortAssigner testee = new DeeplinkPortAssigner(props, true);

+		assertEquals(BASE_PORT_NUMBER, testee.getPortNumberForInstallation("someInstallation"));

+		assertEquals(BASE_PORT_NUMBER+1, testee.getPortNumberForInstallation(MY_INSTALLATION));		

+	}

+	

+	public void testPortForInstallationIsGeneratedAndStored_whenInstallationDoesNotExistInProps() {					

+		DeeplinkPortAssigner testee = new DeeplinkPortAssigner(props, true); 		

+		assertEquals(BASE_PORT_NUMBER, testee.getPortNumberForInstallation(MY_INSTALLATION));		

+		assertEquals(Integer.toString(BASE_PORT_NUMBER), props.getInstallationPort(MY_INSTALLATION));		

+	}

+	

+	public void testPortForInstallationIsGeneratedAndStored_whenInstallationDoesNotExistInPropsAndPropsDoesNotHaveBasePortNumber() {					

+		props = new DeepLinkProperties();

+		DeeplinkPortAssigner testee = new DeeplinkPortAssigner(props, true); 		

+		assertEquals(DeepLinkProperties.DEFAULT_BASE_PORT_NUMBER, testee.getPortNumberForInstallation(MY_INSTALLATION));		

+		assertEquals(Integer.toString(DeepLinkProperties.DEFAULT_BASE_PORT_NUMBER), props.getInstallationPort(MY_INSTALLATION));		

+	}		

+	

+	public void testPortForInstallationReadFromProperties_whenInstallationAlreadyExistsInProps() {		

+		int expectedPortNumber = 8888;

+		props.setInstallationPort(MY_INSTALLATION, expectedPortNumber);

+		

+		DeeplinkPortAssigner testee = new DeeplinkPortAssigner(props, true); 

+		

+		assertEquals(expectedPortNumber, testee.getPortNumberForInstallation(MY_INSTALLATION));		

+	}

+	

+	

+

+}

diff --git a/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/internal/ParsedDeepLinkURLTest.java b/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/internal/ParsedDeepLinkURLTest.java
new file mode 100644
index 0000000..7c80c2b
--- /dev/null
+++ b/tests/org.eclipse.e4.core.deeplink.test/src/org/eclipse/e4/core/deeplink/internal/ParsedDeepLinkURLTest.java
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * 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.core.deeplink.internal;

+

+import org.eclipse.e4.core.deeplink.DeepLinkURLException;
+import org.eclipse.e4.core.deeplink.internal.ParsedDeepLinkURL;
+

+

+import junit.framework.TestCase;

+

+public class ParsedDeepLinkURLTest extends TestCase {

+	public void testCtor_InvalidProtocol_failure() throws Exception {

+		try {

+			new ParsedDeepLinkURL("foo://bar/baz");

+			fail("Expected exception on invalid URL");

+		} catch (DeepLinkURLException e) {

+			//success

+		}

+	}

+

+	public void testCtor_protocolPresent_success() throws Exception {

+		try {

+			new ParsedDeepLinkURL("deeplink://bar/baz");

+			//success

+		} catch (DeepLinkURLException e) {

+			fail("Expected exception on invalid URL");

+		}

+	}

+

+	public void testCtor_InvalidInstallation_failure() throws Exception {

+		try {

+			new ParsedDeepLinkURL("deeplink://");

+			fail("Expected exception on invalid URL");

+		} catch (DeepLinkURLException e) {

+			//success

+		}

+	}

+

+	public void testCtor_InstallationPresent_success() throws Exception {

+		try {

+			new ParsedDeepLinkURL("deeplink://bar/baz");

+			//success

+		} catch (DeepLinkURLException e) {

+			fail("Expected exception on invalid URL");

+		}

+	}

+	

+	public void testCtor_InstallationIsJustSlashes_failure() throws Exception {

+		try {

+			new ParsedDeepLinkURL("deeplink:///");

+			fail("Expected exception on invalid URL");

+		} catch (DeepLinkURLException e) {

+			//success

+		}

+	}

+	

+	public void testCtor_setsInstallation() throws Exception {

+		final String INSTALLATION="installation";

+		ParsedDeepLinkURL testee = new ParsedDeepLinkURL("deeplink://" + INSTALLATION);

+		assertEquals(INSTALLATION, testee.installation);

+	}

+	

+	public void testCtor_installationDoesNotIncludeRestOfURL() throws Exception {

+		final String INSTALLATION="installation";

+		final String REST="/restOfURL";

+		ParsedDeepLinkURL testee = new ParsedDeepLinkURL("deeplink://" + INSTALLATION + REST);

+		assertEquals(INSTALLATION, testee.installation);

+	}

+	

+	public void testCtor_RestOfURLIsEmpty() throws Exception {

+		final String INSTALLATION="installation";

+		final String REST="";

+		ParsedDeepLinkURL testee = new ParsedDeepLinkURL("deeplink://" + INSTALLATION + REST);

+		assertEquals(REST, testee.restOfURL);

+	}

+

+	public void testCtor_RestOfURLIsSlash() throws Exception {

+		final String INSTALLATION="installation";

+		final String REST="/";

+		ParsedDeepLinkURL testee = new ParsedDeepLinkURL("deeplink://" + INSTALLATION + REST);

+		assertEquals(REST, testee.restOfURL);

+	}

+

+	public void testCtor_RestOfURLIsNotEmpty() throws Exception {

+		final String INSTALLATION="installation";

+		final String REST="/restOfURL";

+		ParsedDeepLinkURL testee = new ParsedDeepLinkURL("deeplink://" + INSTALLATION + REST);

+		assertEquals(REST, testee.restOfURL);

+	}

+}