Test Failed
Pull Request — master (#65)
by
unknown
06:49
created

TestGraph.test_constrained_k_shortest_paths()   A

Complexity

Conditions 2

Size

Total Lines 40
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

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