Passed
Pull Request — master (#85)
by
unknown
03:07
created

g_parameter()   A

Complexity

Conditions 1

Size

Total Lines 41
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 30
nop 2
dl 0
loc 41
rs 9.16
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
        sw1 = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
38
        intf_sw1 = get_interface_mock("eth1", 1, sw1)
39
        intf_sw1.link = None
40
        sw1.get_interface_by_port_no.return_value = intf_sw1
41
        sw2 = get_switch_mock("00:00:00:00:00:00:00:02", 0x04)
42
        intf_sw2 = get_interface_mock("eth1", 1, sw2)
43
        intf_sw2.link = None
44
        sw2.get_interface_by_port_no.return_value = intf_sw2
45
        self.napp.controller.switches = {sw1.dpid: sw1, sw2.dpid: sw2}
46
47
    @staticmethod
48
    def get_napp_urls(napp):
49
        """Return the amlight/sdntrace_cp urls.
50
51
        The urls will be like:
52
53
        urls = [
54
            (options, methods, url)
55
        ]
56
57
        """
58
        controller = napp.controller
59
        controller.api_server.register_napp_endpoints(napp)
60
61
        urls = []
62
        for rule in controller.api_server.app.url_map.iter_rules():
63
            options = {}
64
            for arg in rule.arguments:
65
                options[arg] = f"[{0}]".format(arg)
66
67
            if f"{napp.username}/{napp.name}" in str(rule):
68
                urls.append((options, rule.methods, f"{str(rule)}"))
69
70
        return urls
71
72
    def test_verify_api_urls(self):
73
        """Verify all APIs registered."""
74
75
        expected_urls = [
76
            (
77
                {},
78
                {"OPTIONS", "HEAD", "PUT"},
79
                "/api/amlight/sdntrace_cp/trace/ ",
80
            ),
81
            (
82
                {},
83
                {"OPTIONS", "HEAD", "PUT"},
84
                "/api/amlight/sdntrace_cp/traces/ ",
85
            ),
86
        ]
87
        urls = self.get_napp_urls(self.napp)
88
        self.assertEqual(len(expected_urls), len(urls))
89
90
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
91
    def test_trace_step(self, mock_flow_match):
92
        """Test trace_step success result."""
93
        mock_flow_match.return_value = ["1"], ["entries"], 1
94
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
95
96
        mock_interface = Interface("interface A", 1, MagicMock())
97
        mock_interface.address = "00:00:00:00:00:00:00:01"
98
99
        iface1 = get_interface_mock(
100
            "", 1, get_switch_mock("00:00:00:00:00:00:00:01")
101
        )
102
        iface2 = get_interface_mock(
103
            "", 2, get_switch_mock("00:00:00:00:00:00:00:02")
104
        )
105
        mock_interface.link = get_link_mock(iface1, iface2)
106
        mock_interface.link.endpoint_a.port_number = 1
107
        mock_interface.link.endpoint_a.port_number = 2
108
109
        # Patch for utils.find_endpoint
110
        switch.get_interface_by_port_no.return_value = mock_interface
111
112
        entries = MagicMock()
113
114
        stored_flows = {
115
            "flow": {
116
                "table_id": 0,
117
                "cookie": 84114964,
118
                "hard_timeout": 0,
119
                "idle_timeout": 0,
120
                "priority": 10,
121
            },
122
            "flow_id": 1,
123
            "state": "installed",
124
            "switch": "00:00:00:00:00:00:00:01",
125
        }
126
127
        stored_flows_arg = {
128
            "00:00:00:00:00:00:00:01": [stored_flows]
129
        }
130
131
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
132
133
        mock_flow_match.assert_called_once()
134
        self.assertEqual(
135
            result,
136
            {
137
                "dpid": "00:00:00:00:00:00:00:01",
138
                "in_port": 2,
139
                "out_port": 1,
140
                "entries": ["entries"],
141
            },
142
        )
143
144
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
145
    def test_trace_step__no_endpoint(self, mock_flow_match):
146
        """Test trace_step without endpoints available for switch/port."""
147
        mock_flow_match.return_value = ["1"], ["entries"], 1
148
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
149
150
        mock_interface = Interface("interface A", 1, MagicMock())
151
        mock_interface.address = "00:00:00:00:00:00:00:01"
152
        mock_interface.link = None
153
154
        # Patch for utils.find_endpoint
155
        switch.get_interface_by_port_no.return_value = mock_interface
156
157
        entries = MagicMock()
158
159
        stored_flows = {
160
            "flow": {
161
                "table_id": 0,
162
                "cookie": 84114964,
163
                "hard_timeout": 0,
164
                "idle_timeout": 0,
165
                "priority": 10,
166
            },
167
            "flow_id": 1,
168
            "state": "installed",
169
            "switch": "00:00:00:00:00:00:00:01",
170
        }
171
172
        stored_flows_arg = {
173
            "00:00:00:00:00:00:00:01": [stored_flows]
174
        }
175
176
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
177
178
        mock_flow_match.assert_called_once()
179
        self.assertEqual(result, {"entries": ["entries"], "out_port": 1})
180
181
    def test_trace_step__no_flow(self):
182
        """Test trace_step without flows for the switch."""
183
        switch = get_switch_mock("00:00:00:00:00:00:00:01")
184
        entries = MagicMock()
185
186
        stored_flows = {
187
            "flow": {
188
                "table_id": 0,
189
                "cookie": 84114964,
190
                "hard_timeout": 0,
191
                "idle_timeout": 0,
192
                "priority": 10,
193
            },
194
            "flow_id": 1,
195
            "state": "installed",
196
            "switch": "00:00:00:00:00:00:00:01",
197
        }
198
199
        stored_flows_arg = {
200
            "00:00:00:00:00:00:00:01": [stored_flows]
201
        }
202
203
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
204
        assert result is None
205
206
    @patch("napps.amlight.sdntrace_cp.main.Main.trace_step")
207
    def test_tracepath(self, mock_trace_step):
208
        """Test tracepath with success result."""
209
        eth = {"dl_vlan": 100}
210
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
211
        switch = {"switch": dpid, "eth": eth}
212
        entries = {"trace": switch}
213
        mock_trace_step.return_value = {
214
            "dpid": "00:00:00:00:00:00:00:02",
215
            "in_port": 2,
216
            "out_port": 3,
217
            "entries": entries,
218
        }
219
220
        stored_flows_arg = {
221
            "00:00:00:00:00:00:00:01": [],
222
            "00:00:00:00:00:00:00:02": [],
223
        }
224
225
        result = self.napp.tracepath(
226
                                        entries["trace"]["switch"],
227
                                        stored_flows_arg
228
                                    )
229
230
        assert result[0]["in"]["dpid"] == "00:00:00:00:00:00:00:01"
231
        assert result[0]["in"]["port"] == 1
232
        assert result[0]["in"]["type"] == "starting"
233
        assert result[0]["out"]["port"] == 3
234
235
        assert result[1]["in"]["dpid"] == "00:00:00:00:00:00:00:02"
236
        assert result[1]["in"]["port"] == 2
237
        assert result[1]["in"]["type"] == "intermediary"
238
        assert result[1]["out"]["port"] == 3
239
240
    @patch("napps.amlight.sdntrace_cp.main.Main.trace_step")
241
    def test_tracepath_loop(self, mock_trace_step):
242
        """Test tracepath with success result."""
243
        eth = {"dl_vlan": 100}
244
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
245
        switch = {"switch": dpid, "eth": eth}
246
        entries = {"trace": switch}
247
        mock_trace_step.return_value = {
248
            "dpid": "00:00:00:00:00:00:00:01",
249
            "in_port": 1,
250
            "out_port": 1,
251
            "entries": entries,
252
        }
253
254
        result = self.napp.tracepath(
255
                                        entries["trace"]["switch"],
256
                                        {}
257
                                    )
258
        assert len(result) == 2
259
        # input interface = output interface
260
        assert result[0]["in"]["type"] == "starting"
261
        assert result[1]["in"]["type"] == "loop"
262
263
    def test_has_loop(self):
264
        """Test has_loop to detect a tracepath with loop."""
265
        trace_result = [
266
            {
267
                "in": {
268
                    "dpid": "00:00:00:00:00:00:00:01",
269
                    "port": 2,
270
                },
271
                "out": {
272
                    "port": 1,
273
                },
274
            },
275
            {
276
                "in": {
277
                    "dpid": "00:00:00:00:00:00:00:03",
278
                    "port": 2,
279
                },
280
                "out": {
281
                    "port": 1,
282
                },
283
            },
284
            {
285
                "in": {
286
                    "dpid": "00:00:00:00:00:00:00:03",
287
                    "port": 3,
288
                },
289
                "out": {
290
                    "port": 1,
291
                },
292
            },
293
            {
294
                "in": {
295
                    "dpid": "00:00:00:00:00:00:00:03",
296
                    "port": 3,
297
                },
298
                "out": {
299
                    "port": 1,
300
                },
301
            },
302
        ]
303
        trace_step = {
304
            "dpid": "00:00:00:00:00:00:00:03",
305
            "port": 3,
306
        }
307
308
        result = self.napp.has_loop(trace_step, trace_result)
309
310
        self.assertTrue(result)
311
312
    def test_has_loop__fail(self):
313
        """Test has_loop to detect a tracepath with loop."""
314
        trace_result = [
315
            {
316
                "in": {
317
                    "dpid": "00:00:00:00:00:00:00:01",
318
                    "port": 2,
319
                },
320
                "out": {
321
                    "port": 1,
322
                },
323
            },
324
            {
325
                "in": {
326
                    "dpid": "00:00:00:00:00:00:00:02",
327
                    "port": 2,
328
                },
329
                "out": {
330
                    "port": 1,
331
                },
332
            },
333
        ]
334
        trace_step = {
335
            "dpid": "00:00:00:00:00:00:00:03",
336
            "port": 2,
337
        }
338
339
        result = self.napp.has_loop(trace_step, trace_result)
340
341
        self.assertFalse(result)
342
343
    @patch("napps.amlight.sdntrace_cp.main.settings")
344
    def test_update_circuits(self, mock_settings):
345
        """Test update_circuits event listener with success."""
346
        mock_settings.FIND_CIRCUITS_IN_FLOWS = True
347
348
        self.napp.automate = MagicMock()
349
        self.napp.automate.find_circuits = MagicMock()
350
351
        self.napp.update_circuits()
352
353
        self.napp.automate.find_circuits.assert_called_once()
354
355
    @patch("napps.amlight.sdntrace_cp.main.settings")
356
    def test_update_circuits__no_settings(self, mock_settings):
357
        """Test update_circuits event listener without
358
        settings option enabled."""
359
        mock_settings.FIND_CIRCUITS_IN_FLOWS = False
360
361
        self.napp.automate = MagicMock()
362
        self.napp.automate.find_circuits = MagicMock()
363
364
        self.napp.update_circuits()
365
366
        self.napp.automate.find_circuits.assert_not_called()
367
368
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
369
    def test_trace(self, mock_stored_flows):
370
        """Test trace rest call."""
371
        api = get_test_client(get_controller_mock(), self.napp)
372
        url = f"{self.server_name_url}/trace/"
373
374
        payload = {
375
            "trace": {
376
                "switch": {
377
                    "dpid": "00:00:00:00:00:00:00:01",
378
                    "in_port": 1
379
                    },
380
                "eth": {"dl_vlan": 100},
381
            }
382
        }
383
        stored_flows = {
384
                "flow": {
385
                    "table_id": 0,
386
                    "cookie": 84114964,
387
                    "hard_timeout": 0,
388
                    "idle_timeout": 0,
389
                    "priority": 10,
390
                    "match": {"dl_vlan": 100, "in_port": 1},
391
                    "actions": [
392
                        {"action_type": "push_vlan"},
393
                        {"action_type": "set_vlan", "vlan_id": 200},
394
                        {"action_type": "output", "port": 2}
395
                    ],
396
                },
397
                "flow_id": 1,
398
                "state": "installed",
399
                "switch": "00:00:00:00:00:00:00:01",
400
        }
401
        mock_stored_flows.return_value = {
402
            "00:00:00:00:00:00:00:01": [stored_flows]
403
        }
404
405
        response = api.put(
406
            url, data=json.dumps(payload), content_type="application/json"
407
        )
408
        current_data = json.loads(response.data)
409
        result = current_data["result"]
410
411
        assert len(result) == 1
412
        assert result[0]["dpid"] == "00:00:00:00:00:00:00:01"
413
        assert result[0]["port"] == 1
414
        assert result[0]["type"] == "last"
415
        assert result[0]["vlan"] == 100
416
        assert result[0]["out"] == {"port": 2, "vlan": 200}
417
418 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
419
    def test_get_traces(self, mock_stored_flows):
420
        """Test traces rest call."""
421
        api = get_test_client(get_controller_mock(), self.napp)
422
        url = f"{self.server_name_url}/traces/"
423
424
        payload = [{
425
            "trace": {
426
                "switch": {
427
                    "dpid": "00:00:00:00:00:00:00:01",
428
                    "in_port": 1
429
                    },
430
                "eth": {"dl_vlan": 100},
431
            }
432
        }]
433
434
        stored_flow = {
435
            "id": 1,
436
            "flow": {
437
                "table_id": 0,
438
                "cookie": 84114964,
439
                "hard_timeout": 0,
440
                "idle_timeout": 0,
441
                "priority": 10,
442
                "match": {"dl_vlan": 100, "in_port": 1},
443
                "actions": [
444
                    {"action_type": "pop_vlan"},
445
                    {"action_type": "output", "port": 2},
446
                ],
447
            }
448
        }
449
450
        mock_stored_flows.return_value = {
451
            "00:00:00:00:00:00:00:01": [stored_flow]
452
        }
453
454
        response = api.put(
455
            url, data=json.dumps(payload), content_type="application/json"
456
        )
457
        current_data = json.loads(response.data)
458
        result1 = current_data["result"]
459
460
        assert len(result1) == 1
461
        assert len(result1[0]) == 1
462
        assert result1[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
463
        assert result1[0][0]["port"] == 1
464
        assert result1[0][0]["type"] == "last"
465
        assert result1[0][0]["vlan"] == 100
466
        assert result1[0][0]["out"] == {"port": 2}
467
468
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
469
    def test_traces(self, mock_stored_flows):
470
        """Test traces rest call"""
471
        api = get_test_client(get_controller_mock(), self.napp)
472
        url = f"{self.server_name_url}/traces/"
473
474
        payload = [
475
                    {
476
                        "trace": {
477
                            "switch": {
478
                                "dpid": "00:00:00:00:00:00:00:01",
479
                                "in_port": 1
480
                            },
481
                            "eth": {
482
                                "dl_vlan": 100
483
                            }
484
                        }
485
                    },
486
                    {
487
                        "trace": {
488
                            "switch": {
489
                                "dpid": "00:00:00:00:00:00:00:0a",
490
                                "in_port": 1
491
                            },
492
                            "eth": {
493
                                "dl_vlan": 100
494
                            }
495
                        }
496
                    },
497
                    {
498
                        "trace": {
499
                            "switch": {
500
                                "dpid": "00:00:00:00:00:00:00:02",
501
                                "in_port": 2
502
                            },
503
                            "eth": {
504
                                "dl_vlan": 100
505
                            }
506
                        }
507
                    }
508
                ]
509
510
        stored_flow = {
511
            "id": 1,
512
            "flow": {
513
                "table_id": 0,
514
                "cookie": 84114964,
515
                "hard_timeout": 0,
516
                "idle_timeout": 0,
517
                "priority": 10,
518
                "match": {"dl_vlan": 100, "in_port": 1},
519
                "actions": [{"action_type": "output", "port": 2}],
520
            }
521
        }
522
523
        mock_stored_flows.return_value = {
524
            "00:00:00:00:00:00:00:01": [stored_flow],
525
            "00:00:00:00:00:00:00:02": [stored_flow],
526
        }
527
528
        response = api.put(
529
            url, data=json.dumps(payload), content_type="application/json"
530
        )
531
        current_data = json.loads(response.data)
532
        result = current_data["result"]
533
        assert len(result) == 3
534
535
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
536
        assert result[0][0]["port"] == 1
537
        assert result[0][0]["type"] == "last"
538
        assert result[0][0]["vlan"] == 100
539
        assert result[0][0]["out"] == {"port": 2, "vlan": 100}
540
541
        assert result[1][0]["dpid"] == "00:00:00:00:00:00:00:0a"
542
        assert result[1][0]["port"] == 1
543
        assert result[1][0]["type"] == "last"
544
        assert result[1][0]["vlan"] == 100
545
        assert result[1][0]["out"] is None
546
547
        assert result[2][0]["dpid"] == "00:00:00:00:00:00:00:02"
548
        assert result[2][0]["port"] == 2
549
        assert result[2][0]["type"] == "incomplete"
550
        assert result[2][0]["vlan"] == 100
551
        assert result[2][0]["out"] is None
552
553 View Code Duplication
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
554
    def test_traces_with_loop(self, mock_stored_flows):
555
        """Test traces rest call"""
556
        api = get_test_client(get_controller_mock(), self.napp)
557
        url = f"{self.server_name_url}/traces/"
558
559
        payload = [
560
                    {
561
                        "trace": {
562
                            "switch": {
563
                                "dpid": "00:00:00:00:00:00:00:01",
564
                                "in_port": 1
565
                            },
566
                            "eth": {
567
                                "dl_vlan": 100
568
                            }
569
                        }
570
                    }
571
                ]
572
573
        stored_flow = {
574
            "id": 1,
575
            "flow": {
576
                "table_id": 0,
577
                "cookie": 84114964,
578
                "hard_timeout": 0,
579
                "idle_timeout": 0,
580
                "priority": 10,
581
                "match": {"dl_vlan": 100, "in_port": 1},
582
                "actions": [{"action_type": "output", "port": 1}],
583
            }
584
        }
585
586
        mock_stored_flows.return_value = {
587
            "00:00:00:00:00:00:00:01": [stored_flow],
588
        }
589
590
        response = api.put(
591
            url, data=json.dumps(payload), content_type="application/json"
592
        )
593
        current_data = json.loads(response.data)
594
        result = current_data["result"]
595
        assert len(result) == 1
596
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
597
        assert result[0][0]["port"] == 1
598
        assert result[0][0]["type"] == "loop"
599
        assert result[0][0]["vlan"] == 100
600
        assert result[0][0]["out"] == {"port": 1, "vlan": 100}
601
602
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
603
    def test_traces_no_action(self, mock_stored_flows):
604
        """Test traces rest call for two traces with different switches."""
605
        api = get_test_client(get_controller_mock(), self.napp)
606
        url = f"{self.server_name_url}/traces/"
607
608
        payload = [
609
            {
610
                "trace": {
611
                    "switch": {
612
                        "dpid": "00:00:00:00:00:00:00:01",
613
                        "in_port": 1
614
                        },
615
                    "eth": {"dl_vlan": 100},
616
                }
617
            },
618
            {
619
                "trace": {
620
                    "switch": {
621
                        "dpid": "00:00:00:00:00:00:00:02",
622
                        "in_port": 1},
623
                    "eth": {"dl_vlan": 100},
624
                }
625
            }
626
        ]
627
628
        stored_flow1 = {
629
            "id": 1,
630
            "flow": {
631
                "table_id": 0,
632
                "cookie": 84114964,
633
                "hard_timeout": 0,
634
                "idle_timeout": 0,
635
                "priority": 10,
636
                "match": {"dl_vlan": 100, "in_port": 1}
637
            }
638
        }
639
        stored_flow2 = {
640
            "id": 1,
641
            "flow": {
642
                "table_id": 0,
643
                "cookie": 84114964,
644
                "hard_timeout": 0,
645
                "idle_timeout": 0,
646
                "priority": 10,
647
                "match": {"dl_vlan": 100, "in_port": 1},
648
                "actions": []
649
            }
650
        }
651
652
        mock_stored_flows.return_value = {
653
            "00:00:00:00:00:00:00:01": [stored_flow1],
654
            "00:00:00:00:00:00:00:02": [stored_flow2]
655
        }
656
657
        response = api.put(
658
            url, data=json.dumps(payload), content_type="application/json"
659
        )
660
        current_data = json.loads(response.data)
661
        result = current_data["result"]
662
        assert len(result) == 2
663
        assert result[0][-1]['type'] == "incomplete"
664
        assert result[1][-1]['type'] == "incomplete"
665
666
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
667
    def test_get_traces_untagged(self, mock_stored_flows):
668
        """Test traces rest call."""
669
        api = get_test_client(get_controller_mock(), self.napp)
670
        url = f"{self.server_name_url}/traces/"
671
672
        payload = [{
673
            "trace": {
674
                "switch": {
675
                    "dpid": "00:00:00:00:00:00:00:01",
676
                    "in_port": 1
677
                    },
678
                "eth": {"dl_vlan": 10},
679
            }
680
        }, {
681
            "trace": {
682
                "switch": {
683
                    "dpid": "00:00:00:00:00:00:00:01",
684
                    "in_port": 1
685
                    }
686
            }
687
        }
688
        ]
689
690
        stored_flow1 = {
691
            "flow": {
692
                "match": {"dl_vlan": 0, "in_port": 1},
693
                "actions": [
694
                    {"action_type": "pop_vlan"},
695
                    {"action_type": "output", "port": 2},
696
                ],
697
            }
698
        }
699
        stored_flow2 = {
700
            "flow": {
701
                "match": {"in_port": 1},
702
                "actions": [
703
                    {"action_type": "pop_vlan"},
704
                    {"action_type": "output", "port": 3},
705
                ],
706
            }
707
        }
708
        stored_flow3 = {
709
            "flow": {
710
                "match": {"dl_vlan": 10, "in_port": 1},
711
                "actions": [
712
                    {"action_type": "pop_vlan"},
713
                    {"action_type": "output", "port": 1},
714
                ],
715
            }
716
        }
717
        mock_stored_flows.return_value = {
718
            "00:00:00:00:00:00:00:01": [
719
                stored_flow1,
720
                stored_flow2,
721
                stored_flow3
722
            ]
723
        }
724
725
        response = api.put(
726
            url, data=json.dumps(payload), content_type="application/json"
727
        )
728
        current_data = json.loads(response.data)
729
        result = current_data["result"]
730
        assert result[0][0]["type"] == "last"
731
        assert result[0][0]["out"] == {"port": 3}
732
        assert result[1][0]["type"] == "last"
733
        assert result[1][0]["out"] == {"port": 2}
734
735
        mock_stored_flows.return_value = {
736
            "00:00:00:00:00:00:00:01": [
737
                stored_flow3,
738
                stored_flow2,
739
                stored_flow1
740
            ]
741
        }
742
743
        response = api.put(
744
            url, data=json.dumps(payload), content_type="application/json"
745
        )
746
        current_data = json.loads(response.data)
747
        result = current_data["result"]
748
        assert result[0][0]["type"] == "loop"
749
        assert result[0][0]["out"] == {"port": 1}
750
        assert result[1][0]["type"] == "last"
751
        assert result[1][0]["out"] == {"port": 3}
752
753
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
754
    def test_get_traces_any(self, mock_stored_flows):
755
        """Test traces rest call."""
756
        api = get_test_client(get_controller_mock(), self.napp)
757
        url = f"{self.server_name_url}/traces/"
758
759
        payload = [{
760
            "trace": {
761
                "switch": {
762
                    "dpid": "00:00:00:00:00:00:00:01",
763
                    "in_port": 1
764
                    },
765
                "eth": {"dl_vlan": 10}
766
            }
767
        }, {
768
            "trace": {
769
                "switch": {
770
                    "dpid": "00:00:00:00:00:00:00:01",
771
                    "in_port": 1
772
                    }
773
            }
774
        }
775
        ]
776
777
        stored_flow1 = {
778
            "flow": {
779
                "match": {"dl_vlan": "4096/4096", "in_port": 1},
780
                "actions": [
781
                    {"action_type": "pop_vlan"},
782
                    {"action_type": "output", "port": 2},
783
                ],
784
            }
785
        }
786
        stored_flow2 = {
787
            "flow": {
788
                "match": {"dl_vlan": 10, "in_port": 1},
789
                "actions": [
790
                    {"action_type": "pop_vlan"},
791
                    {"action_type": "output", "port": 1},
792
                ],
793
            }
794
        }
795
        stored_flow3 = {
796
            "flow": {
797
                "match": {"dl_vlan": "10/10", "in_port": 1},
798
                "actions": [
799
                    {"action_type": "pop_vlan"},
800
                    {"action_type": "output", "port": 3},
801
                ],
802
            }
803
        }
804
        stored_flow4 = {
805
            "flow": {
806
                "match": {"dl_vlan": "20/10", "in_port": 1},
807
                "actions": [
808
                    {"action_type": "pop_vlan"},
809
                    {"action_type": "output", "port": 1},
810
                ],
811
            }
812
        }
813
        mock_stored_flows.return_value = {
814
            "00:00:00:00:00:00:00:01": [
815
                stored_flow1,
816
                stored_flow2,
817
                stored_flow3,
818
                stored_flow4
819
            ]
820
        }
821
822
        response = api.put(
823
            url, data=json.dumps(payload), content_type="application/json"
824
        )
825
        current_data = json.loads(response.data)
826
        result = current_data["result"]
827
        assert result[0][0]["type"] == "last"
828
        assert result[0][0]["out"] == {"port": 2}
829
        assert result[1][0]["type"] == "incomplete"
830
        assert result[1][0]["out"] is None
831
832
        mock_stored_flows.return_value = {
833
            "00:00:00:00:00:00:00:01": [
834
                stored_flow4,
835
                stored_flow3,
836
                stored_flow2,
837
                stored_flow1
838
            ]
839
        }
840
841
        response = api.put(
842
            url, data=json.dumps(payload), content_type="application/json"
843
        )
844
        current_data = json.loads(response.data)
845
        result = current_data["result"]
846
        assert result[0][0]["type"] == "last"
847
        assert result[0][0]["out"] == {"port": 3}
848
        assert result[1][0]["type"] == "incomplete"
849
        assert result[1][0]["out"] is None
850