Passed
Pull Request — master (#84)
by Vinicius
02:57
created

TestMain.test_load_topology()   B

Complexity

Conditions 3

Size

Total Lines 63
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 51
nop 1
dl 0
loc 63
rs 8.6036
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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