add unit test for multiroute. fix long standing bugs with routing uncovered by said unit test.

This commit is contained in:
Jack Kanarish
2018-01-04 16:06:54 -05:00
parent 3a2f3b7526
commit 0a0cf3f720
2 changed files with 110 additions and 3 deletions

View File

@@ -26,6 +26,52 @@ namespace ICD.Common.Utils.Tests
}
}
private static IEnumerable<int> WideGraph(int node)
{
switch (node)
{
case 1:
yield return 2;
yield return 3;
yield return 4;
yield return 5;
yield return 6;
break;
case 2:
yield return 21;
yield return 22;
break;
case 3:
yield return 1;
yield return 31;
yield return 32;
break;
case 4:
yield return 41;
yield return 42;
break;
case 5:
yield return 51;
yield return 52;
break;
case 6:
yield return 61;
yield return 62;
break;
case 21:
yield return 62;
break;
case 41:
yield return 43;
break;
case 42:
yield return 43;
break;
default:
yield break;
}
}
[Test]
public void BreadthFirstSearchTest()
{
@@ -73,5 +119,61 @@ namespace ICD.Common.Utils.Tests
Assert.AreEqual(1, path.Length);
Assert.AreEqual(1, path[0]);
}
[Test]
public void BreadthFirstSearchManyDestinationsTest()
{
Assert.Throws<ArgumentNullException>(() => RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 1 }, null));
Assert.Throws<ArgumentNullException>(() => RecursionUtils.BreadthFirstSearchManyDestinations(1, null, Graph));
Assert.IsEmpty(RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 5 }, Graph));
Dictionary<int, IEnumerable<int>> paths = RecursionUtils.BreadthFirstSearchManyDestinations(1, new[] { 21, 22, 31, 43, 62 }, WideGraph);
//Make sure all paths were found
Assert.IsTrue(paths.Keys.Contains(21));
Assert.IsTrue(paths.Keys.Contains(22));
Assert.IsTrue(paths.Keys.Contains(31));
Assert.IsTrue(paths.Keys.Contains(43));
Assert.IsTrue(paths.Keys.Contains(62));
//Make sure the shortest paths are taken
Assert.AreEqual(3, paths[21].Count());
Assert.AreEqual(3, paths[22].Count());
Assert.AreEqual(3, paths[31].Count()); // infinite loop exists between 1 and 3
Assert.AreEqual(4, paths[43].Count()); // 43 has two parents of equal distance, 41 and 42
Assert.AreEqual(3, paths[62].Count()); // two paths exist, one is 3, one is 4
// make sure that destinations which were not asked for were not returned
Assert.IsFalse(paths.Keys.Contains(1));
Assert.IsFalse(paths.Keys.Contains(2));
Assert.IsFalse(paths.Keys.Contains(3));
Assert.IsFalse(paths.Keys.Contains(32));
//Verify path for destination 21
Assert.AreEqual(1, paths[21].ToArray()[0]);
Assert.AreEqual(2, paths[21].ToArray()[1]);
Assert.AreEqual(21, paths[21].ToArray()[2]);
//Verify path for destination 22
Assert.AreEqual(1, paths[22].ToArray()[0]);
Assert.AreEqual(2, paths[22].ToArray()[1]);
Assert.AreEqual(22, paths[22].ToArray()[2]);
//Verify path for destination 31
Assert.AreEqual(1, paths[31].ToArray()[0]);
Assert.AreEqual(3, paths[31].ToArray()[1]);
Assert.AreEqual(31, paths[31].ToArray()[2]);
//Verify path for destination 43
Assert.AreEqual(1, paths[43].ToArray()[0]);
Assert.AreEqual(4, paths[43].ToArray()[1]);
Assert.AreEqual(41, paths[43].ToArray()[2]); // when multiple parents exist with valid paths back, the first one should be consistently selected
Assert.AreEqual(43, paths[43].ToArray()[3]);
//Verify path for destination 62
Assert.AreEqual(1, paths[62].ToArray()[0]);
Assert.AreEqual(6, paths[62].ToArray()[1]);
Assert.AreEqual(62, paths[62].ToArray()[2]);
}
}
}

View File

@@ -92,7 +92,7 @@ namespace ICD.Common.Utils
// Found a path to the destination
if (comparer.Equals(node, destination))
return GetPath(destination, nodeParents).Reverse();
return GetPath(destination, root, nodeParents, comparer).Reverse();
}
}
@@ -166,7 +166,7 @@ namespace ICD.Common.Utils
destinationsToBeProcessed.Where(destination => comparer.Equals(closureNode, destination)))
{
destinationsProcessed.Add(destination);
pathsToReturn.Add(destination, GetPath(destination, nodeParents).Reverse());
pathsToReturn.Add(destination, GetPath(destination, root, nodeParents, comparer).Reverse().ToArray());
}
foreach (T destination in destinationsProcessed)
@@ -187,15 +187,20 @@ namespace ICD.Common.Utils
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="start"></param>
/// /// <param name="end"></param>
/// <param name="nodeParents"></param>
/// <returns></returns>
private static IEnumerable<T> GetPath<T>(T start, IDictionary<T, T> nodeParents)
private static IEnumerable<T> GetPath<T>(T start, T end, IDictionary<T, T> nodeParents, IEqualityComparer<T> comparer)
{
IcdHashSet<T> visited = new IcdHashSet<T>();
while (true)
{
yield return start;
if (comparer.Equals(start, end))
break;
visited.Add(start);
T next;