Passed
Push — master ( afe147...e6735a )
by Italo Valcy
10:09 queued 08:09
created

TestPath.test_status_case_2()   A

Complexity

Conditions 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nop 2
dl 0
loc 11
rs 9.95
c 0
b 0
f 0
1
"""Module to test the Path class."""
2
import sys
3
from unittest import TestCase
4
from unittest.mock import patch, Mock, MagicMock
5
6
from kytos.core.common import EntityStatus
7
from kytos.core.link import Link
8
from kytos.core.switch import Switch
9
10
# pylint: disable=wrong-import-position
11
12
sys.path.insert(0, "/var/lib/kytos/napps/..")
13
# pylint: enable=wrong-import-position
14
from napps.kytos.mef_eline.exceptions import InvalidPath  # NOQA pycodestyle
15
from napps.kytos.mef_eline.models import Path, DynamicPathManager  # NOQA pycodestyle
16
from napps.kytos.mef_eline.tests.helpers import (
17
    MockResponse,
18
    id_to_interface_mock,
19
    get_link_mocked,
20
    get_mocked_requests,
21
)  # NOQA pycodestyle
22
23
24
class TestPath(TestCase):
25
    """Class to test path methods."""
26
27
    def test_is_affected_by_link_1(self):
28
        """Test method is affected by link."""
29
        path = Path()
30
        self.assertIs(path.is_affected_by_link(), False)
31
32
    def test_link_affected_by_interface_1(self):
33
        """Test method to get the link using an interface."""
34
        link1 = Mock()
35
        link1.endpoint_a = "a"
36
        link1.endpoint_b = "b"
37
        link2 = Mock()
38
        link2.endpoint_a = "c"
39
        link2.endpoint_b = "d"
40
        path = Path([link1, link2])
41
        self.assertIsNone(path.link_affected_by_interface())
42
43
    def test_link_affected_by_interface_2(self):
44
        """Test method to get the link using an interface."""
45
        link1 = Mock()
46
        link1.endpoint_a = "a"
47
        link1.endpoint_b = "b"
48
        link2 = Mock()
49
        link2.endpoint_a = "c"
50
        link2.endpoint_b = "d"
51
        path = Path([link1, link2])
52
        self.assertEqual(path.link_affected_by_interface("a"), link1)
53
54
    def test_status_case_1(self):
55
        """Test if empty link is DISABLED."""
56
        current_path = Path()
57
        self.assertEqual(current_path.status, EntityStatus.DISABLED)
58
59
    @patch("requests.get", side_effect=get_mocked_requests)
60
    def test_status_case_2(self, requests_mocked):
61
        # pylint: disable=unused-argument
62
        """Test if link status is DOWN."""
63
        link1 = get_link_mocked()
64
        link2 = get_link_mocked()
65
        link1.id = "def"
66
        link2.id = "abc"
67
        links = [link1, link2]
68
        current_path = Path(links)
69
        self.assertEqual(current_path.status, EntityStatus.DOWN)
70
71
    def test_status_case_3(self):
72
        """Test if link status is DISABLED."""
73
        links = []
74
        current_path = Path(links)
75
        self.assertEqual(current_path.status, EntityStatus.DISABLED)
76
77
    # This method will be used by the mock to replace requests.get
78
    def _mocked_requests_get_status_case_4(self):
79
        # pylint: disable=no-self-use
80
        return MockResponse(
81
            {
82
                "links": {
83
                    "abc": {"active": True, "enabled": True},
84
                    "def": {"active": True, "enabled": True},
85
                }
86
            },
87
            200,
88
        )
89
90
    @patch("requests.get", side_effect=_mocked_requests_get_status_case_4)
91
    def test_status_case_4(self, requests_mocked):
92
        # pylint: disable=unused-argument
93
        """Test if link status is UP."""
94
        link1 = get_link_mocked()
95
        link2 = get_link_mocked()
96
        link1.id = "def"
97
        link2.id = "abc"
98
        links = [link1, link2]
99
        current_path = Path(links)
100
        self.assertEqual(current_path.status, EntityStatus.UP)
101
102
    # This method will be used by the mock to replace requests.get
103
    def _mocked_requests_get_status_case_5(self):
104
        # pylint: disable=no-self-use
105
        return MockResponse(
106
            {
107
                "links": {
108
                    "abc": {"active": True, "enabled": True},
109
                    "def": {"active": False, "enabled": False},
110
                }
111
            },
112
            200,
113
        )
114
115
    @patch("requests.get", side_effect=_mocked_requests_get_status_case_5)
116
    def test_status_case_5(self, requests_mocked):
117
        # pylint: disable=unused-argument
118
        """Test if link status is UP."""
119
        link1 = get_link_mocked()
120
        link2 = get_link_mocked()
121
        link1.id = "def"
122
        link2.id = "abc"
123
        links = [link1, link2]
124
        current_path = Path(links)
125
        self.assertEqual(current_path.status, EntityStatus.DISABLED)
126
127
    # This method will be used by the mock to replace requests.get
128
    def _mocked_requests_get_status_case_6(self):
129
        # pylint: disable=no-self-use
130
        return MockResponse(
131
            {
132
                "links": {
133
                    "abc": {"active": False, "enabled": False},
134
                    "def": {"active": False, "enabled": True},
135
                }
136
            },
137
            200,
138
        )
139
140
    @patch("requests.get", side_effect=_mocked_requests_get_status_case_6)
141
    def test_status_case_6(self, requests_mocked):
142
        # pylint: disable=unused-argument
143
        """Test if link status is UP."""
144
        link1 = get_link_mocked()
145
        link2 = get_link_mocked()
146
        link1.id = "def"
147
        link2.id = "abc"
148
        links = [link1, link2]
149
        current_path = Path(links)
150
        self.assertEqual(current_path.status, EntityStatus.DISABLED)
151
152
    def test_compare_same_paths(self):
153
        """Test compare paths with same links."""
154
        links = [
155
            get_link_mocked(
156
                endpoint_a_port=9, endpoint_b_port=10, metadata={"s_vlan": 5}
157
            ),
158
            get_link_mocked(
159
                endpoint_a_port=11, endpoint_b_port=12, metadata={"s_vlan": 6}
160
            ),
161
        ]
162
163
        path_1 = Path(links)
164
        path_2 = Path(links)
165
        self.assertEqual(path_1, path_2)
166
167
    def test_compare_different_paths(self):
168
        """Test compare paths with different links."""
169
        links_1 = [
170
            get_link_mocked(
171
                endpoint_a_port=9, endpoint_b_port=10, metadata={"s_vlan": 5}
172
            ),
173
            get_link_mocked(
174
                endpoint_a_port=11, endpoint_b_port=12, metadata={"s_vlan": 6}
175
            ),
176
        ]
177
        links_2 = [
178
            get_link_mocked(
179
                endpoint_a_port=12, endpoint_b_port=11, metadata={"s_vlan": 5}
180
            ),
181
            get_link_mocked(
182
                endpoint_a_port=14, endpoint_b_port=16, metadata={"s_vlan": 11}
183
            ),
184
        ]
185
186
        path_1 = Path(links_1)
187
        path_2 = Path(links_2)
188
        self.assertNotEqual(path_1, path_2)
189
190
    def test_as_dict(self):
191
        """Test path as dict."""
192
        links = [
193
            get_link_mocked(link_dict={"id": 3}),
194
            get_link_mocked(link_dict={"id": 2}),
195
        ]
196
197
        current_path = Path(links)
198
        expected_dict = [{"id": 3}, {"id": 2}]
199
        self.assertEqual(expected_dict, current_path.as_dict())
200
201
    def test_is_valid(self):
202
        """Test is_valid method."""
203
        switch1 = Switch("00:00:00:00:00:00:00:01")
204
        switch2 = Switch("00:00:00:00:00:00:00:02")
205
        switch3 = Switch("00:00:00:00:00:00:00:03")
206
        switch4 = Switch("00:00:00:00:00:00:00:04")
207
        switch5 = Switch("00:00:00:00:00:00:00:05")
208
        switch6 = Switch("00:00:00:00:00:00:00:06")
209
210
        links1 = [
211
            get_link_mocked(switch_a=switch1, switch_b=switch2),
212
            get_link_mocked(switch_a=switch2, switch_b=switch3),
213
            get_link_mocked(switch_a=switch3, switch_b=switch4),
214
            get_link_mocked(switch_a=switch4, switch_b=switch5),
215
            get_link_mocked(switch_a=switch5, switch_b=switch6),
216
        ]
217
218
        links2 = [
219
            get_link_mocked(switch_a=switch1, switch_b=switch2),
220
            get_link_mocked(switch_a=switch3, switch_b=switch2),
221
            get_link_mocked(switch_a=switch3, switch_b=switch4),
222
        ]
223
224
        for links, switch_a, switch_z, expected in (
225
            (links1, switch1, switch6, True),
226
            (links2, switch1, switch4, False),
227
            (links1, switch2, switch6, False),
228
        ):
229
            with self.subTest(
230
                links=links,
231
                switch_a=switch_a,
232
                switch_z=switch_z,
233
                expected=expected,
234
            ):
235
                path = Path(links)
236
                if expected:
237
                    self.assertEqual(
238
                        path.is_valid(switch_a, switch_z), expected
239
                    )
240
                else:
241
                    with self.assertRaises(InvalidPath):
242
                        path.is_valid(switch_a, switch_z)
243
244
245
class TestDynamicPathManager(TestCase):
246
    """Tests for the DynamicPathManager class"""
247
248
    def test_clear_path(self):
249
        """Test _clear_path method"""
250
        path = [
251
            '00:00:00:00:00:00:00:01:1',
252
            '00:00:00:00:00:00:00:02:3',
253
            '00:00:00:00:00:00:00:02',
254
            '00:00:00:00:00:00:00:02:4',
255
            '00:00:00:00:00:00:00:03:2',
256
            '00:00:00:00:00:00:00:03',
257
            '00:00:00:00:00:00:00:03:1',
258
            '00:00:00:00:00:00:00:04:1'
259
        ]
260
        expected_path = [
261
            '00:00:00:00:00:00:00:01:1',
262
            '00:00:00:00:00:00:00:02:3',
263
            '00:00:00:00:00:00:00:02:4',
264
            '00:00:00:00:00:00:00:03:2',
265
            '00:00:00:00:00:00:00:03:1',
266
            '00:00:00:00:00:00:00:04:1'
267
        ]
268
        # pylint: disable=protected-access
269
        self.assertEqual(DynamicPathManager._clear_path(path), expected_path)
270
271
    def test_create_path_invalid(self):
272
        """Test create_path method"""
273
        path = [
274
            '00:00:00:00:00:00:00:01:1',
275
            '00:00:00:00:00:00:00:02:3',
276
            '00:00:00:00:00:00:00:02',
277
            '00:00:00:00:00:00:00:02:4',
278
            '00:00:00:00:00:00:00:03:2',
279
            '00:00:00:00:00:00:00:03',
280
            '00:00:00:00:00:00:00:03:1',
281
        ]
282
        self.assertIsNone(DynamicPathManager.create_path(path))
283
284
    @patch("requests.post")
285
    def test_get_best_path(self, mock_requests_post):
286
        """Test get_best_path method."""
287
        controller = MagicMock()
288
        controller.get_interface_by_id.side_effect = id_to_interface_mock
289
        DynamicPathManager.set_controller(controller)
290
291
        paths1 = {
292
            "paths": [
293
                {
294
                    "cost": 5,
295
                    "hops": [
296
                        "00:00:00:00:00:00:00:01:1",
297
                        "00:00:00:00:00:00:00:01",
298
                        "00:00:00:00:00:00:00:01:2",
299
                        "00:00:00:00:00:00:00:02:2",
300
                        "00:00:00:00:00:00:00:02",
301
                        "00:00:00:00:00:00:00:02:1"
302
                        ]
303
                },
304
            ]
305
        }
306
307
        expected_path = [
308
            Link(
309
                id_to_interface_mock("00:00:00:00:00:00:00:01:2"),
310
                id_to_interface_mock("00:00:00:00:00:00:00:02:2")
311
            ),
312
        ]
313
314
        # test success case
315
        mock_response = MagicMock()
316
        mock_response.status_code = 200
317
        mock_response.json.return_value = paths1
318
        mock_requests_post.return_value = mock_response
319
320
        res_paths = list(DynamicPathManager.get_best_path(MagicMock()))
321
        self.assertEqual(
322
            [link.id for link in res_paths],
323
            [link.id for link in expected_path]
324
        )
325
326
        # test failure when controller dont find the interface on create_path
327
        controller.get_interface_by_id.side_effect = [
328
            id_to_interface_mock("00:00:00:00:00:00:00:01:2"),
329
            None
330
        ]
331
        self.assertIsNone(DynamicPathManager.get_best_path(MagicMock()))
332
333
        mock_response.status_code = 400
334
        mock_response.json.return_value = {}
335
        mock_requests_post.return_value = mock_response
336
337
        res_paths = DynamicPathManager.get_best_path(MagicMock())
338
        self.assertIsNone(res_paths)
339
340
    @patch("requests.post")
341
    def test_get_best_paths(self, mock_requests_post):
342
        """Test get_best_paths method."""
343
        controller = MagicMock()
344
        controller.get_interface_by_id.side_effect = id_to_interface_mock
345
        DynamicPathManager.set_controller(controller)
346
347
        paths1 = {
348
            "paths": [
349
                {
350
                    "cost": 5,
351
                    "hops": [
352
                        "00:00:00:00:00:00:00:01:1",
353
                        "00:00:00:00:00:00:00:01",
354
                        "00:00:00:00:00:00:00:01:2",
355
                        "00:00:00:00:00:00:00:02:2",
356
                        "00:00:00:00:00:00:00:02",
357
                        "00:00:00:00:00:00:00:02:1"
358
                        ]
359
                },
360
                {
361
                    "cost": 11,
362
                    "hops": [
363
                        "00:00:00:00:00:00:00:01:1",
364
                        "00:00:00:00:00:00:00:01",
365
                        "00:00:00:00:00:00:00:01:2",
366
                        "00:00:00:00:00:00:00:02:2",
367
                        "00:00:00:00:00:00:00:02",
368
                        "00:00:00:00:00:00:00:02:3",
369
                        "00:00:00:00:00:00:00:03:3",
370
                        "00:00:00:00:00:00:00:03",
371
                        "00:00:00:00:00:00:00:03:4",
372
                        "00:00:00:00:00:00:00:04:4",
373
                        "00:00:00:00:00:00:00:04",
374
                        "00:00:00:00:00:00:00:04:1"
375
                        ]
376
                },
377
            ]
378
        }
379
380
        expected_paths_0 = [
381
            Link(
382
                id_to_interface_mock("00:00:00:00:00:00:00:01:2"),
383
                id_to_interface_mock("00:00:00:00:00:00:00:02:2")
384
            ),
385
        ]
386
387
        expected_paths_1 = [
388
            Link(
389
                id_to_interface_mock("00:00:00:00:00:00:00:01:2"),
390
                id_to_interface_mock("00:00:00:00:00:00:00:02:2")
391
            ),
392
            Link(
393
                id_to_interface_mock("00:00:00:00:00:00:00:02:3"),
394
                id_to_interface_mock("00:00:00:00:00:00:00:03:3")
395
            ),
396
            Link(
397
                id_to_interface_mock("00:00:00:00:00:00:00:03:4"),
398
                id_to_interface_mock("00:00:00:00:00:00:00:04:4")
399
            ),
400
        ]
401
402
        mock_response = MagicMock()
403
        mock_response.status_code = 200
404
        mock_response.json.return_value = paths1
405
        mock_requests_post.return_value = mock_response
406
407
        res_paths = list(DynamicPathManager.get_best_paths(MagicMock()))
408
        self.assertEqual(
409
            [link.id for link in res_paths[0]],
410
            [link.id for link in expected_paths_0]
411
        )
412
        self.assertEqual(
413
            [link.id for link in res_paths[1]],
414
            [link.id for link in expected_paths_1]
415
        )
416
417
    @patch("requests.post")
418
    def test_get_disjoint_paths(self, mock_requests_post):
419
        """Test get_disjoint_paths method."""
420
421
        controller = MagicMock()
422
        controller.get_interface_by_id.side_effect = id_to_interface_mock
423
        DynamicPathManager.set_controller(controller)
424
425
        evc = MagicMock()
426
427
        # Topo0
428
        paths1 = {
429
            "paths": [
430
                {
431
                    "cost": 11,
432
                    "hops": [
433
                        "00:00:00:00:00:00:00:01:1",
434
                        "00:00:00:00:00:00:00:01",
435
                        "00:00:00:00:00:00:00:01:2",
436
                        "00:00:00:00:00:00:00:02:2",
437
                        "00:00:00:00:00:00:00:02",
438
                        "00:00:00:00:00:00:00:02:3",
439
                        "00:00:00:00:00:00:00:04:2",
440
                        "00:00:00:00:00:00:00:04",
441
                        "00:00:00:00:00:00:00:04:3",
442
                        "00:00:00:00:00:00:00:05:2",
443
                        "00:00:00:00:00:00:00:05",
444
                        "00:00:00:00:00:00:00:05:1"
445
                        ]
446
                },
447
                {
448
                    "cost": 11,
449
                    "hops": [
450
                        "00:00:00:00:00:00:00:01:1",
451
                        "00:00:00:00:00:00:00:01",
452
                        "00:00:00:00:00:00:00:01:3",
453
                        "00:00:00:00:00:00:00:03:2",
454
                        "00:00:00:00:00:00:00:03",
455
                        "00:00:00:00:00:00:00:03:3",
456
                        "00:00:00:00:00:00:00:04:4",
457
                        "00:00:00:00:00:00:00:04",
458
                        "00:00:00:00:00:00:00:04:3",
459
                        "00:00:00:00:00:00:00:05:2",
460
                        "00:00:00:00:00:00:00:05",
461
                        "00:00:00:00:00:00:00:05:1"
462
                        ]
463
                },
464
                {
465
                    "cost": 14,
466
                    "hops": [
467
                        "00:00:00:00:00:00:00:01:1",
468
                        "00:00:00:00:00:00:00:01",
469
                        "00:00:00:00:00:00:00:01:2",
470
                        "00:00:00:00:00:00:00:02:2",
471
                        "00:00:00:00:00:00:00:02",
472
                        "00:00:00:00:00:00:00:02:3",
473
                        "00:00:00:00:00:00:00:04:2",
474
                        "00:00:00:00:00:00:00:04",
475
                        "00:00:00:00:00:00:00:04:5",
476
                        "00:00:00:00:00:00:00:06:2",
477
                        "00:00:00:00:00:00:00:06",
478
                        "00:00:00:00:00:00:00:06:3",
479
                        "00:00:00:00:00:00:00:05:3",
480
                        "00:00:00:00:00:00:00:05",
481
                        "00:00:00:00:00:00:00:05:1"
482
                    ]
483
                },
484
                {
485
                    "cost": 14,
486
                    "hops": [
487
                        "00:00:00:00:00:00:00:01:1",
488
                        "00:00:00:00:00:00:00:01",
489
                        "00:00:00:00:00:00:00:01:3",
490
                        "00:00:00:00:00:00:00:03:2",
491
                        "00:00:00:00:00:00:00:03",
492
                        "00:00:00:00:00:00:00:03:3",
493
                        "00:00:00:00:00:00:00:04:4",
494
                        "00:00:00:00:00:00:00:04",
495
                        "00:00:00:00:00:00:00:04:5",
496
                        "00:00:00:00:00:00:00:06:2",
497
                        "00:00:00:00:00:00:00:06",
498
                        "00:00:00:00:00:00:00:06:3",
499
                        "00:00:00:00:00:00:00:05:3",
500
                        "00:00:00:00:00:00:00:05",
501
                        "00:00:00:00:00:00:00:05:1"
502
                    ]
503
                },
504
                {
505
                    "cost": 17,
506
                    "hops": [
507
                        "00:00:00:00:00:00:00:01:1",
508
                        "00:00:00:00:00:00:00:01",
509
                        "00:00:00:00:00:00:00:01:3",
510
                        "00:00:00:00:00:00:00:03:2",
511
                        "00:00:00:00:00:00:00:03",
512
                        "00:00:00:00:00:00:00:03:3",
513
                        "00:00:00:00:00:00:00:04:4",
514
                        "00:00:00:00:00:00:00:04",
515
                        "00:00:00:00:00:00:00:04:5",
516
                        "00:00:00:00:00:00:00:06:2",
517
                        "00:00:00:00:00:00:00:06",
518
                        "00:00:00:00:00:00:00:06:4",
519
                        "00:00:00:00:00:00:00:07:2",
520
                        "00:00:00:00:00:00:00:07",
521
                        "00:00:00:00:00:00:00:07:3",
522
                        "00:00:00:00:00:00:00:05:4",
523
                        "00:00:00:00:00:00:00:05",
524
                        "00:00:00:00:00:00:00:05:1"
525
                    ]
526
                },
527
            ]
528
        }
529
530
        mock_response = MagicMock()
531
        mock_response.status_code = 200
532
        mock_response.json.return_value = paths1
533
534
        # when we dont have the current_path
535
        mock_requests_post.return_value = mock_response
536
        disjoint_paths = list(DynamicPathManager.get_disjoint_paths(evc, []))
537
        self.assertEqual(disjoint_paths, [])
538
539
        current_path = [
540
            Link(
541
                id_to_interface_mock("00:00:00:00:00:00:00:01:2"),
542
                id_to_interface_mock("00:00:00:00:00:00:00:02:2")
543
            ),
544
            Link(
545
                id_to_interface_mock("00:00:00:00:00:00:00:02:3"),
546
                id_to_interface_mock("00:00:00:00:00:00:00:04:2")
547
            ),
548
            Link(
549
                id_to_interface_mock("00:00:00:00:00:00:00:04:3"),
550
                id_to_interface_mock("00:00:00:00:00:00:00:05:2")
551
            ),
552
        ]
553
554
        # only one path available from pathfinder (precesilly the
555
        # current_path), so the maximum disjoint path will be empty
556
        mock_response.json.return_value = {"paths": paths1["paths"][0:1]}
557
        mock_requests_post.return_value = mock_response
558
        paths = list(DynamicPathManager.get_disjoint_paths(evc, current_path))
559
        self.assertEqual(len(paths), 0)
560
561
        expected_disjoint_path = [
562
            Link(
563
                id_to_interface_mock("00:00:00:00:00:00:00:01:3"),
564
                id_to_interface_mock("00:00:00:00:00:00:00:03:2")
565
            ),
566
            Link(
567
                id_to_interface_mock("00:00:00:00:00:00:00:03:3"),
568
                id_to_interface_mock("00:00:00:00:00:00:00:04:4")
569
            ),
570
            Link(
571
                id_to_interface_mock("00:00:00:00:00:00:00:04:5"),
572
                id_to_interface_mock("00:00:00:00:00:00:00:06:2")
573
            ),
574
            Link(
575
                id_to_interface_mock("00:00:00:00:00:00:00:06:3"),
576
                id_to_interface_mock("00:00:00:00:00:00:00:05:3")
577
            ),
578
        ]
579
580
        # there are one alternative path
581
        mock_response.json.return_value = paths1
582
        mock_requests_post.return_value = mock_response
583
        paths = list(DynamicPathManager.get_disjoint_paths(evc, current_path))
584
        self.assertEqual(len(paths), 4)
585
        # for more information on the paths please refer to EP029
586
        self.assertEqual(len(paths[0]), 4)  # path S-Z-W-I-D
587
        self.assertEqual(len(paths[1]), 5)  # path S-Z-W-I-J-D
588
        self.assertEqual(len(paths[2]), 3)  # path S-Z-W-D
589
        self.assertEqual(len(paths[3]), 4)  # path S-X-W-I-D
590
        self.assertEqual(
591
            [link.id for link in paths[0]],
592
            [link.id for link in expected_disjoint_path]
593
        )
594
595
        # EP029 Topo2
596
        paths2 = {
597
            "paths": [
598
                {
599
                    "cost": 14,
600
                    "hops": [
601
                        "00:00:00:00:00:00:00:01:1",
602
                        "00:00:00:00:00:00:00:01",
603
                        "00:00:00:00:00:00:00:01:2",
604
                        "00:00:00:00:00:00:00:02:1",
605
                        "00:00:00:00:00:00:00:02",
606
                        "00:00:00:00:00:00:00:02:2",
607
                        "00:00:00:00:00:00:00:03:1",
608
                        "00:00:00:00:00:00:00:03",
609
                        "00:00:00:00:00:00:00:03:2",
610
                        "00:00:00:00:00:00:00:04:1",
611
                        "00:00:00:00:00:00:00:04",
612
                        "00:00:00:00:00:00:00:04:2",
613
                        "00:00:00:00:00:00:00:07:2",
614
                        "00:00:00:00:00:00:00:07",
615
                        "00:00:00:00:00:00:00:07:1"
616
                    ]
617
                },
618
                {
619
                    "cost": 17,
620
                    "hops": [
621
                        "00:00:00:00:00:00:00:01:1",
622
                        "00:00:00:00:00:00:00:01",
623
                        "00:00:00:00:00:00:00:01:2",
624
                        "00:00:00:00:00:00:00:02:1",
625
                        "00:00:00:00:00:00:00:02",
626
                        "00:00:00:00:00:00:00:02:3",
627
                        "00:00:00:00:00:00:00:05:1",
628
                        "00:00:00:00:00:00:00:05",
629
                        "00:00:00:00:00:00:00:05:2",
630
                        "00:00:00:00:00:00:00:06:1",
631
                        "00:00:00:00:00:00:00:06",
632
                        "00:00:00:00:00:00:00:06:2",
633
                        "00:00:00:00:00:00:00:04:3",
634
                        "00:00:00:00:00:00:00:04",
635
                        "00:00:00:00:00:00:00:04:2",
636
                        "00:00:00:00:00:00:00:07:2",
637
                        "00:00:00:00:00:00:00:07",
638
                        "00:00:00:00:00:00:00:07:1"
639
                    ]
640
                }
641
            ]
642
        }
643
644
        current_path = [
645
            Link(
646
                id_to_interface_mock("00:00:00:00:00:00:00:01:2"),
647
                id_to_interface_mock("00:00:00:00:00:00:00:02:1")
648
            ),
649
            Link(
650
                id_to_interface_mock("00:00:00:00:00:00:00:02:2"),
651
                id_to_interface_mock("00:00:00:00:00:00:00:03:1")
652
            ),
653
            Link(
654
                id_to_interface_mock("00:00:00:00:00:00:00:03:2"),
655
                id_to_interface_mock("00:00:00:00:00:00:00:04:1")
656
            ),
657
            Link(
658
                id_to_interface_mock("00:00:00:00:00:00:00:04:2"),
659
                id_to_interface_mock("00:00:00:00:00:00:00:07:2")
660
            ),
661
        ]
662
663
        expected_disjoint_path = [
664
            Link(
665
                id_to_interface_mock("00:00:00:00:00:00:00:01:2"),
666
                id_to_interface_mock("00:00:00:00:00:00:00:02:1")
667
            ),
668
            Link(
669
                id_to_interface_mock("00:00:00:00:00:00:00:02:3"),
670
                id_to_interface_mock("00:00:00:00:00:00:00:05:1")
671
            ),
672
            Link(
673
                id_to_interface_mock("00:00:00:00:00:00:00:05:2"),
674
                id_to_interface_mock("00:00:00:00:00:00:00:06:1")
675
            ),
676
            Link(
677
                id_to_interface_mock("00:00:00:00:00:00:00:06:2"),
678
                id_to_interface_mock("00:00:00:00:00:00:00:04:3")
679
            ),
680
            Link(
681
                id_to_interface_mock("00:00:00:00:00:00:00:04:2"),
682
                id_to_interface_mock("00:00:00:00:00:00:00:07:2")
683
            ),
684
        ]
685
686
        mock_response.json.return_value = {"paths": paths2["paths"]}
687
        mock_requests_post.return_value = mock_response
688
        paths = list(DynamicPathManager.get_disjoint_paths(evc, current_path))
689
        self.assertEqual(len(paths), 1)
690
        self.assertEqual(
691
            [link.id for link in paths[0]],
692
            [link.id for link in expected_disjoint_path]
693
        )
694