Test Failed
Pull Request — master (#49)
by
unknown
03:08
created

build.tests.unit.test_main   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 623
Duplicated Lines 19.9 %

Importance

Changes 0
Metric Value
eloc 397
dl 124
loc 623
rs 10
c 0
b 0
f 0
wmc 20

16 Methods

Rating   Name   Duplication   Size   Complexity  
A TestMain.get_napp_urls() 0 24 4
A TestMain.setUp() 0 16 2
A TestMain.test_verify_api_urls() 0 17 1
A TestMain.test_trace_step() 0 51 1
A TestMain.test_trace_step__no_flow() 0 24 1
A TestMain.test_trace_step__no_endpoint() 0 36 1
A TestMain.test_has_loop__fail() 0 30 1
A TestMain.test_tracepath() 0 49 1
A TestMain.test_has_loop() 0 48 1
A TestMain.test_update_circuits() 0 11 1
A TestMain.test_update_circuits__no_settings() 0 12 1
B TestMain.test_traces() 61 61 1
A TestMain.test_get_traces() 0 39 1
B TestMain.test_traces_same_switch() 63 63 1
A TestMain.test_trace() 0 47 1
B TestMain.test_traces_twice() 0 58 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
        switch_01 = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
227
        switch_01.is_enabled.return_value = True
228
229
        self.napp.controller.switches = {
230
            "00:00:00:00:00:00:00:01": switch_01
231
        }
232
233
        result = self.napp.tracepath(
234
                                        entries["trace"]["switch"],
235
                                        stored_flows_arg
236
                                    )
237
238
        assert result[0]["in"]["dpid"] == "00:00:00:00:00:00:00:01"
239
        assert result[0]["in"]["port"] == 1
240
        assert result[0]["in"]["type"] == "starting"
241
242
        assert result[1]["in"]["dpid"] == "00:00:00:00:00:00:00:02"
243
        assert result[1]["in"]["port"] == 2
244
        assert result[1]["in"]["type"] == "trace"
245
246
    def test_has_loop(self):
247
        """Test has_loop to detect a tracepath with loop."""
248
        trace_result = [
249
            {
250
                "in": {
251
                    "dpid": "00:00:00:00:00:00:00:01",
252
                    "port": 2,
253
                },
254
                "out": {
255
                    "port": 1,
256
                },
257
            },
258
            {
259
                "in": {
260
                    "dpid": "00:00:00:00:00:00:00:03",
261
                    "port": 2,
262
                },
263
                "out": {
264
                    "port": 1,
265
                },
266
            },
267
            {
268
                "in": {
269
                    "dpid": "00:00:00:00:00:00:00:03",
270
                    "port": 3,
271
                },
272
                "out": {
273
                    "port": 1,
274
                },
275
            },
276
            {
277
                "in": {
278
                    "dpid": "00:00:00:00:00:00:00:03",
279
                    "port": 3,
280
                },
281
                "out": {
282
                    "port": 1,
283
                },
284
            },
285
        ]
286
        trace_step = {
287
            "dpid": "00:00:00:00:00:00:00:03",
288
            "port": 3,
289
        }
290
291
        result = self.napp.has_loop(trace_step, trace_result)
292
293
        self.assertTrue(result)
294
295
    def test_has_loop__fail(self):
296
        """Test has_loop to detect a tracepath with loop."""
297
        trace_result = [
298
            {
299
                "in": {
300
                    "dpid": "00:00:00:00:00:00:00:01",
301
                    "port": 2,
302
                },
303
                "out": {
304
                    "port": 1,
305
                },
306
            },
307
            {
308
                "in": {
309
                    "dpid": "00:00:00:00:00:00:00:02",
310
                    "port": 2,
311
                },
312
                "out": {
313
                    "port": 1,
314
                },
315
            },
316
        ]
317
        trace_step = {
318
            "dpid": "00:00:00:00:00:00:00:03",
319
            "port": 2,
320
        }
321
322
        result = self.napp.has_loop(trace_step, trace_result)
323
324
        self.assertFalse(result)
325
326
    @patch("napps.amlight.sdntrace_cp.main.settings")
327
    def test_update_circuits(self, mock_settings):
328
        """Test update_circuits event listener with success."""
329
        mock_settings.FIND_CIRCUITS_IN_FLOWS = True
330
331
        self.napp.automate = MagicMock()
332
        self.napp.automate.find_circuits = MagicMock()
333
334
        self.napp.update_circuits()
335
336
        self.napp.automate.find_circuits.assert_called_once()
337
338
    @patch("napps.amlight.sdntrace_cp.main.settings")
339
    def test_update_circuits__no_settings(self, mock_settings):
340
        """Test update_circuits event listener without
341
        settings option enabled."""
342
        mock_settings.FIND_CIRCUITS_IN_FLOWS = False
343
344
        self.napp.automate = MagicMock()
345
        self.napp.automate.find_circuits = MagicMock()
346
347
        self.napp.update_circuits()
348
349
        self.napp.automate.find_circuits.assert_not_called()
350
351
    @patch("napps.amlight.sdntrace_cp.utils.get_stored_flows")
352
    @patch("napps.amlight.sdntrace_cp.utils.requests")
353
    def test_trace(self, mock_request_get, mock_stored_flows):
354
        """Test trace rest call."""
355
        api = get_test_client(get_controller_mock(), self.napp)
356
        url = f"{self.server_name_url}/trace/"
357
358
        payload = {
359
            "trace": {
360
                "switch": {
361
                    "dpid": "00:00:00:00:00:00:00:01",
362
                    "in_port": 1
363
                    },
364
                "eth": {"dl_vlan": 100},
365
            }
366
        }
367
        stored_flows = {
368
                "flow": {
369
                    "table_id": 0,
370
                    "cookie": 84114964,
371
                    "hard_timeout": 0,
372
                    "idle_timeout": 0,
373
                    "priority": 10,
374
                },
375
                "flow_id": 1,
376
                "state": "installed",
377
                "switch": "00:00:00:00:00:00:00:01",
378
        }
379
        mock_stored_flows.return_value = {
380
            "00:00:00:00:00:00:00:01": [stored_flows]
381
        }
382
        mock_json = MagicMock()
383
        mock_json.json.return_value = {
384
            "00:00:00:00:00:00:00:01": [stored_flows]
385
        }
386
        mock_request_get.get.return_value = mock_json
387
388
        response = api.put(
389
            url, data=json.dumps(payload), content_type="application/json"
390
        )
391
        current_data = json.loads(response.data)
392
        result = current_data["result"]
393
394
        assert result[0]["dpid"] == "00:00:00:00:00:00:00:01"
395
        assert result[0]["port"] == 1
396
        assert result[0]["type"] == "starting"
397
        assert result[0]["vlan"] == 100
398
399
    @patch("napps.amlight.sdntrace_cp.utils.get_stored_flows")
400
    def test_get_traces(self, mock_stored_flows):
401
        """Test traces rest call."""
402
        api = get_test_client(get_controller_mock(), self.napp)
403
        url = f"{self.server_name_url}/traces/"
404
405
        payload = [{
406
            "trace": {
407
                "switch": {
408
                    "dpid": "00:00:00:00:00:00:00:01",
409
                    "in_port": 1
410
                    },
411
                "eth": {"dl_vlan": 100},
412
            }
413
        }]
414
415
        stored_flow = {
416
                "id": 1,
417
                "table_id": 0,
418
                "cookie": 84114964,
419
                "hard_timeout": 0,
420
                "idle_timeout": 0,
421
                "priority": 10,
422
        }
423
424
        mock_stored_flows.return_value = {
425
            "00:00:00:00:00:00:00:01": [stored_flow]
426
        }
427
428
        response = api.put(
429
            url, data=json.dumps(payload), content_type="application/json"
430
        )
431
        current_data = json.loads(response.data)
432
        result1 = current_data["00:00:00:00:00:00:00:01"]
433
434
        assert result1[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
435
        assert result1[0][0]["port"] == 1
436
        assert result1[0][0]["type"] == "starting"
437
        assert result1[0][0]["vlan"] == 100
438
439 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...
440
    @patch("napps.amlight.sdntrace_cp.utils.requests")
441
    def test_traces(self, mock_request_get, mock_stored_flows):
442
        """Test traces rest call for two traces with different switches."""
443
        api = get_test_client(get_controller_mock(), self.napp)
444
        url = f"{self.server_name_url}/traces/"
445
446
        payload = [
447
            {
448
                "trace": {
449
                    "switch": {
450
                        "dpid": "00:00:00:00:00:00:00:01",
451
                        "in_port": 1
452
                        },
453
                    "eth": {"dl_vlan": 100},
454
                }
455
            },
456
            {
457
                "trace": {
458
                    "switch": {
459
                        "dpid": "00:00:00:00:00:00:00:02",
460
                        "in_port": 1},
461
                    "eth": {"dl_vlan": 100},
462
                }
463
            }
464
        ]
465
466
        stored_flow = {
467
                "id": 1,
468
                "table_id": 0,
469
                "cookie": 84114964,
470
                "hard_timeout": 0,
471
                "idle_timeout": 0,
472
                "priority": 10,
473
        }
474
475
        mock_stored_flows.return_value = {
476
            "00:00:00:00:00:00:00:01": [stored_flow]
477
        }
478
        mock_json = MagicMock()
479
        mock_json.json.return_value = {
480
            "00:00:00:00:00:00:00:01": [stored_flow]
481
        }
482
        mock_request_get.get.return_value = mock_json
483
484
        response = api.put(
485
            url, data=json.dumps(payload), content_type="application/json"
486
        )
487
        current_data = json.loads(response.data)
488
        result1 = current_data["00:00:00:00:00:00:00:01"]
489
        result2 = current_data["00:00:00:00:00:00:00:02"]
490
491
        assert result1[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
492
        assert result1[0][0]["port"] == 1
493
        assert result1[0][0]["type"] == "starting"
494
        assert result1[0][0]["vlan"] == 100
495
496
        assert result2[0][0]["dpid"] == "00:00:00:00:00:00:00:02"
497
        assert result2[0][0]["port"] == 1
498
        assert result2[0][0]["type"] == "starting"
499
        assert result2[0][0]["vlan"] == 100
500
501 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...
502
    @patch("napps.amlight.sdntrace_cp.utils.requests")
503
    def test_traces_same_switch(self, mock_request_get, mock_stored_flows):
504
        """Test traces rest call for two traces with samw switches."""
505
        api = get_test_client(get_controller_mock(), self.napp)
506
        url = f"{self.server_name_url}/traces/"
507
508
        payload = [
509
            {
510
                "trace": {
511
                    "switch": {
512
                        "dpid": "00:00:00:00:00:00:00:01",
513
                        "in_port": 1
514
                    },
515
                    "eth": {"dl_vlan": 100},
516
                }
517
            },
518
            {
519
                "trace": {
520
                    "switch": {
521
                        "dpid": "00:00:00:00:00:00:00:01",
522
                        "in_port": 2
523
                    },
524
                    "eth": {"dl_vlan": 100},
525
                }
526
            }
527
        ]
528
529
        stored_flow = {
530
                "id": 1,
531
                "table_id": 0,
532
                "cookie": 84114964,
533
                "hard_timeout": 0,
534
                "idle_timeout": 0,
535
                "priority": 10,
536
        }
537
538
        mock_stored_flows.return_value = {
539
            "00:00:00:00:00:00:00:01": [stored_flow]
540
        }
541
        mock_json = MagicMock()
542
        mock_json.json.return_value = {
543
            "00:00:00:00:00:00:00:01": [stored_flow]
544
        }
545
        mock_request_get.get.return_value = mock_json
546
547
        response = api.put(
548
            url, data=json.dumps(payload), content_type="application/json"
549
        )
550
        current_data = json.loads(response.data)
551
        result = current_data["00:00:00:00:00:00:00:01"]
552
553
        assert len(current_data) == 1
554
555
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
556
        assert result[0][0]["port"] == 1
557
        assert result[0][0]["type"] == "starting"
558
        assert result[0][0]["vlan"] == 100
559
560
        assert result[1][0]["dpid"] == "00:00:00:00:00:00:00:01"
561
        assert result[1][0]["port"] == 2
562
        assert result[1][0]["type"] == "starting"
563
        assert result[1][0]["vlan"] == 100
564
565
    @patch("napps.amlight.sdntrace_cp.utils.get_stored_flows")
566
    @patch("napps.amlight.sdntrace_cp.utils.requests")
567
    def test_traces_twice(self, mock_request_get, mock_stored_flows):
568
        """Test traces rest call for two equal traces."""
569
        api = get_test_client(get_controller_mock(), self.napp)
570
        url = f"{self.server_name_url}/traces/"
571
572
        payload = [
573
            {
574
                "trace": {
575
                    "switch": {
576
                        "dpid": "00:00:00:00:00:00:00:01",
577
                        "in_port": 1
578
                        },
579
                    "eth": {"dl_vlan": 100},
580
                }
581
            },
582
            {
583
                "trace": {
584
                    "switch": {
585
                        "dpid": "00:00:00:00:00:00:00:01",
586
                        "in_port": 1
587
                        },
588
                    "eth": {"dl_vlan": 100},
589
                }
590
            }
591
        ]
592
        stored_flow = {
593
                "id": 1,
594
                "table_id": 0,
595
                "cookie": 84114964,
596
                "hard_timeout": 0,
597
                "idle_timeout": 0,
598
                "priority": 10,
599
        }
600
601
        mock_stored_flows.return_value = {
602
            "00:00:00:00:00:00:00:01": [stored_flow]
603
        }
604
        mock_json = MagicMock()
605
        mock_json.json.return_value = {
606
            "00:00:00:00:00:00:00:01": [stored_flow]
607
        }
608
        mock_request_get.get.return_value = mock_json
609
610
        response = api.put(
611
            url, data=json.dumps(payload), content_type="application/json"
612
        )
613
        current_data = json.loads(response.data)
614
        result = current_data["00:00:00:00:00:00:00:01"]
615
616
        assert len(current_data) == 1
617
        assert len(result) == 1
618
619
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
620
        assert result[0][0]["port"] == 1
621
        assert result[0][0]["type"] == "starting"
622
        assert result[0][0]["vlan"] == 100
623