Passed
Push — master ( e3f2ff...728489 )
by Vinicius
02:32 queued 14s
created

TestMain.test_update_disabled_intra_switch()   B

Complexity

Conditions 1

Size

Total Lines 66
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 48
nop 6
dl 0
loc 66
ccs 21
cts 21
cp 1
crap 1
rs 8.7018
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

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