Passed
Pull Request — master (#129)
by Vinicius
07:32 queued 03:49
created

TestMain.test_notify_link_up_if_status()   A

Complexity

Conditions 1

Size

Total Lines 27
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 1

Importance

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