TestMain.test_create_a_circuit_case_1()   B
last analyzed

Complexity

Conditions 1

Size

Total Lines 72
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

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