Test Failed
Pull Request — master (#49)
by
unknown
02:53
created

TestMain.test_get_traces()   A

Complexity

Conditions 1

Size

Total Lines 39
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 27
nop 2
dl 0
loc 39
rs 9.232
c 0
b 0
f 0
1
"""Module to test the main napp file."""
2
import json
3
from unittest import TestCase
4
from unittest.mock import patch, MagicMock
5
6
from kytos.core.interface import Interface
7
from kytos.lib.helpers import (
8
    get_interface_mock,
9
    get_switch_mock,
10
    get_controller_mock,
11
    get_link_mock,
12
    get_test_client,
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 amlight/sdntrace_cp
24
        """
25
        self.server_name_url = "http://localhost:8181/api/amlight/sdntrace_cp"
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.amlight.sdntrace_cp.main import Main
34
35
        self.napp = Main(get_controller_mock())
36
37
    @staticmethod
38
    def get_napp_urls(napp):
39
        """Return the amlight/sdntrace_cp urls.
40
41
        The urls will be like:
42
43
        urls = [
44
            (options, methods, url)
45
        ]
46
47
        """
48
        controller = napp.controller
49
        controller.api_server.register_napp_endpoints(napp)
50
51
        urls = []
52
        for rule in controller.api_server.app.url_map.iter_rules():
53
            options = {}
54
            for arg in rule.arguments:
55
                options[arg] = f"[{0}]".format(arg)
56
57
            if f"{napp.username}/{napp.name}" in str(rule):
58
                urls.append((options, rule.methods, f"{str(rule)}"))
59
60
        return urls
61
62
    def test_verify_api_urls(self):
63
        """Verify all APIs registered."""
64
65
        expected_urls = [
66
            (
67
                {},
68
                {"OPTIONS", "HEAD", "PUT"},
69
                "/api/amlight/sdntrace_cp/trace/ ",
70
            ),
71
            (
72
                {},
73
                {"OPTIONS", "HEAD", "PUT"},
74
                "/api/amlight/sdntrace_cp/traces/ ",
75
            ),
76
        ]
77
        urls = self.get_napp_urls(self.napp)
78
        self.assertEqual(len(expected_urls), len(urls))
79
80
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
81
    def test_trace_step(self, mock_flow_match):
82
        """Test trace_step success result."""
83
        mock_flow_match.return_value = ["1"], ["entries"], 1
84
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
85
86
        mock_interface = Interface("interface A", 1, MagicMock())
87
        mock_interface.address = "00:00:00:00:00:00:00:01"
88
89
        iface1 = get_interface_mock(
90
            "", 1, get_switch_mock("00:00:00:00:00:00:00:01")
91
        )
92
        iface2 = get_interface_mock(
93
            "", 2, get_switch_mock("00:00:00:00:00:00:00:02")
94
        )
95
        mock_interface.link = get_link_mock(iface1, iface2)
96
        mock_interface.link.endpoint_a.port_number = 1
97
        mock_interface.link.endpoint_a.port_number = 2
98
99
        # Patch for utils.find_endpoint
100
        switch.get_interface_by_port_no.return_value = mock_interface
101
102
        entries = MagicMock()
103
104
        stored_flows = {
105
            "flow": {
106
                "table_id": 0,
107
                "cookie": 84114964,
108
                "hard_timeout": 0,
109
                "idle_timeout": 0,
110
                "priority": 10,
111
            },
112
            "flow_id": 1,
113
            "state": "installed",
114
            "switch": "00:00:00:00:00:00:00:01",
115
        }
116
117
        stored_flows_arg = {
118
            "00:00:00:00:00:00:00:01": [stored_flows]
119
        }
120
121
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
122
123
        mock_flow_match.assert_called_once()
124
        self.assertEqual(
125
            result,
126
            {
127
                "dpid": "00:00:00:00:00:00:00:01",
128
                "in_port": 2,
129
                "out_port": 1,
130
                "entries": ["entries"],
131
            },
132
        )
133
134
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
135
    def test_trace_step__no_endpoint(self, mock_flow_match):
136
        """Test trace_step without endpoints available for switch/port."""
137
        mock_flow_match.return_value = ["1"], ["entries"], 1
138
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
139
140
        mock_interface = Interface("interface A", 1, MagicMock())
141
        mock_interface.address = "00:00:00:00:00:00:00:01"
142
        mock_interface.link = None
143
144
        # Patch for utils.find_endpoint
145
        switch.get_interface_by_port_no.return_value = mock_interface
146
147
        entries = MagicMock()
148
149
        stored_flows = {
150
            "flow": {
151
                "table_id": 0,
152
                "cookie": 84114964,
153
                "hard_timeout": 0,
154
                "idle_timeout": 0,
155
                "priority": 10,
156
            },
157
            "flow_id": 1,
158
            "state": "installed",
159
            "switch": "00:00:00:00:00:00:00:01",
160
        }
161
162
        stored_flows_arg = {
163
            "00:00:00:00:00:00:00:01": [stored_flows]
164
        }
165
166
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
167
168
        mock_flow_match.assert_called_once()
169
        self.assertEqual(result, {"entries": ["entries"], "out_port": 1})
170
171
    def test_trace_step__no_flow(self):
172
        """Test trace_step without flows for the switch."""
173
        switch = get_switch_mock("00:00:00:00:00:00:00:01")
174
        entries = MagicMock()
175
176
        stored_flows = {
177
            "flow": {
178
                "table_id": 0,
179
                "cookie": 84114964,
180
                "hard_timeout": 0,
181
                "idle_timeout": 0,
182
                "priority": 10,
183
            },
184
            "flow_id": 1,
185
            "state": "installed",
186
            "switch": "00:00:00:00:00:00:00:01",
187
        }
188
189
        stored_flows_arg = {
190
            "00:00:00:00:00:00:00:01": [stored_flows]
191
        }
192
193
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
194
        assert result is None
195
196
    @patch("napps.amlight.sdntrace_cp.main.Main.trace_step")
197
    def test_tracepath(self, mock_trace_step):
198
        """Test tracepath with success result."""
199
        eth = {"dl_vlan": 100}
200
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
201
        switch = {"switch": dpid, "eth": eth}
202
        entries = {"trace": switch}
203
        mock_trace_step.return_value = {
204
            "dpid": "00:00:00:00:00:00:00:02",
205
            "in_port": 2,
206
            "out_port": 3,
207
            "entries": entries,
208
        }
209
        stored_flows = {
210
            "flow": {
211
                "table_id": 0,
212
                "cookie": 84114964,
213
                "hard_timeout": 0,
214
                "idle_timeout": 0,
215
                "priority": 10,
216
            },
217
            "flow_id": 1,
218
            "state": "installed",
219
            "switch": "00:00:00:00:00:00:00:01",
220
        }
221
222
        stored_flows_arg = {
223
            "00:00:00:00:00:00:00:01": [stored_flows]
224
        }
225
226
        result = self.napp.tracepath(
227
                                        entries["trace"]["switch"],
228
                                        stored_flows_arg
229
                                    )
230
231
        assert result[0]["in"]["dpid"] == "00:00:00:00:00:00:00:01"
232
        assert result[0]["in"]["port"] == 1
233
        assert result[0]["in"]["type"] == "starting"
234
        assert result[0]["out"]["port"] == 3
235
236
        assert result[1]["in"]["dpid"] == "00:00:00:00:00:00:00:02"
237
        assert result[1]["in"]["port"] == 2
238
        assert result[1]["in"]["type"] == "trace"
239
        assert result[1]["out"]["port"] == 3
240
241
    def test_has_loop(self):
242
        """Test has_loop to detect a tracepath with loop."""
243
        trace_result = [
244
            {
245
                "in": {
246
                    "dpid": "00:00:00:00:00:00:00:01",
247
                    "port": 2,
248
                },
249
                "out": {
250
                    "port": 1,
251
                },
252
            },
253
            {
254
                "in": {
255
                    "dpid": "00:00:00:00:00:00:00:03",
256
                    "port": 2,
257
                },
258
                "out": {
259
                    "port": 1,
260
                },
261
            },
262
            {
263
                "in": {
264
                    "dpid": "00:00:00:00:00:00:00:03",
265
                    "port": 3,
266
                },
267
                "out": {
268
                    "port": 1,
269
                },
270
            },
271
            {
272
                "in": {
273
                    "dpid": "00:00:00:00:00:00:00:03",
274
                    "port": 3,
275
                },
276
                "out": {
277
                    "port": 1,
278
                },
279
            },
280
        ]
281
        trace_step = {
282
            "dpid": "00:00:00:00:00:00:00:03",
283
            "port": 3,
284
        }
285
286
        result = self.napp.has_loop(trace_step, trace_result)
287
288
        self.assertTrue(result)
289
290
    def test_has_loop__fail(self):
291
        """Test has_loop to detect a tracepath with loop."""
292
        trace_result = [
293
            {
294
                "in": {
295
                    "dpid": "00:00:00:00:00:00:00:01",
296
                    "port": 2,
297
                },
298
                "out": {
299
                    "port": 1,
300
                },
301
            },
302
            {
303
                "in": {
304
                    "dpid": "00:00:00:00:00:00:00:02",
305
                    "port": 2,
306
                },
307
                "out": {
308
                    "port": 1,
309
                },
310
            },
311
        ]
312
        trace_step = {
313
            "dpid": "00:00:00:00:00:00:00:03",
314
            "port": 2,
315
        }
316
317
        result = self.napp.has_loop(trace_step, trace_result)
318
319
        self.assertFalse(result)
320
321
    @patch("napps.amlight.sdntrace_cp.main.settings")
322
    def test_update_circuits(self, mock_settings):
323
        """Test update_circuits event listener with success."""
324
        mock_settings.FIND_CIRCUITS_IN_FLOWS = True
325
326
        self.napp.automate = MagicMock()
327
        self.napp.automate.find_circuits = MagicMock()
328
329
        self.napp.update_circuits()
330
331
        self.napp.automate.find_circuits.assert_called_once()
332
333
    @patch("napps.amlight.sdntrace_cp.main.settings")
334
    def test_update_circuits__no_settings(self, mock_settings):
335
        """Test update_circuits event listener without
336
        settings option enabled."""
337
        mock_settings.FIND_CIRCUITS_IN_FLOWS = False
338
339
        self.napp.automate = MagicMock()
340
        self.napp.automate.find_circuits = MagicMock()
341
342
        self.napp.update_circuits()
343
344
        self.napp.automate.find_circuits.assert_not_called()
345
346
    @patch("napps.amlight.sdntrace_cp.utils.get_stored_flows")
347
    def test_trace(self, mock_stored_flows):
348
        """Test trace rest call."""
349
        api = get_test_client(get_controller_mock(), self.napp)
350
        url = f"{self.server_name_url}/trace/"
351
352
        payload = {
353
            "trace": {
354
                "switch": {
355
                    "dpid": "00:00:00:00:00:00:00:01",
356
                    "in_port": 1
357
                    },
358
                "eth": {"dl_vlan": 100},
359
            }
360
        }
361
        stored_flows = {
362
                "flow": {
363
                    "table_id": 0,
364
                    "cookie": 84114964,
365
                    "hard_timeout": 0,
366
                    "idle_timeout": 0,
367
                    "priority": 10,
368
                },
369
                "flow_id": 1,
370
                "state": "installed",
371
                "switch": "00:00:00:00:00:00:00:01",
372
        }
373
        mock_stored_flows.return_value = {
374
            "00:00:00:00:00:00:00:01": [stored_flows]
375
        }
376
377
        response = api.put(
378
            url, data=json.dumps(payload), content_type="application/json"
379
        )
380
        current_data = json.loads(response.data)
381
        result = current_data["result"]
382
383
        assert result[0]["dpid"] == "00:00:00:00:00:00:00:01"
384
        assert result[0]["port"] == 1
385
        assert result[0]["type"] == "starting"
386
        assert result[0]["vlan"] == 100
387
388
    @patch("napps.amlight.sdntrace_cp.utils.get_stored_flows")
389
    def test_get_traces(self, mock_stored_flows):
390
        """Test traces rest call."""
391
        api = get_test_client(get_controller_mock(), self.napp)
392
        url = f"{self.server_name_url}/traces/"
393
394
        payload = [{
395
            "trace": {
396
                "switch": {
397
                    "dpid": "00:00:00:00:00:00:00:01",
398
                    "in_port": 1
399
                    },
400
                "eth": {"dl_vlan": 100},
401
            }
402
        }]
403
404
        stored_flow = {
405
                "id": 1,
406
                "table_id": 0,
407
                "cookie": 84114964,
408
                "hard_timeout": 0,
409
                "idle_timeout": 0,
410
                "priority": 10,
411
        }
412
413
        mock_stored_flows.return_value = {
414
            "00:00:00:00:00:00:00:01": [stored_flow]
415
        }
416
417
        response = api.put(
418
            url, data=json.dumps(payload), content_type="application/json"
419
        )
420
        current_data = json.loads(response.data)
421
        result1 = current_data["00:00:00:00:00:00:00:01"]
422
423
        assert result1[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
424
        assert result1[0][0]["port"] == 1
425
        assert result1[0][0]["type"] == "starting"
426
        assert result1[0][0]["vlan"] == 100
427
428 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.utils.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
429
    def test_traces(self, mock_stored_flows):
430
        """Test traces rest call for two traces with different switches."""
431
        api = get_test_client(get_controller_mock(), self.napp)
432
        url = f"{self.server_name_url}/traces/"
433
434
        payload = [
435
            {
436
                "trace": {
437
                    "switch": {
438
                        "dpid": "00:00:00:00:00:00:00:01",
439
                        "in_port": 1
440
                        },
441
                    "eth": {"dl_vlan": 100},
442
                }
443
            },
444
            {
445
                "trace": {
446
                    "switch": {
447
                        "dpid": "00:00:00:00:00:00:00:02",
448
                        "in_port": 1},
449
                    "eth": {"dl_vlan": 100},
450
                }
451
            }
452
        ]
453
454
        stored_flow = {
455
                "id": 1,
456
                "table_id": 0,
457
                "cookie": 84114964,
458
                "hard_timeout": 0,
459
                "idle_timeout": 0,
460
                "priority": 10,
461
        }
462
463
        mock_stored_flows.return_value = {
464
            "00:00:00:00:00:00:00:01": [stored_flow]
465
        }
466
467
        response = api.put(
468
            url, data=json.dumps(payload), content_type="application/json"
469
        )
470
        current_data = json.loads(response.data)
471
        result1 = current_data["00:00:00:00:00:00:00:01"]
472
        result2 = current_data["00:00:00:00:00:00:00:02"]
473
474
        assert result1[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
475
        assert result1[0][0]["port"] == 1
476
        assert result1[0][0]["type"] == "starting"
477
        assert result1[0][0]["vlan"] == 100
478
479
        assert result2[0][0]["dpid"] == "00:00:00:00:00:00:00:02"
480
        assert result2[0][0]["port"] == 1
481
        assert result2[0][0]["type"] == "starting"
482
        assert result2[0][0]["vlan"] == 100
483
484 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.utils.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
485
    def test_traces_same_switch(self, mock_stored_flows):
486
        """Test traces rest call for two traces with samw switches."""
487
        api = get_test_client(get_controller_mock(), self.napp)
488
        url = f"{self.server_name_url}/traces/"
489
490
        payload = [
491
            {
492
                "trace": {
493
                    "switch": {
494
                        "dpid": "00:00:00:00:00:00:00:01",
495
                        "in_port": 1
496
                    },
497
                    "eth": {"dl_vlan": 100},
498
                }
499
            },
500
            {
501
                "trace": {
502
                    "switch": {
503
                        "dpid": "00:00:00:00:00:00:00:01",
504
                        "in_port": 2
505
                    },
506
                    "eth": {"dl_vlan": 100},
507
                }
508
            }
509
        ]
510
511
        stored_flow = {
512
                "id": 1,
513
                "table_id": 0,
514
                "cookie": 84114964,
515
                "hard_timeout": 0,
516
                "idle_timeout": 0,
517
                "priority": 10,
518
        }
519
520
        mock_stored_flows.return_value = {
521
            "00:00:00:00:00:00:00:01": [stored_flow]
522
        }
523
524
        response = api.put(
525
            url, data=json.dumps(payload), content_type="application/json"
526
        )
527
        current_data = json.loads(response.data)
528
        result = current_data["00:00:00:00:00:00:00:01"]
529
530
        assert len(current_data) == 1
531
532
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
533
        assert result[0][0]["port"] == 1
534
        assert result[0][0]["type"] == "starting"
535
        assert result[0][0]["vlan"] == 100
536
537
        assert result[1][0]["dpid"] == "00:00:00:00:00:00:00:01"
538
        assert result[1][0]["port"] == 2
539
        assert result[1][0]["type"] == "starting"
540
        assert result[1][0]["vlan"] == 100
541
542
    @patch("napps.amlight.sdntrace_cp.utils.get_stored_flows")
543
    def test_traces_twice(self, mock_stored_flows):
544
        """Test traces rest call for two equal traces."""
545
        api = get_test_client(get_controller_mock(), self.napp)
546
        url = f"{self.server_name_url}/traces/"
547
548
        payload = [
549
            {
550
                "trace": {
551
                    "switch": {
552
                        "dpid": "00:00:00:00:00:00:00:01",
553
                        "in_port": 1
554
                        },
555
                    "eth": {"dl_vlan": 100},
556
                }
557
            },
558
            {
559
                "trace": {
560
                    "switch": {
561
                        "dpid": "00:00:00:00:00:00:00:01",
562
                        "in_port": 1
563
                        },
564
                    "eth": {"dl_vlan": 100},
565
                }
566
            }
567
        ]
568
        stored_flow = {
569
                "id": 1,
570
                "table_id": 0,
571
                "cookie": 84114964,
572
                "hard_timeout": 0,
573
                "idle_timeout": 0,
574
                "priority": 10,
575
        }
576
577
        mock_stored_flows.return_value = {
578
            "00:00:00:00:00:00:00:01": [stored_flow]
579
        }
580
581
        response = api.put(
582
            url, data=json.dumps(payload), content_type="application/json"
583
        )
584
        current_data = json.loads(response.data)
585
        result = current_data["00:00:00:00:00:00:00:01"]
586
587
        assert len(current_data) == 1
588
        assert len(result) == 1
589
590
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
591
        assert result[0][0]["port"] == 1
592
        assert result[0][0]["type"] == "starting"
593
        assert result[0][0]["vlan"] == 100
594