Passed
Pull Request — master (#48)
by Vinicius
04:45 queued 02:11
created

TestMain.test_delete_link_metadata()   A

Complexity

Conditions 1

Size

Total Lines 29
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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