Passed
Pull Request — master (#160)
by Antonio
03:45
created

TestEVC.test_should_deploy_case2()   A

Complexity

Conditions 1

Size

Total Lines 15
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 12
nop 2
dl 0
loc 15
rs 9.8
c 0
b 0
f 0
1
"""Method to thest EVCDeploy class."""
2
import sys
3
from unittest import TestCase
4
from unittest.mock import MagicMock, Mock, patch
5
6
from kytos.core.interface import Interface
7
from kytos.core.switch import Switch
8
9
# pylint: disable=wrong-import-position
10
sys.path.insert(0, "/var/lib/kytos/napps/..")
11
# pylint: enable=wrong-import-position
12
13
from napps.kytos.mef_eline.models import EVC, EVCDeploy, Path  # NOQA
14
from napps.kytos.mef_eline.settings import MANAGER_URL  # NOQA
15
from napps.kytos.mef_eline.exceptions import FlowModException  # NOQA
16
from napps.kytos.mef_eline.tests.helpers import (
17
    get_link_mocked,
18
    get_uni_mocked,
19
    get_controller_mock,
20
)  # NOQA
21
22
23
class TestEVC(TestCase):  # pylint: disable=too-many-public-methods
24
    """Tests to verify EVC class."""
25
26
    def setUp(self):
27
        attributes = {
28
            "controller": get_controller_mock(),
29
            "name": "circuit_for_tests",
30
            "uni_a": get_uni_mocked(is_valid=True),
31
            "uni_z": get_uni_mocked(is_valid=True),
32
        }
33
        self.evc_deploy = EVCDeploy(**attributes)
34
35
    def test_primary_links_zipped(self):
36
        """Test primary links zipped method."""
37
38
    @staticmethod
39
    @patch("napps.kytos.mef_eline.models.evc.log")
40
    def test_should_deploy_case1(log_mock):
41
        """Test should deploy method without primary links."""
42
        log_mock.debug.return_value = True
43
        attributes = {
44
            "controller": get_controller_mock(),
45
            "name": "custom_name",
46
            "uni_a": get_uni_mocked(is_valid=True),
47
            "uni_z": get_uni_mocked(is_valid=True),
48
        }
49
50
        evc = EVC(**attributes)
51
        evc.should_deploy()
52
        log_mock.debug.assert_called_with("Path is empty.")
53
54
    @patch("napps.kytos.mef_eline.models.evc.log")
55
    def test_should_deploy_case2(self, log_mock):
56
        """Test should deploy method with disable circuit."""
57
        log_mock.debug.return_value = True
58
        attributes = {
59
            "controller": get_controller_mock(),
60
            "name": "custom_name",
61
            "uni_a": get_uni_mocked(is_valid=True),
62
            "uni_z": get_uni_mocked(is_valid=True),
63
            "primary_links": [get_link_mocked(), get_link_mocked()],
64
        }
65
        evc = EVC(**attributes)
66
67
        self.assertFalse(evc.should_deploy(attributes["primary_links"]))
68
        log_mock.debug.assert_called_with(f"{evc} is disabled.")
69
70
    @patch("napps.kytos.mef_eline.models.evc.log")
71
    def test_should_deploy_case3(self, log_mock):
72
        """Test should deploy method with enabled and not active circuit."""
73
        log_mock.debug.return_value = True
74
        attributes = {
75
            "controller": get_controller_mock(),
76
            "name": "custom_name",
77
            "uni_a": get_uni_mocked(is_valid=True),
78
            "uni_z": get_uni_mocked(is_valid=True),
79
            "primary_links": [get_link_mocked(), get_link_mocked()],
80
            "enabled": True,
81
        }
82
        evc = EVC(**attributes)
83
        self.assertTrue(evc.should_deploy(attributes["primary_links"]))
84
        log_mock.debug.assert_called_with(f"{evc} will be deployed.")
85
86
    @patch("napps.kytos.mef_eline.models.evc.log")
87
    def test_should_deploy_case4(self, log_mock):
88
        """Test should deploy method with enabled and active circuit."""
89
        log_mock.debug.return_value = True
90
        attributes = {
91
            "controller": get_controller_mock(),
92
            "name": "custom_name",
93
            "uni_a": get_uni_mocked(is_valid=True),
94
            "uni_z": get_uni_mocked(is_valid=True),
95
            "primary_links": [get_link_mocked(), get_link_mocked()],
96
            "enabled": True,
97
            "active": True,
98
        }
99
        evc = EVC(**attributes)
100
        self.assertFalse(evc.should_deploy(attributes["primary_links"]))
101
102
    @patch("napps.kytos.mef_eline.models.evc.requests")
103
    def test_send_flow_mods_case1(self, requests_mock):
104
        """Test if you are sending flow_mods."""
105
        flow_mods = {"id": 20}
106
        switch = Mock(spec=Switch, id=1)
107
108
        response = MagicMock()
109
        response.status_code = 201
110
        requests_mock.post.return_value = response
111
112
        # pylint: disable=protected-access
113
        EVC._send_flow_mods(switch, flow_mods)
114
115
        expected_endpoint = f"{MANAGER_URL}/flows/{switch.id}"
116
        expected_data = {"flows": flow_mods, "force": False}
117
        self.assertEqual(requests_mock.post.call_count, 1)
118
        requests_mock.post.assert_called_once_with(
119
            expected_endpoint, json=expected_data
120
        )
121
122
    @patch("napps.kytos.mef_eline.models.evc.requests")
123
    def test_send_flow_mods_case2(self, requests_mock):
124
        """Test if you are sending flow_mods."""
125
        flow_mods = {"id": 20}
126
        switch = Mock(spec=Switch, id=1)
127
        response = MagicMock()
128
        response.status_code = 201
129
        requests_mock.post.return_value = response
130
131
        # pylint: disable=protected-access
132
        EVC._send_flow_mods(switch, flow_mods, command='delete', force=True)
133
134
        expected_endpoint = f"{MANAGER_URL}/delete/{switch.id}"
135
        expected_data = {"flows": flow_mods, "force": True}
136
        self.assertEqual(requests_mock.post.call_count, 1)
137
        requests_mock.post.assert_called_once_with(
138
            expected_endpoint, json=expected_data
139
        )
140
141
    @patch("napps.kytos.mef_eline.models.evc.requests")
142
    def test_send_flow_mods_error(self, requests_mock):
143
        """Test flow_manager call fails."""
144
        flow_mods = {"id": 20}
145
        switch = Mock(spec=Switch, id=1)
146
        response = MagicMock()
147
        response.status_code = 415
148
        requests_mock.post.return_value = response
149
150
        # pylint: disable=protected-access
151
        with self.assertRaises(FlowModException):
152
            EVC._send_flow_mods(
153
                switch,
154
                flow_mods,
155
                command='delete',
156
                force=True
157
            )
158
159
    def test_prepare_flow_mod(self):
160
        """Test prepare flow_mod method."""
161
        interface_a = Interface("eth0", 1, Mock(spec=Switch))
162
        interface_z = Interface("eth1", 3, Mock(spec=Switch))
163
        attributes = {
164
            "controller": get_controller_mock(),
165
            "name": "custom_name",
166
            "uni_a": get_uni_mocked(is_valid=True),
167
            "uni_z": get_uni_mocked(is_valid=True),
168
            "primary_links": [get_link_mocked(), get_link_mocked()],
169
            "enabled": True,
170
            "active": True,
171
        }
172
        evc = EVC(**attributes)
173
174
        # pylint: disable=protected-access
175
        flow_mod = evc._prepare_flow_mod(interface_a, interface_z)
176
        expected_flow_mod = {
177
            "match": {"in_port": interface_a.port_number},
178
            "cookie": evc.get_cookie(),
179
            "actions": [
180
                {"action_type": "output", "port": interface_z.port_number}
181
            ],
182
        }
183
        self.assertEqual(expected_flow_mod, flow_mod)
184
185
    def test_prepare_pop_flow(self):
186
        """Test prepare pop flow  method."""
187
        attributes = {
188
            "controller": get_controller_mock(),
189
            "name": "custom_name",
190
            "uni_a": get_uni_mocked(interface_port=1, is_valid=True),
191
            "uni_z": get_uni_mocked(interface_port=2, is_valid=True),
192
        }
193
        evc = EVC(**attributes)
194
        interface_a = evc.uni_a.interface
195
        interface_z = evc.uni_z.interface
196
        in_vlan = 10
197
198
        # pylint: disable=protected-access
199
        flow_mod = evc._prepare_pop_flow(
200
            interface_a, interface_z, in_vlan
201
        )
202
203
        expected_flow_mod = {
204
            "match": {"in_port": interface_a.port_number, "dl_vlan": in_vlan},
205
            "cookie": evc.get_cookie(),
206
            "actions": [
207
                {"action_type": "pop_vlan"},
208
                {"action_type": "output", "port": interface_z.port_number},
209
            ],
210
        }
211
        self.assertEqual(expected_flow_mod, flow_mod)
212
213
    def test_prepare_push_flow(self):
214
        """Test prepare push flow method."""
215
        attributes = {
216
            "controller": get_controller_mock(),
217
            "name": "custom_name",
218
            "uni_a": get_uni_mocked(interface_port=1, is_valid=True),
219
            "uni_z": get_uni_mocked(interface_port=2, is_valid=True),
220
        }
221
        evc = EVC(**attributes)
222
        interface_a = evc.uni_a.interface
223
        interface_z = evc.uni_z.interface
224
        out_vlan_a = 20
225
226
        for in_vlan_a in (10, None):
227
            for in_vlan_z in (3, None):
228
                with self.subTest(in_vlan_a=in_vlan_a, in_vlan_z=in_vlan_z):
229
                    # pylint: disable=protected-access
230
                    flow_mod = evc._prepare_push_flow(interface_a, interface_z,
231
                                                      in_vlan_a, out_vlan_a,
232
                                                      in_vlan_z)
233
234
                    expected_flow_mod = {
235
                        'match': {'in_port': interface_a.port_number},
236
                        'cookie': evc.get_cookie(),
237
                        'actions': [
238
                            {'action_type': 'push_vlan', 'tag_type': 's'},
239
                            {'action_type': 'set_vlan', 'vlan_id': out_vlan_a},
240
                            {
241
                                'action_type': 'output',
242
                                'port': interface_z.port_number
243
                            }
244
                        ]
245
                    }
246
                    if in_vlan_a and in_vlan_z:
247
                        expected_flow_mod['match']['dl_vlan'] = in_vlan_a
248
                        expected_flow_mod['actions'].insert(0, {
249
                            'action_type': 'set_vlan', 'vlan_id': in_vlan_z
250
                        })
251
                    elif in_vlan_a:
252
                        expected_flow_mod['match']['dl_vlan'] = in_vlan_a
253
                        expected_flow_mod['actions'].insert(0, {
254
                            'action_type': 'pop_vlan'
255
                        })
256
                    elif in_vlan_z:
257
                        expected_flow_mod['actions'].insert(0, {
258
                            'action_type': 'set_vlan', 'vlan_id': in_vlan_z
259
                        })
260
                        expected_flow_mod['actions'].insert(0, {
261
                            'action_type': 'push_vlan', 'tag_type': 'c'
262
                        })
263
                    self.assertEqual(expected_flow_mod, flow_mod)
264
265
    @staticmethod
266
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
267
    def test_install_uni_flows(send_flow_mods_mock):
268
        """Test install uni flows method.
269
270
        This test will verify the flows send to the send_flow_mods method.
271
        """
272
        uni_a = get_uni_mocked(
273
            interface_port=2,
274
            tag_value=82,
275
            switch_id="switch_uni_a",
276
            is_valid=True,
277
        )
278
        uni_z = get_uni_mocked(
279
            interface_port=3,
280
            tag_value=83,
281
            switch_id="switch_uni_z",
282
            is_valid=True,
283
        )
284
285
        attributes = {
286
            "controller": get_controller_mock(),
287
            "name": "custom_name",
288
            "uni_a": uni_a,
289
            "uni_z": uni_z,
290
            "primary_links": [
291
                get_link_mocked(
292
                    endpoint_a_port=9,
293
                    endpoint_b_port=10,
294
                    metadata={"s_vlan": 5},
295
                ),
296
                get_link_mocked(
297
                    endpoint_a_port=11,
298
                    endpoint_b_port=12,
299
                    metadata={"s_vlan": 6},
300
                ),
301
            ],
302
        }
303
        evc = EVC(**attributes)
304
305
        # pylint: disable=protected-access
306
        evc._install_uni_flows(attributes["primary_links"])
307
308
        expected_flow_mod_a = [
309
            {
310
                "match": {
311
                    "in_port": uni_a.interface.port_number,
312
                    "dl_vlan": uni_a.user_tag.value,
313
                },
314
                "cookie": evc.get_cookie(),
315
                "actions": [
316
                    {
317
                        "action_type": "set_vlan",
318
                        "vlan_id": uni_z.user_tag.value
319
                    },
320
                    {"action_type": "push_vlan", "tag_type": "s"},
321
                    {
322
                        "action_type": "set_vlan",
323
                        "vlan_id": evc.primary_links[0]
324
                        .get_metadata("s_vlan")
325
                        .value,
326
                    },
327
                    {
328
                        "action_type": "output",
329
                        "port": evc.primary_links[0].endpoint_a.port_number,
330
                    },
331
                ],
332
            },
333
            {
334
                "match": {
335
                    "in_port": evc.primary_links[0].endpoint_a.port_number,
336
                    "dl_vlan": evc.primary_links[0]
337
                    .get_metadata("s_vlan")
338
                    .value,
339
                },
340
                "cookie": evc.get_cookie(),
341
                "actions": [
342
                    {"action_type": "pop_vlan"},
343
                    {
344
                        "action_type": "output",
345
                        "port": uni_a.interface.port_number,
346
                    },
347
                ],
348
            },
349
        ]
350
351
        send_flow_mods_mock.assert_any_call(
352
            uni_a.interface.switch, expected_flow_mod_a
353
        )
354
355
        expected_flow_mod_z = [
356
            {
357
                "match": {
358
                    "in_port": uni_z.interface.port_number,
359
                    "dl_vlan": uni_z.user_tag.value,
360
                },
361
                "cookie": evc.get_cookie(),
362
                "actions": [
363
                    {
364
                        "action_type": "set_vlan",
365
                        "vlan_id": uni_a.user_tag.value
366
                    },
367
                    {"action_type": "push_vlan", "tag_type": "s"},
368
                    {
369
                        "action_type": "set_vlan",
370
                        "vlan_id": evc.primary_links[-1]
371
                        .get_metadata("s_vlan")
372
                        .value,
373
                    },
374
                    {
375
                        "action_type": "output",
376
                        "port": evc.primary_links[-1].endpoint_b.port_number,
377
                    },
378
                ],
379
            },
380
            {
381
                "match": {
382
                    "in_port": evc.primary_links[-1].endpoint_b.port_number,
383
                    "dl_vlan": evc.primary_links[-1]
384
                    .get_metadata("s_vlan")
385
                    .value,
386
                },
387
                "cookie": evc.get_cookie(),
388
                "actions": [
389
                    {"action_type": "pop_vlan"},
390
                    {
391
                        "action_type": "output",
392
                        "port": uni_z.interface.port_number,
393
                    },
394
                ],
395
            },
396
        ]
397
398
        send_flow_mods_mock.assert_any_call(
399
            uni_z.interface.switch, expected_flow_mod_z
400
        )
401
402
    @staticmethod
403
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
404
    def test_install_nni_flows(send_flow_mods_mock):
405
        """Test install nni flows method.
406
407
        This test will verify the flows send to the send_flow_mods method.
408
        """
409
        uni_a = get_uni_mocked(
410
            interface_port=2,
411
            tag_value=82,
412
            switch_id="switch_uni_a",
413
            is_valid=True,
414
        )
415
        uni_z = get_uni_mocked(
416
            interface_port=3,
417
            tag_value=83,
418
            switch_id="switch_uni_z",
419
            is_valid=True,
420
        )
421
422
        attributes = {
423
            "controller": get_controller_mock(),
424
            "name": "custom_name",
425
            "uni_a": uni_a,
426
            "uni_z": uni_z,
427
            "primary_links": [
428
                get_link_mocked(
429
                    endpoint_a_port=9,
430
                    endpoint_b_port=10,
431
                    metadata={"s_vlan": 5},
432
                ),
433
                get_link_mocked(
434
                    endpoint_a_port=11,
435
                    endpoint_b_port=12,
436
                    metadata={"s_vlan": 6},
437
                ),
438
            ],
439
        }
440
        evc = EVC(**attributes)
441
442
        # pylint: disable=protected-access
443
        evc._install_nni_flows(attributes["primary_links"])
444
445
        in_vlan = evc.primary_links[0].get_metadata("s_vlan").value
446
        out_vlan = evc.primary_links[-1].get_metadata("s_vlan").value
447
448
        in_port = evc.primary_links[0].endpoint_b.port_number
449
        out_port = evc.primary_links[-1].endpoint_a.port_number
450
451
        expected_flow_mods = [
452
            {
453
                "match": {"in_port": in_port, "dl_vlan": in_vlan},
454
                "cookie": evc.get_cookie(),
455
                "actions": [
456
                    {"action_type": "set_vlan", "vlan_id": out_vlan},
457
                    {"action_type": "output", "port": out_port},
458
                ],
459
            },
460
            {
461
                "match": {"in_port": out_port, "dl_vlan": out_vlan},
462
                "cookie": evc.get_cookie(),
463
                "actions": [
464
                    {"action_type": "set_vlan", "vlan_id": in_vlan},
465
                    {"action_type": "output", "port": in_port},
466
                ],
467
            },
468
        ]
469
470
        switch = evc.primary_links[0].endpoint_b.switch
471
        send_flow_mods_mock.assert_called_once_with(switch, expected_flow_mods)
472
473
    @patch("requests.post")
474
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
475
    @patch("napps.kytos.mef_eline.models.evc.log")
476
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
477
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_nni_flows")
478
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_uni_flows")
479
    @patch("napps.kytos.mef_eline.models.evc.EVC.activate")
480
    @patch("napps.kytos.mef_eline.models.evc.EVC.should_deploy")
481
    def test_deploy_successfully(self, *args):
482
        """Test if all methods to deploy are called."""
483
        # pylint: disable=too-many-locals
484
        (
485
            should_deploy_mock,
486
            activate_mock,
487
            install_uni_flows_mock,
488
            install_nni_flows,
489
            chose_vlans_mock,
490
            log_mock,
491
            _,
492
            requests_mock,
493
        ) = args
494
495
        response = MagicMock()
496
        response.status_code = 201
497
        requests_mock.return_value = response
498
499
        should_deploy_mock.return_value = True
500
        uni_a = get_uni_mocked(
501
            interface_port=2,
502
            tag_value=82,
503
            switch_id="switch_uni_a",
504
            is_valid=True,
505
        )
506
        uni_z = get_uni_mocked(
507
            interface_port=3,
508
            tag_value=83,
509
            switch_id="switch_uni_z",
510
            is_valid=True,
511
        )
512
        primary_links = [
513
            get_link_mocked(
514
                endpoint_a_port=9, endpoint_b_port=10, metadata={"s_vlan": 5}
515
            ),
516
            get_link_mocked(
517
                endpoint_a_port=11, endpoint_b_port=12, metadata={"s_vlan": 6}
518
            ),
519
        ]
520
521
        attributes = {
522
            "controller": get_controller_mock(),
523
            "name": "custom_name",
524
            "uni_a": uni_a,
525
            "uni_z": uni_z,
526
            "primary_links": primary_links,
527
            "queue_id": 5,
528
        }
529
530
        # Setup path to deploy
531
        path = Path()
532
        path.append(primary_links[0])
533
        path.append(primary_links[1])
534
535
        evc = EVC(**attributes)
536
537
        deployed = evc.deploy_to_path(path)
538
539
        self.assertEqual(should_deploy_mock.call_count, 1)
540
        self.assertEqual(activate_mock.call_count, 1)
541
        self.assertEqual(install_uni_flows_mock.call_count, 1)
542
        self.assertEqual(install_nni_flows.call_count, 1)
543
        self.assertEqual(chose_vlans_mock.call_count, 1)
544
        log_mock.info.assert_called_with(f"{evc} was deployed.")
545
        self.assertTrue(deployed)
546
547
    @patch("requests.post")
548
    @patch("napps.kytos.mef_eline.models.evc.log")
549
    @patch(
550
        "napps.kytos.mef_eline.models.evc.EVC.discover_new_paths",
551
        return_value=[],
552
    )
553
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
554
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_nni_flows")
555
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_uni_flows")
556
    @patch("napps.kytos.mef_eline.models.evc.EVC.activate")
557
    @patch(
558
        "napps.kytos.mef_eline.models.evc.EVC.should_deploy",
559
        return_value=False,
560
    )
561
    @patch("napps.kytos.mef_eline.models.EVC.sync")
562
    def test_deploy_fail(self, *args):
563
        """Test if all methods is ignored when the should_deploy is false."""
564
        # pylint: disable=too-many-locals
565
        (
566
            sync_mock,
567
            should_deploy_mock,
568
            activate_mock,
569
            install_uni_flows_mock,
570
            install_nni_flows,
571
            choose_vlans_mock,
572
            discover_new_paths,
573
            log_mock,
574
            requests_mock,
575
        ) = args
576
577
        response = MagicMock()
578
        response.status_code = 201
579
        requests_mock.return_value = response
580
581
        uni_a = get_uni_mocked(
582
            interface_port=2,
583
            tag_value=82,
584
            switch_id="switch_uni_a",
585
            switch_dpid="switch_dpid_uni_a",
586
            is_valid=True,
587
        )
588
        uni_z = get_uni_mocked(
589
            interface_port=3,
590
            tag_value=83,
591
            switch_id="switch_uni_z",
592
            switch_dpid="switch_dpid_uni_a",
593
            is_valid=True,
594
        )
595
596
        attributes = {
597
            "controller": get_controller_mock(),
598
            "name": "custom_name",
599
            "uni_a": uni_a,
600
            "uni_z": uni_z,
601
            "primary_links": [
602
                get_link_mocked(
603
                    endpoint_a_port=9,
604
                    endpoint_b_port=10,
605
                    metadata={"s_vlan": 5},
606
                ),
607
                get_link_mocked(
608
                    endpoint_a_port=11,
609
                    endpoint_b_port=12,
610
                    metadata={"s_vlan": 6},
611
                ),
612
            ],
613
        }
614
615
        evc = EVC(**attributes)
616
        deployed = evc.deploy_to_path()
617
618
        self.assertEqual(discover_new_paths.call_count, 1)
619
        self.assertEqual(should_deploy_mock.call_count, 1)
620
        self.assertEqual(activate_mock.call_count, 0)
621
        self.assertEqual(install_uni_flows_mock.call_count, 0)
622
        self.assertEqual(install_nni_flows.call_count, 0)
623
        self.assertEqual(choose_vlans_mock.call_count, 0)
624
        self.assertEqual(log_mock.info.call_count, 0)
625
        self.assertEqual(sync_mock.call_count, 1)
626
        self.assertFalse(deployed)
627
628
    @patch("napps.kytos.mef_eline.models.evc.log")
629
    @patch(
630
        "napps.kytos.mef_eline.models.evc.EVC.discover_new_paths",
631
        return_value=[],
632
    )
633
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
634
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_nni_flows")
635
    @patch("napps.kytos.mef_eline.models.evc.EVC.should_deploy")
636
    @patch("napps.kytos.mef_eline.models.evc.EVC.remove_current_flows")
637
    @patch("napps.kytos.mef_eline.models.evc.EVC.sync")
638
    def test_deploy_error(self, *args):
639
        """Test if all methods is ignored when the should_deploy is false."""
640
        # pylint: disable=too-many-locals
641
        (
642
            sync_mock,
643
            remove_current_flows,
644
            should_deploy_mock,
645
            install_nni_flows,
646
            choose_vlans_mock,
647
            discover_new_paths,
648
            log_mock,
649
        ) = args
650
651
        install_nni_flows.side_effect = FlowModException
652
        should_deploy_mock.return_value = True
653
        uni_a = get_uni_mocked(
654
            interface_port=2,
655
            tag_value=82,
656
            switch_id="switch_uni_a",
657
            is_valid=True,
658
        )
659
        uni_z = get_uni_mocked(
660
            interface_port=3,
661
            tag_value=83,
662
            switch_id="switch_uni_z",
663
            is_valid=True,
664
        )
665
666
        primary_links = [
667
            get_link_mocked(
668
                endpoint_a_port=9, endpoint_b_port=10, metadata={"s_vlan": 5}
669
            ),
670
            get_link_mocked(
671
                endpoint_a_port=11, endpoint_b_port=12, metadata={"s_vlan": 6}
672
            ),
673
        ]
674
675
        attributes = {
676
            "controller": get_controller_mock(),
677
            "name": "custom_name",
678
            "uni_a": uni_a,
679
            "uni_z": uni_z,
680
            "primary_links": primary_links,
681
            "queue_id": 5,
682
        }
683
        # Setup path to deploy
684
        path = Path()
685
        path.append(primary_links[0])
686
        path.append(primary_links[1])
687
688
        evc = EVC(**attributes)
689
690
        deployed = evc.deploy_to_path(path)
691
692
        self.assertEqual(discover_new_paths.call_count, 0)
693
        self.assertEqual(should_deploy_mock.call_count, 1)
694
        self.assertEqual(install_nni_flows.call_count, 1)
695
        self.assertEqual(choose_vlans_mock.call_count, 1)
696
        self.assertEqual(log_mock.error.call_count, 1)
697
        self.assertEqual(sync_mock.call_count, 0)
698
        self.assertEqual(remove_current_flows.call_count, 2)
699
        self.assertFalse(deployed)
700
701
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy_to_path")
702
    @patch("napps.kytos.mef_eline.models.evc.EVC.discover_new_paths")
703
    def test_deploy_to_backup_path1(
704
        self, discover_new_paths_mocked, deploy_to_path_mocked
705
    ):
706
        """Test deployment when dynamic_backup_path is False in same switch"""
707
        uni_a = get_uni_mocked(interface_port=2, tag_value=82, is_valid=True)
708
        uni_z = get_uni_mocked(interface_port=3, tag_value=83, is_valid=True)
709
710
        switch = Mock(spec=Switch)
711
        uni_a.interface.switch = switch
712
        uni_z.interface.switch = switch
713
714
        attributes = {
715
            "controller": get_controller_mock(),
716
            "name": "custom_name",
717
            "uni_a": uni_a,
718
            "uni_z": uni_z,
719
            "enabled": True,
720
            "dynamic_backup_path": False,
721
        }
722
723
        evc = EVC(**attributes)
724
        discover_new_paths_mocked.return_value = []
725
        deploy_to_path_mocked.return_value = True
726
727
        # storehouse initialization mock
728
        evc._storehouse.box = Mock()  # pylint: disable=protected-access
729
        evc._storehouse.box.data = {}  # pylint: disable=protected-access
730
731
        deployed = evc.deploy_to_backup_path()
732
733
        deploy_to_path_mocked.assert_called_once_with()
734
        self.assertEqual(deployed, True)
735
736
    @patch("requests.post")
737
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
738
    @patch("napps.kytos.mef_eline.models.evc.log")
739
    @patch("napps.kytos.mef_eline.models.path.Path.choose_vlans")
740
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_nni_flows")
741
    @patch("napps.kytos.mef_eline.models.evc.EVC._install_uni_flows")
742
    @patch("napps.kytos.mef_eline.models.evc.EVC.activate")
743
    @patch("napps.kytos.mef_eline.models.evc.EVC.should_deploy")
744
    @patch("napps.kytos.mef_eline.models.evc.EVC.discover_new_paths")
745
    def test_deploy_without_path_case1(self, *args):
746
        """Test if not path is found a dynamic path is used."""
747
        # pylint: disable=too-many-locals
748
        (
749
            discover_new_paths_mocked,
750
            should_deploy_mock,
751
            activate_mock,
752
            install_uni_flows_mock,
753
            install_nni_flows,
754
            chose_vlans_mock,
755
            log_mock,
756
            _,
757
            requests_mock,
758
        ) = args
759
760
        response = MagicMock()
761
        response.status_code = 201
762
        requests_mock.return_value = response
763
764
        should_deploy_mock.return_value = False
765
        uni_a = get_uni_mocked(
766
            interface_port=2,
767
            tag_value=82,
768
            switch_id="switch_uni_a",
769
            is_valid=True,
770
        )
771
        uni_z = get_uni_mocked(
772
            interface_port=3,
773
            tag_value=83,
774
            switch_id="switch_uni_z",
775
            is_valid=True,
776
        )
777
778
        attributes = {
779
            "controller": get_controller_mock(),
780
            "name": "custom_name",
781
            "uni_a": uni_a,
782
            "uni_z": uni_z,
783
            "enabled": True,
784
            "dynamic_backup_path": False,
785
        }
786
787
        dynamic_backup_path = Path(
788
            [
789
                get_link_mocked(
790
                    endpoint_a_port=9,
791
                    endpoint_b_port=10,
792
                    metadata={"s_vlan": 5},
793
                ),
794
                get_link_mocked(
795
                    endpoint_a_port=11,
796
                    endpoint_b_port=12,
797
                    metadata={"s_vlan": 6},
798
                ),
799
            ]
800
        )
801
802
        evc = EVC(**attributes)
803
        discover_new_paths_mocked.return_value = [dynamic_backup_path]
804
805
        deployed = evc.deploy_to_path()
806
807
        self.assertEqual(should_deploy_mock.call_count, 1)
808
        self.assertEqual(discover_new_paths_mocked.call_count, 1)
809
        self.assertEqual(activate_mock.call_count, 1)
810
        self.assertEqual(install_uni_flows_mock.call_count, 1)
811
        self.assertEqual(install_nni_flows.call_count, 1)
812
        self.assertEqual(chose_vlans_mock.call_count, 1)
813
        log_mock.info.assert_called_with(f"{evc} was deployed.")
814
        self.assertTrue(deployed)
815
816
    @patch("napps.kytos.mef_eline.models.evc.notify_link_available_tags")
817
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
818
    def test_remove_current_flows(self, send_flow_mods_mocked, notify_mock):
819
        """Test remove current flows."""
820
        uni_a = get_uni_mocked(
821
            interface_port=2,
822
            tag_value=82,
823
            switch_id="switch_uni_a",
824
            is_valid=True,
825
        )
826
        uni_z = get_uni_mocked(
827
            interface_port=3,
828
            tag_value=83,
829
            switch_id="switch_uni_z",
830
            is_valid=True,
831
        )
832
833
        switch_a = Switch("00:00:00:00:00:01")
834
        switch_b = Switch("00:00:00:00:00:02")
835
        switch_c = Switch("00:00:00:00:00:03")
836
837
        attributes = {
838
            "controller": get_controller_mock(),
839
            "name": "custom_name",
840
            "uni_a": uni_a,
841
            "uni_z": uni_z,
842
            "active": True,
843
            "enabled": True,
844
            "primary_links": [
845
                get_link_mocked(
846
                    switch_a=switch_a,
847
                    switch_b=switch_b,
848
                    endpoint_a_port=9,
849
                    endpoint_b_port=10,
850
                    metadata={"s_vlan": 5},
851
                ),
852
                get_link_mocked(
853
                    switch_a=switch_b,
854
                    switch_b=switch_c,
855
                    endpoint_a_port=11,
856
                    endpoint_b_port=12,
857
                    metadata={"s_vlan": 6},
858
                ),
859
            ],
860
        }
861
862
        evc = EVC(**attributes)
863
864
        # storehouse initialization mock
865
        evc._storehouse.box = Mock()  # pylint: disable=protected-access
866
        evc._storehouse.box.data = {}  # pylint: disable=protected-access
867
868
        evc.current_path = evc.primary_links
869
        evc.remove_current_flows()
870
        notify_mock.assert_called()
871
872
        self.assertEqual(send_flow_mods_mocked.call_count, 5)
873
        self.assertFalse(evc.is_active())
874
        flows = [
875
            {"cookie": evc.get_cookie(), "cookie_mask": 18446744073709551615}
876
        ]
877
        switch_1 = evc.primary_links[0].endpoint_a.switch
878
        switch_2 = evc.primary_links[0].endpoint_b.switch
879
        send_flow_mods_mocked.assert_any_call(switch_1, flows, 'delete',
880
                                              force=True)
881
        send_flow_mods_mocked.assert_any_call(switch_2, flows, 'delete',
882
                                              force=True)
883
884
    @staticmethod
885
    @patch("napps.kytos.mef_eline.models.evc.EVC._send_flow_mods")
886
    def test_deploy_direct_uni_flows(send_flow_mods_mock):
887
        """Test _install_direct_uni_flows."""
888
889
        switch = Mock(spec=Switch)
890
        switch.dpid = 2
891
        interface_a = Interface("eth0", 1, switch)
892
        interface_z = Interface("eth1", 3, switch)
893
        uni_a = get_uni_mocked(
894
            tag_value=82,
895
            is_valid=True,
896
        )
897
        uni_z = get_uni_mocked(
898
            tag_value=84,
899
            is_valid=True,
900
        )
901
        uni_a.interface = interface_a
902
        uni_z.interface = interface_z
903
        attributes = {
904
            "controller": get_controller_mock(),
905
            "name": "custom_name",
906
            "uni_a": uni_a,
907
            "uni_z": uni_z,
908
            "enabled": True,
909
            "active": True,
910
        }
911
        evc = EVC(**attributes)
912
913
        # pylint: disable=protected-access
914
        evc._install_direct_uni_flows()
915
        send_flow_mods_mock.assert_called_once_with(
916
            switch, [
917
                {
918
                    "match": {
919
                        "in_port": 1,
920
                        "dl_vlan": 82,
921
                    },
922
                    "cookie": evc.get_cookie(),
923
                    "actions": [
924
                        {
925
                            "action_type": "set_vlan",
926
                            "vlan_id": 84,
927
                        },
928
                        {
929
                            "action_type": "output",
930
                            "port": 3,
931
                        },
932
                    ]
933
                },
934
                {
935
                    "match": {
936
                        "in_port": 3,
937
                        "dl_vlan": 84,
938
                    },
939
                    "cookie": evc.get_cookie(),
940
                    "actions": [
941
                        {
942
                            "action_type": "set_vlan",
943
                            "vlan_id": 82,
944
                        },
945
                        {
946
                            "action_type": "output",
947
                            "port": 1,
948
                        },
949
                    ]
950
                }
951
            ])
952
953
    def test_is_affected_by_link(self):
954
        """Test is_affected_by_link method"""
955
        self.evc_deploy.current_path = Path(['a', 'b', 'c'])
956
        self.assertTrue(self.evc_deploy.is_affected_by_link('b'))
957
958
    def test_is_backup_path_affected_by_link(self):
959
        """Test is_backup_path_affected_by_link method"""
960
        self.evc_deploy.backup_path = Path(['a', 'b', 'c'])
961
        self.assertFalse(self.evc_deploy.is_backup_path_affected_by_link('d'))
962
963
    def test_is_primary_path_affected_by_link(self):
964
        """Test is_primary_path_affected_by_link method"""
965
        self.evc_deploy.primary_path = Path(['a', 'b', 'c'])
966
        self.assertTrue(self.evc_deploy.is_primary_path_affected_by_link('c'))
967
968
    def test_is_using_primary_path(self):
969
        """Test is_using_primary_path method"""
970
        self.evc_deploy.primary_path = Path(['a', 'b', 'c'])
971
        self.evc_deploy.current_path = Path(['e', 'f', 'g'])
972
        self.assertFalse(self.evc_deploy.is_using_primary_path())
973
974
    def test_is_using_backup_path(self):
975
        """Test is_using_backup_path method"""
976
        self.evc_deploy.backup_path = Path(['a', 'b', 'c'])
977
        self.evc_deploy.current_path = Path(['e', 'f', 'g'])
978
        self.assertFalse(self.evc_deploy.is_using_backup_path())
979
980
    @patch('napps.kytos.mef_eline.models.path.Path.status')
981
    def test_is_using_dynamic_path(self, mock_status):
982
        """Test is_using_dynamic_path method"""
983
        mock_status.return_value = False
984
        self.evc_deploy.backup_path = Path([])
985
        self.evc_deploy.primary_path = Path([])
986
        self.assertFalse(self.evc_deploy.is_using_dynamic_path())
987