Passed
Push — master ( 12cd8c...fd29a5 )
by Vinicius
02:12 queued 12s
created

TestGraph.test_update_link_unsupported_metadata()   A

Complexity

Conditions 1

Size

Total Lines 12
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nop 1
dl 0
loc 12
rs 9.85
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
    def test_update_nodes_not_up(self):
75
        """Test update_nodes entity not up."""
76
        topology = get_topology_mock()
77
        keys_num = 2
78
        for key in list(topology.switches.keys())[:keys_num]:
79
            topology.switches[key].status = EntityStatus.DISABLED
80
        for key in topology.switches.keys():
81
            topology.switches[key].interfaces = {}
82
83
        self.kytos_graph.update_nodes(topology.switches)
84
        assert self.mock_graph.add_node.call_count == len(topology.switches) - keys_num
85
86
    def test_update_nodes(self):
87
        """Test update nodes."""
88
        topology = get_topology_mock()
89
        self.kytos_graph.update_nodes(topology.switches)
90
91
        edge_count = sum(
92
            [len(sw.interfaces.values()) for sw in topology.switches.values()]
93
        )
94
        node_count = len(topology.switches) + edge_count
95
        assert self.mock_graph.add_edge.call_count == edge_count
96
        assert self.mock_graph.add_node.call_count == node_count
97
98
    def test_update_nodes_2(self):
99
        """Test update nodes."""
100
101
        effect = MagicMock(side_effect=AttributeError)
102
103
        topology = get_topology_mock()
104
        with self.assertRaises(Exception):
105
            with patch.object(self.mock_graph, "add_node", effect):
106
                self.kytos_graph.update_nodes(topology.switches)
107
108
        self.assertRaises(AttributeError)
109
110
    def test_remove_switch_hops(self):
111
        """Test remove switch hops."""
112
        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
        self.kytos_graph._remove_switch_hops(circuit)
121
122
        expected_circuit = {
123
            "hops": ["00:00:00:00:00:00:00:01:1", "00:00:00:00:00:00:00:01:2"]
124
        }
125
        self.assertEqual(circuit, expected_circuit)
126
127
    @patch("networkx.shortest_simple_paths", return_value=["any"])
128
    def test_shortest_paths(self, mock_shortest_simple_paths):
129
        """Test shortest paths."""
130
        source, dest = "00:00:00:00:00:00:00:01:1", "00:00:00:00:00:00:00:02:2"
131
        k_shortest_paths = self.kytos_graph.k_shortest_paths(source, dest)
132
133
        mock_shortest_simple_paths.assert_called_with(
134
            self.kytos_graph.graph, source, dest, weight=None
135
        )
136
        self.assertEqual(k_shortest_paths, ["any"])
137
138
    @patch("napps.kytos.pathfinder.graph.combinations", autospec=True)
139
    def test_constrained_k_shortest_paths(self, mock_combinations):
140
        """Test shortest constrained paths."""
141
        source, dest = "00:00:00:00:00:00:00:01:1", "00:00:00:00:00:00:00:02:2"
142
        minimum_hits = 1
143
        mandatory_metrics = {"bandwidth": 100}
144
        flexible_metrics = {"utilization": 2}
145
        mock_combinations.return_value = [(("utilization", 2),)]
146
        constrained_k_shortest_paths = [["path1"], ["path2"]]
147
148
        self.kytos_graph.graph.edge_subgraph = MagicMock(return_value=None)
149
        self.kytos_graph.k_shortest_paths = MagicMock(
150
            return_value=constrained_k_shortest_paths
151
        )
152
        self.kytos_graph._filter_links = MagicMock(side_effect=get_filter_links_fake)
153
        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
        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
        self.kytos_graph._filter_links.assert_called()
173
        for constrained_path in k_shortest_paths:
174
            assert constrained_path["hops"] in constrained_k_shortest_paths
175
            assert constrained_path["metrics"] == {
176
                "bandwidth": 100,
177
                "utilization": 2,
178
            }
179
180
    def test_get_link_metadata(self):
181
        """Test metadata retrieval."""
182
        topology = get_topology_with_metadata_mock()
183
        self.kytos_graph.update_nodes(topology.switches)
184
        self.kytos_graph.update_links(topology.links)
185
        endpoint_a = "S1:1"
186
        endpoint_b = "S2:1"
187
        metadata = {"reliability": 5, "bandwidth": 100, "delay": 105}
188
        self.kytos_graph.get_link_metadata = MagicMock(return_value=metadata)
189
190
        result = self.kytos_graph.get_link_metadata(endpoint_a, endpoint_b)
191
192
        assert result == metadata
193
194
    def test_update_link_metadata(self):
195
        """Test update link metadata."""
196
        graph = MagicMock()
197
        link = MagicMock()
198
        endpoint_a_id = 1
199
        endpoint_b_id = 2
200
        link.endpoint_a.id = endpoint_a_id
201
        link.endpoint_b.id = endpoint_b_id
202
        link.metadata.items.return_value = [("reliability", 50)]
203
        self.kytos_graph.graph = graph
204
        self.kytos_graph.update_link_metadata(link)
205
        call_res = str(self.kytos_graph.graph._mock_mock_calls)
206
        assert "__getitem__(1)" in call_res
207
        assert "__getitem__(2)" in call_res
208
        assert "__setitem__('reliability', 50)" in call_res
209
210
    def test_update_link_unsupported_metadata(self):
211
        """Test update link metadata with an unsupported key."""
212
        graph = MagicMock()
213
        link = MagicMock()
214
        endpoint_a_id = 1
215
        endpoint_b_id = 2
216
        link.endpoint_a.id = endpoint_a_id
217
        link.endpoint_b.id = endpoint_b_id
218
        link.metadata.items.return_value = [("random_metric", 50)]
219
        self.kytos_graph.graph = graph
220
        self.kytos_graph.update_link_metadata(link)
221
        assert self.kytos_graph.graph._mock_mock_calls == []
222