Test Failed
Pull Request — master (#396)
by
unknown
04:19
created

TestEVC.test_remove_path_flows()   A

Complexity

Conditions 1

Size

Total Lines 53
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 36
nop 2
dl 0
loc 53
ccs 16
cts 16
cp 1
crap 1
rs 9.016
c 0
b 0
f 0

How to fix   Long Method   

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:

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