Passed
Pull Request — master (#390)
by Vinicius
04:52
created

TestEVC.test_prepare_push_flow()   D

Complexity

Conditions 11

Size

Total Lines 80
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 11

Importance

Changes 0
Metric Value
cc 11
eloc 70
nop 3
dl 0
loc 80
ccs 31
cts 31
cp 1
crap 11
rs 4.7618
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like build.tests.unit.models.test_evc_deploy.TestEVC.test_prepare_push_flow() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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