Passed
Pull Request — master (#330)
by
unknown
07:02
created

TestMain.test_update_circuit()   B

Complexity

Conditions 1

Size

Total Lines 152
Code Lines 110

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 52
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 110
nop 11
dl 0
loc 152
ccs 52
cts 52
cp 1
crap 1
rs 7
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 = MagicMock()
427 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
428 1
        uni1.interface.switch.status = EntityStatus.UP
429 1
        uni2.interface.switch = MagicMock()
430 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
431 1
        uni2.interface.switch.status = EntityStatus.UP
432 1
        uni_from_dict_mock.side_effect = [uni1, uni2]
433 1
        evc_as_dict_mock.return_value = {}
434 1
        sched_add_mock.return_value = True
435 1
        self.napp.mongo_controller.get_circuits.return_value = {}
436
437 1
        url = f"{self.base_endpoint}/v2/evc/"
438 1
        payload = {
439
            "name": "my evc1",
440
            "frequency": "* * * * *",
441
            "uni_a": {
442
                "interface_id": "00:00:00:00:00:00:00:01:1",
443
                "tag": {"tag_type": 1, "value": 80},
444
            },
445
            "uni_z": {
446
                "interface_id": "00:00:00:00:00:00:00:02:2",
447
                "tag": {"tag_type": 1, "value": 1},
448
            },
449
            "dynamic_backup_path": True,
450
            "primary_constraints": {
451
                "spf_max_path_cost": 8,
452
                "mandatory_metrics": {
453
                    "ownership": "red"
454
                }
455
            },
456
            "secondary_constraints": {
457
                "mandatory_metrics": {
458
                    "ownership": "blue"
459
                }
460
            }
461
        }
462
463 1
        response = await self.api_client.post(url, json=payload)
464 1
        current_data = response.json()
465
466
        # verify expected result from request
467 1
        assert 201 == response.status_code
468 1
        assert "circuit_id" in current_data
469
470
        # verify uni called
471 1
        uni_from_dict_mock.called_twice()
472 1
        uni_from_dict_mock.assert_any_call(payload["uni_z"])
473 1
        uni_from_dict_mock.assert_any_call(payload["uni_a"])
474
475
        # verify validation called
476 1
        validate_mock.assert_called_once()
477 1
        validate_mock.assert_called_with(
478
            table_group={'evpl': 0, 'epl': 0},
479
            frequency="* * * * *",
480
            name="my evc1",
481
            uni_a=uni1,
482
            uni_z=uni2,
483
            dynamic_backup_path=True,
484
            primary_constraints=payload["primary_constraints"],
485
            secondary_constraints=payload["secondary_constraints"],
486
        )
487
        # verify save method is called
488 1
        mongo_controller_upsert_mock.assert_called_once()
489
490
        # verify evc as dict is called to save in the box
491 1
        evc_as_dict_mock.assert_called()
492
        # verify add circuit in sched
493 1
        sched_add_mock.assert_called_once()
494
495 1
    async def test_create_a_circuit_case_2(self, event_loop):
496
        """Test create a new circuit trying to send request without a json."""
497 1
        self.napp.controller.loop = event_loop
498 1
        url = f"{self.base_endpoint}/v2/evc/"
499
500 1
        response = await self.api_client.post(url)
501 1
        current_data = response.json()
502 1
        assert 400 == response.status_code
503 1
        assert "Missing required request body" in current_data["description"]
504
505 1
    async def test_create_a_circuit_case_3(self, event_loop):
506
        """Test create a new circuit trying to send request with an
507
        invalid json."""
508 1
        self.napp.controller.loop = event_loop
509 1
        url = f"{self.base_endpoint}/v2/evc/"
510
511 1
        response = await self.api_client.post(
512
            url,
513
            json="This is an {Invalid:} JSON",
514
        )
515 1
        current_data = response.json()
516 1
        assert 400 == response.status_code
517 1
        assert "contains invalid" in current_data["description"]
518
519 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
520 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
521 1
    async def test_create_a_circuit_case_4(
522
        self,
523
        mongo_controller_upsert_mock,
524
        uni_from_dict_mock,
525
        event_loop
526
    ):
527
        """Test create a new circuit trying to send request with an
528
        invalid value."""
529 1
        self.napp.controller.loop = event_loop
530
        # pylint: disable=too-many-locals
531 1
        uni_from_dict_mock.side_effect = ValueError("Could not instantiate")
532 1
        mongo_controller_upsert_mock.return_value = True
533 1
        url = f"{self.base_endpoint}/v2/evc/"
534
535 1
        payload = {
536
            "name": "my evc1",
537
            "frequency": "* * * * *",
538
            "uni_a": {
539
                "interface_id": "00:00:00:00:00:00:00:01:76",
540
                "tag": {"tag_type": 1, "value": 80},
541
            },
542
            "uni_z": {
543
                "interface_id": "00:00:00:00:00:00:00:02:2",
544
                "tag": {"tag_type": 1, "value": 1},
545
            },
546
        }
547
548 1
        response = await self.api_client.post(url, json=payload)
549 1
        current_data = response.json()
550 1
        expected_data = "Error creating UNI: Invalid value"
551 1
        assert 400 == response.status_code
552 1
        assert current_data["description"] == expected_data
553
554 1
        payload["name"] = 1
555 1
        response = await self.api_client.post(url, json=payload)
556 1
        assert 400 == response.status_code, response.data
557
558 1
    async def test_create_a_circuit_invalid_queue_id(self, event_loop):
559
        """Test create a new circuit with invalid queue_id."""
560 1
        self.napp.controller.loop = event_loop
561 1
        url = f"{self.base_endpoint}/v2/evc/"
562
563 1
        payload = {
564
            "name": "my evc1",
565
            "queue_id": 8,
566
            "uni_a": {
567
                "interface_id": "00:00:00:00:00:00:00:01:76",
568
                "tag": {"tag_type": 1, "value": 80},
569
            },
570
            "uni_z": {
571
                "interface_id": "00:00:00:00:00:00:00:02:2",
572
                "tag": {"tag_type": 1, "value": 1},
573
            },
574
        }
575 1
        response = await self.api_client.post(url, json=payload)
576 1
        current_data = response.json()
577 1
        expected_data = "8 is greater than the maximum of 7"
578
579 1
        assert response.status_code == 400
580 1
        assert expected_data in current_data["description"]
581
582 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
583 1
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
584 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
585 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
586 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
587 1
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
588 1
    async def test_create_circuit_already_enabled(
589
        self,
590
        evc_as_dict_mock,
591
        validate_mock,
592
        mongo_controller_upsert_mock,
593
        uni_from_dict_mock,
594
        sched_add_mock,
595
        evc_deploy_mock,
596
        event_loop
597
    ):
598
        """Test create an already created circuit."""
599
        # pylint: disable=too-many-locals
600 1
        self.napp.controller.loop = event_loop
601 1
        validate_mock.return_value = True
602 1
        mongo_controller_upsert_mock.return_value = True
603 1
        sched_add_mock.return_value = True
604 1
        evc_deploy_mock.return_value = True
605 1
        uni1 = create_autospec(UNI)
606 1
        uni2 = create_autospec(UNI)
607 1
        uni1.interface = create_autospec(Interface)
608 1
        uni2.interface = create_autospec(Interface)
609 1
        uni1.interface.switch = MagicMock()
610 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
611 1
        uni1.interface.switch.status = EntityStatus.UP
612 1
        uni2.interface.switch = MagicMock()
613 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
614 1
        uni2.interface.switch.status = EntityStatus.UP
615 1
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
616
617 1
        payload = {
618
            "name": "my evc1",
619
            "uni_a": {
620
                "interface_id": "00:00:00:00:00:00:00:01:1",
621
                "tag": {"tag_type": 1, "value": 80},
622
            },
623
            "uni_z": {
624
                "interface_id": "00:00:00:00:00:00:00:02:2",
625
                "tag": {"tag_type": 1, "value": 1},
626
            },
627
            "dynamic_backup_path": True,
628
        }
629
630 1
        evc_as_dict_mock.return_value = payload
631 1
        response = await self.api_client.post(
632
            f"{self.base_endpoint}/v2/evc/",
633
            json=payload
634
        )
635 1
        assert 201 == response.status_code
636
637 1
        response = await self.api_client.post(
638
            f"{self.base_endpoint}/v2/evc/",
639
            json=payload
640
        )
641 1
        current_data = response.json()
642 1
        expected_data = "The EVC already exists."
643 1
        assert current_data["description"] == expected_data
644 1
        assert 409 == response.status_code
645
646 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
647 1
    async def test_create_circuit_case_5(self, uni_from_dict_mock, event_loop):
648
        """Test when neither primary path nor dynamic_backup_path is set."""
649 1
        self.napp.controller.loop = event_loop
650 1
        url = f"{self.base_endpoint}/v2/evc/"
651 1
        uni1 = create_autospec(UNI)
652 1
        uni2 = create_autospec(UNI)
653 1
        uni1.interface = create_autospec(Interface)
654 1
        uni2.interface = create_autospec(Interface)
655 1
        uni1.interface.switch = MagicMock()
656 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
657 1
        uni1.interface.switch.status = EntityStatus.UP
658 1
        uni2.interface.switch = MagicMock()
659 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
660 1
        uni2.interface.switch.status = EntityStatus.UP
661 1
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
662
663 1
        payload = {
664
            "name": "my evc1",
665
            "frequency": "* * * * *",
666
            "uni_a": {
667
                "interface_id": "00:00:00:00:00:00:00:01:1",
668
                "tag": {"tag_type": 1, "value": 80},
669
            },
670
            "uni_z": {
671
                "interface_id": "00:00:00:00:00:00:00:02:2",
672
                "tag": {"tag_type": 1, "value": 1},
673
            },
674
        }
675
676 1
        response = await self.api_client.post(url, json=payload)
677 1
        current_data = response.json()
678 1
        expected_data = "The EVC must have a primary path "
679 1
        expected_data += "or allow dynamic paths."
680 1
        assert 400 == response.status_code, response.data
681 1
        assert current_data["description"] == expected_data
682
683 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
684 1
    async def test_create_circuit_case_6(
685
        self,
686
        uni_from_dict_mock,
687
        event_loop
688
    ):
689
        """Test create a circuit with a disabled switch."""
690
        # pylint: disable=too-many-locals
691 1
        self.napp.controller.loop = event_loop
692 1
        uni1 = create_autospec(UNI)
693 1
        uni2 = create_autospec(UNI)
694 1
        uni1.interface = create_autospec(Interface)
695 1
        uni2.interface = create_autospec(Interface)
696 1
        uni1.interface.switch = MagicMock()
697 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
698 1
        uni1.interface.switch.status = EntityStatus.UP
699 1
        uni2.interface.switch = MagicMock()
700 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
701 1
        uni2.interface.switch.status = EntityStatus.DISABLED
702 1
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
703
704 1
        payload = {
705
            "name": "my evc1",
706
            "uni_a": {
707
                "interface_id": "00:00:00:00:00:00:00:01:1",
708
                "tag": {"tag_type": 1, "value": 80},
709
            },
710
            "uni_z": {
711
                "interface_id": "00:00:00:00:00:00:00:02:2",
712
                "tag": {"tag_type": 1, "value": 1},
713
            },
714
            "dynamic_backup_path": True,
715
        }
716
717 1
        response = await self.api_client.post(
718
            f"{self.base_endpoint}/v2/evc/",
719
            json=payload
720
        )
721 1
        assert 409 == response.status_code
722
723 1
    @patch("napps.kytos.mef_eline.main.Main._link_from_dict")
724 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
725 1
    async def test_create_circuit_case_7(
726
        self,
727
        uni_from_dict_mock,
728
        link_from_dict_mock,
729
        event_loop
730
    ):
731
        """Test create a circuit with a disabled switch in static path."""
732
        # pylint: disable=too-many-locals
733 1
        self.napp.controller.loop = event_loop
734 1
        link_from_dict_mock.return_value = 1
735 1
        uni1 = create_autospec(UNI)
736 1
        uni2 = create_autospec(UNI)
737 1
        uni1.interface = create_autospec(Interface)
738 1
        uni2.interface = create_autospec(Interface)
739 1
        uni1.interface.switch = MagicMock()
740 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
741 1
        uni1.interface.switch.status = EntityStatus.UP
742 1
        uni2.interface.switch = MagicMock()
743 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
744 1
        uni2.interface.switch.status = EntityStatus.DISABLED
745 1
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
746
747 1
        payload = {
748
            "name": "my evc1",
749
            "uni_a": {
750
                "interface_id": "00:00:00:00:00:00:00:01:1",
751
                "tag": {"tag_type": 1, "value": 80},
752
            },
753
            "uni_z": {
754
                "interface_id": "00:00:00:00:00:00:00:03:2",
755
                "tag": {"tag_type": 1, "value": 1},
756
            },
757
            "primary_path": [
758
                {"endpoint_a": {"id": "00:00:00:00:00:00:00:01:3"},
759
                 "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"}},
760
                {"endpoint_a": {"id": "00:00:00:00:00:00:00:02:3"},
761
                 "endpoint_b": {"id": "00:00:00:00:00:00:00:03:2"}}
762
            ],
763
        }
764
765 1
        response = await self.api_client.post(
766
            f"{self.base_endpoint}/v2/evc/",
767
            json=payload
768
        )
769 1
        assert 409 == response.status_code
770
771 1
    async def test_redeploy_evc(self):
772
        """Test endpoint to redeploy an EVC."""
773 1
        evc1 = MagicMock()
774 1
        evc1.is_enabled.return_value = True
775 1
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
776 1
        url = f"{self.base_endpoint}/v2/evc/1/redeploy"
777 1
        response = await self.api_client.patch(url)
778 1
        assert response.status_code == 202, response.data
779
780 1
    async def test_redeploy_evc_disabled(self):
781
        """Test endpoint to redeploy an EVC."""
782 1
        evc1 = MagicMock()
783 1
        evc1.is_enabled.return_value = False
784 1
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
785 1
        url = f"{self.base_endpoint}/v2/evc/1/redeploy"
786 1
        response = await self.api_client.patch(url)
787 1
        assert response.status_code == 409, response.data
788
789 1
    async def test_redeploy_evc_deleted(self):
790
        """Test endpoint to redeploy an EVC."""
791 1
        evc1 = MagicMock()
792 1
        evc1.is_enabled.return_value = True
793 1
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
794 1
        url = f"{self.base_endpoint}/v2/evc/3/redeploy"
795 1
        response = await self.api_client.patch(url)
796 1
        assert response.status_code == 404, response.data
797
798 1
    async def test_list_schedules__no_data_stored(self):
799
        """Test if list circuits return all circuits stored."""
800 1
        self.napp.mongo_controller.get_circuits.return_value = {"circuits": {}}
801
802 1
        url = f"{self.base_endpoint}/v2/evc/schedule"
803
804 1
        response = await self.api_client.get(url)
805 1
        assert response.status_code == 200
806 1
        assert not response.json()
807
808 1
    def _add_mongodb_schedule_data(self, data_mock):
809
        """Add schedule data to mongodb mock object."""
810 1
        circuits = {"circuits": {}}
811 1
        payload_1 = {
812
            "id": "aa:aa:aa",
813
            "name": "my evc1",
814
            "uni_a": {
815
                "interface_id": "00:00:00:00:00:00:00:01:1",
816
                "tag": {"tag_type": 1, "value": 80},
817
            },
818
            "uni_z": {
819
                "interface_id": "00:00:00:00:00:00:00:02:2",
820
                "tag": {"tag_type": 1, "value": 1},
821
            },
822
            "circuit_scheduler": [
823
                {"id": "1", "frequency": "* * * * *", "action": "create"},
824
                {"id": "2", "frequency": "1 * * * *", "action": "remove"},
825
            ],
826
        }
827 1
        circuits["circuits"].update({"aa:aa:aa": payload_1})
828 1
        payload_2 = {
829
            "id": "bb:bb:bb",
830
            "name": "my second evc2",
831
            "uni_a": {
832
                "interface_id": "00:00:00:00:00:00:00:01:2",
833
                "tag": {"tag_type": 1, "value": 90},
834
            },
835
            "uni_z": {
836
                "interface_id": "00:00:00:00:00:00:00:03:2",
837
                "tag": {"tag_type": 1, "value": 100},
838
            },
839
            "circuit_scheduler": [
840
                {"id": "3", "frequency": "1 * * * *", "action": "create"},
841
                {"id": "4", "frequency": "2 * * * *", "action": "remove"},
842
            ],
843
        }
844 1
        circuits["circuits"].update({"bb:bb:bb": payload_2})
845 1
        payload_3 = {
846
            "id": "cc:cc:cc",
847
            "name": "my third evc3",
848
            "uni_a": {
849
                "interface_id": "00:00:00:00:00:00:00:03:1",
850
                "tag": {"tag_type": 1, "value": 90},
851
            },
852
            "uni_z": {
853
                "interface_id": "00:00:00:00:00:00:00:04:2",
854
                "tag": {"tag_type": 1, "value": 100},
855
            },
856
        }
857 1
        circuits["circuits"].update({"cc:cc:cc": payload_3})
858
        # Add one circuit to the mongodb.
859 1
        data_mock.return_value = circuits
860
861 1
    async def test_list_schedules_from_mongodb(self):
862
        """Test if list circuits return specific circuits stored."""
863 1
        self._add_mongodb_schedule_data(
864
            self.napp.mongo_controller.get_circuits
865
        )
866
867 1
        url = f"{self.base_endpoint}/v2/evc/schedule"
868
869
        # Call URL
870 1
        response = await self.api_client.get(url)
871
        # Expected JSON data from response
872 1
        expected = [
873
            {
874
                "circuit_id": "aa:aa:aa",
875
                "schedule": {
876
                    "action": "create",
877
                    "frequency": "* * * * *",
878
                    "id": "1",
879
                },
880
                "schedule_id": "1",
881
            },
882
            {
883
                "circuit_id": "aa:aa:aa",
884
                "schedule": {
885
                    "action": "remove",
886
                    "frequency": "1 * * * *",
887
                    "id": "2",
888
                },
889
                "schedule_id": "2",
890
            },
891
            {
892
                "circuit_id": "bb:bb:bb",
893
                "schedule": {
894
                    "action": "create",
895
                    "frequency": "1 * * * *",
896
                    "id": "3",
897
                },
898
                "schedule_id": "3",
899
            },
900
            {
901
                "circuit_id": "bb:bb:bb",
902
                "schedule": {
903
                    "action": "remove",
904
                    "frequency": "2 * * * *",
905
                    "id": "4",
906
                },
907
                "schedule_id": "4",
908
            },
909
        ]
910
911 1
        assert response.status_code == 200
912 1
        assert expected == response.json()
913
914 1
    async def test_get_specific_schedule_from_mongodb(self):
915
        """Test get schedules from a circuit."""
916 1
        self._add_mongodb_schedule_data(
917
            self.napp.mongo_controller.get_circuits
918
        )
919
920 1
        requested_circuit_id = "bb:bb:bb"
921 1
        evc = self.napp.mongo_controller.get_circuits()
922 1
        evc = evc["circuits"][requested_circuit_id]
923 1
        self.napp.mongo_controller.get_circuit.return_value = evc
924 1
        url = f"{self.base_endpoint}/v2/evc/{requested_circuit_id}"
925
926
        # Call URL
927 1
        response = await self.api_client.get(url)
928
929
        # Expected JSON data from response
930 1
        expected = [
931
            {"action": "create", "frequency": "1 * * * *", "id": "3"},
932
            {"action": "remove", "frequency": "2 * * * *", "id": "4"},
933
        ]
934
935 1
        assert response.status_code == 200
936 1
        assert expected == response.json()["circuit_scheduler"]
937
938 1
    async def test_get_specific_schedules_from_mongodb_not_found(self):
939
        """Test get specific schedule ID that does not exist."""
940 1
        requested_id = "blah"
941 1
        self.napp.mongo_controller.get_circuit.return_value = None
942 1
        url = f"{self.base_endpoint}/v2/evc/{requested_id}"
943
944
        # Call URL
945 1
        response = await self.api_client.get(url)
946
947 1
        expected = "circuit_id blah not found"
948
        # Assert response not found
949 1
        assert response.status_code == 404
950 1
        assert expected == response.json()["description"]
951
952 1
    def _uni_from_dict_side_effect(self, uni_dict):
953 1
        interface_id = uni_dict.get("interface_id")
954 1
        tag_dict = uni_dict.get("tag")
955 1
        interface = Interface(interface_id, "0", MagicMock(id="1"))
956 1
        return UNI(interface, tag_dict)
957
958 1
    @patch("apscheduler.schedulers.background.BackgroundScheduler.add_job")
959 1
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
960 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
961 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
962 1
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
963 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
964 1
    async def test_create_schedule(
965
        self,
966
        validate_mock,
967
        evc_as_dict_mock,
968
        mongo_controller_upsert_mock,
969
        uni_from_dict_mock,
970
        sched_add_mock,
971
        scheduler_add_job_mock,
972
        event_loop
973
    ):
974
        """Test create a circuit schedule."""
975 1
        self.napp.controller.loop = event_loop
976 1
        validate_mock.return_value = True
977 1
        mongo_controller_upsert_mock.return_value = True
978 1
        uni_from_dict_mock.side_effect = self._uni_from_dict_side_effect
979 1
        evc_as_dict_mock.return_value = {}
980 1
        sched_add_mock.return_value = True
981
982 1
        self._add_mongodb_schedule_data(
983
            self.napp.mongo_controller.get_circuits
984
        )
985
986 1
        requested_id = "bb:bb:bb"
987 1
        url = f"{self.base_endpoint}/v2/evc/schedule/"
988
989 1
        payload = {
990
            "circuit_id": requested_id,
991
            "schedule": {"frequency": "1 * * * *", "action": "create"},
992
            "metadata": {"metadata1": "test_data"},
993
        }
994
995
        # Call URL
996 1
        response = await self.api_client.post(url, json=payload)
997 1
        response_json = response.json()
998
999 1
        assert response.status_code == 201
1000 1
        scheduler_add_job_mock.assert_called_once()
1001 1
        mongo_controller_upsert_mock.assert_called_once()
1002 1
        assert payload["schedule"]["frequency"] == response_json["frequency"]
1003 1
        assert payload["schedule"]["action"] == response_json["action"]
1004 1
        assert response_json["id"] is not None
1005
1006
        # Case 2: there is no schedule
1007 1
        payload = {
1008
              "circuit_id": "cc:cc:cc",
1009
              "schedule": {
1010
                "frequency": "1 * * * *",
1011
                "action": "create"
1012
              }
1013
            }
1014 1
        response = await self.api_client.post(url, json=payload)
1015 1
        assert response.status_code == 201
1016
1017 1
    async def test_create_schedule_invalid_request(self, event_loop):
1018
        """Test create schedule API with invalid request."""
1019 1
        self.napp.controller.loop = event_loop
1020 1
        evc1 = MagicMock()
1021 1
        self.napp.circuits = {'bb:bb:bb': evc1}
1022 1
        url = f'{self.base_endpoint}/v2/evc/schedule/'
1023
1024
        # case 1: empty post
1025 1
        response = await self.api_client.post(url, json={})
1026 1
        assert response.status_code == 400
1027
1028
        # case 2: content-type not specified
1029 1
        payload = {
1030
            "circuit_id": "bb:bb:bb",
1031
            "schedule": {
1032
                "frequency": "1 * * * *",
1033
                "action": "create"
1034
            }
1035
        }
1036 1
        response = await self.api_client.post(url, json=payload)
1037 1
        assert response.status_code == 409
1038
1039
        # case 3: not a dictionary
1040 1
        payload = []
1041 1
        response = await self.api_client.post(url, json=payload)
1042 1
        assert response.status_code == 400
1043
1044
        # case 4: missing circuit id
1045 1
        payload = {
1046
            "schedule": {
1047
                "frequency": "1 * * * *",
1048
                "action": "create"
1049
            }
1050
        }
1051 1
        response = await self.api_client.post(url, json=payload)
1052 1
        assert response.status_code == 400
1053
1054
        # case 5: missing schedule
1055 1
        payload = {
1056
            "circuit_id": "bb:bb:bb"
1057
        }
1058 1
        response = await self.api_client.post(url, json=payload)
1059 1
        assert response.status_code == 400
1060
1061
        # case 6: invalid circuit
1062 1
        payload = {
1063
            "circuit_id": "xx:xx:xx",
1064
            "schedule": {
1065
                "frequency": "1 * * * *",
1066
                "action": "create"
1067
            }
1068
        }
1069 1
        response = await self.api_client.post(url, json=payload)
1070 1
        assert response.status_code == 404
1071
1072
        # case 7: archived or deleted evc
1073 1
        evc1.archived.return_value = True
1074 1
        payload = {
1075
            "circuit_id": "bb:bb:bb",
1076
            "schedule": {
1077
                "frequency": "1 * * * *",
1078
                "action": "create"
1079
            }
1080
        }
1081 1
        response = await self.api_client.post(url, json=payload)
1082 1
        assert response.status_code == 409
1083
1084
        # case 8: invalid json
1085 1
        response = await self.api_client.post(url, json="test")
1086 1
        assert response.status_code == 400
1087
1088 1
    @patch('apscheduler.schedulers.background.BackgroundScheduler.remove_job')
1089 1
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1090 1
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1091 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1092 1
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1093 1
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1094 1
    async def test_update_schedule(
1095
        self,
1096
        validate_mock,
1097
        evc_as_dict_mock,
1098
        mongo_controller_upsert_mock,
1099
        uni_from_dict_mock,
1100
        sched_add_mock,
1101
        scheduler_remove_job_mock,
1102
        event_loop
1103
    ):
1104
        """Test create a circuit schedule."""
1105 1
        self.napp.controller.loop = event_loop
1106 1
        mongo_payload_1 = {
1107
            "circuits": {
1108
                "aa:aa:aa": {
1109
                    "id": "aa:aa:aa",
1110
                    "name": "my evc1",
1111
                    "uni_a": {
1112
                        "interface_id": "00:00:00:00:00:00:00:01:1",
1113
                        "tag": {"tag_type": 1, "value": 80},
1114
                    },
1115
                    "uni_z": {
1116
                        "interface_id": "00:00:00:00:00:00:00:02:2",
1117
                        "tag": {"tag_type": 1, "value": 1},
1118
                    },
1119
                    "circuit_scheduler": [
1120
                        {
1121
                            "id": "1",
1122
                            "frequency": "* * * * *",
1123
                            "action": "create"
1124
                        }
1125
                    ],
1126
                }
1127
            }
1128
        }
1129
1130 1
        validate_mock.return_value = True
1131 1
        mongo_controller_upsert_mock.return_value = True
1132 1
        sched_add_mock.return_value = True
1133 1
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1134 1
        evc_as_dict_mock.return_value = {}
1135 1
        self.napp.mongo_controller.get_circuits.return_value = mongo_payload_1
1136 1
        scheduler_remove_job_mock.return_value = True
1137
1138 1
        requested_schedule_id = "1"
1139 1
        url = f"{self.base_endpoint}/v2/evc/schedule/{requested_schedule_id}"
1140
1141 1
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1142
1143
        # Call URL
1144 1
        response = await self.api_client.patch(url, json=payload)
1145 1
        response_json = response.json()
1146
1147 1
        assert response.status_code == 200
1148 1
        scheduler_remove_job_mock.assert_called_once()
1149 1
        mongo_controller_upsert_mock.assert_called_once()
1150 1
        assert payload["frequency"] == response_json["frequency"]
1151 1
        assert payload["action"] == response_json["action"]
1152 1
        assert response_json["id"] is not None
1153
1154 1
    @patch('napps.kytos.mef_eline.main.Main._find_evc_by_schedule_id')
1155 1
    async def test_update_no_schedule(
1156
        self, find_evc_by_schedule_id_mock, event_loop
1157
    ):
1158
        """Test update a circuit schedule."""
1159 1
        self.napp.controller.loop = event_loop
1160 1
        url = f"{self.base_endpoint}/v2/evc/schedule/1"
1161 1
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1162
1163 1
        find_evc_by_schedule_id_mock.return_value = None, None
1164
1165 1
        response = await self.api_client.patch(url, json=payload)
1166 1
        assert response.status_code == 404
1167
1168 1
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1169 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1170 1
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1171 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1172 1
    async def test_update_schedule_archived(
1173
        self,
1174
        validate_mock,
1175
        evc_as_dict_mock,
1176
        uni_from_dict_mock,
1177
        sched_add_mock,
1178
        event_loop
1179
    ):
1180
        """Test create a circuit schedule."""
1181 1
        self.napp.controller.loop = event_loop
1182 1
        mongo_payload_1 = {
1183
            "circuits": {
1184
                "aa:aa:aa": {
1185
                    "id": "aa:aa:aa",
1186
                    "name": "my evc1",
1187
                    "archived": True,
1188
                    "circuit_scheduler": [
1189
                        {
1190
                            "id": "1",
1191
                            "frequency": "* * * * *",
1192
                            "action": "create"
1193
                        }
1194
                    ],
1195
                }
1196
            }
1197
        }
1198
1199 1
        validate_mock.return_value = True
1200 1
        sched_add_mock.return_value = True
1201 1
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1202 1
        evc_as_dict_mock.return_value = {}
1203 1
        self.napp.mongo_controller.get_circuits.return_value = mongo_payload_1
1204
1205 1
        requested_schedule_id = "1"
1206 1
        url = f"{self.base_endpoint}/v2/evc/schedule/{requested_schedule_id}"
1207
1208 1
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1209
1210
        # Call URL
1211 1
        response = await self.api_client.patch(url, json=payload)
1212 1
        assert response.status_code == 409
1213
1214 1
    @patch("apscheduler.schedulers.background.BackgroundScheduler.remove_job")
1215 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1216 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1217 1
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1218 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1219 1
    async def test_delete_schedule(self, *args):
1220
        """Test create a circuit schedule."""
1221 1
        (
1222
            validate_mock,
1223
            evc_as_dict_mock,
1224
            mongo_controller_upsert_mock,
1225
            uni_from_dict_mock,
1226
            scheduler_remove_job_mock,
1227
        ) = args
1228
1229 1
        mongo_payload_1 = {
1230
            "circuits": {
1231
                "2": {
1232
                    "id": "2",
1233
                    "name": "my evc1",
1234
                    "uni_a": {
1235
                        "interface_id": "00:00:00:00:00:00:00:01:1",
1236
                        "tag": {"tag_type": 1, "value": 80},
1237
                    },
1238
                    "uni_z": {
1239
                        "interface_id": "00:00:00:00:00:00:00:02:2",
1240
                        "tag": {"tag_type": 1, "value": 1},
1241
                    },
1242
                    "circuit_scheduler": [
1243
                        {
1244
                            "id": "1",
1245
                            "frequency": "* * * * *",
1246
                            "action": "create"
1247
                        }
1248
                    ],
1249
                }
1250
            }
1251
        }
1252 1
        validate_mock.return_value = True
1253 1
        mongo_controller_upsert_mock.return_value = True
1254 1
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1255 1
        evc_as_dict_mock.return_value = {}
1256 1
        self.napp.mongo_controller.get_circuits.return_value = mongo_payload_1
1257 1
        scheduler_remove_job_mock.return_value = True
1258
1259 1
        requested_schedule_id = "1"
1260 1
        url = f"{self.base_endpoint}/v2/evc/schedule/{requested_schedule_id}"
1261
1262
        # Call URL
1263 1
        response = await self.api_client.delete(url)
1264
1265 1
        assert response.status_code == 200
1266 1
        scheduler_remove_job_mock.assert_called_once()
1267 1
        mongo_controller_upsert_mock.assert_called_once()
1268 1
        assert "Schedule removed" in f"{response.json()}"
1269
1270 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1271 1
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1272 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1273 1
    async def test_delete_schedule_archived(self, *args):
1274
        """Test create a circuit schedule."""
1275 1
        (
1276
            validate_mock,
1277
            evc_as_dict_mock,
1278
            uni_from_dict_mock,
1279
        ) = args
1280
1281 1
        mongo_payload_1 = {
1282
            "circuits": {
1283
                "2": {
1284
                    "id": "2",
1285
                    "name": "my evc1",
1286
                    "archived": True,
1287
                    "circuit_scheduler": [
1288
                        {
1289
                            "id": "1",
1290
                            "frequency": "* * * * *",
1291
                            "action": "create"
1292
                        }
1293
                    ],
1294
                }
1295
            }
1296
        }
1297
1298 1
        validate_mock.return_value = True
1299 1
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1300 1
        evc_as_dict_mock.return_value = {}
1301 1
        self.napp.mongo_controller.get_circuits.return_value = mongo_payload_1
1302
1303 1
        requested_schedule_id = "1"
1304 1
        url = f"{self.base_endpoint}/v2/evc/schedule/{requested_schedule_id}"
1305
1306
        # Call URL
1307 1
        response = await self.api_client.delete(url)
1308 1
        assert response.status_code == 409
1309
1310 1
    @patch('napps.kytos.mef_eline.main.Main._find_evc_by_schedule_id')
1311 1
    async def test_delete_schedule_not_found(self, mock_find_evc_by_sched):
1312
        """Test delete a circuit schedule - unexisting."""
1313 1
        mock_find_evc_by_sched.return_value = (None, False)
1314 1
        url = f'{self.base_endpoint}/v2/evc/schedule/1'
1315 1
        response = await self.api_client.delete(url)
1316 1
        assert response.status_code == 404
1317
1318 1
    def test_get_evcs_by_svc_level(self) -> None:
1319
        """Test get_evcs_by_svc_level."""
1320 1
        levels = [1, 2, 4, 2, 7]
1321 1
        evcs = {i: MagicMock(service_level=v, creation_time=1)
1322
                for i, v in enumerate(levels)}
1323 1
        self.napp.circuits = evcs
1324 1
        expected_levels = sorted(levels, reverse=True)
1325 1
        evcs_by_level = self.napp.get_evcs_by_svc_level()
1326 1
        assert evcs_by_level
1327
1328 1
        for evc, exp_level in zip(evcs_by_level, expected_levels):
1329 1
            assert evc.service_level == exp_level
1330
1331 1
        evcs = {i: MagicMock(service_level=1, creation_time=i)
1332
                for i in reversed(range(2))}
1333 1
        self.napp.circuits = evcs
1334 1
        evcs_by_level = self.napp.get_evcs_by_svc_level()
1335 1
        for i in range(2):
1336 1
            assert evcs_by_level[i].creation_time == i
1337
1338 1
    async def test_get_circuit_not_found(self):
1339
        """Test /v2/evc/<circuit_id> 404."""
1340 1
        self.napp.mongo_controller.get_circuit.return_value = None
1341 1
        url = f'{self.base_endpoint}/v2/evc/1234'
1342 1
        response = await self.api_client.get(url)
1343 1
        assert response.status_code == 404
1344
1345 1
    @patch('requests.post')
1346 1
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1347 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1348 1
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1349 1
    @patch('kytos.core.Controller.get_interface_by_id')
1350 1
    @patch('napps.kytos.mef_eline.models.path.Path.is_valid')
1351 1
    @patch('napps.kytos.mef_eline.models.evc.EVCDeploy.deploy')
1352 1
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1353 1
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1354 1
    async def test_update_circuit(
1355
        self,
1356
        evc_as_dict_mock,
1357
        uni_from_dict_mock,
1358
        evc_deploy,
1359
        _is_valid_mock,
1360
        interface_by_id_mock,
1361
        _mock_validate,
1362
        _mongo_controller_upsert_mock,
1363
        _sched_add_mock,
1364
        requests_mock,
1365
        event_loop,
1366
    ):
1367
        """Test update a circuit circuit."""
1368 1
        self.napp.controller.loop = event_loop
1369 1
        interface_by_id_mock.return_value = get_uni_mocked().interface
1370 1
        unis = [
1371
            get_uni_mocked(switch_dpid="00:00:00:00:00:00:00:01"),
1372
            get_uni_mocked(switch_dpid="00:00:00:00:00:00:00:02"),
1373
        ]
1374 1
        uni_from_dict_mock.side_effect = 2 * unis
1375
1376 1
        response = MagicMock()
1377 1
        response.status_code = 201
1378 1
        requests_mock.return_value = response
1379
1380 1
        payloads = [
1381
            {
1382
                "name": "my evc1",
1383
                "uni_a": {
1384
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1385
                    "tag": {"tag_type": 1, "value": 80},
1386
                },
1387
                "uni_z": {
1388
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1389
                    "tag": {"tag_type": 1, "value": 1},
1390
                },
1391
                "dynamic_backup_path": True,
1392
            },
1393
            {
1394
                "primary_path": [
1395
                    {
1396
                        "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1397
                        "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"},
1398
                    }
1399
                ]
1400
            },
1401
            {
1402
                "sb_priority": 3
1403
            },
1404
            {
1405
                # It works only with 'enable' and not with 'enabled'
1406
                "enable": True
1407
            },
1408
            {
1409
                "name": "my evc1",
1410
                "active": True,
1411
                "enable": True,
1412
                "uni_a": {
1413
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1414
                    "tag": {
1415
                        "tag_type": 1,
1416
                        "value": 80
1417
                    }
1418
                },
1419
                "uni_z": {
1420
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1421
                    "tag": {
1422
                        "tag_type": 1,
1423
                        "value": 1
1424
                    }
1425
                },
1426
                "priority": 3,
1427
                "bandwidth": 1000,
1428
                "dynamic_backup_path": True
1429
            }
1430
        ]
1431
1432 1
        evc_as_dict_mock.return_value = payloads[0]
1433 1
        response = await self.api_client.post(
1434
            f"{self.base_endpoint}/v2/evc/",
1435
            json=payloads[0],
1436
        )
1437 1
        assert 201 == response.status_code
1438
1439 1
        evc_deploy.reset_mock()
1440 1
        evc_as_dict_mock.return_value = payloads[1]
1441 1
        current_data = response.json()
1442 1
        circuit_id = current_data["circuit_id"]
1443 1
        response = await self.api_client.patch(
1444
            f"{self.base_endpoint}/v2/evc/{circuit_id}",
1445
            json=payloads[1],
1446
        )
1447
        # evc_deploy.assert_called_once()
1448 1
        assert 200 == response.status_code
1449
1450 1
        evc_deploy.reset_mock()
1451 1
        evc_as_dict_mock.return_value = payloads[2]
1452 1
        response = await self.api_client.patch(
1453
            f"{self.base_endpoint}/v2/evc/{circuit_id}",
1454
            json=payloads[2],
1455
        )
1456 1
        evc_deploy.assert_not_called()
1457 1
        assert 200 == response.status_code
1458
1459 1
        evc_deploy.reset_mock()
1460 1
        evc_as_dict_mock.return_value = payloads[3]
1461 1
        response = await self.api_client.patch(
1462
            f"{self.base_endpoint}/v2/evc/{circuit_id}",
1463
            json=payloads[3],
1464
        )
1465 1
        evc_deploy.assert_called_once()
1466 1
        assert 200 == response.status_code
1467
1468 1
        evc_deploy.reset_mock()
1469 1
        response = await self.api_client.patch(
1470
            f"{self.base_endpoint}/v2/evc/{circuit_id}",
1471
            content=b'{"priority":5,}',
1472
            headers={"Content-Type": "application/json"}
1473
        )
1474 1
        evc_deploy.assert_not_called()
1475 1
        assert 400 == response.status_code
1476
1477 1
        response = await self.api_client.patch(
1478
            f"{self.base_endpoint}/v2/evc/1234",
1479
            json=payloads[1],
1480
        )
1481 1
        current_data = response.json()
1482 1
        expected_data = "circuit_id 1234 not found"
1483 1
        assert current_data["description"] == expected_data
1484 1
        assert 404 == response.status_code
1485
1486 1
        await self.api_client.delete(
1487
            f"{self.base_endpoint}/v2/evc/{circuit_id}"
1488
        )
1489 1
        evc_deploy.reset_mock()
1490 1
        response = await self.api_client.patch(
1491
            f"{self.base_endpoint}/v2/evc/{circuit_id}",
1492
            json=payloads[1],
1493
        )
1494 1
        evc_deploy.assert_not_called()
1495 1
        assert 409 == response.status_code
1496 1
        assert "Can't update archived EVC" in response.json()["description"]
1497
1498 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...
1499 1
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1500 1
    @patch("napps.kytos.mef_eline.main.Main._uni_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
    async def test_update_circuit_invalid_json(
1505
        self,
1506
        evc_as_dict_mock,
1507
        validate_mock,
1508
        mongo_controller_upsert_mock,
1509
        uni_from_dict_mock,
1510
        sched_add_mock,
1511
        evc_deploy_mock,
1512
        event_loop
1513
    ):
1514
        """Test update a circuit circuit."""
1515 1
        self.napp.controller.loop = event_loop
1516 1
        validate_mock.return_value = True
1517 1
        mongo_controller_upsert_mock.return_value = True
1518 1
        sched_add_mock.return_value = True
1519 1
        evc_deploy_mock.return_value = True
1520 1
        uni1 = create_autospec(UNI)
1521 1
        uni2 = create_autospec(UNI)
1522 1
        uni1.interface = create_autospec(Interface)
1523 1
        uni2.interface = create_autospec(Interface)
1524 1
        uni1.interface.switch = MagicMock()
1525 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
1526 1
        uni1.interface.switch.status = EntityStatus.UP
1527 1
        uni2.interface.switch = MagicMock()
1528 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
1529 1
        uni2.interface.switch.status = EntityStatus.UP
1530 1
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1531
1532 1
        payload1 = {
1533
            "name": "my evc1",
1534
            "uni_a": {
1535
                "interface_id": "00:00:00:00:00:00:00:01:1",
1536
                "tag": {"tag_type": 1, "value": 80},
1537
            },
1538
            "uni_z": {
1539
                "interface_id": "00:00:00:00:00:00:00:02:2",
1540
                "tag": {"tag_type": 1, "value": 1},
1541
            },
1542
            "dynamic_backup_path": True,
1543
        }
1544
1545 1
        payload2 = {
1546
            "dynamic_backup_path": False,
1547
        }
1548
1549 1
        evc_as_dict_mock.return_value = payload1
1550 1
        response = await self.api_client.post(
1551
            f"{self.base_endpoint}/v2/evc/",
1552
            json=payload1
1553
        )
1554 1
        assert 201 == response.status_code
1555
1556 1
        evc_as_dict_mock.return_value = payload2
1557 1
        current_data = response.json()
1558 1
        circuit_id = current_data["circuit_id"]
1559 1
        response = await self.api_client.patch(
1560
            f"{self.base_endpoint}/v2/evc/{circuit_id}",
1561
            json=payload2
1562
        )
1563 1
        current_data = response.json()
1564 1
        assert 400 == response.status_code
1565 1
        assert "must have a primary path or" in current_data["description"]
1566
1567 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
1568 1
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1569 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1570 1
    @patch("napps.kytos.mef_eline.main.Main._link_from_dict")
1571 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1572 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1573 1
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1574 1
    @patch("napps.kytos.mef_eline.models.path.Path.is_valid")
1575 1
    async def test_update_circuit_invalid_path(
1576
        self,
1577
        is_valid_mock,
1578
        evc_as_dict_mock,
1579
        validate_mock,
1580
        mongo_controller_upsert_mock,
1581
        link_from_dict_mock,
1582
        uni_from_dict_mock,
1583
        sched_add_mock,
1584
        evc_deploy_mock,
1585
        event_loop
1586
    ):
1587
        """Test update a circuit circuit."""
1588 1
        self.napp.controller.loop = event_loop
1589 1
        is_valid_mock.side_effect = InvalidPath("error")
1590 1
        validate_mock.return_value = True
1591 1
        mongo_controller_upsert_mock.return_value = True
1592 1
        sched_add_mock.return_value = True
1593 1
        evc_deploy_mock.return_value = True
1594 1
        link_from_dict_mock.return_value = 1
1595 1
        uni1 = create_autospec(UNI)
1596 1
        uni2 = create_autospec(UNI)
1597 1
        uni1.interface = create_autospec(Interface)
1598 1
        uni2.interface = create_autospec(Interface)
1599 1
        uni1.interface.switch = MagicMock()
1600 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
1601 1
        uni1.interface.switch.status = EntityStatus.UP
1602 1
        uni2.interface.switch = MagicMock()
1603 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
1604 1
        uni2.interface.switch.status = EntityStatus.UP
1605 1
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1606
1607 1
        payload1 = {
1608
            "name": "my evc1",
1609
            "uni_a": {
1610
                "interface_id": "00:00:00:00:00:00:00:01:1",
1611
                "tag": {"tag_type": 1, "value": 80},
1612
            },
1613
            "uni_z": {
1614
                "interface_id": "00:00:00:00:00:00:00:02:2",
1615
                "tag": {"tag_type": 1, "value": 1},
1616
            },
1617
            "dynamic_backup_path": True,
1618
        }
1619
1620 1
        payload2 = {
1621
            "primary_path": [
1622
                {
1623
                    "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1624
                    "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"},
1625
                }
1626
            ]
1627
        }
1628
1629 1
        evc_as_dict_mock.return_value = payload1
1630 1
        response = await self.api_client.post(
1631
            f"{self.base_endpoint}/v2/evc/",
1632
            json=payload1,
1633
        )
1634 1
        assert 201 == response.status_code
1635
1636 1
        evc_as_dict_mock.return_value = payload2
1637 1
        current_data = response.json()
1638 1
        circuit_id = current_data["circuit_id"]
1639 1
        response = await self.api_client.patch(
1640
            f"{self.base_endpoint}/v2/evc/{circuit_id}",
1641
            json=payload2,
1642
        )
1643 1
        current_data = response.json()
1644 1
        expected_data = "primary_path is not a valid path: error"
1645 1
        assert 400 == response.status_code
1646 1
        assert current_data["description"] == expected_data
1647
1648 1
    def test_link_from_dict_non_existent_intf(self):
1649
        """Test _link_from_dict non existent intf."""
1650 1
        self.napp.controller.get_interface_by_id = MagicMock(return_value=None)
1651 1
        link_dict = {
1652
            "endpoint_a": {"id": "a"},
1653
            "endpoint_b": {"id": "b"}
1654
        }
1655 1
        with pytest.raises(ValueError):
1656 1
            self.napp._link_from_dict(link_dict)
1657
1658 1
    def test_uni_from_dict_non_existent_intf(self):
1659
        """Test _link_from_dict non existent intf."""
1660 1
        self.napp.controller.get_interface_by_id = MagicMock(return_value=None)
1661 1
        uni_dict = {
1662
            "interface_id": "aaa",
1663
        }
1664 1
        with pytest.raises(ValueError):
1665 1
            self.napp._uni_from_dict(uni_dict)
1666
1667 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...
1668 1
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1669 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1670 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1671 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1672 1
    async def test_update_evc_no_json_mime(
1673
        self,
1674
        mongo_controller_upsert_mock,
1675
        validate_mock,
1676
        uni_from_dict_mock,
1677
        sched_add_mock,
1678
        evc_deploy_mock,
1679
        event_loop
1680
    ):
1681
        """Test update a circuit with wrong mimetype."""
1682 1
        self.napp.controller.loop = event_loop
1683 1
        validate_mock.return_value = True
1684 1
        sched_add_mock.return_value = True
1685 1
        evc_deploy_mock.return_value = True
1686 1
        uni1 = create_autospec(UNI)
1687 1
        uni2 = create_autospec(UNI)
1688 1
        uni1.interface = create_autospec(Interface)
1689 1
        uni2.interface = create_autospec(Interface)
1690 1
        uni1.interface.switch = MagicMock()
1691 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
1692 1
        uni1.interface.switch.status = EntityStatus.UP
1693 1
        uni2.interface.switch = MagicMock()
1694 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
1695 1
        uni2.interface.switch.status = EntityStatus.UP
1696 1
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1697 1
        mongo_controller_upsert_mock.return_value = True
1698
1699 1
        payload1 = {
1700
            "name": "my evc1",
1701
            "uni_a": {
1702
                "interface_id": "00:00:00:00:00:00:00:01:1",
1703
                "tag": {"tag_type": 1, "value": 80},
1704
            },
1705
            "uni_z": {
1706
                "interface_id": "00:00:00:00:00:00:00:02:2",
1707
                "tag": {"tag_type": 1, "value": 1},
1708
            },
1709
            "dynamic_backup_path": True,
1710
        }
1711
1712 1
        payload2 = {"dynamic_backup_path": False}
1713
1714 1
        response = await self.api_client.post(
1715
            f"{self.base_endpoint}/v2/evc/",
1716
            json=payload1,
1717
        )
1718 1
        assert 201 == response.status_code
1719
1720 1
        current_data = response.json()
1721 1
        circuit_id = current_data["circuit_id"]
1722 1
        response = await self.api_client.patch(
1723
            f"{self.base_endpoint}/v2/evc/{circuit_id}", data=payload2
1724
        )
1725 1
        current_data = response.json()
1726 1
        assert 415 == response.status_code
1727 1
        assert "application/json" in current_data["description"]
1728
1729 1
    async def test_delete_no_evc(self):
1730
        """Test delete when EVC does not exist."""
1731 1
        url = f"{self.base_endpoint}/v2/evc/123"
1732 1
        response = await self.api_client.delete(url)
1733 1
        current_data = response.json()
1734 1
        expected_data = "circuit_id 123 not found"
1735 1
        assert current_data["description"] == expected_data
1736 1
        assert 404 == response.status_code
1737
1738 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.remove_current_flows")
1739 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
1740 1
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1741 1
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1742 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1743 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1744 1
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1745 1
    async def test_delete_archived_evc(
1746
        self,
1747
        evc_as_dict_mock,
1748
        validate_mock,
1749
        mongo_controller_upsert_mock,
1750
        uni_from_dict_mock,
1751
        sched_add_mock,
1752
        evc_deploy_mock,
1753
        remove_current_flows_mock,
1754
        event_loop
1755
    ):
1756
        """Try to delete an archived EVC"""
1757 1
        self.napp.controller.loop = event_loop
1758 1
        validate_mock.return_value = True
1759 1
        mongo_controller_upsert_mock.return_value = True
1760 1
        sched_add_mock.return_value = True
1761 1
        evc_deploy_mock.return_value = True
1762 1
        remove_current_flows_mock.return_value = True
1763 1
        uni1 = create_autospec(UNI)
1764 1
        uni2 = create_autospec(UNI)
1765 1
        uni1.interface = create_autospec(Interface)
1766 1
        uni2.interface = create_autospec(Interface)
1767 1
        uni1.interface.switch = MagicMock()
1768 1
        uni1.interface.switch.return_value = "00:00:00:00:00:00:00:01"
1769 1
        uni1.interface.switch.status = EntityStatus.UP
1770 1
        uni2.interface.switch = MagicMock()
1771 1
        uni2.interface.switch.return_value = "00:00:00:00:00:00:00:02"
1772 1
        uni2.interface.switch.status = EntityStatus.UP
1773 1
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1774
1775 1
        payload1 = {
1776
            "name": "my evc1",
1777
            "uni_a": {
1778
                "interface_id": "00:00:00:00:00:00:00:01:1",
1779
                "tag": {"tag_type": 1, "value": 80},
1780
            },
1781
            "uni_z": {
1782
                "interface_id": "00:00:00:00:00:00:00:02:2",
1783
                "tag": {"tag_type": 1, "value": 1},
1784
            },
1785
            "dynamic_backup_path": True,
1786
        }
1787
1788 1
        evc_as_dict_mock.return_value = payload1
1789 1
        response = await self.api_client.post(
1790
            f"{self.base_endpoint}/v2/evc/",
1791
            json=payload1
1792
        )
1793 1
        assert 201 == response.status_code
1794
1795 1
        current_data = response.json()
1796 1
        circuit_id = current_data["circuit_id"]
1797 1
        response = await self.api_client.delete(
1798
            f"{self.base_endpoint}/v2/evc/{circuit_id}"
1799
        )
1800 1
        assert 200 == response.status_code
1801
1802 1
        response = await self.api_client.delete(
1803
            f"{self.base_endpoint}/v2/evc/{circuit_id}"
1804
        )
1805 1
        current_data = response.json()
1806 1
        expected_data = f"Circuit {circuit_id} already removed"
1807 1
        assert current_data["description"] == expected_data
1808 1
        assert 404 == response.status_code
1809
1810 1
    def test_handle_link_up(self):
1811
        """Test handle_link_up method."""
1812 1
        evc_mock = create_autospec(EVC)
1813 1
        evc_mock.service_level, evc_mock.creation_time = 0, 1
1814 1
        evc_mock.is_enabled = MagicMock(side_effect=[True, False, True])
1815 1
        evc_mock.lock = MagicMock()
1816 1
        type(evc_mock).archived = PropertyMock(
1817
            side_effect=[True, False, False]
1818
        )
1819 1
        evcs = [evc_mock, evc_mock, evc_mock]
1820 1
        event = KytosEvent(name="test", content={"link": "abc"})
1821 1
        self.napp.circuits = dict(zip(["1", "2", "3"], evcs))
1822 1
        self.napp.handle_link_up(event)
1823 1
        evc_mock.handle_link_up.assert_called_once_with("abc")
1824
1825 1
    @patch("time.sleep", return_value=None)
1826 1
    @patch("napps.kytos.mef_eline.main.settings")
1827 1
    @patch("napps.kytos.mef_eline.main.emit_event")
1828 1
    def test_handle_link_down(self, emit_event_mock, settings_mock, _):
1829
        """Test handle_link_down method."""
1830 1
        uni = create_autospec(UNI)
1831 1
        evc1 = MagicMock(id="1", service_level=0, creation_time=1,
1832
                         metadata="mock", _active="true", _enabled="true",
1833
                         uni_a=uni, uni_z=uni)
1834 1
        evc1.name = "name"
1835 1
        evc1.is_affected_by_link.return_value = True
1836 1
        evc1.handle_link_down.return_value = True
1837 1
        evc1.failover_path = None
1838 1
        evc2 = MagicMock(id="2", service_level=6, creation_time=1)
1839 1
        evc2.is_affected_by_link.return_value = False
1840 1
        evc3 = MagicMock(id="3", service_level=5, creation_time=1,
1841
                         metadata="mock", _active="true", _enabled="true",
1842
                         uni_a=uni, uni_z=uni)
1843 1
        evc3.name = "name"
1844 1
        evc3.is_affected_by_link.return_value = True
1845 1
        evc3.handle_link_down.return_value = True
1846 1
        evc3.failover_path = None
1847 1
        evc4 = MagicMock(id="4", service_level=4, creation_time=1,
1848
                         metadata="mock", _active="true", _enabled="true",
1849
                         uni_a=uni, uni_z=uni)
1850 1
        evc4.name = "name"
1851 1
        evc4.is_affected_by_link.return_value = True
1852 1
        evc4.is_failover_path_affected_by_link.return_value = False
1853 1
        evc4.failover_path = ["2"]
1854 1
        evc4.get_failover_flows.return_value = {
1855
            "2": ["flow1", "flow2"],
1856
            "3": ["flow3", "flow4", "flow5", "flow6"],
1857
        }
1858 1
        evc5 = MagicMock(id="5", service_level=7, creation_time=1)
1859 1
        evc5.is_affected_by_link.return_value = True
1860 1
        evc5.is_failover_path_affected_by_link.return_value = False
1861 1
        evc5.failover_path = ["3"]
1862 1
        evc5.get_failover_flows.return_value = {
1863
            "4": ["flow7", "flow8"],
1864
            "5": ["flow9", "flow10"],
1865
        }
1866 1
        link = MagicMock(id="123")
1867 1
        event = KytosEvent(name="test", content={"link": link})
1868 1
        self.napp.circuits = {"1": evc1, "2": evc2, "3": evc3, "4": evc4,
1869
                              "5": evc5}
1870 1
        settings_mock.BATCH_SIZE = 2
1871 1
        self.napp.handle_link_down(event)
1872
1873 1
        assert evc5.service_level > evc4.service_level
1874
        # evc5 batched flows should be sent first
1875 1
        emit_event_mock.assert_has_calls([
1876
            call(
1877
                self.napp.controller,
1878
                context="kytos.flow_manager",
1879
                name="flows.install",
1880
                content={
1881
                    "dpid": "4",
1882
                    "flow_dict": {"flows": ["flow7", "flow8"]},
1883
                }
1884
            ),
1885
            call(
1886
                self.napp.controller,
1887
                context="kytos.flow_manager",
1888
                name="flows.install",
1889
                content={
1890
                    "dpid": "5",
1891
                    "flow_dict": {"flows": ["flow9", "flow10"]},
1892
                }
1893
            ),
1894
            call(
1895
                self.napp.controller,
1896
                context="kytos.flow_manager",
1897
                name="flows.install",
1898
                content={
1899
                    "dpid": "2",
1900
                    "flow_dict": {"flows": ["flow1", "flow2"]},
1901
                }
1902
            ),
1903
            call(
1904
                self.napp.controller,
1905
                context="kytos.flow_manager",
1906
                name="flows.install",
1907
                content={
1908
                    "dpid": "3",
1909
                    "flow_dict": {"flows": ["flow3", "flow4"]},
1910
                }
1911
            ),
1912
            call(
1913
                self.napp.controller,
1914
                context="kytos.flow_manager",
1915
                name="flows.install",
1916
                content={
1917
                    "dpid": "3",
1918
                    "flow_dict": {"flows": ["flow5", "flow6"]},
1919
                }
1920
            ),
1921
        ])
1922 1
        event_name = "evc_affected_by_link_down"
1923 1
        assert evc3.service_level > evc1.service_level
1924
        # evc3 should be handled before evc1
1925 1
        emit_event_mock.assert_has_calls([
1926
            call(self.napp.controller, event_name, content={
1927
                "link_id": "123",
1928
                "evc_id": "3",
1929
                "name": "name",
1930
                "metadata": "mock",
1931
                "active": "true",
1932
                "enabled": "true",
1933
                "uni_a": uni.as_dict(),
1934
                "uni_z": uni.as_dict(),
1935
            }),
1936
            call(self.napp.controller, event_name, content={
1937
                "link_id": "123",
1938
                "evc_id": "1",
1939
                "name": "name",
1940
                "metadata": "mock",
1941
                "active": "true",
1942
                "enabled": "true",
1943
                "uni_a": uni.as_dict(),
1944
                "uni_z": uni.as_dict(),
1945
            }),
1946
        ])
1947 1
        evc4.sync.assert_called_once()
1948 1
        event_name = "redeployed_link_down"
1949 1
        emit_event_mock.assert_has_calls([
1950
            call(self.napp.controller, event_name, content={
1951
                "evc_id": "4",
1952
                "name": "name",
1953
                "metadata": "mock",
1954
                "active": "true",
1955
                "enabled": "true",
1956
                "uni_a": uni.as_dict(),
1957
                "uni_z": uni.as_dict(),
1958
            }),
1959
        ])
1960
1961 1
    @patch("napps.kytos.mef_eline.main.emit_event")
1962 1
    def test_handle_evc_affected_by_link_down(self, emit_event_mock):
1963
        """Test handle_evc_affected_by_link_down method."""
1964 1
        uni = create_autospec(UNI)
1965 1
        evc1 = MagicMock(
1966
            id="1",
1967
            metadata="data_mocked",
1968
            _active="true",
1969
            _enabled="false",
1970
            uni_a=uni,
1971
            uni_z=uni,
1972
        )
1973 1
        evc1.name = "name_mocked"
1974 1
        evc1.handle_link_down.return_value = True
1975 1
        evc2 = MagicMock(
1976
            id="2",
1977
            metadata="mocked_data",
1978
            _active="false",
1979
            _enabled="true",
1980
            uni_a=uni,
1981
            uni_z=uni,
1982
        )
1983 1
        evc2.name = "mocked_name"
1984 1
        evc2.handle_link_down.return_value = False
1985 1
        self.napp.circuits = {"1": evc1, "2": evc2}
1986
1987 1
        event = KytosEvent(name="e1", content={
1988
            "evc_id": "3",
1989
            "link_id": "1",
1990
        })
1991 1
        self.napp.handle_evc_affected_by_link_down(event)
1992 1
        emit_event_mock.assert_not_called()
1993 1
        event.content["evc_id"] = "1"
1994 1
        self.napp.handle_evc_affected_by_link_down(event)
1995 1
        emit_event_mock.assert_called_with(
1996
            self.napp.controller, "redeployed_link_down", content={
1997
                "evc_id": "1",
1998
                "name": "name_mocked",
1999
                "metadata": "data_mocked",
2000
                "active": "true",
2001
                "enabled": "false",
2002
                "uni_a": uni.as_dict(),
2003
                "uni_z": uni.as_dict(),
2004
            }
2005
        )
2006
2007 1
        event.content["evc_id"] = "2"
2008 1
        self.napp.handle_evc_affected_by_link_down(event)
2009 1
        emit_event_mock.assert_called_with(
2010
            self.napp.controller, "error_redeploy_link_down", content={
2011
                "evc_id": "2",
2012
                "name": "mocked_name",
2013
                "metadata": "mocked_data",
2014
                "active": "false",
2015
                "enabled": "true",
2016
                "uni_a": uni.as_dict(),
2017
                "uni_z": uni.as_dict(),
2018
            }
2019
        )
2020
2021 1
    def test_handle_evc_deployed(self):
2022
        """Test handle_evc_deployed method."""
2023 1
        evc = create_autospec(EVC, id="1")
2024 1
        evc.lock = MagicMock()
2025 1
        self.napp.circuits = {"1": evc}
2026
2027 1
        event = KytosEvent(name="e1", content={"evc_id": "2"})
2028 1
        self.napp.handle_evc_deployed(event)
2029 1
        evc.setup_failover_path.assert_not_called()
2030
2031 1
        event.content["evc_id"] = "1"
2032 1
        self.napp.handle_evc_deployed(event)
2033 1
        evc.setup_failover_path.assert_called()
2034
2035 1
    async def test_add_metadata(self, event_loop):
2036
        """Test method to add metadata"""
2037 1
        self.napp.controller.loop = event_loop
2038 1
        evc_mock = create_autospec(EVC)
2039 1
        evc_mock.metadata = {}
2040 1
        evc_mock.id = 1234
2041 1
        self.napp.circuits = {"1234": evc_mock}
2042
2043 1
        payload = {"metadata1": 1, "metadata2": 2}
2044 1
        response = await self.api_client.post(
2045
            f"{self.base_endpoint}/v2/evc/1234/metadata",
2046
            json=payload
2047
        )
2048
2049 1
        assert response.status_code == 201
2050 1
        evc_mock.extend_metadata.assert_called_with(payload)
2051
2052 1
    async def test_add_metadata_malformed_json(self, event_loop):
2053
        """Test method to add metadata with a malformed json"""
2054 1
        self.napp.controller.loop = event_loop
2055 1
        payload = b'{"metadata1": 1, "metadata2": 2,}'
2056 1
        response = await self.api_client.post(
2057
            f"{self.base_endpoint}/v2/evc/1234/metadata",
2058
            content=payload,
2059
            headers={"Content-Type": "application/json"}
2060
        )
2061
2062 1
        assert response.status_code == 400
2063 1
        assert "Failed to deserialize" in response.json()["description"]
2064
2065 1
    async def test_add_metadata_no_body(self, event_loop):
2066
        """Test method to add metadata with no body"""
2067 1
        self.napp.controller.loop = event_loop
2068 1
        response = await self.api_client.post(
2069
            f"{self.base_endpoint}/v2/evc/1234/metadata"
2070
        )
2071 1
        assert response.status_code == 400
2072 1
        assert response.json()["description"] == \
2073
            "Missing required request body"
2074
2075 1
    async def test_add_metadata_no_evc(self, event_loop):
2076
        """Test method to add metadata with no evc"""
2077 1
        self.napp.controller.loop = event_loop
2078 1
        payload = {"metadata1": 1, "metadata2": 2}
2079 1
        response = await self.api_client.post(
2080
            f"{self.base_endpoint}/v2/evc/1234/metadata",
2081
            json=payload,
2082
        )
2083 1
        assert response.status_code == 404
2084 1
        assert response.json()["description"] == \
2085
            "circuit_id 1234 not found."
2086
2087 1
    async def test_add_metadata_wrong_content_type(self, event_loop):
2088
        """Test method to add metadata with wrong content type"""
2089 1
        self.napp.controller.loop = event_loop
2090 1
        payload = {"metadata1": 1, "metadata2": 2}
2091 1
        response = await self.api_client.post(
2092
            f"{self.base_endpoint}/v2/evc/1234/metadata",
2093
            data=payload,
2094
            headers={"Content-Type": "application/xml"}
2095
        )
2096 1
        assert response.status_code == 415
2097 1
        assert "application/xml" in response.json()["description"]
2098
2099 1
    async def test_get_metadata(self):
2100
        """Test method to get metadata"""
2101 1
        evc_mock = create_autospec(EVC)
2102 1
        evc_mock.metadata = {'metadata1': 1, 'metadata2': 2}
2103 1
        evc_mock.id = 1234
2104 1
        self.napp.circuits = {"1234": evc_mock}
2105
2106 1
        response = await self.api_client.get(
2107
            f"{self.base_endpoint}/v2/evc/1234/metadata",
2108
        )
2109 1
        assert response.status_code == 200
2110 1
        assert response.json() == {"metadata": evc_mock.metadata}
2111
2112 1
    async def test_delete_metadata(self):
2113
        """Test method to delete metadata"""
2114 1
        evc_mock = create_autospec(EVC)
2115 1
        evc_mock.metadata = {'metadata1': 1, 'metadata2': 2}
2116 1
        evc_mock.id = 1234
2117 1
        self.napp.circuits = {"1234": evc_mock}
2118
2119 1
        response = await self.api_client.delete(
2120
            f"{self.base_endpoint}/v2/evc/1234/metadata/metadata1",
2121
        )
2122 1
        assert response.status_code == 200
2123
2124 1
    async def test_delete_metadata_no_evc(self):
2125
        """Test method to delete metadata with no evc"""
2126 1
        response = await self.api_client.delete(
2127
            f"{self.base_endpoint}/v2/evc/1234/metadata/metadata1",
2128
        )
2129 1
        assert response.status_code == 404
2130 1
        assert response.json()["description"] == \
2131
            "circuit_id 1234 not found."
2132
2133 1
    @patch('napps.kytos.mef_eline.main.Main._load_evc')
2134 1
    def test_load_all_evcs(self, load_evc_mock):
2135
        """Test load_evcs method"""
2136 1
        mock_circuits = {
2137
            'circuits': {
2138
                1: 'circuit_1',
2139
                2: 'circuit_2',
2140
                3: 'circuit_3',
2141
                4: 'circuit_4'
2142
            }
2143
        }
2144 1
        self.napp.mongo_controller.get_circuits.return_value = mock_circuits
2145 1
        self.napp.circuits = {2: 'circuit_2', 3: 'circuit_3'}
2146 1
        self.napp.load_all_evcs()
2147 1
        load_evc_mock.assert_has_calls([call('circuit_1'), call('circuit_4')])
2148
2149 1
    @patch('napps.kytos.mef_eline.main.Main._evc_from_dict')
2150 1
    def test_load_evc(self, evc_from_dict_mock):
2151
        """Test _load_evc method"""
2152
        # pylint: disable=protected-access
2153
        # case 1: early return with ValueError exception
2154 1
        evc_from_dict_mock.side_effect = ValueError("err")
2155 1
        evc_dict = MagicMock()
2156 1
        assert not self.napp._load_evc(evc_dict)
2157
2158
        # case2: archived evc
2159 1
        evc = MagicMock()
2160 1
        evc.archived = True
2161 1
        evc_from_dict_mock.side_effect = None
2162 1
        evc_from_dict_mock.return_value = evc
2163 1
        assert not self.napp._load_evc(evc_dict)
2164
2165
        # case3: success creating
2166 1
        evc.archived = False
2167 1
        evc.id = 1
2168 1
        self.napp.sched = MagicMock()
2169
2170 1
        result = self.napp._load_evc(evc_dict)
2171 1
        assert result == evc
2172 1
        evc.deactivate.assert_called()
2173 1
        evc.sync.assert_called()
2174 1
        self.napp.sched.add.assert_called_with(evc)
2175 1
        assert self.napp.circuits[1] == evc
2176
2177 1
    def test_handle_flow_mod_error(self):
2178
        """Test handle_flow_mod_error method"""
2179 1
        flow = MagicMock()
2180 1
        flow.cookie = 0xaa00000000000011
2181 1
        event = MagicMock()
2182 1
        event.content = {'flow': flow, 'error_command': 'add'}
2183 1
        evc = create_autospec(EVC)
2184 1
        evc.remove_current_flows = MagicMock()
2185 1
        self.napp.circuits = {"00000000000011": evc}
2186 1
        self.napp.handle_flow_mod_error(event)
2187 1
        evc.remove_current_flows.assert_called_once()
2188
2189 1
    @patch("kytos.core.Controller.get_interface_by_id")
2190 1
    def test_uni_from_dict(self, _get_interface_by_id_mock):
2191
        """Test _uni_from_dict method."""
2192
        # pylint: disable=protected-access
2193
        # case1: early return on empty dict
2194 1
        assert not self.napp._uni_from_dict(None)
2195
2196
        # case2: invalid interface raises ValueError
2197 1
        _get_interface_by_id_mock.return_value = None
2198 1
        uni_dict = {
2199
            "interface_id": "00:01:1",
2200
            "tag": {"tag_type": 1, "value": 81},
2201
        }
2202 1
        with pytest.raises(ValueError):
2203 1
            self.napp._uni_from_dict(uni_dict)
2204
2205
        # case3: success creation
2206 1
        uni_mock = get_uni_mocked(switch_id="00:01")
2207 1
        _get_interface_by_id_mock.return_value = uni_mock.interface
2208 1
        uni = self.napp._uni_from_dict(uni_dict)
2209 1
        assert uni == uni_mock
2210
2211
        # case4: success creation without tag
2212 1
        uni_mock.user_tag = None
2213 1
        del uni_dict["tag"]
2214 1
        uni = self.napp._uni_from_dict(uni_dict)
2215 1
        assert uni == uni_mock
2216
2217 1
    def test_handle_flow_delete(self):
2218
        """Test handle_flow_delete method"""
2219 1
        flow = MagicMock()
2220 1
        flow.cookie = 0xaa00000000000011
2221 1
        event = MagicMock()
2222 1
        event.content = {'flow': flow}
2223 1
        evc = create_autospec(EVC)
2224 1
        evc.set_flow_removed_at = MagicMock()
2225 1
        self.napp.circuits = {"00000000000011": evc}
2226 1
        self.napp.handle_flow_delete(event)
2227 1
        evc.set_flow_removed_at.assert_called_once()
2228
2229 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...
2230
        """Test add_bulk_metadata method"""
2231 1
        self.napp.controller.loop = event_loop
2232 1
        evc_mock = create_autospec(EVC)
2233 1
        evc_mock.id = 1234
2234 1
        self.napp.circuits = {"1234": evc_mock}
2235 1
        payload = {
2236
            "circuit_ids": ["1234"],
2237
            "metadata1": 1,
2238
            "metadata2": 2
2239
        }
2240 1
        response = await self.api_client.post(
2241
            f"{self.base_endpoint}/v2/evc/metadata",
2242
            json=payload
2243
        )
2244 1
        assert response.status_code == 201
2245 1
        args = self.napp.mongo_controller.update_evcs.call_args[0]
2246 1
        ids = payload.pop("circuit_ids")
2247 1
        assert args[0] == ids
2248 1
        assert args[1] == payload
2249 1
        assert args[2] == "add"
2250 1
        calls = self.napp.mongo_controller.update_evcs.call_count
2251 1
        assert calls == 1
2252 1
        evc_mock.extend_metadata.assert_called_with(payload)
2253
2254 1
    async def test_add_bulk_metadata_no_id(self, event_loop):
2255
        """Test add_bulk_metadata with unknown evc id"""
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
            "circuit_ids": ["1234", "4567"]
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 == 404
2268
2269 1
    async def test_add_bulk_metadata_no_circuits(self, event_loop):
2270
        """Test add_bulk_metadata without circuit_ids"""
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
            "metadata": "data"
2277
        }
2278 1
        response = await self.api_client.post(
2279
            f"{self.base_endpoint}/v2/evc/metadata",
2280
            json=payload
2281
        )
2282 1
        assert response.status_code == 400
2283
2284 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...
2285
        """Test delete_metadata method"""
2286 1
        self.napp.controller.loop = event_loop
2287 1
        evc_mock = create_autospec(EVC)
2288 1
        evc_mock.id = 1234
2289 1
        self.napp.circuits = {"1234": evc_mock}
2290 1
        payload = {
2291
            "circuit_ids": ["1234"]
2292
        }
2293 1
        response = await self.api_client.request(
2294
            "DELETE",
2295
            f"{self.base_endpoint}/v2/evc/metadata/metadata1",
2296
            json=payload
2297
        )
2298 1
        assert response.status_code == 200
2299 1
        args = self.napp.mongo_controller.update_evcs.call_args[0]
2300 1
        assert args[0] == payload["circuit_ids"]
2301 1
        assert args[1] == {"metadata1": ""}
2302 1
        assert args[2] == "del"
2303 1
        calls = self.napp.mongo_controller.update_evcs.call_count
2304 1
        assert calls == 1
2305
        assert evc_mock.remove_metadata.call_count == 1
2306