Passed
Push — master ( 4fc02b...d65ad0 )
by Antonio
03:34
created

TestMain._add_mongodb_schedule_data()   B

Complexity

Conditions 1

Size

Total Lines 52
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 39
dl 0
loc 52
rs 8.9439
c 0
b 0
f 0
cc 1
nop 2

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

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