build.tests.unit.graph.test_graph   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 222
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 152
dl 0
loc 222
ccs 125
cts 125
cp 1
rs 10
c 0
b 0
f 0
wmc 22

16 Methods

Rating   Name   Duplication   Size   Complexity  
A TestGraph.test_update_link_unsupported_metadata() 0 12 1
A TestGraph.test_shortest_paths() 0 10 1
A TestGraph.test_update_link_metadata() 0 15 1
A TestGraph.test_update_links() 0 5 1
A TestGraph.test_clear() 0 5 1
A TestGraph.test_update_nodes() 0 11 1
A TestGraph.setup_method() 0 5 1
A TestGraph.test_update_topology_links() 0 6 1
A TestGraph.test_constrained_k_shortest_paths() 0 40 2
A TestGraph.test_update_links_not_up() 0 9 2
A TestGraph.test_update_topology_switches() 0 6 1
A TestGraph.test_update_nodes_2() 0 9 3
A TestGraph.test_get_link_metadata() 0 13 1
A TestGraph.test_remove_switch_hops() 0 16 1
A TestGraph.test_update_nodes_not_up() 0 11 3
A TestGraph.setting_update_topology() 0 10 1
1
"""Test Graph methods."""
2 1
import pytest
3
4 1
from unittest.mock import MagicMock, call, patch
5
6 1
from kytos.core.common import EntityStatus
7 1
from napps.kytos.pathfinder.graph import KytosGraph
8
9
# pylint: disable=import-error
10 1
from tests.helpers import (
11
    get_filter_links_fake,
12
    get_topology_mock,
13
    get_topology_with_metadata_mock,
14
)
15
16
# pylint: disable=arguments-differ, protected-access, no-member
17
18
19 1
class TestGraph:
20
    """Tests for the Main class."""
21
22 1
    def setup_method(self):
23
        """Execute steps before each tests."""
24 1
        self.mock_graph = MagicMock()
25 1
        self.kytos_graph = KytosGraph()
26 1
        self.kytos_graph.graph = self.mock_graph
27
28 1
    def test_clear(self):
29
        """Test clear."""
30 1
        self.kytos_graph.clear()
31
32 1
        self.mock_graph.clear.assert_called()
33
34 1
    def setting_update_topology(self, *args):
35
        """Set the primary elements needed to
36
        test the topology update process."""
37 1
        (mock_update_nodes, mock_update_links) = args
38 1
        topology = get_topology_mock()
39 1
        self.kytos_graph.update_topology(topology)
40
41 1
        self.mock_graph.clear.assert_called()
42
43 1
        return mock_update_nodes, mock_update_links, topology
44
45 1
    @patch("napps.kytos.pathfinder.graph.KytosGraph.update_links")
46 1
    @patch("napps.kytos.pathfinder.graph.KytosGraph.update_nodes")
47 1
    def test_update_topology_switches(self, *args):
48
        """Test update topology."""
49 1
        mock_update_nodes, _, topology = self.setting_update_topology(*args)
50 1
        mock_update_nodes.assert_called_with(topology.switches)
51
52 1
    @patch("napps.kytos.pathfinder.graph.KytosGraph.update_links")
53 1
    @patch("napps.kytos.pathfinder.graph.KytosGraph.update_nodes")
54 1
    def test_update_topology_links(self, *args):
55
        """Test update topology."""
56 1
        _, mock_update_links, topology = self.setting_update_topology(*args)
57 1
        mock_update_links.assert_called_with(topology.links)
58
59 1
    def test_update_links(self):
60
        """Test update_links."""
61 1
        topology = get_topology_mock()
62 1
        self.kytos_graph.update_links(topology.links)
63 1
        assert self.mock_graph.add_edge.call_count == len(topology.links)
64
65 1
    def test_update_links_not_up(self):
66
        """Test update_links entity not up."""
67 1
        topology = get_topology_mock()
68 1
        keys_num = 2
69 1
        for key in list(topology.links.keys())[:keys_num]:
70 1
            topology.links[key].status = EntityStatus.DOWN
71
72 1
        self.kytos_graph.update_links(topology.links)
73 1
        assert self.mock_graph.add_edge.call_count == len(topology.links) - keys_num
74
75
    # pylint: disable=consider-using-dict-items
76 1
    def test_update_nodes_not_up(self):
77
        """Test update_nodes entity not up."""
78 1
        topology = get_topology_mock()
79 1
        keys_num = 2
80 1
        for key in list(topology.switches)[:keys_num]:
81 1
            topology.switches[key].status = EntityStatus.DISABLED
82 1
        for key in topology.switches:
83 1
            topology.switches[key].interfaces = {}
84
85 1
        self.kytos_graph.update_nodes(topology.switches)
86 1
        assert self.mock_graph.add_node.call_count == len(topology.switches) - keys_num
87
88 1
    def test_update_nodes(self):
89
        """Test update nodes."""
90 1
        topology = get_topology_mock()
91 1
        self.kytos_graph.update_nodes(topology.switches)
92
93 1
        edge_count = sum(
94
            (len(sw.interfaces.values()) for sw in topology.switches.values())
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable sw does not seem to be defined.
Loading history...
95
        )
96 1
        node_count = len(topology.switches) + edge_count
97 1
        assert self.mock_graph.add_edge.call_count == edge_count
98 1
        assert self.mock_graph.add_node.call_count == node_count
99
100 1
    def test_update_nodes_2(self):
101
        """Test update nodes."""
102
103 1
        effect = MagicMock(side_effect=AttributeError)
104
105 1
        topology = get_topology_mock()
106 1
        with pytest.raises(TypeError):
107 1
            with patch.object(self.mock_graph, "add_node", effect):
108 1
                self.kytos_graph.update_nodes(topology.switches)
109
110 1
    def test_remove_switch_hops(self):
111
        """Test remove switch hops."""
112 1
        circuit = {
113
            "hops": [
114
                "00:00:00:00:00:00:00:01:1",
115
                "00:00:00:00:00:00:00:01",
116
                "00:00:00:00:00:00:00:01:2",
117
            ]
118
        }
119
120 1
        self.kytos_graph._remove_switch_hops(circuit)
121
122 1
        expected_circuit = {
123
            "hops": ["00:00:00:00:00:00:00:01:1", "00:00:00:00:00:00:00:01:2"]
124
        }
125 1
        assert circuit == expected_circuit
126
127 1
    @patch("networkx.shortest_simple_paths", return_value=["any"])
128 1
    def test_shortest_paths(self, mock_shortest_simple_paths):
129
        """Test shortest paths."""
130 1
        source, dest = "00:00:00:00:00:00:00:01:1", "00:00:00:00:00:00:00:02:2"
131 1
        k_shortest_paths = self.kytos_graph.k_shortest_paths(source, dest)
132
133 1
        mock_shortest_simple_paths.assert_called_with(
134
            self.kytos_graph.graph, source, dest, weight=None
135
        )
136 1
        assert k_shortest_paths == ["any"]
137
138 1
    @patch("napps.kytos.pathfinder.graph.graph.combinations", autospec=True)
139 1
    def test_constrained_k_shortest_paths(self, mock_combinations):
140
        """Test shortest constrained paths."""
141 1
        source, dest = "00:00:00:00:00:00:00:01:1", "00:00:00:00:00:00:00:02:2"
142 1
        minimum_hits = 1
143 1
        mandatory_metrics = {"bandwidth": 100}
144 1
        flexible_metrics = {"utilization": 2}
145 1
        mock_combinations.return_value = [(("utilization", 2),)]
146 1
        constrained_k_shortest_paths = [["path1"], ["path2"]]
147
148 1
        self.kytos_graph.graph.edge_subgraph = MagicMock(return_value=None)
149 1
        self.kytos_graph.k_shortest_paths = MagicMock(
150
            return_value=constrained_k_shortest_paths
151
        )
152 1
        self.kytos_graph._filter_links = MagicMock(side_effect=get_filter_links_fake)
153 1
        k_shortest_paths = self.kytos_graph.constrained_k_shortest_paths(
154
            source,
155
            dest,
156
            minimum_hits=minimum_hits,
157
            mandatory_metrics=mandatory_metrics,
158
            flexible_metrics=flexible_metrics,
159
        )
160
161 1
        self.kytos_graph.k_shortest_paths.assert_has_calls(
162
            [
163
                call(
164
                    source,
165
                    dest,
166
                    weight=None,
167
                    k=1,
168
                    graph=None,
169
                )
170
            ]
171
        )
172 1
        self.kytos_graph._filter_links.assert_called()
173 1
        for constrained_path in k_shortest_paths:
174 1
            assert constrained_path["hops"] in constrained_k_shortest_paths
175 1
            assert constrained_path["metrics"] == {
176
                "bandwidth": 100,
177
                "utilization": 2,
178
            }
179
180 1
    def test_get_link_metadata(self):
181
        """Test metadata retrieval."""
182 1
        topology = get_topology_with_metadata_mock()
183 1
        self.kytos_graph.update_nodes(topology.switches)
184 1
        self.kytos_graph.update_links(topology.links)
185 1
        endpoint_a = "S1:1"
186 1
        endpoint_b = "S2:1"
187 1
        metadata = {"reliability": 5, "bandwidth": 100, "delay": 105}
188 1
        self.kytos_graph.get_link_metadata = MagicMock(return_value=metadata)
189
190 1
        result = self.kytos_graph.get_link_metadata(endpoint_a, endpoint_b)
191
192 1
        assert result == metadata
193
194 1
    def test_update_link_metadata(self):
195
        """Test update link metadata."""
196 1
        graph = MagicMock()
197 1
        link = MagicMock()
198 1
        endpoint_a_id = 1
199 1
        endpoint_b_id = 2
200 1
        link.endpoint_a.id = endpoint_a_id
201 1
        link.endpoint_b.id = endpoint_b_id
202 1
        link.metadata = {"reliability": 50}
203 1
        self.kytos_graph.graph = graph
204 1
        self.kytos_graph.update_link_metadata(link)
205 1
        call_res = str(self.kytos_graph.graph._mock_mock_calls)
206 1
        assert "__getitem__(1)" in call_res
207 1
        assert "__getitem__(2)" in call_res
208 1
        assert "__setitem__('reliability', 50)" in call_res
209
210 1
    def test_update_link_unsupported_metadata(self):
211
        """Test update link metadata with an unsupported key."""
212 1
        graph = MagicMock()
213 1
        link = MagicMock()
214 1
        endpoint_a_id = 1
215 1
        endpoint_b_id = 2
216 1
        link.endpoint_a.id = endpoint_a_id
217 1
        link.endpoint_b.id = endpoint_b_id
218 1
        link.metadata.items.return_value = [("random_metric", 50)]
219 1
        self.kytos_graph.graph = graph
220 1
        self.kytos_graph.update_link_metadata(link)
221
        assert self.kytos_graph.graph._mock_mock_calls == []
222