Test Failed
Pull Request — master (#359)
by
unknown
03:41
created

TestEVC.test_deploy_successfully()   B

Complexity

Conditions 1

Size

Total Lines 47
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 40
nop 2
dl 0
loc 47
ccs 30
cts 30
cp 1
crap 1
rs 8.92
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 1
8
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
13
# pylint: disable=wrong-import-position
14
sys.path.insert(0, "/var/lib/kytos/napps/..")
15 1
# pylint: enable=wrong-import-position
16
17
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 1
                                            EPL_SB_PRIORITY, EVPL_SB_PRIORITY,
21
                                            MANAGER_URL, SDN_TRACE_CP_URL,
22
                                            UNTAGGED_SB_PRIORITY)
23
from napps.kytos.mef_eline.tests.helpers import (get_link_mocked,  # NOQA
24 1
                                                 get_uni_mocked)
25
26
27
# pylint: disable=too-many-public-methods, too-many-lines
28
class TestEVC():
29 1
    """Tests to verify EVC class."""
30
31
    def setup_method(self):
32 1
        """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 1
        [
234
            (100, 50),
235
            (100, "4096/4096"),
236
            (100, 0),
237
            (100, None),
238
            ("4096/4096", 50),
239
            ("4096/4096", "4096/4096"),
240 1
            ("4096/4096", 0),
241 1
            ("4096/4096", None),
242 1
            (0, 50),
243 1
            (0, "4096/4096"),
244
            (0, 0),
245 1
            (0, None),
246 1
            (None, 50),
247 1
            (None, "4096/4096"),
248
            (None, 0),
249 1
            (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
        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
        evc = EVC(**attributes)
262
        interface_a = evc.uni_a.interface
263
        interface_z = evc.uni_z.interface
264
        out_vlan_a = 20
265
266
        # pylint: disable=protected-access
267
        flow_mod = evc._prepare_push_flow(interface_a, interface_z,
268 1
                                          in_vlan_a, out_vlan_a,
269 1
                                          in_vlan_z)
270 1
        expected_flow_mod = {
271
            'match': {'in_port': interface_a.port_number},
272 1
            'cookie': evc.get_cookie(),
273 1
            'owner': 'mef_eline',
274
            'table_id': 3,
275 1
            'table_group': 'evpl',
276
            'actions': [
277 1
                {'action_type': 'push_vlan', 'tag_type': 's'},
278 1
                {'action_type': 'set_vlan', 'vlan_id': out_vlan_a},
279 1
                {
280 1
                    'action_type': 'output',
281 1
                    'port': interface_z.port_number
282 1
                }
283 1
            ],
284 1
            "priority": EVPL_SB_PRIORITY,
285 1
        }
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
            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
            if in_vlan_z == 0:
299
                new_action = {"action_type": "pop_vlan"}
300
                expected_flow_mod["actions"].insert(0, new_action)
301
        elif not in_vlan_a:
302 1
            if in_vlan_a is None:
303
                expected_flow_mod["table_group"] = "epl"
304
                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
                expected_flow_mod["actions"].insert(0, new_action)
309 1
        assert expected_flow_mod == flow_mod
310
311 1
    @staticmethod
312
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
313
    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
        evc = TestEVC.create_evc_inter_switch()
319
320
        # pylint: disable=protected-access
321
        evc._install_uni_flows()
322
        send_flow_mods_mock.assert_not_called()
323
324
        # pylint: disable=protected-access
325
        evc._install_uni_flows(evc.primary_links)
326
327
        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 1
                },
363
                "cookie": evc.get_cookie(),
364
                "owner": "mef_eline",
365
                "table_group": "evpl",
366 1
                "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
        send_flow_mods_mock.assert_any_call(
379
            evc.uni_a.interface.switch.id, expected_flow_mod_a
380
        )
381
382
        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 1
                },
418
                "cookie": evc.get_cookie(),
419
                "owner": "mef_eline",
420
                "table_group": "evpl",
421 1
                "table_id": 0,
422 1
                "actions": [
423
                    {"action_type": "pop_vlan"},
424 1
                    {
425
                        "action_type": "output",
426
                        "port": evc.uni_z.interface.port_number,
427
                    },
428
                ],
429
                "priority": EVPL_SB_PRIORITY,
430
            },
431 1
        ]
432
433
        send_flow_mods_mock.assert_any_call(
434
            evc.uni_z.interface.switch.id, expected_flow_mod_z
435
        )
436
437
    @staticmethod
438
    def create_evc_inter_switch(tag_value_a=82, tag_value_z=83):
439 1
        """Create inter-switch EVC with two links in the path"""
440
        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
        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
        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 1
                    switch_a=Switch(1),
464
                    switch_b=Switch(2),
465 1
                    endpoint_a_port=9,
466 1
                    endpoint_b_port=10,
467 1
                    metadata={"s_vlan": 5},
468
                ),
469
                get_link_mocked(
470
                    switch_a=Switch(2),
471
                    switch_b=Switch(3),
472 1
                    endpoint_a_port=11,
473
                    endpoint_b_port=12,
474
                    metadata={"s_vlan": 6},
475 1
                ),
476
            ],
477 1
            "table_group": {"epl": 0, "evpl": 0}
478 1
        }
479
        return EVC(**attributes)
480 1
481 1
    @staticmethod
482
    @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
        evc = TestEVC.create_evc_inter_switch()
489
490
        # pylint: disable=protected-access
491
        evc._install_nni_flows(evc.primary_links)
492
493
        in_vlan = evc.primary_links[0].get_metadata("s_vlan").value
494
        out_vlan = evc.primary_links[-1].get_metadata("s_vlan").value
495
496
        in_port = evc.primary_links[0].endpoint_b.port_number
497
        out_port = evc.primary_links[-1].endpoint_a.port_number
498
499
        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 1
                "priority": EVPL_SB_PRIORITY
511 1
            },
512
            {
513 1
                "match": {"in_port": out_port, "dl_vlan": out_vlan},
514 1
                "cookie": evc.get_cookie(),
515 1
                "owner": "mef_eline",
516 1
                "table_group": "evpl",
517 1
                "table_id": 0,
518 1
                "actions": [
519 1
                    {"action_type": "set_vlan", "vlan_id": in_vlan},
520 1
                    {"action_type": "output", "port": in_port},
521 1
                ],
522 1
                "priority": EVPL_SB_PRIORITY,
523
            },
524
        ]
525 1
526
        dpid = evc.primary_links[0].endpoint_b.switch.id
527
        send_flow_mods_mock.assert_called_once_with(dpid, expected_flow_mods)
528
529
    @patch("requests.post")
530
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
531
    @patch("napps.kytos.mef_eline.models.evc.log")
532
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
533
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_nni_flows")
534
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_uni_flows")
535
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_direct_uni_flows")
536
    @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 1
        """Test if all methods to deploy are called."""
540
        # pylint: disable=too-many-locals
541 1
        (
542 1
            should_deploy_mock,
543 1
            activate_mock,
544
            install_direct_uni_flows_mock,
545 1
            install_uni_flows_mock,
546 1
            install_nni_flows,
547 1
            chose_vlans_mock,
548 1
            log_mock,
549 1
            _,
550 1
            requests_mock,
551 1
        ) = args
552
553
        response = MagicMock()
554 1
        response.status_code = 201
555 1
        requests_mock.return_value = response
556 1
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 1
569 1
        # intra switch EVC
570 1
        evc = self.create_evc_intra_switch()
571
        assert evc.deploy_to_path(evc.primary_links) is True
572
        assert install_direct_uni_flows_mock.call_count == 1
573 1
        assert activate_mock.call_count == 2
574
        assert log_mock.info.call_count == 2
575
        log_mock.info.assert_called_with(f"{evc} was deployed.")
576
577
    @patch("requests.post")
578
    @patch("napps.kytos.mef_eline.models.evc.log")
579
    @patch("napps.kytos.mef_eline.models.evc.EVC.discover_new_paths")
580
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
581
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_nni_flows")
582
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_uni_flows")
583
    @patch("napps.kytos.mef_eline.models.evc.EVC.activate")
584
    @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 1
        """Test if all methods is ignored when the should_deploy is false."""
588
        # pylint: disable=too-many-locals
589 1
        (
590 1
            sync_mock,
591 1
            should_deploy_mock,
592 1
            activate_mock,
593
            install_uni_flows_mock,
594 1
            install_nni_flows,
595 1
            choose_vlans_mock,
596 1
            discover_new_paths_mock,
597 1
            log_mock,
598 1
            requests_mock,
599 1
        ) = args
600 1
601 1
        response = MagicMock()
602 1
        response.status_code = 201
603
        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
        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
        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
        assert sync_mock.call_count == 1
618
        assert deployed is False
619
620 1
        # 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 1
625 1
        # NoTagAvailable on dynamic path
626
        should_deploy_mock.return_value = False
627
        discover_new_paths_mock.return_value = [Path(['a', 'b'])]
628 1
        choose_vlans_mock.side_effect = KytosNoTagAvailableError("error")
629
        assert evc.deploy_to_path(evc.primary_links) is False
630
631
    @patch("napps.kytos.mef_eline.models.evc.log")
632
    @patch(
633
        "napps.kytos.mef_eline.models.evc.EVC.discover_new_paths",
634
        return_value=[],
635
    )
636
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
637
    @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
    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
        (
645
            sync_mock,
646 1
            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 1
654
        install_nni_flows.side_effect = FlowModException
655
        should_deploy_mock.return_value = True
656
        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
        primary_links = [
670
            get_link_mocked(
671 1
                endpoint_a_port=9, endpoint_b_port=10, metadata={"s_vlan": 5}
672 1
            ),
673 1
            get_link_mocked(
674
                endpoint_a_port=11, endpoint_b_port=12, metadata={"s_vlan": 6}
675 1
            ),
676
        ]
677 1
678
        attributes = {
679 1
            "controller": get_controller_mock(),
680 1
            "name": "custom_name",
681 1
            "uni_a": uni_a,
682 1
            "uni_z": uni_z,
683 1
            "primary_links": primary_links,
684 1
            "queue_id": 5,
685 1
        }
686 1
        # Setup path to deploy
687
        path = Path()
688 1
        path.append(primary_links[0])
689 1
        path.append(primary_links[1])
690 1
691 1
        evc = EVC(**attributes)
692 1
693 1
        deployed = evc.deploy_to_path(path)
694 1
695
        assert discover_new_paths.call_count == 0
696 1
        assert should_deploy_mock.call_count == 1
697
        assert install_nni_flows.call_count == 1
698
        assert choose_vlans_mock.call_count == 1
699
        assert log_mock.error.call_count == 1
700
        assert sync_mock.call_count == 0
701
        assert remove_current_flows.call_count == 2
702
        assert deployed is False
703
704
    @patch("napps.kytos.mef_eline.models.evc.notify_link_available_tags")
705
    @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
    @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
    def test_setup_failover_path(self, *args):
711
        """Test setup_failover_path method."""
712 1
        (
713 1
            sync_mock,
714
            remove_path_flows_mock,
715 1
            install_uni_flows_mock,
716 1
            install_nni_flows_mock,
717
            get_failover_path_candidates_mock,
718
            notify_mock,
719 1
        ) = args
720 1
721 1
        # case1: early return intra switch
722 1
        evc1 = self.create_evc_intra_switch()
723 1
724
        assert evc1.setup_failover_path() is False
725 1
        assert sync_mock.call_count == 0
726 1
727 1
        # 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 1
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
        path_mock.__iter__.return_value = ["link3"]
739 1
        get_failover_path_candidates_mock.return_value = [None, path_mock]
740 1
741 1
        assert evc2.setup_failover_path() is True
742
        remove_path_flows_mock.assert_called_with(["link1", "link2"])
743
        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
        assert sync_mock.call_count == 1
749 1
750 1
        # 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
        sync_mock.call_count = 0
754 1
755 1
        assert evc2.setup_failover_path() is False
756 1
        assert len(list(evc2.failover_path)) == 0
757
        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
        install_nni_flows_mock.side_effect = FlowModException("error")
763 1
        sync_mock.call_count = 0
764 1
765 1
        assert evc2.setup_failover_path() is False
766
        assert len(list(evc2.failover_path)) == 0
767 1
        assert sync_mock.call_count == 1
768
        remove_path_flows_mock.assert_called_with(path_mock)
769
770
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy_to_path")
771
    @patch("napps.kytos.mef_eline.models.evc.EVC.discover_new_paths")
772
    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 1
779
        switch = Mock(spec=Switch)
780 1
        uni_a.interface.switch = switch
781
        uni_z.interface.switch = switch
782 1
783 1
        attributes = {
784
            "controller": get_controller_mock(),
785 1
            "name": "custom_name",
786 1
            "uni_a": uni_a,
787 1
            "uni_z": uni_z,
788 1
            "enabled": True,
789 1
            "dynamic_backup_path": False,
790 1
        }
791 1
792 1
        evc = EVC(**attributes)
793 1
        discover_new_paths_mocked.return_value = []
794 1
        deploy_to_path_mocked.return_value = True
795
796
        deployed = evc.deploy_to_backup_path()
797 1
798
        deploy_to_path_mocked.assert_called_once_with()
799
        assert deployed is True
800
801
    @patch("requests.post")
802
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
803
    @patch("napps.kytos.mef_eline.models.evc.log")
804
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
805
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_nni_flows")
806
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_uni_flows")
807
    @patch("napps.kytos.mef_eline.models.evc.EVC.activate")
808
    @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 1
        """Test if not path is found a dynamic path is used."""
812
        # pylint: disable=too-many-locals
813 1
        (
814 1
            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 1
            log_mock,
821
            _,
822
            requests_mock,
823
        ) = args
824
825
        response = MagicMock()
826
        response.status_code = 201
827 1
        requests_mock.return_value = response
828
829
        should_deploy_mock.return_value = False
830
        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
        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 1
852 1
        dynamic_backup_path = Path(
853
            [
854 1
                get_link_mocked(
855
                    endpoint_a_port=9,
856 1
                    endpoint_b_port=10,
857 1
                    metadata={"s_vlan": 5},
858 1
                ),
859 1
                get_link_mocked(
860 1
                    endpoint_a_port=11,
861 1
                    endpoint_b_port=12,
862 1
                    metadata={"s_vlan": 6},
863 1
                ),
864
            ]
865 1
        )
866 1
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
        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
        assert chose_vlans_mock.call_count == 1
878
        log_mock.info.assert_called_with(f"{evc} was deployed.")
879 1
        assert deployed is True
880 1
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
    @patch("napps.kytos.mef_eline.models.evc.emit_event")
884
    def test_deploy(self, *args):
885 1
        """Test method deploy"""
886 1
        (emit_event_mock, deploy_primary_mock, deploy_backup_mock) = args
887 1
888
        # case 1: deploy to primary
889
        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 1
        # 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
        assert emit_event_mock.call_count == 2
899 1
900 1
        # 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 1
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 1
910 1
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.remove_current_flows")
911
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.sync")
912
    @patch("napps.kytos.mef_eline.models.evc.emit_event")
913 1
    def test_remove(self, *args):
914 1
        """Test method remove"""
915
        (emit_event_mock, sync_mock, remove_flows_mock) = args
916
        self.evc_deploy.remove()
917
        remove_flows_mock.assert_called()
918
        sync_mock.assert_called()
919
        emit_event_mock.assert_called()
920 1
        assert self.evc_deploy.is_enabled() is False
921
922
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
923
    @patch("napps.kytos.mef_eline.models.evc.notify_link_available_tags")
924
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
925
    @patch("napps.kytos.mef_eline.models.evc.log.error")
926
    def test_remove_current_flows(self, *args):
927 1
        """Test remove current flows."""
928 1
        # pylint: disable=too-many-locals
929 1
        (log_error_mock, send_flow_mods_mocked, notify_mock, _) = args
930
        uni_a = get_uni_mocked(
931 1
            interface_port=2,
932
            tag_value=82,
933
            switch_id="switch_uni_a",
934
            is_valid=True,
935
        )
936
        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
        switch_a = Switch("00:00:00:00:00:01")
944
        switch_b = Switch("00:00:00:00:00:02")
945
        switch_c = Switch("00:00:00:00:00:03")
946
947
        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 1
                    switch_a=switch_a,
957
                    switch_b=switch_b,
958 1
                    endpoint_a_port=9,
959 1
                    endpoint_b_port=10,
960 1
                    metadata={"s_vlan": 5},
961
                ),
962 1
                get_link_mocked(
963 1
                    switch_a=switch_b,
964 1
                    switch_b=switch_c,
965
                    endpoint_a_port=11,
966
                    endpoint_b_port=12,
967 1
                    metadata={"s_vlan": 6},
968 1
                ),
969 1
            ],
970
        }
971 1
972
        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 1
            {"cookie": evc.get_cookie(), "cookie_mask": 18446744073709551615}
982 1
        ]
983
        switch_1 = evc.primary_links[0].endpoint_a.switch
984
        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
        send_flow_mods_mocked.side_effect = FlowModException("error")
991
        evc.remove_current_flows()
992
        log_error_mock.assert_called()
993 1
994
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
995
    @patch("napps.kytos.mef_eline.models.evc.notify_link_available_tags")
996
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
997
    @patch("napps.kytos.mef_eline.models.evc.log.error")
998
    def test_remove_failover_flows_exclude_uni_switches(self, *args):
999
        """Test remove failover flows excluding UNI switches."""
1000 1
        # pylint: disable=too-many-locals
1001 1
        (log_error_mock, send_flow_mods_mocked,
1002 1
         notify_mock, mock_upsert) = args
1003
        uni_a = get_uni_mocked(
1004 1
            interface_port=2,
1005
            tag_value=82,
1006
            switch_id="00:00:00:00:00:00:00:01",
1007
            is_valid=True,
1008
        )
1009
        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
        switch_a = Switch("00:00:00:00:00:00:00:01")
1017
        switch_b = Switch("00:00:00:00:00:00:00:02")
1018
        switch_c = Switch("00:00:00:00:00:00:00:03")
1019
1020
        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 1
                    switch_a=switch_a,
1030 1
                    switch_b=switch_b,
1031 1
                    endpoint_a_port=9,
1032
                    endpoint_b_port=10,
1033 1
                    metadata={"s_vlan": 5},
1034 1
                ),
1035
                get_link_mocked(
1036
                    switch_a=switch_b,
1037
                    switch_b=switch_c,
1038 1
                    endpoint_a_port=11,
1039
                    endpoint_b_port=12,
1040 1
                    metadata={"s_vlan": 6},
1041
                ),
1042 1
            ],
1043 1
        }
1044 1
1045
        evc = EVC(**attributes)
1046 1
        evc.remove_failover_flows(exclude_uni_switches=True, sync=True)
1047 1
        notify_mock.assert_called()
1048 1
1049 1
        assert send_flow_mods_mocked.call_count == 1
1050
        flows = [
1051
            {"cookie": evc.get_cookie(),
1052 1
             "cookie_mask": int(0xffffffffffffffff)}
1053
        ]
1054 1
        send_flow_mods_mocked.assert_any_call(switch_b.id, flows, 'delete',
1055
                                              force=True)
1056
        assert mock_upsert.call_count == 1
1057
1058
        send_flow_mods_mocked.side_effect = FlowModException("error")
1059
        evc.remove_current_flows()
1060 1
        log_error_mock.assert_called()
1061
1062
    @patch("napps.kytos.mef_eline.controllers.ELineController.upsert_evc")
1063
    @patch("napps.kytos.mef_eline.models.evc.notify_link_available_tags")
1064
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
1065
    def test_remove_failover_flows_include_all(self, *args):
1066
        """Test remove failover flows including UNI switches."""
1067 1
        # pylint: disable=too-many-locals
1068 1
        (send_flow_mods_mocked,
1069 1
         notify_mock, mock_upsert) = args
1070
        uni_a = get_uni_mocked(
1071 1
            interface_port=2,
1072
            tag_value=82,
1073
            switch_id="00:00:00:00:00:00:00:01",
1074
            is_valid=True,
1075
        )
1076
        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
        switch_a = Switch("00:00:00:00:00:00:00:01")
1084
        switch_b = Switch("00:00:00:00:00:00:00:02")
1085
        switch_c = Switch("00:00:00:00:00:00:00:03")
1086
1087
        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 1
                    switch_a=switch_a,
1097 1
                    switch_b=switch_b,
1098 1
                    endpoint_a_port=9,
1099
                    endpoint_b_port=10,
1100 1
                    metadata={"s_vlan": 5},
1101 1
                ),
1102
                get_link_mocked(
1103
                    switch_a=switch_b,
1104
                    switch_b=switch_c,
1105 1
                    endpoint_a_port=11,
1106
                    endpoint_b_port=12,
1107 1
                    metadata={"s_vlan": 6},
1108
                ),
1109 1
            ],
1110
        }
1111 1
1112
        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 1
            {"cookie": evc.get_cookie(),
1119 1
             "cookie_mask": int(0xffffffffffffffff)}
1120 1
        ]
1121 1
        send_flow_mods_mocked.assert_any_call(switch_a.id, flows, 'delete',
1122
                                              force=True)
1123
        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
        assert mock_upsert.call_count == 1
1128
1129 1
    @staticmethod
1130 1
    def create_evc_intra_switch():
1131 1
        """Create intra-switch EVC."""
1132
        switch = Mock(spec=Switch)
1133
        switch.dpid = 2
1134
        switch.id = switch.dpid
1135
        interface_a = Interface("eth0", 1, switch)
1136
        interface_z = Interface("eth1", 3, switch)
1137
        uni_a = get_uni_mocked(
1138
            tag_value=82,
1139
            is_valid=True,
1140 1
        )
1141
        uni_z = get_uni_mocked(
1142
            tag_value=84,
1143 1
            is_valid=True,
1144 1
        )
1145
        uni_a.interface = interface_a
1146 1
        uni_z.interface = interface_z
1147 1
        attributes = {
1148
            "table_group": {"epl": 0, "evpl": 0},
1149 1
            "controller": get_controller_mock(),
1150 1
            "name": "custom_name",
1151 1
            "id": "1",
1152 1
            "uni_a": uni_a,
1153
            "uni_z": uni_z,
1154
            "enabled": True,
1155
        }
1156
        return EVC(**attributes)
1157
1158
    # pylint: disable=too-many-branches
1159
    @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 1
            (None, 0),
1177 1
            (None, None),
1178 1
        ]
1179 1
    )
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 1
        """Test _install_direct_uni_flows"""
1183 1
        evc = TestEVC.create_evc_intra_switch()
1184 1
        expected_dpid = evc.uni_a.interface.switch.id
1185 1
1186 1
        expected_flows = [
1187 1
            {
1188 1
                "match": {"in_port": 1},
1189 1
                "cookie": evc.get_cookie(),
1190
                "owner": "mef_eline",
1191 1
                "table_id": 0,
1192 1
                "table_group": "epl",
1193
                "actions": [
1194
                    {"action_type": "output", "port": 3},
1195
                ],
1196 1
                "priority": EPL_SB_PRIORITY
1197 1
            },
1198
            {
1199
                "match": {"in_port": 3},
1200
                "cookie": evc.get_cookie(),
1201 1
                "owner": "mef_eline",
1202 1
                "table_id": 0,
1203
                "table_group": "epl",
1204
                "actions": [
1205
                    {"action_type": "output", "port": 1},
1206 1
                ],
1207 1
                "priority": EPL_SB_PRIORITY
1208 1
            }
1209 1
        ]
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
        if uni_a is not None:
1217
            expected_flows[0]["match"]["dl_vlan"] = uni_a
1218
            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
            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
            expected_flows[1]["actions"].insert(
1230
                    0, {"action_type": "set_vlan",
1231
                        "vlan_id": uni_a}
1232 1
                )
1233
            if not uni_z:
1234 1
                expected_flows[1]["actions"].insert(
1235 1
                    0, {"action_type": "push_vlan",
1236
                        "tag_type": "c"}
1237 1
                )
1238
            if uni_z == 0:
1239 1
                new_action = {"action_type": "pop_vlan"}
1240 1
                expected_flows[0]["actions"].insert(0, new_action)
1241
        elif uni_a == "4096/4096":
1242 1
            if uni_z == 0:
1243
                new_action = {"action_type": "pop_vlan"}
1244 1
                expected_flows[0]["actions"].insert(0, new_action)
1245 1
        elif uni_a == 0:
1246
            if uni_z not in evc.special_cases:
1247 1
                expected_flows[0]["actions"].insert(
1248
                    0, {"action_type": "push_vlan",
1249 1
                        "tag_type": "c"}
1250 1
                )
1251 1
            if uni_z:
1252
                new_action = {"action_type": "pop_vlan"}
1253 1
                expected_flows[1]["actions"].insert(0, new_action)
1254
        elif uni_a is None:
1255 1
            if uni_z not in evc.special_cases:
1256 1
                expected_flows[0]["actions"].insert(
1257 1
                    0, {"action_type": "push_vlan",
1258
                        "tag_type": "c"}
1259 1
                )
1260 1
        send_flow_mods_mock.assert_called_with(
1261
            expected_dpid, expected_flows
1262 1
        )
1263 1
1264 1
    def test_is_affected_by_link(self):
1265 1
        """Test is_affected_by_link method"""
1266
        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 1
        """Test is_backup_path_affected_by_link method"""
1271 1
        self.evc_deploy.backup_path = Path(['a', 'b', 'c'])
1272
        assert self.evc_deploy.is_backup_path_affected_by_link('d') is False
1273
1274
    def test_is_primary_path_affected_by_link(self):
1275 1
        """Test is_primary_path_affected_by_link method"""
1276 1
        self.evc_deploy.primary_path = Path(['a', 'b', 'c'])
1277
        assert self.evc_deploy.is_primary_path_affected_by_link('c') is True
1278
1279
    def test_is_using_primary_path(self):
1280 1
        """Test is_using_primary_path method"""
1281
        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 1
        """Test is_using_backup_path method"""
1287 1
        self.evc_deploy.backup_path = Path(['a', 'b', 'c'])
1288
        self.evc_deploy.current_path = Path(['e', 'f', 'g'])
1289 1
        assert self.evc_deploy.is_using_backup_path() is False
1290 1
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
        path = Path([])
1302
        assert self.evc_deploy.get_path_status(path) == EntityStatus.DISABLED
1303
        path = Path([
1304
            get_link_mocked(status=EntityStatus.UP),
1305 1
            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 1
            get_link_mocked(status=EntityStatus.UP)
1311
        ])
1312
        assert self.evc_deploy.get_path_status(path) == EntityStatus.UP
1313
1314
    @patch("napps.kytos.mef_eline.models.evc.EVC._prepare_uni_flows")
1315
    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
        evc.failover_path = Path([])
1319
        assert len(evc.get_failover_flows()) == 0
1320
1321
        path = MagicMock()
1322
        evc.failover_path = path
1323
        evc.get_failover_flows()
1324
        prepare_uni_flows_mock.assert_called_with(path, skip_out=True)
1325
1326
    @patch("napps.kytos.mef_eline.models.evc.log")
1327
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
1328
    @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
        (
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 1
1339
        evc.remove_path_flows()
1340
        make_vlans_available_mock.assert_not_called()
1341
1342
        expected_flows_1 = [
1343
            {
1344 1
                'cookie': 12249790986447749121,
1345 1
                'cookie_mask': 18446744073709551615,
1346 1
                'match': {'in_port': 9, 'dl_vlan':  5}
1347
            },
1348 1
        ]
1349 1
        expected_flows_2 = [
1350
            {
1351 1
                'cookie': 12249790986447749121,
1352 1
                'cookie_mask': 18446744073709551615,
1353 1
                'match': {'in_port': 10, 'dl_vlan': 5}
1354 1
            },
1355 1
            {
1356
                'cookie': 12249790986447749121,
1357 1
                'cookie_mask': 18446744073709551615,
1358 1
                'match': {'in_port': 11, 'dl_vlan': 6}
1359
            },
1360
        ]
1361
        expected_flows_3 = [
1362
            {
1363
                'cookie': 12249790986447749121,
1364
                'cookie_mask': 18446744073709551615,
1365
                'match': {'in_port': 12, 'dl_vlan': 6}
1366 1
            },
1367 1
        ]
1368
1369
        evc.remove_path_flows(evc.primary_links)
1370
        send_flow_mods_mock.assert_has_calls([
1371
            call(1, expected_flows_1, 'delete', force=True),
1372 1
            call(2, expected_flows_2, 'delete', force=True),
1373
            call(3, expected_flows_3, 'delete', force=True),
1374 1
        ], any_order=True)
1375 1
1376 1
        send_flow_mods_mock.side_effect = FlowModException("err")
1377
        evc.remove_path_flows(evc.primary_links)
1378 1
        log_mock.error.assert_called()
1379 1
1380
    @patch("requests.put")
1381 1
    def test_run_bulk_sdntraces(self, put_mock):
1382 1
        """Test run_bulk_sdntraces method for bulk request."""
1383 1
        evc = self.create_evc_inter_switch()
1384 1
        response = MagicMock()
1385
        response.status_code = 200
1386 1
        response.json.return_value = {"result": "ok"}
1387 1
        put_mock.return_value = response
1388
1389
        expected_endpoint = f"{SDN_TRACE_CP_URL}/traces"
1390
        expected_payload = [
1391
                            {
1392
                                'trace': {
1393
                                    'switch': {'dpid': 1, 'in_port': 2},
1394
                                    'eth': {'dl_type': 0x8100, 'dl_vlan': 82}
1395 1
                                }
1396 1
                            }
1397 1
                        ]
1398
        result = EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1399
        put_mock.assert_called_with(
1400
                                    expected_endpoint,
1401
                                    json=expected_payload,
1402 1
                                    timeout=30
1403 1
                                )
1404
        assert result['result'] == "ok"
1405 1
1406 1
        response.status_code = 400
1407 1
        result = EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1408
        assert result == {"result": []}
1409
1410
    @patch("requests.put")
1411
    def test_run_bulk_sdntraces_special_vlan(self, put_mock):
1412 1
        """Test run_bulk_sdntraces method for bulk request."""
1413 1
        evc = self.create_evc_inter_switch()
1414
        response = MagicMock()
1415 1
        response.status_code = 200
1416 1
        put_mock.return_value = response
1417 1
1418
        expected_endpoint = f"{SDN_TRACE_CP_URL}/traces"
1419
        expected_payload = [
1420
                            {
1421
                                'trace': {
1422 1
                                    'switch': {'dpid': 1, 'in_port': 2}
1423 1
                                }
1424
                            }
1425 1
                        ]
1426 1
1427 1
        evc.uni_a.user_tag.value = 'untagged'
1428 1
        EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1429
        put_mock.assert_called_with(
1430
                                    expected_endpoint,
1431
                                    json=expected_payload,
1432
                                    timeout=30
1433 1
                                )
1434 1
        args = put_mock.call_args[1]['json'][0]
1435
        assert 'eth' not in args
1436 1
1437 1
        evc.uni_a.user_tag.value = 0
1438 1
        EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1439
        put_mock.assert_called_with(
1440
                                    expected_endpoint,
1441
                                    json=expected_payload,
1442
                                    timeout=30
1443 1
                                )
1444 1
        args = put_mock.call_args[1]['json'][0]['trace']
1445
        assert 'eth' not in args
1446 1
1447
        evc.uni_a.user_tag.value = '5/2'
1448
        EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1449
        put_mock.assert_called_with(
1450 1
                                    expected_endpoint,
1451 1
                                    json=expected_payload,
1452 1
                                    timeout=30
1453
                                )
1454
        args = put_mock.call_args[1]['json'][0]['trace']
1455
        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
        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 1
                                )
1465 1
        args = put_mock.call_args[1]['json'][0]['trace']
1466 1
        assert args['eth'] == {'dl_type': 33024, 'dl_vlan': 1}
1467
1468
        evc.uni_a.user_tag.value = '4096/4096'
1469
        EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1470
        put_mock.assert_called_with(
1471 1
                                    expected_endpoint,
1472 1
                                    json=expected_payload,
1473
                                    timeout=30
1474 1
                                )
1475
        args = put_mock.call_args[1]['json'][0]['trace']
1476
        assert args['eth'] == {'dl_type': 33024, 'dl_vlan': 1}
1477
1478 1
        expected_payload[0]['trace']['eth'] = {
1479 1
            'dl_type': 0x8100,
1480 1
            'dl_vlan': 10
1481
            }
1482
        evc.uni_a.user_tag.value = '10/10'
1483
        EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1484
        put_mock.assert_called_with(
1485
                                    expected_endpoint,
1486 1
                                    json=expected_payload,
1487 1
                                    timeout=30
1488 1
                                )
1489
        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 1
            'dl_type': 0x8100,
1494 1
            'dl_vlan': 1
1495
            }
1496 1
        evc.uni_a.user_tag.value = '5/3'
1497
        EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1498
        put_mock.assert_called_with(
1499
                                    expected_endpoint,
1500
                                    json=expected_payload,
1501
                                    timeout=30
1502
                                )
1503
        args = put_mock.call_args[1]['json'][0]['trace']
1504
        assert args['eth'] == {'dl_type': 33024, 'dl_vlan': 1}
1505
1506
        expected_payload[0]['trace']['eth'] = {
1507
            'dl_type': 0x8100,
1508
            'dl_vlan': 10
1509
            }
1510
        evc.uni_a.user_tag.value = 10
1511
        EVCDeploy.run_bulk_sdntraces([evc.uni_a])
1512
        put_mock.assert_called_with(
1513 1
                                    expected_endpoint,
1514
                                    json=expected_payload,
1515
                                    timeout=30
1516
                                )
1517
1518
    @patch("napps.kytos.mef_eline.models.evc.log")
1519
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
1520
    def test_check_list_traces(self, run_bulk_sdntraces_mock, _):
1521
        """Test check_list_traces method."""
1522
        evc = self.create_evc_inter_switch()
1523
1524
        for link in evc.primary_links:
1525
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1526
        evc.current_path = evc.primary_links
1527
1528
        trace_a = [
1529
            {
1530
                "dpid": 1,
1531 1
                "port": 2,
1532
                "time": "t1",
1533
                "type": "starting",
1534 1
                "vlan": 82
1535 1
            },
1536
            {
1537
                "dpid": 2,
1538 1
                "port": 10,
1539
                "time": "t2",
1540
                "type": "intermediary",
1541
                "vlan": 5
1542
            },
1543
            {"dpid": 3, "port": 12, "time": "t3", "type": "last", "vlan": 6},
1544 1
        ]
1545 1
        trace_z = [
1546
            {
1547
                "dpid": 3,
1548 1
                "port": 3,
1549
                "time": "t1",
1550
                "type": "starting",
1551
                "vlan": 83
1552
            },
1553
            {
1554 1
                "dpid": 2,
1555 1
                "port": 11,
1556
                "time": "t2",
1557
                "type": "intermediary",
1558 1
                "vlan": 6
1559 1
            },
1560 1
            {"dpid": 1, "port": 9, "time": "t3", "type": "last", "vlan": 5},
1561
        ]
1562
1563 1
        run_bulk_sdntraces_mock.return_value = {
1564 1
                                                "result": [trace_a, trace_z]
1565
                                            }
1566
        result = EVCDeploy.check_list_traces([evc])
1567 1
        assert result[evc.id] is True
1568 1
1569
        # case2: fail incomplete trace from uni_a
1570
        run_bulk_sdntraces_mock.return_value = {
1571 1
                                                "result": [
1572 1
                                                            trace_a[:2],
1573
                                                            trace_z
1574
                                                        ]
1575 1
        }
1576 1
        result = EVCDeploy.check_list_traces([evc])
1577 1
        assert result[evc.id] is False
1578 1
1579
        # case3: fail incomplete trace from uni_z
1580
        run_bulk_sdntraces_mock.return_value = {
1581 1
                                                "result": [
1582 1
                                                            trace_a,
1583 1
                                                            trace_z[:2]
1584 1
                                                        ]
1585 1
        }
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 1
                                                "result": [trace_a, trace_z]
1594
        }
1595
        result = EVCDeploy.check_list_traces([evc])
1596 1
        assert result[evc.id] is False
1597 1
1598 1
        # 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 1
                                                "result": [trace_a, trace_z]
1602 1
        }
1603 1
        result = EVCDeploy.check_list_traces([evc])
1604
        assert result[evc.id] is False
1605 1
1606 1
        # case6: success when no output in traces
1607 1
        trace_a[1]["vlan"] = 5
1608
        trace_z[1]["vlan"] = 6
1609 1
        result = EVCDeploy.check_list_traces([evc])
1610
        assert result[evc.id] is True
1611 1
1612 1
        # case7: fail when output is None in trace_a or trace_b
1613 1
        trace_a[-1]["out"] = None
1614
        result = EVCDeploy.check_list_traces([evc])
1615 1
        assert result[evc.id] is False
1616
        trace_a[-1].pop("out", None)
1617
        trace_z[-1]["out"] = None
1618
        result = EVCDeploy.check_list_traces([evc])
1619
        assert result[evc.id] is False
1620
1621
        # case8: success when the output is correct on both uni
1622
        trace_a[-1]["out"] = {"port": 3, "vlan": 83}
1623
        trace_z[-1]["out"] = {"port": 2, "vlan": 82}
1624
        result = EVCDeploy.check_list_traces([evc])
1625
        assert result[evc.id] is True
1626
1627
        # case9: fail if any output is incorrect
1628
        trace_a[-1]["out"] = {"port": 3, "vlan": 99}
1629
        trace_z[-1]["out"] = {"port": 2, "vlan": 82}
1630
        result = EVCDeploy.check_list_traces([evc])
1631
        assert result[evc.id] is False
1632
        trace_a[-1]["out"] = {"port": 3, "vlan": 83}
1633
        trace_z[-1]["out"] = {"port": 2, "vlan": 99}
1634
        result = EVCDeploy.check_list_traces([evc])
1635
        assert result[evc.id] is False
1636
1637 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
    @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
        evc = self.create_evc_inter_switch("any", "any")
1642
1643
        for link in evc.primary_links:
1644
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1645
        evc.current_path = evc.primary_links
1646
1647
        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 1
                "port": 12,
1665
                'out': {'port': 3, 'vlan': 1},
1666
                "time": "t3",
1667 1
                "type": "last",
1668 1
                "vlan": 6
1669
            },
1670 1
        ]
1671 1
        trace_z = [
1672 1
            {
1673
                "dpid": 3,
1674 1
                "port": 3,
1675
                "time": "t1",
1676 1
                "type": "starting",
1677 1
                "vlan": 1
1678 1
            },
1679
            {
1680 1
                "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
        run_bulk_sdntraces_mock.return_value = {
1697
                                                "result": [trace_a, trace_z]
1698
                                            }
1699
        result = EVCDeploy.check_list_traces([evc])
1700
        assert result[evc.id] is True
1701
1702 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
    @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
        evc = self.create_evc_inter_switch("untagged", "untagged")
1707
1708
        for link in evc.primary_links:
1709
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1710
        evc.current_path = evc.primary_links
1711
1712
        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 1
                "port": 12,
1730
                'out': {'port': 3},
1731
                "time": "t3", "type":
1732 1
                "last",
1733 1
                "vlan": 6
1734
                },
1735 1
        ]
1736 1
        trace_z = [
1737 1
            {
1738
                "dpid": 3,
1739 1
                "port": 3,
1740
                "time": "t1",
1741 1
                "type": "starting",
1742 1
                "vlan": 0
1743 1
            },
1744
            {
1745 1
                "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
        bulk_sdntraces_mock.return_value = {
1762 1
                                                "result": [trace_a, trace_z]
1763
                                            }
1764
        result = EVCDeploy.check_list_traces([evc])
1765
        assert result[evc.id] is True
1766
1767
    @patch("napps.kytos.mef_eline.models.evc.log")
1768
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.run_bulk_sdntraces")
1769
    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
        evc = self.create_evc_inter_switch()
1772
1773
        for link in evc.primary_links:
1774
            link.metadata['s_vlan'] = MagicMock(value=link.metadata['s_vlan'])
1775
        evc.current_path = evc.primary_links
1776
1777
        trace_a = [
1778
            {
1779
                "dpid": 1,
1780
                "port": 2,
1781
                "time": "t1",
1782
                "type": "starting",
1783
                "vlan": 82
1784
            },
1785
            {
1786 1
                "dpid": 2,
1787
                "port": 10,
1788
                "time": "t2",
1789 1
                "type": "intermediary",
1790
                "vlan": 5
1791 1
            },
1792
            {"dpid": 3, "port": 12, "time": "t3", "type": "last", "vlan": 6},
1793 1
        ]
1794
        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 1
                "port": 9,
1812
                "time": "t3",
1813
                "type": "incomplete",
1814 1
                "vlan": 5
1815
            },
1816 1
        ]
1817
1818 1
        run_bulk_sdntraces_mock.return_value = {
1819
                                                "result": [trace_a, trace_z]
1820
                                            }
1821
        result = EVCDeploy.check_list_traces([evc])
1822 1
        # type incomplete
1823
        assert result[evc.id] is False
1824 1
1825 1
        trace_z = [
1826
            {
1827 1
                "dpid": 3,
1828
                "port": 3,
1829 1
                "time": "t1",
1830 1
                "type": "starting",
1831 1
                "vlan": 83
1832 1
            },
1833 1
            {
1834 1
                "dpid": 2,
1835
                "port": 11,
1836
                "time": "t2",
1837 1
                "type": "intermediary",
1838
                "vlan": 6
1839 1
            },
1840 1
            {"dpid": 1, "port": 9, "time": "t3", "type": "loop", "vlan": 5},
1841 1
        ]
1842 1
1843 1
        run_bulk_sdntraces_mock.return_value = {
1844
                                                "result": [trace_a, trace_z]
1845 1
                                            }
1846
        result = EVCDeploy.check_list_traces([evc])
1847 1
        # type loop
1848 1
        assert result[evc.id] is False
1849 1
1850
    @patch(
1851 1
        "napps.kytos.mef_eline.models.path.DynamicPathManager"
1852 1
        ".get_disjoint_paths"
1853 1
    )
1854
    def test_get_failover_path_vandidates(self, get_disjoint_paths_mock):
1855 1
        """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 1
        """Test is_failover_path_affected_by_link method"""
1861 1
        link1 = get_link_mocked(endpoint_a_port=1, endpoint_b_port=2)
1862
        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
        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 1
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
        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 1
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 1
1887
        uni = get_uni_mocked(tag_value="untagged")
1888 1
        value = EVC._get_value_from_uni_tag(uni)
1889
        assert value == 0
1890 1
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 1
1895 1
    def test_get_priority(self):
1896 1
        """Test get_priority_from_vlan"""
1897
        evpl_value = EVC.get_priority(100)
1898
        assert evpl_value == EVPL_SB_PRIORITY
1899
1900
        untagged_value = EVC.get_priority(0)
1901
        assert untagged_value == UNTAGGED_SB_PRIORITY
1902
1903
        any_value = EVC.get_priority("4096/4096")
1904
        assert any_value == ANY_SB_PRIORITY
1905
1906
        epl_value = EVC.get_priority(None)
1907
        assert epl_value == EPL_SB_PRIORITY
1908
1909
    def test_set_flow_table_group_id(self):
1910
        """Test set_flow_table_group_id"""
1911
        self.evc_deploy.table_group = {"epl": 3, "evpl": 4}
1912
        flow_mod = {}
1913
        self.evc_deploy.set_flow_table_group_id(flow_mod, 100)
1914
        assert flow_mod["table_group"] == "evpl"
1915
        assert flow_mod["table_id"] == 4
1916
        self.evc_deploy.set_flow_table_group_id(flow_mod, None)
1917
        assert flow_mod["table_group"] == "epl"
1918
        assert flow_mod["table_id"] == 3
1919
1920
    def test_get_endpoint_by_id(self):
1921
        """Test get_endpoint_by_id"""
1922
        link = MagicMock()
1923
        link.endpoint_a.switch.id = "01"
1924
        link.endpoint_b.switch.id = "02"
1925
        result = self.evc_deploy.get_endpoint_by_id(link, "01", operator.eq)
1926
        assert result == link.endpoint_a
1927
        result = self.evc_deploy.get_endpoint_by_id(link, "01", operator.ne)
1928
        assert result == link.endpoint_b
1929