Passed
Pull Request — master (#258)
by
unknown
03:26
created

build.tests.unit.models.test_evc_deploy   F

Complexity

Total Complexity 62

Size/Duplication

Total Lines 1687
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 1203
dl 0
loc 1687
rs 2.24
c 0
b 0
f 0
wmc 62

46 Methods

Rating   Name   Duplication   Size   Complexity  
A TestEVC.test_prepare_pop_flow() 0 28 1
A TestEVC.test_should_deploy_case1() 0 15 1
A TestEVC.test_send_flow_mods_case1() 0 18 1
A TestEVC.test_send_flow_mods_case2() 0 17 1
A TestEVC.test_prepare_flow_mod() 0 26 1
A TestEVC.test_should_deploy_case4() 0 15 1
A TestEVC.setUp() 0 8 1
A TestEVC.test_primary_links_zipped() 0 2 1
A TestEVC.test_should_deploy_case2() 0 15 1
A TestEVC.test_send_flow_mods_error() 0 16 2
A TestEVC.test_should_deploy_case3() 0 15 1
B TestEVC.test_prepare_push_flow() 0 54 8
A TestEVC.create_evc_inter_switch() 0 42 1
A TestEVC.test_is_using_backup_path() 0 5 1
A TestEVC.test_remove() 0 11 1
B TestEVC.test_deploy_successfully() 0 47 1
A TestEVC.create_evc_intra_switch() 0 27 1
B TestEVC.test_remove_failover_flows_exclude_uni_switches() 0 67 1
A TestEVC.test_get_failover_flows() 0 11 1
B TestEVC.test_deploy_fail() 0 53 1
A TestEVC.test_is_using_primary_path() 0 5 1
B TestEVC.test_remove_current_flows() 0 71 1
A TestEVC.test_deploy_to_backup_path1() 0 30 1
B TestEVC.test_check_list_traces() 0 93 2
A TestEVC.test_remove_path_flows() 0 53 1
A TestEVC.test_is_eligible_for_failover_path() 0 7 1
A TestEVC.test_install_nni_flows() 0 41 1
B TestEVC.test_remove_failover_flows_include_all() 0 66 1
A TestEVC.test_is_failover_path_affected_by_link() 0 11 1
A TestEVC.test_is_primary_path_affected_by_link() 0 4 1
B TestEVC.test_deploy_error() 0 72 1
B TestEVC.test_deploy_direct_uni_flows_untagged_any() 0 83 1
A TestEVC.test_get_value_from_uni_tag() 0 17 1
A TestEVC.test_is_using_dynamic_path() 0 7 1
B TestEVC.test_prepare_push_flow_any_untagged() 0 49 8
A TestEVC.test_is_backup_path_affected_by_link() 0 4 1
A TestEVC.test_deploy() 0 28 1
B TestEVC.test_deploy_without_path_case1() 0 79 1
A TestEVC.test_get_path_status() 0 22 1
B TestEVC.test_setup_failover_path() 0 65 1
B TestEVC.test_deploy_direct_uni_flows() 0 113 1
A TestEVC.test_run_sdntrace() 0 24 1
A TestEVC.test_get_failover_path_vandidates() 0 8 1
B TestEVC.test_install_uni_flows() 0 112 1
A TestEVC.test_run_bulk_sdntraces() 0 29 1
A TestEVC.test_is_affected_by_link() 0 4 1

How to fix   Complexity   

Complexity

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

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

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