Passed
Push — master ( 8e49b2...5f8a07 )
by
unknown
04:50 queued 14s
created

TestMain.test_goto_table_1_switch()   B

Complexity

Conditions 1

Size

Total Lines 125
Code Lines 76

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 125
ccs 30
cts 30
cp 1
rs 7.7854
c 0
b 0
f 0
cc 1
nop 3
crap 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
"""Module to test the main napp file."""
2 1
import pytest
3 1
from unittest.mock import patch, MagicMock
4
5 1
from kytos.core.interface import Interface
6 1
from kytos.lib.helpers import (
7
    get_interface_mock,
8
    get_switch_mock,
9
    get_controller_mock,
10
    get_link_mock,
11
    get_test_client,
12
)
13 1
from kytos.core.rest_api import HTTPException
14
15
16
# pylint: disable=too-many-public-methods, too-many-lines
17 1
class TestMain:
18
    """Test the Main class."""
19
20 1
    def setup_method(self):
21
        """Execute steps before each tests."""
22
        # The decorator run_on_thread is patched, so methods that listen
23
        # for events do not run on threads while tested.
24
        # Decorators have to be patched before the methods that are
25
        # decorated with them are imported.
26 1
        patch("kytos.core.helpers.run_on_thread", lambda x: x).start()
27
        # pylint: disable=import-outside-toplevel
28 1
        from napps.amlight.sdntrace_cp.main import Main
29
30 1
        controller = get_controller_mock()
31 1
        self.napp = Main(controller)
32
33 1
        sw1 = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
34 1
        intf_sw1 = get_interface_mock("eth1", 1, sw1)
35 1
        intf_sw1.link = None
36 1
        sw1.get_interface_by_port_no.return_value = intf_sw1
37 1
        sw2 = get_switch_mock("00:00:00:00:00:00:00:02", 0x04)
38 1
        intf_sw2 = get_interface_mock("eth1", 1, sw2)
39 1
        intf_sw2.link = None
40 1
        sw2.get_interface_by_port_no.return_value = intf_sw2
41 1
        self.napp.controller.switches = {sw1.dpid: sw1, sw2.dpid: sw2}
42 1
        self.api_client = get_test_client(controller, self.napp)
43 1
        self.base_endpoint = "amlight/sdntrace_cp/v1"
44 1
        self.trace_endpoint = f"{self.base_endpoint}/trace"
45 1
        self.traces_endpoint = f"{self.base_endpoint}/traces"
46
47 1
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
48 1
    def test_trace_step(self, mock_flow_match):
49
        """Test trace_step success result."""
50 1
        mock_flow_match.return_value = ["1"], ["entries"], 1
51 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
52
53 1
        mock_interface = Interface("interface A", 1, MagicMock())
54 1
        mock_interface.address = "00:00:00:00:00:00:00:01"
55
56 1
        iface1 = get_interface_mock(
57
            "", 1, get_switch_mock("00:00:00:00:00:00:00:01")
58
        )
59 1
        iface2 = get_interface_mock(
60
            "", 2, get_switch_mock("00:00:00:00:00:00:00:02")
61
        )
62 1
        mock_interface.link = get_link_mock(iface1, iface2)
63 1
        mock_interface.link.endpoint_a.port_number = 1
64 1
        mock_interface.link.endpoint_a.port_number = 2
65
66
        # Patch for utils.find_endpoint
67 1
        switch.get_interface_by_port_no.return_value = mock_interface
68
69 1
        entries = MagicMock()
70
71 1
        stored_flows = {
72
            "flow": {
73
                "table_id": 0,
74
                "cookie": 84114964,
75
                "hard_timeout": 0,
76
                "idle_timeout": 0,
77
                "priority": 10,
78
            },
79
            "flow_id": 1,
80
            "state": "installed",
81
            "switch": "00:00:00:00:00:00:00:01",
82
        }
83
84 1
        stored_flows_arg = {
85
            "00:00:00:00:00:00:00:01": [stored_flows]
86
        }
87
88 1
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
89
90 1
        mock_flow_match.assert_called_once()
91 1
        assert result == {
92
                    "dpid": "00:00:00:00:00:00:00:01",
93
                    "in_port": 2,
94
                    "out_port": 1,
95
                    "entries": ["entries"],
96
                }
97
98 1
    @patch("napps.amlight.sdntrace_cp.main.Main.match_and_apply")
99 1
    def test_trace_step__no_endpoint(self, mock_flow_match):
100
        """Test trace_step without endpoints available for switch/port."""
101 1
        mock_flow_match.return_value = ["1"], ["entries"], 1
102 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
103
104 1
        mock_interface = Interface("interface A", 1, MagicMock())
105 1
        mock_interface.address = "00:00:00:00:00:00:00:01"
106 1
        mock_interface.link = None
107
108
        # Patch for utils.find_endpoint
109 1
        switch.get_interface_by_port_no.return_value = mock_interface
110
111 1
        entries = MagicMock()
112
113 1
        stored_flows = {
114
            "flow": {
115
                "table_id": 0,
116
                "cookie": 84114964,
117
                "hard_timeout": 0,
118
                "idle_timeout": 0,
119
                "priority": 10,
120
            },
121
            "flow_id": 1,
122
            "state": "installed",
123
            "switch": "00:00:00:00:00:00:00:01",
124
        }
125
126 1
        stored_flows_arg = {
127
            "00:00:00:00:00:00:00:01": [stored_flows]
128
        }
129
130 1
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
131
132 1
        mock_flow_match.assert_called_once()
133 1
        assert result == {"entries": ["entries"], "out_port": 1}
134
135 1
    def test_trace_step__no_flow(self):
136
        """Test trace_step without flows for the switch."""
137 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01")
138 1
        entries = MagicMock()
139
140 1
        stored_flows = {
141
            "flow": {
142
                "table_id": 0,
143
                "cookie": 84114964,
144
                "hard_timeout": 0,
145
                "idle_timeout": 0,
146
                "priority": 10,
147
            },
148
            "flow_id": 1,
149
            "state": "installed",
150
            "switch": "00:00:00:00:00:00:00:01",
151
        }
152
153 1
        stored_flows_arg = {
154
            "00:00:00:00:00:00:00:01": [stored_flows]
155
        }
156
157 1
        result = self.napp.trace_step(switch, entries, stored_flows_arg)
158 1
        assert result is None
159
160 1
    @patch("napps.amlight.sdntrace_cp.main.Main.trace_step")
161 1
    def test_tracepath(self, mock_trace_step):
162
        """Test tracepath with success result."""
163 1
        eth = {"dl_vlan": 100}
164 1
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
165 1
        switch = {"switch": dpid, "eth": eth}
166 1
        entries = {"trace": switch}
167 1
        mock_trace_step.return_value = {
168
            "dpid": "00:00:00:00:00:00:00:02",
169
            "in_port": 2,
170
            "out_port": 3,
171
            "entries": entries,
172
        }
173
174 1
        stored_flows_arg = {
175
            "00:00:00:00:00:00:00:01": [],
176
            "00:00:00:00:00:00:00:02": [],
177
        }
178
179 1
        result = self.napp.tracepath(
180
                                        entries["trace"]["switch"],
181
                                        stored_flows_arg
182
                                    )
183
184 1
        assert result[0]["in"]["dpid"] == "00:00:00:00:00:00:00:01"
185 1
        assert result[0]["in"]["port"] == 1
186 1
        assert result[0]["in"]["type"] == "starting"
187 1
        assert result[0]["out"]["port"] == 3
188
189 1
        assert result[1]["in"]["dpid"] == "00:00:00:00:00:00:00:02"
190 1
        assert result[1]["in"]["port"] == 2
191 1
        assert result[1]["in"]["type"] == "intermediary"
192 1
        assert result[1]["out"]["port"] == 3
193
194 1
    @patch("napps.amlight.sdntrace_cp.main.Main.trace_step")
195 1
    def test_tracepath_loop(self, mock_trace_step):
196
        """Test tracepath with success result."""
197 1
        eth = {"dl_vlan": 100}
198 1
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
199 1
        switch = {"switch": dpid, "eth": eth}
200 1
        entries = {"trace": switch}
201 1
        mock_trace_step.return_value = {
202
            "dpid": "00:00:00:00:00:00:00:01",
203
            "in_port": 1,
204
            "out_port": 1,
205
            "entries": entries,
206
        }
207
208 1
        result = self.napp.tracepath(
209
                                        entries["trace"]["switch"],
210
                                        {}
211
                                    )
212 1
        assert len(result) == 2
213
        # input interface = output interface
214 1
        assert result[0]["in"]["type"] == "starting"
215 1
        assert result[1]["in"]["type"] == "loop"
216
217 1
    def test_has_loop(self):
218
        """Test has_loop to detect a tracepath with loop."""
219 1
        trace_result = [
220
            {
221
                "in": {
222
                    "dpid": "00:00:00:00:00:00:00:01",
223
                    "port": 2,
224
                },
225
                "out": {
226
                    "port": 1,
227
                },
228
            },
229
            {
230
                "in": {
231
                    "dpid": "00:00:00:00:00:00:00:03",
232
                    "port": 2,
233
                },
234
                "out": {
235
                    "port": 1,
236
                },
237
            },
238
            {
239
                "in": {
240
                    "dpid": "00:00:00:00:00:00:00:03",
241
                    "port": 3,
242
                },
243
                "out": {
244
                    "port": 1,
245
                },
246
            },
247
            {
248
                "in": {
249
                    "dpid": "00:00:00:00:00:00:00:03",
250
                    "port": 3,
251
                },
252
                "out": {
253
                    "port": 1,
254
                },
255
            },
256
        ]
257 1
        trace_step = {
258
            "dpid": "00:00:00:00:00:00:00:03",
259
            "port": 3,
260
        }
261
262 1
        result = self.napp.has_loop(trace_step, trace_result)
263 1
        assert result
264
265 1
    def test_has_loop__fail(self):
266
        """Test has_loop to detect a tracepath with loop."""
267 1
        trace_result = [
268
            {
269
                "in": {
270
                    "dpid": "00:00:00:00:00:00:00:01",
271
                    "port": 2,
272
                },
273
                "out": {
274
                    "port": 1,
275
                },
276
            },
277
            {
278
                "in": {
279
                    "dpid": "00:00:00:00:00:00:00:02",
280
                    "port": 2,
281
                },
282
                "out": {
283
                    "port": 1,
284
                },
285
            },
286
        ]
287 1
        trace_step = {
288
            "dpid": "00:00:00:00:00:00:00:03",
289
            "port": 2,
290
        }
291
292 1
        result = self.napp.has_loop(trace_step, trace_result)
293 1
        assert not result
294
295 1 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...
296 1
    async def test_trace(self, mock_stored_flows, event_loop):
297
        """Test trace rest call."""
298 1
        self.napp.controller.loop = event_loop
299 1
        payload = {
300
            "trace": {
301
                "switch": {
302
                    "dpid": "00:00:00:00:00:00:00:01",
303
                    "in_port": 1
304
                    },
305
                "eth": {"dl_vlan": 100},
306
            }
307
        }
308 1
        stored_flows = {
309
                "flow": {
310
                    "table_id": 0,
311
                    "cookie": 84114964,
312
                    "hard_timeout": 0,
313
                    "idle_timeout": 0,
314
                    "priority": 10,
315
                    "match": {"dl_vlan": 100, "in_port": 1},
316
                    "actions": [
317
                        {"action_type": "push_vlan"},
318
                        {"action_type": "set_vlan", "vlan_id": 200},
319
                        {"action_type": "output", "port": 2}
320
                    ],
321
                },
322
                "flow_id": 1,
323
                "state": "installed",
324
                "switch": "00:00:00:00:00:00:00:01",
325
        }
326 1
        mock_stored_flows.return_value = {
327
            "00:00:00:00:00:00:00:01": [stored_flows]
328
        }
329
330 1
        resp = await self.api_client.put(self.trace_endpoint, json=payload)
331 1
        assert resp.status_code == 200
332 1
        current_data = resp.json()
333 1
        result = current_data["result"]
334
335 1
        assert len(result) == 1
336 1
        assert result[0]["dpid"] == "00:00:00:00:00:00:00:01"
337 1
        assert result[0]["port"] == 1
338 1
        assert result[0]["type"] == "last"
339 1
        assert result[0]["vlan"] == 100
340 1
        assert result[0]["out"] == {"port": 2, "vlan": 200}
341
342 1 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...
343 1
    async def test_trace_instructions(self, mock_stored_flows, event_loop):
344
        """Test trace rest call with instructions."""
345 1
        self.napp.controller.loop = event_loop
346 1
        payload = {
347
            "trace": {
348
                "switch": {
349
                    "dpid": "00:00:00:00:00:00:00:01",
350
                    "in_port": 1
351
                    },
352
                "eth": {"dl_vlan": 100},
353
            }
354
        }
355 1
        stored_flows = {
356
                "flow": {
357
                    "table_id": 0,
358
                    "cookie": 84114964,
359
                    "hard_timeout": 0,
360
                    "idle_timeout": 0,
361
                    "priority": 10,
362
                    "match": {"dl_vlan": 100, "in_port": 1},
363
                    "instructions": [
364
                        {
365
                            "instruction_type": "apply_actions",
366
                            "actions": [
367
                                {"action_type": "push_vlan"},
368
                                {"action_type": "set_vlan", "vlan_id": 200},
369
                                {"action_type": "output", "port": 2}
370
                            ]
371
                        }
372
                    ]
373
                },
374
                "flow_id": 1,
375
                "state": "installed",
376
                "switch": "00:00:00:00:00:00:00:01",
377
        }
378 1
        mock_stored_flows.return_value = {
379
            "00:00:00:00:00:00:00:01": [stored_flows]
380
        }
381
382 1
        resp = await self.api_client.put(self.trace_endpoint, json=payload)
383 1
        assert resp.status_code == 200
384 1
        current_data = resp.json()
385 1
        result = current_data["result"]
386
387 1
        assert len(result) == 1
388 1
        assert result[0]["dpid"] == "00:00:00:00:00:00:00:01"
389 1
        assert result[0]["port"] == 1
390 1
        assert result[0]["type"] == "last"
391 1
        assert result[0]["vlan"] == 100
392 1
        assert result[0]["out"] == {"port": 2, "vlan": 200}
393
394 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
395 1
    async def test_instructions_no_match(self, mock_stored_flows, event_loop):
396
        """Test a no match for trace rest call with instructions."""
397 1
        self.napp.controller.loop = event_loop
398 1
        payload = {
399
            "trace": {
400
                "switch": {
401
                    "dpid": "00:00:00:00:00:00:00:01",
402
                    "in_port": 1
403
                    },
404
                "eth": {"dl_vlan": 100},
405
            }
406
        }
407 1
        stored_flows = {
408
                "flow": {
409
                    "table_id": 0,
410
                    "cookie": 84114964,
411
                    "hard_timeout": 0,
412
                    "idle_timeout": 0,
413
                    "priority": 10,
414
                    "match": {"dl_vlan": 100, "in_port": 1},
415
                    "instructions": [
416
                        {
417
                            "instruction_type": "apply_actions",
418
                            "actions": [
419
                                {"action_type": "push_vlan"},
420
                                {"action_type": "set_vlan", "vlan_id": 200}
421
                            ]
422
                        }
423
                    ]
424
                },
425
                "flow_id": 1,
426
                "state": "installed",
427
                "switch": "00:00:00:00:00:00:00:01",
428
        }
429 1
        mock_stored_flows.return_value = {
430
            "00:00:00:00:00:00:00:01": [stored_flows]
431
        }
432
433 1
        resp = await self.api_client.put(self.trace_endpoint, json=payload)
434 1
        assert resp.status_code == 200
435 1
        current_data = resp.json()
436 1
        result = current_data["result"]
437 1
        assert result == []
438
439 1 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...
440 1
    async def test_get_traces(self, mock_stored_flows, event_loop):
441
        """Test traces rest call."""
442 1
        self.napp.controller.loop = event_loop
443 1
        payload = [{
444
            "trace": {
445
                "switch": {
446
                    "dpid": "00:00:00:00:00:00:00:01",
447
                    "in_port": 1
448
                    },
449
                "eth": {"dl_vlan": 100},
450
            }
451
        }]
452
453 1
        stored_flow = {
454
            "id": 1,
455
            "flow": {
456
                "table_id": 0,
457
                "cookie": 84114964,
458
                "hard_timeout": 0,
459
                "idle_timeout": 0,
460
                "priority": 10,
461
                "match": {"dl_vlan": 100, "in_port": 1},
462
                "actions": [
463
                    {"action_type": "pop_vlan"},
464
                    {"action_type": "output", "port": 2},
465
                ],
466
            }
467
        }
468
469 1
        mock_stored_flows.return_value = {
470
            "00:00:00:00:00:00:00:01": [stored_flow]
471
        }
472
473 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
474 1
        assert resp.status_code == 200
475 1
        current_data = resp.json()
476 1
        result1 = current_data["result"]
477
478 1
        assert len(result1) == 1
479 1
        assert len(result1[0]) == 1
480 1
        assert result1[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
481 1
        assert result1[0][0]["port"] == 1
482 1
        assert result1[0][0]["type"] == "last"
483 1
        assert result1[0][0]["vlan"] == 100
484 1
        assert result1[0][0]["out"] == {"port": 2}
485
486 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
487 1
    async def test_traces(self, mock_stored_flows, event_loop):
488
        """Test traces rest call"""
489 1
        self.napp.controller.loop = event_loop
490 1
        payload = [
491
                    {
492
                        "trace": {
493
                            "switch": {
494
                                "dpid": "00:00:00:00:00:00:00:01",
495
                                "in_port": 1
496
                            },
497
                            "eth": {
498
                                "dl_vlan": 100
499
                            }
500
                        }
501
                    },
502
                    {
503
                        "trace": {
504
                            "switch": {
505
                                "dpid": "00:00:00:00:00:00:00:0a",
506
                                "in_port": 1
507
                            },
508
                            "eth": {
509
                                "dl_vlan": 100
510
                            }
511
                        }
512
                    },
513
                    {
514
                        "trace": {
515
                            "switch": {
516
                                "dpid": "00:00:00:00:00:00:00:02",
517
                                "in_port": 2
518
                            },
519
                            "eth": {
520
                                "dl_vlan": 100
521
                            }
522
                        }
523
                    }
524
                ]
525
526 1
        stored_flow = {
527
            "id": 1,
528
            "flow": {
529
                "table_id": 0,
530
                "cookie": 84114964,
531
                "hard_timeout": 0,
532
                "idle_timeout": 0,
533
                "priority": 10,
534
                "match": {"dl_vlan": 100, "in_port": 1},
535
                "actions": [{"action_type": "output", "port": 2}],
536
            }
537
        }
538
539 1
        mock_stored_flows.return_value = {
540
            "00:00:00:00:00:00:00:01": [stored_flow],
541
            "00:00:00:00:00:00:00:02": [stored_flow],
542
        }
543
544 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
545 1
        assert resp.status_code == 200
546 1
        current_data = resp.json()
547 1
        result = current_data["result"]
548 1
        assert len(result) == 3
549
550 1
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
551 1
        assert result[0][0]["port"] == 1
552 1
        assert result[0][0]["type"] == "last"
553 1
        assert result[0][0]["vlan"] == 100
554 1
        assert result[0][0]["out"] == {"port": 2, "vlan": 100}
555
556 1
        assert result[1][0]["dpid"] == "00:00:00:00:00:00:00:0a"
557 1
        assert result[1][0]["port"] == 1
558 1
        assert result[1][0]["type"] == "last"
559 1
        assert result[1][0]["vlan"] == 100
560 1
        assert result[1][0]["out"] is None
561
562 1
        assert len(result[2]) == 0
563
564 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
565 1
    async def test_traces_fail(self, mock_stored_flows, event_loop):
566
        """Test traces with a failed dependency."""
567 1
        self.napp.controller.loop = event_loop
568 1
        mock_stored_flows.side_effect = HTTPException(424, "failed")
569 1
        payload = [{
570
            "trace": {
571
                "switch": {
572
                    "dpid": "00:00:00:00:00:00:00:01",
573
                    "in_port": 1
574
                    },
575
                "eth": {"dl_vlan": 100},
576
            }
577
        }]
578 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
579 1
        assert resp.status_code == 424
580
581 1 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...
582 1
    async def test_traces_with_loop(self, mock_stored_flows, event_loop):
583
        """Test traces rest call"""
584 1
        self.napp.controller.loop = event_loop
585 1
        payload = [
586
                    {
587
                        "trace": {
588
                            "switch": {
589
                                "dpid": "00:00:00:00:00:00:00:01",
590
                                "in_port": 1
591
                            },
592
                            "eth": {
593
                                "dl_vlan": 100
594
                            }
595
                        }
596
                    }
597
                ]
598
599 1
        stored_flow = {
600
            "id": 1,
601
            "flow": {
602
                "table_id": 0,
603
                "cookie": 84114964,
604
                "hard_timeout": 0,
605
                "idle_timeout": 0,
606
                "priority": 10,
607
                "match": {"dl_vlan": 100, "in_port": 1},
608
                "actions": [{"action_type": "output", "port": 1}],
609
            }
610
        }
611
612 1
        mock_stored_flows.return_value = {
613
            "00:00:00:00:00:00:00:01": [stored_flow],
614
        }
615
616 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
617 1
        assert resp.status_code == 200
618 1
        current_data = resp.json()
619 1
        result = current_data["result"]
620 1
        assert len(result) == 1
621 1
        assert result[0][0]["dpid"] == "00:00:00:00:00:00:00:01"
622 1
        assert result[0][0]["port"] == 1
623 1
        assert result[0][0]["type"] == "loop"
624 1
        assert result[0][0]["vlan"] == 100
625 1
        assert result[0][0]["out"] == {"port": 1, "vlan": 100}
626
627 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
628 1
    async def test_traces_no_action(self, mock_stored_flows, event_loop):
629
        """Test traces rest call for two traces with different switches."""
630 1
        self.napp.controller.loop = event_loop
631 1
        payload = [
632
            {
633
                "trace": {
634
                    "switch": {
635
                        "dpid": "00:00:00:00:00:00:00:01",
636
                        "in_port": 1
637
                        },
638
                    "eth": {"dl_vlan": 100},
639
                }
640
            },
641
            {
642
                "trace": {
643
                    "switch": {
644
                        "dpid": "00:00:00:00:00:00:00:02",
645
                        "in_port": 1},
646
                    "eth": {"dl_vlan": 100},
647
                }
648
            }
649
        ]
650
651 1
        stored_flow1 = {
652
            "id": 1,
653
            "flow": {
654
                "table_id": 0,
655
                "cookie": 84114964,
656
                "hard_timeout": 0,
657
                "idle_timeout": 0,
658
                "priority": 10,
659
                "match": {"dl_vlan": 100, "in_port": 1}
660
            }
661
        }
662 1
        stored_flow2 = {
663
            "id": 1,
664
            "flow": {
665
                "table_id": 0,
666
                "cookie": 84114964,
667
                "hard_timeout": 0,
668
                "idle_timeout": 0,
669
                "priority": 10,
670
                "match": {"dl_vlan": 100, "in_port": 1},
671
                "actions": []
672
            }
673
        }
674
675 1
        mock_stored_flows.return_value = {
676
            "00:00:00:00:00:00:00:01": [stored_flow1],
677
            "00:00:00:00:00:00:00:02": [stored_flow2]
678
        }
679
680 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
681 1
        assert resp.status_code == 200
682 1
        current_data = resp.json()
683 1
        result = current_data["result"]
684 1
        assert len(result) == 2
685 1
        assert len(result[0]) == 0
686 1
        assert len(result[1]) == 0
687
688 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
689 1
    async def test_get_traces_untagged(self, mock_stored_flows, event_loop):
690
        """Test traces rest call."""
691 1
        self.napp.controller.loop = event_loop
692 1
        payload = [{
693
            "trace": {
694
                "switch": {
695
                    "dpid": "00:00:00:00:00:00:00:01",
696
                    "in_port": 1
697
                    },
698
                "eth": {"dl_vlan": 10},
699
            }
700
        }, {
701
            "trace": {
702
                "switch": {
703
                    "dpid": "00:00:00:00:00:00:00:01",
704
                    "in_port": 1
705
                    }
706
            }
707
        }
708
        ]
709
710 1
        stored_flow1 = {
711
            "flow": {
712
                "match": {"dl_vlan": 0, "in_port": 1},
713
                "actions": [
714
                    {"action_type": "pop_vlan"},
715
                    {"action_type": "output", "port": 2},
716
                ],
717
            }
718
        }
719 1
        stored_flow2 = {
720
            "flow": {
721
                "match": {"in_port": 1},
722
                "actions": [
723
                    {"action_type": "pop_vlan"},
724
                    {"action_type": "output", "port": 3},
725
                ],
726
            }
727
        }
728 1
        stored_flow3 = {
729
            "flow": {
730
                "match": {"dl_vlan": 10, "in_port": 1},
731
                "actions": [
732
                    {"action_type": "pop_vlan"},
733
                    {"action_type": "output", "port": 1},
734
                ],
735
            }
736
        }
737 1
        mock_stored_flows.return_value = {
738
            "00:00:00:00:00:00:00:01": [
739
                stored_flow1,
740
                stored_flow2,
741
                stored_flow3
742
            ]
743
        }
744
745 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
746 1
        assert resp.status_code == 200
747 1
        current_data = resp.json()
748
749 1
        result = current_data["result"]
750 1
        assert result[0][0]["type"] == "last"
751 1
        assert result[0][0]["out"] == {"port": 3}
752 1
        assert result[1][0]["type"] == "last"
753 1
        assert result[1][0]["out"] == {"port": 2}
754
755 1
        mock_stored_flows.return_value = {
756
            "00:00:00:00:00:00:00:01": [
757
                stored_flow3,
758
                stored_flow2,
759
                stored_flow1
760
            ]
761
        }
762
763 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
764 1
        assert resp.status_code == 200
765 1
        current_data = resp.json()
766 1
        result = current_data["result"]
767 1
        assert result[0][0]["type"] == "loop"
768 1
        assert result[0][0]["out"] == {"port": 1}
769 1
        assert result[1][0]["type"] == "last"
770 1
        assert result[1][0]["out"] == {"port": 3}
771
772 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
773 1
    async def test_get_traces_any(self, mock_stored_flows, event_loop):
774
        """Test traces rest call."""
775 1
        self.napp.controller.loop = event_loop
776 1
        payload = [{
777
            "trace": {
778
                "switch": {
779
                    "dpid": "00:00:00:00:00:00:00:01",
780
                    "in_port": 1
781
                    },
782
                "eth": {"dl_vlan": 10}
783
            }
784
        }, {
785
            "trace": {
786
                "switch": {
787
                    "dpid": "00:00:00:00:00:00:00:01",
788
                    "in_port": 1
789
                    }
790
            }
791
        }
792
        ]
793
794 1
        stored_flow1 = {
795
            "flow": {
796
                "match": {"dl_vlan": "4096/4096", "in_port": 1},
797
                "actions": [
798
                    {"action_type": "pop_vlan"},
799
                    {"action_type": "output", "port": 2},
800
                ],
801
            }
802
        }
803 1
        stored_flow2 = {
804
            "flow": {
805
                "match": {"dl_vlan": 10, "in_port": 1},
806
                "actions": [
807
                    {"action_type": "pop_vlan"},
808
                    {"action_type": "output", "port": 1},
809
                ],
810
            }
811
        }
812 1
        stored_flow3 = {
813
            "flow": {
814
                "match": {"dl_vlan": "10/10", "in_port": 1},
815
                "actions": [
816
                    {"action_type": "pop_vlan"},
817
                    {"action_type": "output", "port": 3},
818
                ],
819
            }
820
        }
821 1
        stored_flow4 = {
822
            "flow": {
823
                "match": {"dl_vlan": "20/10", "in_port": 1},
824
                "actions": [
825
                    {"action_type": "pop_vlan"},
826
                    {"action_type": "output", "port": 1},
827
                ],
828
            }
829
        }
830 1
        mock_stored_flows.return_value = {
831
            "00:00:00:00:00:00:00:01": [
832
                stored_flow1,
833
                stored_flow2,
834
                stored_flow3,
835
                stored_flow4
836
            ]
837
        }
838
839 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
840 1
        assert resp.status_code == 200
841 1
        current_data = resp.json()
842 1
        result = current_data["result"]
843 1
        assert result[0][0]["type"] == "last"
844 1
        assert result[0][0]["out"] == {"port": 2}
845 1
        assert len(result[1]) == 0
846
847 1
        mock_stored_flows.return_value = {
848
            "00:00:00:00:00:00:00:01": [
849
                stored_flow4,
850
                stored_flow3,
851
                stored_flow2,
852
                stored_flow1
853
            ]
854
        }
855
856 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
857 1
        assert resp.status_code == 200
858 1
        current_data = resp.json()
859 1
        result = current_data["result"]
860 1
        assert result[0][0]["type"] == "last"
861 1
        assert result[0][0]["out"] == {"port": 3}
862 1
        assert len(result[1]) == 0
863
864 1
    @pytest.mark.parametrize(
865
        "flow,args,match",
866
        [
867
            (
868
                {'flow': {'match': {'dl_vlan': 10}}},
869
                {'dl_vlan': [10]},
870
                {'flow': {'match': {'dl_vlan': 10}}},
871
            ),
872
            (
873
                {'flow': {'match': {'dl_vlan': 0}}},
874
                {},
875
                {'flow': {'match': {'dl_vlan': 0}}},
876
            ),
877
            (
878
                {'flow': {'match': {'dl_vlan': '10/10'}}},
879
                {'dl_vlan': [10]},
880
                {'flow': {'match': {'dl_vlan': '10/10'}}},
881
            ),
882
            (
883
                {'flow': {'match': {'dl_vlan': '10/10'}}},
884
                {'dl_vlan': [2]},
885
                False,
886
            ),
887
            (
888
                {'flow': {'match': {
889
                                    'nw_src': '192.168.20.21/10',
890
                                    'nw_dst': '192.168.20.21/32',
891
                                    'ipv6_src': '2002:db8::8a3f:362:7897/10',
892
                                    'ipv6_dst': '2002:db8::8a3f:362:7897/128',
893
                                    }
894
                          },
895
                 },
896
                {
897
                        'nw_src': '192.168.20.21',
898
                        'nw_dst': '192.168.20.21',
899
                        'ipv6_src': '2002:db8::8a3f:362:7897',
900
                        'ipv6_dst': '2002:db8::8a3f:362:7897',
901
                },
902
                {'flow': {'match': {
903
                                    'nw_src': '192.168.20.21/10',
904
                                    'nw_dst': '192.168.20.21/32',
905
                                    'ipv6_src': '2002:db8::8a3f:362:7897/10',
906
                                    'ipv6_dst': '2002:db8::8a3f:362:7897/128',
907
                                    }
908
                          }
909
                 },
910
            ),
911
            (
912
                {'flow': {'match': {'nw_src': '192.168.20.21'}}},
913
                {'nw_src': '192.168.20.30'},
914
                False,
915
            ),
916
            (
917
                {'flow': {'match': {'ipv6_src': '2002:db8::8a3f:362:7'}}},
918
                {'ipv6_src': '2002:db8::8a3f:362:7897'},
919
                False,
920
            ),
921
            (
922
                {'flow': {'match': {'in_port': 1, 'dl_vlan': '4096/4096'}}},
923
                {'in_port': 1, 'dl_vlan': [1]},
924
                {'flow': {'match': {'in_port': 1, 'dl_vlan': '4096/4096'}}},
925
            ),
926
            (
927
                {'flow': {'match': {'in_port': 1, 'dl_vlan': '4096/4096'}}},
928
                {'dl_vlan': [1]},
929
                False,
930
            ),
931
        ],
932
    )
933 1
    def test_do_match(self, flow, args, match):
934
        """Test do_match."""
935 1
        assert self.napp.do_match(flow, args, 0) == match
936
937 1
    def test_match_flows(self):
938
        """Test match_flows."""
939 1
        flow = {"flow": {"match": {"dl_vlan": "10/10", "in_port": 1}}}
940 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01")
941 1
        stored_flows = {"00:00:00:00:00:00:00:01": [flow]}
942 1
        args = {"dl_vlan": [10], "in_port": 1}
943 1
        resp = self.napp.match_flows(switch, 0, args, stored_flows)
944 1
        assert resp == [flow]
945
946 1
        stored_flows = {}
947 1
        resp = self.napp.match_flows(switch, 0, args, stored_flows)
948 1
        assert not resp
949
950 1
    @pytest.mark.parametrize(
951
        "flow,args,resp",
952
        [
953
            (
954
                {"flow": {
955
                          "match": {"dl_vlan": "10/10", "in_port": 1},
956
                          "actions": [{'action_type': 'output', 'port': 1}]
957
                          }
958
                 },
959
                {"dl_vlan": [10], "in_port": 1},
960
                ({"flow": {
961
                            "match": {"dl_vlan": "10/10", "in_port": 1},
962
                            "actions": [{'action_type': 'output', 'port': 1}]
963
                            }
964
                  }, {"dl_vlan": [10], "in_port": 1}, 1),
965
            ),
966
            (
967
                {"flow": {
968
                          "match": {"dl_vlan": "10/10", "in_port": 1},
969
                          "actions": [{'action_type': 'push_vlan'}]
970
                          }
971
                 },
972
                {"dl_vlan": [10], "in_port": 1},
973
                ({"flow": {
974
                            "match": {"dl_vlan": "10/10", "in_port": 1},
975
                            "actions": [{'action_type': 'push_vlan'}]
976
                            }
977
                  }, {"dl_vlan": [10, 0], "in_port": 1}, None),
978
            ),
979
            (
980
                {"flow": {
981
                          "match": {"dl_vlan": "10/10", "in_port": 1},
982
                          "actions": [{'action_type': 'pop_vlan'}]
983
                          }
984
                 },
985
                {"dl_vlan": [10], "in_port": 1},
986
                ({"flow": {
987
                            "match": {"dl_vlan": "10/10", "in_port": 1},
988
                            "actions": [{'action_type': 'pop_vlan'}]
989
                            }
990
                  }, {"in_port": 1}, None),
991
            ),
992
            (
993
                {"flow": {
994
                          "match": {"dl_vlan": "10/10", "in_port": 1},
995
                          "actions": [{'action_type': 'set_vlan',
996
                                       'vlan_id': 2}]
997
                          }
998
                 },
999
                {"dl_vlan": [10], "in_port": 1},
1000
                ({"flow": {
1001
                            "match": {"dl_vlan": "10/10", "in_port": 1},
1002
                            "actions": [{'action_type': 'set_vlan',
1003
                                         'vlan_id': 2}]
1004
                            }
1005
                  }, {"dl_vlan": [2], "in_port": 1}, None),
1006
            ),
1007
        ],
1008
    )
1009 1
    def test_match_and_apply(self, flow, args, resp):
1010
        """Test match_and_apply."""
1011 1
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
1012 1
        stored_flows = {"00:00:00:00:00:00:00:01": [flow]}
1013 1
        assert self.napp.match_and_apply(switch, args, stored_flows) == resp
1014
1015 1
        stored_flows = {}
1016 1
        resp = self.napp.match_and_apply(switch, args, stored_flows)
1017 1
        assert not resp[0]
1018 1
        assert not resp[2]
1019
1020 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
1021 1
    async def test_goto_table_1_switch(self, mock_stored_flows, event_loop):
1022
        """Test match_and_apply with goto_table"""
1023 1
        self.napp.controller.loop = event_loop
1024
1025 1
        stored_flow1 = {
1026
            "flow": {
1027
                        "match": {
1028
                            "in_port": 1
1029
                        },
1030
                        "instructions": [
1031
                            {
1032
                                "instruction_type": "goto_table",
1033
                                "table_id": 1
1034
                            }
1035
                        ]
1036
                    }
1037
        }
1038 1
        stored_flow2 = {
1039
            "flow": {
1040
                        "table_id": 1,
1041
                        "match": {
1042
                            "in_port": 1
1043
                        },
1044
                        "instructions": [
1045
                            {
1046
                                "instruction_type": "apply_actions",
1047
                                "actions": [
1048
                                    {
1049
                                        "action_type": "output",
1050
                                        "port": 2
1051
                                    }
1052
                                ]
1053
                            }
1054
                        ]
1055
                    }
1056
        }
1057 1
        stored_flow3 = {
1058
            "flow": {
1059
                        "match": {
1060
                            "in_port": 2
1061
                        },
1062
                        "instructions": [
1063
                            {
1064
                                "instruction_type": "goto_table",
1065
                                "table_id": 2
1066
                            }
1067
                        ]
1068
                    }
1069
        }
1070 1
        stored_flow4 = {
1071
            "flow": {
1072
                        "table_id": 2,
1073
                        "match": {
1074
                            "in_port": 2
1075
                        },
1076
                        "instructions": [
1077
                            {
1078
                                "instruction_type": "apply_actions",
1079
                                "actions": [
1080
                                    {
1081
                                        "action_type": "output",
1082
                                        "port": 1
1083
                                    }
1084
                                ]
1085
                            }
1086
                        ]
1087
                    }
1088
        }
1089 1
        mock_stored_flows.return_value = {
1090
            "00:00:00:00:00:00:00:01": [
1091
                stored_flow1,
1092
                stored_flow2,
1093
                stored_flow4,
1094
                stored_flow3
1095
            ]
1096
        }
1097
1098 1
        payload = [{
1099
            "trace": {
1100
                "switch": {
1101
                    "dpid": "00:00:00:00:00:00:00:01",
1102
                    "in_port": 1
1103
                    }
1104
            }
1105
        }, {
1106
            "trace": {
1107
                "switch": {
1108
                    "dpid": "00:00:00:00:00:00:00:01",
1109
                    "in_port": 2
1110
                    }
1111
            }
1112
        }
1113
        ]
1114
1115 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1116 1
        assert resp.status_code == 200
1117 1
        current_data = resp.json()
1118 1
        result = current_data["result"]
1119 1
        result_t1 = result[0]
1120 1
        assert result_t1[0]['dpid'] == '00:00:00:00:00:00:00:01'
1121 1
        assert result_t1[0]['port'] == 1
1122 1
        assert result_t1[0]['type'] == 'last'
1123 1
        assert result_t1[0]['out']['port'] == 2
1124
1125 1
        result_t1 = result[1]
1126 1
        assert result_t1[0]['dpid'] == '00:00:00:00:00:00:00:01'
1127 1
        assert result_t1[0]['port'] == 2
1128 1
        assert result_t1[0]['type'] == 'last'
1129 1
        assert result_t1[0]['out']['port'] == 1
1130
1131 1
        mock_stored_flows.return_value = {
1132
            "00:00:00:00:00:00:00:01": [
1133
                stored_flow1,
1134
                stored_flow4
1135
            ]
1136
        }
1137
1138 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1139 1
        assert resp.status_code == 200
1140 1
        current_data = resp.json()
1141 1
        result = current_data["result"]
1142
1143 1
        assert len(result[0]) == 0
1144 1
        assert len(result[1]) == 0
1145
1146 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
1147 1
    async def test_fail_wrong_goto_table(self, mock_stored_flows, event_loop):
1148
        """Test match_and_apply with goto_table"""
1149 1
        self.napp.controller.loop = event_loop
1150
1151 1
        stored_flow1 = {
1152
            "flow": {
1153
                        "match": {
1154
                            "in_port": 1
1155
                        },
1156
                        "instructions": [
1157
                            {
1158
                                "instruction_type": "goto_table",
1159
                                "table_id": 2
1160
                            }
1161
                        ]
1162
                    }
1163
        }
1164 1
        stored_flow2 = {
1165
            "flow": {
1166
                        "table_id": 2,
1167
                        "match": {
1168
                            "in_port": 1
1169
                        },
1170
                        "instructions": [
1171
                            {
1172
                                "instruction_type": "goto_table",
1173
                                "table_id": 1
1174
                            }
1175
                        ]
1176
                    }
1177
        }
1178 1
        mock_stored_flows.return_value = {
1179
            "00:00:00:00:00:00:00:01": [
1180
                stored_flow1,
1181
                stored_flow2
1182
            ]
1183
        }
1184
1185 1
        payload = [{
1186
            "trace": {
1187
                "switch": {
1188
                    "dpid": "00:00:00:00:00:00:00:01",
1189
                    "in_port": 1
1190
                    }
1191
            }
1192
        }
1193
        ]
1194
1195 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1196 1
        assert resp.status_code == 409
1197
1198 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
1199 1
    async def test_trace_goto_table_intra(self, mock_stored_flows, event_loop):
1200
        """Test trace rest call.
1201
            Topology:
1202
                switches: {s1}
1203
                links:{
1204
                    s1-eth17 -- s1-eth18,
1205
                    s1-eth19 -- s1-eth20
1206
                }
1207
        """
1208 1
        self.napp.controller.loop = event_loop
1209
1210 1
        switch = self.napp.controller.switches["00:00:00:00:00:00:00:01"]
1211
1212 1
        mock_interface = Interface("interface A", 1, MagicMock())
1213
1214 1
        mock_stored_flows.return_value = {
1215
            "00:00:00:00:00:00:00:01": [
1216
                {"flow": {
1217
                    "match": {
1218
                        "in_port": 15,
1219
                        "dl_vlan": 201
1220
                        },
1221
                    "instructions": [{
1222
                        "instruction_type": "apply_actions",
1223
                        "actions": [{
1224
                            "action_type": "push_int"
1225
                        }]
1226
                        }, {
1227
                            "instruction_type": "goto_table",
1228
                            "table_id": 2
1229
                        }
1230
                    ],
1231
                    "table_id": 0,
1232
                    "table_group": "evpl",
1233
                    "priority": 20100,
1234
                    }, },
1235
                {"flow": {
1236
                    "match": {
1237
                        "in_port": 16,
1238
                        "dl_vlan": 200
1239
                        },
1240
                    "instructions": [{
1241
                        "instruction_type": "apply_actions",
1242
                        "actions": [{
1243
                            "action_type": "push_int"
1244
                        }]
1245
                        }, {
1246
                            "instruction_type": "goto_table",
1247
                            "table_id": 2
1248
                        }
1249
                    ],
1250
                    "table_id": 0,
1251
                    "table_group": "evpl",
1252
                    "priority": 20100,
1253
                    }, },
1254
                {"flow": {
1255
                    "match": {
1256
                        "in_port": 15,
1257
                        "dl_vlan": 201
1258
                        },
1259
                    "instructions": [{
1260
                        "instruction_type": "apply_actions",
1261
                        "actions": [{
1262
                            "action_type": "add_int_metadata"
1263
                        }, {
1264
                            "action_type": "output",
1265
                            "port": 19
1266
                        }]}
1267
                    ],
1268
                    "table_id": 2,
1269
                    "table_group": "base",
1270
                    "priority": 20000,
1271
                    }},
1272
                {"flow": {
1273
                    "match": {
1274
                        "in_port": 16,
1275
                        "dl_vlan": 200
1276
                        },
1277
                    "instructions": [{
1278
                        "instruction_type": "apply_actions",
1279
                        "actions": [{
1280
                            "action_type": "add_int_metadata"
1281
                        }, {
1282
                            "action_type": "output",
1283
                            "port": 17
1284
                        }]}
1285
                    ],
1286
                    "table_id": 2,
1287
                    "table_group": "base",
1288
                    "priority": 20000,
1289
                    }, },
1290
                {"flow": {
1291
                    "match": {
1292
                        "in_port": 20,
1293
                        "dl_vlan": 201
1294
                        },
1295
                    "instructions": [{
1296
                        "instruction_type": "apply_actions",
1297
                        "actions": [{
1298
                            "action_type": "send_report"
1299
                        }]},
1300
                        {
1301
                            "instruction_type": "goto_table",
1302
                            "table_id": 2
1303
                        }
1304
                    ],
1305
                    "table_id": 0,
1306
                    "table_group": "evpl",
1307
                    "priority": 20000,
1308
                    }, },
1309
                {"flow": {
1310
                    "match": {
1311
                        "in_port": 20,
1312
                        "dl_vlan": 201
1313
                        },
1314
                    "instructions": [{
1315
                        "instruction_type": "apply_actions",
1316
                        "actions": [{
1317
                            "action_type": "pop_int"
1318
                        }, {
1319
                            "action_type": "set_vlan",
1320
                            "vlan_id": 200
1321
                        }, {
1322
                            "action_type": "output",
1323
                            "port": 16
1324
                        }]}
1325
                    ],
1326
                    "table_id": 2,
1327
                    "table_group": "base",
1328
                    "priority": 20000,
1329
                    }, },
1330
                {"flow": {
1331
                    "match": {
1332
                        "in_port": 18,
1333
                        "dl_vlan": 200
1334
                        },
1335
                    "instructions": [{
1336
                        "instruction_type": "apply_actions",
1337
                        "actions": [{
1338
                            "action_type": "send_report"
1339
                        }]},
1340
                        {
1341
                            "instruction_type": "goto_table",
1342
                            "table_id": 2
1343
                        }
1344
                    ],
1345
                    "table_id": 0,
1346
                    "table_group": "evpl",
1347
                    "priority": 20000,
1348
                    }, },
1349
                {"flow": {
1350
                    "match": {
1351
                        "in_port": 18,
1352
                        "dl_vlan": 200
1353
                        },
1354
                    "instructions": [{
1355
                        "instruction_type": "apply_actions",
1356
                        "actions": [{
1357
                            "action_type": "pop_int"
1358
                        }, {
1359
                            "action_type": "set_vlan",
1360
                            "vlan_id": 201
1361
                        }, {
1362
                            "action_type": "output",
1363
                            "port": 15
1364
                        }]}
1365
                    ],
1366
                    "table_id": 2,
1367
                    "table_group": "base",
1368
                    "priority": 20000,
1369
                    }, },
1370
                ]}
1371 1
        payload = [
1372
            {"trace": {
1373
                "switch": {
1374
                    "dpid": "00:00:00:00:00:00:00:01",
1375
                    "in_port": 15
1376
                    },
1377
                "eth": {"dl_vlan": 201}
1378
                }}
1379
        ]
1380
1381 1
        iface1 = get_interface_mock("s1-eth11", 19, switch)
1382 1
        iface2 = get_interface_mock("s1-eth11", 20, switch)
1383 1
        mock_interface.link = get_link_mock(iface2, iface1)
1384
1385 1
        switch.get_interface_by_port_no.return_value = mock_interface
1386
1387 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1388 1
        assert resp.status_code == 200
1389 1
        current_data = resp.json()
1390 1
        result = current_data["result"][0]
1391
1392 1
        assert result[0]['dpid'] == '00:00:00:00:00:00:00:01'
1393 1
        assert result[0]['port'] == 15
1394 1
        assert result[0]['vlan'] == 201
1395
1396 1
        assert result[1]['port'] == 20
1397 1
        assert result[1]['out']['port'] == 16
1398 1
        assert result[1]['out']['vlan'] == 200
1399 1
        payload = [
1400
            {"trace": {
1401
                "switch": {
1402
                    "dpid": "00:00:00:00:00:00:00:01",
1403
                    "in_port": 16
1404
                    },
1405
                "eth": {"dl_vlan": 200}
1406
                }}
1407
        ]
1408
1409 1
        iface1 = get_interface_mock("s1-eth11", 17, switch)
1410 1
        iface2 = get_interface_mock("s1-eth11", 18, switch)
1411 1
        mock_interface.link = get_link_mock(iface2, iface1)
1412
1413 1
        switch.get_interface_by_port_no.return_value = mock_interface
1414
1415 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1416 1
        assert resp.status_code == 200
1417 1
        current_data = resp.json()
1418 1
        result = current_data["result"][0]
1419
1420 1
        assert result[0]['dpid'] == '00:00:00:00:00:00:00:01'
1421 1
        assert result[0]['port'] == 16
1422 1
        assert result[0]['vlan'] == 200
1423
1424 1
        assert result[1]['port'] == 18
1425 1
        assert result[1]['out']['port'] == 15
1426 1
        assert result[1]['out']['vlan'] == 201
1427
1428
    # pylint: disable=too-many-statements
1429 1
    @patch("napps.amlight.sdntrace_cp.main.get_stored_flows")
1430 1
    async def test_trace_goto_table_inter(self, mock_stored_flows, event_loop):
1431
        """Test trace rest call.
1432
            Topology:
1433
                switches: {s1, s2}
1434
                links:{
1435
                    s1-eth17 -- s1-eth18,
1436
                    s1-eth11 -- s2-eth11,
1437
                    s2-eth25 -- s2-eth26
1438
                }
1439
        """
1440 1
        self.napp.controller.loop = event_loop
1441
1442 1
        switch1 = self.napp.controller.switches["00:00:00:00:00:00:00:01"]
1443 1
        switch2 = self.napp.controller.switches["00:00:00:00:00:00:00:02"]
1444
1445 1
        mock_interface1 = Interface("interface A", 1, MagicMock())
1446 1
        mock_interface2 = Interface("interface B", 1, MagicMock())
1447
1448 1
        mock_stored_flows.return_value = {
1449
            "00:00:00:00:00:00:00:01": [
1450
                {"flow": {
1451
                    "match": {
1452
                        "in_port": 15,
1453
                        "dl_vlan": 100
1454
                        },
1455
                    "instructions": [{
1456
                        "instruction_type": "apply_actions",
1457
                        "actions": [{
1458
                            "action_type": "push_int"
1459
                        }]
1460
                        }, {
1461
                            "instruction_type": "goto_table",
1462
                            "table_id": 2
1463
                        }
1464
                    ],
1465
                    "table_id": 0,
1466
                    "table_group": "evpl",
1467
                    "priority": 20100,
1468
                    }, },
1469
                {"flow": {
1470
                    "match": {
1471
                        "in_port": 15,
1472
                        "dl_vlan": 100
1473
                        },
1474
                    "instructions": [{
1475
                        "instruction_type": "apply_actions",
1476
                        "actions": [{
1477
                            "action_type": "add_int_metadata"
1478
                        }, {
1479
                            "action_type": "set_vlan",
1480
                            "vlan_id": 100
1481
                        }, {
1482
                            "action_type": "push_vlan",
1483
                            "tag_type": "s"
1484
                        }, {
1485
                            "action_type": "set_vlan",
1486
                            "vlan_id": 1
1487
                        }, {
1488
                            "action_type": "output",
1489
                            "port": 11
1490
                        }]}
1491
                    ],
1492
                    "table_id": 2,
1493
                    "table_group": "base",
1494
                    "priority": 20000,
1495
                    }},
1496
                {"flow": {
1497
                    "match": {
1498
                        "in_port": 11,
1499
                        "dl_vlan": 1
1500
                        },
1501
                    "instructions": [{
1502
                        "instruction_type": "apply_actions",
1503
                        "actions": [{
1504
                            "action_type": "add_int_metadata"
1505
                        }, {
1506
                            "action_type": "output",
1507
                            "port": 17
1508
                        }]}
1509
                    ],
1510
                    "table_id": 0,
1511
                    "table_group": "evpl",
1512
                    "priority": 20100,
1513
                    }},
1514
                {"flow": {
1515
                    "match": {
1516
                        "in_port": 18,
1517
                        "dl_vlan": 1
1518
                        },
1519
                    "instructions": [{
1520
                        "instruction_type": "apply_actions",
1521
                        "actions": [{
1522
                            "action_type": "send_report"
1523
                        }]},
1524
                        {
1525
                            "instruction_type": "goto_table",
1526
                            "table_id": 2
1527
                        }
1528
                    ],
1529
                    "table_id": 0,
1530
                    "table_group": "evpl",
1531
                    "priority": 20000,
1532
                    }, },
1533
                {"flow": {
1534
                    "match": {
1535
                        "in_port": 18,
1536
                        "dl_vlan": 1
1537
                        },
1538
                    "instructions": [{
1539
                        "instruction_type": "apply_actions",
1540
                        "actions": [{
1541
                            "action_type": "pop_int"
1542
                        }, {
1543
                            "action_type": "pop_vlan"
1544
                        }, {
1545
                            "action_type": "output",
1546
                            "port": 15
1547
                        }]}
1548
                    ],
1549
                    "table_id": 2,
1550
                    "table_group": "base",
1551
                    "priority": 20000,
1552
                    }, }
1553
            ],
1554
            "00:00:00:00:00:00:00:02": [
1555
                {"flow": {
1556
                    "match": {
1557
                        "in_port": 22,
1558
                        "dl_vlan": 100
1559
                        },
1560
                    "instructions": [{
1561
                        "instruction_type": "apply_actions",
1562
                        "actions": [{
1563
                            "action_type": "push_int"
1564
                        }]
1565
                        }, {
1566
                            "instruction_type": "goto_table",
1567
                            "table_id": 2
1568
                        }
1569
                    ],
1570
                    "table_id": 0,
1571
                    "table_group": "evpl",
1572
                    "priority": 20100,
1573
                    }, },
1574
                {"flow": {
1575
                    "match": {
1576
                        "in_port": 11,
1577
                        "dl_vlan": 1
1578
                        },
1579
                    "instructions": [{
1580
                        "instruction_type": "apply_actions",
1581
                        "actions": [{
1582
                            "action_type": "add_int_metadata"
1583
                        }, {
1584
                            "action_type": "output",
1585
                            "port": 25
1586
                        }]}
1587
                    ],
1588
                    "table_id": 0,
1589
                    "table_group": "evpl",
1590
                    "priority": 20100,
1591
                    }},
1592
                {"flow": {
1593
                    "match": {
1594
                        "in_port": 22,
1595
                        "dl_vlan": 100
1596
                        },
1597
                    "instructions": [{
1598
                        "instruction_type": "apply_actions",
1599
                        "actions": [{
1600
                            "action_type": "add_int_metadata"
1601
                        }, {
1602
                            "action_type": "set_vlan",
1603
                            "vlan_id": 100
1604
                        }, {
1605
                            "action_type": "push_vlan",
1606
                            "tag_type": "s"
1607
                        }, {
1608
                            "action_type": "set_vlan",
1609
                            "vlan_id": 1
1610
                        }, {
1611
                            "action_type": "output",
1612
                            "port": 11
1613
                        }]}
1614
                    ],
1615
                    "table_id": 2,
1616
                    "table_group": "base",
1617
                    "priority": 20000,
1618
                    }},
1619
                {"flow": {
1620
                    "match": {
1621
                        "in_port": 26,
1622
                        "dl_vlan": 1
1623
                        },
1624
                    "instructions": [{
1625
                        "instruction_type": "apply_actions",
1626
                        "actions": [{
1627
                            "action_type": "send_report"
1628
                        }]},
1629
                        {
1630
                            "instruction_type": "goto_table",
1631
                            "table_id": 2
1632
                        }
1633
                    ],
1634
                    "table_id": 0,
1635
                    "table_group": "evpl",
1636
                    "priority": 20000,
1637
                    }, },
1638
                {"flow": {
1639
                    "match": {
1640
                        "in_port": 26,
1641
                        "dl_vlan": 1
1642
                        },
1643
                    "instructions": [{
1644
                        "instruction_type": "apply_actions",
1645
                        "actions": [{
1646
                            "action_type": "pop_int"
1647
                        }, {
1648
                            "action_type": "pop_vlan"
1649
                        }, {
1650
                            "action_type": "output",
1651
                            "port": 22
1652
                        }]}
1653
                    ],
1654
                    "table_id": 2,
1655
                    "table_group": "base",
1656
                    "priority": 20000,
1657
                    }, }
1658
            ]
1659
        }
1660
1661 1
        iface1 = get_interface_mock("s1-eth11", 11, switch1)
1662 1
        iface2 = get_interface_mock("s2-eth11", 11, switch2)
1663 1
        iface3 = get_interface_mock("s2-eth25", 25, switch2)
1664 1
        iface4 = get_interface_mock("s2-eth26", 26, switch2)
1665 1
        mock_interface1.link = get_link_mock(iface2, iface1)
1666 1
        mock_interface2.link = get_link_mock(iface4, iface3)
1667
1668 1
        switch1.get_interface_by_port_no.return_value = mock_interface1
1669 1
        switch2.get_interface_by_port_no.return_value = mock_interface2
1670
1671 1
        payload = [
1672
            {"trace": {
1673
                "switch": {
1674
                    "dpid": "00:00:00:00:00:00:00:01",
1675
                    "in_port": 15
1676
                    },
1677
                "eth": {"dl_vlan": 100}
1678
                }}
1679
        ]
1680
1681 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1682 1
        assert resp.status_code == 200
1683 1
        result = resp.json()["result"][0]
1684
1685 1
        assert result[0]['dpid'] == '00:00:00:00:00:00:00:01'
1686 1
        assert result[0]['port'] == 15
1687 1
        assert result[0]['vlan'] == 100
1688
1689 1
        assert result[1]['dpid'] == '00:00:00:00:00:00:00:02'
1690 1
        assert result[1]['port'] == 11
1691 1
        assert result[1]['vlan'] == 1
1692
1693 1
        assert result[2]['dpid'] == '00:00:00:00:00:00:00:02'
1694 1
        assert result[2]['port'] == 26
1695 1
        assert result[2]['vlan'] == 1
1696 1
        assert result[2]['out']['port'] == 22
1697 1
        assert result[2]['out']['vlan'] == 100
1698
1699 1
        iface3 = get_interface_mock("s1-eth17", 17, switch1)
1700 1
        iface4 = get_interface_mock("s1-eth18", 18, switch1)
1701 1
        mock_interface1.link = get_link_mock(iface1, iface2)
1702 1
        mock_interface2.link = get_link_mock(iface4, iface3)
1703
1704 1
        switch1.get_interface_by_port_no.return_value = mock_interface2
1705 1
        switch2.get_interface_by_port_no.return_value = mock_interface1
1706
1707 1
        payload = [
1708
            {"trace": {
1709
                "switch": {
1710
                    "dpid": "00:00:00:00:00:00:00:02",
1711
                    "in_port": 22
1712
                    },
1713
                "eth": {"dl_vlan": 100}
1714
                }}
1715
        ]
1716
1717 1
        resp = await self.api_client.put(self.traces_endpoint, json=payload)
1718 1
        assert resp.status_code == 200
1719 1
        result = resp.json()["result"][0]
1720
1721 1
        assert result[0]['dpid'] == '00:00:00:00:00:00:00:02'
1722 1
        assert result[0]['port'] == 22
1723 1
        assert result[0]['vlan'] == 100
1724
1725 1
        assert result[1]['dpid'] == '00:00:00:00:00:00:00:01'
1726 1
        assert result[1]['port'] == 11
1727 1
        assert result[1]['vlan'] == 1
1728
1729 1
        assert result[2]['dpid'] == '00:00:00:00:00:00:00:01'
1730 1
        assert result[2]['port'] == 18
1731 1
        assert result[2]['vlan'] == 1
1732 1
        assert result[2]['out']['port'] == 15
1733
        assert result[2]['out']['vlan'] == 100
1734