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