Test Failed
Pull Request — master (#174)
by Antonio
03:08
created

build.tests.test_main   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 1271
Duplicated Lines 3.93 %

Importance

Changes 0
Metric Value
eloc 922
dl 50
loc 1271
rs 8.798
c 0
b 0
f 0
wmc 41

35 Methods

Rating   Name   Duplication   Size   Complexity  
A TestMain.test_list_without_circuits() 0 7 1
A TestMain.test_handle_link_up() 0 10 1
A TestMain.test_circuit_with_valid_id() 12 12 1
B TestMain.test_update_circuit() 0 104 2
A TestMain.test_list_no_circuits_stored() 0 12 1
B TestMain.test_create_circuit_already_enabled() 0 54 1
A TestMain.test_evc_from_dict_paths() 0 47 1
A TestMain.test_evc_from_dict() 0 38 1
A TestMain.get_app_test_client() 0 5 1
A TestMain.test_list_with_archived_circuits_stored_1() 13 13 1
A TestMain.test_evc_from_dict_links() 0 46 1
A TestMain.test_list_schedules_from_storehouse() 0 30 1
A TestMain.test_list_with_circuits_stored() 0 13 1
A TestMain.test_get_specific_schedules_from_storehouse_not_found() 0 13 1
B TestMain.test_delete_schedule() 0 55 1
A TestMain.test_list_schedules__no_data() 0 7 1
B TestMain.test_create_a_circuit_case_1() 0 65 1
B TestMain.test_load_circuits_by_interface() 0 189 1
A TestMain.test_update_schedule_archived() 0 45 1
A TestMain.test_handle_link_down() 0 9 1
A TestMain.test_list_with_archived_circuits_stored_2() 13 13 1
A TestMain.test_verify_api_urls() 0 35 1
A TestMain._uni_from_dict_side_effect() 0 5 1
A TestMain.test_delete_schedule_archived() 0 35 1
B TestMain._add_storehouse_schedule_data() 0 86 1
A TestMain.test_circuit_with_invalid_id() 12 12 1
A TestMain.test_create_a_circuit_case_2() 0 11 1
B TestMain.test_create_schedule() 0 48 1
A TestMain.test_get_specific_schedule_from_storehouse() 0 19 1
A TestMain.get_napp_urls() 0 24 4
B TestMain.test_update_circuit_invalid_json() 0 54 1
A TestMain.test_list_schedules__no_data_stored() 0 14 1
A TestMain.test_get_event_listeners() 0 10 2
A TestMain.setUp() 0 10 2
B TestMain.test_update_schedule() 0 69 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like build.tests.test_main often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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