Passed
Push — master ( 369831...28d78d )
by Italo Valcy
01:35 queued 13s
created

TestMain.test_load_circuits_by_interface()   B

Complexity

Conditions 1

Size

Total Lines 187
Code Lines 153

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 153
nop 1
dl 0
loc 187
rs 7
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
"""Module to test the main napp file."""
2
import json
3
from unittest import TestCase
4
from unittest.mock import MagicMock, PropertyMock, call, create_autospec, patch
5
6
from kytos.core.events import KytosEvent
7
from kytos.core.interface import UNI, Interface
8
from napps.kytos.mef_eline.exceptions import InvalidPath
9
from napps.kytos.mef_eline.models import EVC
10
from tests.helpers import get_controller_mock, get_uni_mocked
11
12
13
# pylint: disable=too-many-public-methods, too-many-lines
14
class TestMain(TestCase):
15
    """Test the Main class."""
16
17
    def setUp(self):
18
        """Execute steps before each tests.
19
20
        Set the server_name_url_url from kytos/mef_eline
21
        """
22
        self.server_name_url = 'http://localhost:8181/api/kytos/mef_eline'
23
24
        # The decorator run_on_thread is patched, so methods that listen
25
        # for events do not run on threads while tested.
26
        # Decorators have to be patched before the methods that are
27
        # decorated with them are imported.
28
        patch('kytos.core.helpers.run_on_thread', lambda x: x).start()
29
        # pylint: disable=import-outside-toplevel
30
        from napps.kytos.mef_eline.main import Main
31
32
        self.addCleanup(patch.stopall)
33
        self.napp = Main(get_controller_mock())
34
35
    def test_get_event_listeners(self):
36
        """Verify all event listeners registered."""
37
        expected_events = ['kytos/core.shutdown',
38
                           'kytos/core.shutdown.kytos/mef_eline',
39
                           'kytos/topology.link_up',
40
                           'kytos/topology.link_down']
41
        actual_events = self.napp.listeners()
42
43
        for _event in expected_events:
44
            self.assertIn(_event, actual_events, '%s' % _event)
45
46
    def test_verify_api_urls(self):
47
        """Verify all APIs registered."""
48
        expected_urls = [
49
            ({}, {'POST', 'OPTIONS'},
50
             '/api/kytos/mef_eline/v2/evc/'),
51
52
            ({}, {'OPTIONS', 'HEAD', 'GET'},
53
             '/api/kytos/mef_eline/v2/evc/'),
54
55
            ({'circuit_id': '[circuit_id]'}, {'OPTIONS', 'DELETE'},
56
             '/api/kytos/mef_eline/v2/evc/<circuit_id>'),
57
58
            ({'circuit_id': '[circuit_id]'}, {'OPTIONS', 'HEAD', 'GET'},
59
             '/api/kytos/mef_eline/v2/evc/<circuit_id>'),
60
61
            ({'circuit_id': '[circuit_id]'}, {'OPTIONS', 'PATCH'},
62
             '/api/kytos/mef_eline/v2/evc/<circuit_id>'),
63
64
            ({'circuit_id': '[circuit_id]'}, {'OPTIONS', 'HEAD', 'GET'},
65
             '/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata'),
66
67
            ({'circuit_id': '[circuit_id]'}, {'OPTIONS', 'POST'},
68
             '/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata'),
69
70
            ({'circuit_id': '[circuit_id]', 'key': '[key]'},
71
             {'OPTIONS', 'DELETE'},
72
             '/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata/<key>'),
73
74
            ({'circuit_id': '[circuit_id]'}, {'OPTIONS', 'PATCH'},
75
             '/api/kytos/mef_eline/v2/evc/<circuit_id>/redeploy'),
76
77
            ({}, {'OPTIONS', 'GET', 'HEAD'},
78
             '/api/kytos/mef_eline/v2/evc/schedule'),
79
80
            ({}, {'POST', 'OPTIONS'},
81
             '/api/kytos/mef_eline/v2/evc/schedule/'),
82
83
            ({'schedule_id': '[schedule_id]'},
84
             {'OPTIONS', 'DELETE'},
85
             '/api/kytos/mef_eline/v2/evc/schedule/<schedule_id>'),
86
87
            ({'schedule_id': '[schedule_id]'},
88
             {'OPTIONS', 'PATCH'},
89
             '/api/kytos/mef_eline/v2/evc/schedule/<schedule_id>')
90
            ]
91
92
        urls = self.get_napp_urls(self.napp)
93
        self.assertCountEqual(expected_urls, urls)
94
95
    @patch('napps.kytos.mef_eline.main.log')
96
    @patch('napps.kytos.mef_eline.main.Main.execute_consistency')
97
    def test_execute(self, mock_execute_consistency, mock_log):
98
        """Test execute."""
99
        self.napp.execute()
100
        mock_execute_consistency.assert_called()
101
        self.assertEqual(mock_log.debug.call_count, 2)
102
103
        # Test locked should return
104
        mock_execute_consistency.call_count = 0
105
        mock_log.info.call_count = 0
106
        # pylint: disable=protected-access
107
        self.napp._lock = MagicMock()
108
        self.napp._lock.locked.return_value = True
109
        # pylint: enable=protected-access
110
        self.napp.execute()
111
        mock_execute_consistency.assert_not_called()
112
        mock_log.info.assert_not_called()
113
114
    @patch('napps.kytos.mef_eline.main.settings')
115
    @patch('napps.kytos.mef_eline.main.Main._load_evc')
116
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
117
    def test_execute_consistency(self, *args):
118
        """Test execute_consistency."""
119
        (mock_get_data, mock_load_evc, mock_settings) = args
120
121
        stored_circuits = {'1': {'name': 'circuit_1'},
122
                           '2': {'name': 'circuit_2'},
123
                           '3': {'name': 'circuit_3'}}
124
        mock_get_data.return_value = stored_circuits
125
        mock_settings.WAIT_FOR_OLD_PATH = -1
126
        evc1 = MagicMock()
127
        evc1.is_enabled.return_value = True
128
        evc1.is_active.return_value = False
129
        evc1.lock.locked.return_value = False
130
        evc1.check_traces.return_value = True
131
        evc2 = MagicMock()
132
        evc2.is_enabled.return_value = True
133
        evc2.is_active.return_value = False
134
        evc2.lock.locked.return_value = False
135
        evc2.check_traces.return_value = False
136
        self.napp.circuits = {'1': evc1, '2': evc2}
137
138
        self.napp.execute_consistency()
139
        self.assertEqual(evc1.activate.call_count, 1)
140
        self.assertEqual(evc1.sync.call_count, 1)
141
        self.assertEqual(evc2.deploy.call_count, 1)
142
        mock_load_evc.assert_called_with(stored_circuits['3'])
143
144
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
145
    @patch('napps.kytos.mef_eline.models.evc.EVCBase._validate')
146
    def test_evc_from_dict(self, _validate_mock, uni_from_dict_mock):
147
        """
148
        Test the helper method that create an EVN from dict.
149
150
        Verify object creation with circuit data and schedule data.
151
        """
152
        _validate_mock.return_value = True
153
        uni_from_dict_mock.side_effect = ['uni_a', 'uni_z']
154
        payload = {
155
            "name": "my evc1",
156
            "uni_a": {
157
                "interface_id": "00:00:00:00:00:00:00:01:1",
158
                "tag": {
159
                    "tag_type": 1,
160
                    "value": 80
161
                }
162
            },
163
            "uni_z": {
164
                "interface_id": "00:00:00:00:00:00:00:02:2",
165
                "tag": {
166
                    "tag_type": 1,
167
                    "value": 1
168
                }
169
            },
170
            "circuit_scheduler": [{
171
                "frequency": "* * * * *",
172
                "action": "create"
173
            }],
174
            "queue_id": 5
175
        }
176
        # pylint: disable=protected-access
177
        evc_response = self.napp._evc_from_dict(payload)
178
        self.assertIsNotNone(evc_response)
179
        self.assertIsNotNone(evc_response.uni_a)
180
        self.assertIsNotNone(evc_response.uni_z)
181
        self.assertIsNotNone(evc_response.circuit_scheduler)
182
        self.assertIsNotNone(evc_response.name)
183
        self.assertIsNotNone(evc_response.queue_id)
184
185
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
186
    @patch('napps.kytos.mef_eline.models.evc.EVCBase._validate')
187
    @patch('kytos.core.Controller.get_interface_by_id')
188
    def test_evc_from_dict_paths(self, _get_interface_by_id_mock,
189
                                 _validate_mock, uni_from_dict_mock):
190
        """
191
        Test the helper method that create an EVN from dict.
192
193
        Verify object creation with circuit data and schedule data.
194
        """
195
        _get_interface_by_id_mock.return_value = True
196
        _validate_mock.return_value = True
197
        uni_from_dict_mock.side_effect = ['uni_a', 'uni_z']
198
        payload = {
199
            "name": "my evc1",
200
            "uni_a": {
201
                "interface_id": "00:00:00:00:00:00:00:01:1",
202
                "tag": {
203
                    "tag_type": 1,
204
                    "value": 80
205
                }
206
            },
207
            "uni_z": {
208
                "interface_id": "00:00:00:00:00:00:00:02:2",
209
                "tag": {
210
                    "tag_type": 1,
211
                    "value": 1
212
                }
213
            },
214
            "current_path": [],
215
            "primary_path": [
216
                {"endpoint_a": {"interface_id": "00:00:00:00:00:00:00:01:1"},
217
                 "endpoint_b": {"interface_id": "00:00:00:00:00:00:00:02:2"}}
218
            ],
219
            "backup_path": []
220
        }
221
222
        # pylint: disable=protected-access
223
        evc_response = self.napp._evc_from_dict(payload)
224
        self.assertIsNotNone(evc_response)
225
        self.assertIsNotNone(evc_response.uni_a)
226
        self.assertIsNotNone(evc_response.uni_z)
227
        self.assertIsNotNone(evc_response.circuit_scheduler)
228
        self.assertIsNotNone(evc_response.name)
229
        self.assertEqual(len(evc_response.current_path), 0)
230
        self.assertEqual(len(evc_response.backup_path), 0)
231
        self.assertEqual(len(evc_response.primary_path), 1)
232
233
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
234
    @patch('napps.kytos.mef_eline.models.evc.EVCBase._validate')
235
    @patch('kytos.core.Controller.get_interface_by_id')
236
    def test_evc_from_dict_links(self, _get_interface_by_id_mock,
237
                                 _validate_mock, uni_from_dict_mock):
238
        """
239
        Test the helper method that create an EVN from dict.
240
241
        Verify object creation with circuit data and schedule data.
242
        """
243
        _get_interface_by_id_mock.return_value = True
244
        _validate_mock.return_value = True
245
        uni_from_dict_mock.side_effect = ['uni_a', 'uni_z']
246
        payload = {
247
            "name": "my evc1",
248
            "uni_a": {
249
                "interface_id": "00:00:00:00:00:00:00:01:1",
250
                "tag": {
251
                    "tag_type": 1,
252
                    "value": 80
253
                }
254
            },
255
            "uni_z": {
256
                "interface_id": "00:00:00:00:00:00:00:02:2",
257
                "tag": {
258
                    "tag_type": 1,
259
                    "value": 1
260
                }
261
            },
262
            "primary_links": [
263
                {"endpoint_a": {"interface_id": "00:00:00:00:00:00:00:01:1"},
264
                 "endpoint_b": {"interface_id": "00:00:00:00:00:00:00:02:2"}}
265
            ],
266
            "backup_links": []
267
        }
268
269
        # pylint: disable=protected-access
270
        evc_response = self.napp._evc_from_dict(payload)
271
        self.assertIsNotNone(evc_response)
272
        self.assertIsNotNone(evc_response.uni_a)
273
        self.assertIsNotNone(evc_response.uni_z)
274
        self.assertIsNotNone(evc_response.circuit_scheduler)
275
        self.assertIsNotNone(evc_response.name)
276
        self.assertEqual(len(evc_response.current_links_cache), 0)
277
        self.assertEqual(len(evc_response.backup_links), 0)
278
        self.assertEqual(len(evc_response.primary_links), 1)
279
280
    def test_list_without_circuits(self):
281
        """Test if list circuits return 'no circuit stored.'."""
282
        api = self.get_app_test_client(self.napp)
283
        url = f'{self.server_name_url}/v2/evc/'
284
        response = api.get(url)
285
        self.assertEqual(response.status_code, 200, response.data)
286
        self.assertEqual(json.loads(response.data.decode()), {})
287
288
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
289
    def test_list_no_circuits_stored(self, storehouse_data_mock):
290
        """Test if list circuits return all circuits stored."""
291
        circuits = {}
292
        storehouse_data_mock.return_value = circuits
293
294
        api = self.get_app_test_client(self.napp)
295
        url = f'{self.server_name_url}/v2/evc/'
296
297
        response = api.get(url)
298
        expected_result = circuits
299
        self.assertEqual(json.loads(response.data), expected_result)
300
301
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
302
    def test_list_with_circuits_stored(self, storehouse_data_mock):
303
        """Test if list circuits return all circuits stored."""
304
        circuits = {'1': {'name': 'circuit_1'},
305
                    '2': {'name': 'circuit_2'}}
306
        storehouse_data_mock.return_value = circuits
307
308
        api = self.get_app_test_client(self.napp)
309
        url = f'{self.server_name_url}/v2/evc/'
310
311
        response = api.get(url)
312
        expected_result = circuits
313
        self.assertEqual(json.loads(response.data), expected_result)
314
315 View Code Duplication
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
316
    def test_list_with_archived_circuits_stored_1(self, storehouse_data_mock):
317
        """Test if list circuits return only circuits not archived."""
318
        circuits = {'1': {'name': 'circuit_1'},
319
                    '2': {'name': 'circuit_2', 'archived': True}}
320
        storehouse_data_mock.return_value = circuits
321
322
        api = self.get_app_test_client(self.napp)
323
        url = f'{self.server_name_url}/v2/evc/'
324
325
        response = api.get(url)
326
        expected_result = {'1': circuits['1']}
327
        self.assertEqual(json.loads(response.data), expected_result)
328
329 View Code Duplication
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
330
    def test_list_with_archived_circuits_stored_2(self, storehouse_data_mock):
331
        """Test if list circuits return all circuits."""
332
        circuits = {'1': {'name': 'circuit_1'},
333
                    '2': {'name': 'circuit_2', 'archived': True}}
334
        storehouse_data_mock.return_value = circuits
335
336
        api = self.get_app_test_client(self.napp)
337
        url = f'{self.server_name_url}/v2/evc/?archived=True'
338
339
        response = api.get(url)
340
        expected_result = circuits
341
        self.assertEqual(json.loads(response.data), expected_result)
342
343 View Code Duplication
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
344
    def test_circuit_with_valid_id(self, storehouse_data_mock):
345
        """Test if get_circuit return the circuit attributes."""
346
        circuits = {'1': {'name': 'circuit_1'},
347
                    '2': {'name': 'circuit_2'}}
348
        storehouse_data_mock.return_value = circuits
349
350
        api = self.get_app_test_client(self.napp)
351
        url = f'{self.server_name_url}/v2/evc/1'
352
        response = api.get(url)
353
        expected_result = circuits['1']
354
        self.assertEqual(json.loads(response.data), expected_result)
355
356 View Code Duplication
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
357
    def test_circuit_with_invalid_id(self, storehouse_data_mock):
358
        """Test if get_circuit return invalid circuit_id."""
359
        circuits = {'1': {'name': 'circuit_1'},
360
                    '2': {'name': 'circuit_2'}}
361
        storehouse_data_mock.return_value = circuits
362
363
        api = self.get_app_test_client(self.napp)
364
        url = f'{self.server_name_url}/v2/evc/3'
365
        response = api.get(url)
366
        expected_result = 'circuit_id 3 not found'
367
        self.assertEqual(json.loads(response.data)['description'],
368
                         expected_result)
369
370
    @patch('napps.kytos.mef_eline.models.evc.EVC.deploy')
371
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
372
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
373
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
374
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
375
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
376
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
377
    def test_create_a_circuit_case_1(self, *args):
378
        """Test create a new circuit."""
379
        # pylint: disable=too-many-locals
380
        (validate_mock, evc_as_dict_mock, save_evc_mock,
381
         uni_from_dict_mock, sched_add_mock, storehouse_data_mock,
382
         evc_deploy_mock) = args
383
384
        validate_mock.return_value = True
385
        save_evc_mock.return_value = True
386
        evc_deploy_mock.return_value = True
387
        uni1 = create_autospec(UNI)
388
        uni2 = create_autospec(UNI)
389
        uni1.interface = create_autospec(Interface)
390
        uni2.interface = create_autospec(Interface)
391
        uni1.interface.switch = '00:00:00:00:00:00:00:01'
392
        uni2.interface.switch = '00:00:00:00:00:00:00:02'
393
        uni_from_dict_mock.side_effect = [uni1, uni2]
394
        evc_as_dict_mock.return_value = {}
395
        sched_add_mock.return_value = True
396
        storehouse_data_mock.return_value = {}
397
398
        api = self.get_app_test_client(self.napp)
399
        url = f'{self.server_name_url}/v2/evc/'
400
        payload = {
401
                   "name": "my evc1",
402
                   "frequency": "* * * * *",
403
                   "uni_a": {
404
                     "interface_id": "00:00:00:00:00:00:00:01:1",
405
                     "tag": {
406
                       "tag_type": 1,
407
                       "value": 80
408
                     }
409
                   },
410
                   "uni_z": {
411
                     "interface_id": "00:00:00:00:00:00:00:02:2",
412
                     "tag": {
413
                       "tag_type": 1,
414
                       "value": 1
415
                     }
416
                   },
417
                   "dynamic_backup_path": True
418
                 }
419
420
        response = api.post(url, data=json.dumps(payload),
421
                            content_type='application/json')
422
        current_data = json.loads(response.data)
423
424
        # verify expected result from request
425
        self.assertEqual(201, response.status_code, response.data)
426
        self.assertIn('circuit_id', current_data)
427
428
        # verify uni called
429
        uni_from_dict_mock.called_twice()
430
        uni_from_dict_mock.assert_any_call(payload['uni_z'])
431
        uni_from_dict_mock.assert_any_call(payload['uni_a'])
432
433
        # verify validation called
434
        validate_mock.assert_called_once()
435
        validate_mock.assert_called_with(frequency='* * * * *',
436
                                         name='my evc1',
437
                                         uni_a=uni1,
438
                                         uni_z=uni2,
439
                                         dynamic_backup_path=True)
440
        # verify save method is called
441
        save_evc_mock.assert_called_once()
442
443
        # verify evc as dict is called to save in the box
444
        evc_as_dict_mock.assert_called_once()
445
        # verify add circuit in sched
446
        sched_add_mock.assert_called_once()
447
448
    @staticmethod
449
    def get_napp_urls(napp):
450
        """Return the kytos/mef_eline urls.
451
452
        The urls will be like:
453
454
        urls = [
455
            (options, methods, url)
456
        ]
457
458
        """
459
        controller = napp.controller
460
        controller.api_server.register_napp_endpoints(napp)
461
462
        urls = []
463
        for rule in controller.api_server.app.url_map.iter_rules():
464
            options = {}
465
            for arg in rule.arguments:
466
                options[arg] = "[{0}]".format(arg)
467
468
            if f'{napp.username}/{napp.name}' in str(rule):
469
                urls.append((options, rule.methods, f'{str(rule)}'))
470
471
        return urls
472
473
    @staticmethod
474
    def get_app_test_client(napp):
475
        """Return a flask api test client."""
476
        napp.controller.api_server.register_napp_endpoints(napp)
477
        return napp.controller.api_server.app.test_client()
478
479
    def test_create_a_circuit_case_2(self):
480
        """Test create a new circuit trying to send request without a json."""
481
        api = self.get_app_test_client(self.napp)
482
        url = f'{self.server_name_url}/v2/evc/'
483
484
        response = api.post(url)
485
        current_data = json.loads(response.data)
486
        expected_data = 'The request body mimetype is not application/json.'
487
488
        self.assertEqual(415, response.status_code, response.data)
489
        self.assertEqual(current_data['description'], expected_data)
490
491
    def test_create_a_circuit_case_3(self):
492
        """Test create a new circuit trying to send request with an
493
           invalid json."""
494
        api = self.get_app_test_client(self.napp)
495
        url = f'{self.server_name_url}/v2/evc/'
496
497
        response = api.post(url, data='This is an {Invalid:} JSON',
498
                            content_type='application/json')
499
        current_data = json.loads(response.data)
500
        expected_data = 'The request body is not a well-formed JSON.'
501
502
        self.assertEqual(400, response.status_code, response.data)
503
        self.assertEqual(current_data['description'], expected_data)
504
505
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
506
    def test_create_a_circuit_case_4(self, uni_from_dict_mock):
507
        """Test create a new circuit trying to send request with an
508
           invalid value."""
509
        # pylint: disable=too-many-locals
510
        uni_from_dict_mock.side_effect = ValueError('Could not instantiate')
511
        api = self.get_app_test_client(self.napp)
512
        url = f'{self.server_name_url}/v2/evc/'
513
514
        payload = {
515
                   "name": "my evc1",
516
                   "frequency": "* * * * *",
517
                   "uni_a": {
518
                     "interface_id": "00:00:00:00:00:00:00:01:76",
519
                     "tag": {
520
                       "tag_type": 1,
521
                       "value": 80
522
                     }
523
                   },
524
                   "uni_z": {
525
                     "interface_id": "00:00:00:00:00:00:00:02:2",
526
                     "tag": {
527
                       "tag_type": 1,
528
                       "value": 1
529
                     }
530
                   }
531
                 }
532
533
        response = api.post(url, data=json.dumps(payload),
534
                            content_type='application/json')
535
        current_data = json.loads(response.data)
536
        expected_data = 'Error creating UNI: Could not instantiate'
537
538
        self.assertEqual(400, response.status_code, response.data)
539
        self.assertEqual(current_data['description'], expected_data)
540
541
    @patch('napps.kytos.mef_eline.models.evc.EVC.deploy')
542
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
543
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
544
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
545
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
546
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
547
    def test_create_circuit_already_enabled(self, *args):
548
        """Test create an already created circuit."""
549
        # pylint: disable=too-many-locals
550
        (evc_as_dict_mock, validate_mock, save_evc_mock,
551
         uni_from_dict_mock, sched_add_mock, evc_deploy_mock) = args
552
553
        validate_mock.return_value = True
554
        save_evc_mock.return_value = True
555
        sched_add_mock.return_value = True
556
        evc_deploy_mock.return_value = True
557
        uni1 = create_autospec(UNI)
558
        uni2 = create_autospec(UNI)
559
        uni1.interface = create_autospec(Interface)
560
        uni2.interface = create_autospec(Interface)
561
        uni1.interface.switch = '00:00:00:00:00:00:00:01'
562
        uni2.interface.switch = '00:00:00:00:00:00:00:02'
563
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
564
565
        api = self.get_app_test_client(self.napp)
566
        payload = {
567
            "name": "my evc1",
568
            "uni_a": {
569
                "interface_id": "00:00:00:00:00:00:00:01:1",
570
                "tag": {
571
                    "tag_type": 1,
572
                    "value": 80
573
                }
574
            },
575
            "uni_z": {
576
                "interface_id": "00:00:00:00:00:00:00:02:2",
577
                "tag": {
578
                    "tag_type": 1,
579
                    "value": 1
580
                }
581
            },
582
            "dynamic_backup_path": True
583
        }
584
585
        evc_as_dict_mock.return_value = payload
586
        response = api.post(f'{self.server_name_url}/v2/evc/',
587
                            data=json.dumps(payload),
588
                            content_type='application/json')
589
        self.assertEqual(201, response.status_code)
590
591
        response = api.post(f'{self.server_name_url}/v2/evc/',
592
                            data=json.dumps(payload),
593
                            content_type='application/json')
594
        current_data = json.loads(response.data)
595
        expected_data = 'The EVC already exists.'
596
        self.assertEqual(current_data['description'], expected_data)
597
        self.assertEqual(409, response.status_code)
598
599
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
600
    def test_create_circuit_case_5(self, uni_from_dict_mock):
601
        """Test when neither primary path nor dynamic_backup_path is set."""
602
        api = self.get_app_test_client(self.napp)
603
        url = f'{self.server_name_url}/v2/evc/'
604
        uni1 = create_autospec(UNI)
605
        uni2 = create_autospec(UNI)
606
        uni1.interface = create_autospec(Interface)
607
        uni2.interface = create_autospec(Interface)
608
        uni1.interface.switch = '00:00:00:00:00:00:00:01'
609
        uni2.interface.switch = '00:00:00:00:00:00:00:02'
610
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
611
612
        payload = {
613
                   "name": "my evc1",
614
                   "frequency": "* * * * *",
615
                   "uni_a": {
616
                     "interface_id": "00:00:00:00:00:00:00:01:1",
617
                     "tag": {
618
                       "tag_type": 1,
619
                       "value": 80
620
                     }
621
                   },
622
                   "uni_z": {
623
                     "interface_id": "00:00:00:00:00:00:00:02:2",
624
                     "tag": {
625
                       "tag_type": 1,
626
                       "value": 1
627
                     }
628
                   }
629
                 }
630
631
        response = api.post(url, data=json.dumps(payload),
632
                            content_type='application/json')
633
        current_data = json.loads(response.data)
634
        expected = 'The EVC must have a primary path or allow dynamic paths.'
635
636
        self.assertEqual(400, response.status_code, response.data)
637
        self.assertEqual(current_data['description'], expected)
638
639
    def test_redeploy_evc(self):
640
        """Test endpoint to redeploy an EVC."""
641
        evc1 = MagicMock()
642
        evc1.is_enabled.return_value = True
643
        self.napp.circuits = {'1': evc1,
644
                              '2': MagicMock()}
645
        api = self.get_app_test_client(self.napp)
646
        url = f'{self.server_name_url}/v2/evc/1/redeploy'
647
        response = api.patch(url)
648
        self.assertEqual(response.status_code, 202, response.data)
649
650
    def test_redeploy_evc_disabled(self):
651
        """Test endpoint to redeploy an EVC."""
652
        evc1 = MagicMock()
653
        evc1.is_enabled.return_value = False
654
        self.napp.circuits = {'1': evc1,
655
                              '2': MagicMock()}
656
        api = self.get_app_test_client(self.napp)
657
        url = f'{self.server_name_url}/v2/evc/1/redeploy'
658
        response = api.patch(url)
659
        self.assertEqual(response.status_code, 409, response.data)
660
661
    def test_redeploy_evc_deleted(self):
662
        """Test endpoint to redeploy an EVC."""
663
        evc1 = MagicMock()
664
        evc1.is_enabled.return_value = True
665
        self.napp.circuits = {'1': evc1,
666
                              '2': MagicMock()}
667
        api = self.get_app_test_client(self.napp)
668
        url = f'{self.server_name_url}/v2/evc/3/redeploy'
669
        response = api.patch(url)
670
        self.assertEqual(response.status_code, 404, response.data)
671
672
    def test_list_schedules__no_data(self):
673
        """Test list of schedules."""
674
        api = self.get_app_test_client(self.napp)
675
        url = f'{self.server_name_url}/v2/evc/schedule'
676
        response = api.get(url)
677
        self.assertEqual(response.status_code, 200, response.data)
678
        self.assertEqual(json.loads(response.data.decode()), {})
679
680
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
681
    def test_list_schedules__no_data_stored(self, storehouse_data_mock):
682
        """Test if list circuits return all circuits stored."""
683
        circuits = {}
684
        storehouse_data_mock.return_value = circuits
685
686
        api = self.get_app_test_client(self.napp)
687
        url = f'{self.server_name_url}/v2/evc/schedule'
688
689
        response = api.get(url)
690
        expected_result = circuits
691
692
        self.assertEqual(response.status_code, 200, response.data)
693
        self.assertEqual(json.loads(response.data), expected_result)
694
695
    # pylint: disable=no-self-use
696
    def _add_storehouse_schedule_data(self, storehouse_data_mock):
697
        """Add schedule data to storehouse mock object."""
698
        circuits = {}
699
        payload_1 = {
700
            "id": "aa:aa:aa",
701
            "name": "my evc1",
702
            "uni_a": {
703
                "interface_id": "00:00:00:00:00:00:00:01:1",
704
                "tag": {
705
                    "tag_type": 1,
706
                    "value": 80
707
                }
708
            },
709
            "uni_z": {
710
                "interface_id": "00:00:00:00:00:00:00:02:2",
711
                "tag": {
712
                    "tag_type": 1,
713
                    "value": 1
714
                }
715
            },
716
            "circuit_scheduler": [
717
                {
718
                    "id": "1",
719
                    "frequency": "* * * * *",
720
                    "action": "create"
721
                },
722
                {
723
                    "id": "2",
724
                    "frequency": "1 * * * *",
725
                    "action": "remove"
726
                }
727
            ]
728
        }
729
        circuits.update({"aa:aa:aa": payload_1})
730
        payload_2 = {
731
            "id": "bb:bb:bb",
732
            "name": "my second evc2",
733
            "uni_a": {
734
                "interface_id": "00:00:00:00:00:00:00:01:2",
735
                "tag": {
736
                    "tag_type": 1,
737
                    "value": 90
738
                }
739
            },
740
            "uni_z": {
741
                "interface_id": "00:00:00:00:00:00:00:03:2",
742
                "tag": {
743
                    "tag_type": 1,
744
                    "value": 100
745
                }
746
            },
747
            "circuit_scheduler": [
748
                {
749
                    "id": "3",
750
                    "frequency": "1 * * * *",
751
                    "action": "create"
752
                },
753
                {
754
                    "id": "4",
755
                    "frequency": "2 * * * *",
756
                    "action": "remove"
757
                }
758
            ]
759
        }
760
        circuits.update({"bb:bb:bb": payload_2})
761
        payload_3 = {
762
            "id": "cc:cc:cc",
763
            "name": "my third evc3",
764
            "uni_a": {
765
                "interface_id": "00:00:00:00:00:00:00:03:1",
766
                "tag": {
767
                    "tag_type": 1,
768
                    "value": 90
769
                }
770
            },
771
            "uni_z": {
772
                "interface_id": "00:00:00:00:00:00:00:04:2",
773
                "tag": {
774
                    "tag_type": 1,
775
                    "value": 100
776
                }
777
            }
778
        }
779
        circuits.update({"cc:cc:cc": payload_3})
780
        # Add one circuit to the storehouse.
781
        storehouse_data_mock.return_value = circuits
782
783
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
784
    def test_list_schedules_from_storehouse(self, storehouse_data_mock):
785
        """Test if list circuits return specific circuits stored."""
786
        self._add_storehouse_schedule_data(storehouse_data_mock)
787
788
        api = self.get_app_test_client(self.napp)
789
        url = f'{self.server_name_url}/v2/evc/schedule'
790
791
        # Call URL
792
        response = api.get(url)
793
        # Expected JSON data from response
794
        expected = [{'circuit_id': 'aa:aa:aa',
795
                     'schedule': {'action': 'create',
796
                                  'frequency': '* * * * *', 'id': '1'},
797
                     'schedule_id': '1'},
798
                    {'circuit_id': 'aa:aa:aa',
799
                     'schedule': {'action': 'remove',
800
                                  'frequency': '1 * * * *', 'id': '2'},
801
                     'schedule_id': '2'},
802
                    {'circuit_id': 'bb:bb:bb',
803
                     'schedule': {'action': 'create',
804
                                  'frequency': '1 * * * *', 'id': '3'},
805
                     'schedule_id': '3'},
806
                    {'circuit_id': 'bb:bb:bb',
807
                     'schedule': {'action': 'remove',
808
                                  'frequency': '2 * * * *', 'id': '4'},
809
                     'schedule_id': '4'}]
810
811
        self.assertEqual(response.status_code, 200, response.data)
812
        self.assertEqual(expected, json.loads(response.data))
813
814
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
815
    def test_get_specific_schedule_from_storehouse(self, storehouse_data_mock):
816
        """Test get schedules from a circuit."""
817
        self._add_storehouse_schedule_data(storehouse_data_mock)
818
819
        requested_circuit_id = "bb:bb:bb"
820
        api = self.get_app_test_client(self.napp)
821
        url = f'{self.server_name_url}/v2/evc/{requested_circuit_id}'
822
823
        # Call URL
824
        response = api.get(url)
825
826
        # Expected JSON data from response
827
        expected = [{'action': 'create', 'frequency': '1 * * * *', 'id': '3'},
828
                    {'action': 'remove', 'frequency': '2 * * * *', 'id': '4'}]
829
830
        self.assertEqual(response.status_code, 200)
831
        self.assertEqual(expected,
832
                         json.loads(response.data)["circuit_scheduler"])
833
834
    def test_get_specific_schedules_from_storehouse_not_found(self):
835
        """Test get specific schedule ID that does not exist."""
836
        requested_id = "blah"
837
        api = self.get_app_test_client(self.napp)
838
        url = f'{self.server_name_url}/v2/evc/{requested_id}'
839
840
        # Call URL
841
        response = api.get(url)
842
843
        expected = 'circuit_id blah not found'
844
        # Assert response not found
845
        self.assertEqual(response.status_code, 404, response.data)
846
        self.assertEqual(expected, json.loads(response.data)['description'])
847
848
    def _uni_from_dict_side_effect(self, uni_dict):
849
        interface_id = uni_dict.get("interface_id")
850
        tag_dict = uni_dict.get("tag")
851
        interface = Interface(interface_id, "0", "switch")
852
        return UNI(interface, tag_dict)
853
854
    @patch('apscheduler.schedulers.background.BackgroundScheduler.add_job')
855
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
856
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
857
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
858
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
859
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
860
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
861
    def test_create_schedule(self, *args):  # pylint: disable=too-many-locals
862
        """Test create a circuit schedule."""
863
        (validate_mock, evc_as_dict_mock, save_evc_mock,
864
         uni_from_dict_mock, sched_add_mock, storehouse_data_mock,
865
         scheduler_add_job_mock) = args
866
867
        validate_mock.return_value = True
868
        save_evc_mock.return_value = True
869
        uni_from_dict_mock.side_effect = self._uni_from_dict_side_effect
870
        evc_as_dict_mock.return_value = {}
871
        sched_add_mock.return_value = True
872
        storehouse_data_mock.return_value = {}
873
874
        self._add_storehouse_schedule_data(storehouse_data_mock)
875
876
        requested_id = "bb:bb:bb"
877
        api = self.get_app_test_client(self.napp)
878
        url = f'{self.server_name_url}/v2/evc/schedule/'
879
880
        payload = {
881
              "circuit_id": requested_id,
882
              "schedule": {
883
                "frequency": "1 * * * *",
884
                "action": "create"
885
              }
886
            }
887
888
        # Call URL
889
        response = api.post(url, data=json.dumps(payload),
890
                            content_type='application/json')
891
892
        response_json = json.loads(response.data)
893
894
        self.assertEqual(response.status_code, 201, response.data)
895
        scheduler_add_job_mock.assert_called_once()
896
        save_evc_mock.assert_called_once()
897
        self.assertEqual(payload["schedule"]["frequency"],
898
                         response_json["frequency"])
899
        self.assertEqual(payload["schedule"]["action"],
900
                         response_json["action"])
901
        self.assertIsNotNone(response_json["id"])
902
903
    @patch('apscheduler.schedulers.background.BackgroundScheduler.remove_job')
904
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
905
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
906
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
907
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
908
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
909
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
910
    def test_update_schedule(self, *args):  # pylint: disable=too-many-locals
911
        """Test create a circuit schedule."""
912
        (validate_mock, evc_as_dict_mock, save_evc_mock,
913
         uni_from_dict_mock, sched_add_mock, storehouse_data_mock,
914
         scheduler_remove_job_mock) = args
915
916
        storehouse_payload_1 = {
917
            "aa:aa:aa": {
918
                "id": "aa:aa:aa",
919
                "name": "my evc1",
920
                "uni_a": {
921
                    "interface_id": "00:00:00:00:00:00:00:01:1",
922
                    "tag": {
923
                        "tag_type": 1,
924
                        "value": 80
925
                    }
926
                },
927
                "uni_z": {
928
                    "interface_id": "00:00:00:00:00:00:00:02:2",
929
                    "tag": {
930
                        "tag_type": 1,
931
                        "value": 1
932
                    }
933
                },
934
                "circuit_scheduler": [{
935
                    "id": "1",
936
                    "frequency": "* * * * *",
937
                    "action": "create"
938
                }
939
                ]
940
            }
941
        }
942
943
        validate_mock.return_value = True
944
        save_evc_mock.return_value = True
945
        sched_add_mock.return_value = True
946
        uni_from_dict_mock.side_effect = ['uni_a', 'uni_z']
947
        evc_as_dict_mock.return_value = {}
948
        storehouse_data_mock.return_value = storehouse_payload_1
949
        scheduler_remove_job_mock.return_value = True
950
951
        requested_schedule_id = "1"
952
        api = self.get_app_test_client(self.napp)
953
        url = f'{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}'
954
955
        payload = {
956
            "frequency": "*/1 * * * *",
957
            "action": "create"
958
        }
959
960
        # Call URL
961
        response = api.patch(url, data=json.dumps(payload),
962
                             content_type='application/json')
963
964
        response_json = json.loads(response.data)
965
966
        self.assertEqual(response.status_code, 200, response.data)
967
        scheduler_remove_job_mock.assert_called_once()
968
        save_evc_mock.assert_called_once()
969
        self.assertEqual(payload["frequency"], response_json["frequency"])
970
        self.assertEqual(payload["action"], response_json["action"])
971
        self.assertIsNotNone(response_json["id"])
972
973
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
974
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
975
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
976
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
977
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
978
    def test_update_schedule_archived(self, *args):
979
        """Test create a circuit schedule."""
980
        # pylint: disable=too-many-locals
981
        (validate_mock, evc_as_dict_mock,
982
         uni_from_dict_mock, sched_add_mock, storehouse_data_mock) = args
983
984
        storehouse_payload_1 = {
985
            "aa:aa:aa": {
986
                "id": "aa:aa:aa",
987
                "name": "my evc1",
988
                "archived": True,
989
                "circuit_scheduler": [{
990
                    "id": "1",
991
                    "frequency": "* * * * *",
992
                    "action": "create"
993
                }
994
                ]
995
            }
996
        }
997
998
        validate_mock.return_value = True
999
        sched_add_mock.return_value = True
1000
        uni_from_dict_mock.side_effect = ['uni_a', 'uni_z']
1001
        evc_as_dict_mock.return_value = {}
1002
        storehouse_data_mock.return_value = storehouse_payload_1
1003
1004
        requested_schedule_id = "1"
1005
        api = self.get_app_test_client(self.napp)
1006
        url = f'{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}'
1007
1008
        payload = {
1009
            "frequency": "*/1 * * * *",
1010
            "action": "create"
1011
        }
1012
1013
        # Call URL
1014
        response = api.patch(url, data=json.dumps(payload),
1015
                             content_type='application/json')
1016
1017
        self.assertEqual(response.status_code, 403, response.data)
1018
1019
    @patch('apscheduler.schedulers.background.BackgroundScheduler.remove_job')
1020
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
1021
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1022
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
1023
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1024
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1025
    def test_delete_schedule(self, *args):
1026
        """Test create a circuit schedule."""
1027
        (validate_mock, evc_as_dict_mock, save_evc_mock,
1028
         uni_from_dict_mock, storehouse_data_mock,
1029
         scheduler_remove_job_mock) = args
1030
1031
        storehouse_payload_1 = {
1032
            "2": {
1033
                "id": "2",
1034
                "name": "my evc1",
1035
                "uni_a": {
1036
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1037
                    "tag": {
1038
                        "tag_type": 1,
1039
                        "value": 80
1040
                    }
1041
                },
1042
                "uni_z": {
1043
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1044
                    "tag": {
1045
                        "tag_type": 1,
1046
                        "value": 1
1047
                    }
1048
                },
1049
                "circuit_scheduler": [{
1050
                    "id": "1",
1051
                    "frequency": "* * * * *",
1052
                    "action": "create"
1053
                }]
1054
            }
1055
        }
1056
        validate_mock.return_value = True
1057
        save_evc_mock.return_value = True
1058
        uni_from_dict_mock.side_effect = ['uni_a', 'uni_z']
1059
        evc_as_dict_mock.return_value = {}
1060
        storehouse_data_mock.return_value = storehouse_payload_1
1061
        scheduler_remove_job_mock.return_value = True
1062
1063
        requested_schedule_id = "1"
1064
        api = self.get_app_test_client(self.napp)
1065
        url = f'{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}'
1066
1067
        # Call URL
1068
        response = api.delete(url)
1069
1070
        self.assertEqual(response.status_code, 200, response.data)
1071
        scheduler_remove_job_mock.assert_called_once()
1072
        save_evc_mock.assert_called_once()
1073
        self.assertIn("Schedule removed", f"{response.data}")
1074
1075
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
1076
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1077
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1078
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1079
    def test_delete_schedule_archived(self, *args):
1080
        """Test create a circuit schedule."""
1081
        (validate_mock, evc_as_dict_mock,
1082
         uni_from_dict_mock, storehouse_data_mock) = args
1083
1084
        storehouse_payload_1 = {
1085
            "2": {
1086
                "id": "2",
1087
                "name": "my evc1",
1088
                "archived": True,
1089
                "circuit_scheduler": [{
1090
                    "id": "1",
1091
                    "frequency": "* * * * *",
1092
                    "action": "create"
1093
                }]
1094
            }
1095
        }
1096
1097
        validate_mock.return_value = True
1098
        uni_from_dict_mock.side_effect = ['uni_a', 'uni_z']
1099
        evc_as_dict_mock.return_value = {}
1100
        storehouse_data_mock.return_value = storehouse_payload_1
1101
1102
        requested_schedule_id = "1"
1103
        api = self.get_app_test_client(self.napp)
1104
        url = f'{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}'
1105
1106
        # Call URL
1107
        response = api.delete(url)
1108
1109
        self.assertEqual(response.status_code, 403, response.data)
1110
1111
    @patch('requests.post')
1112
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1113
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
1114
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1115
    @patch('kytos.core.Controller.get_interface_by_id')
1116
    @patch('napps.kytos.mef_eline.models.path.Path.is_valid')
1117
    @patch('napps.kytos.mef_eline.models.evc.EVCDeploy.deploy')
1118
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1119
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1120
    def test_update_circuit(self, *args):
1121
        """Test update a circuit circuit."""
1122
        # pylint: disable=too-many-locals
1123
        (evc_as_dict_mock, uni_from_dict_mock, evc_deploy,
1124
         *mocks, requests_mock) = args
1125
        response = MagicMock()
1126
        response.status_code = 201
1127
        requests_mock.return_value = response
1128
1129
        for mock in mocks:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable mocks does not seem to be defined.
Loading history...
1130
            mock.return_value = True
1131
        unis = [get_uni_mocked(switch_dpid='00:00:00:00:00:00:00:01'),
1132
                get_uni_mocked(switch_dpid='00:00:00:00:00:00:00:02')]
1133
        uni_from_dict_mock.side_effect = 2 * unis
1134
1135
        api = self.get_app_test_client(self.napp)
1136
        payloads = [
1137
            {
1138
                "name": "my evc1",
1139
                "active": True,
1140
                "uni_a": {
1141
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1142
                    "tag": {
1143
                        "tag_type": 1,
1144
                        "value": 80
1145
                    }
1146
                },
1147
                "uni_z": {
1148
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1149
                    "tag": {
1150
                        "tag_type": 1,
1151
                        "value": 1
1152
                    }
1153
                },
1154
                "dynamic_backup_path": True
1155
            },
1156
            {
1157
                "primary_path": [
1158
                    {
1159
                        "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1160
                        "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"}
1161
                    }
1162
                ]
1163
            },
1164
            {
1165
                "priority": 3
1166
            },
1167
            {
1168
                # It works only with 'enable' and not with 'enabled'
1169
                "enable": True
1170
            },
1171
            {
1172
                "name": "my evc1",
1173
                "active": True,
1174
                "enable": True,
1175
                "uni_a": {
1176
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1177
                    "tag": {
1178
                        "tag_type": 1,
1179
                        "value": 80
1180
                    }
1181
                },
1182
                "uni_z": {
1183
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1184
                    "tag": {
1185
                        "tag_type": 1,
1186
                        "value": 1
1187
                    }
1188
                },
1189
                "priority": 3,
1190
                "bandwidth": 1000,
1191
                "dynamic_backup_path": True
1192
            }
1193
        ]
1194
1195
        evc_as_dict_mock.return_value = payloads[0]
1196
        response = api.post(f'{self.server_name_url}/v2/evc/',
1197
                            data=json.dumps(payloads[0]),
1198
                            content_type='application/json')
1199
        self.assertEqual(201, response.status_code)
1200
1201
        evc_deploy.reset_mock()
1202
        evc_as_dict_mock.return_value = payloads[1]
1203
        current_data = json.loads(response.data)
1204
        circuit_id = current_data['circuit_id']
1205
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1206
                             data=json.dumps(payloads[1]),
1207
                             content_type='application/json')
1208
        evc_deploy.assert_called_once()
1209
        self.assertEqual(200, response.status_code)
1210
1211
        evc_deploy.reset_mock()
1212
        evc_as_dict_mock.return_value = payloads[2]
1213
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1214
                             data=json.dumps(payloads[2]),
1215
                             content_type='application/json')
1216
        evc_deploy.assert_not_called()
1217
        self.assertEqual(200, response.status_code)
1218
1219
        evc_deploy.reset_mock()
1220
        evc_as_dict_mock.return_value = payloads[3]
1221
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1222
                             data=json.dumps(payloads[3]),
1223
                             content_type='application/json')
1224
        evc_deploy.assert_called_once()
1225
        self.assertEqual(200, response.status_code)
1226
1227
        evc_deploy.reset_mock()
1228
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1229
                             data='{"priority":5,}',
1230
                             content_type='application/json')
1231
        evc_deploy.assert_not_called()
1232
        self.assertEqual(400, response.status_code)
1233
1234
        evc_deploy.reset_mock()
1235
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1236
                             data=json.dumps(payloads[3]),
1237
                             content_type='application/json')
1238
        evc_deploy.assert_called_once()
1239
        self.assertEqual(200, response.status_code)
1240
1241
        response = api.patch(f'{self.server_name_url}/v2/evc/1234',
1242
                             data=json.dumps(payloads[1]),
1243
                             content_type='application/json')
1244
        current_data = json.loads(response.data)
1245
        expected_data = 'circuit_id 1234 not found'
1246
        self.assertEqual(current_data['description'], expected_data)
1247
        self.assertEqual(404, response.status_code)
1248
1249
        api.delete(f'{self.server_name_url}/v2/evc/{circuit_id}')
1250
        evc_deploy.reset_mock()
1251
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1252
                             data=json.dumps(payloads[1]),
1253
                             content_type='application/json')
1254
        evc_deploy.assert_not_called()
1255
        self.assertEqual(405, response.status_code)
1256
1257 View Code Duplication
    @patch('napps.kytos.mef_eline.models.evc.EVC.deploy')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1258
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1259
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1260
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
1261
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1262
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1263
    def test_update_circuit_invalid_json(self, *args):
1264
        """Test update a circuit circuit."""
1265
        # pylint: disable=too-many-locals
1266
        (evc_as_dict_mock, validate_mock, save_evc_mock,
1267
         uni_from_dict_mock, sched_add_mock, evc_deploy_mock) = args
1268
1269
        validate_mock.return_value = True
1270
        save_evc_mock.return_value = True
1271
        sched_add_mock.return_value = True
1272
        evc_deploy_mock.return_value = True
1273
        uni1 = create_autospec(UNI)
1274
        uni2 = create_autospec(UNI)
1275
        uni1.interface = create_autospec(Interface)
1276
        uni2.interface = create_autospec(Interface)
1277
        uni1.interface.switch = '00:00:00:00:00:00:00:01'
1278
        uni2.interface.switch = '00:00:00:00:00:00:00:02'
1279
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1280
1281
        api = self.get_app_test_client(self.napp)
1282
        payload1 = {
1283
            "name": "my evc1",
1284
            "uni_a": {
1285
                "interface_id": "00:00:00:00:00:00:00:01:1",
1286
                "tag": {
1287
                    "tag_type": 1,
1288
                    "value": 80
1289
                }
1290
            },
1291
            "uni_z": {
1292
                "interface_id": "00:00:00:00:00:00:00:02:2",
1293
                "tag": {
1294
                    "tag_type": 1,
1295
                    "value": 1
1296
                }
1297
            },
1298
            "dynamic_backup_path": True
1299
        }
1300
1301
        payload2 = {
1302
            "dynamic_backup_path": False,
1303
        }
1304
1305
        evc_as_dict_mock.return_value = payload1
1306
        response = api.post(f'{self.server_name_url}/v2/evc/',
1307
                            data=json.dumps(payload1),
1308
                            content_type='application/json')
1309
        self.assertEqual(201, response.status_code)
1310
1311
        evc_as_dict_mock.return_value = payload2
1312
        current_data = json.loads(response.data)
1313
        circuit_id = current_data['circuit_id']
1314
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1315
                             data=payload2,
1316
                             content_type='application/json')
1317
        current_data = json.loads(response.data)
1318
        expected_data = 'The request body is not a well-formed JSON.'
1319
        self.assertEqual(current_data['description'], expected_data)
1320
        self.assertEqual(400, response.status_code)
1321
1322
    @patch('napps.kytos.mef_eline.models.evc.EVC.deploy')
1323
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1324
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1325
    @patch('napps.kytos.mef_eline.main.Main._link_from_dict')
1326
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
1327
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1328
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1329
    @patch('napps.kytos.mef_eline.models.path.Path.is_valid')
1330
    def test_update_circuit_invalid_path(self, *args):
1331
        """Test update a circuit circuit."""
1332
        # pylint: disable=too-many-locals
1333
        (is_valid_mock, evc_as_dict_mock, validate_mock, save_evc_mock,
1334
         link_from_dict_mock, uni_from_dict_mock, sched_add_mock,
1335
         evc_deploy_mock) = args
1336
1337
        is_valid_mock.side_effect = InvalidPath('error')
1338
        validate_mock.return_value = True
1339
        save_evc_mock.return_value = True
1340
        sched_add_mock.return_value = True
1341
        evc_deploy_mock.return_value = True
1342
        link_from_dict_mock.return_value = 1
1343
        uni1 = create_autospec(UNI)
1344
        uni2 = create_autospec(UNI)
1345
        uni1.interface = create_autospec(Interface)
1346
        uni2.interface = create_autospec(Interface)
1347
        uni1.interface.switch = '00:00:00:00:00:00:00:01'
1348
        uni2.interface.switch = '00:00:00:00:00:00:00:02'
1349
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1350
1351
        api = self.get_app_test_client(self.napp)
1352
        payload1 = {
1353
            "name": "my evc1",
1354
            "uni_a": {
1355
                "interface_id": "00:00:00:00:00:00:00:01:1",
1356
                "tag": {
1357
                    "tag_type": 1,
1358
                    "value": 80
1359
                }
1360
            },
1361
            "uni_z": {
1362
                "interface_id": "00:00:00:00:00:00:00:02:2",
1363
                "tag": {
1364
                    "tag_type": 1,
1365
                    "value": 1
1366
                }
1367
            },
1368
            "dynamic_backup_path": True
1369
        }
1370
1371
        payload2 = {
1372
            "primary_path": [
1373
                    {
1374
                        "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1375
                        "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"}
1376
                    }
1377
                ]
1378
        }
1379
1380
        evc_as_dict_mock.return_value = payload1
1381
        response = api.post(f'{self.server_name_url}/v2/evc/',
1382
                            data=json.dumps(payload1),
1383
                            content_type='application/json')
1384
        self.assertEqual(201, response.status_code)
1385
1386
        evc_as_dict_mock.return_value = payload2
1387
        current_data = json.loads(response.data)
1388
        circuit_id = current_data['circuit_id']
1389
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1390
                             data=json.dumps(payload2),
1391
                             content_type='application/json')
1392
        current_data = json.loads(response.data)
1393
        expected_data = 'primary_path is not a valid path: error'
1394
        self.assertEqual(400, response.status_code)
1395
        self.assertEqual(current_data['description'], expected_data)
1396
1397 View Code Duplication
    @patch('napps.kytos.mef_eline.models.evc.EVC.deploy')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1398
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1399
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1400
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
1401
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1402
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1403
    def test_update_evc_no_json_mime(self, *args):
1404
        """Test update a circuit with wrong mimetype."""
1405
        # pylint: disable=too-many-locals
1406
        (evc_as_dict_mock, validate_mock, save_evc_mock,
1407
         uni_from_dict_mock, sched_add_mock, evc_deploy_mock) = args
1408
1409
        validate_mock.return_value = True
1410
        save_evc_mock.return_value = True
1411
        sched_add_mock.return_value = True
1412
        evc_deploy_mock.return_value = True
1413
        uni1 = create_autospec(UNI)
1414
        uni2 = create_autospec(UNI)
1415
        uni1.interface = create_autospec(Interface)
1416
        uni2.interface = create_autospec(Interface)
1417
        uni1.interface.switch = '00:00:00:00:00:00:00:01'
1418
        uni2.interface.switch = '00:00:00:00:00:00:00:02'
1419
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1420
1421
        api = self.get_app_test_client(self.napp)
1422
        payload1 = {
1423
            "name": "my evc1",
1424
            "uni_a": {
1425
                "interface_id": "00:00:00:00:00:00:00:01:1",
1426
                "tag": {
1427
                    "tag_type": 1,
1428
                    "value": 80
1429
                }
1430
            },
1431
            "uni_z": {
1432
                "interface_id": "00:00:00:00:00:00:00:02:2",
1433
                "tag": {
1434
                    "tag_type": 1,
1435
                    "value": 1
1436
                }
1437
            },
1438
            "dynamic_backup_path": True
1439
        }
1440
1441
        payload2 = {
1442
            "dynamic_backup_path": False
1443
        }
1444
1445
        evc_as_dict_mock.return_value = payload1
1446
        response = api.post(f'{self.server_name_url}/v2/evc/',
1447
                            data=json.dumps(payload1),
1448
                            content_type='application/json')
1449
        self.assertEqual(201, response.status_code)
1450
1451
        evc_as_dict_mock.return_value = payload2
1452
        current_data = json.loads(response.data)
1453
        circuit_id = current_data['circuit_id']
1454
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1455
                             data=payload2)
1456
        current_data = json.loads(response.data)
1457
        expected_data = 'The request body mimetype is not application/json.'
1458
        self.assertEqual(current_data['description'], expected_data)
1459
        self.assertEqual(415, response.status_code)
1460
1461
    def test_delete_no_evc(self):
1462
        """Test delete when EVC does not exist."""
1463
        api = self.get_app_test_client(self.napp)
1464
        response = api.delete(f'{self.server_name_url}/v2/evc/123')
1465
        current_data = json.loads(response.data)
1466
        expected_data = 'circuit_id 123 not found'
1467
        self.assertEqual(current_data['description'], expected_data)
1468
        self.assertEqual(404, response.status_code)
1469
1470
    def test_handle_link_up(self):
1471
        """Test handle_link_up method."""
1472
        evc_mock = create_autospec(EVC)
1473
        evc_mock.is_enabled = MagicMock(side_effect=[True, False, True])
1474
        evc_mock.lock = MagicMock()
1475
        type(evc_mock).archived = \
1476
            PropertyMock(side_effect=[True, False, False])
1477
        evcs = [evc_mock, evc_mock, evc_mock]
1478
        event = KytosEvent(name='test', content={'link': 'abc'})
1479
        self.napp.circuits = dict(zip(['1', '2', '3'], evcs))
1480
        self.napp.handle_link_up(event)
1481
        evc_mock.handle_link_up.assert_called_once_with('abc')
1482
1483
    def test_handle_link_down(self):
1484
        """Test handle_link_down method."""
1485
        evc_mock = create_autospec(EVC)
1486
        evc_mock.is_affected_by_link = \
1487
            MagicMock(side_effect=[True, False, True])
1488
        evc_mock.lock = MagicMock()
1489
        evc_mock.handle_link_down = MagicMock(side_effect=[True, True])
1490
        evcs = [evc_mock, evc_mock, evc_mock]
1491
        event = KytosEvent(name='test', content={'link': 'abc'})
1492
        self.napp.circuits = dict(zip(['1', '2', '3'], evcs))
1493
        self.napp.handle_link_down(event)
1494
        evc_mock.handle_link_down.assert_has_calls([call(), call()])
1495
1496
    def test_add_metadata(self):
1497
        """Test method to add metadata"""
1498
        evc_mock = create_autospec(EVC)
1499
        evc_mock.metadata = {}
1500
        evc_mock.id = 1234
1501
        self.napp.circuits = {'1234': evc_mock}
1502
1503
        api = self.get_app_test_client(self.napp)
1504
        payload = {'metadata1': 1, 'metadata2': 2}
1505
        response = api.post(f'{self.server_name_url}/v2/evc/1234/metadata',
1506
                            data=json.dumps(payload),
1507
                            content_type='application/json')
1508
1509
        self.assertEqual(response.status_code, 201)
1510
        evc_mock.extend_metadata.assert_called_with(payload)
1511