Bug 508741 - Some ThemeAPITest#testThemeExtension* tests fail on some
platforms

TopologicalSort didn't preserved definition order for the extensions
with same id from same plugin.xml, because it used a custom, *random*
order of iteration offered by HashMap. Quote: "This class makes no
guarantees as to the order of the map; in particular, it does not
guarantee that the order will remain constant over time."

Depending on the order of map insertion and on the custom HashMap hash
algorithm implementation, the TopologicalSort produced different results
for same inputs on different environments, so that equal elements order
was changed by the sort algorithm and the result order for equal
elements was more or less random in different environments. This showed
up in the unstable test behavior of the ThemeAPITest, which relied on
the right (definition) order of contributions to the
"org.eclipse.ui.themes" extension point.

By using "Linked" versions of the Map and Set we make the code in
TopologicalSort stable across different environments because we preserve
the sort order for equal elements and so preserve the definition order
for contributions with equal keys coming from same plugin.xml.

See also
http://javaclipse.blogspot.de/2016/03/stable-tests-and-transition-to-java-8.html

Change-Id: Iabba91de64a8bb96da4589ff74cda0506e4fd886
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/TopologicalSort.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/TopologicalSort.java
index 9b50cc5..a932b05 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/TopologicalSort.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/TopologicalSort.java
@@ -16,8 +16,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -66,11 +66,11 @@
  *            ID
  */
 public abstract class TopologicalSort<T, ID> {
-	private final Map<ID, Collection<T>> mappedObjects = new HashMap<>();
+	private final Map<ID, Collection<T>> mappedObjects = new LinkedHashMap<>();
 	// Captures the bundles that are listed as requirements for a particular bundle.
-	private final Map<ID, Collection<ID>> requires = new HashMap<>();
+	private final Map<ID, Collection<ID>> requires = new LinkedHashMap<>();
 	// Captures the bundles that list a particular bundle as a requirement
-	private final Map<ID, Collection<ID>> depends = new HashMap<>();
+	private final Map<ID, Collection<ID>> depends = new LinkedHashMap<>();
 
 	/**
 	 * Return the identifier for the given object. The implementation properly tracks where multiple
@@ -185,7 +185,7 @@
 			ID id = getId(o);
 			Collection<T> exts = mappedObjects.get(id);
 			if (exts == null) {
-				mappedObjects.put(id, exts = new HashSet<>());
+				mappedObjects.put(id, exts = new LinkedHashSet<>());
 			}
 			exts.add(o);
 		}
@@ -196,8 +196,8 @@
 		requires.clear();
 		depends.clear();
 		for (ID id : mappedObjects.keySet()) {
-			requires.put(id, new HashSet<ID>());
-			depends.put(id, new HashSet<ID>());
+			requires.put(id, new LinkedHashSet<ID>());
+			depends.put(id, new LinkedHashSet<ID>());
 		}
 
 		// now populate the dependency graph