From ef99847441d0ee6ea4fa55df75d551eaafcd0917 Mon Sep 17 00:00:00 2001 From: esynr3z Date: Tue, 23 Jan 2024 08:10:15 +0300 Subject: [PATCH] feat: add tests for graph module --- pip_hdl/graph.py | 6 ++-- pip_hdl/metainfo.py | 2 +- tests/test_dummy.py | 6 ---- tests/test_graph.py | 84 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 10 deletions(-) delete mode 100644 tests/test_dummy.py create mode 100644 tests/test_graph.py diff --git a/pip_hdl/graph.py b/pip_hdl/graph.py index 5978f5b..71a48f1 100644 --- a/pip_hdl/graph.py +++ b/pip_hdl/graph.py @@ -7,7 +7,7 @@ from collections import deque from pathlib import Path -from typing import Any, Deque, Iterable, Iterator, List, Set +from typing import Any, Deque, Iterable, Iterator, List, Sequence, Set from .metainfo import PackageMetaInfo @@ -36,7 +36,7 @@ def add_upstreams(self, nodes: Iterable[Node]) -> None: class DependencyGraph: """Directed Acyclic Graph to operate with package dependecies conveniently.""" - def __init__(self, packages: List[PackageMetaInfo]) -> None: + def __init__(self, packages: Sequence[PackageMetaInfo]) -> None: """Create dependecy DAG from provided packages.""" # create nodes self.nodes = {n.id: n for n in self._packages_to_nodes(packages)} @@ -69,7 +69,7 @@ def _traverse_from(self, nodes: Iterable[Node]) -> Iterator[Node]: if node in visited: continue - if set(node.downstreams).intersection(set(planned)): + if set(node.upstreams).intersection(set(planned)): # dependencies are not resolved yet, plan the job again planned.append(node) continue diff --git a/pip_hdl/metainfo.py b/pip_hdl/metainfo.py index bdb336c..1991655 100644 --- a/pip_hdl/metainfo.py +++ b/pip_hdl/metainfo.py @@ -22,7 +22,7 @@ class PackageDependency(NamedTuple): """Descriptor for a HDL package dependency.""" spec: str # packaging.requirements.Requirement friendly specification - module: ModuleType + module: Optional[ModuleType] metainfo: PackageMetaInfo diff --git a/tests/test_dummy.py b/tests/test_dummy.py deleted file mode 100644 index 86b8a15..0000000 --- a/tests/test_dummy.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Dummy test.""" - - -def test_dummy(): - """Dummy test.""" - assert True diff --git a/tests/test_graph.py b/tests/test_graph.py new file mode 100644 index 0000000..fd8a7f3 --- /dev/null +++ b/tests/test_graph.py @@ -0,0 +1,84 @@ +"""Tests of `graph module.""" +from typing import List, Sequence + +from pip_hdl.graph import DependencyGraph +from pip_hdl.metainfo import PackageDependency, PackageMetaInfo + + +class MockPackageMetaInfo(PackageMetaInfo): + """Simplified version of class to mock dependencies resolution.""" + + def __init__(self, name: str, dependencies: Sequence[PackageMetaInfo]) -> None: + """Init object.""" + super().__init__(name) + self._dependencies_meta = dependencies + + @property + def dependencies(self) -> List[PackageDependency]: + """Simplified dependencies.""" + return [PackageDependency(spec="", module=None, metainfo=d) for d in self._dependencies_meta] + + +def test_empty(): + """Test iterating empty graph.""" + graph = DependencyGraph([]) + assert list(graph) == [] + + +def test_single_node(): + """Test iterating graph from a single package.""" + package = MockPackageMetaInfo("foo", []) + graph = DependencyGraph([package]) + assert [node.id for node in graph] == [package.name] + + +def test_multi_node(): + """Test iterating graph from multiple packages.""" + packages = [MockPackageMetaInfo("foo", []), MockPackageMetaInfo("bar", []), MockPackageMetaInfo("baz", [])] + graph = DependencyGraph(packages) + assert set(node.id for node in graph) == set(p.name for p in packages) + + +def test_chain(): + """Test iterating graph in form of chain.""" + foo_pkg = MockPackageMetaInfo("foo", []) + bar_pkg = MockPackageMetaInfo("bar", [foo_pkg]) + baz_pkg = MockPackageMetaInfo("baz", [bar_pkg]) + packages = [bar_pkg, foo_pkg, baz_pkg] + graph = DependencyGraph(packages) + assert list(node.id for node in graph) == ["foo", "bar", "baz"] + + +def test_triangle(): + """Test iterating graph in form of triangle.""" + foo_pkg = MockPackageMetaInfo("foo", []) + bar_pkg = MockPackageMetaInfo("bar", [foo_pkg]) + baz_pkg = MockPackageMetaInfo("baz", [bar_pkg, foo_pkg]) + packages = [bar_pkg, foo_pkg, baz_pkg] + graph = DependencyGraph(packages) + assert list(node.id for node in graph) == ["foo", "bar", "baz"] + + +def test_diamond(): + """Test iterating graph in form of diamond.""" + foo_pkg = MockPackageMetaInfo("foo", []) + bar_pkg = MockPackageMetaInfo("bar", [foo_pkg]) + baz_pkg = MockPackageMetaInfo("baz", [bar_pkg]) + ham_pkg = MockPackageMetaInfo("ham", [baz_pkg]) + packages = [ham_pkg, bar_pkg, foo_pkg, baz_pkg] + graph = DependencyGraph(packages) + assert list(node.id for node in graph) == ["foo", "bar", "baz", "ham"] + + +def test_tree(): + """Test iterating graph in form of tree.""" + a1_pkg = MockPackageMetaInfo("a1", []) + a2_pkg = MockPackageMetaInfo("a2", []) + b1_pkg = MockPackageMetaInfo("b1", []) + b2_pkg = MockPackageMetaInfo("b2", []) + c1_pkg = MockPackageMetaInfo("c1", [a1_pkg, a2_pkg]) + c2_pkg = MockPackageMetaInfo("c2", [b1_pkg, b2_pkg]) + d_pkg = MockPackageMetaInfo("d", [c1_pkg, c2_pkg]) + packages = [a1_pkg, a2_pkg, b1_pkg, b2_pkg, c1_pkg, c2_pkg, d_pkg] + graph = DependencyGraph(packages) + assert list(node.id for node in graph) == ["a1", "a2", "b1", "b2", "c1", "c2", "d"]