Bug 362692 - Reconciler inconsistent with small sampling
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
index 57b60f4..cb53921 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
@@ -553,21 +553,8 @@
 		for (Iterator<IInstallableUnit> iter = allIUs.iterator(); iter.hasNext();) {
 			final IInstallableUnit iu = iter.next();
 			IInstallableUnit existing = profileIUs.get(iu);
-			// the IU doesn't exist in the profile so we are adding it and need to set properties
-			if (existing == null) {
-				if (QueryUtil.isGroup(iu))
-					request.setInstallableUnitProfileProperty(iu, IProfile.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());
-				// mark all IUs with special property
-				request.setInstallableUnitProfileProperty(iu, PROP_FROM_DROPINS, Boolean.TRUE.toString());
-				request.setInstallableUnitInclusionRules(iu, ProfileInclusionRules.createOptionalInclusionRule(iu));
-				request.setInstallableUnitProfileProperty(iu, IProfile.PROP_PROFILE_LOCKED_IU, Integer.toString(IProfile.LOCK_UNINSTALL));
-
-				// as soon as we find something locally that needs to be installed, then 
-				// everything from the parent's dropins must be installed locally as well.
-				if (!foundIUsToAdd && availableProfileIUs.get(iu) == null) {
-					foundIUsToAdd = true;
-				}
-			} else {
+			// check to see if this IU has moved locations
+			if (existing != null) {
 				// if the IU is already installed in the profile then check to see if it was moved.
 				String one = iu.getProperty(RepositoryListener.FILE_NAME);
 				String two = existing.getProperty(RepositoryListener.FILE_NAME);
@@ -576,8 +563,24 @@
 				// cheat here... since we always set the filename property for bundles in the dropins,
 				// if the existing IU's filename is null then it isn't from the dropins. a better
 				// (and more expensive) way to find this out is to do an IU profile property query.
-				if (one != null && two != null && !one.equals(two))
+				if (one != null && two != null && !one.equals(two)) {
 					toMove.add(iu);
+					break;
+				}
+			}
+			// even though we are adding all IUs below, we need to explicitly set the properties for
+			// them as well. Do that here.
+			if (QueryUtil.isGroup(iu))
+				request.setInstallableUnitProfileProperty(iu, IProfile.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());
+			// mark all IUs with special property
+			request.setInstallableUnitProfileProperty(iu, PROP_FROM_DROPINS, Boolean.TRUE.toString());
+			request.setInstallableUnitInclusionRules(iu, ProfileInclusionRules.createOptionalInclusionRule(iu));
+			request.setInstallableUnitProfileProperty(iu, IProfile.PROP_PROFILE_LOCKED_IU, Integer.toString(IProfile.LOCK_UNINSTALL));
+
+			// as soon as we find something locally that needs to be installed, then 
+			// everything from the parent's dropins must be installed locally as well.
+			if (!foundIUsToAdd && availableProfileIUs.get(iu) == null) {
+				foundIUsToAdd = true;
 			}
 		}
 
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/AbstractReconcilerTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/AbstractReconcilerTest.java
index 07e4e4b..bbc0281 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/AbstractReconcilerTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/AbstractReconcilerTest.java
@@ -369,11 +369,20 @@
 		return false;
 	}
 
+	public void reconcile(String message) {
+		reconcile(message, false);
+	}
+
 	/*
 	 * Run the reconciler to discover changes in the drop-ins folder and update the system state.
 	 */
-	public void reconcile(String message) {
-		runEclipse(message, new String[] {"-application", "org.eclipse.equinox.p2.reconciler.application"});
+	public void reconcile(String message, boolean clean) {
+		List<String> args = new ArrayList<String>();
+		args.add("-application");
+		args.add("org.eclipse.equinox.p2.reconciler.application");
+		if (clean)
+			args.add("-clean");
+		runEclipse(message, args.toArray(new String[args.size()]));
 	}
 
 	/*
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/AllTests.java
index a000a4d..241a335 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/AllTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/AllTests.java
@@ -26,6 +26,7 @@
 		suite.addTest(ConfigurationTests.suite());
 		suite.addTest(FeaturePatchTest.suite());
 		suite.addTest(SharedInstallTests.suite());
+		suite.addTest(Bug362692.suite());
 		return suite;
 	}
 }
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/Bug362692.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/Bug362692.java
new file mode 100644
index 0000000..bface8a
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/reconciler/dropins/Bug362692.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.reconciler.dropins;
+
+import java.io.File;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test for Bug 362692. Inconsistent results from reconciliation when starting
+ * with -clean. Data set listed below. Put the bundles in the drop-ins and start
+ * with -clean and ensure the highest version of the bundles is loaded.
+ * 
+ * B v1, v2
+ * C v1, v2
+ * D v1, v2
+ * Both B and C depend on D [1.0.0, any)
+ */
+public class Bug362692 extends AbstractReconcilerTest {
+
+	public Bug362692(String name) {
+		super(name);
+	}
+
+	public static Test suite() {
+		TestSuite suite = new ReconcilerTestSuite();
+		suite.setName(Bug362692.class.getName());
+		suite.addTest(new Bug362692("testReconcile"));
+		return suite;
+	}
+
+	public void testReconcile() {
+		// assert initial state
+		assertInitialized();
+		assertDoesNotExistInBundlesInfo("0.1", "b");
+		assertDoesNotExistInBundlesInfo("0.2", "c");
+		assertDoesNotExistInBundlesInfo("0.3", "d");
+
+		// add bundle to dropins
+		File plugins = getTestData("2.0", "testData/bug362692/plugins");
+		add("2.1", "dropins", plugins);
+
+		// reconcile + clean
+		reconcile("3.0", true);
+
+		// assert highest versions of bundles are installed
+		assertExistsInBundlesInfo("4.0", "b", "2.0.0", "dropins");
+		assertExistsInBundlesInfo("4.1", "c", "2.0.0", "dropins");
+		assertExistsInBundlesInfo("4.2", "d", "2.0.0", "dropins");
+
+		// reconcile + clean
+		reconcile("6.0", true);
+
+		// assert highest versions of bundles still are installed
+		assertExistsInBundlesInfo("7.0", "b", "2.0.0", "dropins");
+		assertExistsInBundlesInfo("7.1", "c", "2.0.0", "dropins");
+		assertExistsInBundlesInfo("7.2", "d", "2.0.0", "dropins");
+
+		// cleanup
+		remove("99.0", "dropins", "plugins");
+		reconcile("99.1", true);
+		assertDoesNotExistInBundlesInfo("99.2", "b");
+		assertDoesNotExistInBundlesInfo("99.3", "c");
+		assertDoesNotExistInBundlesInfo("99.4", "d");
+	}
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/b_1.0.0.jar b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/b_1.0.0.jar
new file mode 100644
index 0000000..8109bfe
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/b_1.0.0.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/b_2.0.0.jar b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/b_2.0.0.jar
new file mode 100644
index 0000000..b4bbb9b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/b_2.0.0.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/c_1.0.0.jar b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/c_1.0.0.jar
new file mode 100644
index 0000000..12afb93
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/c_1.0.0.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/c_2.0.0.jar b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/c_2.0.0.jar
new file mode 100644
index 0000000..efa19d7
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/c_2.0.0.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/d_1.0.0.jar b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/d_1.0.0.jar
new file mode 100644
index 0000000..a923653
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/d_1.0.0.jar
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/d_2.0.0.jar b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/d_2.0.0.jar
new file mode 100644
index 0000000..7f900db
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/testData/bug362692/plugins/d_2.0.0.jar
Binary files differ