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