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

TestMain.test_create_circuit_already_enabled()   B

Complexity

Conditions 1

Size

Total Lines 59
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 48
nop 8
dl 0
loc 59
ccs 28
cts 28
cp 1
crap 1
rs 8.7018
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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