Passed
Pull Request — master (#473)
by Vinicius
05:03
created

TestEVC.test_remove_path_flows()   B

Complexity

Conditions 1

Size

Total Lines 58
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 1

Importance

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