Passed
Pull Request — master (#38)
by Vinicius
02:40
created

TestMain.test_notify_link_status_change()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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