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

TestMain.test_delete_archived_evc()   B

Complexity

Conditions 1

Size

Total Lines 69
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 56
nop 2
dl 0
loc 69
rs 8.44
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, 404, 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
        # Case 2: there is no schedule
928
        payload = {
929
              "circuit_id": "cc:cc:cc",
930
              "schedule": {
931
                "frequency": "1 * * * *",
932
                "action": "create"
933
              }
934
            }
935
        response = api.post(url, data=json.dumps(payload),
936
                            content_type='application/json')
937
        self.assertEqual(response.status_code, 201)
938
939
    def test_create_schedule_invalid_request(self):
940
        """Test create schedule API with invalid request."""
941
        evc1 = MagicMock()
942
        self.napp.circuits = {'bb:bb:bb': evc1}
943
        api = self.get_app_test_client(self.napp)
944
        url = f'{self.server_name_url}/v2/evc/schedule/'
945
946
        # case 1: empty post
947
        response = api.post(url, data="")
948
        self.assertEqual(response.status_code, 415)
949
950
        # case 2: content-type not specified
951
        payload = {
952
            "circuit_id": "bb:bb:bb",
953
            "schedule": {
954
                "frequency": "1 * * * *",
955
                "action": "create"
956
            }
957
        }
958
        response = api.post(url, data=json.dumps(payload))
959
        self.assertEqual(response.status_code, 415)
960
961
        # case 3: not a dictionary
962
        payload = []
963
        response = api.post(url, data=json.dumps(payload),
964
                            content_type='application/json')
965
        self.assertEqual(response.status_code, 400)
966
967
        # case 4: missing circuit id
968
        payload = {
969
            "schedule": {
970
                "frequency": "1 * * * *",
971
                "action": "create"
972
            }
973
        }
974
        response = api.post(url, data=json.dumps(payload),
975
                            content_type='application/json')
976
        self.assertEqual(response.status_code, 400)
977
978
        # case 5: missing schedule
979
        payload = {
980
            "circuit_id": "bb:bb:bb"
981
        }
982
        response = api.post(url, data=json.dumps(payload),
983
                            content_type='application/json')
984
        self.assertEqual(response.status_code, 400)
985
986
        # case 6: invalid circuit
987
        payload = {
988
            "circuit_id": "xx:xx:xx",
989
            "schedule": {
990
                "frequency": "1 * * * *",
991
                "action": "create"
992
            }
993
        }
994
        response = api.post(url, data=json.dumps(payload),
995
                            content_type='application/json')
996
        self.assertEqual(response.status_code, 404)
997
998
        # case 7: archived or deleted evc
999
        evc1.archived.return_value = True
1000
        payload = {
1001
            "circuit_id": "bb:bb:bb",
1002
            "schedule": {
1003
                "frequency": "1 * * * *",
1004
                "action": "create"
1005
            }
1006
        }
1007
        response = api.post(url, data=json.dumps(payload),
1008
                            content_type='application/json')
1009
        self.assertEqual(response.status_code, 403)
1010
1011
    @patch('apscheduler.schedulers.background.BackgroundScheduler.remove_job')
1012
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
1013
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1014
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1015
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
1016
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1017
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1018
    def test_update_schedule(self, *args):  # pylint: disable=too-many-locals
1019
        """Test create a circuit schedule."""
1020
        (
1021
            validate_mock,
1022
            evc_as_dict_mock,
1023
            save_evc_mock,
1024
            uni_from_dict_mock,
1025
            sched_add_mock,
1026
            storehouse_data_mock,
1027
            scheduler_remove_job_mock,
1028
        ) = args
1029
1030
        storehouse_payload_1 = {
1031
            "aa:aa:aa": {
1032
                "id": "aa:aa:aa",
1033
                "name": "my evc1",
1034
                "uni_a": {
1035
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1036
                    "tag": {"tag_type": 1, "value": 80},
1037
                },
1038
                "uni_z": {
1039
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1040
                    "tag": {"tag_type": 1, "value": 1},
1041
                },
1042
                "circuit_scheduler": [
1043
                    {"id": "1", "frequency": "* * * * *", "action": "create"}
1044
                ],
1045
            }
1046
        }
1047
1048
        validate_mock.return_value = True
1049
        save_evc_mock.return_value = True
1050
        sched_add_mock.return_value = True
1051
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1052
        evc_as_dict_mock.return_value = {}
1053
        storehouse_data_mock.return_value = storehouse_payload_1
1054
        scheduler_remove_job_mock.return_value = True
1055
1056
        requested_schedule_id = "1"
1057
        api = self.get_app_test_client(self.napp)
1058
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1059
1060
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1061
1062
        # Call URL
1063
        response = api.patch(
1064
            url, data=json.dumps(payload), content_type="application/json"
1065
        )
1066
1067
        response_json = json.loads(response.data)
1068
1069
        self.assertEqual(response.status_code, 200, response.data)
1070
        scheduler_remove_job_mock.assert_called_once()
1071
        save_evc_mock.assert_called_once()
1072
        self.assertEqual(payload["frequency"], response_json["frequency"])
1073
        self.assertEqual(payload["action"], response_json["action"])
1074
        self.assertIsNotNone(response_json["id"])
1075
1076
    @patch('napps.kytos.mef_eline.main.Main._find_evc_by_schedule_id')
1077
    def test_update_no_schedule(self, find_evc_by_schedule_id_mock):
1078
        """Test update a circuit schedule."""
1079
        api = self.get_app_test_client(self.napp)
1080
        url = f"{self.server_name_url}/v2/evc/schedule/1"
1081
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1082
1083
        find_evc_by_schedule_id_mock.return_value = None, None
1084
1085
        response = api.patch(
1086
            url, data=json.dumps(payload), content_type="application/json"
1087
        )
1088
1089
        self.assertEqual(response.status_code, 404)
1090
1091
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
1092
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1093
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1094
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1095
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1096
    def test_update_schedule_archived(self, *args):
1097
        """Test create a circuit schedule."""
1098
        # pylint: disable=too-many-locals
1099
        (
1100
            validate_mock,
1101
            evc_as_dict_mock,
1102
            uni_from_dict_mock,
1103
            sched_add_mock,
1104
            storehouse_data_mock,
1105
        ) = args
1106
1107
        storehouse_payload_1 = {
1108
            "aa:aa:aa": {
1109
                "id": "aa:aa:aa",
1110
                "name": "my evc1",
1111
                "archived": True,
1112
                "circuit_scheduler": [
1113
                    {"id": "1", "frequency": "* * * * *", "action": "create"}
1114
                ],
1115
            }
1116
        }
1117
1118
        validate_mock.return_value = True
1119
        sched_add_mock.return_value = True
1120
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1121
        evc_as_dict_mock.return_value = {}
1122
        storehouse_data_mock.return_value = storehouse_payload_1
1123
1124
        requested_schedule_id = "1"
1125
        api = self.get_app_test_client(self.napp)
1126
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1127
1128
        payload = {"frequency": "*/1 * * * *", "action": "create"}
1129
1130
        # Call URL
1131
        response = api.patch(
1132
            url, data=json.dumps(payload), content_type="application/json"
1133
        )
1134
1135
        self.assertEqual(response.status_code, 403, response.data)
1136
1137
    @patch("apscheduler.schedulers.background.BackgroundScheduler.remove_job")
1138
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
1139
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1140
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1141
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1142
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1143
    def test_delete_schedule(self, *args):
1144
        """Test create a circuit schedule."""
1145
        (
1146
            validate_mock,
1147
            evc_as_dict_mock,
1148
            save_evc_mock,
1149
            uni_from_dict_mock,
1150
            storehouse_data_mock,
1151
            scheduler_remove_job_mock,
1152
        ) = args
1153
1154
        storehouse_payload_1 = {
1155
            "2": {
1156
                "id": "2",
1157
                "name": "my evc1",
1158
                "uni_a": {
1159
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1160
                    "tag": {"tag_type": 1, "value": 80},
1161
                },
1162
                "uni_z": {
1163
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1164
                    "tag": {"tag_type": 1, "value": 1},
1165
                },
1166
                "circuit_scheduler": [
1167
                    {"id": "1", "frequency": "* * * * *", "action": "create"}
1168
                ],
1169
            }
1170
        }
1171
        validate_mock.return_value = True
1172
        save_evc_mock.return_value = True
1173
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1174
        evc_as_dict_mock.return_value = {}
1175
        storehouse_data_mock.return_value = storehouse_payload_1
1176
        scheduler_remove_job_mock.return_value = True
1177
1178
        requested_schedule_id = "1"
1179
        api = self.get_app_test_client(self.napp)
1180
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1181
1182
        # Call URL
1183
        response = api.delete(url)
1184
1185
        self.assertEqual(response.status_code, 200, response.data)
1186
        scheduler_remove_job_mock.assert_called_once()
1187
        save_evc_mock.assert_called_once()
1188
        self.assertIn("Schedule removed", f"{response.data}")
1189
1190
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.get_data")
1191
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1192
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1193
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1194
    def test_delete_schedule_archived(self, *args):
1195
        """Test create a circuit schedule."""
1196
        (
1197
            validate_mock,
1198
            evc_as_dict_mock,
1199
            uni_from_dict_mock,
1200
            storehouse_data_mock,
1201
        ) = args
1202
1203
        storehouse_payload_1 = {
1204
            "2": {
1205
                "id": "2",
1206
                "name": "my evc1",
1207
                "archived": True,
1208
                "circuit_scheduler": [
1209
                    {"id": "1", "frequency": "* * * * *", "action": "create"}
1210
                ],
1211
            }
1212
        }
1213
1214
        validate_mock.return_value = True
1215
        uni_from_dict_mock.side_effect = ["uni_a", "uni_z"]
1216
        evc_as_dict_mock.return_value = {}
1217
        storehouse_data_mock.return_value = storehouse_payload_1
1218
1219
        requested_schedule_id = "1"
1220
        api = self.get_app_test_client(self.napp)
1221
        url = f"{self.server_name_url}/v2/evc/schedule/{requested_schedule_id}"
1222
1223
        # Call URL
1224
        response = api.delete(url)
1225
1226
        self.assertEqual(response.status_code, 403, response.data)
1227
1228
    @patch('napps.kytos.mef_eline.main.Main._find_evc_by_schedule_id')
1229
    def test_delete_schedule_not_found(self, mock_find_evc_by_sched):
1230
        """Test delete a circuit schedule - unexisting."""
1231
        mock_find_evc_by_sched.return_value = (None, False)
1232
        api = self.get_app_test_client(self.napp)
1233
        url = f'{self.server_name_url}/v2/evc/schedule/1'
1234
        response = api.delete(url)
1235
        self.assertEqual(response.status_code, 404)
1236
1237
    def test_get_circuit_not_found(self):
1238
        """Test /v2/evc/<circuit_id> 404."""
1239
        api = self.get_app_test_client(self.napp)
1240
        url = f'{self.server_name_url}/v2/evc/1234'
1241
        response = api.get(url)
1242
        self.assertEqual(response.status_code, 404)
1243
1244
    @patch('requests.post')
1245
    @patch('napps.kytos.mef_eline.scheduler.Scheduler.add')
1246
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.save_evc')
1247
    @patch('napps.kytos.mef_eline.models.evc.EVC._validate')
1248
    @patch('kytos.core.Controller.get_interface_by_id')
1249
    @patch('napps.kytos.mef_eline.models.path.Path.is_valid')
1250
    @patch('napps.kytos.mef_eline.models.evc.EVCDeploy.deploy')
1251
    @patch('napps.kytos.mef_eline.main.Main._uni_from_dict')
1252
    @patch('napps.kytos.mef_eline.main.EVC.as_dict')
1253
    def test_update_circuit(self, *args):
1254
        """Test update a circuit circuit."""
1255
        # pylint: disable=too-many-locals,duplicate-code
1256
        (
1257
            evc_as_dict_mock,
1258
            uni_from_dict_mock,
1259
            evc_deploy,
1260
            *mocks,
1261
            requests_mock,
1262
        ) = args
1263
1264
        for mock in mocks:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable mocks does not seem to be defined.
Loading history...
1265
            mock.return_value = True
1266
        unis = [
1267
            get_uni_mocked(switch_dpid="00:00:00:00:00:00:00:01"),
1268
            get_uni_mocked(switch_dpid="00:00:00:00:00:00:00:02"),
1269
        ]
1270
        uni_from_dict_mock.side_effect = 2 * unis
1271
1272
        response = MagicMock()
1273
        response.status_code = 201
1274
        requests_mock.return_value = response
1275
1276
        api = self.get_app_test_client(self.napp)
1277
        payloads = [
1278
            {
1279
                "name": "my evc1",
1280
                "uni_a": {
1281
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1282
                    "tag": {"tag_type": 1, "value": 80},
1283
                },
1284
                "uni_z": {
1285
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1286
                    "tag": {"tag_type": 1, "value": 1},
1287
                },
1288
                "dynamic_backup_path": True,
1289
            },
1290
            {
1291
                "primary_path": [
1292
                    {
1293
                        "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1294
                        "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"},
1295
                    }
1296
                ]
1297
            },
1298
            {
1299
                "priority": 3
1300
            },
1301
            {
1302
                # It works only with 'enable' and not with 'enabled'
1303
                "enable": True
1304
            },
1305
            {
1306
                "name": "my evc1",
1307
                "active": True,
1308
                "enable": True,
1309
                "uni_a": {
1310
                    "interface_id": "00:00:00:00:00:00:00:01:1",
1311
                    "tag": {
1312
                        "tag_type": 1,
1313
                        "value": 80
1314
                    }
1315
                },
1316
                "uni_z": {
1317
                    "interface_id": "00:00:00:00:00:00:00:02:2",
1318
                    "tag": {
1319
                        "tag_type": 1,
1320
                        "value": 1
1321
                    }
1322
                },
1323
                "priority": 3,
1324
                "bandwidth": 1000,
1325
                "dynamic_backup_path": True
1326
            }
1327
        ]
1328
1329
        evc_as_dict_mock.return_value = payloads[0]
1330
        response = api.post(
1331
            f"{self.server_name_url}/v2/evc/",
1332
            data=json.dumps(payloads[0]),
1333
            content_type="application/json",
1334
        )
1335
        self.assertEqual(201, response.status_code)
1336
1337
        evc_deploy.reset_mock()
1338
        evc_as_dict_mock.return_value = payloads[1]
1339
        current_data = json.loads(response.data)
1340
        circuit_id = current_data["circuit_id"]
1341
        response = api.patch(
1342
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1343
            data=json.dumps(payloads[1]),
1344
            content_type="application/json",
1345
        )
1346
        # evc_deploy.assert_called_once()
1347
        self.assertEqual(200, response.status_code)
1348
1349
        evc_deploy.reset_mock()
1350
        evc_as_dict_mock.return_value = payloads[2]
1351
        response = api.patch(
1352
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1353
            data=json.dumps(payloads[2]),
1354
            content_type="application/json",
1355
        )
1356
        evc_deploy.assert_not_called()
1357
        self.assertEqual(200, response.status_code)
1358
1359
        evc_deploy.reset_mock()
1360
        evc_as_dict_mock.return_value = payloads[3]
1361
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1362
                             data=json.dumps(payloads[3]),
1363
                             content_type='application/json')
1364
        evc_deploy.assert_called_once()
1365
        self.assertEqual(200, response.status_code)
1366
1367
        evc_deploy.reset_mock()
1368
        response = api.patch(f'{self.server_name_url}/v2/evc/{circuit_id}',
1369
                             data='{"priority":5,}',
1370
                             content_type='application/json')
1371
        evc_deploy.assert_not_called()
1372
        self.assertEqual(400, response.status_code)
1373
1374
        evc_deploy.reset_mock()
1375
        response = api.patch(
1376
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1377
            data=json.dumps(payloads[3]),
1378
            content_type="application/json",
1379
        )
1380
        evc_deploy.assert_called_once()
1381
        self.assertEqual(200, response.status_code)
1382
1383
        response = api.patch(
1384
            f"{self.server_name_url}/v2/evc/1234",
1385
            data=json.dumps(payloads[1]),
1386
            content_type="application/json",
1387
        )
1388
        current_data = json.loads(response.data)
1389
        expected_data = "circuit_id 1234 not found"
1390
        self.assertEqual(current_data["description"], expected_data)
1391
        self.assertEqual(404, response.status_code)
1392
1393
        api.delete(f"{self.server_name_url}/v2/evc/{circuit_id}")
1394
        evc_deploy.reset_mock()
1395
        response = api.patch(
1396
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1397
            data=json.dumps(payloads[1]),
1398
            content_type="application/json",
1399
        )
1400
        evc_deploy.assert_not_called()
1401
        self.assertEqual(405, response.status_code)
1402
1403 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...
1404
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1405
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1406
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1407
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1408
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1409
    def test_update_circuit_invalid_json(self, *args):
1410
        """Test update a circuit circuit."""
1411
        # pylint: disable=too-many-locals
1412
        (
1413
            evc_as_dict_mock,
1414
            validate_mock,
1415
            save_evc_mock,
1416
            uni_from_dict_mock,
1417
            sched_add_mock,
1418
            evc_deploy_mock,
1419
        ) = args
1420
1421
        validate_mock.return_value = True
1422
        save_evc_mock.return_value = True
1423
        sched_add_mock.return_value = True
1424
        evc_deploy_mock.return_value = True
1425
        uni1 = create_autospec(UNI)
1426
        uni2 = create_autospec(UNI)
1427
        uni1.interface = create_autospec(Interface)
1428
        uni2.interface = create_autospec(Interface)
1429
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1430
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1431
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1432
1433
        api = self.get_app_test_client(self.napp)
1434
        payload1 = {
1435
            "name": "my evc1",
1436
            "uni_a": {
1437
                "interface_id": "00:00:00:00:00:00:00:01:1",
1438
                "tag": {"tag_type": 1, "value": 80},
1439
            },
1440
            "uni_z": {
1441
                "interface_id": "00:00:00:00:00:00:00:02:2",
1442
                "tag": {"tag_type": 1, "value": 1},
1443
            },
1444
            "dynamic_backup_path": True,
1445
        }
1446
1447
        payload2 = {
1448
            "dynamic_backup_path": False,
1449
        }
1450
1451
        evc_as_dict_mock.return_value = payload1
1452
        response = api.post(
1453
            f"{self.server_name_url}/v2/evc/",
1454
            data=json.dumps(payload1),
1455
            content_type="application/json",
1456
        )
1457
        self.assertEqual(201, response.status_code)
1458
1459
        evc_as_dict_mock.return_value = payload2
1460
        current_data = json.loads(response.data)
1461
        circuit_id = current_data["circuit_id"]
1462
        response = api.patch(
1463
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1464
            data=payload2,
1465
            content_type="application/json",
1466
        )
1467
        current_data = json.loads(response.data)
1468
        expected_data = "The request body is not a well-formed JSON."
1469
        self.assertEqual(current_data["description"], expected_data)
1470
        self.assertEqual(400, response.status_code)
1471
1472
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
1473
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1474
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1475
    @patch("napps.kytos.mef_eline.main.Main._link_from_dict")
1476
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1477
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1478
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1479
    @patch("napps.kytos.mef_eline.models.path.Path.is_valid")
1480
    def test_update_circuit_invalid_path(self, *args):
1481
        """Test update a circuit circuit."""
1482
        # pylint: disable=too-many-locals
1483
        (
1484
            is_valid_mock,
1485
            evc_as_dict_mock,
1486
            validate_mock,
1487
            save_evc_mock,
1488
            link_from_dict_mock,
1489
            uni_from_dict_mock,
1490
            sched_add_mock,
1491
            evc_deploy_mock,
1492
        ) = args
1493
1494
        is_valid_mock.side_effect = InvalidPath("error")
1495
        validate_mock.return_value = True
1496
        save_evc_mock.return_value = True
1497
        sched_add_mock.return_value = True
1498
        evc_deploy_mock.return_value = True
1499
        link_from_dict_mock.return_value = 1
1500
        uni1 = create_autospec(UNI)
1501
        uni2 = create_autospec(UNI)
1502
        uni1.interface = create_autospec(Interface)
1503
        uni2.interface = create_autospec(Interface)
1504
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1505
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1506
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1507
1508
        api = self.get_app_test_client(self.napp)
1509
        payload1 = {
1510
            "name": "my evc1",
1511
            "uni_a": {
1512
                "interface_id": "00:00:00:00:00:00:00:01:1",
1513
                "tag": {"tag_type": 1, "value": 80},
1514
            },
1515
            "uni_z": {
1516
                "interface_id": "00:00:00:00:00:00:00:02:2",
1517
                "tag": {"tag_type": 1, "value": 1},
1518
            },
1519
            "dynamic_backup_path": True,
1520
        }
1521
1522
        payload2 = {
1523
            "primary_path": [
1524
                {
1525
                    "endpoint_a": {"id": "00:00:00:00:00:00:00:01:1"},
1526
                    "endpoint_b": {"id": "00:00:00:00:00:00:00:02:2"},
1527
                }
1528
            ]
1529
        }
1530
1531
        evc_as_dict_mock.return_value = payload1
1532
        response = api.post(
1533
            f"{self.server_name_url}/v2/evc/",
1534
            data=json.dumps(payload1),
1535
            content_type="application/json",
1536
        )
1537
        self.assertEqual(201, response.status_code)
1538
1539
        evc_as_dict_mock.return_value = payload2
1540
        current_data = json.loads(response.data)
1541
        circuit_id = current_data["circuit_id"]
1542
        response = api.patch(
1543
            f"{self.server_name_url}/v2/evc/{circuit_id}",
1544
            data=json.dumps(payload2),
1545
            content_type="application/json",
1546
        )
1547
        current_data = json.loads(response.data)
1548
        expected_data = "primary_path is not a valid path: error"
1549
        self.assertEqual(400, response.status_code)
1550
        self.assertEqual(current_data["description"], expected_data)
1551
1552 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...
1553
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1554
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1555
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1556
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1557
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1558
    def test_update_evc_no_json_mime(self, *args):
1559
        """Test update a circuit with wrong mimetype."""
1560
        # pylint: disable=too-many-locals
1561
        (
1562
            evc_as_dict_mock,
1563
            validate_mock,
1564
            save_evc_mock,
1565
            uni_from_dict_mock,
1566
            sched_add_mock,
1567
            evc_deploy_mock,
1568
        ) = args
1569
1570
        validate_mock.return_value = True
1571
        save_evc_mock.return_value = True
1572
        sched_add_mock.return_value = True
1573
        evc_deploy_mock.return_value = True
1574
        uni1 = create_autospec(UNI)
1575
        uni2 = create_autospec(UNI)
1576
        uni1.interface = create_autospec(Interface)
1577
        uni2.interface = create_autospec(Interface)
1578
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1579
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1580
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1581
1582
        api = self.get_app_test_client(self.napp)
1583
        payload1 = {
1584
            "name": "my evc1",
1585
            "uni_a": {
1586
                "interface_id": "00:00:00:00:00:00:00:01:1",
1587
                "tag": {"tag_type": 1, "value": 80},
1588
            },
1589
            "uni_z": {
1590
                "interface_id": "00:00:00:00:00:00:00:02:2",
1591
                "tag": {"tag_type": 1, "value": 1},
1592
            },
1593
            "dynamic_backup_path": True,
1594
        }
1595
1596
        payload2 = {"dynamic_backup_path": False}
1597
1598
        evc_as_dict_mock.return_value = payload1
1599
        response = api.post(
1600
            f"{self.server_name_url}/v2/evc/",
1601
            data=json.dumps(payload1),
1602
            content_type="application/json",
1603
        )
1604
        self.assertEqual(201, response.status_code)
1605
1606
        evc_as_dict_mock.return_value = payload2
1607
        current_data = json.loads(response.data)
1608
        circuit_id = current_data["circuit_id"]
1609
        response = api.patch(
1610
            f"{self.server_name_url}/v2/evc/{circuit_id}", data=payload2
1611
        )
1612
        current_data = json.loads(response.data)
1613
        expected_data = "The request body mimetype is not application/json."
1614
        self.assertEqual(current_data["description"], expected_data)
1615
        self.assertEqual(415, response.status_code)
1616
1617
    def test_delete_no_evc(self):
1618
        """Test delete when EVC does not exist."""
1619
        api = self.get_app_test_client(self.napp)
1620
        response = api.delete(f"{self.server_name_url}/v2/evc/123")
1621
        current_data = json.loads(response.data)
1622
        expected_data = "circuit_id 123 not found"
1623
        self.assertEqual(current_data["description"], expected_data)
1624
        self.assertEqual(404, response.status_code)
1625
1626
    @patch("napps.kytos.mef_eline.models.evc.EVC.remove_current_flows")
1627
    @patch("napps.kytos.mef_eline.models.evc.EVC.deploy")
1628
    @patch("napps.kytos.mef_eline.scheduler.Scheduler.add")
1629
    @patch("napps.kytos.mef_eline.main.Main._uni_from_dict")
1630
    @patch("napps.kytos.mef_eline.storehouse.StoreHouse.save_evc")
1631
    @patch("napps.kytos.mef_eline.models.evc.EVC._validate")
1632
    @patch("napps.kytos.mef_eline.main.EVC.as_dict")
1633
    def test_delete_archived_evc(self, *args):
1634
        """Try to delete an archived EVC"""
1635
        # pylint: disable=too-many-locals
1636
        (
1637
            evc_as_dict_mock,
1638
            validate_mock,
1639
            save_evc_mock,
1640
            uni_from_dict_mock,
1641
            sched_add_mock,
1642
            evc_deploy_mock,
1643
            remove_current_flows_mock
1644
        ) = args
1645
1646
        validate_mock.return_value = True
1647
        save_evc_mock.return_value = True
1648
        sched_add_mock.return_value = True
1649
        evc_deploy_mock.return_value = True
1650
        remove_current_flows_mock.return_value = True
1651
        uni1 = create_autospec(UNI)
1652
        uni2 = create_autospec(UNI)
1653
        uni1.interface = create_autospec(Interface)
1654
        uni2.interface = create_autospec(Interface)
1655
        uni1.interface.switch = "00:00:00:00:00:00:00:01"
1656
        uni2.interface.switch = "00:00:00:00:00:00:00:02"
1657
        uni_from_dict_mock.side_effect = [uni1, uni2, uni1, uni2]
1658
1659
        api = self.get_app_test_client(self.napp)
1660
        payload1 = {
1661
            "name": "my evc1",
1662
            "uni_a": {
1663
                "interface_id": "00:00:00:00:00:00:00:01:1",
1664
                "tag": {"tag_type": 1, "value": 80},
1665
            },
1666
            "uni_z": {
1667
                "interface_id": "00:00:00:00:00:00:00:02:2",
1668
                "tag": {"tag_type": 1, "value": 1},
1669
            },
1670
            "dynamic_backup_path": True,
1671
        }
1672
1673
        evc_as_dict_mock.return_value = payload1
1674
        response = api.post(
1675
            f"{self.server_name_url}/v2/evc/",
1676
            data=json.dumps(payload1),
1677
            content_type="application/json",
1678
        )
1679
        self.assertEqual(201, response.status_code)
1680
1681
        current_data = json.loads(response.data)
1682
        circuit_id = current_data["circuit_id"]
1683
        response = api.delete(
1684
            f"{self.server_name_url}/v2/evc/{circuit_id}"
1685
        )
1686
        self.assertEqual(200, response.status_code)
1687
1688
        response = api.delete(
1689
            f"{self.server_name_url}/v2/evc/{circuit_id}"
1690
        )
1691
        current_data = json.loads(response.data)
1692
        expected_data = f"Circuit {circuit_id} already removed"
1693
        self.assertEqual(current_data["description"], expected_data)
1694
        self.assertEqual(404, response.status_code)
1695
1696
    def test_handle_link_up(self):
1697
        """Test handle_link_up method."""
1698
        evc_mock = create_autospec(EVC)
1699
        evc_mock.is_enabled = MagicMock(side_effect=[True, False, True])
1700
        evc_mock.lock = MagicMock()
1701
        type(evc_mock).archived = PropertyMock(
1702
            side_effect=[True, False, False]
1703
        )
1704
        evcs = [evc_mock, evc_mock, evc_mock]
1705
        event = KytosEvent(name="test", content={"link": "abc"})
1706
        self.napp.circuits = dict(zip(["1", "2", "3"], evcs))
1707
        self.napp.handle_link_up(event)
1708
        evc_mock.handle_link_up.assert_called_once_with("abc")
1709
1710
    def test_handle_link_down(self):
1711
        """Test handle_link_down method."""
1712
        evc_mock = create_autospec(EVC)
1713
        evc_mock.is_affected_by_link = MagicMock(
1714
            side_effect=[True, False, True]
1715
        )
1716
        evc_mock.lock = MagicMock()
1717
        evc_mock.handle_link_down = MagicMock(side_effect=[True, True])
1718
        evcs = [evc_mock, evc_mock, evc_mock]
1719
        event = KytosEvent(name="test", content={"link": "abc"})
1720
        self.napp.circuits = dict(zip(["1", "2", "3"], evcs))
1721
        self.napp.handle_link_down(event)
1722
        evc_mock.handle_link_down.assert_has_calls([call(), call()])
1723
1724
    def test_add_metadata(self):
1725
        """Test method to add metadata"""
1726
        evc_mock = create_autospec(EVC)
1727
        evc_mock.metadata = {}
1728
        evc_mock.id = 1234
1729
        self.napp.circuits = {"1234": evc_mock}
1730
1731
        api = self.get_app_test_client(self.napp)
1732
        payload = {"metadata1": 1, "metadata2": 2}
1733
        response = api.post(
1734
            f"{self.server_name_url}/v2/evc/1234/metadata",
1735
            data=json.dumps(payload),
1736
            content_type="application/json",
1737
        )
1738
1739
        self.assertEqual(response.status_code, 201)
1740
        evc_mock.extend_metadata.assert_called_with(payload)
1741
1742
    def test_add_metadata_malformed_json(self):
1743
        """Test method to add metadata with a malformed json"""
1744
        api = self.get_app_test_client(self.napp)
1745
        payload = '{"metadata1": 1, "metadata2": 2,}'
1746
        response = api.post(
1747
            f"{self.server_name_url}/v2/evc/1234/metadata",
1748
            data=payload,
1749
            content_type="application/json"
1750
        )
1751
1752
        self.assertEqual(response.status_code, 400)
1753
        self.assertEqual(
1754
            response.json["description"],
1755
            "The request body is not a well-formed JSON."
1756
        )
1757
1758
    def test_add_metadata_no_body(self):
1759
        """Test method to add metadata with no body"""
1760
        api = self.get_app_test_client(self.napp)
1761
        response = api.post(
1762
            f"{self.server_name_url}/v2/evc/1234/metadata"
1763
        )
1764
        self.assertEqual(response.status_code, 400)
1765
        self.assertEqual(
1766
            response.json["description"],
1767
            "The request body is empty."
1768
        )
1769
1770
    def test_add_metadata_no_evc(self):
1771
        """Test method to add metadata with no evc"""
1772
        api = self.get_app_test_client(self.napp)
1773
        payload = {"metadata1": 1, "metadata2": 2}
1774
        response = api.post(
1775
            f"{self.server_name_url}/v2/evc/1234/metadata",
1776
            data=json.dumps(payload),
1777
            content_type="application/json",
1778
        )
1779
        self.assertEqual(response.status_code, 404)
1780
        self.assertEqual(
1781
            response.json["description"],
1782
            "circuit_id 1234 not found."
1783
        )
1784
1785
    def test_add_metadata_wrong_content_type(self):
1786
        """Test method to add metadata with wrong content type"""
1787
        api = self.get_app_test_client(self.napp)
1788
        payload = {"metadata1": 1, "metadata2": 2}
1789
        response = api.post(
1790
            f"{self.server_name_url}/v2/evc/1234/metadata",
1791
            data=json.dumps(payload),
1792
            content_type="application/xml",
1793
        )
1794
        self.assertEqual(response.status_code, 415)
1795
        self.assertEqual(
1796
            response.json["description"],
1797
            "The content type must be application/json "
1798
            "(received application/xml)."
1799
        )
1800
1801
    def test_get_metadata(self):
1802
        """Test method to get metadata"""
1803
        evc_mock = create_autospec(EVC)
1804
        evc_mock.metadata = {'metadata1': 1, 'metadata2': 2}
1805
        evc_mock.id = 1234
1806
        self.napp.circuits = {"1234": evc_mock}
1807
1808
        api = self.get_app_test_client(self.napp)
1809
        response = api.get(
1810
            f"{self.server_name_url}/v2/evc/1234/metadata",
1811
        )
1812
        self.assertEqual(response.status_code, 200)
1813
        self.assertEqual(response.json, {"metadata": evc_mock.metadata})
1814
1815
    def test_delete_metadata(self):
1816
        """Test method to delete metadata"""
1817
        evc_mock = create_autospec(EVC)
1818
        evc_mock.metadata = {'metadata1': 1, 'metadata2': 2}
1819
        evc_mock.id = 1234
1820
        self.napp.circuits = {"1234": evc_mock}
1821
1822
        api = self.get_app_test_client(self.napp)
1823
        response = api.delete(
1824
            f"{self.server_name_url}/v2/evc/1234/metadata/metadata1",
1825
        )
1826
        self.assertEqual(response.status_code, 200)
1827
1828
    def test_delete_metadata_no_evc(self):
1829
        """Test method to delete metadata with no evc"""
1830
        api = self.get_app_test_client(self.napp)
1831
        response = api.delete(
1832
            f"{self.server_name_url}/v2/evc/1234/metadata/metadata1",
1833
        )
1834
        self.assertEqual(response.status_code, 404)
1835
        self.assertEqual(
1836
            response.json["description"],
1837
            "circuit_id 1234 not found."
1838
        )
1839
1840
    @patch('napps.kytos.mef_eline.storehouse.StoreHouse.get_data')
1841
    @patch('napps.kytos.mef_eline.main.Main._load_evc')
1842
    def test_load_all_evcs(self, load_evc_mock, get_data_mock):
1843
        """Test load_evcs method"""
1844
        get_data_mock.return_value = {
1845
            1: 'circuit_1',
1846
            2: 'circuit_2',
1847
            3: 'circuit_3',
1848
            4: 'circuit_4'
1849
        }
1850
        self.napp.circuits = {2: 'circuit_2', 3: 'circuit_3'}
1851
        self.napp.load_all_evcs()
1852
        load_evc_mock.assert_has_calls([call('circuit_1'), call('circuit_4')])
1853
1854
    def test_handle_flow_mod_error(self):
1855
        """Test handle_flow_mod_error method"""
1856
        flow = MagicMock()
1857
        flow.cookie = 0xaa00000000000011
1858
        event = MagicMock()
1859
        event.content = {'flow': flow, 'error_command': 'add'}
1860
        evc = create_autospec(EVC)
1861
        evc.remove_current_flows = MagicMock()
1862
        self.napp.circuits = {"00000000000011": evc}
1863
        self.napp.handle_flow_mod_error(event)
1864
        evc.remove_current_flows.assert_called_once()
1865