Test Failed
Pull Request — master (#136)
by
unknown
02:50
created

TestMain.test_interruption_start()   A

Complexity

Conditions 1

Size

Total Lines 39
Code Lines 29

Duplication

Lines 39
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 29
nop 3
dl 39
loc 39
ccs 0
cts 0
cp 0
crap 2
rs 9.184
c 0
b 0
f 0
1
"""Module to test the main napp file."""
2
# pylint: disable=import-error,no-name-in-module,wrong-import-order
3
# pylint: disable=import-outside-toplevel,attribute-defined-outside-init
4 1
import pytest
5 1
import time
6 1
from datetime import timedelta
7 1
from unittest.mock import MagicMock, create_autospec, patch, call
8
9 1
from kytos.core.common import EntityStatus
10 1
from kytos.core.helpers import now
11 1
from kytos.core.events import KytosEvent
12 1
from kytos.core.interface import Interface
13 1
from kytos.core.link import Link
14 1
from kytos.core.switch import Switch
15 1
from kytos.lib.helpers import (get_interface_mock, get_link_mock,
16
                               get_controller_mock, get_switch_mock,
17
                               get_test_client)
18 1
from napps.kytos.topology.exceptions import RestoreError
19
20
21 1
@pytest.mark.parametrize("liveness_status, status",
22
                         [("up", EntityStatus.UP),
23
                          ("down", EntityStatus.DOWN)])
24 1
def test_handle_link_liveness_status(liveness_status, status) -> None:
25
    """Test handle link liveness."""
26 1
    from napps.kytos.topology.main import Main
27 1
    Main.get_topo_controller = MagicMock()
28 1
    napp = Main(get_controller_mock())
29 1
    napp.notify_topology_update = MagicMock()
30 1
    napp.notify_link_status_change = MagicMock()
31
32 1
    link = MagicMock(id="some_id", status=status)
33 1
    napp.handle_link_liveness_status(link, liveness_status)
34
35 1
    add_link_meta = napp.topo_controller.add_link_metadata
36 1
    add_link_meta.assert_called_with(link.id, {"liveness_status":
37
                                               liveness_status})
38 1
    link.extend_metadata.assert_called_with({"liveness_status":
39
                                             liveness_status})
40 1
    assert napp.notify_topology_update.call_count == 1
41 1
    assert napp.notify_link_status_change.call_count == 1
42 1
    reason = f"liveness_{liveness_status}"
43 1
    napp.notify_link_status_change.assert_called_with(link, reason=reason)
44
45
46
# pylint: disable=too-many-public-methods
47 1
class TestMain:
48
    """Test the Main class."""
49
50
    # pylint: disable=too-many-public-methods, protected-access,C0302
51
52 1
    def setup_method(self):
53
        """Execute steps before each tests."""
54 1
        patch('kytos.core.helpers.run_on_thread', lambda x: x).start()
55
        # pylint: disable=import-outside-toplevel
56 1
        from napps.kytos.topology.main import Main
57 1
        Main.get_topo_controller = MagicMock()
58 1
        controller = get_controller_mock()
59 1
        self.napp = Main(controller)
60 1
        self.api_client = get_test_client(controller, self.napp)
61 1
        self.base_endpoint = 'kytos/topology/v3'
62
63 1
    def test_get_event_listeners(self):
64
        """Verify all event listeners registered."""
65 1
        expected_events = [
66
            'kytos/core.shutdown',
67
            'kytos/core.shutdown.kytos/topology',
68
            'kytos/maintenance.start_link',
69
            'kytos/maintenance.end_link',
70
            'kytos/maintenance.start_switch',
71
            'kytos/maintenance.end_switch',
72
            'kytos/.*.link_available_tags',
73
            '.*.topo_controller.upsert_switch',
74
            '.*.of_lldp.network_status.updated',
75
            '.*.interface.is.nni',
76
            '.*.connection.lost',
77
            '.*.switch.interfaces.created',
78
            '.*.topology.switch.interface.created',
79
            '.*.switch.interface.deleted',
80
            '.*.switch.interface.link_down',
81
            '.*.switch.interface.link_up',
82
            '.*.switch.(new|reconnected)',
83
            'kytos/.*.liveness.(up|down)',
84
            'kytos/.*.liveness.disabled',
85
            'kytos/topology.get',
86
            '.*.switch.port.created',
87 1
            'kytos/topology.notify_link_up_if_status',
88 1
            'topology.interruption.start',
89
            'topology.interruption.end',
90 1
        ]
91
        actual_events = self.napp.listeners()
92 1
        assert sorted(expected_events) == sorted(actual_events)
93 1
94 1
    def test_get_link_or_create(self):
95 1
        """Test _get_link_or_create."""
96 1
        dpid_a = "00:00:00:00:00:00:00:01"
97 1
        dpid_b = "00:00:00:00:00:00:00:02"
98 1
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
99 1
        mock_switch_b = get_switch_mock(dpid_b, 0x04)
100
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
101 1
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
102
        mock_interface_a.id = dpid_a
103 1
        mock_interface_b.id = dpid_b
104 1
105 1
        link, created = self.napp._get_link_or_create(mock_interface_a,
106
                                                      mock_interface_b)
107 1
        assert created
108
        assert link.endpoint_a.id == dpid_a
109 1
        assert link.endpoint_b.id == dpid_b
110
111 1
        link, created = self.napp._get_link_or_create(mock_interface_a,
112
                                                      mock_interface_b)
113 1
        assert not created
114 1
115 1
    def test_get_link_from_interface(self):
116 1
        """Test _get_link_from_interface."""
117 1
        mock_switch_a = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
118 1
        mock_switch_b = get_switch_mock("00:00:00:00:00:00:00:02", 0x04)
119 1
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
120 1
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
121 1
        mock_interface_c = get_interface_mock('s2-eth1', 2, mock_switch_b)
122
        mock_link = get_link_mock(mock_interface_a, mock_interface_b)
123 1
        self.napp.links = {'0e2b5d7bc858b9f38db11b69': mock_link}
124 1
        response = self.napp._get_link_from_interface(mock_interface_a)
125
        assert response == mock_link
126 1
127
        response = self.napp._get_link_from_interface(mock_interface_c)
128 1
        assert not response
129 1
130 1
    async def test_get_topology(self):
131
        """Test get_topology."""
132
        dpid_a = "00:00:00:00:00:00:00:01"
133
        dpid_b = "00:00:00:00:00:00:00:02"
134
        expected = {
135
                      "topology": {
136
                        "switches": {
137
                          "00:00:00:00:00:00:00:01": {
138
                            "metadata": {
139
                              "lat": "0.0",
140
                              "lng": "-30.0"
141
                            }
142
                          },
143
                          "00:00:00:00:00:00:00:02": {
144
                            "metadata": {
145
                              "lat": "0.0",
146
                              "lng": "-30.0"
147
                            }
148
                          }
149
                        },
150
                        "links": {
151
                          "cf0f4071be4": {
152
                            "id": "cf0f4071be4"
153
                          }
154 1
                        }
155 1
                      }
156 1
                    }
157 1
158
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
159 1
        mock_switch_b = get_switch_mock(dpid_b, 0x04)
160 1
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
161 1
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
162 1
163
        mock_link = get_link_mock(mock_interface_a, mock_interface_b)
164 1
        mock_link.id = 'cf0f4071be4'
165 1
        mock_switch_a.id = dpid_a
166
        mock_switch_a.as_dict.return_value = {'metadata': {'lat': '0.0',
167
                                              'lng': '-30.0'}}
168 1
        mock_switch_b.id = dpid_b
169
        mock_switch_b.as_dict.return_value = {'metadata': {'lat': '0.0',
170
                                              'lng': '-30.0'}}
171 1
172 1
        self.napp.controller.switches = {dpid_a: mock_switch_a,
173 1
                                         dpid_b: mock_switch_b}
174 1
175 1
        self.napp.links = {"cf0f4071be4": mock_link}
176 1
        mock_link.as_dict.return_value = {"id": "cf0f4071be4"}
177
        endpoint = f"{self.base_endpoint}/"
178 1
        response = await self.api_client.get(endpoint)
179
        assert response.status_code == 200
180 1
        assert response.json() == expected
181
182 1
    def test_load_topology(self):
183 1
        """Test load_topology."""
184 1
        link_id = \
185
            'cf0f4071be426b3f745027f5d22bc61f8312ae86293c9b28e7e66015607a9260'
186
        dpid_a = '00:00:00:00:00:00:00:01'
187
        dpid_b = '00:00:00:00:00:00:00:02'
188
        topology = {
189
            "topology": {
190
                "links": {
191
                    link_id: {
192
                        "enabled": True,
193
                        "id": link_id,
194
                        "endpoint_a": {"id": f"{dpid_a}:2"},
195
                        "endpoint_b": {"id": f"{dpid_b}:2"},
196
                    }
197
                },
198
                "switches": {
199
                    dpid_a: {
200
                        "dpid": dpid_a,
201
                        "enabled": True,
202
                        "metadata": {},
203
                        "id": dpid_a,
204
                        "interfaces": {
205
                            f"{dpid_a}:2": {
206
                                "enabled": True,
207
                                "metadata": {},
208
                                "lldp": True,
209
                                "port_number": 2,
210
                                "name": "s1-eth2",
211
                            }
212
                        },
213
                    },
214
                    dpid_b: {
215
                        "dpid": dpid_b,
216
                        "enabled": True,
217
                        "metadata": {},
218
                        "id": dpid_b,
219
                        "interfaces": {
220
                            f"{dpid_b}:2": {
221
                                "enabled": True,
222
                                "metadata": {},
223
                                "lldp": True,
224
                                "port_number": 2,
225
                                "name": "s2-eth2",
226
                            }
227
                        },
228 1
                    },
229 1
                },
230 1
            }
231 1
        }
232 1
        switches_expected = [dpid_a, dpid_b]
233 1
        interfaces_expected = [f'{dpid_a}:2', f'{dpid_b}:2']
234 1
        links_expected = [link_id]
235 1
        self.napp.topo_controller.get_topology.return_value = topology
236 1
        self.napp.load_topology()
237 1
        assert switches_expected == list(self.napp.controller.switches.keys())
238 1
        interfaces = []
239 1
        for switch in self.napp.controller.switches.values():
240
            for iface in switch.interfaces.values():
241 1
                interfaces.append(iface.id)
242 1
        assert interfaces_expected == interfaces
243 1
        assert links_expected == list(self.napp.links.keys())
244
245 1
    @patch('napps.kytos.topology.main.Main._load_switch')
246 1
    @patch('napps.kytos.topology.main.Main._load_link')
247
    def test_load_topology_does_nothing(self, *args):
248
        """Test _load_network_status doing nothing."""
249 1
        (mock_load_link, mock_load_switch) = args
250 1
        self.napp.topo_controller.get_topology.return_value = {
251 1
            "topology": {"switches": {}, "links": {}}
252
        }
253 1
        self.napp.topo_controller.load_topology()
254 1
        assert mock_load_link.call_count == 0
255 1
        assert mock_load_switch.call_count == 0
256
257 1
    @patch('napps.kytos.topology.main.Main._load_switch')
258 1
    @patch('napps.kytos.topology.main.log')
259
    def test_load_topology_fail_switch(self, *args):
260
        """Test load_topology failure in switch."""
261
        (mock_log, mock_load_switch) = args
262
        topology = {
263
            'topology': {
264
                'links': {},
265
                'switches': {
266 1
                    '1': {}
267 1
                }
268 1
            }
269 1
        }
270 1
        mock_log.error.return_value = True
271 1
        self.napp.topo_controller.get_topology.return_value = topology
272
        mock_load_switch.side_effect = Exception('xpto')
273 1
        self.napp.load_topology()
274 1
        error = 'Error loading switch: xpto'
275 1
        mock_log.error.assert_called_with(error)
276
277 1
    @patch('napps.kytos.topology.main.Main._load_link')
278 1
    @patch('napps.kytos.topology.main.log')
279
    def test_load_topology_fail_link(self, *args):
280
        """Test load_topology failure in link."""
281
        (mock_log, mock_load_link) = args
282
        topology = {
283
            'topology': {
284
                'switches': {},
285
                'links': {
286 1
                    '1': {}
287 1
                }
288 1
            }
289 1
        }
290 1
        mock_log.error.return_value = True
291 1
        self.napp.topo_controller.get_topology.return_value = topology
292
        mock_load_link.side_effect = Exception('xpto')
293 1
        self.napp.load_topology()
294 1
        error = 'Error loading link 1: xpto'
295 1
        mock_log.error.assert_called_with(error)
296
297 1
    @patch('napps.kytos.topology.main.Main.load_interfaces_available_tags')
298 1
    @patch('napps.kytos.topology.main.KytosEvent')
299 1
    def test_load_switch(self, *args):
300 1
        """Test _load_switch."""
301 1
        (mock_event, mock_load_tags) = args
302 1
        mock_buffers_put = MagicMock()
303 1
        self.napp.controller.buffers.app.put = mock_buffers_put
304
        dpid_a = "00:00:00:00:00:00:00:01"
305
        dpid_x = "00:00:00:00:00:00:00:XX"
306
        iface_a = f'{dpid_a}:1'
307
        switch_attrs = {
308
            'dpid': dpid_a,
309
            'enabled': True,
310
            'id': dpid_a,
311
            'metadata': {},
312
            'interfaces': {
313
                iface_a: {
314
                    'enabled': True,
315
                    'active': True,
316
                    'lldp': True,
317
                    'id': iface_a,
318
                    'switch': dpid_a,
319
                    'metadata': {},
320
                    'name': 's2-eth1',
321 1
                    'port_number': 1
322
                }
323 1
            }
324 1
        }
325 1
        self.napp._load_switch(dpid_a, switch_attrs)
326 1
327 1
        assert len(self.napp.controller.switches) == 1
328 1
        assert dpid_a in self.napp.controller.switches
329 1
        assert dpid_x not in self.napp.controller.switches
330
        switch = self.napp.controller.switches[dpid_a]
331 1
        interface_details = self.napp.topo_controller.get_interfaces_details
332 1
        interface_details.assert_called_once_with([iface_a])
333 1
        mock_load_tags.assert_called()
334 1
335
        assert switch.id == dpid_a
336 1
        assert switch.dpid == dpid_a
337 1
        assert switch.is_enabled()
338 1
        assert not switch.is_active()
339 1
340 1
        assert len(switch.interfaces) == 1
341
        assert 1 in switch.interfaces
342 1
        assert 2 not in switch.interfaces
343 1
        mock_event.assert_called()
344 1
        mock_buffers_put.assert_called()
345 1
346 1
        interface = switch.interfaces[1]
347 1
        assert interface.id == iface_a
348 1
        assert interface.switch.id == dpid_a
349 1
        assert interface.port_number == 1
350 1
        assert interface.is_enabled()
351
        assert not interface.is_active()
352 1
        assert interface.lldp
353
        assert interface.uni
354 1
        assert not interface.nni
355 1
356 1
    def test_load_switch_attrs(self):
357
        """Test _load_switch."""
358
        dpid_b = "00:00:00:00:00:00:00:02"
359
        iface_b = f'{dpid_b}:1'
360
        switch_attrs = {
361
            "active": True,
362
            "connection": "127.0.0.1:43230",
363
            "data_path": "XX Human readable desc of dp",
364
            "dpid": "00:00:00:00:00:00:00:02",
365
            "enabled": False,
366
            "hardware": "Open vSwitch",
367
            "id": "00:00:00:00:00:00:00:02",
368
            "interfaces": {
369
                "00:00:00:00:00:00:00:02:1": {
370
                    "active": True,
371
                    "enabled": False,
372
                    "id": "00:00:00:00:00:00:00:02:1",
373
                    "link": "",
374
                    "lldp": False,
375
                    "mac": "de:58:c3:30:b7:b7",
376
                    "metadata": {},
377
                    "name": "s2-eth1",
378
                    "nni": False,
379
                    "port_number": 1,
380
                    "speed": 1250000000,
381
                    "switch": "00:00:00:00:00:00:00:02",
382
                    "type": "interface",
383
                    "uni": True
384
                },
385
            },
386
            "manufacturer": "Nicira, Inc.",
387
            "metadata": {},
388
            "name": "00:00:00:00:00:00:00:04",
389
            "ofp_version": "0x04",
390
            "serial": "XX serial number",
391 1
            "software": "2.10.7",
392 1
            "type": "switch"
393 1
        }
394 1
395
        assert len(self.napp.controller.switches) == 0
396 1
        self.napp._load_switch(dpid_b, switch_attrs)
397 1
        assert len(self.napp.controller.switches) == 1
398 1
        assert dpid_b in self.napp.controller.switches
399 1
400 1
        switch = self.napp.controller.switches[dpid_b]
401 1
        assert switch.id == dpid_b
402 1
        assert switch.dpid == dpid_b
403 1
        assert not switch.is_enabled()
404 1
        assert not switch.is_active()
405 1
        assert switch.description['manufacturer'] == 'Nicira, Inc.'
406 1
        assert switch.description['hardware'] == 'Open vSwitch'
407
        assert switch.description['software'] == '2.10.7'
408 1
        assert switch.description['serial'] == 'XX serial number'
409 1
        exp_data_path = 'XX Human readable desc of dp'
410 1
        assert switch.description['data_path'] == exp_data_path
411
412 1
        assert len(switch.interfaces) == 1
413 1
        assert 1 in switch.interfaces
414 1
        assert 2 not in switch.interfaces
415 1
416 1
        interface = switch.interfaces[1]
417 1
        assert interface.id == iface_b
418 1
        assert interface.switch.id == dpid_b
419 1
        assert interface.port_number == 1
420
        assert not interface.is_enabled()
421 1
        assert not interface.lldp
422
        assert interface.uni
423 1
        assert not interface.nni
424 1
425 1
    def test_interfaces_available_tags(self):
426 1
        """Test load_interfaces_available_tags."""
427 1
        dpid_a = "00:00:00:00:00:00:00:01"
428 1
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
429 1
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
430
        mock_interface_a.id = dpid_a + ':1'
431 1
        mock_switch_a.interfaces = {1: mock_interface_a}
432
        tags = [1, 2, 3]
433 1
        interface_details = [{"id": mock_interface_a.id,
434
                             "available_vlans": tags}]
435 1
        self.napp.load_interfaces_available_tags(mock_switch_a,
436
                                                 interface_details)
437 1
        mock_interface_a.set_available_tags.assert_called_once_with(tags)
438 1
439 1
    def test_handle_on_link_available_tags(self):
440 1
        """test_handle_on_link_available_tags."""
441 1
        dpid_a = "00:00:00:00:00:00:00:01"
442 1
        dpid_b = "00:00:00:00:00:00:00:02"
443 1
        tag = MagicMock()
444 1
        tag.value = 1
445 1
        tags = [tag]
446 1
        link_mock = MagicMock()
447 1
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
448 1
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
449 1
        mock_interface_a.available_tags = tags
450 1
        mock_switch_b = get_switch_mock(dpid_b, 0x04)
451 1
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
452 1
        mock_interface_b.available_tags = tags
453
        link_id = '4d42dc08522'
454 1
        link_mock.id = link_id
455 1
        link_mock.endpoint_a = mock_interface_a
456 1
        link_mock.endpoint_b = mock_interface_b
457 1
458
        self.napp.links[link_id] = link_mock
459
        self.napp.handle_on_link_available_tags(link_mock)
460
        bulk_upsert = self.napp.topo_controller.bulk_upsert_interface_details
461
        bulk_upsert.assert_called_once_with(
462
            [
463
                (
464
                    "00:00:00:00:00:00:00:01:1",
465
                    {"_id": "00:00:00:00:00:00:00:01:1",
466
                     "available_vlans": [1]},
467
                ),
468
                (
469
                    "00:00:00:00:00:00:00:02:1",
470
                    {"_id": "00:00:00:00:00:00:00:02:1",
471
                     "available_vlans": [1]},
472 1
                ),
473
            ]
474 1
        )
475 1
476 1
    def test_load_link(self):
477 1
        """Test _load_link."""
478 1
        dpid_a = "00:00:00:00:00:00:00:01"
479 1
        dpid_b = "00:00:00:00:00:00:00:02"
480 1
        link_id = '4d42dc08522'
481 1
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
482 1
        mock_switch_b = get_switch_mock(dpid_b, 0x04)
483 1
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
484 1
        mock_interface_a.id = dpid_a + ':1'
485 1
        mock_interface_a.available_tags = [1, 2, 3]
486 1
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
487 1
        mock_interface_b.id = dpid_b + ':1'
488 1
        mock_interface_b.available_tags = [1, 2, 3]
489 1
        mock_switch_a.interfaces = {1: mock_interface_a}
490
        mock_switch_b.interfaces = {1: mock_interface_b}
491
        self.napp.controller.switches[dpid_a] = mock_switch_a
492
        self.napp.controller.switches[dpid_b] = mock_switch_b
493
        link_attrs = {
494
            'enabled': True,
495
            'id': link_id,
496
            'metadata': {},
497
            'endpoint_a': {
498
                'id': mock_interface_a.id
499
            },
500
            'endpoint_b': {
501 1
                'id': mock_interface_b.id
502
            }
503 1
        }
504 1
505
        self.napp._load_link(link_attrs)
506 1
507 1
        assert len(self.napp.links) == 1
508 1
        link = list(self.napp.links.values())[0]
509 1
510 1
        assert link.endpoint_a.id == mock_interface_a.id
511 1
        assert link.endpoint_b.id == mock_interface_b.id
512
        assert mock_interface_a.nni
513
        assert mock_interface_b.nni
514 1
        assert mock_interface_a.update_link.call_count == 1
515 1
        assert mock_interface_b.update_link.call_count == 1
516 1
517 1
        # test enable/disable
518 1
        link_id = '4d42dc08522'
519 1
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
520
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
521
        mock_link = get_link_mock(mock_interface_a, mock_interface_b)
522 1
        mock_link.id = link_id
523 1
        with patch('napps.kytos.topology.main.Main._get_link_or_create',
524 1
                   return_value=(mock_link, True)):
525 1
            # enable link
526
            link_attrs['enabled'] = True
527 1
            self.napp.links = {link_id: mock_link}
528 1
            self.napp._load_link(link_attrs)
529 1
            assert mock_link.enable.call_count == 1
530 1
            # disable link
531
            link_attrs['enabled'] = False
532 1
            self.napp.links = {link_id: mock_link}
533 1
            self.napp._load_link(link_attrs)
534
            assert mock_link.disable.call_count == 1
535 1
536 1
    @patch('napps.kytos.topology.main.Main._get_link_or_create')
537 1
    def test_fail_load_link(self, get_link_or_create_mock):
538 1
        """Test fail load_link."""
539 1
        dpid_a = '00:00:00:00:00:00:00:01'
540 1
        dpid_b = '00:00:00:00:00:00:00:02'
541 1
        link_id = '4d42dc08522'
542 1
        mock_switch_a = get_switch_mock(dpid_a)
543 1
        mock_switch_b = get_switch_mock(dpid_b)
544 1
        mock_interface_a_1 = get_interface_mock('s1-eth1', 1, mock_switch_a)
545 1
        mock_interface_b_1 = get_interface_mock('s2-eth1', 1, mock_switch_b)
546
        mock_link = get_link_mock(mock_interface_a_1, mock_interface_b_1)
547 1
        mock_link.id = link_id
548
        self.napp.links = {link_id: mock_link}
549
        get_link_or_create_mock.return_value = mock_link
550
551
        link_attrs_fail = {
552
            'enabled': True,
553
            'id': link_id,
554
            'metadata': {},
555
            'endpoint_a': {
556
                'id': f"{dpid_a}:999",
557
            },
558 1
            'endpoint_b': {
559 1
                'id': f"{dpid_b}:999",
560
            }
561 1
        }
562
        with pytest.raises(RestoreError):
563
            self.napp._load_link(link_attrs_fail)
564
565
        link_attrs_fail = {
566
            'enabled': True,
567
            'id': link_id,
568
            'endpoint_a': {
569
                'id': f"{dpid_a}:1",
570
            },
571 1
            'endpoint_b': {
572 1
                'id': f"{dpid_b}:1",
573
            }
574 1
        }
575 1
        with pytest.raises(RestoreError):
576 1
            self.napp._load_link(link_attrs_fail)
577
578 1 View Code Duplication
    @patch('napps.kytos.topology.main.Main.notify_switch_links_status')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
579 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
580 1
    async def test_enable_switch(self, mock_notify_topo, mock_sw_l_status):
581
        """Test enable_switch."""
582 1
        dpid = "00:00:00:00:00:00:00:01"
583 1
        mock_switch = get_switch_mock(dpid)
584 1
        self.napp.controller.switches = {dpid: mock_switch}
585 1
586 1
        endpoint = f"{self.base_endpoint}/switches/{dpid}/enable"
587 1
        response = await self.api_client.post(endpoint)
588 1
        assert response.status_code == 201
589
        assert mock_switch.enable.call_count == 1
590
        self.napp.topo_controller.enable_switch.assert_called_once_with(dpid)
591 1
        mock_notify_topo.assert_called()
592 1
        mock_sw_l_status.assert_called()
593 1
594 1
        # fail case
595 1
        mock_switch.enable.call_count = 0
596 1
        dpid = "00:00:00:00:00:00:00:02"
597
        endpoint = f"{self.base_endpoint}/switches/{dpid}/enable"
598 1
        response = await self.api_client.post(endpoint)
599 1
        assert response.status_code == 404
600 1
        assert mock_switch.enable.call_count == 0
601
602 1 View Code Duplication
    @patch('napps.kytos.topology.main.Main.notify_switch_links_status')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
603 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
604 1
    async def test_disable_switch(self, mock_notify_topo, mock_sw_l_status):
605
        """Test disable_switch."""
606 1
        dpid = "00:00:00:00:00:00:00:01"
607 1
        mock_switch = get_switch_mock(dpid)
608 1
        self.napp.controller.switches = {dpid: mock_switch}
609 1
610 1
        endpoint = f"{self.base_endpoint}/switches/{dpid}/disable"
611 1
        response = await self.api_client.post(endpoint)
612 1
        assert response.status_code == 201
613
        assert mock_switch.disable.call_count == 1
614
        self.napp.topo_controller.disable_switch.assert_called_once_with(dpid)
615 1
        mock_notify_topo.assert_called()
616 1
        mock_sw_l_status.assert_called()
617 1
618 1
        # fail case
619 1
        mock_switch.disable.call_count = 0
620 1
        dpid = "00:00:00:00:00:00:00:02"
621
        endpoint = f"{self.base_endpoint}/switches/{dpid}/disable"
622 1
        response = await self.api_client.post(endpoint)
623
        assert response.status_code == 404
624 1
        assert mock_switch.disable.call_count == 0
625 1
626 1
    async def test_get_switch_metadata(self):
627 1
        """Test get_switch_metadata."""
628
        dpid = "00:00:00:00:00:00:00:01"
629 1
        mock_switch = get_switch_mock(dpid)
630 1
        mock_switch.metadata = "A"
631 1
        self.napp.controller.switches = {dpid: mock_switch}
632 1
633
        endpoint = f"{self.base_endpoint}/switches/{dpid}/metadata"
634
        response = await self.api_client.get(endpoint)
635 1
        assert response.status_code == 200
636 1
        assert response.json() == {"metadata": mock_switch.metadata}
637 1
638 1
        # fail case
639
        dpid = "00:00:00:00:00:00:00:02"
640 1
        endpoint = f"{self.base_endpoint}/switches/{dpid}/metadata"
641 1
        response = await self.api_client.get(endpoint)
642
        assert response.status_code == 404
643
644
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
645 1
    async def test_add_switch_metadata(
646 1
        self, mock_metadata_changes, event_loop
647 1
    ):
648 1
        """Test add_switch_metadata."""
649 1
        self.napp.controller.loop = event_loop
650
        dpid = "00:00:00:00:00:00:00:01"
651 1
        mock_switch = get_switch_mock(dpid)
652 1
        self.napp.controller.switches = {dpid: mock_switch}
653 1
        payload = {"data": "A"}
654
655 1
        endpoint = f"{self.base_endpoint}/switches/{dpid}/metadata"
656 1
        response = await self.api_client.post(endpoint, json=payload)
657
        assert response.status_code == 201
658
659
        mock_metadata_changes.assert_called()
660
        self.napp.topo_controller.add_switch_metadata.assert_called_once_with(
661 1
            dpid, payload
662 1
        )
663 1
664 1
        # fail case
665
        dpid = "00:00:00:00:00:00:00:02"
666 1
        endpoint = f"{self.base_endpoint}/switches/{dpid}/metadata"
667
        response = await self.api_client.post(endpoint, json=payload)
668 1
        assert response.status_code == 404
669 1
670 1
    async def test_add_switch_metadata_wrong_format(self, event_loop):
671
        """Test add_switch_metadata_wrong_format."""
672 1
        self.napp.controller.loop = event_loop
673 1
        dpid = "00:00:00:00:00:00:00:01"
674 1
        payload = 'A'
675
676 1
        endpoint = f"{self.base_endpoint}/switches/{dpid}/metadata"
677 1
        response = await self.api_client.post(endpoint, json=payload)
678 1
        assert response.status_code == 400
679
680 1
        payload = None
681 1
        response = await self.api_client.post(endpoint, json=payload)
682
        assert response.status_code == 415
683
684
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
685 1
    async def test_delete_switch_metadata(
686 1
        self, mock_metadata_changes, event_loop
687 1
    ):
688 1
        """Test delete_switch_metadata."""
689 1
        self.napp.controller.loop = event_loop
690
        dpid = "00:00:00:00:00:00:00:01"
691 1
        mock_switch = get_switch_mock(dpid)
692 1
        mock_switch.metadata = {"A": "A"}
693 1
        self.napp.controller.switches = {dpid: mock_switch}
694
695 1
        key = "A"
696 1
        endpoint = f"{self.base_endpoint}/switches/{dpid}/metadata/{key}"
697 1
        response = await self.api_client.delete(endpoint)
698 1
699
        assert response.status_code == 200
700
        assert mock_metadata_changes.call_count == 1
701
        del_key_mock = self.napp.topo_controller.delete_switch_metadata_key
702
        del_key_mock.assert_called_with(
703 1
            dpid, key
704 1
        )
705 1
706 1
        # fail case
707 1
        key = "A"
708 1
        dpid = "00:00:00:00:00:00:00:02"
709
        endpoint = f"{self.base_endpoint}/switches/{dpid}/metadata/{key}"
710 1
        response = await self.api_client.delete(endpoint)
711 1
        assert mock_metadata_changes.call_count == 1
712
        assert response.status_code == 404
713 1
714 1 View Code Duplication
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
715 1
    async def test_enable_interfaces(self, mock_notify_topo):
716 1
        """Test enable_interfaces."""
717 1
        dpid = '00:00:00:00:00:00:00:01'
718 1
        mock_switch = get_switch_mock(dpid)
719
        mock_interface_1 = get_interface_mock('s1-eth1', 1, mock_switch)
720 1
        mock_interface_2 = get_interface_mock('s1-eth2', 2, mock_switch)
721
        mock_switch.interfaces = {1: mock_interface_1, 2: mock_interface_2}
722 1
        self.napp.controller.switches = {dpid: mock_switch}
723 1
724 1
        interface_id = '00:00:00:00:00:00:00:01:1'
725 1
726 1
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/enable"
727 1
        response = await self.api_client.post(endpoint)
728
        assert response.status_code == 200
729
        assert mock_interface_1.enable.call_count == 1
730 1
        assert mock_interface_2.enable.call_count == 0
731
        self.napp.topo_controller.enable_interface.assert_called_with(
732 1
            interface_id
733 1
        )
734 1
        mock_notify_topo.assert_called()
735 1
736 1
        mock_interface_1.enable.call_count = 0
737 1
        mock_interface_2.enable.call_count = 0
738
        endpoint = f"{self.base_endpoint}/interfaces/switch/{dpid}/enable"
739
        response = await self.api_client.post(endpoint)
740 1
        assert response.status_code == 200
741 1
        self.napp.topo_controller.upsert_switch.assert_called_with(
742
            mock_switch.id, mock_switch.as_dict()
743
        )
744 1
        assert mock_interface_1.enable.call_count == 1
745 1
        assert mock_interface_2.enable.call_count == 1
746 1
747 1
        # test interface not found
748 1
        interface_id = '00:00:00:00:00:00:00:01:3'
749 1
        mock_interface_1.enable.call_count = 0
750 1
        mock_interface_2.enable.call_count = 0
751 1
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/enable"
752
        response = await self.api_client.post(endpoint)
753
        assert response.status_code == 404
754 1
        assert mock_interface_1.enable.call_count == 0
755 1
        assert mock_interface_2.enable.call_count == 0
756 1
757 1
        # test switch not found
758 1
        dpid = '00:00:00:00:00:00:00:02'
759 1
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/enable"
760
        response = await self.api_client.post(endpoint)
761 1
        assert response.status_code == 404
762 1
        assert mock_interface_1.enable.call_count == 0
763
        assert mock_interface_2.enable.call_count == 0
764 1
765 1 View Code Duplication
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
766 1
    async def test_disable_interfaces(self, mock_notify_topo):
767 1
        """Test disable_interfaces."""
768 1
        interface_id = '00:00:00:00:00:00:00:01:1'
769 1
        dpid = '00:00:00:00:00:00:00:01'
770 1
        mock_switch = get_switch_mock(dpid)
771
        mock_interface_1 = get_interface_mock('s1-eth1', 1, mock_switch)
772 1
        mock_interface_2 = get_interface_mock('s1-eth2', 2, mock_switch)
773 1
        mock_switch.interfaces = {1: mock_interface_1, 2: mock_interface_2}
774 1
        self.napp.controller.switches = {dpid: mock_switch}
775
776 1
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/disable"
777
        response = await self.api_client.post(endpoint)
778
        assert response.status_code == 200
779 1
780 1
        self.napp.topo_controller.disable_interface.assert_called_with(
781 1
            interface_id
782
        )
783 1
        assert mock_interface_1.disable.call_count == 1
784 1
        assert mock_interface_2.disable.call_count == 0
785
        mock_notify_topo.assert_called()
786 1
787 1
        mock_interface_1.disable.call_count = 0
788 1
        mock_interface_2.disable.call_count = 0
789
790 1
        endpoint = f"{self.base_endpoint}/interfaces/switch/{dpid}/disable"
791
        response = await self.api_client.post(endpoint)
792
        assert response.status_code == 200
793 1
794 1
        self.napp.topo_controller.upsert_switch.assert_called_with(
795
            mock_switch.id, mock_switch.as_dict()
796
        )
797 1
        assert mock_interface_1.disable.call_count == 1
798 1
        assert mock_interface_2.disable.call_count == 1
799 1
800 1
        # test interface not found
801 1
        interface_id = '00:00:00:00:00:00:00:01:3'
802
        mock_interface_1.disable.call_count = 0
803 1
        mock_interface_2.disable.call_count = 0
804 1
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/disable"
805 1
        response = await self.api_client.post(endpoint)
806
807
        assert response.status_code == 404
808 1
        assert mock_interface_1.disable.call_count == 0
809 1
        assert mock_interface_2.disable.call_count == 0
810 1
811 1
        # test switch not found
812 1
        dpid = '00:00:00:00:00:00:00:02'
813 1
        endpoint = f"{self.base_endpoint}/interfaces/switch/{dpid}/disable"
814
        response = await self.api_client.post(endpoint)
815 1
        assert response.status_code == 404
816
        assert mock_interface_1.disable.call_count == 0
817 1
        assert mock_interface_2.disable.call_count == 0
818 1
819 1
    async def test_get_interface_metadata(self):
820 1
        """Test get_interface_metada."""
821 1
        interface_id = '00:00:00:00:00:00:00:01:1'
822 1
        dpid = '00:00:00:00:00:00:00:01'
823 1
        mock_switch = get_switch_mock(dpid)
824
        mock_interface = get_interface_mock('s1-eth1', 1, mock_switch)
825 1
        mock_interface.metadata = {"A": "B"}
826 1
        mock_switch.interfaces = {1: mock_interface}
827 1
        self.napp.controller.switches = {dpid: mock_switch}
828 1
829
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/metadata"
830
        response = await self.api_client.get(endpoint)
831 1
        assert response.status_code == 200
832 1
        assert response.json() == {"metadata": mock_interface.metadata}
833 1
834 1
        # fail case switch not found
835
        interface_id = '00:00:00:00:00:00:00:02:1'
836
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/metadata"
837 1
        response = await self.api_client.get(endpoint)
838 1
        assert response.status_code == 404
839 1
840 1
        # fail case interface not found
841
        interface_id = '00:00:00:00:00:00:00:01:2'
842 1
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/metadata"
843 1
        response = await self.api_client.get(endpoint)
844
        assert response.status_code == 404
845
846
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
847 1
    async def test_add_interface_metadata(
848 1
        self, mock_metadata_changes, event_loop
849 1
    ):
850 1
        """Test add_interface_metadata."""
851 1
        self.napp.controller.loop = event_loop
852 1
        interface_id = '00:00:00:00:00:00:00:01:1'
853 1
        dpid = '00:00:00:00:00:00:00:01'
854 1
        mock_switch = get_switch_mock(dpid)
855 1
        mock_interface = get_interface_mock('s1-eth1', 1, mock_switch)
856 1
        mock_interface.metadata = {"metada": "A"}
857 1
        mock_switch.interfaces = {1: mock_interface}
858 1
        self.napp.controller.switches = {dpid: mock_switch}
859 1
        payload = {"metada": "A"}
860
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/metadata"
861
        response = await self.api_client.post(endpoint, json=payload)
862 1
        assert response.status_code == 201
863 1
        mock_metadata_changes.assert_called()
864 1
865 1
        # fail case switch not found
866
        interface_id = '00:00:00:00:00:00:00:02:1'
867
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/metadata"
868 1
        response = await self.api_client.post(endpoint, json=payload)
869 1
        assert response.status_code == 404
870 1
871 1
        # fail case interface not found
872
        interface_id = '00:00:00:00:00:00:00:01:2'
873 1
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/metadata"
874
        response = await self.api_client.post(endpoint, json=payload)
875 1
        assert response.status_code == 404
876 1
877 1
    async def test_add_interface_metadata_wrong_format(self, event_loop):
878 1
        """Test add_interface_metadata_wrong_format."""
879 1
        self.napp.controller.loop = event_loop
880 1
        interface_id = "00:00:00:00:00:00:00:01:1"
881 1
        endpoint = f"{self.base_endpoint}/interfaces/{interface_id}/metadata"
882
        response = await self.api_client.post(endpoint, json='A')
883 1
        assert response.status_code == 400
884
        response = await self.api_client.post(endpoint, json=None)
885 1
        assert response.status_code == 415
886 1
887 1
    async def test_delete_interface_metadata(self, event_loop):
888 1
        """Test delete_interface_metadata."""
889 1
        self.napp.controller.loop = event_loop
890 1
        interface_id = '00:00:00:00:00:00:00:01:1'
891 1
        dpid = '00:00:00:00:00:00:00:01'
892 1
        mock_switch = get_switch_mock(dpid)
893 1
        mock_interface = get_interface_mock('s1-eth1', 1, mock_switch)
894
        mock_interface.remove_metadata.side_effect = [True, False]
895
        mock_interface.metadata = {"A": "A"}
896 1
        mock_switch.interfaces = {1: mock_interface}
897 1
        self.napp.controller.switches = {'00:00:00:00:00:00:00:01':
898 1
                                         mock_switch}
899 1
900
        key = 'A'
901 1
        url = f"{self.base_endpoint}/interfaces/{interface_id}/metadata/{key}"
902 1
        response = await self.api_client.delete(url)
903
        assert response.status_code == 200
904
905 1
        del_key_mock = self.napp.topo_controller.delete_interface_metadata_key
906 1
        del_key_mock.assert_called_once_with(interface_id, key)
907 1
908 1
        # fail case switch not found
909 1
        key = 'A'
910
        interface_id = '00:00:00:00:00:00:00:02:1'
911
        url = f"{self.base_endpoint}/interfaces/{interface_id}/metadata/{key}"
912 1
        response = await self.api_client.delete(url)
913 1
        assert response.status_code == 404
914 1
915 1
        # fail case interface not found
916 1
        key = 'A'
917
        interface_id = '00:00:00:00:00:00:00:01:2'
918
        url = f"{self.base_endpoint}/interfaces/{interface_id}/metadata/{key}"
919 1
        response = await self.api_client.delete(url)
920 1
        assert response.status_code == 404
921 1
922 1
        # fail case metadata not found
923 1
        key = 'B'
924
        interface_id = '00:00:00:00:00:00:00:01:1'
925 1
        url = f"{self.base_endpoint}/interfaces/{interface_id}/metadata/{key}"
926 1
        response = await self.api_client.delete(url)
927
        assert response.status_code == 404
928 1
929 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
930
    async def test_enable_link(self, mock_notify_topo):
931 1
        """Test enable_link."""
932 1
        mock_link = MagicMock(Link)
933 1
        self.napp.links = {'1': mock_link}
934 1
935 1
        link_id = "1"
936 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/enable"
937 1
        response = await self.api_client.post(endpoint)
938
        assert response.status_code == 201
939
        assert mock_link.enable.call_count == 1
940 1
        self.napp.topo_controller.enable_link.assert_called_with(link_id)
941 1
        mock_notify_topo.assert_called()
942 1
943 1
        # fail case
944
        link_id = "2"
945 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/enable"
946 1
        response = await self.api_client.post(endpoint)
947
        assert response.status_code == 404
948 1
949 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
950
    async def test_disable_link(self, mock_notify_topo):
951 1
        """Test disable_link."""
952 1
        mock_link = MagicMock(Link)
953 1
        self.napp.links = {'1': mock_link}
954 1
955 1
        link_id = "1"
956 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/disable"
957 1
        response = await self.api_client.post(endpoint)
958
        assert response.status_code == 201
959
        assert mock_link.disable.call_count == 1
960 1
        assert mock_notify_topo.call_count == 1
961 1
        self.napp.topo_controller.disable_link.assert_called_with(link_id)
962 1
963 1
        # fail case
964
        link_id = "2"
965 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/disable"
966
        response = await self.api_client.post(endpoint)
967 1
        assert response.status_code == 404
968 1
969
    def test_handle_lldp_status_updated(self):
970 1
        """Test handle_lldp_status_updated."""
971 1
        event = MagicMock()
972 1
        self.napp.controller.buffers.app.put = MagicMock()
973 1
974
        dpid_a = "00:00:00:00:00:00:00:01"
975 1
        dpid_b = "00:00:00:00:00:00:00:02"
976 1
        dpids = [dpid_a, dpid_b]
977 1
        interface_ids = [f"{dpid}:1" for dpid in dpids]
978
979
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
980 1
        mock_switch_b = get_switch_mock(dpid_b, 0x04)
981 1
        self.napp.controller.switches = {dpid_a: mock_switch_a,
982
                                         dpid_b: mock_switch_b}
983 1
984 1
        event.content = {"interface_ids": interface_ids, "state": "disabled"}
985
        self.napp.handle_lldp_status_updated(event)
986 1
987
        mock_put = self.napp.controller.buffers.app.put
988 1
        assert mock_put.call_count == len(interface_ids)
989 1
990 1
    def test_handle_topo_controller_upsert_switch(self):
991 1
        """Test handle_topo_controller_upsert_switch."""
992
        event = MagicMock()
993 1
        self.napp.handle_topo_controller_upsert_switch(event)
994
        mock = self.napp.topo_controller.upsert_switch
995 1
        mock.assert_called_with(event.id, event.as_dict())
996 1
997 1
    async def test_get_link_metadata(self):
998 1
        """Test get_link_metadata."""
999
        mock_link = MagicMock(Link)
1000 1
        mock_link.metadata = "A"
1001 1
        self.napp.links = {'1': mock_link}
1002 1
        msg_success = {"metadata": "A"}
1003 1
1004 1
        link_id = "1"
1005
        endpoint = f"{self.base_endpoint}/links/{link_id}/metadata"
1006
        response = await self.api_client.get(endpoint)
1007 1
        assert response.status_code == 200
1008 1
        assert msg_success == response.json()
1009 1
1010 1
        # fail case
1011
        link_id = "2"
1012 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/metadata"
1013 1
        response = await self.api_client.get(endpoint)
1014
        assert response.status_code == 404
1015 1
1016 1
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
1017 1
    async def test_add_link_metadata(self, mock_metadata_changes, event_loop):
1018 1
        """Test add_link_metadata."""
1019 1
        self.napp.controller.loop = event_loop
1020 1
        mock_link = MagicMock(Link)
1021
        mock_link.metadata = "A"
1022 1
        self.napp.links = {'1': mock_link}
1023 1
        payload = {"metadata": "A"}
1024 1
        link_id = 1
1025 1
1026
        endpoint = f"{self.base_endpoint}/links/{link_id}/metadata"
1027
        response = await self.api_client.post(endpoint, json=payload)
1028 1
        assert response.status_code == 201
1029 1
        mock_metadata_changes.assert_called()
1030 1
1031 1
        # fail case
1032
        link_id = 2
1033 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/metadata"
1034
        response = await self.api_client.post(endpoint, json=payload)
1035 1
        assert response.status_code == 404
1036 1
1037 1
    async def test_add_link_metadata_wrong_format(self, event_loop):
1038 1
        """Test add_link_metadata_wrong_format."""
1039 1
        self.napp.controller.loop = event_loop
1040 1
        link_id = 'cf0f4071be426b3f745027f5d22'
1041
        payload = "A"
1042 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/metadata"
1043 1
        response = await self.api_client.post(endpoint, json=payload)
1044 1
        assert response.status_code == 400
1045
1046 1
        payload = None
1047 1
        response = await self.api_client.post(endpoint, json=payload)
1048
        assert response.status_code == 415
1049 1
1050 1
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
1051 1
    async def test_delete_link_metadata(self, mock_metadata_changes):
1052 1
        """Test delete_link_metadata."""
1053
        mock_link = MagicMock(Link)
1054 1
        mock_link.metadata = {"A": "A"}
1055 1
        mock_link.remove_metadata.side_effect = [True, False]
1056 1
        self.napp.links = {'1': mock_link}
1057 1
1058 1
        link_id = 1
1059 1
        key = 'A'
1060 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/metadata/{key}"
1061 1
        response = await self.api_client.delete(endpoint)
1062
        assert response.status_code == 200
1063
        del_mock = self.napp.topo_controller.delete_link_metadata_key
1064 1
        del_mock.assert_called_once_with(mock_link.id, key)
1065 1
        mock_metadata_changes.assert_called()
1066 1
1067 1
        # fail case link not found
1068 1
        link_id = 2
1069
        key = 'A'
1070
        endpoint = f"{self.base_endpoint}/links/{link_id}/metadata/{key}"
1071 1
        response = await self.api_client.delete(endpoint)
1072 1
        assert response.status_code == 404
1073 1
1074 1
        # fail case metadata not found
1075 1
        link_id = 1
1076
        key = 'B'
1077 1
        endpoint = f"{self.base_endpoint}/links/{link_id}/metadata/{key}"
1078 1
        response = await self.api_client.delete(endpoint)
1079
        assert response.status_code == 404
1080 1
1081 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1082 1
    def test_handle_new_switch(self, mock_notify_topology_update):
1083 1
        """Test handle_new_switch."""
1084 1
        mock_event = MagicMock()
1085 1
        mock_switch = create_autospec(Switch)
1086
        mock_event.content['switch'] = mock_switch
1087 1
        self.napp.handle_new_switch(mock_event)
1088
        mock = self.napp.topo_controller.upsert_switch
1089 1
        mock.assert_called_once_with(mock_event.content['switch'].id,
1090 1
                                     mock_event.content['switch'].as_dict())
1091
        mock_notify_topology_update.assert_called()
1092 1
1093 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1094 1
    def test_handle_connection_lost(self, mock_notify_topology_update):
1095 1
        """Test handle connection_lost."""
1096 1
        mock_event = MagicMock()
1097 1
        mock_switch = create_autospec(Switch)
1098
        mock_switch.return_value = True
1099 1
        mock_event.content['source'] = mock_switch
1100 1
        self.napp.handle_connection_lost(mock_event)
1101
        mock_notify_topology_update.assert_called()
1102 1
1103 1
    @patch('napps.kytos.topology.main.Main.handle_interface_link_up')
1104 1
    def test_handle_interface_created(self, mock_link_up):
1105 1
        """Test handle_interface_created."""
1106 1
        mock_event = MagicMock()
1107 1
        mock_interface = create_autospec(Interface)
1108
        mock_interface.id = "1"
1109 1
        mock_event.content = {'interface': mock_interface}
1110 1
        self.napp.handle_interface_created(mock_event)
1111
        mock_link_up.assert_called()
1112 1
1113 1
    @patch('napps.kytos.topology.main.Main.handle_interface_link_up')
1114 1
    def test_handle_interface_created_inactive(self, mock_link_up):
1115 1
        """Test handle_interface_created inactive."""
1116 1
        mock_event = MagicMock()
1117 1
        mock_interface = create_autospec(Interface)
1118 1
        mock_interface.id = "1"
1119
        mock_event.content = {'interface': mock_interface}
1120 1
        mock_interface.is_active.return_value = False
1121
        self.napp.handle_interface_created(mock_event)
1122 1
        mock_link_up.assert_not_called()
1123 1
1124 1
    def test_handle_interfaces_created(self):
1125 1
        """Test handle_interfaces_created."""
1126 1
        buffers_app_mock = MagicMock()
1127 1
        self.napp.controller.buffers.app = buffers_app_mock
1128 1
        mock_switch = create_autospec(Switch)
1129 1
        mock_event = MagicMock()
1130 1
        mock_interface = create_autospec(Interface)
1131 1
        mock_interface.id = "1"
1132
        mock_interface.switch = mock_switch
1133 1
        mock_interface_two = create_autospec(Interface)
1134 1
        mock_interface_two.id = "2"
1135 1
        mock_event.content = {'interfaces': [mock_interface,
1136 1
                              mock_interface_two]}
1137
        self.napp.handle_interfaces_created(mock_event)
1138 1
        upsert_mock = self.napp.topo_controller.upsert_switch
1139 1
        upsert_mock.assert_called_with(mock_switch.id, mock_switch.as_dict())
1140
        assert self.napp.controller.buffers.app.put.call_count == 2
1141 1
1142 1
    @patch('napps.kytos.topology.main.Main.handle_interface_link_down')
1143 1
    def test_handle_interface_down(self, mock_handle_interface_link_down):
1144 1
        """Test handle interface down."""
1145 1
        mock_event = MagicMock()
1146
        mock_interface = create_autospec(Interface)
1147 1
        mock_event.content['interface'] = mock_interface
1148 1
        self.napp.handle_interface_down(mock_event)
1149
        mock_handle_interface_link_down.assert_called()
1150 1
1151 1
    @patch('napps.kytos.topology.main.Main.handle_interface_down')
1152 1
    def test_interface_deleted(self, mock_handle_interface_link_down):
1153
        """Test interface deleted."""
1154 1
        mock_event = MagicMock()
1155 1
        self.napp.handle_interface_deleted(mock_event)
1156 1
        mock_handle_interface_link_down.assert_called()
1157 1
1158
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
1159 1
    @patch('napps.kytos.topology.main.Main.notify_link_up_if_status')
1160
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1161
    def test_interface_link_up(self, *args):
1162
        """Test interface link_up."""
1163 1
        (mock_notify_topology_update,
1164 1
         mock_notify_link_up_if_status,
1165 1
         mock_link_from_interface) = args
1166 1
1167 1
        tnow = time.time()
1168 1
        mock_interface_a = create_autospec(Interface)
1169 1
        mock_interface_a.is_active.return_value = False
1170 1
        mock_interface_b = create_autospec(Interface)
1171 1
        mock_interface_b.is_active.return_value = True
1172 1
        mock_link = create_autospec(Link)
1173 1
        mock_link.get_metadata.return_value = tnow
1174 1
        mock_link.is_active.side_effect = [False, True]
1175 1
        mock_link.endpoint_a = mock_interface_a
1176 1
        mock_link.endpoint_b = mock_interface_b
1177 1
        mock_link_from_interface.return_value = mock_link
1178 1
        mock_link.status = EntityStatus.UP
1179 1
        event = KytosEvent("kytos.of_core.switch.interface.down")
1180 1
        self.napp.handle_interface_link_up(mock_interface_a, event)
1181 1
        mock_notify_topology_update.assert_called()
1182
        mock_link.extend_metadata.assert_called()
1183 1
        mock_link.activate.assert_called()
1184 1
        self.napp.topo_controller.activate_link.assert_called()
1185 1
        mock_notify_link_up_if_status.assert_called()
1186 1
1187
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
1188 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1189
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1190
    def test_interface_link_down(self, *args):
1191 1
        """Test interface link down."""
1192 1
        (mock_status_change, mock_topology_update,
1193 1
         mock_link_from_interface) = args
1194 1
1195 1
        mock_interface = create_autospec(Interface)
1196 1
        mock_link = create_autospec(Link)
1197 1
        mock_link.is_active.return_value = True
1198 1
        mock_link_from_interface.return_value = mock_link
1199
        event = KytosEvent("kytos.of_core.switch.interface.link_up")
1200 1
        self.napp.handle_interface_link_down(mock_interface, event)
1201 1
        mock_topology_update.assert_called()
1202 1
        mock_status_change.assert_called()
1203
1204 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1205
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1206 1
    def test_interface_link_down_unordered_event(self, *args):
1207 1
        """Test interface link down unordered event."""
1208 1
        (mock_status_change, mock_topology_update) = args
1209 1
1210 1
        mock_interface = create_autospec(Interface)
1211 1
        mock_interface.id = "1"
1212 1
        event_2 = KytosEvent("kytos.of_core.switch.interface.down")
1213 1
        event_1 = KytosEvent("kytos.of_core.switch.interface.up")
1214 1
        assert event_1.timestamp > event_2.timestamp
1215
        self.napp._intfs_updated_at[mock_interface.id] = event_1.timestamp
1216 1
        self.napp.handle_interface_link_down(mock_interface, event_2)
1217 1
        mock_topology_update.assert_not_called()
1218 1
        mock_status_change.assert_not_called()
1219
1220 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1221
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1222 1
    def test_interface_link_up_unordered_event(self, *args):
1223 1
        """Test interface link up unordered event."""
1224 1
        (mock_status_change, mock_topology_update) = args
1225 1
1226 1
        mock_interface = create_autospec(Interface)
1227 1
        mock_interface.id = "1"
1228 1
        event_2 = KytosEvent("kytos.of_core.switch.interface.up")
1229 1
        event_1 = KytosEvent("kytos.of_core.switch.interface.down")
1230 1
        assert event_1.timestamp > event_2.timestamp
1231
        self.napp._intfs_updated_at[mock_interface.id] = event_1.timestamp
1232 1
        self.napp.handle_interface_link_up(mock_interface, event_2)
1233 1
        mock_topology_update.assert_not_called()
1234 1
        mock_status_change.assert_not_called()
1235 1
1236
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
1237 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1238
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1239
    def test_handle_link_down(self, *args):
1240 1
        """Test interface link down."""
1241 1
        (mock_status_change, mock_topology_update,
1242 1
         mock_link_from_interface) = args
1243 1
1244 1
        mock_interface = create_autospec(Interface)
1245 1
        mock_link = create_autospec(Link)
1246 1
        mock_link.is_active.return_value = True
1247 1
        mock_link_from_interface.return_value = mock_link
1248 1
        self.napp.handle_link_down(mock_interface)
1249 1
        assert self.napp.topo_controller.deactivate_link.call_count == 1
1250 1
        mock_interface.deactivate.assert_called()
1251
        mock_link.deactivate.assert_called()
1252 1
        assert mock_topology_update.call_count == 1
1253 1
        mock_status_change.assert_called()
1254 1
        assert self.napp.topo_controller.deactivate_interface.call_count == 1
1255 1
1256
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
1257 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1258
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1259
    def test_handle_link_down_not_active(self, *args):
1260 1
        """Test interface link down with link not active."""
1261 1
        (mock_status_change, mock_topology_update,
1262 1
         mock_link_from_interface) = args
1263 1
1264 1
        mock_interface = create_autospec(Interface)
1265 1
        mock_link = create_autospec(Link)
1266 1
        mock_link.is_active.return_value = False
1267 1
        mock_link_from_interface.return_value = mock_link
1268 1
        mock_link.get_metadata.return_value = False
1269 1
        self.napp.handle_link_down(mock_interface)
1270 1
        assert self.napp.topo_controller.deactivate_link.call_count == 0
1271
        mock_interface.deactivate.assert_called()
1272 1
        mock_topology_update.assert_called()
1273 1
        mock_status_change.assert_not_called()
1274 1
        assert self.napp.topo_controller.deactivate_interface.call_count == 1
1275 1
1276
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
1277 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1278
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1279
    def test_handle_link_down_not_active_last_status(self, *args):
1280 1
        """Test interface link down with link not active."""
1281 1
        (mock_status_change, mock_topology_update,
1282 1
         mock_link_from_interface) = args
1283 1
1284 1
        mock_interface = create_autospec(Interface)
1285 1
        mock_link = create_autospec(Link)
1286 1
        mock_link.is_active.return_value = False
1287 1
        mock_link_from_interface.return_value = mock_link
1288 1
        mock_link.get_metadata.return_value = True
1289 1
        self.napp.handle_link_down(mock_interface)
1290 1
        deactivate_link = self.napp.topo_controller.deactivate_link
1291 1
        assert deactivate_link.call_count == 1
1292 1
        assert deactivate_link.call_args[0][0] == mock_link.id
1293 1
        assert not deactivate_link.call_args[0][2]
1294
        mock_interface.deactivate.assert_called()
1295 1
        mock_topology_update.assert_called()
1296 1
        mock_status_change.assert_called()
1297 1
        assert self.napp.topo_controller.deactivate_interface.call_count == 1
1298 1
1299
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
1300 1
    @patch('napps.kytos.topology.main.Main.notify_link_up_if_status')
1301
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1302
    def test_handle_link_up(self, *args):
1303
        """Test handle link up."""
1304 1
        (mock_notify_topology_update,
1305 1
         mock_notify_link_up_if_status,
1306 1
         mock_link_from_interface) = args
1307 1
1308 1
        mock_interface = create_autospec(Interface)
1309 1
        mock_link = MagicMock(status=EntityStatus.UP)
1310 1
        mock_link.is_active.return_value = True
1311 1
        mock_link_from_interface.return_value = mock_link
1312 1
        self.napp.handle_link_up(mock_interface)
1313
        assert self.napp.topo_controller.activate_link.call_count == 1
1314 1
        mock_interface.activate.assert_called()
1315 1
        assert mock_notify_link_up_if_status.call_count == 1
1316 1
        mock_notify_topology_update.assert_called()
1317 1
1318 1
    @patch('time.sleep')
1319
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
1320 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1321
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1322
    def test_handle_link_up_intf_down(self, *args):
1323 1
        """Test handle link up but one intf down."""
1324 1
        (mock_status_change, mock_topology_update,
1325 1
         mock_link_from_interface, _) = args
1326 1
1327 1
        mock_interface = create_autospec(Interface)
1328 1
        mock_link = MagicMock()
1329 1
        mock_link.endpoint_a.is_active.return_value = False
1330 1
        mock_link.is_active.return_value = False
1331 1
        mock_link_from_interface.return_value = mock_link
1332 1
        self.napp.handle_link_up(mock_interface)
1333
        mock_interface.activate.assert_called()
1334 1
        assert self.napp.topo_controller.activate_link.call_count == 0
1335 1
        assert mock_topology_update.call_count == 1
1336 1
        mock_status_change.assert_not_called()
1337
1338 1
    @patch('napps.kytos.topology.main.Main._get_link_or_create')
1339
    @patch('napps.kytos.topology.main.Main.notify_link_up_if_status')
1340
    def test_add_links(self, *args):
1341 1
        """Test add_links."""
1342 1
        (mock_notify_link_up_if_status,
1343 1
         mock_get_link_or_create) = args
1344 1
1345 1
        mock_link = MagicMock()
1346 1
        mock_get_link_or_create.return_value = (mock_link, True)
1347
        mock_event = MagicMock()
1348 1
        mock_intf_a = MagicMock()
1349 1
        mock_intf_b = MagicMock()
1350 1
        mock_event.content = {
1351 1
            "interface_a": mock_intf_a,
1352 1
            "interface_b": mock_intf_b
1353 1
        }
1354 1
        self.napp.add_links(mock_event)
1355 1
        mock_link.extend_metadata.assert_called()
1356
        mock_get_link_or_create.assert_called()
1357 1
        mock_notify_link_up_if_status.assert_called()
1358
        mock_intf_a.update_link.assert_called()
1359 1
        mock_intf_b.update_link.assert_called()
1360 1
        mock_link.endpoint_a = mock_intf_a
1361 1
        mock_link.endpoint_b = mock_intf_b
1362 1
1363 1
    def test_notify_switch_enabled(self):
1364
        """Test notify switch enabled."""
1365 1
        dpid = "00:00:00:00:00:00:00:01"
1366
        mock_buffers_put = MagicMock()
1367 1
        self.napp.controller.buffers.app.put = mock_buffers_put
1368 1
        self.napp.notify_switch_enabled(dpid)
1369 1
        mock_buffers_put.assert_called()
1370 1
1371 1
    def test_notify_switch_disabled(self):
1372
        """Test notify switch disabled."""
1373 1
        dpid = "00:00:00:00:00:00:00:01"
1374
        mock_buffers_put = MagicMock()
1375 1
        self.napp.controller.buffers.app.put = mock_buffers_put
1376 1
        self.napp.notify_switch_disabled(dpid)
1377 1
        mock_buffers_put.assert_called()
1378 1
1379
    def test_notify_topology_update(self):
1380 1
        """Test notify_topology_update."""
1381
        mock_buffers_put = MagicMock()
1382 1
        self.napp.controller.buffers.app.put = mock_buffers_put
1383 1
        self.napp.notify_topology_update()
1384 1
        mock_buffers_put.assert_called()
1385 1
1386 1
    def test_notify_current_topology(self):
1387 1
        """Test notify_current_topology."""
1388 1
        mock_buffers_put = MagicMock()
1389 1
        self.napp.controller.buffers.app.put = mock_buffers_put
1390
        self.napp.notify_current_topology()
1391 1
        mock_buffers_put.assert_called()
1392
        args = mock_buffers_put.call_args
1393 1
        expected_event = args[0][0]
1394 1
        assert expected_event.name == "kytos/topology.current"
1395 1
        assert "topology" in expected_event.content
1396 1
1397 1
    def test_notify_link_status_change(self):
1398
        """Test notify link status change."""
1399 1
        mock_buffers_put = MagicMock()
1400
        self.napp.controller.buffers.app.put = mock_buffers_put
1401 1
        mock_link = create_autospec(Link)
1402 1
        mock_link.id = 'test_link'
1403 1
        mock_link.status_reason = frozenset()
1404 1
        mock_link.status = EntityStatus.UP
1405 1
1406 1
        # Check when switching to up
1407 1
        self.napp.notify_link_status_change(mock_link, 'test')
1408 1
        assert mock_buffers_put.call_count == 1
1409 1
        args, kwargs = mock_buffers_put.call_args
1410 1
        event = args[0]
1411 1
        assert event.content['link'] is mock_link
1412
        assert event.content['reason'] == 'test'
1413 1
        assert event.name == 'kytos/topology.link_up'
1414
        
1415 1
1416 1
        # Check result when no change
1417 1
        self.napp.notify_link_status_change(mock_link, 'test2')
1418 1
        assert mock_buffers_put.call_count == 1
1419 1
1420 1
        # Check when switching to down
1421 1
        mock_link.status_reason = frozenset({'disabled'})
1422
        mock_link.status = EntityStatus.DOWN
1423 1
        self.napp.notify_link_status_change(mock_link, 'test3')
1424
        assert mock_buffers_put.call_count == 2
1425 1
        args, kwargs = mock_buffers_put.call_args
1426 1
        event = args[0]
1427
        assert event.content['link'] is mock_link
1428
        assert event.content['reason'] == 'test3'
1429
        assert event.name == 'kytos/topology.link_down'
1430
1431
    def test_notify_metadata_changes(self):
1432
        """Test notify metadata changes."""
1433
        mock_buffers_put = MagicMock()
1434 1
        self.napp.controller.buffers.app.put = mock_buffers_put
1435 1
        count = 0
1436 1
        for spec in [Switch, Interface, Link]:
1437 1
            mock_obj = create_autospec(spec)
1438 1
            mock_obj.metadata = {"some_key": "some_value"}
1439
            self.napp.notify_metadata_changes(mock_obj, 'added')
1440 1
            assert mock_buffers_put.call_count == count+1
1441
            count += 1
1442 1
        with pytest.raises(ValueError):
1443 1
            self.napp.notify_metadata_changes(MagicMock(), 'added')
1444
1445
    def test_notify_port_created(self):
1446
        """Test notify port created."""
1447
        mock_buffers_put = MagicMock()
1448
        self.napp.controller.buffers.app.put = mock_buffers_put
1449
        event = KytosEvent("some_event")
1450
        expected_name = "kytos/topology.port.created"
1451 1
        self.napp.notify_port_created(event)
1452 1
        assert mock_buffers_put.call_count == 1
1453 1
        assert mock_buffers_put.call_args_list[0][0][0].name == expected_name
1454
1455 1
    def test_get_links_from_interfaces(self) -> None:
1456
        """Test get_links_from_interfaces."""
1457 1
        interfaces = [MagicMock(id=f"intf{n}") for n in range(4)]
1458 1
        links = {
1459 1
            "link1": MagicMock(id="link1",
1460 1
                               endpoint_a=interfaces[0],
1461
                               endpoint_b=interfaces[1]),
1462 1
            "link2": MagicMock(id="link2",
1463 1
                               endpoint_a=interfaces[2],
1464
                               endpoint_b=interfaces[3]),
1465 1
        }
1466 1
        self.napp.links = links
1467 1
        response = self.napp.get_links_from_interfaces(interfaces)
1468 1
        assert links == response
1469 1
        response = self.napp.get_links_from_interfaces(interfaces[:2])
1470 1
        assert response == {"link1": links["link1"]}
1471 1
1472 1
    def test_handle_link_liveness_disabled(self) -> None:
1473 1
        """Test handle_link_liveness_disabled."""
1474 1
        interfaces = [MagicMock(id=f"intf{n}") for n in range(4)]
1475 1
        links = {
1476 1
            "link1": MagicMock(id="link1",
1477
                               endpoint_a=interfaces[0],
1478 1
                               endpoint_b=interfaces[1]),
1479 1
            "link2": MagicMock(id="link2",
1480
                               endpoint_a=interfaces[2],
1481 1
                               endpoint_b=interfaces[3]),
1482 1
        }
1483 1
        self.napp.links = links
1484 1
        self.napp.notify_topology_update = MagicMock()
1485 1
        self.napp.notify_link_status_change = MagicMock()
1486 1
1487 1
        self.napp.handle_link_liveness_disabled(interfaces)
1488 1
1489 1
        bulk_delete = self.napp.topo_controller.bulk_delete_link_metadata_key
1490 1
        assert bulk_delete.call_count == 1
1491 1
        assert self.napp.notify_topology_update.call_count == 1
1492 1
        assert self.napp.notify_link_status_change.call_count == len(links)
1493
1494 1
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1495 1
    def test_handle_link_maintenance_start(self, status_change_mock):
1496
        """Test handle_link_maintenance_start."""
1497 1
        link1 = MagicMock()
1498 1
        link1.id = 2
1499 1
        link2 = MagicMock()
1500 1
        link2.id = 3
1501 1
        link3 = MagicMock()
1502 1
        link3.id = 4
1503 1
        content = {'links': [link1.id, link2.id]}
1504 1
        event = MagicMock()
1505 1
        event.content = content
1506 1
        self.napp.links = {2: link1, 4: link3}
1507 1
        self.napp.handle_link_maintenance_start(event)
1508 1
        status_change_mock.assert_called_once_with(link1, reason='maintenance')
1509 1
1510 1
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1511 1
    def test_handle_link_maintenance_end(self, status_change_mock):
1512 1
        """Test handle_link_maintenance_end."""
1513 1
        link1 = MagicMock()
1514 1
        link1.id = 2
1515 1
        link2 = MagicMock()
1516 1
        link2.id = 3
1517 1
        link3 = MagicMock()
1518 1
        link3.id = 4
1519
        content = {'links': [link1.id, link2.id]}
1520 1
        event = MagicMock()
1521 1
        event.content = content
1522
        self.napp.links = {2: link1, 4: link3}
1523 1
        self.napp.handle_link_maintenance_end(event)
1524 1
        status_change_mock.assert_called_once_with(link1, reason='maintenance')
1525 1
1526 1 View Code Duplication
    @patch('napps.kytos.topology.main.Main.handle_link_down')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1527 1
    def test_handle_switch_maintenance_start(self, handle_link_down_mock):
1528 1
        """Test handle_switch_maintenance_start."""
1529 1
        switch1 = MagicMock()
1530 1
        switch1.id = 'a'
1531 1
        interface1 = MagicMock()
1532 1
        interface1.is_active.return_value = True
1533 1
        interface2 = MagicMock()
1534 1
        interface2.is_active.return_value = False
1535 1
        interface3 = MagicMock()
1536 1
        interface3.is_active.return_value = True
1537 1
        switch1.interfaces = {1: interface1, 2: interface2, 3: interface3}
1538 1
        switch2 = MagicMock()
1539 1
        switch2.id = 'b'
1540 1
        interface4 = MagicMock()
1541 1
        interface4.is_active.return_value = False
1542 1
        interface5 = MagicMock()
1543 1
        interface5.is_active.return_value = True
1544 1
        switch2.interfaces = {1: interface4, 2: interface5}
1545
        content = {'switches': [switch1.id, switch2.id]}
1546 1
        event = MagicMock()
1547
        event.content = content
1548 1
        self.napp.controller.switches = {'a': switch1, 'b': switch2}
1549 1
        self.napp.handle_switch_maintenance_start(event)
1550 1
        assert handle_link_down_mock.call_count == 3
1551 1
1552 1 View Code Duplication
    @patch('napps.kytos.topology.main.Main.handle_link_up')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1553 1
    def test_handle_switch_maintenance_end(self, handle_link_up_mock):
1554
        """Test handle_switch_maintenance_end."""
1555 1
        switch1 = MagicMock()
1556 1
        switch1.id = 'a'
1557 1
        interface1 = MagicMock()
1558 1
        interface1.is_active.return_value = True
1559
        interface2 = MagicMock()
1560 1
        interface2.is_active.return_value = False
1561 1
        interface3 = MagicMock()
1562 1
        interface3.is_active.return_value = True
1563 1
        switch1.interfaces = {1: interface1, 2: interface2, 3: interface3}
1564
        switch2 = MagicMock()
1565
        switch2.id = 'b'
1566
        interface4 = MagicMock()
1567
        interface4.is_active.return_value = False
1568
        interface5 = MagicMock()
1569
        interface5.is_active.return_value = True
1570
        switch2.interfaces = {1: interface4, 2: interface5}
1571 1
        content = {'switches': [switch1.id, switch2.id]}
1572 1
        event = MagicMock()
1573 1
        event.content = content
1574 1
        self.napp.controller.switches = {'a': switch1, 'b': switch2}
1575 1
        self.napp.handle_switch_maintenance_end(event)
1576 1
        assert handle_link_up_mock.call_count == 5
1577
1578 1
    def test_link_status_hook_link_up_timer(self) -> None:
1579 1
        """Test status hook link up timer."""
1580 1
        last_change = time.time() - self.napp.link_up_timer + 5
1581 1
        link = MagicMock(metadata={"last_status_change": last_change})
1582 1
        link.is_active.return_value = True
1583 1
        link.is_enabled.return_value = True
1584 1
        res = self.napp.link_status_hook_link_up_timer(link)
1585
        assert res == EntityStatus.DOWN
1586 1
1587
        last_change = time.time() - self.napp.link_up_timer
1588 1
        link.metadata["last_status_change"] = last_change
1589 1
        res = self.napp.link_status_hook_link_up_timer(link)
1590
        assert res is None
1591 1
1592 1
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1593 1
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
1594 1
    @patch('time.sleep')
1595 1
    def test_notify_link_up_if_status(
1596 1
        self,
1597 1
        mock_sleep,
1598
        mock_notify_topo,
1599 1
        mock_notify_link,
1600 1
    ) -> None:
1601
        """Test notify link up if status."""
1602 1
1603 1
        link = MagicMock(status=EntityStatus.UP)
1604 1
        link.get_metadata.return_value = now()
1605
        assert not self.napp.notify_link_up_if_status(link, "link up")
1606
        link.update_metadata.assert_not_called()
1607 1
        mock_notify_topo.assert_not_called()
1608 1
        mock_notify_link.assert_not_called()
1609 1
1610
        link = MagicMock(status=EntityStatus.UP)
1611 1
        link.get_metadata.return_value = now() - timedelta(seconds=60)
1612 1
        assert not self.napp.notify_link_up_if_status(link, "link up")
1613 1
        link.update_metadata.assert_called()
1614
        self.napp.topo_controller.add_link_metadata.assert_called()
1615 1
        mock_notify_topo.assert_called()
1616
        mock_notify_link.assert_called()
1617 1
1618 1
        assert mock_sleep.call_count == 2
1619 1
1620 1
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1621 1
    def test_notify_switch_links_status(self, mock_notify_link_status_change):
1622 1
        """Test switch links notification when switch status change"""
1623 1
        buffers_app_mock = MagicMock()
1624
        self.napp.controller.buffers.app = buffers_app_mock
1625 1
        dpid = "00:00:00:00:00:00:00:01"
1626 1
        mock_switch = get_switch_mock(dpid)
1627 1
        link1 = MagicMock()
1628 1
        link1.endpoint_a.switch = mock_switch
1629
        self.napp.links = {1: link1}
1630
1631 1
        self.napp.notify_switch_links_status(mock_switch, "link enabled")
1632 1
        assert self.napp.controller.buffers.app.put.call_count == 1
1633 1
1634 1
        self.napp.notify_switch_links_status(mock_switch, "link disabled")
1635
        assert self.napp.controller.buffers.app.put.call_count == 1
1636
        assert mock_notify_link_status_change.call_count == 1
1637
1638
        # Without notification
1639
        link1.endpoint_a.switch = None
1640
        self.napp.notify_switch_links_status(mock_switch, "link enabled")
1641
        assert self.napp.controller.buffers.app.put.call_count == 1
1642
1643
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1644
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
1645
    def test_notify_interface_link_status(self, *args):
1646
        """Test interface links notification when enable"""
1647
        (mock_get_link_from_interface,
1648
         mock_notify_link_status_change) = args
1649
        buffers_app_mock = MagicMock()
1650
        self.napp.controller.buffers.app = buffers_app_mock
1651
        mock_link = MagicMock()
1652
        mock_get_link_from_interface.return_value = mock_link
1653
        self.napp.notify_interface_link_status(MagicMock(), "link enabled")
1654
        assert mock_get_link_from_interface.call_count == 1
1655
        assert self.napp.controller.buffers.app.put.call_count == 1
1656
1657
        self.napp.notify_interface_link_status(MagicMock(), "link disabled")
1658
        assert mock_get_link_from_interface.call_count == 2
1659
        assert mock_notify_link_status_change.call_count == 1
1660
        assert self.napp.controller.buffers.app.put.call_count == 1
1661
1662
        # Without notification
1663
        mock_get_link_from_interface.return_value = None
1664
        self.napp.notify_interface_link_status(MagicMock(), "link enabled")
1665
        assert mock_get_link_from_interface.call_count == 3
1666
        assert self.napp.controller.buffers.app.put.call_count == 1
1667
1668 View Code Duplication
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1669
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1670
    def test_interruption_start(
1671
        self,
1672
        mock_notify_link_status_change,
1673
        mock_notify_topology_update
1674
    ):
1675
        """Tests processing of received interruption start events."""
1676
        link_a = MagicMock()
1677
        link_b = MagicMock()
1678
        link_c = MagicMock()
1679
        self.napp.links = {
1680
            'link_a': link_a,
1681
            'link_b': link_b,
1682
            'link_c': link_c,
1683
        }
1684
        event = KytosEvent(
1685
            "topology.interruption.start",
1686
            {
1687
                'type': 'test_interruption',
1688
                'switches': [
1689
                ],
1690
                'interfaces': [
1691
                ],
1692
                'links': [
1693
                    'link_a',
1694
                    'link_c',
1695
                ],
1696
            }
1697
        )
1698
        self.napp.handle_interruption_start(event)
1699
        mock_notify_link_status_change.assert_has_calls(
1700
            [
1701
                call(link_a, 'test_interruption'),
1702
                call(link_c, 'test_interruption'),
1703
            ]
1704
        )
1705
        assert mock_notify_link_status_change.call_count == 2
1706
        mock_notify_topology_update.assert_called_once()
1707
1708 View Code Duplication
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1709
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
1710
    def test_interruption_end(
1711
        self,
1712
        mock_notify_link_status_change,
1713
        mock_notify_topology_update
1714
    ):
1715
        """Tests processing of received interruption end events."""
1716
        link_a = MagicMock()
1717
        link_b = MagicMock()
1718
        link_c = MagicMock()
1719
        self.napp.links = {
1720
            'link_a': link_a,
1721
            'link_b': link_b,
1722
            'link_c': link_c,
1723
        }
1724
        event = KytosEvent(
1725
            "topology.interruption.start",
1726
            {
1727
                'type': 'test_interruption',
1728
                'switches': [
1729
                ],
1730
                'interfaces': [
1731
                ],
1732
                'links': [
1733
                    'link_a',
1734
                    'link_c',
1735
                ],
1736
            }
1737
        )
1738
        self.napp.handle_interruption_end(event)
1739
        mock_notify_link_status_change.assert_has_calls(
1740
            [
1741
                call(link_a, 'test_interruption'),
1742
                call(link_c, 'test_interruption'),
1743
            ]
1744
        )
1745
        assert mock_notify_link_status_change.call_count == 2
1746
        mock_notify_topology_update.assert_called_once()
1747