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

TestMain.test_get_metadata()   A

Complexity

Conditions 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 9
nop 1
dl 0
loc 12
ccs 8
cts 8
cp 1
crap 1
rs 9.95
c 0
b 0
f 0
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