Test Failed
Pull Request — master (#112)
by Vinicius
06:26
created

build.tests.unit.test_main   F

Complexity

Total Complexity 71

Size/Duplication

Total Lines 1540
Duplicated Lines 15.26 %

Importance

Changes 0
Metric Value
eloc 1235
dl 235
loc 1540
rs 1.52
c 0
b 0
f 0
wmc 71

62 Methods

Rating   Name   Duplication   Size   Complexity  
A TestMain.test_handle_new_switch() 0 11 1
A TestMain.test_handle_switch_maintenance_start() 22 22 1
A TestMain.test_handle_link_up_intf_down() 0 19 1
A TestMain.test_disable_switch() 22 22 1
A TestMain.test_notify_port_created() 0 9 1
A TestMain.test_notify_topology_update() 0 8 1
A TestMain.test_disable_link() 0 20 1
A TestMain.test_add_switch_metadata() 0 24 1
A TestMain.test_get_link_from_interface() 0 14 1
A TestMain.test_get_switch_metadata() 0 17 1
B TestMain.test_get_topology() 0 53 1
A TestMain.test_add_links() 0 25 1
A TestMain.test_notify_link_status_change() 0 9 1
A TestMain.test_handle_link_down() 0 19 1
A TestMain.test_enable_link() 0 20 1
A TestMain.test_get_links_from_interfaces() 0 16 1
A TestMain.test_handle_interfaces_created() 0 17 1
A TestMain.test_handle_interface_down() 0 8 1
B TestMain.test_load_switch() 0 55 1
B TestMain.test_load_topology() 0 63 3
A TestMain.test_interface_link_up() 0 24 1
A TestMain.test_add_link_metadata_wrong_format() 0 15 1
A TestMain.test_enable_switch() 22 22 1
A TestMain.test_delete_interface_metadata() 0 41 1
A TestMain.test_add_interface_metadata() 0 32 1
A TestMain.test_load_topology_fail_link() 0 19 1
A TestMain.test_handle_switch_maintenance_end() 22 22 1
A TestMain.test_handle_on_link_available_tags() 0 33 1
B TestMain.test_enable_interfaces() 50 50 1
B TestMain.test_verify_api_urls() 47 47 1
A TestMain.test_add_switch_metadata_wrong_format() 0 14 1
A TestMain.test_notify_switch_enabled() 0 9 1
A TestMain.test_get_interface_metadata() 0 26 1
A TestMain.test_handle_link_up() 0 17 1
A TestMain.test_load_topology_fail_switch() 0 19 1
A TestMain.test_interfaces_available_tags() 0 13 1
A TestMain.test_get_event_listeners() 0 25 1
A TestMain.test_delete_switch_metadata() 0 26 1
A TestMain.test_handle_link_maintenance_start() 0 15 1
A TestMain.test_interface_deleted() 0 6 1
A TestMain.test_get_link_or_create() 0 20 1
A TestMain.test_handle_topo_controller_upsert_switch() 0 6 1
B TestMain.test_load_switch_attrs() 0 68 1
A TestMain.test_handle_link_maintenance_end() 0 15 1
B TestMain.test_disable_interfaces() 50 50 1
A TestMain.test_add_link_metadata() 0 22 1
A TestMain.test_notify_switch_disabled() 0 9 1
A TestMain.test_notify_current_topology() 0 9 1
A TestMain.test_get_link_metadata() 0 19 1
A TestMain.test_delete_link_metadata() 0 31 1
A TestMain.test_add_interface_metadata_wrong_format() 0 14 1
A TestMain.test_handle_link_down_not_active() 0 19 1
A TestMain.test_interface_link_down() 0 17 1
A TestMain.test_notify_metadata_changes() 0 15 3
A TestMain.test_handle_connection_lost() 0 9 1
A TestMain.test_handle_link_liveness_disabled() 0 21 1
A TestMain.setUp() 0 13 2
A TestMain.test_handle_interface_created() 0 9 1
A TestMain.test_handle_lldp_status_updated() 0 20 1
A TestMain.test_load_topology_does_nothing() 0 11 1
B TestMain.test_load_link() 0 59 2
A TestMain.test_fail_load_link() 0 41 3

1 Function

Rating   Name   Duplication   Size   Complexity  
A test_handle_link_liveness_status() 0 23 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like build.tests.unit.test_main often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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