Passed
Pull Request — master (#681)
by Aldo
04:55
created

  A

Complexity

Conditions 1

Size

Total Lines 33
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 25
nop 1
dl 0
loc 33
ccs 9
cts 9
cp 1
crap 1
rs 9.28
c 0
b 0
f 0
1
"""Method to thest EVCDeploy class."""
2 1
import sys
3 1
from unittest.mock import MagicMock, Mock, call, patch
4 1
import operator
5 1
import pytest
6 1
from kytos.lib.helpers import get_controller_mock
7
8 1
from kytos.core.common import EntityStatus
9 1
from kytos.core.exceptions import (KytosNoTagAvailableError,
10
                                   KytosTagtypeNotSupported)
11 1
from kytos.core.interface import Interface
12 1
from kytos.core.switch import Switch
13 1
from httpx import TimeoutException
14
# pylint: disable=wrong-import-position
15 1
sys.path.insert(0, "/var/lib/kytos/napps/..")
16
# pylint: enable=wrong-import-position
17
18 1
from napps.kytos.mef_eline.exceptions import (ActivationError,
19
                                              FlowModException,   # NOQA
20
                                              EVCPathNotInstalled)
21 1
from napps.kytos.mef_eline.models import EVC, EVCDeploy, Path  # NOQA
22 1
from napps.kytos.mef_eline.settings import (ANY_SB_PRIORITY,  # NOQA
23
                                            EPL_SB_PRIORITY, EVPL_SB_PRIORITY,
24
                                            MANAGER_URL,
25
                                            SDN_TRACE_CP_URL,
26
                                            UNTAGGED_SB_PRIORITY)
27 1
from napps.kytos.mef_eline.tests.helpers import (get_link_mocked,  # NOQA
28
                                                 get_uni_mocked)
29
30
31
# pylint: disable=too-many-public-methods, too-many-lines
32 1
class TestEVC():
33
    """Tests to verify EVC class."""
34
35 1
    def setup_method(self):
36
        """Setup method"""
37 1
        attributes = {
38
            "controller": get_controller_mock(),
39
            "name": "circuit_for_tests",
40
            "uni_a": get_uni_mocked(is_valid=True),
41
            "uni_z": get_uni_mocked(is_valid=True),
42
        }
43 1
        self.evc_deploy = EVCDeploy(**attributes)
44
45 1
    def test_primary_links_zipped_empty(self):
46
        """Test primary links zipped method."""
47 1
        assert not self.evc_deploy.links_zipped(None)
48
49 1
    @staticmethod
50 1
    @patch("napps.kytos.mef_eline.models.evc.log")
51 1
    def test_should_deploy_case1(log_mock):
52
        """Test should deploy method without primary links."""
53 1
        log_mock.debug.return_value = True
54 1
        attributes = {
55
            "controller": get_controller_mock(),
56
            "name": "custom_name",
57
            "uni_a": get_uni_mocked(is_valid=True),
58
            "uni_z": get_uni_mocked(is_valid=True),
59
        }
60
61 1
        evc = EVC(**attributes)
62 1
        evc.should_deploy()
63 1
        log_mock.debug.assert_called_with("Path is empty.")
64
65 1 View Code Duplication
    @patch("napps.kytos.mef_eline.models.evc.log")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
66 1
    def test_should_deploy_case2(self, log_mock):
67
        """Test should deploy method with disable circuit."""
68 1
        log_mock.debug.return_value = True
69 1
        attributes = {
70
            "controller": get_controller_mock(),
71
            "name": "custom_name",
72
            "uni_a": get_uni_mocked(is_valid=True),
73
            "uni_z": get_uni_mocked(is_valid=True),
74
            "primary_links": [get_link_mocked(), get_link_mocked()],
75
        }
76 1
        evc = EVC(**attributes)
77
78 1
        assert evc.should_deploy(attributes["primary_links"]) is False
79 1
        log_mock.debug.assert_called_with(f"{evc} is disabled.")
80
81 1 View Code Duplication
    @patch("napps.kytos.mef_eline.models.evc.log")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
82 1
    def test_should_deploy_case3(self, log_mock):
83
        """Test should deploy method with enabled and not active circuit."""
84 1
        log_mock.debug.return_value = True
85 1
        attributes = {
86
            "controller": get_controller_mock(),
87
            "name": "custom_name",
88
            "uni_a": get_uni_mocked(is_valid=True),
89
            "uni_z": get_uni_mocked(is_valid=True),
90
            "primary_links": [get_link_mocked(), get_link_mocked()],
91
            "enabled": True,
92
        }
93 1
        evc = EVC(**attributes)
94 1
        assert evc.should_deploy(attributes["primary_links"]) is True
95 1
        log_mock.debug.assert_called_with(f"{evc} will be deployed.")
96
97 1
    @patch("napps.kytos.mef_eline.models.evc.log")
98 1
    def test_should_deploy_case4(self, log_mock):
99
        """Test should deploy method with enabled and active circuit."""
100 1
        log_mock.debug.return_value = True
101 1
        attributes = {
102
            "controller": get_controller_mock(),
103
            "name": "custom_name",
104
            "uni_a": get_uni_mocked(is_valid=True),
105
            "uni_z": get_uni_mocked(is_valid=True),
106
            "primary_links": [get_link_mocked(), get_link_mocked()],
107
            "enabled": True,
108
            "active": True,
109
        }
110 1
        evc = EVC(**attributes)
111 1
        assert evc.should_deploy(attributes["primary_links"]) is False
112
113 1
    @patch("napps.kytos.mef_eline.models.evc.httpx")
114 1
    def test_send_flow_mods_case1(self, httpx_mock):
115
        """Test if _send_flow_mods is sending flow_mods to be installed."""
116 1
        flow_mods = {"00:01": {"flows": [20]}}
117
118 1
        response = MagicMock()
119 1
        response.status_code = 201
120 1
        response.is_server_error = False
121 1
        httpx_mock.post.return_value = response
122
123
        # pylint: disable=protected-access
124 1
        EVC._send_flow_mods(flow_mods, "install")
125
126 1
        expected_endpoint = f"{MANAGER_URL}/flows"
127 1
        expected_data = flow_mods
128 1
        expected_data["force"] = False
129 1
        assert httpx_mock.post.call_count == 1
130 1
        httpx_mock.post.assert_called_once_with(
131
            expected_endpoint, json=expected_data, timeout=30
132
        )
133
134 1
    @patch("napps.kytos.mef_eline.models.evc.httpx")
135 1
    def test_send_flow_mods_case2(self, httpx_mock):
136
        """Test if _send_flow_mods are sending flow_mods to be deleted
137
         and by_switch."""
138 1
        flow_mods = {"00:01": {"flows": [20]}}
139 1
        response = MagicMock()
140 1
        response.status_code = 201
141 1
        response.is_server_error = False
142 1
        httpx_mock.request.return_value = response
143
144
        # pylint: disable=protected-access
145 1
        EVC._send_flow_mods(
146
            flow_mods, command='delete', force=True, by_switch=True
147
        )
148
149 1
        expected_endpoint = f"{MANAGER_URL}/flows_by_switch/?force={True}"
150 1
        assert httpx_mock.request.call_count == 1
151 1
        httpx_mock.request.assert_called_once_with(
152
            "DELETE", expected_endpoint, json=flow_mods, timeout=30
153
        )
154
155 1
    @patch("time.sleep")
156 1
    @patch("napps.kytos.mef_eline.models.evc.httpx")
157 1
    def test_send_flow_mods_error(self, httpx_mock, _):
158
        """Test flow_manager call fails."""
159 1
        flow_mods = {"00:01": {"flows": [20]}}
160 1
        response = MagicMock()
161 1
        response.status_code = 415
162 1
        httpx_mock.post.return_value = response
163
164
        # pylint: disable=protected-access
165 1
        with pytest.raises(FlowModException):
166 1
            EVC._send_flow_mods(
167
                flow_mods,
168
                command='delete',
169
                force=True
170
            )
171 1
        assert httpx_mock.request.call_count == 3
172
173 1
    def test_prepare_flow_mod(self):
174
        """Test prepare flow_mod method."""
175 1
        interface_a = Interface("eth0", 1, Mock(spec=Switch))
176 1
        interface_z = Interface("eth1", 3, Mock(spec=Switch))
177 1
        attributes = {
178
            "table_group": {"epl": 0, "evpl": 0},
179
            "controller": get_controller_mock(),
180
            "name": "custom_name",
181
            "uni_a": get_uni_mocked(is_valid=True),
182
            "uni_z": get_uni_mocked(is_valid=True),
183
            "primary_links": [get_link_mocked(), get_link_mocked()],
184
            "enabled": True,
185
            "active": True,
186
        }
187 1
        evc = EVC(**attributes)
188
189
        # pylint: disable=protected-access
190 1
        flow_mod = evc._prepare_flow_mod(interface_a, interface_z)
191 1
        expected_flow_mod = {
192
            "match": {"in_port": interface_a.port_number},
193
            "cookie": evc.get_cookie(),
194
            "owner": "mef_eline",
195
            "actions": [
196
                {"action_type": "output", "port": interface_z.port_number}
197
            ],
198
            "priority": EVPL_SB_PRIORITY,
199
            "table_group": "evpl",
200
            "table_id": 0,
201
        }
202 1
        assert expected_flow_mod == flow_mod
203
204 1
        evc.sb_priority = 1234
205 1
        flow_mod = evc._prepare_flow_mod(interface_a, interface_z, 3)
206 1
        assert flow_mod["priority"] == 1234
207 1
        assert flow_mod["actions"][0]["action_type"] == "set_queue"
208 1
        assert flow_mod["actions"][0]["queue_id"] == 3
209 1
        assert flow_mod["actions"][1]["action_type"] == "output"
210 1
        assert flow_mod["actions"][1]["port"] == interface_z.port_number
211
212 1 View Code Duplication
    @pytest.mark.parametrize(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
213
        "out_vlan, in_vlan, new_c_vlan",
214
        [
215
            (2, 100, 0),
216
            (2, 100, 200),
217
        ]
218
    )
219 1
    def test_prepare_pop_flow_set_vlan(self, out_vlan, in_vlan, new_c_vlan):
220
        """Test _preprate_pop_flow when it adds set_vlan."""
221 1
        attributes = {
222
            "table_group": {"epl": 0, "evpl": 0},
223
            "controller": get_controller_mock(),
224
            "name": "custom_name",
225
            "uni_a": get_uni_mocked(interface_port=1, is_valid=True),
226
            "uni_z": get_uni_mocked(interface_port=2, is_valid=True),
227
        }
228 1
        evc = EVC(**attributes)
229 1
        interface_a = evc.uni_a.interface
230 1
        interface_z = evc.uni_z.interface
231 1
        flow_mod = evc._prepare_pop_flow(
232
            interface_a, interface_z, out_vlan, in_vlan, new_c_vlan
233
        )
234 1
        expected_flow_mod = {
235
            "match": {"in_port": interface_a.port_number,
236
                      "dl_vlan": out_vlan},
237
            "cookie": evc.get_cookie(),
238
            "owner": "mef_eline",
239
            "actions": [
240
                {"action_type": "set_vlan", "vlan_id": in_vlan},
241
                {"action_type": "output", "port": interface_z.port_number},
242
            ],
243
            "priority": EVPL_SB_PRIORITY,
244
            "table_group": "evpl",
245
            "table_id": 0,
246
        }
247 1
        assert flow_mod == expected_flow_mod
248
249 1 View Code Duplication
    @pytest.mark.parametrize(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
250
        "out_vlan, in_vlan, new_c_vlan",
251
        [
252
            (2, 100, 100),
253
            (2, 0, 100),
254
            (2, "4096/4096", 100),
255
            (2, None, 100),
256
            (2, 0, 0),
257
            (2, "4096/4096", 0),
258
            (2, None, 0),
259
            (2, 100, "4096/4096"),
260
            (2, 0, "4096/4096"),
261
            (2, "4096/4096", "4096/4096"),
262
            (2, None, "4096/4096"),
263
            (2, 100, None),
264
            (2, 0, None),
265
            (2, "4096/4096", None),
266
            (2, None, None)
267
        ]
268
    )
269 1
    def test_prepare_pop_flow_pop_vlan(self, out_vlan, in_vlan, new_c_vlan):
270
        """Test _prepare_pop_flow  method with pop_vlan."""
271 1
        attributes = {
272
            "table_group": {"epl": 0, "evpl": 0},
273
            "controller": get_controller_mock(),
274
            "name": "custom_name",
275
            "uni_a": get_uni_mocked(interface_port=1, is_valid=True),
276
            "uni_z": get_uni_mocked(interface_port=2, is_valid=True),
277
        }
278 1
        evc = EVC(**attributes)
279 1
        interface_a = evc.uni_a.interface
280 1
        interface_z = evc.uni_z.interface
281
282
        # pylint: disable=protected-access
283 1
        flow_mod = evc._prepare_pop_flow(
284
            interface_a, interface_z, out_vlan, in_vlan, new_c_vlan
285
        )
286
287 1
        expected_flow_mod = {
288
            "match": {"in_port": interface_a.port_number,
289
                      "dl_vlan": out_vlan},
290
            "cookie": evc.get_cookie(),
291
            "owner": "mef_eline",
292
            "actions": [
293
                {"action_type": "pop_vlan"},
294
                {"action_type": "output", "port": interface_z.port_number},
295
            ],
296
            "priority": EVPL_SB_PRIORITY,
297
            "table_group": "evpl",
298
            "table_id": 0,
299
        }
300 1
        assert expected_flow_mod == flow_mod
301
302
    # pylint: disable=too-many-branches
303 1
    @pytest.mark.parametrize(
304
        "in_vlan_a,in_vlan_z",
305
        [
306
            (100, 50),
307
            (100, 100),
308
            (100, "4096/4096"),
309
            (100, 0),
310
            (100, None),
311
            ("4096/4096", 50),
312
            ("4096/4096", "4096/4096"),
313
            ("4096/4096", 0),
314
            ("4096/4096", None),
315
            (0, 50),
316
            (0, "4096/4096"),
317
            (0, 0),
318
            (0, None),
319
            (None, 50),
320
            (None, "4096/4096"),
321
            (None, 0),
322
            (None, None),
323
        ]
324
    )
325 1
    def test_prepare_push_flow(self, in_vlan_a, in_vlan_z):
326
        """Test prepare push flow method."""
327 1
        attributes = {
328
            "table_group": {"evpl": 3, "epl": 4},
329
            "controller": get_controller_mock(),
330
            "name": "custom_name",
331
            "uni_a": get_uni_mocked(interface_port=1, is_valid=True),
332
            "uni_z": get_uni_mocked(interface_port=2, is_valid=True),
333
        }
334 1
        evc = EVC(**attributes)
335 1
        interface_a = evc.uni_a.interface
336 1
        interface_z = evc.uni_z.interface
337 1
        out_vlan_a = 20
338
339
        # pylint: disable=protected-access
340 1
        flow_mod = evc._prepare_push_flow(interface_a, interface_z,
341
                                          in_vlan_a, out_vlan_a,
342
                                          in_vlan_z)
343 1
        expected_flow_mod = {
344
            'match': {'in_port': interface_a.port_number},
345
            'cookie': evc.get_cookie(),
346
            'owner': 'mef_eline',
347
            'table_id': 3,
348
            'table_group': 'evpl',
349
            'actions': [
350
                {'action_type': 'push_vlan', 'tag_type': 's'},
351
                {'action_type': 'set_vlan', 'vlan_id': out_vlan_a},
352
                {
353
                    'action_type': 'output',
354
                    'port': interface_z.port_number
355
                }
356
            ],
357
            "priority": EVPL_SB_PRIORITY,
358
        }
359 1
        expected_flow_mod["priority"] = evc.get_priority(in_vlan_a)
360 1
        if (
361
            isinstance(in_vlan_a, int) and
362
            isinstance(in_vlan_z, int) and
363
            in_vlan_a != in_vlan_z
364
        ):
365 1
            expected_flow_mod["actions"].pop(0)
366 1
        if in_vlan_a is not None:
367 1
            expected_flow_mod['match']['dl_vlan'] = in_vlan_a
368 1
        if (
369
            in_vlan_z not in evc.special_cases and
370
            in_vlan_a != in_vlan_z and
371
            not isinstance(in_vlan_a, int)
372
        ):
373 1
            new_action = {"action_type": "set_vlan",
374
                          "vlan_id": in_vlan_z}
375 1
            expected_flow_mod["actions"].insert(0, new_action)
376 1
        if in_vlan_a == "4096/4096":
377 1
            if in_vlan_z == 0:
378 1
                new_action = {"action_type": "pop_vlan"}
379 1
                expected_flow_mod["actions"].insert(0, new_action)
380 1
        elif not in_vlan_a:
381 1
            if in_vlan_a is None:
382 1
                expected_flow_mod["table_group"] = "epl"
383 1
                expected_flow_mod["table_id"] = 4
384 1
            if in_vlan_z not in evc.special_cases:
385 1
                new_action = {"action_type": "push_vlan",
386
                              "tag_type": "c"}
387 1
                expected_flow_mod["actions"].insert(0, new_action)
388 1
        assert expected_flow_mod == flow_mod, (in_vlan_a, in_vlan_z)
389
390 1
    @staticmethod
391 1
    def create_evc_inter_switch(tag_value_a=82, tag_value_z=83):
392
        """Create inter-switch EVC with two links in the path"""
393 1
        uni_a = get_uni_mocked(
394
            interface_port=2,
395
            tag_value=tag_value_a,
396
            switch_id=1,
397
            switch_dpid=1,
398
            is_valid=True,
399
        )
400 1
        uni_z = get_uni_mocked(
401
            interface_port=3,
402
            tag_value=tag_value_z,
403
            switch_id=3,
404
            switch_dpid=3,
405
            is_valid=True,
406
        )
407
408 1
        attributes = {
409
            "controller": get_controller_mock(),
410
            "name": "custom_name",
411
            "id": "1",
412
            "uni_a": uni_a,
413
            "uni_z": uni_z,
414
            "primary_links": [
415
                get_link_mocked(
416
                    switch_a=Switch(1),
417
                    switch_b=Switch(2),
418
                    endpoint_a_port=9,
419
                    endpoint_b_port=10,
420
                    metadata={"s_vlan": 5},
421
                ),
422
                get_link_mocked(
423
                    switch_a=Switch(2),
424
                    switch_b=Switch(3),
425
                    endpoint_a_port=11,
426
                    endpoint_b_port=12,
427
                    metadata={"s_vlan": 6},
428
                ),
429
            ],
430
            "table_group": {"epl": 0, "evpl": 0}
431
        }
432 1
        return EVC(**attributes)
433
434 1
    @patch("httpx.post")
435 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
436 1
    @patch("napps.kytos.mef_eline.models.evc.log")
437 1
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
438 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_flows")
439 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_direct_uni_flows")
440 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.try_to_activate")
441 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.should_deploy")
442 1
    def test_deploy_successfully(self, *args):
443
        """Test if all methods to deploy are called."""
444
        # pylint: disable=too-many-locals
445 1
        (
446
            should_deploy_mock,
447
            activate_mock,
448
            install_direct_uni_flows_mock,
449
            install_unni_flows_mock,
450
            chose_vlans_mock,
451
            log_mock,
452
            _,
453
            httpx_mock,
454
        ) = args
455
456 1
        response = MagicMock()
457 1
        response.status_code = 201
458 1
        response.is_server_error = False
459 1
        httpx_mock.return_value = response
460
461 1
        should_deploy_mock.return_value = True
462 1
        evc = self.create_evc_inter_switch()
463 1
        deployed = evc.deploy_to_path(evc.primary_links)
464
465 1
        assert should_deploy_mock.call_count == 1
466 1
        assert activate_mock.call_count == 1
467 1
        assert install_unni_flows_mock.call_count == 1
468 1
        assert chose_vlans_mock.call_count == 1
469 1
        log_mock.info.assert_called_with(f"{evc} was deployed.")
470 1
        assert deployed is True
471
472
        # intra switch EVC
473 1
        evc = self.create_evc_intra_switch()
474 1
        assert evc.deploy_to_path(evc.primary_links) is True
475 1
        assert install_direct_uni_flows_mock.call_count == 1
476 1
        assert activate_mock.call_count == 2
477 1
        assert log_mock.info.call_count == 2
478 1
        log_mock.info.assert_called_with(f"{evc} was deployed.")
479
480 1
    @patch("httpx.post")
481 1
    @patch("napps.kytos.mef_eline.models.evc.log")
482 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.discover_new_paths")
483 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
484 1
    def test_create_evc_all_paths_invalid(self, *args):
485
        """Test create an EVC where all paths are invalid."""
486 1
        (
487
            _,
488
            discover_new_paths_mock,
489
            log_mock,
490
            httpx_mock,
491
        ) = args
492
493 1
        response = MagicMock(status_code=201, is_server_error=False)
494 1
        httpx_mock.return_value = response
495 1
        evc = self.create_evc_inter_switch()
496
497 1
        discover_new_paths_mock.return_value = iter([None, None])
498 1
        evc.deploy_to_path()
499 1
        msg_expected = "try increasing `max_paths`"
500 1
        assert log_mock.warning.call_count == 1
501 1
        assert msg_expected in log_mock.warning.call_args[0][0]
502
503 1
    def test_try_to_activate_intra_evc(self) -> None:
504
        """Test try_to_activate for intra EVC."""
505
506 1
        evc = self.create_evc_intra_switch()
507 1
        assert evc.is_intra_switch()
508 1
        assert not evc.is_active()
509 1
        assert evc.uni_a.interface.status == EntityStatus.DISABLED
510 1
        assert evc.uni_z.interface.status == EntityStatus.DISABLED
511 1
        with pytest.raises(ActivationError) as exc:
512 1
            evc.try_to_activate()
513 1
        assert "Won't be able to activate" in str(exc)
514 1
        assert "due to UNI" in str(exc)
515 1
        assert not evc.is_active()
516
517 1
        evc.uni_a.interface.enable()
518 1
        evc.uni_z.interface.enable()
519 1
        evc.uni_a.interface.activate()
520 1
        evc.uni_z.interface.deactivate()
521 1
        with pytest.raises(ActivationError) as exc:
522 1
            evc.try_to_activate()
523 1
        assert "Won't be able to activate" in str(exc)
524 1
        assert "due to UNI" in str(exc)
525 1
        assert not evc.is_active()
526
527 1
        evc.uni_z.interface.activate()
528
529 1
        assert evc.try_to_activate()
530 1
        assert evc.is_active()
531
532 1
    def test_try_to_activate_inter_evc(self) -> None:
533
        """Test try_to_activate for inter EVC."""
534
535 1
        evc = self.create_evc_inter_switch()
536 1
        assert not evc.is_intra_switch()
537 1
        assert not evc.is_active()
538 1
        assert evc.uni_a.interface.status == EntityStatus.DISABLED
539 1
        assert evc.uni_z.interface.status == EntityStatus.DISABLED
540 1
        with pytest.raises(ActivationError) as exc:
541 1
            evc.try_to_activate()
542 1
        assert "Won't be able to activate" in str(exc)
543 1
        assert "due to UNI" in str(exc)
544 1
        assert not evc.is_active()
545
546 1
        evc.uni_a.interface.enable()
547 1
        evc.uni_z.interface.enable()
548 1
        evc.uni_a.interface.activate()
549 1
        evc.uni_z.interface.deactivate()
550 1
        with pytest.raises(ActivationError) as exc:
551 1
            evc.try_to_activate()
552 1
        assert "Won't be able to activate" in str(exc)
553 1
        assert "due to UNI" in str(exc)
554 1
        assert not evc.is_active()
555
556 1
        evc.uni_z.interface.activate()
557
558 1
        with pytest.raises(ActivationError) as exc:
559 1
            evc.try_to_activate()
560 1
        assert "due to current_path status EntityStatus.DISABLED" in str(exc)
561
562 1
        cur_path = MagicMock()
563 1
        setattr(evc, "current_path", cur_path)
564 1
        cur_path.status = EntityStatus.UP
565 1
        assert evc.try_to_activate()
566 1
        assert evc.is_active()
567
568 1
    @patch("httpx.post")
569 1
    @patch("napps.kytos.mef_eline.models.evc.log")
570 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.discover_new_paths")
571 1
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
572 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_flows")
573 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.activate")
574 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.should_deploy")
575 1
    @patch("napps.kytos.mef_eline.models.EVC.sync")
576 1
    def test_deploy_fail(self, *args):
577
        """Test if all methods is ignored when the should_deploy is false."""
578
        # pylint: disable=too-many-locals
579 1
        (
580
            sync_mock,
581
            should_deploy_mock,
582
            activate_mock,
583
            install_unni_flows_mock,
584
            choose_vlans_mock,
585
            discover_new_paths_mock,
586
            log_mock,
587
            httpx_mock,
588
        ) = args
589
590 1
        response = MagicMock()
591 1
        response.status_code = 201
592 1
        httpx_mock.return_value = response
593
594 1
        evc = self.create_evc_inter_switch()
595 1
        should_deploy_mock.return_value = False
596 1
        discover_new_paths_mock.return_value = []
597 1
        deployed = evc.deploy_to_path()
598
599 1
        assert discover_new_paths_mock.call_count == 1
600 1
        assert should_deploy_mock.call_count == 1
601 1
        assert activate_mock.call_count == 0
602 1
        assert install_unni_flows_mock.call_count == 0
603 1
        assert choose_vlans_mock.call_count == 0
604 1
        assert log_mock.info.call_count == 0
605 1
        assert sync_mock.call_count == 0
606 1
        assert deployed is False
607
608
        # NoTagAvailable on static path
609 1
        should_deploy_mock.return_value = True
610 1
        choose_vlans_mock.side_effect = KytosNoTagAvailableError(MagicMock())
611 1
        assert evc.deploy_to_path(evc.primary_links) is False
612
613
        # NoTagAvailable on dynamic path
614 1
        should_deploy_mock.return_value = False
615 1
        discover_new_paths_mock.return_value = [Path(['a', 'b'])]
616 1
        choose_vlans_mock.side_effect = KytosNoTagAvailableError(MagicMock())
617 1
        assert evc.deploy_to_path(evc.primary_links) is False
618
619 1
    @patch("napps.kytos.mef_eline.models.evc.log")
620 1
    @patch(
621
        "napps.kytos.mef_eline.models.evc.EVC.discover_new_paths",
622
        return_value=[],
623
    )
624 1
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
625 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_flows")
626 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.should_deploy")
627 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.remove_current_flows")
628 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.sync")
629 1
    def test_deploy_error(self, *args):
630
        """Test if all methods is ignored when the should_deploy is false."""
631
        # pylint: disable=too-many-locals
632 1
        (
633
            sync_mock,
634
            remove_current_flows,
635
            should_deploy_mock,
636
            install_unni_flows,
637
            choose_vlans_mock,
638
            discover_new_paths,
639
            log_mock,
640
        ) = args
641
642 1
        install_unni_flows.side_effect = EVCPathNotInstalled
643 1
        should_deploy_mock.return_value = True
644 1
        uni_a = get_uni_mocked(
645
            interface_port=2,
646
            tag_value=82,
647
            switch_id="switch_uni_a",
648
            is_valid=True,
649
        )
650 1
        uni_z = get_uni_mocked(
651
            interface_port=3,
652
            tag_value=83,
653
            switch_id="switch_uni_z",
654
            is_valid=True,
655
        )
656
657 1
        primary_links = [
658
            get_link_mocked(
659
                endpoint_a_port=9, endpoint_b_port=10, metadata={"s_vlan": 5}
660
            ),
661
            get_link_mocked(
662
                endpoint_a_port=11, endpoint_b_port=12, metadata={"s_vlan": 6}
663
            ),
664
        ]
665
666 1
        attributes = {
667
            "controller": get_controller_mock(),
668
            "name": "custom_name",
669
            "uni_a": uni_a,
670
            "uni_z": uni_z,
671
            "primary_links": primary_links,
672
            "queue_id": 5,
673
        }
674
        # Setup path to deploy
675 1
        path = Path()
676 1
        path.append(primary_links[0])
677 1
        path.append(primary_links[1])
678
679 1
        evc = EVC(**attributes)
680
681 1
        deployed = evc.deploy_to_path(path)
682
683 1
        assert discover_new_paths.call_count == 0
684 1
        assert should_deploy_mock.call_count == 1
685 1
        assert install_unni_flows.call_count == 1
686 1
        assert choose_vlans_mock.call_count == 1
687 1
        assert log_mock.error.call_count == 1
688 1
        assert sync_mock.call_count == 0
689 1
        assert remove_current_flows.call_count == 2
690 1
        assert deployed is False
691
692 1
    @patch("napps.kytos.mef_eline.models.evc.emit_event")
693 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.get_failover_path_candidates")
694 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_flows")
695 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.remove_path_flows")
696 1
    @patch("napps.kytos.mef_eline.models.EVC.sync")
697 1
    def test_setup_failover_path(self, *args):
698
        """Test setup_failover_path method."""
699 1
        (
700
            sync_mock,
701
            remove_path_flows_mock,
702
            install_unni_flows_mock,
703
            get_failover_path_candidates_mock,
704
            emit_event_mock,
705
        ) = args
706
707
        # case1: early return intra switch
708 1
        evc1 = self.create_evc_intra_switch()
709
710 1
        assert evc1.setup_failover_path() is False
711 1
        assert sync_mock.call_count == 0
712
713
        # case2: early return not eligible for path failover
714 1
        evc2 = self.create_evc_inter_switch()
715 1
        evc2.is_eligible_for_failover_path = MagicMock(return_value=False)
716
717 1
        assert evc2.setup_failover_path() is False
718 1
        assert sync_mock.call_count == 0
719
720
        # case3: success failover_path setup
721 1
        evc2.is_eligible_for_failover_path = MagicMock(return_value=True)
722 1
        evc2.failover_path = ["link1", "link2"]
723 1
        path_mock = MagicMock()
724 1
        path_mock.__iter__.return_value = ["link3"]
725 1
        get_failover_path_candidates_mock.return_value = [None, path_mock]
726 1
        mock_choose = path_mock.choose_vlans
727
728 1
        assert evc2.setup_failover_path() is True
729 1
        remove_path_flows_mock.assert_called_with(["link1", "link2"])
730 1
        mock_choose.assert_called()
731 1
        install_unni_flows_mock.assert_called_with(path_mock, skip_in=True)
732 1
        assert evc2.failover_path == path_mock
733 1
        assert sync_mock.call_count == 1
734 1
        assert emit_event_mock.call_count == 1
735 1
        assert emit_event_mock.call_args[0][1] == "failover_deployed"
736
737
        # case 4: failed to setup failover_path - No Tag available
738 1
        evc2.failover_path = []
739 1
        mock_choose.side_effect = KytosNoTagAvailableError(MagicMock())
740 1
        sync_mock.call_count = 0
741
742 1
        assert evc2.setup_failover_path() is False
743 1
        assert len(list(evc2.failover_path)) == 0
744 1
        assert sync_mock.call_count == 1
745
746
        # case 5: failed to setup failover_path - FlowMod exception
747 1
        evc2.failover_path = []
748 1
        mock_choose.side_effect = None
749 1
        install_unni_flows_mock.side_effect = EVCPathNotInstalled("error")
750 1
        sync_mock.call_count = 0
751
752 1
        assert evc2.setup_failover_path() is False
753 1
        assert len(list(evc2.failover_path)) == 0
754 1
        assert sync_mock.call_count == 1
755 1
        remove_path_flows_mock.assert_called_with(path_mock)
756
757 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy_to_path")
758 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.discover_new_paths")
759 1
    def test_deploy_to_backup_path1(
760
        self, discover_new_paths_mocked, deploy_to_path_mocked
761
    ):
762
        """Test deployment when dynamic_backup_path is False in same switch"""
763 1
        uni_a = get_uni_mocked(interface_port=2, tag_value=82, is_valid=True)
764 1
        uni_z = get_uni_mocked(interface_port=3, tag_value=83, is_valid=True)
765
766 1
        switch = Mock(spec=Switch)
767 1
        uni_a.interface.switch = switch
768 1
        uni_z.interface.switch = switch
769
770 1
        attributes = {
771
            "controller": get_controller_mock(),
772
            "name": "custom_name",
773
            "uni_a": uni_a,
774
            "uni_z": uni_z,
775
            "enabled": True,
776
            "dynamic_backup_path": False,
777
        }
778
779 1
        evc = EVC(**attributes)
780 1
        discover_new_paths_mocked.return_value = []
781 1
        deploy_to_path_mocked.return_value = True
782
783 1
        deployed = evc.deploy_to_backup_path()
784
785 1
        deploy_to_path_mocked.assert_called_once_with(old_path_dict=None)
786 1
        assert deployed is True
787
788 1
    @patch("httpx.post")
789 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
790 1
    @patch("napps.kytos.mef_eline.models.evc.log")
791 1
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
792 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_flows")
793 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.try_to_activate")
794 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.should_deploy")
795 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.discover_new_paths")
796 1
    def test_deploy_without_path_case1(self, *args):
797
        """Test if not path is found a dynamic path is used."""
798
        # pylint: disable=too-many-locals
799 1
        (
800
            discover_new_paths_mocked,
801
            should_deploy_mock,
802
            activate_mock,
803
            install_unni_flows_mock,
804
            chose_vlans_mock,
805
            log_mock,
806
            _,
807
            httpx_mock,
808
        ) = args
809
810 1
        response = MagicMock()
811 1
        response.status_code = 201
812 1
        httpx_mock.return_value = response
813
814 1
        should_deploy_mock.return_value = False
815 1
        uni_a = get_uni_mocked(
816
            interface_port=2,
817
            tag_value=82,
818
            switch_id="switch_uni_a",
819
            is_valid=True,
820
        )
821 1
        uni_z = get_uni_mocked(
822
            interface_port=3,
823
            tag_value=83,
824
            switch_id="switch_uni_z",
825
            is_valid=True,
826
        )
827
828 1
        attributes = {
829
            "controller": get_controller_mock(),
830
            "name": "custom_name",
831
            "uni_a": uni_a,
832
            "uni_z": uni_z,
833
            "enabled": True,
834
            "dynamic_backup_path": False,
835
        }
836
837 1
        dynamic_backup_path = Path(
838
            [
839
                get_link_mocked(
840
                    endpoint_a_port=9,
841
                    endpoint_b_port=10,
842
                    metadata={"s_vlan": 5},
843
                ),
844
                get_link_mocked(
845
                    endpoint_a_port=11,
846
                    endpoint_b_port=12,
847
                    metadata={"s_vlan": 6},
848
                ),
849
            ]
850
        )
851
852 1
        evc = EVC(**attributes)
853 1
        discover_new_paths_mocked.return_value = [dynamic_backup_path]
854
855 1
        deployed = evc.deploy_to_path()
856
857 1
        assert should_deploy_mock.call_count == 1
858 1
        assert discover_new_paths_mocked.call_count == 1
859 1
        assert activate_mock.call_count == 1
860 1
        assert install_unni_flows_mock.call_count == 1
861 1
        assert chose_vlans_mock.call_count == 1
862 1
        log_mock.info.assert_called_with(f"{evc} was deployed.")
863 1
        assert deployed is True
864
865 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.deploy_to_primary_path")
866 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.deploy_to_backup_path")
867 1
    @patch("napps.kytos.mef_eline.models.evc.emit_event")
868 1
    def test_deploy(self, *args):
869
        """Test method deploy"""
870 1
        (emit_event_mock, deploy_primary_mock, deploy_backup_mock) = args
871
872
        # case 1: deploy to primary
873 1
        self.evc_deploy.archived = False
874 1
        deploy_primary_mock.return_value = True
875 1
        assert self.evc_deploy.deploy()
876 1
        assert emit_event_mock.call_count == 1
877
878
        # case 2: deploy to backup
879 1
        deploy_primary_mock.return_value = False
880 1
        deploy_backup_mock.return_value = True
881 1
        assert self.evc_deploy.deploy()
882 1
        assert emit_event_mock.call_count == 2
883
884
        # case 3: fail to deploy to primary and backup
885 1
        deploy_backup_mock.return_value = False
886 1
        assert self.evc_deploy.deploy() is False
887 1
        assert emit_event_mock.call_count == 2
888
889
        # case 4: archived
890 1
        self.evc_deploy.archived = True
891 1
        assert self.evc_deploy.deploy() is False
892 1
        assert emit_event_mock.call_count == 2
893
894 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.remove_current_flows")
895 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.sync")
896 1
    @patch("napps.kytos.mef_eline.models.evc.emit_event")
897 1
    def test_remove(self, *args):
898
        """Test method remove"""
899 1
        (emit_event_mock, sync_mock, remove_flows_mock) = args
900 1
        self.evc_deploy.remove()
901 1
        remove_flows_mock.assert_called()
902 1
        sync_mock.assert_called()
903 1
        emit_event_mock.assert_called()
904 1
        assert self.evc_deploy.is_enabled() is False
905
906 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
907 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
908 1
    @patch("napps.kytos.mef_eline.models.evc.log.error")
909 1
    def test_remove_current_flows(self, *args):
910
        """Test remove current flows."""
911
        # pylint: disable=too-many-locals
912 1
        (log_error_mock, send_flow_mods_mocked, _) = args
913 1
        uni_a = get_uni_mocked(
914
            interface_port=2,
915
            tag_value=82,
916
            switch_id="switch_uni_a",
917
            is_valid=True,
918
        )
919 1
        uni_z = get_uni_mocked(
920
            interface_port=3,
921
            tag_value=83,
922
            switch_id="switch_uni_z",
923
            is_valid=True,
924
        )
925
926 1
        switch_a = Switch("00:00:00:00:00:01")
927 1
        switch_b = Switch("00:00:00:00:00:02")
928 1
        switch_c = Switch("00:00:00:00:00:03")
929 1
        link_a_b = get_link_mocked(
930
            switch_a=switch_a,
931
            switch_b=switch_b,
932
            endpoint_a_port=9,
933
            endpoint_b_port=10,
934
            metadata={"s_vlan": Mock(value=5)},
935
        )
936 1
        link_b_c = get_link_mocked(
937
            switch_a=switch_b,
938
            switch_b=switch_c,
939
            endpoint_a_port=11,
940
            endpoint_b_port=12,
941
            metadata={"s_vlan": Mock(value=6)},
942
        )
943
944 1
        attributes = {
945
            "controller": get_controller_mock(),
946
            "name": "custom_name",
947
            "uni_a": uni_a,
948
            "uni_z": uni_z,
949
            "active": True,
950
            "enabled": True,
951
            "primary_links": [link_a_b, link_b_c]
952
953
        }
954
955 1
        expected_old_path = {
956
            link_a_b.id: 5,
957
            link_b_c.id: 6
958
        }
959
960 1
        evc = EVC(**attributes)
961
962 1
        evc.current_path = evc.primary_links
963 1
        old_path = evc.remove_current_flows(return_path=True)
964 1
        assert old_path == expected_old_path
965 1
        assert send_flow_mods_mocked.call_count == 1
966 1
        assert evc.is_active() is False
967 1
        flows = [
968
            {"cookie": evc.get_cookie(), "cookie_mask": 18446744073709551615,
969
             "owner": "mef_eline"}
970
        ]
971 1
        expected_flows = {
972
            "switches": [
973
                switch_a.id, switch_b.id, switch_c.id,
974
                evc.uni_a.interface.switch.id,
975
                evc.uni_z.interface.switch.id,
976
            ],
977
            "flows": flows
978
        }
979 1
        args = send_flow_mods_mocked.call_args[0]
980 1
        assert set(expected_flows["switches"]) == set(args[0]["switches"])
981 1
        assert expected_flows["flows"] == args[0]["flows"]
982 1
        assert 'delete' == args[1]
983
984 1
        send_flow_mods_mocked.side_effect = FlowModException("error")
985 1
        evc.remove_current_flows()
986 1
        log_error_mock.assert_called()
987
988 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
989 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
990 1
    @patch("napps.kytos.mef_eline.models.evc.log.error")
991 1
    def test_remove_current_flows_error(self, *args):
992
        """Test remove current flows with KytosTagError from vlans."""
993 1
        (log_error_mock, __, _) = args
994 1
        uni_a = get_uni_mocked(
995
            interface_port=2,
996
            tag_value=82,
997
            switch_id="switch_uni_a",
998
            is_valid=True,
999
        )
1000 1
        uni_z = get_uni_mocked(
1001
            interface_port=3,
1002
            tag_value=83,
1003
            switch_id="switch_uni_z",
1004
            is_valid=True,
1005
        )
1006
1007 1
        switch_a = Switch("00:00:00:00:00:01")
1008 1
        switch_b = Switch("00:00:00:00:00:02")
1009 1
        switch_c = Switch("00:00:00:00:00:03")
1010 1
        current_path = MagicMock()
1011 1
        current_path.return_value = [
1012
            get_link_mocked(
1013
                switch_a=switch_a,
1014
                switch_b=switch_b,
1015
                endpoint_a_port=9,
1016
                endpoint_b_port=10,
1017
                metadata={"s_vlan": 5},
1018
            ),
1019
            get_link_mocked(
1020
                switch_a=switch_b,
1021
                switch_b=switch_c,
1022
                endpoint_a_port=11,
1023
                endpoint_b_port=12,
1024
                metadata={"s_vlan": 6},
1025
            )
1026
        ]
1027 1
        attributes = {
1028
            "controller": get_controller_mock(),
1029
            "name": "custom_name",
1030
            "uni_a": uni_a,
1031
            "uni_z": uni_z,
1032
            "active": True,
1033
            "enabled": True,
1034
            "primary_links": [],
1035
        }
1036 1
        evc = EVC(**attributes)
1037 1
        assert evc.is_active()
1038 1
        current_path.make_vlans_available.side_effect = (
1039
            KytosTagtypeNotSupported("")
1040
        )
1041 1
        evc.remove_current_flows(current_path)
1042 1
        log_error_mock.assert_called()
1043 1
        assert not evc.is_active()
1044
1045 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1046 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
1047 1
    @patch("napps.kytos.mef_eline.models.evc.log.error")
1048 1
    def test_remove_failover_flows_exclude_uni_switches(self, *args):
1049
        """Test remove failover flows excluding UNI switches."""
1050
        # pylint: disable=too-many-locals
1051 1
        (log_error_mock, send_flow_mods_mocked, mock_upsert) = args
1052 1
        uni_a = get_uni_mocked(
1053
            interface_port=2,
1054
            tag_value=82,
1055
            switch_id="00:00:00:00:00:00:00:01",
1056
            is_valid=True,
1057
        )
1058 1
        uni_z = get_uni_mocked(
1059
            interface_port=3,
1060
            tag_value=83,
1061
            switch_id="00:00:00:00:00:00:00:03",
1062
            is_valid=True,
1063
        )
1064
1065 1
        switch_a = Switch("00:00:00:00:00:00:00:01")
1066 1
        switch_b = Switch("00:00:00:00:00:00:00:02")
1067 1
        switch_c = Switch("00:00:00:00:00:00:00:03")
1068
1069 1
        attributes = {
1070
            "controller": get_controller_mock(),
1071
            "name": "custom_name",
1072
            "uni_a": uni_a,
1073
            "uni_z": uni_z,
1074
            "active": True,
1075
            "enabled": True,
1076
            "failover_path": [
1077
                get_link_mocked(
1078
                    switch_a=switch_a,
1079
                    switch_b=switch_b,
1080
                    endpoint_a_port=9,
1081
                    endpoint_b_port=10,
1082
                    metadata={"s_vlan": 5},
1083
                ),
1084
                get_link_mocked(
1085
                    switch_a=switch_b,
1086
                    switch_b=switch_c,
1087
                    endpoint_a_port=11,
1088
                    endpoint_b_port=12,
1089
                    metadata={"s_vlan": 6},
1090
                ),
1091
            ],
1092
        }
1093
1094 1
        evc = EVC(**attributes)
1095 1
        evc.remove_failover_flows(exclude_uni_switches=True, sync=True)
1096
1097 1
        assert send_flow_mods_mocked.call_count == 1
1098 1
        flows = [
1099
            {"cookie": evc.get_cookie(),
1100
             "cookie_mask": int(0xffffffffffffffff),
1101
             "owner": "mef_eline"}
1102
        ]
1103 1
        expected_flows = {
1104
            "switches": [switch_b.id],
1105
            "flows": flows
1106
        }
1107 1
        send_flow_mods_mocked.assert_any_call(expected_flows, 'delete',
1108
                                              force=True)
1109 1
        assert mock_upsert.call_count == 1
1110
1111 1
        send_flow_mods_mocked.side_effect = FlowModException("error")
1112 1
        evc.remove_current_flows()
1113 1
        log_error_mock.assert_called()
1114
1115 1
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1116 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
1117 1
    def test_remove_failover_flows_include_all(self, *args):
1118
        """Test remove failover flows including UNI switches."""
1119
        # pylint: disable=too-many-locals
1120 1
        (send_flow_mods_mocked, mock_upsert) = args
1121 1
        uni_a = get_uni_mocked(
1122
            interface_port=2,
1123
            tag_value=82,
1124
            switch_id="00:00:00:00:00:00:00:01",
1125
            is_valid=True,
1126
        )
1127 1
        uni_z = get_uni_mocked(
1128
            interface_port=3,
1129
            tag_value=83,
1130
            switch_id="00:00:00:00:00:00:00:03",
1131
            is_valid=True,
1132
        )
1133
1134 1
        switch_a = Switch("00:00:00:00:00:00:00:01")
1135 1
        switch_b = Switch("00:00:00:00:00:00:00:02")
1136 1
        switch_c = Switch("00:00:00:00:00:00:00:03")
1137
1138 1
        attributes = {
1139
            "controller": get_controller_mock(),
1140
            "name": "custom_name",
1141
            "uni_a": uni_a,
1142
            "uni_z": uni_z,
1143
            "active": True,
1144
            "enabled": True,
1145
            "failover_path": [
1146
                get_link_mocked(
1147
                    switch_a=switch_a,
1148
                    switch_b=switch_b,
1149
                    endpoint_a_port=9,
1150
                    endpoint_b_port=10,
1151
                    metadata={"s_vlan": 5},
1152
                ),
1153
                get_link_mocked(
1154
                    switch_a=switch_b,
1155
                    switch_b=switch_c,
1156
                    endpoint_a_port=11,
1157
                    endpoint_b_port=12,
1158
                    metadata={"s_vlan": 6},
1159
                ),
1160
            ],
1161
        }
1162
1163 1
        evc = EVC(**attributes)
1164 1
        evc.remove_failover_flows(exclude_uni_switches=False, sync=True)
1165
1166 1
        assert send_flow_mods_mocked.call_count == 1
1167 1
        flows = [
1168
            {"cookie": evc.get_cookie(),
1169
             "cookie_mask": int(0xffffffffffffffff),
1170
             "owner": "mef_eline"}
1171
        ]
1172 1
        expected_flows = {
1173
            "switches": [switch_a.id, switch_b.id, switch_c.id],
1174
            "flows": flows
1175
        }
1176 1
        args = send_flow_mods_mocked.call_args[0]
1177 1
        assert set(args[0]["switches"]) == set(expected_flows["switches"])
1178 1
        assert args[0]["flows"] == expected_flows["flows"]
1179 1
        assert args[1] == 'delete'
1180 1
        assert mock_upsert.call_count == 1
1181
1182 1
    @staticmethod
1183 1
    def create_evc_intra_switch():
1184
        """Create intra-switch EVC."""
1185 1
        switch = Mock(spec=Switch)
1186 1
        switch.dpid = 2
1187 1
        switch.id = switch.dpid
1188 1
        interface_a = Interface("eth0", 1, switch)
1189 1
        interface_z = Interface("eth1", 3, switch)
1190 1
        uni_a = get_uni_mocked(
1191
            tag_value=82,
1192
            is_valid=True,
1193
        )
1194 1
        uni_z = get_uni_mocked(
1195
            tag_value=84,
1196
            is_valid=True,
1197
        )
1198 1
        uni_a.interface = interface_a
1199 1
        uni_z.interface = interface_z
1200 1
        attributes = {
1201
            "table_group": {"epl": 0, "evpl": 0},
1202
            "controller": get_controller_mock(),
1203
            "name": "custom_name",
1204
            "id": "1",
1205
            "uni_a": uni_a,
1206
            "uni_z": uni_z,
1207
            "enabled": True,
1208
        }
1209 1
        return EVC(**attributes)
1210
1211
    # pylint: disable=too-many-branches
1212 1
    @pytest.mark.parametrize(
1213
        "uni_a,uni_z",
1214
        [
1215
            (100, 50),
1216
            (100, "4096/4096"),
1217
            (100, 0),
1218
            (100, None),
1219
            ("4096/4096", 50),
1220
            ("4096/4096", "4096/4096"),
1221
            ("4096/4096", 0),
1222
            ("4096/4096", None),
1223
            (0, 50),
1224
            (0, "4096/4096"),
1225
            (0, 0),
1226
            (0, None),
1227
            (None, 50),
1228
            (None, "4096/4096"),
1229
            (None, 0),
1230
            (None, None),
1231
        ]
1232
    )
1233 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
1234 1
    def test_deploy_direct_uni_flows(self, send_flow_mods_mock, uni_a, uni_z):
1235
        """Test _install_direct_uni_flows"""
1236 1
        evc = TestEVC.create_evc_intra_switch()
1237 1
        expected_dpid = evc.uni_a.interface.switch.id
1238
1239 1
        expected_flows = [
1240
            {
1241
                "match": {"in_port": 1},
1242
                "cookie": evc.get_cookie(),
1243
                "owner": "mef_eline",
1244
                "table_id": 0,
1245
                "table_group": "epl",
1246
                "actions": [
1247
                    {"action_type": "output", "port": 3},
1248
                ],
1249
                "priority": EPL_SB_PRIORITY
1250
            },
1251
            {
1252
                "match": {"in_port": 3},
1253
                "cookie": evc.get_cookie(),
1254
                "owner": "mef_eline",
1255
                "table_id": 0,
1256
                "table_group": "epl",
1257
                "actions": [
1258
                    {"action_type": "output", "port": 1},
1259
                ],
1260
                "priority": EPL_SB_PRIORITY
1261
            }
1262
        ]
1263 1
        evc.uni_a = get_uni_mocked(tag_value=uni_a, is_valid=True)
1264 1
        evc.uni_a.interface.port_number = 1
1265 1
        evc.uni_z = get_uni_mocked(tag_value=uni_z, is_valid=True)
1266 1
        evc.uni_z.interface.port_number = 3
1267 1
        expected_dpid = evc.uni_a.interface.switch.id
1268 1
        evc._install_direct_uni_flows()
1269 1
        if uni_a is not None:
1270 1
            expected_flows[0]["match"]["dl_vlan"] = uni_a
1271 1
            expected_flows[0]["table_group"] = "evpl"
1272 1
        if uni_z is not None:
1273 1
            expected_flows[1]["match"]["dl_vlan"] = uni_z
1274 1
            expected_flows[1]["table_group"] = "evpl"
1275 1
        expected_flows[0]["priority"] = EVC.get_priority(uni_a)
1276 1
        expected_flows[1]["priority"] = EVC.get_priority(uni_z)
1277 1
        if uni_z not in evc.special_cases:
1278 1
            expected_flows[0]["actions"].insert(
1279
                0, {"action_type": "set_vlan", "vlan_id": uni_z}
1280
            )
1281 1
        if uni_a not in evc.special_cases:
1282 1
            expected_flows[1]["actions"].insert(
1283
                    0, {"action_type": "set_vlan",
1284
                        "vlan_id": uni_a}
1285
                )
1286 1
            if not uni_z:
1287 1
                expected_flows[1]["actions"].insert(
1288
                    0, {"action_type": "push_vlan",
1289
                        "tag_type": "c"}
1290
                )
1291 1
            if uni_z == 0:
1292 1
                new_action = {"action_type": "pop_vlan"}
1293 1
                expected_flows[0]["actions"].insert(0, new_action)
1294 1
        elif uni_a == "4096/4096":
1295 1
            if uni_z == 0:
1296 1
                new_action = {"action_type": "pop_vlan"}
1297 1
                expected_flows[0]["actions"].insert(0, new_action)
1298 1
        elif uni_a == 0:
1299 1
            if uni_z not in evc.special_cases:
1300 1
                expected_flows[0]["actions"].insert(
1301
                    0, {"action_type": "push_vlan",
1302
                        "tag_type": "c"}
1303
                )
1304 1
            if uni_z:
1305 1
                new_action = {"action_type": "pop_vlan"}
1306 1
                expected_flows[1]["actions"].insert(0, new_action)
1307 1
        elif uni_a is None:
1308 1
            if uni_z not in evc.special_cases:
1309 1
                expected_flows[0]["actions"].insert(
1310
                    0, {"action_type": "push_vlan",
1311
                        "tag_type": "c"}
1312
                )
1313 1
        flow_mods = {"switches": [expected_dpid], "flows": expected_flows}
1314 1
        send_flow_mods_mock.assert_called_with(flow_mods, "install")
1315
1316 1
    def test_is_affected_by_link(self):
1317
        """Test is_affected_by_link method"""
1318 1
        self.evc_deploy.current_path = Path(['a', 'b', 'c'])
1319 1
        assert self.evc_deploy.is_affected_by_link('b') is True
1320
1321 1
    def test_is_backup_path_affected_by_link(self):
1322
        """Test is_backup_path_affected_by_link method"""
1323 1
        self.evc_deploy.backup_path = Path(['a', 'b', 'c'])
1324 1
        assert self.evc_deploy.is_backup_path_affected_by_link('d') is False
1325
1326 1
    def test_is_primary_path_affected_by_link(self):
1327
        """Test is_primary_path_affected_by_link method"""
1328 1
        self.evc_deploy.primary_path = Path(['a', 'b', 'c'])
1329 1
        assert self.evc_deploy.is_primary_path_affected_by_link('c') is True
1330
1331 1
    def test_is_using_primary_path(self):
1332
        """Test is_using_primary_path method"""
1333 1
        self.evc_deploy.primary_path = Path(['a', 'b', 'c'])
1334 1
        self.evc_deploy.current_path = Path(['e', 'f', 'g'])
1335 1
        assert self.evc_deploy.is_using_primary_path() is False
1336
1337 1
    def test_is_using_backup_path(self):
1338
        """Test is_using_backup_path method"""
1339 1
        self.evc_deploy.backup_path = Path(['a', 'b', 'c'])
1340 1
        self.evc_deploy.current_path = Path(['e', 'f', 'g'])
1341 1
        assert self.evc_deploy.is_using_backup_path() is False
1342
1343 1
    @patch('napps.kytos.mef_eline.models.path.Path.status')
1344 1
    def test_is_using_dynamic_path(self, mock_status):
1345
        """Test is_using_dynamic_path method"""
1346 1
        mock_status.return_value = False
1347 1
        self.evc_deploy.backup_path = Path([])
1348 1
        self.evc_deploy.primary_path = Path([])
1349 1
        assert self.evc_deploy.is_using_dynamic_path() is False
1350
1351 1
    def test_get_path_status(self):
1352
        """Test get_path_status method"""
1353 1
        path = Path([])
1354 1
        assert self.evc_deploy.get_path_status(path) == EntityStatus.DISABLED
1355 1
        path = Path([
1356
            get_link_mocked(status=EntityStatus.UP),
1357
            get_link_mocked(status=EntityStatus.DOWN)
1358
        ])
1359 1
        assert self.evc_deploy.get_path_status(path) == EntityStatus.DOWN
1360 1
        path = Path([
1361
            get_link_mocked(status=EntityStatus.UP),
1362
            get_link_mocked(status=EntityStatus.UP)
1363
        ])
1364 1
        assert self.evc_deploy.get_path_status(path) == EntityStatus.UP
1365
1366 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._prepare_uni_flows")
1367 1
    def test_get_failover_flows(self, prepare_uni_flows_mock):
1368
        """Test get_failover_flows method."""
1369 1
        evc = self.create_evc_inter_switch()
1370 1
        evc.failover_path = Path([])
1371 1
        assert len(evc.get_failover_flows()) == 0
1372
1373 1
        path = MagicMock()
1374 1
        evc.failover_path = path
1375 1
        evc.get_failover_flows()
1376 1
        prepare_uni_flows_mock.assert_called_with(path, skip_out=True)
1377
1378 1
    @patch("napps.kytos.mef_eline.models.evc.log")
1379 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
1380 1
    @patch("napps.kytos.mef_eline.models.path.Path.make_vlans_available")
1381 1
    def test_remove_path_flows(self, *args):
1382
        """Test remove path flows."""
1383 1
        (
1384
            make_vlans_available_mock,
1385
            send_flow_mods_mock,
1386
            log_mock
1387
        ) = args
1388
1389 1
        evc = self.create_evc_inter_switch()
1390
1391 1
        evc.remove_path_flows()
1392 1
        make_vlans_available_mock.assert_not_called()
1393
1394 1
        expected_flows_1 = [
1395
            {
1396
                'cookie': 12249790986447749121,
1397
                'cookie_mask': 18446744073709551615,
1398
                "owner": "mef_eline",
1399
                'match': {'in_port': 9, 'dl_vlan':  5}
1400
            },
1401
        ]
1402 1
        expected_flows_2 = [
1403
            {
1404
                'cookie': 12249790986447749121,
1405
                'cookie_mask': 18446744073709551615,
1406
                "owner": "mef_eline",
1407
                'match': {'in_port': 10, 'dl_vlan': 5}
1408
            },
1409
            {
1410
                'cookie': 12249790986447749121,
1411
                'cookie_mask': 18446744073709551615,
1412
                "owner": "mef_eline",
1413
                'match': {'in_port': 11, 'dl_vlan': 6}
1414
            },
1415
        ]
1416 1
        expected_flows_3 = [
1417
            {
1418
                'cookie': 12249790986447749121,
1419
                'cookie_mask': 18446744073709551615,
1420
                "owner": "mef_eline",
1421
                'match': {'in_port': 12, 'dl_vlan': 6}
1422
            },
1423
        ]
1424
1425 1
        dpid_flows = evc.remove_path_flows(evc.primary_links)
1426 1
        assert dpid_flows
1427 1
        assert len(dpid_flows) == 3
1428 1
        assert sum(len(flows) for flows in dpid_flows.values()) == len(
1429
            expected_flows_1
1430
        ) + len(expected_flows_2) + len(expected_flows_3)
1431 1
        send_flow_mods_mock.assert_called_once()
1432 1
        expected_flows = {
1433
            1: {"flows": expected_flows_1},
1434
            2: {"flows": expected_flows_2},
1435
            3: {"flows": expected_flows_3}
1436
        }
1437 1
        send_flow_mods_mock.assert_called_with(
1438
            expected_flows, "delete", force=True, by_switch=True
1439
        )
1440
1441 1
        send_flow_mods_mock.side_effect = FlowModException("err")
1442 1
        evc.remove_path_flows(evc.primary_links)
1443 1
        log_mock.error.assert_called()
1444
1445 1
    @patch("httpx.put")
1446 1
    def test_run_bulk_sdntraces(self, put_mock):
1447
        """Test run_bulk_sdntraces method for bulk request."""
1448 1
        evc = self.create_evc_inter_switch()
1449 1
        response = MagicMock()
1450 1
        response.status_code = 200
1451 1
        response.json.return_value = {"result": "ok"}
1452 1
        put_mock.return_value = response
1453
1454 1
        expected_endpoint = f"{SDN_TRACE_CP_URL}/traces"
1455 1
        expected_payload = [
1456
                            {
1457
                                'trace': {
1458
                                    'switch': {'dpid': 1, 'in_port': 2},
1459
                                    'eth': {'dl_type': 0x8100, 'dl_vlan': 82}
1460
                                }
1461
                            }
1462
                        ]
1463 1
        arg_tuple = [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1464 1
        result = EVCDeploy.run_bulk_sdntraces(arg_tuple)
1465 1
        put_mock.assert_called_with(
1466
                                    expected_endpoint,
1467
                                    json=expected_payload,
1468
                                    timeout=30
1469
                                )
1470 1
        assert result['result'] == "ok"
1471
1472 1
        response.status_code = 400
1473 1
        result = EVCDeploy.run_bulk_sdntraces(arg_tuple)
1474 1
        assert result == {"result": []}
1475
1476 1
        put_mock.side_effect = TimeoutException('Timeout')
1477 1
        response.status_code = 200
1478 1
        result = EVCDeploy.run_bulk_sdntraces(arg_tuple)
1479 1
        assert result == {"result": []}
1480
1481 1
    @patch("httpx.put")
1482 1
    def test_run_bulk_sdntraces_special_vlan(self, put_mock):
1483
        """Test run_bulk_sdntraces method for bulk request."""
1484 1
        evc = self.create_evc_inter_switch()
1485 1
        response = MagicMock()
1486 1
        response.status_code = 200
1487 1
        put_mock.return_value = response
1488
1489 1
        expected_endpoint = f"{SDN_TRACE_CP_URL}/traces"
1490 1
        expected_payload = [
1491
                            {
1492
                                'trace': {
1493
                                    'switch': {'dpid': 1, 'in_port': 2}
1494
                                }
1495
                            }
1496
                        ]
1497 1
        evc.uni_a.user_tag.value = 'untagged'
1498 1
        EVCDeploy.run_bulk_sdntraces(
1499
            [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1500
        )
1501 1
        put_mock.assert_called_with(
1502
                                    expected_endpoint,
1503
                                    json=expected_payload,
1504
                                    timeout=30
1505
                                )
1506 1
        args = put_mock.call_args[1]['json'][0]
1507 1
        assert 'eth' not in args
1508
1509 1
        evc.uni_a.user_tag.value = 0
1510 1
        EVCDeploy.run_bulk_sdntraces(
1511
            [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1512
        )
1513 1
        put_mock.assert_called_with(
1514
                                    expected_endpoint,
1515
                                    json=expected_payload,
1516
                                    timeout=30
1517
                                )
1518 1
        args = put_mock.call_args[1]['json'][0]['trace']
1519 1
        assert 'eth' not in args
1520
1521 1
        evc.uni_a.user_tag.value = '5/2'
1522 1
        EVCDeploy.run_bulk_sdntraces(
1523
            [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1524
        )
1525 1
        put_mock.assert_called_with(
1526
                                    expected_endpoint,
1527
                                    json=expected_payload,
1528
                                    timeout=30
1529
                                )
1530 1
        args = put_mock.call_args[1]['json'][0]['trace']
1531 1
        assert 'eth' not in args
1532
1533 1
        expected_payload[0]['trace']['eth'] = {'dl_type': 0x8100, 'dl_vlan': 1}
1534 1
        evc.uni_a.user_tag.value = 'any'
1535 1
        EVCDeploy.run_bulk_sdntraces(
1536
            [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1537
        )
1538 1
        put_mock.assert_called_with(
1539
                                    expected_endpoint,
1540
                                    json=expected_payload,
1541
                                    timeout=30
1542
                                )
1543 1
        args = put_mock.call_args[1]['json'][0]['trace']
1544 1
        assert args['eth'] == {'dl_type': 33024, 'dl_vlan': 1}
1545
1546 1
        evc.uni_a.user_tag.value = '4096/4096'
1547 1
        EVCDeploy.run_bulk_sdntraces(
1548
            [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1549
        )
1550 1
        put_mock.assert_called_with(
1551
                                    expected_endpoint,
1552
                                    json=expected_payload,
1553
                                    timeout=30
1554
                                )
1555 1
        args = put_mock.call_args[1]['json'][0]['trace']
1556 1
        assert args['eth'] == {'dl_type': 33024, 'dl_vlan': 1}
1557
1558 1
        expected_payload[0]['trace']['eth'] = {
1559
            'dl_type': 0x8100,
1560
            'dl_vlan': 10
1561
            }
1562 1
        evc.uni_a.user_tag.value = '10/10'
1563 1
        EVCDeploy.run_bulk_sdntraces(
1564
            [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1565
        )
1566 1
        put_mock.assert_called_with(
1567
                                    expected_endpoint,
1568
                                    json=expected_payload,
1569
                                    timeout=30
1570
                                )
1571 1
        args = put_mock.call_args[1]['json'][0]['trace']
1572 1
        assert args['eth'] == {'dl_type': 33024, 'dl_vlan': 10}
1573
1574 1
        expected_payload[0]['trace']['eth'] = {
1575
            'dl_type': 0x8100,
1576
            'dl_vlan': 1
1577
            }
1578 1
        evc.uni_a.user_tag.value = '5/3'
1579 1
        EVCDeploy.run_bulk_sdntraces(
1580
            [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1581
        )
1582 1
        put_mock.assert_called_with(
1583
                                    expected_endpoint,
1584
                                    json=expected_payload,
1585
                                    timeout=30
1586
                                )
1587 1
        args = put_mock.call_args[1]['json'][0]['trace']
1588 1
        assert args['eth'] == {'dl_type': 33024, 'dl_vlan': 1}
1589
1590 1
        expected_payload[0]['trace']['eth'] = {
1591
            'dl_type': 0x8100,
1592
            'dl_vlan': 10
1593
            }
1594 1
        evc.uni_a.user_tag.value = 10
1595 1
        EVCDeploy.run_bulk_sdntraces(
1596
            [(evc.uni_a.interface, evc.uni_a.user_tag.value)]
1597
        )
1598 1
        put_mock.assert_called_with(
1599
                                    expected_endpoint,
1600
                                    json=expected_payload,
1601
                                    timeout=30
1602
                                )
1603
1604 1
    @patch("napps.kytos.mef_eline.models.evc.log")
1605 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
1606 1
    def test_check_list_traces_ordered_unordered(self, run_bulk_mock, _):
1607
        """Test check_list_traces with UNIs ordered and unordered."""
1608 1
        evc = self.create_evc_inter_switch()
1609
1610 1
        for link in evc.primary_links:
1611 1
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1612 1
        evc.current_path = evc.primary_links
1613
1614 1
        trace_a = [
1615
            {
1616
                "dpid": 1,
1617
                "port": 2,
1618
                "time": "t1",
1619
                "type": "starting",
1620
                "vlan": 82
1621
            },
1622
            {
1623
                "dpid": 2,
1624
                "port": 10,
1625
                "time": "t2",
1626
                "type": "intermediary",
1627
                "vlan": 5
1628
            },
1629
            {"dpid": 3, "port": 12, "time": "t3", "type": "last", "vlan": 6},
1630
        ]
1631 1
        trace_z = [
1632
            {
1633
                "dpid": 3,
1634
                "port": 3,
1635
                "time": "t1",
1636
                "type": "starting",
1637
                "vlan": 83
1638
            },
1639
            {
1640
                "dpid": 2,
1641
                "port": 11,
1642
                "time": "t2",
1643
                "type": "intermediary",
1644
                "vlan": 6
1645
            },
1646
            {"dpid": 1, "port": 9, "time": "t3", "type": "last", "vlan": 5},
1647
        ]
1648
1649 1
        run_bulk_mock.return_value = {"result": [trace_a, trace_z]}
1650 1
        result = EVCDeploy.check_list_traces([evc])
1651 1
        assert result[evc.id]
1652
1653
        # swapped UNIs since uni_a and uni_z might not be ordered with cur path
1654 1
        run_bulk_mock.return_value = {"result": [trace_z, trace_a]}
1655 1
        evc.uni_a, evc.uni_z = evc.uni_z, evc.uni_a
1656 1
        result = EVCDeploy.check_list_traces([evc])
1657 1
        assert result[evc.id]
1658
1659 1
    @patch("napps.kytos.mef_eline.models.evc.log")
1660 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
1661 1
    def test_check_list_traces(self, run_bulk_sdntraces_mock, _):
1662
        """Test check_list_traces method."""
1663 1
        evc = self.create_evc_inter_switch()
1664
1665 1
        for link in evc.primary_links:
1666 1
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1667 1
        evc.current_path = evc.primary_links
1668
1669 1
        trace_a = [
1670
            {
1671
                "dpid": 1,
1672
                "port": 2,
1673
                "time": "t1",
1674
                "type": "starting",
1675
                "vlan": 82
1676
            },
1677
            {
1678
                "dpid": 2,
1679
                "port": 10,
1680
                "time": "t2",
1681
                "type": "intermediary",
1682
                "vlan": 5
1683
            },
1684
            {"dpid": 3, "port": 12, "time": "t3", "type": "last", "vlan": 6},
1685
        ]
1686 1
        trace_z = [
1687
            {
1688
                "dpid": 3,
1689
                "port": 3,
1690
                "time": "t1",
1691
                "type": "starting",
1692
                "vlan": 83
1693
            },
1694
            {
1695
                "dpid": 2,
1696
                "port": 11,
1697
                "time": "t2",
1698
                "type": "intermediary",
1699
                "vlan": 6
1700
            },
1701
            {"dpid": 1, "port": 9, "time": "t3", "type": "last", "vlan": 5},
1702
        ]
1703
1704 1
        run_bulk_sdntraces_mock.return_value = {
1705
                                                "result": [trace_a, trace_z]
1706
                                            }
1707 1
        result = EVCDeploy.check_list_traces([evc])
1708 1
        assert result[evc.id] is True
1709
1710
        # case2: fail incomplete trace from uni_a
1711 1
        run_bulk_sdntraces_mock.return_value = {
1712
                                                "result": [
1713
                                                            trace_a[:2],
1714
                                                            trace_z
1715
                                                        ]
1716
        }
1717 1
        result = EVCDeploy.check_list_traces([evc])
1718 1
        assert result[evc.id] is False
1719
1720
        # case3: fail incomplete trace from uni_z
1721 1
        run_bulk_sdntraces_mock.return_value = {
1722
                                                "result": [
1723
                                                            trace_a,
1724
                                                            trace_z[:2]
1725
                                                        ]
1726
        }
1727 1
        result = EVCDeploy.check_list_traces([evc])
1728 1
        assert result[evc.id] is False
1729
1730
        # case4: fail wrong vlan id in trace from uni_a
1731 1
        trace_a[1]["vlan"] = 5
1732 1
        trace_z[1]["vlan"] = 99
1733 1
        run_bulk_sdntraces_mock.return_value = {
1734
                                                "result": [trace_a, trace_z]
1735
        }
1736 1
        result = EVCDeploy.check_list_traces([evc])
1737 1
        assert result[evc.id] is False
1738
1739
        # case5: fail wrong vlan id in trace from uni_z
1740 1
        trace_a[1]["vlan"] = 99
1741 1
        run_bulk_sdntraces_mock.return_value = {
1742
                                                "result": [trace_a, trace_z]
1743
        }
1744 1
        result = EVCDeploy.check_list_traces([evc])
1745 1
        assert result[evc.id] is False
1746
1747
        # case6: success when no output in traces
1748 1
        trace_a[1]["vlan"] = 5
1749 1
        trace_z[1]["vlan"] = 6
1750 1
        result = EVCDeploy.check_list_traces([evc])
1751 1
        assert result[evc.id] is True
1752
1753
        # case7: fail when output is None in trace_a or trace_b
1754 1
        trace_a[-1]["out"] = None
1755 1
        result = EVCDeploy.check_list_traces([evc])
1756 1
        assert result[evc.id] is False
1757 1
        trace_a[-1].pop("out", None)
1758 1
        trace_z[-1]["out"] = None
1759 1
        result = EVCDeploy.check_list_traces([evc])
1760 1
        assert result[evc.id] is False
1761
1762
        # case8: success when the output is correct on both uni
1763 1
        trace_a[-1]["out"] = {"port": 3, "vlan": 83}
1764 1
        trace_z[-1]["out"] = {"port": 2, "vlan": 82}
1765 1
        result = EVCDeploy.check_list_traces([evc])
1766 1
        assert result[evc.id] is True
1767
1768
        # case9: fail if any output is incorrect
1769 1
        trace_a[-1]["out"] = {"port": 3, "vlan": 99}
1770 1
        trace_z[-1]["out"] = {"port": 2, "vlan": 82}
1771 1
        result = EVCDeploy.check_list_traces([evc])
1772 1
        assert result[evc.id] is False
1773 1
        trace_a[-1]["out"] = {"port": 3, "vlan": 83}
1774 1
        trace_z[-1]["out"] = {"port": 2, "vlan": 99}
1775 1
        result = EVCDeploy.check_list_traces([evc])
1776 1
        assert result[evc.id] is False
1777
1778 1 View Code Duplication
    @patch("napps.kytos.mef_eline.models.evc.log")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1779 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
1780 1
    def test_check_list_traces_any_cases(self, run_bulk_sdntraces_mock, _):
1781
        """Test check_list_traces method."""
1782 1
        evc = self.create_evc_inter_switch("any", "any")
1783
1784 1
        for link in evc.primary_links:
1785 1
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1786 1
        evc.current_path = evc.primary_links
1787
1788 1
        trace_a = [
1789
            {
1790
                "dpid": 1,
1791
                "port": 2,
1792
                "time": "t1",
1793
                "type": "starting",
1794
                "vlan": 1
1795
            },
1796
            {
1797
                "dpid": 2,
1798
                "port": 10,
1799
                "time": "t2",
1800
                "type": "intermediary",
1801
                "vlan": 5
1802
            },
1803
            {
1804
                "dpid": 3,
1805
                "port": 12,
1806
                'out': {'port': 3, 'vlan': 1},
1807
                "time": "t3",
1808
                "type": "last",
1809
                "vlan": 6
1810
            },
1811
        ]
1812 1
        trace_z = [
1813
            {
1814
                "dpid": 3,
1815
                "port": 3,
1816
                "time": "t1",
1817
                "type": "starting",
1818
                "vlan": 1
1819
            },
1820
            {
1821
                "dpid": 2,
1822
                "port": 11,
1823
                "time": "t2",
1824
                "type": "intermediary",
1825
                "vlan": 6
1826
            },
1827
            {
1828
                "dpid": 1,
1829
                "port": 9,
1830
                'out': {'port': 2, 'vlan': 1},
1831
                "time": "t3",
1832
                "type": "last",
1833
                "vlan": 5
1834
            },
1835
        ]
1836
1837 1
        run_bulk_sdntraces_mock.return_value = {
1838
                                                "result": [trace_a, trace_z]
1839
                                            }
1840 1
        result = EVCDeploy.check_list_traces([evc])
1841 1
        assert result[evc.id] is True
1842
1843 1 View Code Duplication
    @patch("napps.kytos.mef_eline.models.evc.log")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1844 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
1845 1
    def test_check_list_traces_untagged_cases(self, bulk_sdntraces_mock, _):
1846
        """Test check_list_traces method."""
1847 1
        evc = self.create_evc_inter_switch("untagged", "untagged")
1848
1849 1
        for link in evc.primary_links:
1850 1
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1851 1
        evc.current_path = evc.primary_links
1852
1853 1
        trace_a = [
1854
            {
1855
                "dpid": 1,
1856
                "port": 2,
1857
                "time": "t1",
1858
                "type": "starting",
1859
                "vlan": 0
1860
            },
1861
            {
1862
                "dpid": 2,
1863
                "port": 10,
1864
                "time": "t2",
1865
                "type": "intermediary",
1866
                "vlan": 5
1867
            },
1868
            {
1869
                "dpid": 3,
1870
                "port": 12,
1871
                'out': {'port': 3},
1872
                "time": "t3", "type":
1873
                "last",
1874
                "vlan": 6
1875
                },
1876
        ]
1877 1
        trace_z = [
1878
            {
1879
                "dpid": 3,
1880
                "port": 3,
1881
                "time": "t1",
1882
                "type": "starting",
1883
                "vlan": 0
1884
            },
1885
            {
1886
                "dpid": 2,
1887
                "port": 11,
1888
                "time": "t2",
1889
                "type": "intermediary",
1890
                "vlan": 6
1891
            },
1892
            {
1893
                "dpid": 1,
1894
                "port": 9,
1895
                'out': {'port': 2},
1896
                "time": "t3",
1897
                "type": "last",
1898
                "vlan": 5
1899
            },
1900
        ]
1901
1902 1
        bulk_sdntraces_mock.return_value = {
1903
                                                "result": [trace_a, trace_z]
1904
                                            }
1905 1
        result = EVCDeploy.check_list_traces([evc])
1906 1
        assert result[evc.id] is True
1907
1908 1
    @patch("napps.kytos.mef_eline.models.evc.log")
1909 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
1910 1
    def test_check_list_traces_invalid_types(self, run_bulk_sdntraces_mock, _):
1911
        """Test check_list_traces method for invalid traces by trace type."""
1912 1
        evc = self.create_evc_inter_switch()
1913
1914 1
        for link in evc.primary_links:
1915 1
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1916 1
        evc.current_path = evc.primary_links
1917
1918 1
        trace_a = [
1919
            {
1920
                "dpid": 1,
1921
                "port": 2,
1922
                "time": "t1",
1923
                "type": "starting",
1924
                "vlan": 82
1925
            },
1926
            {
1927
                "dpid": 2,
1928
                "port": 10,
1929
                "time": "t2",
1930
                "type": "intermediary",
1931
                "vlan": 5
1932
            },
1933
            {"dpid": 3, "port": 12, "time": "t3", "type": "last", "vlan": 6},
1934
        ]
1935 1
        trace_z = [
1936
            {
1937
                "dpid": 3,
1938
                "port": 3,
1939
                "time": "t1",
1940
                "type": "starting",
1941
                "vlan": 83
1942
            },
1943
            {
1944
                "dpid": 2,
1945
                "port": 11,
1946
                "time": "t2",
1947
                "type": "intermediary",
1948
                "vlan": 6
1949
            },
1950
            {
1951
                "dpid": 1,
1952
                "port": 9,
1953
                "time": "t3",
1954
                "type": "last",
1955
                "vlan": 5
1956
            },
1957
        ]
1958
1959 1
        run_bulk_sdntraces_mock.return_value = {
1960
                                                "result": [trace_a, trace_z]
1961
                                            }
1962 1
        result = EVCDeploy.check_list_traces([evc])
1963
1964 1
        assert result[evc.id] is True
1965
1966 1
        trace_z = [
1967
            {
1968
                "dpid": 3,
1969
                "port": 3,
1970
                "time": "t1",
1971
                "type": "starting",
1972
                "vlan": 83
1973
            },
1974
            {
1975
                "dpid": 2,
1976
                "port": 11,
1977
                "time": "t2",
1978
                "type": "loop",
1979
                "vlan": 6
1980
            },
1981
        ]
1982
1983 1
        run_bulk_sdntraces_mock.return_value = {
1984
                                                "result": [trace_a, trace_z]
1985
                                            }
1986 1
        result = EVCDeploy.check_list_traces([evc])
1987
        # type loop
1988 1
        assert result[evc.id] is False
1989
1990 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.check_trace")
1991 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.check_range")
1992 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
1993 1
    def test_check_list_traces_vlan_list(self, *args):
1994
        """Test check_list_traces with vlan list"""
1995 1
        mock_bulk, mock_range, mock_trace = args
1996 1
        mask_list = [1, '2/4094', '4/4094']
1997 1
        evc = self.create_evc_inter_switch([[1, 5]], [[1, 5]])
1998 1
        evc.uni_a.user_tag.mask_list = mask_list
1999 1
        evc.uni_z.user_tag.mask_list = mask_list
2000 1
        mock_bulk.return_value = {"result": ["mock"] * 6}
2001 1
        mock_range.return_value = True
2002 1
        actual_return = EVC.check_list_traces([evc])
2003 1
        assert actual_return == {evc._id: True}
2004 1
        assert mock_trace.call_count == 0
2005 1
        assert mock_range.call_count == 1
2006 1
        args = mock_range.call_args[0]
2007 1
        assert args[0] == evc
2008 1
        assert args[1] == ["mock"] * 6
2009
2010 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.check_trace")
2011 1
    @patch("napps.kytos.mef_eline.models.evc.log")
2012 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
2013 1
    def test_check_list_traces_empty(self, mock_bulk, mock_log, mock_trace):
2014
        """Test check_list_traces with empty return"""
2015 1
        evc = self.create_evc_inter_switch(1, 1)
2016 1
        actual_return = EVC.check_list_traces([])
2017 1
        assert not actual_return
2018
2019 1
        mock_bulk.return_value = {"result": []}
2020 1
        actual_return = EVC.check_list_traces([evc])
2021 1
        assert not actual_return
2022
2023 1
        mock_bulk.return_value = {"result": ["mock"]}
2024 1
        mock_trace.return_value = True
2025 1
        actual_return = EVC.check_list_traces([evc])
2026 1
        assert mock_log.error.call_count == 1
2027 1
        assert not actual_return
2028
2029 1
    @patch(
2030
        "napps.kytos.mef_eline.models.path.DynamicPathManager"
2031
        ".get_disjoint_paths"
2032
    )
2033 1
    def test_get_failover_path_vandidates(self, get_disjoint_paths_mock):
2034
        """Test get_failover_path_candidates method"""
2035 1
        self.evc_deploy.get_failover_path_candidates()
2036 1
        get_disjoint_paths_mock.assert_called_once()
2037
2038 1
    def test_is_failover_path_affected_by_link(self):
2039
        """Test is_failover_path_affected_by_link method"""
2040 1
        link1 = get_link_mocked(endpoint_a_port=1, endpoint_b_port=2)
2041 1
        link2 = get_link_mocked(endpoint_a_port=3, endpoint_b_port=4)
2042 1
        link3 = get_link_mocked(endpoint_a_port=5, endpoint_b_port=6)
2043 1
        self.evc_deploy.failover_path = Path([link1, link2])
2044 1
        assert self.evc_deploy.is_failover_path_affected_by_link(link1) is True
2045 1
        assert self.evc_deploy.is_failover_path_affected_by_link(link3) \
2046
               is False
2047
2048 1
    def test_is_eligible_for_failover_path(self):
2049
        """Test is_eligible_for_failover_path method"""
2050 1
        assert self.evc_deploy.is_eligible_for_failover_path() is False
2051 1
        self.evc_deploy.dynamic_backup_path = True
2052 1
        self.evc_deploy.primary_path = Path([])
2053 1
        self.evc_deploy.backup_path = Path([])
2054 1
        assert self.evc_deploy.is_eligible_for_failover_path() is True
2055
2056 1
    def test_get_value_from_uni_tag(self):
2057
        """Test _get_value_from_uni_tag"""
2058 1
        uni = get_uni_mocked(tag_value="any")
2059 1
        value = EVC._get_value_from_uni_tag(uni)
2060 1
        assert value == "4096/4096"
2061
2062 1
        uni.user_tag.value = "untagged"
2063 1
        value = EVC._get_value_from_uni_tag(uni)
2064 1
        assert value == 0
2065
2066 1
        uni.user_tag.value = 100
2067 1
        value = EVC._get_value_from_uni_tag(uni)
2068 1
        assert value == 100
2069
2070 1
        uni.user_tag = None
2071 1
        value = EVC._get_value_from_uni_tag(uni)
2072 1
        assert value is None
2073
2074 1
        uni = get_uni_mocked(tag_value=[[12, 20]])
2075 1
        uni.user_tag.mask_list = ['12/4092', '16/4092', '20/4094']
2076
2077 1
        value = EVC._get_value_from_uni_tag(uni)
2078 1
        assert value == ['12/4092', '16/4092', '20/4094']
2079
2080 1
    def test_get_priority(self):
2081
        """Test get_priority_from_vlan"""
2082 1
        evpl_value = EVC.get_priority(100)
2083 1
        assert evpl_value == EVPL_SB_PRIORITY
2084
2085 1
        untagged_value = EVC.get_priority(0)
2086 1
        assert untagged_value == UNTAGGED_SB_PRIORITY
2087
2088 1
        any_value = EVC.get_priority("4096/4096")
2089 1
        assert any_value == ANY_SB_PRIORITY
2090
2091 1
        epl_value = EVC.get_priority(None)
2092 1
        assert epl_value == EPL_SB_PRIORITY
2093
2094 1
        epl_value = EVC.get_priority([[1, 5]])
2095 1
        assert epl_value == EVPL_SB_PRIORITY
2096
2097 1
    def test_set_flow_table_group_id(self):
2098
        """Test set_flow_table_group_id"""
2099 1
        self.evc_deploy.table_group = {"epl": 3, "evpl": 4}
2100 1
        flow_mod = {}
2101 1
        self.evc_deploy.set_flow_table_group_id(flow_mod, 100)
2102 1
        assert flow_mod["table_group"] == "evpl"
2103 1
        assert flow_mod["table_id"] == 4
2104 1
        self.evc_deploy.set_flow_table_group_id(flow_mod, None)
2105 1
        assert flow_mod["table_group"] == "epl"
2106 1
        assert flow_mod["table_id"] == 3
2107
2108 1
    def test_get_endpoint_by_id(self):
2109
        """Test get_endpoint_by_id"""
2110 1
        link = MagicMock()
2111 1
        link.endpoint_a.switch.id = "01"
2112 1
        link.endpoint_b.switch.id = "02"
2113 1
        result = self.evc_deploy.get_endpoint_by_id(link, "01", operator.eq)
2114 1
        assert result == link.endpoint_a
2115 1
        result = self.evc_deploy.get_endpoint_by_id(link, "01", operator.ne)
2116 1
        assert result == link.endpoint_b
2117
2118 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._prepare_pop_flow")
2119 1
    @patch("napps.kytos.mef_eline.models.evc.EVC.get_endpoint_by_id")
2120 1
    @patch("napps.kytos.mef_eline.models.evc.EVC._prepare_push_flow")
2121 1
    def test_prepare_uni_flows(self, mock_push, mock_endpoint, _):
2122
        """Test _prepare_uni_flows"""
2123 1
        mask_list = [1, '2/4094', '4/4094']
2124 1
        uni_a = get_uni_mocked(interface_port=1, tag_value=[[1, 5]])
2125 1
        uni_a.user_tag.mask_list = mask_list
2126 1
        uni_z = get_uni_mocked(interface_port=2, tag_value=[[1, 5]])
2127 1
        uni_z.user_tag.mask_list = mask_list
2128 1
        mock_endpoint.return_value = "mock_endpoint"
2129 1
        attributes = {
2130
            "table_group": {"evpl": 3, "epl": 4},
2131
            "controller": get_controller_mock(),
2132
            "name": "custom_name",
2133
            "uni_a": uni_a,
2134
            "uni_z": uni_z,
2135
        }
2136 1
        evc = EVC(**attributes)
2137 1
        link = get_link_mocked()
2138 1
        evc._prepare_uni_flows(Path([link]))
2139 1
        call_list = []
2140 1
        for i in range(0, 3):
2141 1
            call_list.append(call(
2142
                uni_a.interface,
2143
                "mock_endpoint",
2144
                mask_list[i],
2145
                None,
2146
                mask_list,
2147
                queue_id=-1
2148
            ))
2149 1
        for i in range(0, 3):
2150 1
            call_list.append(call(
2151
                uni_z.interface,
2152
                "mock_endpoint",
2153
                mask_list[i],
2154
                None,
2155
                mask_list,
2156
                queue_id=-1
2157
            ))
2158 1
        mock_push.assert_has_calls(call_list)
2159
2160 1
    def test_prepare_direct_uni_flows(self):
2161
        """Test _prepare_direct_uni_flows"""
2162 1
        mask_list = [1, '2/4094', '4/4094']
2163 1
        uni_a = get_uni_mocked(interface_port=1, tag_value=[[1, 5]])
2164 1
        uni_a.user_tag.mask_list = mask_list
2165 1
        uni_z = get_uni_mocked(interface_port=2, tag_value=[[1, 5]])
2166 1
        uni_z.user_tag.mask_list = mask_list
2167 1
        attributes = {
2168
            "table_group": {"evpl": 3, "epl": 4},
2169
            "controller": get_controller_mock(),
2170
            "name": "custom_name",
2171
            "uni_a": uni_a,
2172
            "uni_z": uni_z,
2173
        }
2174 1
        evc = EVC(**attributes)
2175 1
        flows = evc._prepare_direct_uni_flows()[1]
2176 1
        assert len(flows) == 6
2177 1
        for i in range(0, 3):
2178 1
            assert flows[i]["match"]["in_port"] == 1
2179 1
            assert flows[i]["match"]["dl_vlan"] == mask_list[i]
2180 1
            assert flows[i]["priority"] == EVPL_SB_PRIORITY
2181 1
        for i in range(3, 6):
2182 1
            assert flows[i]["match"]["in_port"] == 2
2183 1
            assert flows[i]["match"]["dl_vlan"] == mask_list[i-3]
2184 1
            assert flows[i]["priority"] == EVPL_SB_PRIORITY
2185
2186 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.check_trace")
2187 1
    def test_check_range(self, mock_check_range):
2188
        """Test check_range"""
2189 1
        mask_list = [1, '2/4094', '4/4094']
2190 1
        uni_a = get_uni_mocked(interface_port=1, tag_value=[[1, 5]])
2191 1
        uni_a.user_tag.mask_list = mask_list
2192 1
        uni_z = get_uni_mocked(interface_port=2, tag_value=[[1, 5]])
2193 1
        uni_z.user_tag.mask_list = mask_list
2194 1
        attributes = {
2195
            "table_group": {"evpl": 3, "epl": 4},
2196
            "controller": get_controller_mock(),
2197
            "name": "custom_name",
2198
            "uni_a": uni_a,
2199
            "uni_z": uni_z,
2200
        }
2201 1
        circuit = EVC(**attributes)
2202 1
        traces = list(range(0, 6))
2203 1
        mock_check_range.return_value = True
2204 1
        check = EVC.check_range(circuit, traces)
2205 1
        call_list = []
2206 1
        for i in range(0, 3):
2207 1
            call_list.append(call(
2208
                circuit.id, circuit.name,
2209
                mask_list[i], mask_list[i],
2210
                uni_a.interface,
2211
                uni_z.interface,
2212
                circuit.current_path,
2213
                i*2, i*2+1
2214
            ))
2215 1
        mock_check_range.assert_has_calls(call_list)
2216 1
        assert check
2217
2218 1
        mock_check_range.side_effect = [True, False, True]
2219 1
        check = EVC.check_range(circuit, traces)
2220 1
        assert check is False
2221
2222 1
    def test_add_tag_errors(self):
2223
        """Test add_tag_errors"""
2224 1
        msg = "No available path was found."
2225 1
        tag_errors = []
2226 1
        tag_errors.append('Mocked error 1')
2227 1
        actual = self.evc_deploy.add_tag_errors(msg, tag_errors)
2228 1
        assert actual == ('No available path was found. 1 path was rejected'
2229
                          f' with message: {tag_errors}')
2230
2231 1
        tag_errors.append('Mocked error 2')
2232 1
        actual = self.evc_deploy.add_tag_errors(msg, tag_errors)
2233 1
        assert actual == ('No available path was found. 2 paths were'
2234
                          f' rejected with messages: {tag_errors}')
2235
2236 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.setup_failover_path")
2237 1
    def test_try_setup_failover_path(self, setup_failover_mock):
2238
        """Test try_setup_failover_path"""
2239 1
        self.evc_deploy.failover_path = True
2240 1
        self.evc_deploy.current_path = False
2241 1
        self.evc_deploy.is_active = MagicMock(return_value=False)
2242 1
        self.evc_deploy.try_setup_failover_path()
2243 1
        assert setup_failover_mock.call_count == 0
2244
2245 1
        self.evc_deploy.failover_path = False
2246 1
        self.evc_deploy.current_path = True
2247 1
        self.evc_deploy.is_active = MagicMock(return_value=True)
2248 1
        self.evc_deploy.try_setup_failover_path()
2249 1
        assert setup_failover_mock.call_count == 1
2250
2251 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy._send_flow_mods")
2252 1
    @patch(
2253
        "napps.kytos.mef_eline.models.evc.EVCDeploy._prepare_direct_uni_flows"
2254
    )
2255 1
    def test_install_direct_uni_flows_error(self, prepare_mock, send_mock):
2256
        """Test _install_direct_uni_flows with errors"""
2257 1
        prepare_mock.return_value = True, True
2258 1
        send_mock.side_effect = FlowModException
2259 1
        with pytest.raises(EVCPathNotInstalled):
2260 1
            self.evc_deploy._install_direct_uni_flows()
2261
2262 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy._send_flow_mods")
2263 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy._prepare_nni_flows")
2264 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy._prepare_uni_flows")
2265 1
    def test_install_flows_error(
2266
        self, prepare_uni_mock, prepare_nni_mock, send_flow_mock
2267
    ):
2268
        """Test _install_flows with error"""
2269 1
        prepare_nni_mock.return_value = {'1': [1]}
2270 1
        prepare_uni_mock.return_value = {'2': [2]}
2271 1
        send_flow_mock.side_effect = FlowModException('err')
2272 1
        with pytest.raises(EVCPathNotInstalled):
2273 1
            self.evc_deploy._install_flows()
2274
2275 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy._send_flow_mods")
2276 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy._prepare_nni_flows")
2277 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy._prepare_uni_flows")
2278 1
    def test_install_flows(
2279
        self, prepare_uni_mock, prepare_nni_mock, send_flow_mock
2280
    ):
2281
        """Test that the dictionary contains uni and nni flows sent
2282
         to be installed from _install_uni_flows."""
2283 1
        prepare_nni_mock.return_value = {'00:01': ["flow1"]}
2284 1
        prepare_uni_mock.return_value = {
2285
            '00:02': ["flow1"], '00:01': ["flow2"]
2286
        }
2287 1
        out_flows = self.evc_deploy._install_flows()
2288 1
        expected_out_fows = {
2289
            '00:01': ["flow1", "flow2"],
2290
            '00:02': ["flow1"]
2291
        }
2292 1
        assert out_flows == expected_out_fows
2293
2294 1
        expected_installed_flows = {
2295
            '00:01': {"flows": ["flow1", "flow2"]},
2296
            '00:02': {"flows": ["flow1"]}
2297
        }
2298 1
        send_flow_mock.assert_called_with(
2299
            expected_installed_flows, "install", by_switch=True
2300
        )
2301