diff --git a/scripts/TouchinBuild/Core/DependencyResolver/DependencyResolver.py b/scripts/TouchinBuild/Core/DependencyResolver/DependencyResolver.py new file mode 100644 index 0000000..42dfbc2 --- /dev/null +++ b/scripts/TouchinBuild/Core/DependencyResolver/DependencyResolver.py @@ -0,0 +1,38 @@ +class DependencyResolver: + def __init__(self): + pass + + def resolve(self, unresolved): + assert unresolved is not None + resolved = [] + + while len(unresolved) > 0: + node = unresolved[0] + self.resolveNode(node, resolved, unresolved, []) + + return resolved + + def resolveNode(self, node, resolved, unresolved, seen): + assert node is not None + assert resolved is not None + assert seen is not None + + seen.append(node) + + for dependency in node.edges: + if dependency not in resolved: + self.guardNotCircularReference(node, dependency, seen) + self.resolveNode(dependency, resolved, unresolved, seen) + + resolved.append(node) + unresolved.remove(node) + seen.remove(node) + + def guardNotCircularReference(self, start, dependency, seen): + assert start is not None + assert dependency is not None + assert seen is not None + + if dependency in seen: + raise Exception('Circular reference detected: {0} -> {1}'.format(start.name, dependency.name)) + diff --git a/scripts/TouchinBuild/Core/DependencyResolver/Node.py b/scripts/TouchinBuild/Core/DependencyResolver/Node.py new file mode 100644 index 0000000..06e1726 --- /dev/null +++ b/scripts/TouchinBuild/Core/DependencyResolver/Node.py @@ -0,0 +1,12 @@ +class Node: + def __init__(self, name): + assert name is not None + + self.name = name + self.edges = [] + + def addEdge(self, node): + assert node is not None + assert node not in self.edges + + self.edges.append(node) \ No newline at end of file diff --git a/scripts/TouchinBuild/Core/DependencyResolver/__init__.py b/scripts/TouchinBuild/Core/DependencyResolver/__init__.py new file mode 100644 index 0000000..cc31abc --- /dev/null +++ b/scripts/TouchinBuild/Core/DependencyResolver/__init__.py @@ -0,0 +1 @@ +__author__ = 'rzaitov' diff --git a/scripts/TouchinBuild/Tests/UnitTests/DependencyResolver/__init__.py b/scripts/TouchinBuild/Tests/UnitTests/DependencyResolver/__init__.py new file mode 100644 index 0000000..cc31abc --- /dev/null +++ b/scripts/TouchinBuild/Tests/UnitTests/DependencyResolver/__init__.py @@ -0,0 +1 @@ +__author__ = 'rzaitov' diff --git a/scripts/TouchinBuild/Tests/UnitTests/DependencyResolver/test_resolver.py b/scripts/TouchinBuild/Tests/UnitTests/DependencyResolver/test_resolver.py new file mode 100644 index 0000000..23834c6 --- /dev/null +++ b/scripts/TouchinBuild/Tests/UnitTests/DependencyResolver/test_resolver.py @@ -0,0 +1,31 @@ +import unittest +from Core.DependencyResolver.DependencyResolver import DependencyResolver +from Core.DependencyResolver.Node import Node + + +class TestDependencyResolver(unittest.TestCase): + def setUp(self): + self.resolver = DependencyResolver() + + def test_OneConnectedness(self): + node1 = Node('node1') + node2 = Node('node2') + + node3 = Node('node3') + node3.addEdge(node1) + node3.addEdge(node2) + + node4 = Node('node4') + node4.addEdge(node3) + node4.addEdge(node1) + + unresolved = [node4, node3, node2, node1] + resolved = self.resolver.resolve(unresolved) + + self.assertEqual(4, len(resolved)) + + self.assertEqual(node1, resolved[0]) + self.assertEqual(node2, resolved[1]) + self.assertEqual(node3, resolved[2]) + self.assertEqual(node4, resolved[3]) +