Passed
Push — master ( fa6907...6c74fb )
by Vinicius
02:48 queued 15s
created

TestMain.test_create_schedule()   B

Complexity

Conditions 1

Size

Total Lines 58
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 44
nop 8
dl 0
loc 58
ccs 28
cts 28
cp 1
crap 1
rs 8.824
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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