Passed
Pull Request — master (#491)
by Aldo
04:10
created

TestEVC.test_install_nni_flows()   A

Complexity

Conditions 1

Size

Total Lines 50
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 1

Importance

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