Test Failed
Pull Request — master (#47)
by
unknown
06:35
created

TestMain.test_tracepath()   A

Complexity

Conditions 1

Size

Total Lines 25
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 20
nop 2
dl 0
loc 25
rs 9.4
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
        result = self.napp.trace_step(switch, entries)
105
106
        mock_flow_match.assert_called_once()
107
        self.assertEqual(
108
            result,
109
            {
110
                "dpid": "00:00:00:00:00:00:00:01",
111
                "in_port": 2,
112
                "out_port": 1,
113
                "entries": ["entries"],
114
            },
115
        )
116
117
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
118
    def test_trace_step__no_endpoint(self, mock_flow_match):
119
        """Test trace_step without endpoints available for switch/port."""
120
        mock_flow_match.return_value = ["1"], ["entries"], 1
121
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
122
123
        mock_interface = Interface("interface A", 1, MagicMock())
124
        mock_interface.address = "00:00:00:00:00:00:00:01"
125
        mock_interface.link = None
126
127
        # Patch for utils.find_endpoint
128
        switch.get_interface_by_port_no.return_value = mock_interface
129
130
        entries = MagicMock()
131
132
        result = self.napp.trace_step(switch, entries)
133
134
        mock_flow_match.assert_called_once()
135
        self.assertEqual(result, {"entries": ["entries"], "out_port": 1})
136
137
    @patch("napps.amlight.sdntrace_cp.main.Main.map_flows")
138
    def test_trace_step__no_flow(self, mock_stored_flows):
139
        """Test trace_step without flows for the switch."""
140
        switch = get_switch_mock("00:00:00:00:00:00:00:01")
141
        entries = MagicMock()
142
143
        map_flow = {
144
                "id": 1,
145
                "priority": 10,
146
        }
147
148
        mock_stored_flows.return_value = {
149
            "00:00:00:00:00:00:00:01": [map_flow]
150
        }
151
152
        result = self.napp.trace_step(switch, entries)
153
        assert result is None
154
155
    @patch("napps.amlight.sdntrace_cp.main.Main.trace_step")
156
    def test_tracepath(self, mock_trace_step):
157
        """Test tracepath with success result."""
158
        eth = {"dl_vlan": 100}
159
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
160
        switch = {"switch": dpid, "eth": eth}
161
        entries = {"trace": switch}
162
        mock_trace_step.return_value = {
163
            "dpid": "00:00:00:00:00:00:00:02",
164
            "in_port": 2,
165
            "out_port": 3,
166
            "entries": entries,
167
        }
168
169
        result = self.napp.tracepath(entries["trace"]["switch"])
170
171
        assert result[0]["in"]["dpid"] == "00:00:00:00:00:00:00:01"
172
        assert result[0]["in"]["port"] == 1
173
        assert result[0]["in"]["type"] == "starting"
174
        assert result[0]["out"]["port"] == 3
175
176
        assert result[1]["in"]["dpid"] == "00:00:00:00:00:00:00:02"
177
        assert result[1]["in"]["port"] == 2
178
        assert result[1]["in"]["type"] == "trace"
179
        assert result[1]["out"]["port"] == 3
180
181
    def test_has_loop(self):
182
        """Test has_loop to detect a tracepath with loop."""
183
        trace_result = [
184
            {
185
                "in": {
186
                    "dpid": "00:00:00:00:00:00:00:01",
187
                    "port": 2,
188
                },
189
                "out": {
190
                    "port": 1,
191
                },
192
            },
193
            {
194
                "in": {
195
                    "dpid": "00:00:00:00:00:00:00:03",
196
                    "port": 2,
197
                },
198
                "out": {
199
                    "port": 1,
200
                },
201
            },
202
            {
203
                "in": {
204
                    "dpid": "00:00:00:00:00:00:00:03",
205
                    "port": 3,
206
                },
207
                "out": {
208
                    "port": 1,
209
                },
210
            },
211
            {
212
                "in": {
213
                    "dpid": "00:00:00:00:00:00:00:03",
214
                    "port": 3,
215
                },
216
                "out": {
217
                    "port": 1,
218
                },
219
            },
220
        ]
221
        trace_step = {
222
            "dpid": "00:00:00:00:00:00:00:03",
223
            "port": 3,
224
        }
225
226
        result = self.napp.has_loop(trace_step, trace_result)
227
228
        self.assertTrue(result)
229
230
    def test_has_loop__fail(self):
231
        """Test has_loop to detect a tracepath with loop."""
232
        trace_result = [
233
            {
234
                "in": {
235
                    "dpid": "00:00:00:00:00:00:00:01",
236
                    "port": 2,
237
                },
238
                "out": {
239
                    "port": 1,
240
                },
241
            },
242
            {
243
                "in": {
244
                    "dpid": "00:00:00:00:00:00:00:02",
245
                    "port": 2,
246
                },
247
                "out": {
248
                    "port": 1,
249
                },
250
            },
251
        ]
252
        trace_step = {
253
            "dpid": "00:00:00:00:00:00:00:03",
254
            "port": 2,
255
        }
256
257
        result = self.napp.has_loop(trace_step, trace_result)
258
259
        self.assertFalse(result)
260
261
    @patch("napps.amlight.sdntrace_cp.main.settings")
262
    def test_update_circuits(self, mock_settings):
263
        """Test update_circuits event listener with success."""
264
        mock_settings.FIND_CIRCUITS_IN_FLOWS = True
265
266
        self.napp.automate = MagicMock()
267
        self.napp.automate.find_circuits = MagicMock()
268
269
        event = MagicMock()
270
        self.napp.update_circuits(event)
271
272
        self.napp.automate.find_circuits.assert_called_once()
273
274
    @patch("napps.amlight.sdntrace_cp.main.settings")
275
    def test_update_circuits__no_settings(self, mock_settings):
276
        """Test update_circuits event listener without
277
        settings option enabled."""
278
        mock_settings.FIND_CIRCUITS_IN_FLOWS = False
279
280
        self.napp.automate = MagicMock()
281
        self.napp.automate.find_circuits = MagicMock()
282
283
        event = MagicMock()
284
        self.napp.update_circuits(event)
285
286
        self.napp.automate.find_circuits.assert_not_called()
287
288
    @patch("napps.amlight.sdntrace_cp.main.Main.get_stored_flows")
289
    def test_trace(self, mock_stored_flows):
290
        """Test trace rest call."""
291
        api = get_test_client(get_controller_mock(), self.napp)
292
        url = f"{self.server_name_url}/trace/"
293
294
        payload = {
295
            "trace": {
296
                "switch": {
297
                    "dpid": "00:00:00:00:00:00:00:01",
298
                    "in_port": 1
299
                    },
300
                "eth": {"dl_vlan": 100},
301
            }
302
        }
303
        stored_flows = {
304
            "00:00:00:00:00:00:00:01": {
305
                "flow": {
306
                    "table_id": 0,
307
                    "cookie": 84114964,
308
                    "hard_timeout": 0,
309
                    "idle_timeout": 0,
310
                    "priority": 10,
311
                },
312
                "flow_id": 1,
313
                "state": "installed",
314
                "switch": "00:00:00:00:00:00:00:01",
315
            }
316
        }
317
        mock_stored_flows.return_value = {
318
            "00:00:00:00:00:00:00:01": [stored_flows]
319
        }
320
321
        response = api.put(
322
            url, data=json.dumps(payload), content_type="application/json"
323
        )
324
        current_data = json.loads(response.data)
325
        result = current_data["result"]
326
327
        assert result[0]["dpid"] == "00:00:00:00:00:00:00:01"
328
        assert result[0]["port"] == 1
329
        assert result[0]["type"] == "starting"
330
        assert result[0]["vlan"] == 100
331
332 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.main.Main.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
333
    def test_traces(self, mock_stored_flows):
334
        """Test traces rest call for two traces with different switches."""
335
        api = get_test_client(get_controller_mock(), self.napp)
336
        url = f"{self.server_name_url}/traces/"
337
338
        payload = [
339
            {
340
                "trace": {
341
                    "switch": {
342
                        "dpid": "00:00:00:00:00:00:00:01",
343
                        "in_port": 1
344
                        },
345
                    "eth": {"dl_vlan": 100},
346
                }
347
            },
348
            {
349
                "trace": {
350
                    "switch": {
351
                        "dpid": "00:00:00:00:00:00:00:02",
352
                        "in_port": 1},
353
                    "eth": {"dl_vlan": 100},
354
                }
355
            }
356
        ]
357
358
        stored_flow = {
359
                "id": 1,
360
                "table_id": 0,
361
                "cookie": 84114964,
362
                "hard_timeout": 0,
363
                "idle_timeout": 0,
364
                "priority": 10,
365
        }
366
367
        mock_stored_flows.return_value = {
368
            "00:00:00:00:00:00:00:01": [stored_flow]
369
        }
370
371
        response = api.put(
372
            url, data=json.dumps(payload), content_type="application/json"
373
        )
374
        current_data = json.loads(response.data)
375
        result1 = current_data["00:00:00:00:00:00:00:01"]
376
        result2 = current_data["00:00:00:00:00:00:00:02"]
377
378
        assert result1[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
379
        assert result1[0][0]["port"] == 1
380
        assert result1[0][0]["type"] == "starting"
381
        assert result1[0][0]["vlan"] == 100
382
383
        assert result2[0][0]["dpid"] == "00:00:00:00:00:00:00:02"
384
        assert result2[0][0]["port"] == 1
385
        assert result2[0][0]["type"] == "starting"
386
        assert result2[0][0]["vlan"] == 100
387
388 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.main.Main.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
389
    def test_traces_same_switch(self, mock_stored_flows):
390
        """Test traces rest call for two traces with samw switches."""
391
        api = get_test_client(get_controller_mock(), self.napp)
392
        url = f"{self.server_name_url}/traces/"
393
394
        payload = [
395
            {
396
                "trace": {
397
                    "switch": {
398
                        "dpid": "00:00:00:00:00:00:00:01",
399
                        "in_port": 1
400
                    },
401
                    "eth": {"dl_vlan": 100},
402
                }
403
            },
404
            {
405
                "trace": {
406
                    "switch": {
407
                        "dpid": "00:00:00:00:00:00:00:01",
408
                        "in_port": 2
409
                    },
410
                    "eth": {"dl_vlan": 100},
411
                }
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
        result = current_data["00:00:00:00:00:00:00:01"]
433
434
        assert len(current_data) == 1
435
436
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
437
        assert result[0][0]["port"] == 1
438
        assert result[0][0]["type"] == "starting"
439
        assert result[0][0]["vlan"] == 100
440
441
        assert result[1][0]["dpid"] == "00:00:00:00:00:00:00:01"
442
        assert result[1][0]["port"] == 2
443
        assert result[1][0]["type"] == "starting"
444
        assert result[1][0]["vlan"] == 100
445
446
    @patch("napps.amlight.sdntrace_cp.main.Main.get_stored_flows")
447
    def test_traces_twice(self, mock_stored_flows):
448
        """Test traces rest call for two equal traces."""
449
        api = get_test_client(get_controller_mock(), self.napp)
450
        url = f"{self.server_name_url}/traces/"
451
452
        payload = [
453
            {
454
                "trace": {
455
                    "switch": {
456
                        "dpid": "00:00:00:00:00:00:00:01",
457
                        "in_port": 1
458
                        },
459
                    "eth": {"dl_vlan": 100},
460
                }
461
            },
462
            {
463
                "trace": {
464
                    "switch": {
465
                        "dpid": "00:00:00:00:00:00:00:01",
466
                        "in_port": 1
467
                        },
468
                    "eth": {"dl_vlan": 100},
469
                }
470
            }
471
        ]
472
        stored_flow = {
473
                "id": 1,
474
                "table_id": 0,
475
                "cookie": 84114964,
476
                "hard_timeout": 0,
477
                "idle_timeout": 0,
478
                "priority": 10,
479
        }
480
481
        mock_stored_flows.return_value = {
482
            "00:00:00:00:00:00:00:01": [stored_flow]
483
        }
484
485
        response = api.put(
486
            url, data=json.dumps(payload), content_type="application/json"
487
        )
488
        current_data = json.loads(response.data)
489
        result = current_data["00:00:00:00:00:00:00:01"]
490
491
        assert len(current_data) == 1
492
        assert len(result) == 1
493
494
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
495
        assert result[0][0]["port"] == 1
496
        assert result[0][0]["type"] == "starting"
497
        assert result[0][0]["vlan"] == 100
498