Passed
Pull Request — master (#321)
by
unknown
03:36
created

build.tests.unit.test_main.test_on_table_enabled()   A

Complexity

Conditions 1

Size

Total Lines 24
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 18
nop 0
dl 0
loc 24
rs 9.5
c 0
b 0
f 0
1
"""Module to test the main napp file."""
2
import json
3
from unittest import TestCase
4
from unittest.mock import (
5
    AsyncMock,
6
    MagicMock,
7
    PropertyMock,
8
    call,
9
    create_autospec,
10
    patch
11
)
12
13
from kytos.core.events import KytosEvent
14
from kytos.core.interface import UNI, Interface
15
from kytos.lib.helpers import get_controller_mock
16
from napps.kytos.mef_eline.exceptions import InvalidPath
17
from napps.kytos.mef_eline.models import EVC
18
from napps.kytos.mef_eline.tests.helpers import get_uni_mocked
19
20
21
async def test_on_table_enabled():
22
    """Test on_table_enabled"""
23
    # pylint: disable=import-outside-toplevel
24
    from napps.kytos.mef_eline.main import Main
25
    controller = get_controller_mock()
26
    controller.buffers.app.aput = AsyncMock()
27
    Main.get_eline_controller = MagicMock()
28
    napp = Main(controller)
29
30
    # Succesfully setting table groups
31
    content = {"mef_eline": {"epl": 2}}
32
    event = KytosEvent(name="kytos/of_multi_table.enable_table",
33
                       content=content)
34
    await napp.on_table_enabled(event)
35
    assert napp.table_group["epl"] == 2
36
    assert napp.table_group["evpl"] == 0
37
    assert controller.buffers.app.aput.call_count == 1
38
39
    # Failure at setting table groups
40
    content = {"mef_eline": {"unknown": 123}}
41
    event = KytosEvent(name="kytos/of_multi_table.enable_table",
42
                       content=content)
43
    await napp.on_table_enabled(event)
44
    assert controller.buffers.app.aput.call_count == 1
45
46
47
# pylint: disable=too-many-public-methods, too-many-lines
48
class TestMain(TestCase):
49
    """Test the Main class."""
50
51
    def setUp(self):
52
        """Execute steps before each tests.
53
54
        Set the server_name_url_url from kytos/mef_eline
55
        """
56
        self.server_name_url = "http://localhost:8181/api/kytos/mef_eline"
57
58
        # The decorator run_on_thread is patched, so methods that listen
59
        # for events do not run on threads while tested.
60
        # Decorators have to be patched before the methods that are
61
        # decorated with them are imported.
62
        patch("kytos.core.helpers.run_on_thread", lambda x: x).start()
63
        # pylint: disable=import-outside-toplevel
64
        from napps.kytos.mef_eline.main import Main
65
        Main.get_eline_controller = MagicMock()
66
        self.addCleanup(patch.stopall)
67
        self.napp = Main(get_controller_mock())
68
69
    def test_get_event_listeners(self):
70
        """Verify all event listeners registered."""
71
        expected_events = [
72
            "kytos/core.shutdown",
73
            "kytos/core.shutdown.kytos/mef_eline",
74
            "kytos/topology.link_up",
75
            "kytos/topology.link_down",
76
        ]
77
        actual_events = self.napp.listeners()
78
79
        for _event in expected_events:
80
            self.assertIn(_event, actual_events, _event)
81
82
    def test_verify_api_urls(self):
83
        """Verify all APIs registered."""
84
        expected_urls = [
85
            ({}, {"POST", "OPTIONS"}, "/api/kytos/mef_eline/v2/evc/"),
86
            ({}, {"OPTIONS", "HEAD", "GET"}, "/api/kytos/mef_eline/v2/evc/"),
87
            (
88
                {"circuit_id": "[circuit_id]"},
89
                {"OPTIONS", "DELETE"},
90
                "/api/kytos/mef_eline/v2/evc/<circuit_id>",
91
            ),
92
            (
93
                {"circuit_id": "[circuit_id]"},
94
                {"OPTIONS", "HEAD", "GET"},
95
                "/api/kytos/mef_eline/v2/evc/<circuit_id>",
96
            ),
97
            (
98
                {"circuit_id": "[circuit_id]"},
99
                {"OPTIONS", "PATCH"},
100
                "/api/kytos/mef_eline/v2/evc/<circuit_id>",
101
            ),
102
            (
103
                {"circuit_id": "[circuit_id]"},
104
                {"OPTIONS", "HEAD", "GET"},
105
                "/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata",
106
            ),
107
            (
108
                {"circuit_id": "[circuit_id]"},
109
                {"OPTIONS", "POST"},
110
                "/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata",
111
            ),
112
            (
113
                {"circuit_id": "[circuit_id]", "key": "[key]"},
114
                {"OPTIONS", "DELETE"},
115
                "/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata/<key>",
116
            ),
117
            (
118
                {"circuit_id": "[circuit_id]"},
119
                {"OPTIONS", "PATCH"},
120
                "/api/kytos/mef_eline/v2/evc/<circuit_id>/redeploy",
121
            ),
122
            (
123
                {},
124
                {"OPTIONS", "DELETE"},
125
                "/api/kytos/mef_eline/v2/evc/metadata",
126
            ),
127
            (
128
                {},
129
                {"OPTIONS", "POST"},
130
                "/api/kytos/mef_eline/v2/evc/metadata",
131
            ),
132
            (
133
                {},
134
                {"OPTIONS", "GET", "HEAD"},
135
                "/api/kytos/mef_eline/v2/evc/schedule",
136
            ),
137
            ({}, {"POST", "OPTIONS"}, "/api/kytos/mef_eline/v2/evc/schedule/"),
138
            (
139
                {"schedule_id": "[schedule_id]"},
140
                {"OPTIONS", "DELETE"},
141
                "/api/kytos/mef_eline/v2/evc/schedule/<schedule_id>",
142
            ),
143
            (
144
                {"schedule_id": "[schedule_id]"},
145
                {"OPTIONS", "PATCH"},
146
                "/api/kytos/mef_eline/v2/evc/schedule/<schedule_id>",
147
            ),
148
        ]
149
        urls = self.get_napp_urls(self.napp)
150
        self.assertEqual(len(expected_urls), len(urls))
151
152
    @patch('napps.kytos.mef_eline.main.log')
153
    @patch('napps.kytos.mef_eline.main.Main.execute_consistency')
154
    def test_execute(self, mock_execute_consistency, mock_log):
155
        """Test execute."""
156
        self.napp.execution_rounds = 0
157
        self.napp.execute()
158
        mock_execute_consistency.assert_called()
159
        self.assertEqual(mock_log.debug.call_count, 2)
160
161
        # Test locked should return
162
        mock_execute_consistency.call_count = 0
163
        mock_log.info.call_count = 0
164
        # pylint: disable=protected-access
165
        self.napp._lock = MagicMock()
166
        self.napp._lock.locked.return_value = True
167
        # pylint: enable=protected-access
168
        self.napp.execute()
169
        mock_execute_consistency.assert_not_called()
170
        mock_log.info.assert_not_called()
171
172
    @patch('napps.kytos.mef_eline.main.settings')
173
    @patch('napps.kytos.mef_eline.main.Main._load_evc')
174
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
175
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.check_list_traces")
176
    def test_execute_consistency(self, mock_check_list_traces, *args):
177
        """Test execute_consistency."""
178
        (mongo_controller_upsert_mock, mock_load_evc, mock_settings) = args
179
180
        stored_circuits = {'1': {'name': 'circuit_1'},
181
                           '2': {'name': 'circuit_2'},
182
                           '3': {'name': 'circuit_3'}}
183
        mongo_controller_upsert_mock.return_value = True
184
        self.napp.mongo_controller.get_circuits.return_value = {
185
            "circuits": stored_circuits
186
        }
187
188
        mock_settings.WAIT_FOR_OLD_PATH = -1
189
        evc1 = MagicMock(id=1, service_level=0, creation_time=1)
190
        evc1.is_enabled.return_value = True
191
        evc1.is_active.return_value = False
192
        evc1.lock.locked.return_value = False
193
        evc1.has_recent_removed_flow.return_value = False
194
        evc1.is_recent_updated.return_value = False
195
        evc1.execution_rounds = 0
196
        evc2 = MagicMock(id=2, service_level=7, creation_time=1)
197
        evc2.is_enabled.return_value = True
198
        evc2.is_active.return_value = False
199
        evc2.lock.locked.return_value = False
200
        evc2.has_recent_removed_flow.return_value = False
201
        evc2.is_recent_updated.return_value = False
202
        evc2.execution_rounds = 0
203
        self.napp.circuits = {'1': evc1, '2': evc2}
204
        assert self.napp.get_evcs_by_svc_level() == [evc2, evc1]
205
206
        mock_check_list_traces.return_value = {
207
                                                1: True,
208
                                                2: False
209
                                            }
210
211
        self.napp.execute_consistency()
212
        self.assertEqual(evc1.activate.call_count, 1)
213
        self.assertEqual(evc1.sync.call_count, 1)
214
        self.assertEqual(evc2.deploy.call_count, 1)
215
        mock_load_evc.assert_called_with(stored_circuits['3'])
216
217
    @patch('napps.kytos.mef_eline.main.settings')
218
    @patch('napps.kytos.mef_eline.main.Main._load_evc')
219
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
220
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.check_list_traces")
221
    def test_execute_consistency_wait_for(self, mock_check_list_traces, *args):
222
        """Test execute and wait for setting."""
223
        (mongo_controller_upsert_mock, _, mock_settings) = args
224
225
        stored_circuits = {'1': {'name': 'circuit_1'}}
226
        mongo_controller_upsert_mock.return_value = True
227
        self.napp.mongo_controller.get_circuits.return_value = {
228
            "circuits": stored_circuits
229
        }
230
231
        mock_settings.WAIT_FOR_OLD_PATH = -1
232
        evc1 = MagicMock(id=1, service_level=0, creation_time=1)
233
        evc1.is_enabled.return_value = True
234
        evc1.is_active.return_value = False
235
        evc1.lock.locked.return_value = False
236
        evc1.has_recent_removed_flow.return_value = False
237
        evc1.is_recent_updated.return_value = False
238
        evc1.execution_rounds = 0
239
        evc1.deploy.call_count = 0
240
        self.napp.circuits = {'1': evc1}
241
        assert self.napp.get_evcs_by_svc_level() == [evc1]
242
        mock_settings.WAIT_FOR_OLD_PATH = 1
243
244
        mock_check_list_traces.return_value = {1: False}
245
246
        self.napp.execute_consistency()
247
        self.assertEqual(evc1.deploy.call_count, 0)
248
        self.napp.execute_consistency()
249
        self.assertEqual(evc1.deploy.call_count, 1)
250
251
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
252
    @patch('napps.kytos.mef_eline.models.evc.EVCBase._validate')
253
    def test_evc_from_dict(self, _validate_mock, uni_from_dict_mock):
254
        """
255
        Test the helper method that create an EVN from dict.
256
257
        Verify object creation with circuit data and schedule data.
258
        """
259
        _validate_mock.return_value = True
260
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
261
        payload = {
262
            "name": "my evc1",
263
            "uni_a": {
264
                "interface_id": "00:00:00:00:00:00:00:01:1",
265
                "tag": {"tag_type": 1, "value": 80},
266
            },
267
            "uni_z": {
268
                "interface_id": "00:00:00:00:00:00:00:02:2",
269
                "tag": {"tag_type": 1, "value": 1},
270
            },
271
            "circuit_scheduler": [
272
                {"frequency": "* * * * *", "action": "create"}
273
            ],
274
            "queue_id": 5,
275
        }
276
        # pylint: disable=protected-access
277
        evc_response = self.napp._evc_from_dict(payload)
278
        self.assertIsNotNone(evc_response)
279
        self.assertIsNotNone(evc_response.uni_a)
280
        self.assertIsNotNone(evc_response.uni_z)
281
        self.assertIsNotNone(evc_response.circuit_scheduler)
282
        self.assertIsNotNone(evc_response.name)
283
        self.assertIsNotNone(evc_response.queue_id)
284
285
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
286
    @patch("napps.kytos.mef_eline.models.evc.EVCBase._validate")
287
    @patch("kytos.core.Controller.get_interface_by_id")
288
    def test_evc_from_dict_paths(
289
        self, _get_interface_by_id_mock, _validate_mock, uni_from_dict_mock
290
    ):
291
        """
292
        Test the helper method that create an EVN from dict.
293
294
        Verify object creation with circuit data and schedule data.
295
        """
296
297
        _get_interface_by_id_mock.return_value = get_uni_mocked().interface
298
        _validate_mock.return_value = True
299
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
300
        payload = {
301
            "name": "my evc1",
302
            "uni_a": {
303
                "interface_id": "00:00:00:00:00:00:00:01:1",
304
                "tag": {"tag_type": 1, "value": 80},
305
            },
306
            "uni_z": {
307
                "interface_id": "00:00:00:00:00:00:00:02:2",
308
                "tag": {"tag_type": 1, "value": 1},
309
            },
310
            "current_path": [],
311
            "primary_path": [
312
                {
313
                    "endpoint_a": {
314
                        "interface_id": "00:00:00:00:00:00:00:01:1"
315
                    },
316
                    "endpoint_b": {
317
                        "interface_id": "00:00:00:00:00:00:00:02:2"
318
                    },
319
                }
320
            ],
321
            "backup_path": [],
322
        }
323
324
        # pylint: disable=protected-access
325
        evc_response = self.napp._evc_from_dict(payload)
326
        self.assertIsNotNone(evc_response)
327
        self.assertIsNotNone(evc_response.uni_a)
328
        self.assertIsNotNone(evc_response.uni_z)
329
        self.assertIsNotNone(evc_response.circuit_scheduler)
330
        self.assertIsNotNone(evc_response.name)
331
        self.assertEqual(len(evc_response.current_path), 0)
332
        self.assertEqual(len(evc_response.backup_path), 0)
333
        self.assertEqual(len(evc_response.primary_path), 1)
334
335
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
336
    @patch("napps.kytos.mef_eline.models.evc.EVCBase._validate")
337
    @patch("kytos.core.Controller.get_interface_by_id")
338
    def test_evc_from_dict_links(
339
        self, _get_interface_by_id_mock, _validate_mock, uni_from_dict_mock
340
    ):
341
        """
342
        Test the helper method that create an EVN from dict.
343
344
        Verify object creation with circuit data and schedule data.
345
        """
346
        _get_interface_by_id_mock.return_value = get_uni_mocked().interface
347
        _validate_mock.return_value = True
348
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
349
        payload = {
350
            "name": "my evc1",
351
            "uni_a": {
352
                "interface_id": "00:00:00:00:00:00:00:01:1",
353
                "tag": {"tag_type": 1, "value": 80},
354
            },
355
            "uni_z": {
356
                "interface_id": "00:00:00:00:00:00:00:02:2",
357
                "tag": {"tag_type": 1, "value": 1},
358
            },
359
            "primary_links": [
360
                {
361
                    "endpoint_a": {
362
                        "interface_id": "00:00:00:00:00:00:00:01:1"
363
                    },
364
                    "endpoint_b": {
365
                        "interface_id": "00:00:00:00:00:00:00:02:2"
366
                    },
367
                    "metadata": {
368
                        "s_vlan": {
369
                            "tag_type": 1,
370
                            "value": 100
371
                        }
372
                    },
373
                }
374
            ],
375
            "backup_links": [],
376
        }
377
378
        # pylint: disable=protected-access
379
        evc_response = self.napp._evc_from_dict(payload)
380
        self.assertIsNotNone(evc_response)
381
        self.assertIsNotNone(evc_response.uni_a)
382
        self.assertIsNotNone(evc_response.uni_z)
383
        self.assertIsNotNone(evc_response.circuit_scheduler)
384
        self.assertIsNotNone(evc_response.name)
385
        self.assertEqual(len(evc_response.current_links_cache), 0)
386
        self.assertEqual(len(evc_response.backup_links), 0)
387
        self.assertEqual(len(evc_response.primary_links), 1)
388
389
    def test_list_without_circuits(self):
390
        """Test if list circuits return 'no circuit stored.'."""
391
        circuits = {"circuits": {}}
392
        self.napp.mongo_controller.get_circuits.return_value = circuits
393
        api = self.get_app_test_client(self.napp)
394
        url = f"{self.server_name_url}/v2/evc/"
395
        response = api.get(url)
396
        self.assertEqual(response.status_code, 200, response.data)
397
        self.assertEqual(json.loads(response.data.decode()), {})
398
399
    def test_list_no_circuits_stored(self):
400
        """Test if list circuits return all circuits stored."""
401
        circuits = {"circuits": {}}
402
        self.napp.mongo_controller.get_circuits.return_value = circuits
403
404
        api = self.get_app_test_client(self.napp)
405
        url = f"{self.server_name_url}/v2/evc/"
406
407
        response = api.get(url)
408
        expected_result = circuits["circuits"]
409
        self.assertEqual(json.loads(response.data), expected_result)
410
411 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...
412
        """Test if list circuits return all circuits stored."""
413
        circuits = {
414
            'circuits':
415
            {"1": {"name": "circuit_1"}, "2": {"name": "circuit_2"}}
416
        }
417
        get_circuits = self.napp.mongo_controller.get_circuits
418
        get_circuits.return_value = circuits
419
420
        api = self.get_app_test_client(self.napp)
421
        url = f"{self.server_name_url}/v2/evc/"
422
423
        response = api.get(url)
424
        expected_result = circuits["circuits"]
425
        get_circuits.assert_called_with(archived="false", metadata={})
426
        self.assertEqual(json.loads(response.data), expected_result)
427
428 View Code Duplication
    def test_list_with_archived_circuits_archived(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
429
        """Test if list circuits only archived circuits."""
430
        circuits = {
431
            'circuits':
432
            {
433
                "1": {"name": "circuit_1", "archived": True},
434
            }
435
        }
436
        get_circuits = self.napp.mongo_controller.get_circuits
437
        get_circuits.return_value = circuits
438
439
        api = self.get_app_test_client(self.napp)
440
        url = f"{self.server_name_url}/v2/evc/?archived=true&metadata.a=1"
441
442
        response = api.get(url)
443
        get_circuits.assert_called_with(archived="true",
444
                                        metadata={"metadata.a": "1"})
445
        expected_result = {"1": circuits["circuits"]["1"]}
446
        self.assertEqual(json.loads(response.data), expected_result)
447
448
    def test_list_with_archived_circuits_all(self):
449
        """Test if list circuits return all circuits."""
450
        circuits = {
451
            'circuits': {
452
                "1": {"name": "circuit_1"},
453
                "2": {"name": "circuit_2", "archived": True},
454
            }
455
        }
456
        self.napp.mongo_controller.get_circuits.return_value = circuits
457
458
        api = self.get_app_test_client(self.napp)
459
        url = f"{self.server_name_url}/v2/evc/?archived=null"
460
461
        response = api.get(url)
462
        expected_result = circuits["circuits"]
463
        self.assertEqual(json.loads(response.data), expected_result)
464
465
    def test_circuit_with_valid_id(self):
466
        """Test if get_circuit return the circuit attributes."""
467
        circuit = {"name": "circuit_1"}
468
        self.napp.mongo_controller.get_circuit.return_value = circuit
469
470
        api = self.get_app_test_client(self.napp)
471
        url = f"{self.server_name_url}/v2/evc/1"
472
        response = api.get(url)
473
        expected_result = circuit
474
        self.assertEqual(json.loads(response.data), expected_result)
475
476
    def test_circuit_with_invalid_id(self):
477
        """Test if get_circuit return invalid circuit_id."""
478
        self.napp.mongo_controller.get_circuit.return_value = None
479
        api = self.get_app_test_client(self.napp)
480
        url = f"{self.server_name_url}/v2/evc/3"
481
        response = api.get(url)
482
        expected_result = "circuit_id 3 not found"
483
        self.assertEqual(
484
            json.loads(response.data)["description"], expected_result
485
        )
486
487
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
488
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
489
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
490
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
491
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
492
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
493
    def test_create_a_circuit_case_1(self, *args):
494
        """Test create a new circuit."""
495
        # pylint: disable=too-many-locals
496
        (
497
            validate_mock,
498
            evc_as_dict_mock,
499
            mongo_controller_upsert_mock,
500
            uni_from_dict_mock,
501
            sched_add_mock,
502
            evc_deploy_mock,
503
        ) = args
504
505
        validate_mock.return_value = True
506
        mongo_controller_upsert_mock.return_value = True
507
        evc_deploy_mock.return_value = True
508
        uni1 = create_autospec(UNI)
509
        uni2 = create_autospec(UNI)
510
        uni1.interface = create_autospec(Interface)
511
        uni2.interface = create_autospec(Interface)
512
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
513
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
514
        uni_from_dict_mock.side_effect = [uni1, uni2]
515
        evc_as_dict_mock.return_value = {}
516
        sched_add_mock.return_value = True
517
        self.napp.mongo_controller.get_circuits.return_value = {}
518
519
        api = self.get_app_test_client(self.napp)
520
        url = f"{self.server_name_url}/v2/evc/"
521
        payload = {
522
            "name": "my evc1",
523
            "frequency": "* * * * *",
524
            "uni_a": {
525
                "interface_id": "00:00:00:00:00:00:00:01:1",
526
                "tag": {"tag_type": 1, "value": 80},
527
            },
528
            "uni_z": {
529
                "interface_id": "00:00:00:00:00:00:00:02:2",
530
                "tag": {"tag_type": 1, "value": 1},
531
            },
532
            "dynamic_backup_path": True,
533
            "primary_constraints": {
534
                "spf_max_path_cost": 8,
535
                "mandatory_metrics": {
536
                    "ownership": "red"
537
                }
538
            },
539
            "secondary_constraints": {
540
                "mandatory_metrics": {
541
                    "ownership": "blue"
542
                }
543
            }
544
        }
545
546
        response = api.post(
547
            url, data=json.dumps(payload), content_type="application/json"
548
        )
549
        current_data = json.loads(response.data)
550
551
        # verify expected result from request
552
        self.assertEqual(201, response.status_code, response.data)
553
        self.assertIn("circuit_id", current_data)
554
555
        # verify uni called
556
        uni_from_dict_mock.called_twice()
557
        uni_from_dict_mock.assert_any_call(payload["uni_z"])
558
        uni_from_dict_mock.assert_any_call(payload["uni_a"])
559
560
        # verify validation called
561
        validate_mock.assert_called_once()
562
        validate_mock.assert_called_with(
563
            table_group={'evpl': 0, 'epl': 0},
564
            frequency="* * * * *",
565
            name="my evc1",
566
            uni_a=uni1,
567
            uni_z=uni2,
568
            dynamic_backup_path=True,
569
            primary_constraints=payload["primary_constraints"],
570
            secondary_constraints=payload["secondary_constraints"],
571
        )
572
        # verify save method is called
573
        mongo_controller_upsert_mock.assert_called_once()
574
575
        # verify evc as dict is called to save in the box
576
        evc_as_dict_mock.assert_called()
577
        # verify add circuit in sched
578
        sched_add_mock.assert_called_once()
579
580
    @staticmethod
581
    def get_napp_urls(napp):
582
        """Return the kytos/mef_eline urls.
583
584
        The urls will be like:
585
586
        urls = [
587
            (options, methods, url)
588
        ]
589
590
        """
591
        controller = napp.controller
592
        controller.api_server.register_napp_endpoints(napp)
593
594
        urls = []
595
        for rule in controller.api_server.app.url_map.iter_rules():
596
            options = {}
597
            for arg in rule.arguments:
598
                options[arg] = f"[{0}]".format(arg)
599
600
            if f"{napp.username}/{napp.name}" in str(rule):
601
                urls.append((options, rule.methods, f"{str(rule)}"))
602
603
        return urls
604
605
    @staticmethod
606
    def get_app_test_client(napp):
607
        """Return a flask api test client."""
608
        napp.controller.api_server.register_napp_endpoints(napp)
609
        return napp.controller.api_server.app.test_client()
610
611
    def test_create_a_circuit_case_2(self):
612
        """Test create a new circuit trying to send request without a json."""
613
        api = self.get_app_test_client(self.napp)
614
        url = f"{self.server_name_url}/v2/evc/"
615
616
        response = api.post(url)
617
        current_data = json.loads(response.data)
618
        expected_message = "The request body mimetype is not application/json."
619
        expected_data = expected_message
620
        self.assertEqual(415, response.status_code, response.data)
621
        self.assertEqual(current_data["description"], expected_data)
622
623
    def test_create_a_circuit_case_3(self):
624
        """Test create a new circuit trying to send request with an
625
        invalid json."""
626
        api = self.get_app_test_client(self.napp)
627
        url = f"{self.server_name_url}/v2/evc/"
628
629
        response = api.post(
630
            url,
631
            data="This is an {Invalid:} JSON",
632
            content_type="application/json",
633
        )
634
        current_data = json.loads(response.data)
635
        expected_data = "The request body is not a well-formed JSON."
636
637
        self.assertEqual(400, response.status_code, response.data)
638
        self.assertEqual(current_data["description"], expected_data)
639
640
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
641
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
642
    def test_create_a_circuit_case_4(
643
        self,
644
        mongo_controller_upsert_mock,
645
        uni_from_dict_mock
646
    ):
647
        """Test create a new circuit trying to send request with an
648
        invalid value."""
649
        # pylint: disable=too-many-locals
650
        uni_from_dict_mock.side_effect = ValueError("Could not instantiate")
651
        mongo_controller_upsert_mock.return_value = True
652
        api = self.get_app_test_client(self.napp)
653
        url = f"{self.server_name_url}/v2/evc/"
654
655
        payload = {
656
            "name": "my evc1",
657
            "frequency": "* * * * *",
658
            "uni_a": {
659
                "interface_id": "00:00:00:00:00:00:00:01:76",
660
                "tag": {"tag_type": 1, "value": 80},
661
            },
662
            "uni_z": {
663
                "interface_id": "00:00:00:00:00:00:00:02:2",
664
                "tag": {"tag_type": 1, "value": 1},
665
            },
666
        }
667
668
        response = api.post(
669
            url, data=json.dumps(payload), content_type="application/json"
670
        )
671
        current_data = json.loads(response.data)
672
        expected_data = "Error creating UNI: Invalid value"
673
        self.assertEqual(400, response.status_code, response.data)
674
        self.assertEqual(current_data["description"], expected_data)
675
676
        payload["name"] = 1
677
        response = api.post(
678
            url, data=json.dumps(payload), content_type="application/json"
679
        )
680
        self.assertEqual(400, response.status_code, response.data)
681
682
    def test_create_a_circuit_invalid_queue_id(self):
683
        """Test create a new circuit with invalid queue_id."""
684
        api = self.get_app_test_client(self.napp)
685
        url = f"{self.server_name_url}/v2/evc/"
686
687
        payload = {
688
            "name": "my evc1",
689
            "queue_id": 8,
690
            "uni_a": {
691
                "interface_id": "00:00:00:00:00:00:00:01:76",
692
                "tag": {"tag_type": 1, "value": 80},
693
            },
694
            "uni_z": {
695
                "interface_id": "00:00:00:00:00:00:00:02:2",
696
                "tag": {"tag_type": 1, "value": 1},
697
            },
698
        }
699
        response = api.post(
700
            url,
701
            data=json.dumps(payload),
702
            content_type="application/json",
703
        )
704
        current_data = json.loads(response.data)
705
        expected_data = "8 is greater than the maximum of 7"
706
707
        assert response.status_code == 400
708
        assert expected_data in current_data["description"], expected_data
709
710
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
711
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
712
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
713
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
714
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
715
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
716
    def test_create_circuit_already_enabled(self, *args):
717
        """Test create an already created circuit."""
718
        # pylint: disable=too-many-locals
719
        (
720
            evc_as_dict_mock,
721
            validate_mock,
722
            mongo_controller_upsert_mock,
723
            uni_from_dict_mock,
724
            sched_add_mock,
725
            evc_deploy_mock,
726
        ) = args
727
728
        validate_mock.return_value = True
729
        mongo_controller_upsert_mock.return_value = True
730
        sched_add_mock.return_value = True
731
        evc_deploy_mock.return_value = True
732
        uni1 = create_autospec(UNI)
733
        uni2 = create_autospec(UNI)
734
        uni1.interface = create_autospec(Interface)
735
        uni2.interface = create_autospec(Interface)
736
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
737
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
738
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
739
740
        api = self.get_app_test_client(self.napp)
741
        payload = {
742
            "name": "my evc1",
743
            "uni_a": {
744
                "interface_id": "00:00:00:00:00:00:00:01:1",
745
                "tag": {"tag_type": 1, "value": 80},
746
            },
747
            "uni_z": {
748
                "interface_id": "00:00:00:00:00:00:00:02:2",
749
                "tag": {"tag_type": 1, "value": 1},
750
            },
751
            "dynamic_backup_path": True,
752
        }
753
754
        evc_as_dict_mock.return_value = payload
755
        response = api.post(
756
            f"{self.server_name_url}/v2/evc/",
757
            data=json.dumps(payload),
758
            content_type="application/json",
759
        )
760
        self.assertEqual(201, response.status_code)
761
762
        response = api.post(
763
            f"{self.server_name_url}/v2/evc/",
764
            data=json.dumps(payload),
765
            content_type="application/json",
766
        )
767
        current_data = json.loads(response.data)
768
        expected_data = "The EVC already exists."
769
        self.assertEqual(current_data["description"], expected_data)
770
        self.assertEqual(409, response.status_code)
771
772
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
773
    def test_create_circuit_case_5(self, uni_from_dict_mock):
774
        """Test when neither primary path nor dynamic_backup_path is set."""
775
        api = self.get_app_test_client(self.napp)
776
        url = f"{self.server_name_url}/v2/evc/"
777
        uni1 = create_autospec(UNI)
778
        uni2 = create_autospec(UNI)
779
        uni1.interface = create_autospec(Interface)
780
        uni2.interface = create_autospec(Interface)
781
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
782
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
783
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
784
785
        payload = {
786
            "name": "my evc1",
787
            "frequency": "* * * * *",
788
            "uni_a": {
789
                "interface_id": "00:00:00:00:00:00:00:01:1",
790
                "tag": {"tag_type": 1, "value": 80},
791
            },
792
            "uni_z": {
793
                "interface_id": "00:00:00:00:00:00:00:02:2",
794
                "tag": {"tag_type": 1, "value": 1},
795
            },
796
        }
797
798
        response = api.post(
799
            url, data=json.dumps(payload), content_type="application/json"
800
        )
801
        current_data = json.loads(response.data)
802
        expected_data = "The EVC must have a primary path "
803
        expected_data += "or allow dynamic paths."
804
        self.assertEqual(400, response.status_code, response.data)
805
        self.assertEqual(current_data["description"], expected_data)
806
807
    def test_redeploy_evc(self):
808
        """Test endpoint to redeploy an EVC."""
809
        evc1 = MagicMock()
810
        evc1.is_enabled.return_value = True
811
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
812
        api = self.get_app_test_client(self.napp)
813
        url = f"{self.server_name_url}/v2/evc/1/redeploy"
814
        response = api.patch(url)
815
        self.assertEqual(response.status_code, 202, response.data)
816
817
    def test_redeploy_evc_disabled(self):
818
        """Test endpoint to redeploy an EVC."""
819
        evc1 = MagicMock()
820
        evc1.is_enabled.return_value = False
821
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
822
        api = self.get_app_test_client(self.napp)
823
        url = f"{self.server_name_url}/v2/evc/1/redeploy"
824
        response = api.patch(url)
825
        self.assertEqual(response.status_code, 409, response.data)
826
827
    def test_redeploy_evc_deleted(self):
828
        """Test endpoint to redeploy an EVC."""
829
        evc1 = MagicMock()
830
        evc1.is_enabled.return_value = True
831
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
832
        api = self.get_app_test_client(self.napp)
833
        url = f"{self.server_name_url}/v2/evc/3/redeploy"
834
        response = api.patch(url)
835
        self.assertEqual(response.status_code, 404, response.data)
836
837
    def test_list_schedules__no_data_stored(self):
838
        """Test if list circuits return all circuits stored."""
839
        self.napp.mongo_controller.get_circuits.return_value = {"circuits": {}}
840
841
        api = self.get_app_test_client(self.napp)
842
        url = f"{self.server_name_url}/v2/evc/schedule"
843
844
        response = api.get(url)
845
        expected_result = {}
846
847
        self.assertEqual(response.status_code, 200, response.data)
848
        self.assertEqual(json.loads(response.data), expected_result)
849
850
    def _add_mongodb_schedule_data(self, data_mock):
851
        """Add schedule data to mongodb mock object."""
852
        circuits = {"circuits": {}}
853
        payload_1 = {
854
            "id": "aa:aa:aa",
855
            "name": "my evc1",
856
            "uni_a": {
857
                "interface_id": "00:00:00:00:00:00:00:01:1",
858
                "tag": {"tag_type": 1, "value": 80},
859
            },
860
            "uni_z": {
861
                "interface_id": "00:00:00:00:00:00:00:02:2",
862
                "tag": {"tag_type": 1, "value": 1},
863
            },
864
            "circuit_scheduler": [
865
                {"id": "1", "frequency": "* * * * *", "action": "create"},
866
                {"id": "2", "frequency": "1 * * * *", "action": "remove"},
867
            ],
868
        }
869
        circuits["circuits"].update({"aa:aa:aa": payload_1})
870
        payload_2 = {
871
            "id": "bb:bb:bb",
872
            "name": "my second evc2",
873
            "uni_a": {
874
                "interface_id": "00:00:00:00:00:00:00:01:2",
875
                "tag": {"tag_type": 1, "value": 90},
876
            },
877
            "uni_z": {
878
                "interface_id": "00:00:00:00:00:00:00:03:2",
879
                "tag": {"tag_type": 1, "value": 100},
880
            },
881
            "circuit_scheduler": [
882
                {"id": "3", "frequency": "1 * * * *", "action": "create"},
883
                {"id": "4", "frequency": "2 * * * *", "action": "remove"},
884
            ],
885
        }
886
        circuits["circuits"].update({"bb:bb:bb": payload_2})
887
        payload_3 = {
888
            "id": "cc:cc:cc",
889
            "name": "my third evc3",
890
            "uni_a": {
891
                "interface_id": "00:00:00:00:00:00:00:03:1",
892
                "tag": {"tag_type": 1, "value": 90},
893
            },
894
            "uni_z": {
895
                "interface_id": "00:00:00:00:00:00:00:04:2",
896
                "tag": {"tag_type": 1, "value": 100},
897
            },
898
        }
899
        circuits["circuits"].update({"cc:cc:cc": payload_3})
900
        # Add one circuit to the mongodb.
901
        data_mock.return_value = circuits
902
903
    def test_list_schedules_from_mongodb(self):
904
        """Test if list circuits return specific circuits stored."""
905
        self._add_mongodb_schedule_data(
906
            self.napp.mongo_controller.get_circuits
907
        )
908
909
        api = self.get_app_test_client(self.napp)
910
        url = f"{self.server_name_url}/v2/evc/schedule"
911
912
        # Call URL
913
        response = api.get(url)
914
        # Expected JSON data from response
915
        expected = [
916
            {
917
                "circuit_id": "aa:aa:aa",
918
                "schedule": {
919
                    "action": "create",
920
                    "frequency": "* * * * *",
921
                    "id": "1",
922
                },
923
                "schedule_id": "1",
924
            },
925
            {
926
                "circuit_id": "aa:aa:aa",
927
                "schedule": {
928
                    "action": "remove",
929
                    "frequency": "1 * * * *",
930
                    "id": "2",
931
                },
932
                "schedule_id": "2",
933
            },
934
            {
935
                "circuit_id": "bb:bb:bb",
936
                "schedule": {
937
                    "action": "create",
938
                    "frequency": "1 * * * *",
939
                    "id": "3",
940
                },
941
                "schedule_id": "3",
942
            },
943
            {
944
                "circuit_id": "bb:bb:bb",
945
                "schedule": {
946
                    "action": "remove",
947
                    "frequency": "2 * * * *",
948
                    "id": "4",
949
                },
950
                "schedule_id": "4",
951
            },
952
        ]
953
954
        self.assertEqual(response.status_code, 200, response.data)
955
        self.assertEqual(expected, json.loads(response.data))
956
957
    def test_get_specific_schedule_from_mongodb(self):
958
        """Test get schedules from a circuit."""
959
        self._add_mongodb_schedule_data(
960
            self.napp.mongo_controller.get_circuits
961
        )
962
963
        requested_circuit_id = "bb:bb:bb"
964
        evc = self.napp.mongo_controller.get_circuits()
965
        evc = evc["circuits"][requested_circuit_id]
966
        self.napp.mongo_controller.get_circuit.return_value = evc
967
        api = self.get_app_test_client(self.napp)
968
        url = f"{self.server_name_url}/v2/evc/{requested_circuit_id}"
969
970
        # Call URL
971
        response = api.get(url)
972
973
        # Expected JSON data from response
974
        expected = [
975
            {"action": "create", "frequency": "1 * * * *", "id": "3"},
976
            {"action": "remove", "frequency": "2 * * * *", "id": "4"},
977
        ]
978
979
        self.assertEqual(response.status_code, 200)
980
        self.assertEqual(
981
            expected, json.loads(response.data)["circuit_scheduler"]
982
        )
983
984
    def test_get_specific_schedules_from_mongodb_not_found(self):
985
        """Test get specific schedule ID that does not exist."""
986
        requested_id = "blah"
987
        api = self.get_app_test_client(self.napp)
988
        self.napp.mongo_controller.get_circuit.return_value = None
989
        url = f"{self.server_name_url}/v2/evc/{requested_id}"
990
991
        # Call URL
992
        response = api.get(url)
993
994
        expected = "circuit_id blah not found"
995
        # Assert response not found
996
        self.assertEqual(response.status_code, 404, response.data)
997
        self.assertEqual(expected, json.loads(response.data)["description"])
998
999
    def _uni_from_dict_side_effect(self, uni_dict):
1000
        interface_id = uni_dict.get("interface_id")
1001
        tag_dict = uni_dict.get("tag")
1002
        interface = Interface(interface_id, "0", MagicMock(id="1"))
1003
        return UNI(interface, tag_dict)
1004
1005
    @patch("apscheduler.schedulers.background.BackgroundScheduler.add_job")
1006
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1007
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1008
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1009
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1010
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1011
    def test_create_schedule(self, *args):  # pylint: disable=too-many-locals
1012
        """Test create a circuit schedule."""
1013
        (
1014
            validate_mock,
1015
            evc_as_dict_mock,
1016
            mongo_controller_upsert_mock,
1017
            uni_from_dict_mock,
1018
            sched_add_mock,
1019
            scheduler_add_job_mock,
1020
        ) = args
1021
1022
        validate_mock.return_value = True
1023
        mongo_controller_upsert_mock.return_value = True
1024
        uni_from_dict_mock.side_effect = self._uni_from_dict_side_effect
1025
        evc_as_dict_mock.return_value = {}
1026
        sched_add_mock.return_value = True
1027
1028
        self._add_mongodb_schedule_data(
1029
            self.napp.mongo_controller.get_circuits
1030
        )
1031
1032
        requested_id = "bb:bb:bb"
1033
        api = self.get_app_test_client(self.napp)
1034
        url = f"{self.server_name_url}/v2/evc/schedule/"
1035
1036
        payload = {
1037
            "circuit_id": requested_id,
1038
            "schedule": {"frequency": "1 * * * *", "action": "create"},
1039
            "metadata": {"metadata1": "test_data"},
1040
        }
1041
1042
        # Call URL
1043
        response = api.post(
1044
            url, data=json.dumps(payload), content_type="application/json"
1045
        )
1046
1047
        response_json = json.loads(response.data)
1048
1049
        self.assertEqual(response.status_code, 201, response.data)
1050
        scheduler_add_job_mock.assert_called_once()
1051
        mongo_controller_upsert_mock.assert_called_once()
1052
        self.assertEqual(
1053
            payload["schedule"]["frequency"], response_json["frequency"]
1054
        )
1055
        self.assertEqual(
1056
            payload["schedule"]["action"], response_json["action"]
1057
        )
1058
        self.assertIsNotNone(response_json["id"])
1059
1060
        # Case 2: there is no schedule
1061
        payload = {
1062
              "circuit_id": "cc:cc:cc",
1063
              "schedule": {
1064
                "frequency": "1 * * * *",
1065
                "action": "create"
1066
              }
1067
            }
1068
        response = api.post(url, data=json.dumps(payload),
1069
                            content_type='application/json')
1070
        self.assertEqual(response.status_code, 201)
1071
1072
    def test_create_schedule_invalid_request(self):
1073
        """Test create schedule API with invalid request."""
1074
        evc1 = MagicMock()
1075
        self.napp.circuits = {'bb:bb:bb': evc1}
1076
        api = self.get_app_test_client(self.napp)
1077
        url = f'{self.server_name_url}/v2/evc/schedule/'
1078
1079
        # case 1: empty post
1080
        response = api.post(url, data="")
1081
        self.assertEqual(response.status_code, 415)
1082
1083
        # case 2: content-type not specified
1084
        payload = {
1085
            "circuit_id": "bb:bb:bb",
1086
            "schedule": {
1087
                "frequency": "1 * * * *",
1088
                "action": "create"
1089
            }
1090
        }
1091
        response = api.post(url, data=json.dumps(payload))
1092
        self.assertEqual(response.status_code, 415)
1093
1094
        # case 3: not a dictionary
1095
        payload = []
1096
        response = api.post(url, data=json.dumps(payload),
1097
                            content_type='application/json')
1098
        self.assertEqual(response.status_code, 400)
1099
1100
        # case 4: missing circuit id
1101
        payload = {
1102
            "schedule": {
1103
                "frequency": "1 * * * *",
1104
                "action": "create"
1105
            }
1106
        }
1107
        response = api.post(url, data=json.dumps(payload),
1108
                            content_type='application/json')
1109
        self.assertEqual(response.status_code, 400)
1110
1111
        # case 5: missing schedule
1112
        payload = {
1113
            "circuit_id": "bb:bb:bb"
1114
        }
1115
        response = api.post(url, data=json.dumps(payload),
1116
                            content_type='application/json')
1117
        self.assertEqual(response.status_code, 400)
1118
1119
        # case 6: invalid circuit
1120
        payload = {
1121
            "circuit_id": "xx:xx:xx",
1122
            "schedule": {
1123
                "frequency": "1 * * * *",
1124
                "action": "create"
1125
            }
1126
        }
1127
        response = api.post(url, data=json.dumps(payload),
1128
                            content_type='application/json')
1129
        self.assertEqual(response.status_code, 404)
1130
1131
        # case 7: archived or deleted evc
1132
        evc1.archived.return_value = True
1133
        payload = {
1134
            "circuit_id": "bb:bb:bb",
1135
            "schedule": {
1136
                "frequency": "1 * * * *",
1137
                "action": "create"
1138
            }
1139
        }
1140
        response = api.post(url, data=json.dumps(payload),
1141
                            content_type='application/json')
1142
        self.assertEqual(response.status_code, 403)
1143
1144
        # case 8: invalid json
1145
        response = api.post(url, data='{"test"}',
1146
                            content_type='application/json')
1147
        self.assertEqual(response.status_code, 400)
1148
1149
    @patch('apscheduler.schedulers.background.BackgroundScheduler.remove_job')
1150
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1151
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1152
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1153
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1154
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1155
    def test_update_schedule(self, *args):  # pylint: disable=too-many-locals
1156
        """Test create a circuit schedule."""
1157
        (
1158
            validate_mock,
1159
            evc_as_dict_mock,
1160
            mongo_controller_upsert_mock,
1161
            uni_from_dict_mock,
1162
            sched_add_mock,
1163
            scheduler_remove_job_mock,
1164
        ) = args
1165
1166
        mongo_payload_1 = {
1167
            "circuits": {
1168
                "aa:aa:aa": {
1169
                    "id": "aa:aa:aa",
1170
                    "name": "my evc1",
1171
                    "uni_a": {
1172
                        "interface_id": "00:00:00:00:00:00:00:01:1",
1173
                        "tag": {"tag_type": 1, "value": 80},
1174
                    },
1175
                    "uni_z": {
1176
                        "interface_id": "00:00:00:00:00:00:00:02:2",
1177
                        "tag": {"tag_type": 1, "value": 1},
1178
                    },
1179
                    "circuit_scheduler": [
1180
                        {
1181
                            "id": "1",
1182
                            "frequency": "* * * * *",
1183
                            "action": "create"
1184
                        }
1185
                    ],
1186
                }
1187
            }
1188
        }
1189
1190
        validate_mock.return_value = True
1191
        mongo_controller_upsert_mock.return_value = True
1192
        sched_add_mock.return_value = True
1193
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1194
        evc_as_dict_mock.return_value = {}
1195
        self.napp.mongo_controller.get_circuits.return_value = mongo_payload_1
1196
        scheduler_remove_job_mock.return_value = True
1197
1198
        requested_schedule_id = "1"
1199
        api = self.get_app_test_client(self.napp)
1200
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1201
1202
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1203
1204
        # Call URL
1205
        response = api.patch(
1206
            url, data=json.dumps(payload), content_type="application/json"
1207
        )
1208
1209
        response_json = json.loads(response.data)
1210
1211
        self.assertEqual(response.status_code, 200, response.data)
1212
        scheduler_remove_job_mock.assert_called_once()
1213
        mongo_controller_upsert_mock.assert_called_once()
1214
        self.assertEqual(payload["frequency"], response_json["frequency"])
1215
        self.assertEqual(payload["action"], response_json["action"])
1216
        self.assertIsNotNone(response_json["id"])
1217
1218
    @patch('napps.kytos.mef_eline.main.Main._find_evc_by_schedule_id')
1219
    def test_update_no_schedule(self, find_evc_by_schedule_id_mock):
1220
        """Test update a circuit schedule."""
1221
        api = self.get_app_test_client(self.napp)
1222
        url = f"{self.server_name_url}/v2/evc/schedule/1"
1223
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1224
1225
        find_evc_by_schedule_id_mock.return_value = None, None
1226
1227
        response = api.patch(
1228
            url, data=json.dumps(payload), content_type="application/json"
1229
        )
1230
1231
        self.assertEqual(response.status_code, 404)
1232
1233
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1234
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1235
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1236
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1237
    def test_update_schedule_archived(self, *args):
1238
        """Test create a circuit schedule."""
1239
        # pylint: disable=too-many-locals
1240
        (
1241
            validate_mock,
1242
            evc_as_dict_mock,
1243
            uni_from_dict_mock,
1244
            sched_add_mock,
1245
        ) = args
1246
1247
        mongo_payload_1 = {
1248
            "circuits": {
1249
                "aa:aa:aa": {
1250
                    "id": "aa:aa:aa",
1251
                    "name": "my evc1",
1252
                    "archived": True,
1253
                    "circuit_scheduler": [
1254
                        {
1255
                            "id": "1",
1256
                            "frequency": "* * * * *",
1257
                            "action": "create"
1258
                        }
1259
                    ],
1260
                }
1261
            }
1262
        }
1263
1264
        validate_mock.return_value = True
1265
        sched_add_mock.return_value = True
1266
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1267
        evc_as_dict_mock.return_value = {}
1268
        self.napp.mongo_controller.get_circuits.return_value = mongo_payload_1
1269
1270
        requested_schedule_id = "1"
1271
        api = self.get_app_test_client(self.napp)
1272
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1273
1274
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1275
1276
        # Call URL
1277
        response = api.patch(
1278
            url, data=json.dumps(payload), content_type="application/json"
1279
        )
1280
1281
        self.assertEqual(response.status_code, 403, response.data)
1282
1283
    @patch("apscheduler.schedulers.background.BackgroundScheduler.remove_job")
1284
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1285
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1286
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1287
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1288
    def test_delete_schedule(self, *args):
1289
        """Test create a circuit schedule."""
1290
        (
1291
            validate_mock,
1292
            evc_as_dict_mock,
1293
            mongo_controller_upsert_mock,
1294
            uni_from_dict_mock,
1295
            scheduler_remove_job_mock,
1296
        ) = args
1297
1298
        mongo_payload_1 = {
1299
            "circuits": {
1300
                "2": {
1301
                    "id": "2",
1302
                    "name": "my evc1",
1303
                    "uni_a": {
1304
                        "interface_id": "00:00:00:00:00:00:00:01:1",
1305
                        "tag": {"tag_type": 1, "value": 80},
1306
                    },
1307
                    "uni_z": {
1308
                        "interface_id": "00:00:00:00:00:00:00:02:2",
1309
                        "tag": {"tag_type": 1, "value": 1},
1310
                    },
1311
                    "circuit_scheduler": [
1312
                        {
1313
                            "id": "1",
1314
                            "frequency": "* * * * *",
1315
                            "action": "create"
1316
                        }
1317
                    ],
1318
                }
1319
            }
1320
        }
1321
        validate_mock.return_value = True
1322
        mongo_controller_upsert_mock.return_value = True
1323
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1324
        evc_as_dict_mock.return_value = {}
1325
        self.napp.mongo_controller.get_circuits.return_value = mongo_payload_1
1326
        scheduler_remove_job_mock.return_value = True
1327
1328
        requested_schedule_id = "1"
1329
        api = self.get_app_test_client(self.napp)
1330
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1331
1332
        # Call URL
1333
        response = api.delete(url)
1334
1335
        self.assertEqual(response.status_code, 200, response.data)
1336
        scheduler_remove_job_mock.assert_called_once()
1337
        mongo_controller_upsert_mock.assert_called_once()
1338
        self.assertIn("Schedule removed", f"{response.data}")
1339
1340
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1341
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1342
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1343
    def test_delete_schedule_archived(self, *args):
1344
        """Test create a circuit schedule."""
1345
        (
1346
            validate_mock,
1347
            evc_as_dict_mock,
1348
            uni_from_dict_mock,
1349
        ) = args
1350
1351
        mongo_payload_1 = {
1352
            "circuits": {
1353
                "2": {
1354
                    "id": "2",
1355
                    "name": "my evc1",
1356
                    "archived": True,
1357
                    "circuit_scheduler": [
1358
                        {
1359
                            "id": "1",
1360
                            "frequency": "* * * * *",
1361
                            "action": "create"
1362
                        }
1363
                    ],
1364
                }
1365
            }
1366
        }
1367
1368
        validate_mock.return_value = True
1369
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1370
        evc_as_dict_mock.return_value = {}
1371
        self.napp.mongo_controller.get_circuits.return_value = mongo_payload_1
1372
1373
        requested_schedule_id = "1"
1374
        api = self.get_app_test_client(self.napp)
1375
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1376
1377
        # Call URL
1378
        response = api.delete(url)
1379
1380
        self.assertEqual(response.status_code, 403, response.data)
1381
1382
    @patch('napps.kytos.mef_eline.main.Main._find_evc_by_schedule_id')
1383
    def test_delete_schedule_not_found(self, mock_find_evc_by_sched):
1384
        """Test delete a circuit schedule - unexisting."""
1385
        mock_find_evc_by_sched.return_value = (None, False)
1386
        api = self.get_app_test_client(self.napp)
1387
        url = f'{self.server_name_url}/v2/evc/schedule/1'
1388
        response = api.delete(url)
1389
        self.assertEqual(response.status_code, 404)
1390
1391
    def test_get_evcs_by_svc_level(self) -> None:
1392
        """Test get_evcs_by_svc_level."""
1393
        levels = [1, 2, 4, 2, 7]
1394
        evcs = {i: MagicMock(service_level=v, creation_time=1)
1395
                for i, v in enumerate(levels)}
1396
        self.napp.circuits = evcs
1397
        expected_levels = sorted(levels, reverse=True)
1398
        evcs_by_level = self.napp.get_evcs_by_svc_level()
1399
        assert evcs_by_level
1400
1401
        for evc, exp_level in zip(evcs_by_level, expected_levels):
1402
            assert evc.service_level == exp_level
1403
1404
        evcs = {i: MagicMock(service_level=1, creation_time=i)
1405
                for i in reversed(range(2))}
1406
        self.napp.circuits = evcs
1407
        evcs_by_level = self.napp.get_evcs_by_svc_level()
1408
        for i in range(2):
1409
            assert evcs_by_level[i].creation_time == i
1410
1411
    def test_get_circuit_not_found(self):
1412
        """Test /v2/evc/<circuit_id> 404."""
1413
        self.napp.mongo_controller.get_circuit.return_value = None
1414
        api = self.get_app_test_client(self.napp)
1415
        url = f'{self.server_name_url}/v2/evc/1234'
1416
        response = api.get(url)
1417
        self.assertEqual(response.status_code, 404)
1418
1419
    @patch('requests.post')
1420
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1421
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1422
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1423
    @patch('kytos.core.Controller.get_interface_by_id')
1424
    @patch('napps.kytos.mef_eline.models.path.Path.is_valid')
1425
    @patch('napps.kytos.mef_eline.models.evc.EVCDeploy.deploy')
1426
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1427
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1428
    def test_update_circuit(self, *args):
1429
        """Test update a circuit circuit."""
1430
        # pylint: disable=too-many-locals,duplicate-code
1431
        (
1432
            evc_as_dict_mock,
1433
            uni_from_dict_mock,
1434
            evc_deploy,
1435
            _,
1436
            interface_by_id_mock,
1437
            _,
1438
            _,
1439
            _,
1440
            requests_mock,
1441
        ) = args
1442
1443
        interface_by_id_mock.return_value = get_uni_mocked().interface
1444
        unis = [
1445
            get_uni_mocked(switch_dpid="00:00:00:00:00:00:00:01"),
1446
            get_uni_mocked(switch_dpid="00:00:00:00:00:00:00:02"),
1447
        ]
1448
        uni_from_dict_mock.side_effect = 2 * unis
1449
1450
        response = MagicMock()
1451
        response.status_code = 201
1452
        requests_mock.return_value = response
1453
1454
        api = self.get_app_test_client(self.napp)
1455
        payloads = [
1456
            {
1457
                "name": "my evc1",
1458
                "uni_a": {
1459
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1460
                    "tag": {"tag_type": 1, "value": 80},
1461
                },
1462
                "uni_z": {
1463
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1464
                    "tag": {"tag_type": 1, "value": 1},
1465
                },
1466
                "dynamic_backup_path": True,
1467
            },
1468
            {
1469
                "primary_path": [
1470
                    {
1471
                        "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1472
                        "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"},
1473
                    }
1474
                ]
1475
            },
1476
            {
1477
                "sb_priority": 3
1478
            },
1479
            {
1480
                # It works only with 'enable' and not with 'enabled'
1481
                "enable": True
1482
            },
1483
            {
1484
                "name": "my evc1",
1485
                "active": True,
1486
                "enable": True,
1487
                "uni_a": {
1488
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1489
                    "tag": {
1490
                        "tag_type": 1,
1491
                        "value": 80
1492
                    }
1493
                },
1494
                "uni_z": {
1495
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1496
                    "tag": {
1497
                        "tag_type": 1,
1498
                        "value": 1
1499
                    }
1500
                },
1501
                "priority": 3,
1502
                "bandwidth": 1000,
1503
                "dynamic_backup_path": True
1504
            }
1505
        ]
1506
1507
        evc_as_dict_mock.return_value = payloads[0]
1508
        response = api.post(
1509
            f"{self.server_name_url}/v2/evc/",
1510
            data=json.dumps(payloads[0]),
1511
            content_type="application/json",
1512
        )
1513
        self.assertEqual(201, response.status_code)
1514
1515
        evc_deploy.reset_mock()
1516
        evc_as_dict_mock.return_value = payloads[1]
1517
        current_data = json.loads(response.data)
1518
        circuit_id = current_data["circuit_id"]
1519
        response = api.patch(
1520
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1521
            data=json.dumps(payloads[1]),
1522
            content_type="application/json",
1523
        )
1524
        # evc_deploy.assert_called_once()
1525
        self.assertEqual(200, response.status_code)
1526
1527
        evc_deploy.reset_mock()
1528
        evc_as_dict_mock.return_value = payloads[2]
1529
        response = api.patch(
1530
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1531
            data=json.dumps(payloads[2]),
1532
            content_type="application/json",
1533
        )
1534
        evc_deploy.assert_not_called()
1535
        self.assertEqual(200, response.status_code)
1536
1537
        evc_deploy.reset_mock()
1538
        evc_as_dict_mock.return_value = payloads[3]
1539
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1540
                             data=json.dumps(payloads[3]),
1541
                             content_type='application/json')
1542
        evc_deploy.assert_called_once()
1543
        self.assertEqual(200, response.status_code)
1544
1545
        evc_deploy.reset_mock()
1546
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1547
                             data='{"priority":5,}',
1548
                             content_type='application/json')
1549
        evc_deploy.assert_not_called()
1550
        self.assertEqual(400, response.status_code)
1551
1552
        evc_deploy.reset_mock()
1553
        response = api.patch(
1554
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1555
            data=json.dumps(payloads[3]),
1556
            content_type="application/json",
1557
        )
1558
        evc_deploy.assert_called_once()
1559
        self.assertEqual(200, response.status_code)
1560
1561
        response = api.patch(
1562
            f"{self.server_name_url}/v2/evc/1234",
1563
            data=json.dumps(payloads[1]),
1564
            content_type="application/json",
1565
        )
1566
        current_data = json.loads(response.data)
1567
        expected_data = "circuit_id 1234 not found"
1568
        self.assertEqual(current_data["description"], expected_data)
1569
        self.assertEqual(404, response.status_code)
1570
1571
        api.delete(f"{self.server_name_url}/v2/evc/{circuit_id}")
1572
        evc_deploy.reset_mock()
1573
        response = api.patch(
1574
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1575
            data=json.dumps(payloads[1]),
1576
            content_type="application/json",
1577
        )
1578
        evc_deploy.assert_not_called()
1579
        self.assertEqual(405, response.status_code)
1580
1581 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...
1582
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1583
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1584
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1585
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1586
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1587
    def test_update_circuit_invalid_json(self, *args):
1588
        """Test update a circuit circuit."""
1589
        # pylint: disable=too-many-locals
1590
        (
1591
            evc_as_dict_mock,
1592
            validate_mock,
1593
            mongo_controller_upsert_mock,
1594
            uni_from_dict_mock,
1595
            sched_add_mock,
1596
            evc_deploy_mock,
1597
        ) = args
1598
1599
        validate_mock.return_value = True
1600
        mongo_controller_upsert_mock.return_value = True
1601
        sched_add_mock.return_value = True
1602
        evc_deploy_mock.return_value = True
1603
        uni1 = create_autospec(UNI)
1604
        uni2 = create_autospec(UNI)
1605
        uni1.interface = create_autospec(Interface)
1606
        uni2.interface = create_autospec(Interface)
1607
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1608
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1609
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1610
1611
        api = self.get_app_test_client(self.napp)
1612
        payload1 = {
1613
            "name": "my evc1",
1614
            "uni_a": {
1615
                "interface_id": "00:00:00:00:00:00:00:01:1",
1616
                "tag": {"tag_type": 1, "value": 80},
1617
            },
1618
            "uni_z": {
1619
                "interface_id": "00:00:00:00:00:00:00:02:2",
1620
                "tag": {"tag_type": 1, "value": 1},
1621
            },
1622
            "dynamic_backup_path": True,
1623
        }
1624
1625
        payload2 = {
1626
            "dynamic_backup_path": False,
1627
        }
1628
1629
        evc_as_dict_mock.return_value = payload1
1630
        response = api.post(
1631
            f"{self.server_name_url}/v2/evc/",
1632
            data=json.dumps(payload1),
1633
            content_type="application/json",
1634
        )
1635
        self.assertEqual(201, response.status_code)
1636
1637
        evc_as_dict_mock.return_value = payload2
1638
        current_data = json.loads(response.data)
1639
        circuit_id = current_data["circuit_id"]
1640
        response = api.patch(
1641
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1642
            data=payload2,
1643
            content_type="application/json",
1644
        )
1645
        current_data = json.loads(response.data)
1646
        expected_data = "The request body is not a well-formed JSON."
1647
        self.assertEqual(current_data["description"], expected_data)
1648
        self.assertEqual(400, response.status_code)
1649
1650
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
1651
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1652
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1653
    @patch("napps.kytos.mef_eline.main.Main._link_from_dict")
1654
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1655
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1656
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1657
    @patch("napps.kytos.mef_eline.models.path.Path.is_valid")
1658
    def test_update_circuit_invalid_path(self, *args):
1659
        """Test update a circuit circuit."""
1660
        # pylint: disable=too-many-locals
1661
        (
1662
            is_valid_mock,
1663
            evc_as_dict_mock,
1664
            validate_mock,
1665
            mongo_controller_upsert_mock,
1666
            link_from_dict_mock,
1667
            uni_from_dict_mock,
1668
            sched_add_mock,
1669
            evc_deploy_mock,
1670
        ) = args
1671
1672
        is_valid_mock.side_effect = InvalidPath("error")
1673
        validate_mock.return_value = True
1674
        mongo_controller_upsert_mock.return_value = True
1675
        sched_add_mock.return_value = True
1676
        evc_deploy_mock.return_value = True
1677
        link_from_dict_mock.return_value = 1
1678
        uni1 = create_autospec(UNI)
1679
        uni2 = create_autospec(UNI)
1680
        uni1.interface = create_autospec(Interface)
1681
        uni2.interface = create_autospec(Interface)
1682
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1683
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1684
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1685
1686
        api = self.get_app_test_client(self.napp)
1687
        payload1 = {
1688
            "name": "my evc1",
1689
            "uni_a": {
1690
                "interface_id": "00:00:00:00:00:00:00:01:1",
1691
                "tag": {"tag_type": 1, "value": 80},
1692
            },
1693
            "uni_z": {
1694
                "interface_id": "00:00:00:00:00:00:00:02:2",
1695
                "tag": {"tag_type": 1, "value": 1},
1696
            },
1697
            "dynamic_backup_path": True,
1698
        }
1699
1700
        payload2 = {
1701
            "primary_path": [
1702
                {
1703
                    "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1704
                    "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"},
1705
                }
1706
            ]
1707
        }
1708
1709
        evc_as_dict_mock.return_value = payload1
1710
        response = api.post(
1711
            f"{self.server_name_url}/v2/evc/",
1712
            data=json.dumps(payload1),
1713
            content_type="application/json",
1714
        )
1715
        self.assertEqual(201, response.status_code)
1716
1717
        evc_as_dict_mock.return_value = payload2
1718
        current_data = json.loads(response.data)
1719
        circuit_id = current_data["circuit_id"]
1720
        response = api.patch(
1721
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1722
            data=json.dumps(payload2),
1723
            content_type="application/json",
1724
        )
1725
        current_data = json.loads(response.data)
1726
        expected_data = "primary_path is not a valid path: error"
1727
        self.assertEqual(400, response.status_code)
1728
        self.assertEqual(current_data["description"], expected_data)
1729
1730
    def test_link_from_dict_non_existent_intf(self):
1731
        """Test _link_from_dict non existent intf."""
1732
        self.napp.controller.get_interface_by_id = MagicMock(return_value=None)
1733
        link_dict = {
1734
            "endpoint_a": {"id": "a"},
1735
            "endpoint_b": {"id": "b"}
1736
        }
1737
        with self.assertRaises(ValueError):
1738
            self.napp._link_from_dict(link_dict)
1739
1740
    def test_uni_from_dict_non_existent_intf(self):
1741
        """Test _link_from_dict non existent intf."""
1742
        self.napp.controller.get_interface_by_id = MagicMock(return_value=None)
1743
        uni_dict = {
1744
            "interface_id": "aaa",
1745
        }
1746
        with self.assertRaises(ValueError):
1747
            self.napp._uni_from_dict(uni_dict)
1748
1749 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...
1750
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1751
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1752
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1753
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1754
    def test_update_evc_no_json_mime(self, *args):
1755
        """Test update a circuit with wrong mimetype."""
1756
        # pylint: disable=too-many-locals
1757
        (
1758
            mongo_controller_upsert_mock,
1759
            validate_mock,
1760
            uni_from_dict_mock,
1761
            sched_add_mock,
1762
            evc_deploy_mock,
1763
        ) = args
1764
1765
        validate_mock.return_value = True
1766
        sched_add_mock.return_value = True
1767
        evc_deploy_mock.return_value = True
1768
        uni1 = create_autospec(UNI)
1769
        uni2 = create_autospec(UNI)
1770
        uni1.interface = create_autospec(Interface)
1771
        uni2.interface = create_autospec(Interface)
1772
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1773
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1774
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1775
        mongo_controller_upsert_mock.return_value = True
1776
1777
        api = self.get_app_test_client(self.napp)
1778
        payload1 = {
1779
            "name": "my evc1",
1780
            "uni_a": {
1781
                "interface_id": "00:00:00:00:00:00:00:01:1",
1782
                "tag": {"tag_type": 1, "value": 80},
1783
            },
1784
            "uni_z": {
1785
                "interface_id": "00:00:00:00:00:00:00:02:2",
1786
                "tag": {"tag_type": 1, "value": 1},
1787
            },
1788
            "dynamic_backup_path": True,
1789
        }
1790
1791
        payload2 = {"dynamic_backup_path": False}
1792
1793
        response = api.post(
1794
            f"{self.server_name_url}/v2/evc/",
1795
            data=json.dumps(payload1),
1796
            content_type="application/json",
1797
        )
1798
        self.assertEqual(201, response.status_code)
1799
1800
        current_data = json.loads(response.data)
1801
        circuit_id = current_data["circuit_id"]
1802
        response = api.patch(
1803
            f"{self.server_name_url}/v2/evc/{circuit_id}", data=payload2
1804
        )
1805
        current_data = json.loads(response.data)
1806
        expected_data = "The request body mimetype is not application/json."
1807
        self.assertEqual(current_data["description"], expected_data)
1808
        self.assertEqual(415, response.status_code)
1809
1810
    def test_delete_no_evc(self):
1811
        """Test delete when EVC does not exist."""
1812
        api = self.get_app_test_client(self.napp)
1813
        response = api.delete(f"{self.server_name_url}/v2/evc/123")
1814
        current_data = json.loads(response.data)
1815
        expected_data = "circuit_id 123 not found"
1816
        self.assertEqual(current_data["description"], expected_data)
1817
        self.assertEqual(404, response.status_code)
1818
1819
    @patch("napps.kytos.mef_eline.models.evc.EVC.remove_current_flows")
1820
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
1821
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1822
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1823
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1824
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1825
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1826
    def test_delete_archived_evc(self, *args):
1827
        """Try to delete an archived EVC"""
1828
        # pylint: disable=too-many-locals
1829
        (
1830
            evc_as_dict_mock,
1831
            validate_mock,
1832
            mongo_controller_upsert_mock,
1833
            uni_from_dict_mock,
1834
            sched_add_mock,
1835
            evc_deploy_mock,
1836
            remove_current_flows_mock
1837
        ) = args
1838
1839
        validate_mock.return_value = True
1840
        mongo_controller_upsert_mock.return_value = True
1841
        sched_add_mock.return_value = True
1842
        evc_deploy_mock.return_value = True
1843
        remove_current_flows_mock.return_value = True
1844
        uni1 = create_autospec(UNI)
1845
        uni2 = create_autospec(UNI)
1846
        uni1.interface = create_autospec(Interface)
1847
        uni2.interface = create_autospec(Interface)
1848
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1849
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1850
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1851
1852
        api = self.get_app_test_client(self.napp)
1853
        payload1 = {
1854
            "name": "my evc1",
1855
            "uni_a": {
1856
                "interface_id": "00:00:00:00:00:00:00:01:1",
1857
                "tag": {"tag_type": 1, "value": 80},
1858
            },
1859
            "uni_z": {
1860
                "interface_id": "00:00:00:00:00:00:00:02:2",
1861
                "tag": {"tag_type": 1, "value": 1},
1862
            },
1863
            "dynamic_backup_path": True,
1864
        }
1865
1866
        evc_as_dict_mock.return_value = payload1
1867
        response = api.post(
1868
            f"{self.server_name_url}/v2/evc/",
1869
            data=json.dumps(payload1),
1870
            content_type="application/json",
1871
        )
1872
        self.assertEqual(201, response.status_code)
1873
1874
        current_data = json.loads(response.data)
1875
        circuit_id = current_data["circuit_id"]
1876
        response = api.delete(
1877
            f"{self.server_name_url}/v2/evc/{circuit_id}"
1878
        )
1879
        self.assertEqual(200, response.status_code)
1880
1881
        response = api.delete(
1882
            f"{self.server_name_url}/v2/evc/{circuit_id}"
1883
        )
1884
        current_data = json.loads(response.data)
1885
        expected_data = f"Circuit {circuit_id} already removed"
1886
        self.assertEqual(current_data["description"], expected_data)
1887
        self.assertEqual(404, response.status_code)
1888
1889
    def test_handle_link_up(self):
1890
        """Test handle_link_up method."""
1891
        evc_mock = create_autospec(EVC)
1892
        evc_mock.service_level, evc_mock.creation_time = 0, 1
1893
        evc_mock.is_enabled = MagicMock(side_effect=[True, False, True])
1894
        evc_mock.lock = MagicMock()
1895
        type(evc_mock).archived = PropertyMock(
1896
            side_effect=[True, False, False]
1897
        )
1898
        evcs = [evc_mock, evc_mock, evc_mock]
1899
        event = KytosEvent(name="test", content={"link": "abc"})
1900
        self.napp.circuits = dict(zip(["1", "2", "3"], evcs))
1901
        self.napp.handle_link_up(event)
1902
        evc_mock.handle_link_up.assert_called_once_with("abc")
1903
1904
    @patch("time.sleep", return_value=None)
1905
    @patch("napps.kytos.mef_eline.main.settings")
1906
    @patch("napps.kytos.mef_eline.main.emit_event")
1907
    def test_handle_link_down(self, emit_event_mock, settings_mock, _):
1908
        """Test handle_link_down method."""
1909
        uni = create_autospec(UNI)
1910
        evc1 = MagicMock(id="1", service_level=0, creation_time=1,
1911
                         metadata="mock", _active="true", _enabled="true",
1912
                         uni_a=uni, uni_z=uni)
1913
        evc1.name = "name"
1914
        evc1.is_affected_by_link.return_value = True
1915
        evc1.handle_link_down.return_value = True
1916
        evc1.failover_path = None
1917
        evc2 = MagicMock(id="2", service_level=6, creation_time=1)
1918
        evc2.is_affected_by_link.return_value = False
1919
        evc3 = MagicMock(id="3", service_level=5, creation_time=1,
1920
                         metadata="mock", _active="true", _enabled="true",
1921
                         uni_a=uni, uni_z=uni)
1922
        evc3.name = "name"
1923
        evc3.is_affected_by_link.return_value = True
1924
        evc3.handle_link_down.return_value = True
1925
        evc3.failover_path = None
1926
        evc4 = MagicMock(id="4", service_level=4, creation_time=1,
1927
                         metadata="mock", _active="true", _enabled="true",
1928
                         uni_a=uni, uni_z=uni)
1929
        evc4.name = "name"
1930
        evc4.is_affected_by_link.return_value = True
1931
        evc4.is_failover_path_affected_by_link.return_value = False
1932
        evc4.failover_path = ["2"]
1933
        evc4.get_failover_flows.return_value = {
1934
            "2": ["flow1", "flow2"],
1935
            "3": ["flow3", "flow4", "flow5", "flow6"],
1936
        }
1937
        evc5 = MagicMock(id="5", service_level=7, creation_time=1)
1938
        evc5.is_affected_by_link.return_value = True
1939
        evc5.is_failover_path_affected_by_link.return_value = False
1940
        evc5.failover_path = ["3"]
1941
        evc5.get_failover_flows.return_value = {
1942
            "4": ["flow7", "flow8"],
1943
            "5": ["flow9", "flow10"],
1944
        }
1945
        link = MagicMock(id="123")
1946
        event = KytosEvent(name="test", content={"link": link})
1947
        self.napp.circuits = {"1": evc1, "2": evc2, "3": evc3, "4": evc4,
1948
                              "5": evc5}
1949
        settings_mock.BATCH_SIZE = 2
1950
        self.napp.handle_link_down(event)
1951
1952
        assert evc5.service_level > evc4.service_level
1953
        # evc5 batched flows should be sent first
1954
        emit_event_mock.assert_has_calls([
1955
            call(
1956
                self.napp.controller,
1957
                context="kytos.flow_manager",
1958
                name="flows.install",
1959
                content={
1960
                    "dpid": "4",
1961
                    "flow_dict": {"flows": ["flow7", "flow8"]},
1962
                }
1963
            ),
1964
            call(
1965
                self.napp.controller,
1966
                context="kytos.flow_manager",
1967
                name="flows.install",
1968
                content={
1969
                    "dpid": "5",
1970
                    "flow_dict": {"flows": ["flow9", "flow10"]},
1971
                }
1972
            ),
1973
            call(
1974
                self.napp.controller,
1975
                context="kytos.flow_manager",
1976
                name="flows.install",
1977
                content={
1978
                    "dpid": "2",
1979
                    "flow_dict": {"flows": ["flow1", "flow2"]},
1980
                }
1981
            ),
1982
            call(
1983
                self.napp.controller,
1984
                context="kytos.flow_manager",
1985
                name="flows.install",
1986
                content={
1987
                    "dpid": "3",
1988
                    "flow_dict": {"flows": ["flow3", "flow4"]},
1989
                }
1990
            ),
1991
            call(
1992
                self.napp.controller,
1993
                context="kytos.flow_manager",
1994
                name="flows.install",
1995
                content={
1996
                    "dpid": "3",
1997
                    "flow_dict": {"flows": ["flow5", "flow6"]},
1998
                }
1999
            ),
2000
        ])
2001
        event_name = "evc_affected_by_link_down"
2002
        assert evc3.service_level > evc1.service_level
2003
        # evc3 should be handled before evc1
2004
        emit_event_mock.assert_has_calls([
2005
            call(self.napp.controller, event_name, content={
2006
                "link_id": "123",
2007
                "evc_id": "3",
2008
                "name": "name",
2009
                "metadata": "mock",
2010
                "active": "true",
2011
                "enabled": "true",
2012
                "uni_a": uni.as_dict(),
2013
                "uni_z": uni.as_dict(),
2014
            }),
2015
            call(self.napp.controller, event_name, content={
2016
                "link_id": "123",
2017
                "evc_id": "1",
2018
                "name": "name",
2019
                "metadata": "mock",
2020
                "active": "true",
2021
                "enabled": "true",
2022
                "uni_a": uni.as_dict(),
2023
                "uni_z": uni.as_dict(),
2024
            }),
2025
        ])
2026
        evc4.sync.assert_called_once()
2027
        event_name = "redeployed_link_down"
2028
        emit_event_mock.assert_has_calls([
2029
            call(self.napp.controller, event_name, content={
2030
                "evc_id": "4",
2031
                "name": "name",
2032
                "metadata": "mock",
2033
                "active": "true",
2034
                "enabled": "true",
2035
                "uni_a": uni.as_dict(),
2036
                "uni_z": uni.as_dict(),
2037
            }),
2038
        ])
2039
2040
    @patch("napps.kytos.mef_eline.main.emit_event")
2041
    def test_handle_evc_affected_by_link_down(self, emit_event_mock):
2042
        """Test handle_evc_affected_by_link_down method."""
2043
        uni = create_autospec(UNI)
2044
        evc1 = MagicMock(
2045
            id="1",
2046
            metadata="data_mocked",
2047
            _active="true",
2048
            _enabled="false",
2049
            uni_a=uni,
2050
            uni_z=uni,
2051
        )
2052
        evc1.name = "name_mocked"
2053
        evc1.handle_link_down.return_value = True
2054
        evc2 = MagicMock(
2055
            id="2",
2056
            metadata="mocked_data",
2057
            _active="false",
2058
            _enabled="true",
2059
            uni_a=uni,
2060
            uni_z=uni,
2061
        )
2062
        evc2.name = "mocked_name"
2063
        evc2.handle_link_down.return_value = False
2064
        self.napp.circuits = {"1": evc1, "2": evc2}
2065
2066
        event = KytosEvent(name="e1", content={
2067
            "evc_id": "3",
2068
            "link_id": "1",
2069
        })
2070
        self.napp.handle_evc_affected_by_link_down(event)
2071
        emit_event_mock.assert_not_called()
2072
        event.content["evc_id"] = "1"
2073
        self.napp.handle_evc_affected_by_link_down(event)
2074
        emit_event_mock.assert_called_with(
2075
            self.napp.controller, "redeployed_link_down", content={
2076
                "evc_id": "1",
2077
                "name": "name_mocked",
2078
                "metadata": "data_mocked",
2079
                "active": "true",
2080
                "enabled": "false",
2081
                "uni_a": uni.as_dict(),
2082
                "uni_z": uni.as_dict(),
2083
            }
2084
        )
2085
2086
        event.content["evc_id"] = "2"
2087
        self.napp.handle_evc_affected_by_link_down(event)
2088
        emit_event_mock.assert_called_with(
2089
            self.napp.controller, "error_redeploy_link_down", content={
2090
                "evc_id": "2",
2091
                "name": "mocked_name",
2092
                "metadata": "mocked_data",
2093
                "active": "false",
2094
                "enabled": "true",
2095
                "uni_a": uni.as_dict(),
2096
                "uni_z": uni.as_dict(),
2097
            }
2098
        )
2099
2100
    def test_handle_evc_deployed(self):
2101
        """Test handle_evc_deployed method."""
2102
        evc = create_autospec(EVC, id="1")
2103
        evc.lock = MagicMock()
2104
        self.napp.circuits = {"1": evc}
2105
2106
        event = KytosEvent(name="e1", content={"evc_id": "2"})
2107
        self.napp.handle_evc_deployed(event)
2108
        evc.setup_failover_path.assert_not_called()
2109
2110
        event.content["evc_id"] = "1"
2111
        self.napp.handle_evc_deployed(event)
2112
        evc.setup_failover_path.assert_called()
2113
2114
    def test_add_metadata(self):
2115
        """Test method to add metadata"""
2116
        evc_mock = create_autospec(EVC)
2117
        evc_mock.metadata = {}
2118
        evc_mock.id = 1234
2119
        self.napp.circuits = {"1234": evc_mock}
2120
2121
        api = self.get_app_test_client(self.napp)
2122
        payload = {"metadata1": 1, "metadata2": 2}
2123
        response = api.post(
2124
            f"{self.server_name_url}/v2/evc/1234/metadata",
2125
            data=json.dumps(payload),
2126
            content_type="application/json",
2127
        )
2128
2129
        self.assertEqual(response.status_code, 201)
2130
        evc_mock.extend_metadata.assert_called_with(payload)
2131
2132
    def test_add_metadata_malformed_json(self):
2133
        """Test method to add metadata with a malformed json"""
2134
        api = self.get_app_test_client(self.napp)
2135
        payload = '{"metadata1": 1, "metadata2": 2,}'
2136
        response = api.post(
2137
            f"{self.server_name_url}/v2/evc/1234/metadata",
2138
            data=payload,
2139
            content_type="application/json"
2140
        )
2141
2142
        self.assertEqual(response.status_code, 400)
2143
        self.assertEqual(
2144
            response.json["description"],
2145
            "The request body is not a well-formed JSON."
2146
        )
2147
2148
    def test_add_metadata_no_body(self):
2149
        """Test method to add metadata with no body"""
2150
        api = self.get_app_test_client(self.napp)
2151
        response = api.post(
2152
            f"{self.server_name_url}/v2/evc/1234/metadata"
2153
        )
2154
        self.assertEqual(response.status_code, 400)
2155
        self.assertEqual(
2156
            response.json["description"],
2157
            "The request body is empty."
2158
        )
2159
2160
    def test_add_metadata_no_evc(self):
2161
        """Test method to add metadata with no evc"""
2162
        api = self.get_app_test_client(self.napp)
2163
        payload = {"metadata1": 1, "metadata2": 2}
2164
        response = api.post(
2165
            f"{self.server_name_url}/v2/evc/1234/metadata",
2166
            data=json.dumps(payload),
2167
            content_type="application/json",
2168
        )
2169
        self.assertEqual(response.status_code, 404)
2170
        self.assertEqual(
2171
            response.json["description"],
2172
            "circuit_id 1234 not found."
2173
        )
2174
2175
    def test_add_metadata_wrong_content_type(self):
2176
        """Test method to add metadata with wrong content type"""
2177
        api = self.get_app_test_client(self.napp)
2178
        payload = {"metadata1": 1, "metadata2": 2}
2179
        response = api.post(
2180
            f"{self.server_name_url}/v2/evc/1234/metadata",
2181
            data=json.dumps(payload),
2182
            content_type="application/xml",
2183
        )
2184
        self.assertEqual(response.status_code, 415)
2185
        self.assertEqual(
2186
            response.json["description"],
2187
            "The content type must be application/json "
2188
            "(received application/xml)."
2189
        )
2190
2191
    def test_get_metadata(self):
2192
        """Test method to get metadata"""
2193
        evc_mock = create_autospec(EVC)
2194
        evc_mock.metadata = {'metadata1': 1, 'metadata2': 2}
2195
        evc_mock.id = 1234
2196
        self.napp.circuits = {"1234": evc_mock}
2197
2198
        api = self.get_app_test_client(self.napp)
2199
        response = api.get(
2200
            f"{self.server_name_url}/v2/evc/1234/metadata",
2201
        )
2202
        self.assertEqual(response.status_code, 200)
2203
        self.assertEqual(response.json, {"metadata": evc_mock.metadata})
2204
2205
    def test_delete_metadata(self):
2206
        """Test method to delete metadata"""
2207
        evc_mock = create_autospec(EVC)
2208
        evc_mock.metadata = {'metadata1': 1, 'metadata2': 2}
2209
        evc_mock.id = 1234
2210
        self.napp.circuits = {"1234": evc_mock}
2211
2212
        api = self.get_app_test_client(self.napp)
2213
        response = api.delete(
2214
            f"{self.server_name_url}/v2/evc/1234/metadata/metadata1",
2215
        )
2216
        self.assertEqual(response.status_code, 200)
2217
2218
    def test_delete_metadata_no_evc(self):
2219
        """Test method to delete metadata with no evc"""
2220
        api = self.get_app_test_client(self.napp)
2221
        response = api.delete(
2222
            f"{self.server_name_url}/v2/evc/1234/metadata/metadata1",
2223
        )
2224
        self.assertEqual(response.status_code, 404)
2225
        self.assertEqual(
2226
            response.json["description"],
2227
            "circuit_id 1234 not found."
2228
        )
2229
2230
    @patch('napps.kytos.mef_eline.main.Main._load_evc')
2231
    def test_load_all_evcs(self, load_evc_mock):
2232
        """Test load_evcs method"""
2233
        mock_circuits = {
2234
            'circuits': {
2235
                1: 'circuit_1',
2236
                2: 'circuit_2',
2237
                3: 'circuit_3',
2238
                4: 'circuit_4'
2239
            }
2240
        }
2241
        self.napp.mongo_controller.get_circuits.return_value = mock_circuits
2242
        self.napp.circuits = {2: 'circuit_2', 3: 'circuit_3'}
2243
        self.napp.load_all_evcs()
2244
        load_evc_mock.assert_has_calls([call('circuit_1'), call('circuit_4')])
2245
2246
    @patch('napps.kytos.mef_eline.main.Main._evc_from_dict')
2247
    def test_load_evc(self, evc_from_dict_mock):
2248
        """Test _load_evc method"""
2249
        # pylint: disable=protected-access
2250
        # case 1: early return with ValueError exception
2251
        evc_from_dict_mock.side_effect = ValueError("err")
2252
        evc_dict = MagicMock()
2253
        self.assertEqual(self.napp._load_evc(evc_dict), None)
2254
2255
        # case2: archived evc
2256
        evc = MagicMock()
2257
        evc.archived = True
2258
        evc_from_dict_mock.side_effect = None
2259
        evc_from_dict_mock.return_value = evc
2260
        self.assertEqual(self.napp._load_evc(evc_dict), None)
2261
2262
        # case3: success creating
2263
        evc.archived = False
2264
        evc.id = 1
2265
        self.napp.sched = MagicMock()
2266
2267
        result = self.napp._load_evc(evc_dict)
2268
        self.assertEqual(result, evc)
2269
        evc.deactivate.assert_called()
2270
        evc.sync.assert_called()
2271
        self.napp.sched.add.assert_called_with(evc)
2272
        self.assertEqual(self.napp.circuits[1], evc)
2273
2274
    def test_handle_flow_mod_error(self):
2275
        """Test handle_flow_mod_error method"""
2276
        flow = MagicMock()
2277
        flow.cookie = 0xaa00000000000011
2278
        event = MagicMock()
2279
        event.content = {'flow': flow, 'error_command': 'add'}
2280
        evc = create_autospec(EVC)
2281
        evc.remove_current_flows = MagicMock()
2282
        self.napp.circuits = {"00000000000011": evc}
2283
        self.napp.handle_flow_mod_error(event)
2284
        evc.remove_current_flows.assert_called_once()
2285
2286
    @patch("kytos.core.Controller.get_interface_by_id")
2287
    def test_uni_from_dict(self, _get_interface_by_id_mock):
2288
        """Test _uni_from_dict method."""
2289
        # pylint: disable=protected-access
2290
        # case1: early return on empty dict
2291
        self.assertEqual(self.napp._uni_from_dict(None), False)
2292
2293
        # case2: invalid interface raises ValueError
2294
        _get_interface_by_id_mock.return_value = None
2295
        uni_dict = {
2296
            "interface_id": "00:01:1",
2297
            "tag": {"tag_type": 1, "value": 81},
2298
        }
2299
        with self.assertRaises(ValueError):
2300
            self.napp._uni_from_dict(uni_dict)
2301
2302
        # case3: success creation
2303
        uni_mock = get_uni_mocked(switch_id="00:01")
2304
        _get_interface_by_id_mock.return_value = uni_mock.interface
2305
        uni = self.napp._uni_from_dict(uni_dict)
2306
        self.assertEqual(uni, uni_mock)
2307
2308
        # case4: success creation without tag
2309
        uni_mock.user_tag = None
2310
        del uni_dict["tag"]
2311
        uni = self.napp._uni_from_dict(uni_dict)
2312
        self.assertEqual(uni, uni_mock)
2313
2314
    def test_handle_flow_delete(self):
2315
        """Test handle_flow_delete method"""
2316
        flow = MagicMock()
2317
        flow.cookie = 0xaa00000000000011
2318
        event = MagicMock()
2319
        event.content = {'flow': flow}
2320
        evc = create_autospec(EVC)
2321
        evc.set_flow_removed_at = MagicMock()
2322
        self.napp.circuits = {"00000000000011": evc}
2323
        self.napp.handle_flow_delete(event)
2324
        evc.set_flow_removed_at.assert_called_once()
2325
2326 View Code Duplication
    def test_add_bulk_metadata(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2327
        """Test add_bulk_metadata method"""
2328
        evc_mock = create_autospec(EVC)
2329
        evc_mock.id = 1234
2330
        self.napp.circuits = {"1234": evc_mock}
2331
        api = self.get_app_test_client(self.napp)
2332
        payload = {
2333
            "circuit_ids": ["1234"],
2334
            "metadata1": 1,
2335
            "metadata2": 2
2336
        }
2337
        response = api.post(
2338
            f"{self.server_name_url}/v2/evc/metadata",
2339
            data=json.dumps(payload),
2340
            content_type="application/json",
2341
        )
2342
        self.assertEqual(response.status_code, 201)
2343
        args = self.napp.mongo_controller.update_evcs.call_args[0]
2344
        ids = payload.pop("circuit_ids")
2345
        self.assertEqual(args[0], ids)
2346
        self.assertEqual(args[1], payload)
2347
        self.assertEqual(args[2], "add")
2348
        calls = self.napp.mongo_controller.update_evcs.call_count
2349
        self.assertEqual(calls, 1)
2350
        evc_mock.extend_metadata.assert_called_with(payload)
2351
2352
    def test_add_bulk_metadata_no_id(self):
2353
        """Test add_bulk_metadata with unknown evc id"""
2354
        evc_mock = create_autospec(EVC)
2355
        evc_mock.id = 1234
2356
        self.napp.circuits = {"1234": evc_mock}
2357
        api = self.get_app_test_client(self.napp)
2358
        payload = {
2359
            "circuit_ids": ["1234", "4567"]
2360
        }
2361
        response = api.post(
2362
            f"{self.server_name_url}/v2/evc/metadata",
2363
            data=json.dumps(payload),
2364
            content_type="application/json",
2365
        )
2366
        self.assertEqual(response.status_code, 404)
2367
2368
    def test_add_bulk_metadata_no_circuits(self):
2369
        """Test add_bulk_metadata without circuit_ids"""
2370
        evc_mock = create_autospec(EVC)
2371
        evc_mock.id = 1234
2372
        self.napp.circuits = {"1234": evc_mock}
2373
        api = self.get_app_test_client(self.napp)
2374
        payload = {
2375
            "metadata": "data"
2376
        }
2377
        response = api.post(
2378
            f"{self.server_name_url}/v2/evc/metadata",
2379
            data=json.dumps(payload),
2380
            content_type="application/json",
2381
        )
2382
        self.assertEqual(response.status_code, 400)
2383
2384 View Code Duplication
    def test_delete_bulk_metadata(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2385
        """Test delete_metadata method"""
2386
        evc_mock = create_autospec(EVC)
2387
        evc_mock.id = 1234
2388
        self.napp.circuits = {"1234": evc_mock}
2389
        api = self.get_app_test_client(self.napp)
2390
        payload = {
2391
            "circuit_ids": ["1234"]
2392
        }
2393
        response = api.delete(
2394
            f"{self.server_name_url}/v2/evc/metadata/metadata1",
2395
            data=json.dumps(payload),
2396
            content_type="application/json",
2397
        )
2398
        self.assertEqual(response.status_code, 200)
2399
        args = self.napp.mongo_controller.update_evcs.call_args[0]
2400
        self.assertEqual(args[0], payload["circuit_ids"])
2401
        self.assertEqual(args[1], {"metadata1": ""})
2402
        self.assertEqual(args[2], "del")
2403
        calls = self.napp.mongo_controller.update_evcs.call_count
2404
        self.assertEqual(calls, 1)
2405
        self.assertEqual(evc_mock.remove_metadata.call_count, 1)
2406