blob: 80e9327fbf60c564c854d0109da6165adb38edd8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.openide.util;
import java.io.*;
import java.util.*;
import org.netbeans.junit.*;
import junit.textui.TestRunner;
/** Test BaseUtilities.topologicalSort.
* @author Jesse Glick
*/
public class UtilitiesTopologicalSortTest extends NbTestCase {
public UtilitiesTopologicalSortTest(String name) {
super(name);
}
public static void main(String[] args) {
TestRunner.run(new NbTestSuite(UtilitiesTopologicalSortTest.class));
}
/**
* @see "#27286"
*/
public void testTopologicalSort() throws Exception {
Collection c = Arrays.asList(new String[] {"a", "b", "c", "d", "e", "f"});
Map m = new HashMap();
m.put("f", Collections.singletonList("a"));
List l = BaseUtilities.topologicalSort(c, m);
assertNotNull(l);
assertTrue(l.indexOf("f") < l.indexOf("a"));
m.put("e", Collections.singletonList("b"));
l = BaseUtilities.topologicalSort(c, m);
assertNotNull(l);
assertTrue(l.indexOf("f") < l.indexOf("a"));
assertTrue(l.indexOf("e") < l.indexOf("b"));
m.put("b", Collections.singletonList("a"));
l = BaseUtilities.topologicalSort(c, m);
assertNotNull(l);
assertTrue(l.indexOf("f") < l.indexOf("a"));
assertTrue(l.indexOf("e") < l.indexOf("b"));
assertTrue(l.indexOf("b") < l.indexOf("a"));
// Test that it is modifiable:
l.add("foo");
Collections.reverse(l);
// Test cycles:
m.put("a", Collections.singletonList("e"));
try {
l = BaseUtilities.topologicalSort(c, m);
fail ("Should throw an exception");
} catch (TopologicalSortException ex) {
}
}
public void testTopologicalSortError() throws Exception {
Collection c = Arrays.asList(new String[] {"first", "a", "b", "c", "d", "e", "f", "last"});
Map m = new HashMap();
// to make sure that not whole visited graph will be in the cycle
m.put("first", Collections.singletonList ("f"));
m.put("last", Collections.singletonList ("f"));
m.put("f", Collections.singletonList("a"));
BaseUtilities.topologicalSort (c, m); // does not throw an error
m.put("e", Collections.singletonList("b"));
BaseUtilities.topologicalSort (c, m); // does not throw an error
m.put("b", Collections.singletonList("a"));
BaseUtilities.topologicalSort (c, m); // does not throw an error
m.put("a", Collections.singletonList("e"));
try {
BaseUtilities.topologicalSort (c, m);
fail ("Should throw an error");
} catch (TopologicalSortException ex) {
Set[] sets = ex.topologicalSets();
assertEquals ("There is one cycle of size 3, all other objects are sortable", 6, sets.length);
Set cycle = null;
for (int i = 0; i < sets.length; i++) {
if (sets[i].size () > 1) {
assertNull ("There is just one unsortable component", cycle);
cycle = sets[i];
} else {
assertEquals ("Size is 1", 1, sets[i].size ());
}
}
assertTrue ("a is there", cycle.contains ("a"));
assertTrue ("b is there", cycle.contains ("b"));
assertTrue ("e is there", cycle.contains ("e"));
assertEquals ("Three vertexes are in the cycle", 3, cycle.size ());
assertBefore ("first", "f", sets);
assertBefore ("last", "f", sets);
assertBefore ("f", "a", sets);
assertBefore ("f", "b", sets);
assertBefore ("f", "e", sets);
List partial = ex.partialSort ();
assertEquals ("Has the same size as the original", c.size (), partial.size ());
assertBefore ("first", "f", partial);
assertBefore ("last", "f", partial);
assertBefore ("f", "a", partial);
assertBefore ("f", "b", partial);
assertBefore ("f", "e", partial);
}
}
public void testMoreCycles () throws Exception {
Collection c = Arrays.asList(new String[] {"first", "a", "b", "c", "d", "e", "f", "last"});
Map m = new HashMap();
// to make sure that not whole visited graph will be in the cycle
m.put ("a", Collections.singletonList ("a")); // self cycle
// cycle 2
m.put ("b", Collections.singletonList ("c"));
m.put ("c", Collections.singletonList ("b"));
// cycle 3
m.put ("d", Collections.singletonList ("e"));
m.put ("e", Collections.singletonList ("f"));
m.put ("f", Collections.singletonList ("d"));
Collection sizes = new ArrayList ();
try {
BaseUtilities.topologicalSort (c, m);
fail ("Should throw an error");
} catch (TopologicalSortException ex) {
Set[] sets = ex.topologicalSets();
for (int i = 0; i < sets.length; i++) {
sizes.add (new Integer (sets[i].size ()));
}
assertEquals ("There were three cycles plus first+last", 5, sizes.size ());
assertTrue ("One of size 1", sizes.contains (new Integer (1)));
assertTrue ("One of size 2", sizes.contains (new Integer (2)));
assertTrue ("One of size 3", sizes.contains (new Integer (3)));
sets = ex.unsortableSets();
assertEquals ("Three cycles", 3, sets.length);
}
}
public void testDetectSelfCycle () throws Exception {
Collection c = Arrays.asList(new String[] {"a", "b" });
Map m = new HashMap();
m.put ("a", Arrays.asList (new String[] { "a" }));
m.put ("b", Arrays.asList (new String[] { "a" }));
try {
BaseUtilities.topologicalSort (c, m);
fail ("Definitively there is a cycle");
} catch (TopologicalSortException ex) {
Set[] sets = ex.unsortableSets ();
assertEquals ("One cycle", 1, sets.length);
assertEquals ("Contains one item", 1, sets[0].size ());
assertTrue ("Contains a", sets[0].contains ("a"));
}
}
public void testFindLongestCycle () throws Exception {
Collection c = Arrays.asList(new String[] {"a", "b", "c", "d", "e", "f" });
Map m = new HashMap();
// to make sure that not whole visited graph will be in the cycle
m.put ("a", Arrays.asList (new String[] { "b", "c" }));
m.put ("b", Arrays.asList (new String[] { "a", "d" }));
m.put ("c", Arrays.asList (new String[] { "a", "d" }));
m.put ("d", Arrays.asList (new String[] { "b", "c", "e" }));
m.put ("f", Arrays.asList (new String[] { "a" }));
try {
BaseUtilities.topologicalSort (c, m);
fail ("Definitively there is a cycle");
} catch (TopologicalSortException ex) {
Set[] sets = ex.topologicalSets();
assertEquals ("There is one cycle and e+f", 3, sets.length);
assertBefore ("f", "a", sets);
assertBefore ("f", "b", sets);
assertBefore ("f", "c", sets);
assertBefore ("f", "d", sets);
assertBefore ("f", "e", sets);
assertBefore ("a", "e", sets);
assertBefore ("b", "e", sets);
assertBefore ("c", "e", sets);
assertBefore ("d", "e", sets);
assertEquals ("set of f", 1, sets[0].size ());
assertEquals ("set of a,b,c,d", 4, sets[1].size ());
assertEquals ("set of e", 1, sets[2].size ());
}
}
public void testStability() throws Exception {
Collection c = Arrays.asList(new String[] {"a", "b", "c", "d", "e", "f"});
assertEquals(c, BaseUtilities.topologicalSort(c, Collections.EMPTY_MAP));
Map m = new HashMap();
m.put("e", Collections.singletonList("d"));
List l = BaseUtilities.topologicalSort(c, m);
assertNotNull(l);
assertEquals(Arrays.asList(new String[] {"a", "b", "c"}), l.subList(0, 3));
m = new HashMap();
m.put("c", Collections.singletonList("a"));
l = BaseUtilities.topologicalSort(c, m);
assertNotNull(l);
assertEquals(Arrays.asList(new String[] {"d", "e", "f"}), l.subList(3, 6));
m = new HashMap();
m.put("a", Collections.singletonList("f"));
assertEquals(c, BaseUtilities.topologicalSort(c, m));
m.put("a", Collections.singletonList("b"));
assertEquals(c, BaseUtilities.topologicalSort(c, m));
m.put("b", Collections.singletonList("f"));
assertEquals(c, BaseUtilities.topologicalSort(c, m));
m.put("c", Collections.singletonList("e"));
assertEquals(c, BaseUtilities.topologicalSort(c, m));
m.put("a", Collections.singletonList("e"));
assertEquals(c, BaseUtilities.topologicalSort(c, m));
/* Does not work - oh well:
c = Arrays.asList(new String[] {"a", "b", "c", "d", "e", "x", "y"});
m = new HashMap();
m.put("c", Arrays.asList(new String[] {"x", "y"}));
m.put("x", Collections.singletonList("d"));
m.put("y", Collections.singletonList("d"));
System.err.println("-----");
l = BaseUtilities.topologicalSort(c, m);
assertNotNull(l);
System.err.println(l);
assertEquals(Arrays.asList(new String[] {"a", "b", "c"}), l.subList(0, 3));
assertEquals(Arrays.asList(new String[] {"d", "e"}), l.subList(5, 7));
*/
}
public void testTopologicalSortCompile() throws Exception {
Collection<String> c = new ArrayList<String>();
Map<Object, Collection<String>> edges = new HashMap<Object,Collection<String>>();
List<String> result = BaseUtilities.topologicalSort(c, edges);
}
public void testTopologicalSortCompile2() throws Exception {
Collection<String> c = new ArrayList<String>();
Map<Object, List<String>> edges = new HashMap<Object,List<String>>();
List<String> result = BaseUtilities.topologicalSort(c, edges);
}
public void testTopologicalSortCompile3() throws Exception {
Collection<Number> c = new ArrayList<Number>();
Map<Object, List<Integer>> edges = new HashMap<Object,List<Integer>>();
List<Number> result = BaseUtilities.topologicalSort(c, edges);
}
public void testTopologicalSortIssue101820() throws Exception {
Object a = "a";
Object b = "b";
Map<Object, Collection<Object>> deps = new HashMap<Object, Collection<Object>>();
deps.put(a, Arrays.asList(b));
deps.put(b, Arrays.asList());
assertEquals(Arrays.asList(a), BaseUtilities.topologicalSort(Arrays.asList(a), deps));
}
public void testErrorReporting () throws Exception {
Collection c = Arrays.asList(new String[] {"a", "b", "c", "d", "e", "f"});
Map m = new HashMap ();
m.put ("a", Arrays.asList (new String[] { "a" }));
m.put ("b", Arrays.asList (new String[] { "c" }));
m.put ("c", Arrays.asList (new String[] { "b" }));
try {
BaseUtilities.topologicalSort(c, m);
fail ("Unsortable");
} catch (TopologicalSortException ex) {
StringWriter w = new StringWriter ();
ex.printStackTrace (new PrintWriter (w, true));
ByteArrayOutputStream s = new ByteArrayOutputStream ();
ex.printStackTrace (new java.io.PrintStream (s, true));
byte[] warr = w.toString().getBytes("utf-8");
byte[] sarr = s.toByteArray();
assertTrue ("Both messages should be the same", Arrays.equals(warr, sarr));
{
String msg = w.toString();
int cnt = 0;
int indx = -1;
for (;;) {
indx = msg.indexOf("Conflict #", indx + 1);
if (indx == -1) break;
cnt++;
}
assertEquals(
"There is the same number of lines with " +
"'Conflict #' as unsortable sets",
cnt, ex.unsortableSets().length
);
}
{
String msg = ex.getMessage();
int cnt = 0;
int indx = -1;
for (;;) {
indx = msg.indexOf("Conflict #", indx + 1);
if (indx == -1) break;
cnt++;
}
assertEquals(
"There is the same number of lines with " +
"'Conflict #' as unsortable sets",
cnt, ex.unsortableSets().length
);
}
}
}
private static void assertBefore (String first, String second, Collection c) {
assertBefore (first, second, c, false);
}
private static void assertBefore (String first, String second, Set[] sets) {
assertBefore (first, second, Arrays.asList (sets), true);
}
private static void assertBefore (String first, String second, Collection c, boolean useSets) {
Iterator it = c.iterator();
boolean wasFirst = false;
boolean wasSecond = false;
while (it.hasNext ()) {
Object obj = it.next ();
if (useSets ? ((Set)obj).contains (second) : obj == second) {
assertTrue ("[" + second + "] found before [" + first + "] in " + c, wasFirst);
wasSecond = true;
}
if (useSets ? ((Set)obj).contains (first) : obj == first) {
wasFirst = true;
}
}
assertTrue ("[" + first + "] not found", wasFirst);
assertTrue ("[" + second + "] not found", wasSecond);
}
}