Passed
Pull Request — master (#359)
by
unknown
03:35
created

TestEVC.test_should_deploy_case4()   A

Complexity

Conditions 1

Size

Total Lines 15
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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