Passed
Pull Request — master (#90)
by Antonio
05:03
created

TestMain.test_verify_api_urls()   B

Complexity

Conditions 1

Size

Total Lines 59
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 47
nop 1
dl 0
loc 59
rs 8.7345
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
"""Module to test the main napp file."""
2
import json
3
from unittest import TestCase
4
from unittest.mock import MagicMock, PropertyMock, call, create_autospec, patch
5
6
from kytos.core.events import KytosEvent
7
from kytos.core.interface import UNI, Interface
8
from napps.kytos.mef_eline.exceptions import InvalidPath
9
from napps.kytos.mef_eline.models import EVC
10
from napps.kytos.mef_eline.tests.helpers import (
11
    get_controller_mock,
12
    get_uni_mocked,
13
)
14
15
16
# pylint: disable=too-many-public-methods, too-many-lines
17
class TestMain(TestCase):
18
    """Test the Main class."""
19
20
    def setUp(self):
21
        """Execute steps before each tests.
22
23
        Set the server_name_url_url from kytos/mef_eline
24
        """
25
        self.server_name_url = "http://localhost:8181/api/kytos/mef_eline"
26
27
        # The decorator run_on_thread is patched, so methods that listen
28
        # for events do not run on threads while tested.
29
        # Decorators have to be patched before the methods that are
30
        # decorated with them are imported.
31
        patch("kytos.core.helpers.run_on_thread", lambda x: x).start()
32
        # pylint: disable=import-outside-toplevel
33
        from napps.kytos.mef_eline.main import Main
34
35
        self.addCleanup(patch.stopall)
36
        self.napp = Main(get_controller_mock())
37
38
    def test_get_event_listeners(self):
39
        """Verify all event listeners registered."""
40
        expected_events = [
41
            "kytos/core.shutdown",
42
            "kytos/core.shutdown.kytos/mef_eline",
43
            "kytos/topology.link_up",
44
            "kytos/topology.link_down",
45
        ]
46
        actual_events = self.napp.listeners()
47
48
        for _event in expected_events:
49
            self.assertIn(_event, actual_events, _event)
50
51
    def test_verify_api_urls(self):
52
        """Verify all APIs registered."""
53
        expected_urls = [
54
            ({}, {"POST", "OPTIONS"}, "/api/kytos/mef_eline/v2/evc/"),
55
            ({}, {"OPTIONS", "HEAD", "GET"}, "/api/kytos/mef_eline/v2/evc/"),
56
            (
57
                {"circuit_id": "[circuit_id]"},
58
                {"OPTIONS", "DELETE"},
59
                "/api/kytos/mef_eline/v2/evc/<circuit_id>",
60
            ),
61
            (
62
                {"circuit_id": "[circuit_id]"},
63
                {"OPTIONS", "HEAD", "GET"},
64
                "/api/kytos/mef_eline/v2/evc/<circuit_id>",
65
            ),
66
            (
67
                {"circuit_id": "[circuit_id]"},
68
                {"OPTIONS", "PATCH"},
69
                "/api/kytos/mef_eline/v2/evc/<circuit_id>",
70
            ),
71
            (
72
                {"circuit_id": "[circuit_id]"},
73
                {"OPTIONS", "HEAD", "GET"},
74
                "/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata",
75
            ),
76
            (
77
                {"circuit_id": "[circuit_id]"},
78
                {"OPTIONS", "POST"},
79
                "/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata",
80
            ),
81
            (
82
                {"circuit_id": "[circuit_id]", "key": "[key]"},
83
                {"OPTIONS", "DELETE"},
84
                "/api/kytos/mef_eline/v2/evc/<circuit_id>/metadata/<key>",
85
            ),
86
            (
87
                {"circuit_id": "[circuit_id]"},
88
                {"OPTIONS", "PATCH"},
89
                "/api/kytos/mef_eline/v2/evc/<circuit_id>/redeploy",
90
            ),
91
            (
92
                {},
93
                {"OPTIONS", "GET", "HEAD"},
94
                "/api/kytos/mef_eline/v2/evc/schedule",
95
            ),
96
            ({}, {"POST", "OPTIONS"}, "/api/kytos/mef_eline/v2/evc/schedule/"),
97
            (
98
                {"schedule_id": "[schedule_id]"},
99
                {"OPTIONS", "DELETE"},
100
                "/api/kytos/mef_eline/v2/evc/schedule/<schedule_id>",
101
            ),
102
            (
103
                {"schedule_id": "[schedule_id]"},
104
                {"OPTIONS", "PATCH"},
105
                "/api/kytos/mef_eline/v2/evc/schedule/<schedule_id>",
106
            ),
107
        ]
108
        urls = self.get_napp_urls(self.napp)
109
        self.assertEqual(len(expected_urls), len(urls))
110
111
    @patch('napps.kytos.mef_eline.main.log')
112
    @patch('napps.kytos.mef_eline.main.Main.execute_consistency')
113
    def test_execute(self, mock_execute_consistency, mock_log):
114
        """Test execute."""
115
        self.napp.execute()
116
        mock_execute_consistency.assert_called()
117
        self.assertEqual(mock_log.debug.call_count, 2)
118
119
        # Test locked should return
120
        mock_execute_consistency.call_count = 0
121
        mock_log.info.call_count = 0
122
        # pylint: disable=protected-access
123
        self.napp._lock = MagicMock()
124
        self.napp._lock.locked.return_value = True
125
        # pylint: enable=protected-access
126
        self.napp.execute()
127
        mock_execute_consistency.assert_not_called()
128
        mock_log.info.assert_not_called()
129
130
    @patch('napps.kytos.mef_eline.main.settings')
131
    @patch('napps.kytos.mef_eline.main.Main._load_evc')
132
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
133
    def test_execute_consistency(self, *args):
134
        """Test execute_consistency."""
135
        (mock_get_data, mock_load_evc, mock_settings) = args
136
137
        stored_circuits = {'1': {'name': 'circuit_1'},
138
                           '2': {'name': 'circuit_2'},
139
                           '3': {'name': 'circuit_3'}}
140
        mock_get_data.return_value = stored_circuits
141
        mock_settings.WAIT_FOR_OLD_PATH = -1
142
        evc1 = MagicMock()
143
        evc1.is_enabled.return_value = True
144
        evc1.is_active.return_value = False
145
        evc1.lock.locked.return_value = False
146
        evc1.check_traces.return_value = True
147
        evc2 = MagicMock()
148
        evc2.is_enabled.return_value = True
149
        evc2.is_active.return_value = False
150
        evc2.lock.locked.return_value = False
151
        evc2.check_traces.return_value = False
152
        self.napp.circuits = {'1': evc1, '2': evc2}
153
154
        self.napp.execute_consistency()
155
        self.assertEqual(evc1.activate.call_count, 1)
156
        self.assertEqual(evc1.sync.call_count, 1)
157
        self.assertEqual(evc2.deploy.call_count, 1)
158
        mock_load_evc.assert_called_with(stored_circuits['3'])
159
160
    @patch('napps.kytos.mef_eline.main.settings')
161
    def test_execute_consistency_wait_for(self, mock_settings):
162
        """Test execute and wait for setting."""
163
        evc1 = MagicMock()
164
        evc1.is_enabled.return_value = True
165
        evc1.is_active.return_value = False
166
        evc1.lock.locked.return_value = False
167
        evc1.check_traces.return_value = False
168
        evc1.deploy.call_count = 0
169
        self.napp.circuits = {'1': evc1}
170
        self.napp.execution_rounds = 0
171
        mock_settings.WAIT_FOR_OLD_PATH = 1
172
173
        self.napp.execute_consistency()
174
        self.assertEqual(evc1.deploy.call_count, 0)
175
        self.napp.execute_consistency()
176
        self.assertEqual(evc1.deploy.call_count, 1)
177
178
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
179
    @patch('napps.kytos.mef_eline.models.evc.EVCBase._validate')
180
    def test_evc_from_dict(self, _validate_mock, uni_from_dict_mock):
181
        """
182
        Test the helper method that create an EVN from dict.
183
184
        Verify object creation with circuit data and schedule data.
185
        """
186
        _validate_mock.return_value = True
187
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
188
        payload = {
189
            "name": "my evc1",
190
            "uni_a": {
191
                "interface_id": "00:00:00:00:00:00:00:01:1",
192
                "tag": {"tag_type": 1, "value": 80},
193
            },
194
            "uni_z": {
195
                "interface_id": "00:00:00:00:00:00:00:02:2",
196
                "tag": {"tag_type": 1, "value": 1},
197
            },
198
            "circuit_scheduler": [
199
                {"frequency": "* * * * *", "action": "create"}
200
            ],
201
            "queue_id": 5,
202
        }
203
        # pylint: disable=protected-access
204
        evc_response = self.napp._evc_from_dict(payload)
205
        self.assertIsNotNone(evc_response)
206
        self.assertIsNotNone(evc_response.uni_a)
207
        self.assertIsNotNone(evc_response.uni_z)
208
        self.assertIsNotNone(evc_response.circuit_scheduler)
209
        self.assertIsNotNone(evc_response.name)
210
        self.assertIsNotNone(evc_response.queue_id)
211
212
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
213
    @patch("napps.kytos.mef_eline.models.evc.EVCBase._validate")
214
    @patch("kytos.core.Controller.get_interface_by_id")
215
    def test_evc_from_dict_paths(
216
        self, _get_interface_by_id_mock, _validate_mock, uni_from_dict_mock
217
    ):
218
        """
219
        Test the helper method that create an EVN from dict.
220
221
        Verify object creation with circuit data and schedule data.
222
        """
223
        _get_interface_by_id_mock.return_value = True
224
        _validate_mock.return_value = True
225
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
226
        payload = {
227
            "name": "my evc1",
228
            "uni_a": {
229
                "interface_id": "00:00:00:00:00:00:00:01:1",
230
                "tag": {"tag_type": 1, "value": 80},
231
            },
232
            "uni_z": {
233
                "interface_id": "00:00:00:00:00:00:00:02:2",
234
                "tag": {"tag_type": 1, "value": 1},
235
            },
236
            "current_path": [],
237
            "primary_path": [
238
                {
239
                    "endpoint_a": {
240
                        "interface_id": "00:00:00:00:00:00:00:01:1"
241
                    },
242
                    "endpoint_b": {
243
                        "interface_id": "00:00:00:00:00:00:00:02:2"
244
                    },
245
                }
246
            ],
247
            "backup_path": [],
248
        }
249
250
        # pylint: disable=protected-access
251
        evc_response = self.napp._evc_from_dict(payload)
252
        self.assertIsNotNone(evc_response)
253
        self.assertIsNotNone(evc_response.uni_a)
254
        self.assertIsNotNone(evc_response.uni_z)
255
        self.assertIsNotNone(evc_response.circuit_scheduler)
256
        self.assertIsNotNone(evc_response.name)
257
        self.assertEqual(len(evc_response.current_path), 0)
258
        self.assertEqual(len(evc_response.backup_path), 0)
259
        self.assertEqual(len(evc_response.primary_path), 1)
260
261
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
262
    @patch("napps.kytos.mef_eline.models.evc.EVCBase._validate")
263
    @patch("kytos.core.Controller.get_interface_by_id")
264
    def test_evc_from_dict_links(
265
        self, _get_interface_by_id_mock, _validate_mock, uni_from_dict_mock
266
    ):
267
        """
268
        Test the helper method that create an EVN from dict.
269
270
        Verify object creation with circuit data and schedule data.
271
        """
272
        _get_interface_by_id_mock.return_value = True
273
        _validate_mock.return_value = True
274
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
275
        payload = {
276
            "name": "my evc1",
277
            "uni_a": {
278
                "interface_id": "00:00:00:00:00:00:00:01:1",
279
                "tag": {"tag_type": 1, "value": 80},
280
            },
281
            "uni_z": {
282
                "interface_id": "00:00:00:00:00:00:00:02:2",
283
                "tag": {"tag_type": 1, "value": 1},
284
            },
285
            "primary_links": [
286
                {
287
                    "endpoint_a": {
288
                        "interface_id": "00:00:00:00:00:00:00:01:1"
289
                    },
290
                    "endpoint_b": {
291
                        "interface_id": "00:00:00:00:00:00:00:02:2"
292
                    },
293
                }
294
            ],
295
            "backup_links": [],
296
        }
297
298
        # pylint: disable=protected-access
299
        evc_response = self.napp._evc_from_dict(payload)
300
        self.assertIsNotNone(evc_response)
301
        self.assertIsNotNone(evc_response.uni_a)
302
        self.assertIsNotNone(evc_response.uni_z)
303
        self.assertIsNotNone(evc_response.circuit_scheduler)
304
        self.assertIsNotNone(evc_response.name)
305
        self.assertEqual(len(evc_response.current_links_cache), 0)
306
        self.assertEqual(len(evc_response.backup_links), 0)
307
        self.assertEqual(len(evc_response.primary_links), 1)
308
309
    def test_list_without_circuits(self):
310
        """Test if list circuits return 'no circuit stored.'."""
311
        api = self.get_app_test_client(self.napp)
312
        url = f"{self.server_name_url}/v2/evc/"
313
        response = api.get(url)
314
        self.assertEqual(response.status_code, 200, response.data)
315
        self.assertEqual(json.loads(response.data.decode()), {})
316
317
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
318
    def test_list_no_circuits_stored(self, storehouse_data_mock):
319
        """Test if list circuits return all circuits stored."""
320
        circuits = {}
321
        storehouse_data_mock.return_value = circuits
322
323
        api = self.get_app_test_client(self.napp)
324
        url = f"{self.server_name_url}/v2/evc/"
325
326
        response = api.get(url)
327
        expected_result = circuits
328
        self.assertEqual(json.loads(response.data), expected_result)
329
330
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
331
    def test_list_with_circuits_stored(self, storehouse_data_mock):
332
        """Test if list circuits return all circuits stored."""
333
        circuits = {"1": {"name": "circuit_1"}, "2": {"name": "circuit_2"}}
334
        storehouse_data_mock.return_value = circuits
335
336
        api = self.get_app_test_client(self.napp)
337
        url = f"{self.server_name_url}/v2/evc/"
338
339
        response = api.get(url)
340
        expected_result = circuits
341
        self.assertEqual(json.loads(response.data), expected_result)
342
343 View Code Duplication
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
344
    def test_list_with_archived_circuits_stored_1(self, storehouse_data_mock):
345
        """Test if list circuits return only circuits not archived."""
346
        circuits = {
347
            "1": {"name": "circuit_1"},
348
            "2": {"name": "circuit_2", "archived": True},
349
        }
350
        storehouse_data_mock.return_value = circuits
351
352
        api = self.get_app_test_client(self.napp)
353
        url = f"{self.server_name_url}/v2/evc/"
354
355
        response = api.get(url)
356
        expected_result = {"1": circuits["1"]}
357
        self.assertEqual(json.loads(response.data), expected_result)
358
359 View Code Duplication
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
360
    def test_list_with_archived_circuits_stored_2(self, storehouse_data_mock):
361
        """Test if list circuits return all circuits."""
362
        circuits = {
363
            "1": {"name": "circuit_1"},
364
            "2": {"name": "circuit_2", "archived": True},
365
        }
366
        storehouse_data_mock.return_value = circuits
367
368
        api = self.get_app_test_client(self.napp)
369
        url = f"{self.server_name_url}/v2/evc/?archived=True"
370
371
        response = api.get(url)
372
        expected_result = circuits
373
        self.assertEqual(json.loads(response.data), expected_result)
374
375 View Code Duplication
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
376
    def test_circuit_with_valid_id(self, storehouse_data_mock):
377
        """Test if get_circuit return the circuit attributes."""
378
        circuits = {"1": {"name": "circuit_1"}, "2": {"name": "circuit_2"}}
379
        storehouse_data_mock.return_value = circuits
380
381
        api = self.get_app_test_client(self.napp)
382
        url = f"{self.server_name_url}/v2/evc/1"
383
        response = api.get(url)
384
        expected_result = circuits["1"]
385
        self.assertEqual(json.loads(response.data), expected_result)
386
387 View Code Duplication
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
388
    def test_circuit_with_invalid_id(self, storehouse_data_mock):
389
        """Test if get_circuit return invalid circuit_id."""
390
        circuits = {"1": {"name": "circuit_1"}, "2": {"name": "circuit_2"}}
391
        storehouse_data_mock.return_value = circuits
392
393
        api = self.get_app_test_client(self.napp)
394
        url = f"{self.server_name_url}/v2/evc/3"
395
        response = api.get(url)
396
        expected_result = "circuit_id 3 not found"
397
        self.assertEqual(
398
            json.loads(response.data)["description"], expected_result
399
        )
400
401
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
402
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
403
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
404
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
405
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
406
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
407
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
408
    def test_create_a_circuit_case_1(self, *args):
409
        """Test create a new circuit."""
410
        # pylint: disable=too-many-locals
411
        (
412
            validate_mock,
413
            evc_as_dict_mock,
414
            save_evc_mock,
415
            uni_from_dict_mock,
416
            sched_add_mock,
417
            storehouse_data_mock,
418
            evc_deploy_mock,
419
        ) = args
420
421
        validate_mock.return_value = True
422
        save_evc_mock.return_value = True
423
        evc_deploy_mock.return_value = True
424
        uni1 = create_autospec(UNI)
425
        uni2 = create_autospec(UNI)
426
        uni1.interface = create_autospec(Interface)
427
        uni2.interface = create_autospec(Interface)
428
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
429
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
430
        uni_from_dict_mock.side_effect = [uni1, uni2]
431
        evc_as_dict_mock.return_value = {}
432
        sched_add_mock.return_value = True
433
        storehouse_data_mock.return_value = {}
434
435
        api = self.get_app_test_client(self.napp)
436
        url = f"{self.server_name_url}/v2/evc/"
437
        payload = {
438
            "name": "my evc1",
439
            "frequency": "* * * * *",
440
            "uni_a": {
441
                "interface_id": "00:00:00:00:00:00:00:01:1",
442
                "tag": {"tag_type": 1, "value": 80},
443
            },
444
            "uni_z": {
445
                "interface_id": "00:00:00:00:00:00:00:02:2",
446
                "tag": {"tag_type": 1, "value": 1},
447
            },
448
            "dynamic_backup_path": True,
449
        }
450
451
        response = api.post(
452
            url, data=json.dumps(payload), content_type="application/json"
453
        )
454
        current_data = json.loads(response.data)
455
456
        # verify expected result from request
457
        self.assertEqual(201, response.status_code, response.data)
458
        self.assertIn("circuit_id", current_data)
459
460
        # verify uni called
461
        uni_from_dict_mock.called_twice()
462
        uni_from_dict_mock.assert_any_call(payload["uni_z"])
463
        uni_from_dict_mock.assert_any_call(payload["uni_a"])
464
465
        # verify validation called
466
        validate_mock.assert_called_once()
467
        validate_mock.assert_called_with(
468
            frequency="* * * * *",
469
            name="my evc1",
470
            uni_a=uni1,
471
            uni_z=uni2,
472
            dynamic_backup_path=True,
473
        )
474
        # verify save method is called
475
        save_evc_mock.assert_called_once()
476
477
        # verify evc as dict is called to save in the box
478
        evc_as_dict_mock.assert_called_once()
479
        # verify add circuit in sched
480
        sched_add_mock.assert_called_once()
481
482
    @staticmethod
483
    def get_napp_urls(napp):
484
        """Return the kytos/mef_eline urls.
485
486
        The urls will be like:
487
488
        urls = [
489
            (options, methods, url)
490
        ]
491
492
        """
493
        controller = napp.controller
494
        controller.api_server.register_napp_endpoints(napp)
495
496
        urls = []
497
        for rule in controller.api_server.app.url_map.iter_rules():
498
            options = {}
499
            for arg in rule.arguments:
500
                options[arg] = f"[{0}]".format(arg)
501
502
            if f"{napp.username}/{napp.name}" in str(rule):
503
                urls.append((options, rule.methods, f"{str(rule)}"))
504
505
        return urls
506
507
    @staticmethod
508
    def get_app_test_client(napp):
509
        """Return a flask api test client."""
510
        napp.controller.api_server.register_napp_endpoints(napp)
511
        return napp.controller.api_server.app.test_client()
512
513
    def test_create_a_circuit_case_2(self):
514
        """Test create a new circuit trying to send request without a json."""
515
        api = self.get_app_test_client(self.napp)
516
        url = f"{self.server_name_url}/v2/evc/"
517
518
        response = api.post(url)
519
        current_data = json.loads(response.data)
520
        expected_message = "The request body mimetype is not application/json."
521
        expected_data = expected_message
522
        self.assertEqual(415, response.status_code, response.data)
523
        self.assertEqual(current_data["description"], expected_data)
524
525
    def test_create_a_circuit_case_3(self):
526
        """Test create a new circuit trying to send request with an
527
        invalid json."""
528
        api = self.get_app_test_client(self.napp)
529
        url = f"{self.server_name_url}/v2/evc/"
530
531
        response = api.post(
532
            url,
533
            data="This is an {Invalid:} JSON",
534
            content_type="application/json",
535
        )
536
        current_data = json.loads(response.data)
537
        expected_data = "The request body is not a well-formed JSON."
538
539
        self.assertEqual(400, response.status_code, response.data)
540
        self.assertEqual(current_data["description"], expected_data)
541
542
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
543
    def test_create_a_circuit_case_4(self, uni_from_dict_mock):
544
        """Test create a new circuit trying to send request with an
545
        invalid value."""
546
        # pylint: disable=too-many-locals
547
        uni_from_dict_mock.side_effect = ValueError("Could not instantiate")
548
        api = self.get_app_test_client(self.napp)
549
        url = f"{self.server_name_url}/v2/evc/"
550
551
        payload = {
552
            "name": "my evc1",
553
            "frequency": "* * * * *",
554
            "uni_a": {
555
                "interface_id": "00:00:00:00:00:00:00:01:76",
556
                "tag": {"tag_type": 1, "value": 80},
557
            },
558
            "uni_z": {
559
                "interface_id": "00:00:00:00:00:00:00:02:2",
560
                "tag": {"tag_type": 1, "value": 1},
561
            },
562
        }
563
564
        response = api.post(
565
            url, data=json.dumps(payload), content_type="application/json"
566
        )
567
        current_data = json.loads(response.data)
568
        expected_data = "Error creating UNI: Invalid value"
569
        self.assertEqual(400, response.status_code, response.data)
570
        self.assertEqual(current_data["description"], expected_data)
571
572
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
573
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
574
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
575
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
576
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
577
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
578
    def test_create_circuit_already_enabled(self, *args):
579
        """Test create an already created circuit."""
580
        # pylint: disable=too-many-locals
581
        (
582
            evc_as_dict_mock,
583
            validate_mock,
584
            save_evc_mock,
585
            uni_from_dict_mock,
586
            sched_add_mock,
587
            evc_deploy_mock,
588
        ) = args
589
590
        validate_mock.return_value = True
591
        save_evc_mock.return_value = True
592
        sched_add_mock.return_value = True
593
        evc_deploy_mock.return_value = True
594
        uni1 = create_autospec(UNI)
595
        uni2 = create_autospec(UNI)
596
        uni1.interface = create_autospec(Interface)
597
        uni2.interface = create_autospec(Interface)
598
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
599
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
600
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
601
602
        api = self.get_app_test_client(self.napp)
603
        payload = {
604
            "name": "my evc1",
605
            "uni_a": {
606
                "interface_id": "00:00:00:00:00:00:00:01:1",
607
                "tag": {"tag_type": 1, "value": 80},
608
            },
609
            "uni_z": {
610
                "interface_id": "00:00:00:00:00:00:00:02:2",
611
                "tag": {"tag_type": 1, "value": 1},
612
            },
613
            "dynamic_backup_path": True,
614
        }
615
616
        evc_as_dict_mock.return_value = payload
617
        response = api.post(
618
            f"{self.server_name_url}/v2/evc/",
619
            data=json.dumps(payload),
620
            content_type="application/json",
621
        )
622
        self.assertEqual(201, response.status_code)
623
624
        response = api.post(
625
            f"{self.server_name_url}/v2/evc/",
626
            data=json.dumps(payload),
627
            content_type="application/json",
628
        )
629
        current_data = json.loads(response.data)
630
        expected_data = "The EVC already exists."
631
        self.assertEqual(current_data["description"], expected_data)
632
        self.assertEqual(409, response.status_code)
633
634
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
635
    def test_create_circuit_case_5(self, uni_from_dict_mock):
636
        """Test when neither primary path nor dynamic_backup_path is set."""
637
        api = self.get_app_test_client(self.napp)
638
        url = f"{self.server_name_url}/v2/evc/"
639
        uni1 = create_autospec(UNI)
640
        uni2 = create_autospec(UNI)
641
        uni1.interface = create_autospec(Interface)
642
        uni2.interface = create_autospec(Interface)
643
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
644
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
645
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
646
647
        payload = {
648
            "name": "my evc1",
649
            "frequency": "* * * * *",
650
            "uni_a": {
651
                "interface_id": "00:00:00:00:00:00:00:01:1",
652
                "tag": {"tag_type": 1, "value": 80},
653
            },
654
            "uni_z": {
655
                "interface_id": "00:00:00:00:00:00:00:02:2",
656
                "tag": {"tag_type": 1, "value": 1},
657
            },
658
        }
659
660
        response = api.post(
661
            url, data=json.dumps(payload), content_type="application/json"
662
        )
663
        current_data = json.loads(response.data)
664
        expected_data = "The EVC must have a primary path "
665
        expected_data += "or allow dynamic paths."
666
        self.assertEqual(400, response.status_code, response.data)
667
        self.assertEqual(current_data["description"], expected_data)
668
669
    def test_redeploy_evc(self):
670
        """Test endpoint to redeploy an EVC."""
671
        evc1 = MagicMock()
672
        evc1.is_enabled.return_value = True
673
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
674
        api = self.get_app_test_client(self.napp)
675
        url = f"{self.server_name_url}/v2/evc/1/redeploy"
676
        response = api.patch(url)
677
        self.assertEqual(response.status_code, 202, response.data)
678
679
    def test_redeploy_evc_disabled(self):
680
        """Test endpoint to redeploy an EVC."""
681
        evc1 = MagicMock()
682
        evc1.is_enabled.return_value = False
683
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
684
        api = self.get_app_test_client(self.napp)
685
        url = f"{self.server_name_url}/v2/evc/1/redeploy"
686
        response = api.patch(url)
687
        self.assertEqual(response.status_code, 409, response.data)
688
689
    def test_redeploy_evc_deleted(self):
690
        """Test endpoint to redeploy an EVC."""
691
        evc1 = MagicMock()
692
        evc1.is_enabled.return_value = True
693
        self.napp.circuits = {"1": evc1, "2": MagicMock()}
694
        api = self.get_app_test_client(self.napp)
695
        url = f"{self.server_name_url}/v2/evc/3/redeploy"
696
        response = api.patch(url)
697
        self.assertEqual(response.status_code, 404, response.data)
698
699
    def test_list_schedules__no_data(self):
700
        """Test list of schedules."""
701
        api = self.get_app_test_client(self.napp)
702
        url = f"{self.server_name_url}/v2/evc/schedule"
703
        response = api.get(url)
704
        self.assertEqual(response.status_code, 200, response.data)
705
        self.assertEqual(json.loads(response.data.decode()), {})
706
707
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
708
    def test_list_schedules__no_data_stored(self, storehouse_data_mock):
709
        """Test if list circuits return all circuits stored."""
710
        circuits = {}
711
        storehouse_data_mock.return_value = circuits
712
713
        api = self.get_app_test_client(self.napp)
714
        url = f"{self.server_name_url}/v2/evc/schedule"
715
716
        response = api.get(url)
717
        expected_result = circuits
718
719
        self.assertEqual(response.status_code, 200, response.data)
720
        self.assertEqual(json.loads(response.data), expected_result)
721
722
    # pylint: disable=no-self-use
723
    def _add_storehouse_schedule_data(self, storehouse_data_mock):
724
        """Add schedule data to storehouse mock object."""
725
        circuits = {}
726
        payload_1 = {
727
            "id": "aa:aa:aa",
728
            "name": "my evc1",
729
            "uni_a": {
730
                "interface_id": "00:00:00:00:00:00:00:01:1",
731
                "tag": {"tag_type": 1, "value": 80},
732
            },
733
            "uni_z": {
734
                "interface_id": "00:00:00:00:00:00:00:02:2",
735
                "tag": {"tag_type": 1, "value": 1},
736
            },
737
            "circuit_scheduler": [
738
                {"id": "1", "frequency": "* * * * *", "action": "create"},
739
                {"id": "2", "frequency": "1 * * * *", "action": "remove"},
740
            ],
741
        }
742
        circuits.update({"aa:aa:aa": payload_1})
743
        payload_2 = {
744
            "id": "bb:bb:bb",
745
            "name": "my second evc2",
746
            "uni_a": {
747
                "interface_id": "00:00:00:00:00:00:00:01:2",
748
                "tag": {"tag_type": 1, "value": 90},
749
            },
750
            "uni_z": {
751
                "interface_id": "00:00:00:00:00:00:00:03:2",
752
                "tag": {"tag_type": 1, "value": 100},
753
            },
754
            "circuit_scheduler": [
755
                {"id": "3", "frequency": "1 * * * *", "action": "create"},
756
                {"id": "4", "frequency": "2 * * * *", "action": "remove"},
757
            ],
758
        }
759
        circuits.update({"bb:bb:bb": payload_2})
760
        payload_3 = {
761
            "id": "cc:cc:cc",
762
            "name": "my third evc3",
763
            "uni_a": {
764
                "interface_id": "00:00:00:00:00:00:00:03:1",
765
                "tag": {"tag_type": 1, "value": 90},
766
            },
767
            "uni_z": {
768
                "interface_id": "00:00:00:00:00:00:00:04:2",
769
                "tag": {"tag_type": 1, "value": 100},
770
            },
771
        }
772
        circuits.update({"cc:cc:cc": payload_3})
773
        # Add one circuit to the storehouse.
774
        storehouse_data_mock.return_value = circuits
775
776
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
777
    def test_list_schedules_from_storehouse(self, storehouse_data_mock):
778
        """Test if list circuits return specific circuits stored."""
779
        self._add_storehouse_schedule_data(storehouse_data_mock)
780
781
        api = self.get_app_test_client(self.napp)
782
        url = f"{self.server_name_url}/v2/evc/schedule"
783
784
        # Call URL
785
        response = api.get(url)
786
        # Expected JSON data from response
787
        expected = [
788
            {
789
                "circuit_id": "aa:aa:aa",
790
                "schedule": {
791
                    "action": "create",
792
                    "frequency": "* * * * *",
793
                    "id": "1",
794
                },
795
                "schedule_id": "1",
796
            },
797
            {
798
                "circuit_id": "aa:aa:aa",
799
                "schedule": {
800
                    "action": "remove",
801
                    "frequency": "1 * * * *",
802
                    "id": "2",
803
                },
804
                "schedule_id": "2",
805
            },
806
            {
807
                "circuit_id": "bb:bb:bb",
808
                "schedule": {
809
                    "action": "create",
810
                    "frequency": "1 * * * *",
811
                    "id": "3",
812
                },
813
                "schedule_id": "3",
814
            },
815
            {
816
                "circuit_id": "bb:bb:bb",
817
                "schedule": {
818
                    "action": "remove",
819
                    "frequency": "2 * * * *",
820
                    "id": "4",
821
                },
822
                "schedule_id": "4",
823
            },
824
        ]
825
826
        self.assertEqual(response.status_code, 200, response.data)
827
        self.assertEqual(expected, json.loads(response.data))
828
829
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
830
    def test_get_specific_schedule_from_storehouse(self, storehouse_data_mock):
831
        """Test get schedules from a circuit."""
832
        self._add_storehouse_schedule_data(storehouse_data_mock)
833
834
        requested_circuit_id = "bb:bb:bb"
835
        api = self.get_app_test_client(self.napp)
836
        url = f"{self.server_name_url}/v2/evc/{requested_circuit_id}"
837
838
        # Call URL
839
        response = api.get(url)
840
841
        # Expected JSON data from response
842
        expected = [
843
            {"action": "create", "frequency": "1 * * * *", "id": "3"},
844
            {"action": "remove", "frequency": "2 * * * *", "id": "4"},
845
        ]
846
847
        self.assertEqual(response.status_code, 200)
848
        self.assertEqual(
849
            expected, json.loads(response.data)["circuit_scheduler"]
850
        )
851
852
    def test_get_specific_schedules_from_storehouse_not_found(self):
853
        """Test get specific schedule ID that does not exist."""
854
        requested_id = "blah"
855
        api = self.get_app_test_client(self.napp)
856
        url = f"{self.server_name_url}/v2/evc/{requested_id}"
857
858
        # Call URL
859
        response = api.get(url)
860
861
        expected = "circuit_id blah not found"
862
        # Assert response not found
863
        self.assertEqual(response.status_code, 400, response.data)
864
        self.assertEqual(expected, json.loads(response.data)["description"])
865
866
    def _uni_from_dict_side_effect(self, uni_dict):
867
        interface_id = uni_dict.get("interface_id")
868
        tag_dict = uni_dict.get("tag")
869
        interface = Interface(interface_id, "0", "switch")
870
        return UNI(interface, tag_dict)
871
872
    @patch("apscheduler.schedulers.background.BackgroundScheduler.add_job")
873
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
874
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
875
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
876
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
877
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
878
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
879
    def test_create_schedule(self, *args):  # pylint: disable=too-many-locals
880
        """Test create a circuit schedule."""
881
        (
882
            validate_mock,
883
            evc_as_dict_mock,
884
            save_evc_mock,
885
            uni_from_dict_mock,
886
            sched_add_mock,
887
            storehouse_data_mock,
888
            scheduler_add_job_mock,
889
        ) = args
890
891
        validate_mock.return_value = True
892
        save_evc_mock.return_value = True
893
        uni_from_dict_mock.side_effect = self._uni_from_dict_side_effect
894
        evc_as_dict_mock.return_value = {}
895
        sched_add_mock.return_value = True
896
        storehouse_data_mock.return_value = {}
897
898
        self._add_storehouse_schedule_data(storehouse_data_mock)
899
900
        requested_id = "bb:bb:bb"
901
        api = self.get_app_test_client(self.napp)
902
        url = f"{self.server_name_url}/v2/evc/schedule/"
903
904
        payload = {
905
            "circuit_id": requested_id,
906
            "schedule": {"frequency": "1 * * * *", "action": "create"},
907
        }
908
909
        # Call URL
910
        response = api.post(
911
            url, data=json.dumps(payload), content_type="application/json"
912
        )
913
914
        response_json = json.loads(response.data)
915
916
        self.assertEqual(response.status_code, 201, response.data)
917
        scheduler_add_job_mock.assert_called_once()
918
        save_evc_mock.assert_called_once()
919
        self.assertEqual(
920
            payload["schedule"]["frequency"], response_json["frequency"]
921
        )
922
        self.assertEqual(
923
            payload["schedule"]["action"], response_json["action"]
924
        )
925
        self.assertIsNotNone(response_json["id"])
926
927
    @patch("apscheduler.schedulers.background.BackgroundScheduler.remove_job")
928
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
929
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
930
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
931
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
932
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
933
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
934
    def test_update_schedule(self, *args):  # pylint: disable=too-many-locals
935
        """Test create a circuit schedule."""
936
        (
937
            validate_mock,
938
            evc_as_dict_mock,
939
            save_evc_mock,
940
            uni_from_dict_mock,
941
            sched_add_mock,
942
            storehouse_data_mock,
943
            scheduler_remove_job_mock,
944
        ) = args
945
946
        storehouse_payload_1 = {
947
            "aa:aa:aa": {
948
                "id": "aa:aa:aa",
949
                "name": "my evc1",
950
                "uni_a": {
951
                    "interface_id": "00:00:00:00:00:00:00:01:1",
952
                    "tag": {"tag_type": 1, "value": 80},
953
                },
954
                "uni_z": {
955
                    "interface_id": "00:00:00:00:00:00:00:02:2",
956
                    "tag": {"tag_type": 1, "value": 1},
957
                },
958
                "circuit_scheduler": [
959
                    {"id": "1", "frequency": "* * * * *", "action": "create"}
960
                ],
961
            }
962
        }
963
964
        validate_mock.return_value = True
965
        save_evc_mock.return_value = True
966
        sched_add_mock.return_value = True
967
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
968
        evc_as_dict_mock.return_value = {}
969
        storehouse_data_mock.return_value = storehouse_payload_1
970
        scheduler_remove_job_mock.return_value = True
971
972
        requested_schedule_id = "1"
973
        api = self.get_app_test_client(self.napp)
974
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
975
976
        payload = {"frequency": "*/1 * * * *", "action": "create"}
977
978
        # Call URL
979
        response = api.patch(
980
            url, data=json.dumps(payload), content_type="application/json"
981
        )
982
983
        response_json = json.loads(response.data)
984
985
        self.assertEqual(response.status_code, 200, response.data)
986
        scheduler_remove_job_mock.assert_called_once()
987
        save_evc_mock.assert_called_once()
988
        self.assertEqual(payload["frequency"], response_json["frequency"])
989
        self.assertEqual(payload["action"], response_json["action"])
990
        self.assertIsNotNone(response_json["id"])
991
992
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
993
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
994
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
995
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
996
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
997
    def test_update_schedule_archived(self, *args):
998
        """Test create a circuit schedule."""
999
        # pylint: disable=too-many-locals
1000
        (
1001
            validate_mock,
1002
            evc_as_dict_mock,
1003
            uni_from_dict_mock,
1004
            sched_add_mock,
1005
            storehouse_data_mock,
1006
        ) = args
1007
1008
        storehouse_payload_1 = {
1009
            "aa:aa:aa": {
1010
                "id": "aa:aa:aa",
1011
                "name": "my evc1",
1012
                "archived": True,
1013
                "circuit_scheduler": [
1014
                    {"id": "1", "frequency": "* * * * *", "action": "create"}
1015
                ],
1016
            }
1017
        }
1018
1019
        validate_mock.return_value = True
1020
        sched_add_mock.return_value = True
1021
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1022
        evc_as_dict_mock.return_value = {}
1023
        storehouse_data_mock.return_value = storehouse_payload_1
1024
1025
        requested_schedule_id = "1"
1026
        api = self.get_app_test_client(self.napp)
1027
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1028
1029
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1030
1031
        # Call URL
1032
        response = api.patch(
1033
            url, data=json.dumps(payload), content_type="application/json"
1034
        )
1035
1036
        self.assertEqual(response.status_code, 403, response.data)
1037
1038
    @patch("apscheduler.schedulers.background.BackgroundScheduler.remove_job")
1039
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
1040
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1041
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1042
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1043
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1044
    def test_delete_schedule(self, *args):
1045
        """Test create a circuit schedule."""
1046
        (
1047
            validate_mock,
1048
            evc_as_dict_mock,
1049
            save_evc_mock,
1050
            uni_from_dict_mock,
1051
            storehouse_data_mock,
1052
            scheduler_remove_job_mock,
1053
        ) = args
1054
1055
        storehouse_payload_1 = {
1056
            "2": {
1057
                "id": "2",
1058
                "name": "my evc1",
1059
                "uni_a": {
1060
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1061
                    "tag": {"tag_type": 1, "value": 80},
1062
                },
1063
                "uni_z": {
1064
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1065
                    "tag": {"tag_type": 1, "value": 1},
1066
                },
1067
                "circuit_scheduler": [
1068
                    {"id": "1", "frequency": "* * * * *", "action": "create"}
1069
                ],
1070
            }
1071
        }
1072
        validate_mock.return_value = True
1073
        save_evc_mock.return_value = True
1074
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1075
        evc_as_dict_mock.return_value = {}
1076
        storehouse_data_mock.return_value = storehouse_payload_1
1077
        scheduler_remove_job_mock.return_value = True
1078
1079
        requested_schedule_id = "1"
1080
        api = self.get_app_test_client(self.napp)
1081
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1082
1083
        # Call URL
1084
        response = api.delete(url)
1085
1086
        self.assertEqual(response.status_code, 200, response.data)
1087
        scheduler_remove_job_mock.assert_called_once()
1088
        save_evc_mock.assert_called_once()
1089
        self.assertIn("Schedule removed", f"{response.data}")
1090
1091
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
1092
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1093
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1094
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1095
    def test_delete_schedule_archived(self, *args):
1096
        """Test create a circuit schedule."""
1097
        (
1098
            validate_mock,
1099
            evc_as_dict_mock,
1100
            uni_from_dict_mock,
1101
            storehouse_data_mock,
1102
        ) = args
1103
1104
        storehouse_payload_1 = {
1105
            "2": {
1106
                "id": "2",
1107
                "name": "my evc1",
1108
                "archived": True,
1109
                "circuit_scheduler": [
1110
                    {"id": "1", "frequency": "* * * * *", "action": "create"}
1111
                ],
1112
            }
1113
        }
1114
1115
        validate_mock.return_value = True
1116
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1117
        evc_as_dict_mock.return_value = {}
1118
        storehouse_data_mock.return_value = storehouse_payload_1
1119
1120
        requested_schedule_id = "1"
1121
        api = self.get_app_test_client(self.napp)
1122
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1123
1124
        # Call URL
1125
        response = api.delete(url)
1126
1127
        self.assertEqual(response.status_code, 403, response.data)
1128
1129
    @patch("requests.post")
1130
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1131
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1132
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1133
    @patch("kytos.core.Controller.get_interface_by_id")
1134
    @patch("napps.kytos.mef_eline.models.path.Path.is_valid")
1135
    @patch("napps.kytos.mef_eline.models.evc.EVCDeploy.deploy")
1136
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1137
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1138
    def test_update_circuit(self, *args):
1139
        """Test update a circuit circuit."""
1140
        # pylint: disable=too-many-locals,duplicate-code
1141
        (
1142
            evc_as_dict_mock,
1143
            uni_from_dict_mock,
1144
            evc_deploy,
1145
            *mocks,
1146
            requests_mock,
1147
        ) = args
1148
1149
        for mock in mocks:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable mocks does not seem to be defined.
Loading history...
1150
            mock.return_value = True
1151
        unis = [
1152
            get_uni_mocked(switch_dpid="00:00:00:00:00:00:00:01"),
1153
            get_uni_mocked(switch_dpid="00:00:00:00:00:00:00:02"),
1154
        ]
1155
        uni_from_dict_mock.side_effect = 2 * unis
1156
1157
        response = MagicMock()
1158
        response.status_code = 201
1159
        requests_mock.return_value = response
1160
1161
        api = self.get_app_test_client(self.napp)
1162
        payloads = [
1163
            {
1164
                "name": "my evc1",
1165
                "uni_a": {
1166
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1167
                    "tag": {"tag_type": 1, "value": 80},
1168
                },
1169
                "uni_z": {
1170
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1171
                    "tag": {"tag_type": 1, "value": 1},
1172
                },
1173
                "dynamic_backup_path": True,
1174
            },
1175
            {
1176
                "primary_path": [
1177
                    {
1178
                        "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1179
                        "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"},
1180
                    }
1181
                ]
1182
            },
1183
            {
1184
                "priority": 3
1185
            },
1186
            {
1187
                # It works only with 'enable' and not with 'enabled'
1188
                "enable": True
1189
            },
1190
            {
1191
                "name": "my evc1",
1192
                "active": True,
1193
                "enable": True,
1194
                "uni_a": {
1195
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1196
                    "tag": {
1197
                        "tag_type": 1,
1198
                        "value": 80
1199
                    }
1200
                },
1201
                "uni_z": {
1202
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1203
                    "tag": {
1204
                        "tag_type": 1,
1205
                        "value": 1
1206
                    }
1207
                },
1208
                "priority": 3,
1209
                "bandwidth": 1000,
1210
                "dynamic_backup_path": True
1211
            }
1212
        ]
1213
1214
        evc_as_dict_mock.return_value = payloads[0]
1215
        response = api.post(
1216
            f"{self.server_name_url}/v2/evc/",
1217
            data=json.dumps(payloads[0]),
1218
            content_type="application/json",
1219
        )
1220
        self.assertEqual(201, response.status_code)
1221
1222
        evc_deploy.reset_mock()
1223
        evc_as_dict_mock.return_value = payloads[1]
1224
        current_data = json.loads(response.data)
1225
        circuit_id = current_data["circuit_id"]
1226
        response = api.patch(
1227
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1228
            data=json.dumps(payloads[1]),
1229
            content_type="application/json",
1230
        )
1231
        # evc_deploy.assert_called_once()
1232
        self.assertEqual(200, response.status_code)
1233
1234
        evc_deploy.reset_mock()
1235
        evc_as_dict_mock.return_value = payloads[2]
1236
        response = api.patch(
1237
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1238
            data=json.dumps(payloads[2]),
1239
            content_type="application/json",
1240
        )
1241
        evc_deploy.assert_not_called()
1242
        self.assertEqual(200, response.status_code)
1243
1244
        evc_deploy.reset_mock()
1245
        evc_as_dict_mock.return_value = payloads[3]
1246
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1247
                             data=json.dumps(payloads[3]),
1248
                             content_type='application/json')
1249
        evc_deploy.assert_called_once()
1250
        self.assertEqual(200, response.status_code)
1251
1252
        evc_deploy.reset_mock()
1253
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1254
                             data='{"priority":5,}',
1255
                             content_type='application/json')
1256
        evc_deploy.assert_not_called()
1257
        self.assertEqual(400, response.status_code)
1258
1259
        evc_deploy.reset_mock()
1260
        response = api.patch(
1261
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1262
            data=json.dumps(payloads[3]),
1263
            content_type="application/json",
1264
        )
1265
        evc_deploy.assert_called_once()
1266
        self.assertEqual(200, response.status_code)
1267
1268
        response = api.patch(
1269
            f"{self.server_name_url}/v2/evc/1234",
1270
            data=json.dumps(payloads[1]),
1271
            content_type="application/json",
1272
        )
1273
        current_data = json.loads(response.data)
1274
        expected_data = "circuit_id 1234 not found"
1275
        self.assertEqual(current_data["description"], expected_data)
1276
        self.assertEqual(404, response.status_code)
1277
1278
        api.delete(f"{self.server_name_url}/v2/evc/{circuit_id}")
1279
        evc_deploy.reset_mock()
1280
        response = api.patch(
1281
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1282
            data=json.dumps(payloads[1]),
1283
            content_type="application/json",
1284
        )
1285
        evc_deploy.assert_not_called()
1286
        self.assertEqual(405, response.status_code)
1287
1288 View Code Duplication
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1289
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1290
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1291
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1292
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1293
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1294
    def test_update_circuit_invalid_json(self, *args):
1295
        """Test update a circuit circuit."""
1296
        # pylint: disable=too-many-locals
1297
        (
1298
            evc_as_dict_mock,
1299
            validate_mock,
1300
            save_evc_mock,
1301
            uni_from_dict_mock,
1302
            sched_add_mock,
1303
            evc_deploy_mock,
1304
        ) = args
1305
1306
        validate_mock.return_value = True
1307
        save_evc_mock.return_value = True
1308
        sched_add_mock.return_value = True
1309
        evc_deploy_mock.return_value = True
1310
        uni1 = create_autospec(UNI)
1311
        uni2 = create_autospec(UNI)
1312
        uni1.interface = create_autospec(Interface)
1313
        uni2.interface = create_autospec(Interface)
1314
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1315
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1316
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1317
1318
        api = self.get_app_test_client(self.napp)
1319
        payload1 = {
1320
            "name": "my evc1",
1321
            "uni_a": {
1322
                "interface_id": "00:00:00:00:00:00:00:01:1",
1323
                "tag": {"tag_type": 1, "value": 80},
1324
            },
1325
            "uni_z": {
1326
                "interface_id": "00:00:00:00:00:00:00:02:2",
1327
                "tag": {"tag_type": 1, "value": 1},
1328
            },
1329
            "dynamic_backup_path": True,
1330
        }
1331
1332
        payload2 = {
1333
            "dynamic_backup_path": False,
1334
        }
1335
1336
        evc_as_dict_mock.return_value = payload1
1337
        response = api.post(
1338
            f"{self.server_name_url}/v2/evc/",
1339
            data=json.dumps(payload1),
1340
            content_type="application/json",
1341
        )
1342
        self.assertEqual(201, response.status_code)
1343
1344
        evc_as_dict_mock.return_value = payload2
1345
        current_data = json.loads(response.data)
1346
        circuit_id = current_data["circuit_id"]
1347
        response = api.patch(
1348
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1349
            data=payload2,
1350
            content_type="application/json",
1351
        )
1352
        current_data = json.loads(response.data)
1353
        expected_data = "The request body is not a well-formed JSON."
1354
        self.assertEqual(current_data["description"], expected_data)
1355
        self.assertEqual(400, response.status_code)
1356
1357
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
1358
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1359
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1360
    @patch("napps.kytos.mef_eline.main.Main._link_from_dict")
1361
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1362
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1363
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1364
    @patch("napps.kytos.mef_eline.models.path.Path.is_valid")
1365
    def test_update_circuit_invalid_path(self, *args):
1366
        """Test update a circuit circuit."""
1367
        # pylint: disable=too-many-locals
1368
        (
1369
            is_valid_mock,
1370
            evc_as_dict_mock,
1371
            validate_mock,
1372
            save_evc_mock,
1373
            link_from_dict_mock,
1374
            uni_from_dict_mock,
1375
            sched_add_mock,
1376
            evc_deploy_mock,
1377
        ) = args
1378
1379
        is_valid_mock.side_effect = InvalidPath("error")
1380
        validate_mock.return_value = True
1381
        save_evc_mock.return_value = True
1382
        sched_add_mock.return_value = True
1383
        evc_deploy_mock.return_value = True
1384
        link_from_dict_mock.return_value = 1
1385
        uni1 = create_autospec(UNI)
1386
        uni2 = create_autospec(UNI)
1387
        uni1.interface = create_autospec(Interface)
1388
        uni2.interface = create_autospec(Interface)
1389
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1390
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1391
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1392
1393
        api = self.get_app_test_client(self.napp)
1394
        payload1 = {
1395
            "name": "my evc1",
1396
            "uni_a": {
1397
                "interface_id": "00:00:00:00:00:00:00:01:1",
1398
                "tag": {"tag_type": 1, "value": 80},
1399
            },
1400
            "uni_z": {
1401
                "interface_id": "00:00:00:00:00:00:00:02:2",
1402
                "tag": {"tag_type": 1, "value": 1},
1403
            },
1404
            "dynamic_backup_path": True,
1405
        }
1406
1407
        payload2 = {
1408
            "primary_path": [
1409
                {
1410
                    "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1411
                    "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"},
1412
                }
1413
            ]
1414
        }
1415
1416
        evc_as_dict_mock.return_value = payload1
1417
        response = api.post(
1418
            f"{self.server_name_url}/v2/evc/",
1419
            data=json.dumps(payload1),
1420
            content_type="application/json",
1421
        )
1422
        self.assertEqual(201, response.status_code)
1423
1424
        evc_as_dict_mock.return_value = payload2
1425
        current_data = json.loads(response.data)
1426
        circuit_id = current_data["circuit_id"]
1427
        response = api.patch(
1428
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1429
            data=json.dumps(payload2),
1430
            content_type="application/json",
1431
        )
1432
        current_data = json.loads(response.data)
1433
        expected_data = "primary_path is not a valid path: error"
1434
        self.assertEqual(400, response.status_code)
1435
        self.assertEqual(current_data["description"], expected_data)
1436
1437 View Code Duplication
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1438
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1439
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1440
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1441
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1442
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1443
    def test_update_evc_no_json_mime(self, *args):
1444
        """Test update a circuit with wrong mimetype."""
1445
        # pylint: disable=too-many-locals
1446
        (
1447
            evc_as_dict_mock,
1448
            validate_mock,
1449
            save_evc_mock,
1450
            uni_from_dict_mock,
1451
            sched_add_mock,
1452
            evc_deploy_mock,
1453
        ) = args
1454
1455
        validate_mock.return_value = True
1456
        save_evc_mock.return_value = True
1457
        sched_add_mock.return_value = True
1458
        evc_deploy_mock.return_value = True
1459
        uni1 = create_autospec(UNI)
1460
        uni2 = create_autospec(UNI)
1461
        uni1.interface = create_autospec(Interface)
1462
        uni2.interface = create_autospec(Interface)
1463
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1464
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1465
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1466
1467
        api = self.get_app_test_client(self.napp)
1468
        payload1 = {
1469
            "name": "my evc1",
1470
            "uni_a": {
1471
                "interface_id": "00:00:00:00:00:00:00:01:1",
1472
                "tag": {"tag_type": 1, "value": 80},
1473
            },
1474
            "uni_z": {
1475
                "interface_id": "00:00:00:00:00:00:00:02:2",
1476
                "tag": {"tag_type": 1, "value": 1},
1477
            },
1478
            "dynamic_backup_path": True,
1479
        }
1480
1481
        payload2 = {"dynamic_backup_path": False}
1482
1483
        evc_as_dict_mock.return_value = payload1
1484
        response = api.post(
1485
            f"{self.server_name_url}/v2/evc/",
1486
            data=json.dumps(payload1),
1487
            content_type="application/json",
1488
        )
1489
        self.assertEqual(201, response.status_code)
1490
1491
        evc_as_dict_mock.return_value = payload2
1492
        current_data = json.loads(response.data)
1493
        circuit_id = current_data["circuit_id"]
1494
        response = api.patch(
1495
            f"{self.server_name_url}/v2/evc/{circuit_id}", data=payload2
1496
        )
1497
        current_data = json.loads(response.data)
1498
        expected_data = "The request body mimetype is not application/json."
1499
        self.assertEqual(current_data["description"], expected_data)
1500
        self.assertEqual(415, response.status_code)
1501
1502
    def test_delete_no_evc(self):
1503
        """Test delete when EVC does not exist."""
1504
        api = self.get_app_test_client(self.napp)
1505
        response = api.delete(f"{self.server_name_url}/v2/evc/123")
1506
        current_data = json.loads(response.data)
1507
        expected_data = "circuit_id 123 not found"
1508
        self.assertEqual(current_data["description"], expected_data)
1509
        self.assertEqual(404, response.status_code)
1510
1511
    def test_handle_link_up(self):
1512
        """Test handle_link_up method."""
1513
        evc_mock = create_autospec(EVC)
1514
        evc_mock.is_enabled = MagicMock(side_effect=[True, False, True])
1515
        evc_mock.lock = MagicMock()
1516
        type(evc_mock).archived = PropertyMock(
1517
            side_effect=[True, False, False]
1518
        )
1519
        evcs = [evc_mock, evc_mock, evc_mock]
1520
        event = KytosEvent(name="test", content={"link": "abc"})
1521
        self.napp.circuits = dict(zip(["1", "2", "3"], evcs))
1522
        self.napp.handle_link_up(event)
1523
        evc_mock.handle_link_up.assert_called_once_with("abc")
1524
1525
    def test_handle_link_down(self):
1526
        """Test handle_link_down method."""
1527
        evc_mock = create_autospec(EVC)
1528
        evc_mock.is_affected_by_link = MagicMock(
1529
            side_effect=[True, False, True]
1530
        )
1531
        evc_mock.lock = MagicMock()
1532
        evc_mock.handle_link_down = MagicMock(side_effect=[True, True])
1533
        evcs = [evc_mock, evc_mock, evc_mock]
1534
        event = KytosEvent(name="test", content={"link": "abc"})
1535
        self.napp.circuits = dict(zip(["1", "2", "3"], evcs))
1536
        self.napp.handle_link_down(event)
1537
        evc_mock.handle_link_down.assert_has_calls([call(), call()])
1538
1539
    def test_add_metadata(self):
1540
        """Test method to add metadata"""
1541
        evc_mock = create_autospec(EVC)
1542
        evc_mock.metadata = {}
1543
        evc_mock.id = 1234
1544
        self.napp.circuits = {"1234": evc_mock}
1545
1546
        api = self.get_app_test_client(self.napp)
1547
        payload = {"metadata1": 1, "metadata2": 2}
1548
        response = api.post(
1549
            f"{self.server_name_url}/v2/evc/1234/metadata",
1550
            data=json.dumps(payload),
1551
            content_type="application/json",
1552
        )
1553
1554
        self.assertEqual(response.status_code, 201)
1555
        evc_mock.extend_metadata.assert_called_with(payload)
1556