Test Failed
Pull Request — master (#20)
by Vinicius
03:34
created

TestTracePath.test_tracepath_result()   B

Complexity

Conditions 1

Size

Total Lines 74
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 47
nop 5
dl 0
loc 74
rs 8.7345
c 0
b 0
f 0

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
"""
2
    Test tracing.trace_entries
3
"""
4
from unittest import TestCase
5
from unittest.mock import MagicMock, patch
6
7
from napps.amlight.sdntrace.tracing.trace_msg import TraceMsg
8
from napps.amlight.sdntrace.tracing.trace_manager import TraceManager
9
from napps.amlight.sdntrace.tracing.tracer import TracePath
10
from napps.amlight.sdntrace.shared.switches import Switches
11
from napps.amlight.sdntrace.tracing.rest import FormatRest
12
13
from kytos.lib.helpers import (
14
    get_interface_mock,
15
    get_link_mock,
16
    get_switch_mock,
17
    get_controller_mock,
18
)
19
20
21
# pylint: disable=too-many-public-methods, too-many-lines,
22
# pylint: disable=protected-access, too-many-locals
23
class TestTracePath(TestCase):
24
    """Test all combinations for DPID"""
25
26
    def setUp(self):
27
        self.create_basic_switches(get_controller_mock())
28
29
        # The decorator run_on_thread is patched, so methods that listen
30
        # for events do not run on threads while tested.
31
        # Decorators have to be patched before the methods that are
32
        # decorated with them are imported.
33
        patch("kytos.core.helpers.run_on_thread", lambda x: x).start()
34
35
        self.addCleanup(patch.stopall)
36
        self.trace_manager = TraceManager(controller=get_controller_mock())
37
38 View Code Duplication
    @classmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
39
    def create_basic_switches(cls, controller):
40
        """Create basic mock switches for Kytos controller."""
41
        dpid_a = "00:00:00:00:00:00:00:01"
42
        dpid_b = "00:00:00:00:00:00:00:02"
43
44
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
45
        mock_switch_b = get_switch_mock(dpid_b, 0x04)
46
        mock_interface_a = get_interface_mock("s1-eth1", 1, mock_switch_a)
47
        mock_interface_b = get_interface_mock("s2-eth1", 1, mock_switch_b)
48
49
        mock_link = get_link_mock(mock_interface_a, mock_interface_b)
50
        mock_link.id = "cf0f4071be4"
51
        mock_switch_a.id = dpid_a
52
        mock_switch_a.as_dict.return_value = {"metadata": {}}
53
        mock_switch_b.id = dpid_b
54
        mock_switch_b.as_dict.return_value = {"metadata": {}}
55
56
        controller.switches = {dpid_a: mock_switch_a, dpid_b: mock_switch_b}
57
58
        Switches(controller.switches)
59
60
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
61
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
62
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
63
    @patch("napps.amlight.sdntrace.tracing.tracer.TracePath.tracepath_loop")
64
    def test_tracepath(
65
        self, mock_trace_loop, mock_get_switch, mock_color, mock_switch_colors
66
    ):
67
        """Test tracepath initial result item. Mocking tracepath loop
68
        to get just one step."""
69
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
70
71
        switch = MagicMock()
72
        switch.dpid = "00:00:00:00:00:00:00:01"
73
        mock_get_switch.return_value = switch
74
75
        # Mock tracepath loop to create only the initial result item
76
        mock_trace_loop.return_value = True
77
78
        # Trace id to recover the result
79
        trace_id = 111
80
81
        # Creating trace entries
82
        eth = {"dl_vlan": 100}
83
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
84
        switch = {"switch": dpid, "eth": eth}
85
        entries = {"trace": switch}
86
        trace_entries = self.trace_manager.is_entry_valid(entries)
87
88
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
89
        tracer.tracepath()
90
91
        # Retrieve trace result created from tracepath
92
        result = self.trace_manager.get_result(trace_id)
93
94
        self.assertEqual(result["request_id"], 111)
95
        self.assertEqual(len(result["result"]), 1)
96
        self.assertEqual(result["result"][0]["type"], "starting")
97
        self.assertEqual(result["result"][0]["dpid"], dpid["dpid"])
98
        self.assertEqual(result["result"][0]["port"], dpid["in_port"])
99
100
        self.assertEqual(
101
            result["request"]["trace"]["switch"]["dpid"], dpid["dpid"]
102
        )
103
        self.assertEqual(
104
            result["request"]["trace"]["switch"]["in_port"], dpid["in_port"]
105
        )
106
        self.assertEqual(
107
            result["request"]["trace"]["eth"]["dl_vlan"], eth["dl_vlan"]
108
        )
109
        self.assertEqual(mock_color.call_count, 2)
110
        self.assertEqual(mock_switch_colors.call_count, 2)
111
112
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
113
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
114
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
115
    @patch("napps.amlight.sdntrace.tracing.tracer.TracePath.tracepath_loop")
116
    def test_tracepath_result(
117
        self, mock_trace_loop, mock_get_switch, mock_color, mock_switch_colors
118
    ):
119
        """Test tracepath initial result item. Patching the tracepath loop
120
        to test multiple steps."""
121
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
122
123
        # Patch Switches.get_switch
124
        def wrap_get_switch(dpid):
125
            switch = MagicMock()
126
            switch.dpid = dpid
127
            return switch
128
129
        mock_get_switch.side_effect = wrap_get_switch
130
131
        # Trace id to recover the result
132
        trace_id = 111
133
134
        # Creating trace entries
135
        eth = {"dl_vlan": 100}
136
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
137
        switch = {"switch": dpid, "eth": eth}
138
        entries = {"trace": switch}
139
        trace_entries = self.trace_manager.is_entry_valid(entries)
140
141
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
142
143
        # Patch tracepath loop to create a second result item
144
        # pylint: disable=unused-argument
145
        def wrap_tracepath_loop(entries, color, switch):
146
            rest = FormatRest()
147
            rest.add_trace_step(
148
                tracer.trace_result,
149
                trace_type="trace",
150
                dpid="00:00:00:00:00:00:00:03",
151
                port=3,
152
            )
153
            return True
154
155
        mock_trace_loop.side_effect = wrap_tracepath_loop
156
157
        # Execute tracepath
158
        tracer.tracepath()
159
160
        # Retrieve trace result created from tracepath
161
        result = self.trace_manager.get_result(trace_id)
162
163
        self.assertEqual(result["request_id"], 111)
164
        self.assertEqual(len(result["result"]), 2)
165
        self.assertEqual(result["result"][0]["type"], "starting")
166
        self.assertEqual(result["result"][0]["dpid"], dpid["dpid"])
167
        self.assertEqual(result["result"][0]["port"], dpid["in_port"])
168
169
        self.assertEqual(result["result"][1]["type"], "trace")
170
        self.assertEqual(
171
            result["result"][1]["dpid"], "00:00:00:00:00:00:00:03"
172
        )
173
        self.assertEqual(result["result"][1]["port"], 3)
174
175
        self.assertEqual(
176
            result["request"]["trace"]["switch"]["dpid"], dpid["dpid"]
177
        )
178
        self.assertEqual(
179
            result["request"]["trace"]["switch"]["in_port"], dpid["in_port"]
180
        )
181
        self.assertEqual(
182
            result["request"]["trace"]["eth"]["dl_vlan"], eth["dl_vlan"]
183
        )
184
        self.assertEqual(mock_color.call_count, 2)
185
        self.assertEqual(mock_switch_colors.call_count, 2)
186
187
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
188
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
189
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
190
    @patch("napps.amlight.sdntrace.tracing.tracer.TracePath.tracepath_loop")
191
    @patch("napps.amlight.sdntrace.tracing.tracer.send_packet_out")
192
    def test_send_trace_probe(
193
        self,
194
        mock_send_packet_out,
195
        mock_trace_loop,
196
        mock_get_switch,
197
        mock_color,
198
        mock_switch_colors,
199
    ):
200
        """Test send_trace_probe send and receive."""
201
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
202
203
        mock_send_packet_out.return_value = True
204
205
        switch_obj = MagicMock()
206
        switch_obj.dpid = "00:00:00:00:00:00:00:01"
207
        mock_get_switch.return_value = switch_obj
208
209
        # Mock tracepath loop to create only the initial result item
210
        mock_trace_loop.return_value = True
211
212
        # Creating a fake packet in
213
        msg = TraceMsg()
214
        msg.request_id = 111
215
        pkt_in = {}
216
        pkt_in["dpid"] = "00:00:00:00:00:00:00:01"
217
        pkt_in["in_port"] = 1
218
        pkt_in["msg"] = msg
219
        pkt_in["ethernet"] = "fake_ethernet_object"
220
        pkt_in["event"] = "fake_event_object"
221
        self.trace_manager.trace_pkt_in = [pkt_in]
222
223
        # Trace id to recover the result
224
        trace_id = 111
225
226
        # Creating trace entries
227
        eth = {"dl_vlan": 100, "dl_type": 2048}
228
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
229
        switch = {"switch": dpid, "eth": eth}
230
        entries = {"trace": switch}
231
        trace_entries = self.trace_manager.is_entry_valid(entries)
232
233
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
234
235
        in_port = 1
236
        probe_pkt = MagicMock()
237
238
        result = tracer.send_trace_probe(switch_obj, in_port, probe_pkt)
239
240
        mock_send_packet_out.assert_called_once()
241
242
        self.assertEqual(result[0]["dpid"], "00:00:00:00:00:00:00:01")
243
        self.assertEqual(result[0]["port"], 1)
244
        self.assertEqual(result[1], "fake_event_object")
245
        mock_color.assert_called_once()
246
        mock_switch_colors.assert_called_once()
247
248
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
249
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
250
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
251
    @patch("napps.amlight.sdntrace.tracing.tracer.TracePath.tracepath_loop")
252
    @patch("napps.amlight.sdntrace.tracing.tracer.send_packet_out")
253
    def test_send_trace_probe_timeout(
254
        self,
255
        mock_send_packet_out,
256
        mock_trace_loop,
257
        mock_get_switch,
258
        mock_color,
259
        mock_switch_colors,
260
    ):
261
        """Test send_trace_probe with timeout."""
262
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
263
        mock_send_packet_out.return_value = True
264
265
        switch_obj = MagicMock()
266
        switch_obj.dpid = "00:00:00:00:00:00:00:01"
267
        mock_get_switch.return_value = switch_obj
268
269
        # Mock tracepath loop to create only the initial result item
270
        mock_trace_loop.return_value = True
271
272
        # Creating a fake packet in
273
        self.trace_manager.trace_pkt_in = []
274
275
        # Trace id to recover the result
276
        trace_id = 111
277
278
        # Creating trace entries
279
        eth = {"dl_vlan": 100, "dl_type": 2048}
280
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
281
        switch = {"switch": dpid, "eth": eth}
282
        entries = {"trace": switch}
283
        trace_entries = self.trace_manager.is_entry_valid(entries)
284
285
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
286
287
        in_port = 1
288
        probe_pkt = MagicMock()
289
290
        result = tracer.send_trace_probe(switch_obj, in_port, probe_pkt)
291
292
        self.assertEqual(mock_send_packet_out.call_count, 3)
293
294
        self.assertEqual(result[0], "timeout")
295
        self.assertEqual(result[1], False)
296
        mock_color.assert_called_once()
297
        mock_switch_colors.assert_called_once()
298
299
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
300
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
301
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
302
    def test_check_loop(self, mock_get_switch, mock_color, mock_switch_colors):
303
        """Test check_loop with loop detection."""
304
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
305
306
        # Patch Switches.get_switch
307
        def wrap_get_switch(dpid):
308
            switch = MagicMock()
309
            switch.dpid = dpid
310
            return switch
311
312
        mock_get_switch.side_effect = wrap_get_switch
313
314
        # Trace id to recover the result
315
        trace_id = 111
316
317
        # Creating trace entries
318
        eth = {"dl_vlan": 100, "dl_type": 2048}
319
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
320
        switch = {"switch": dpid, "eth": eth}
321
        entries = {"trace": switch}
322
        trace_entries = self.trace_manager.is_entry_valid(entries)
323
324
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
325
326
        # Patch tracepath loop to create a second result item
327
        rest = FormatRest()
328
        rest.add_trace_step(
329
            tracer.trace_result,
330
            trace_type="trace",
331
            dpid="00:00:00:00:00:00:00:01",
332
            port=1,
333
        )
334
        rest.add_trace_step(
335
            tracer.trace_result,
336
            trace_type="trace",
337
            dpid="00:00:00:00:00:00:00:02",
338
            port=2,
339
        )
340
        rest.add_trace_step(
341
            tracer.trace_result,
342
            trace_type="trace",
343
            dpid="00:00:00:00:00:00:00:03",
344
            port=3,
345
        )
346
        rest.add_trace_step(
347
            tracer.trace_result,
348
            trace_type="trace",
349
            dpid="00:00:00:00:00:00:00:01",
350
            port=1,
351
        )
352
353
        result = tracer.check_loop()
354
        mock_color.assert_called_once()
355
        mock_switch_colors.assert_called_once()
356
        self.assertEqual(result, True)
357
358
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
359
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
360
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
361
    def test_check_loop_false(
362
        self, mock_get_switch, mock_color, mock_switch_colors
363
    ):
364
        """Test check_loop with no loop detection."""
365
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
366
367
        # Patch Switches.get_switch
368
        def wrap_get_switch(dpid):
369
            switch = MagicMock()
370
            switch.dpid = dpid
371
            return switch
372
373
        mock_get_switch.side_effect = wrap_get_switch
374
375
        # Trace id to recover the result
376
        trace_id = 111
377
378
        # Creating trace entries
379
        eth = {"dl_vlan": 100, "dl_type": 2048}
380
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
381
        switch = {"switch": dpid, "eth": eth}
382
        entries = {"trace": switch}
383
        trace_entries = self.trace_manager.is_entry_valid(entries)
384
385
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
386
387
        # Patch tracepath loop to create a second result item
388
        rest = FormatRest()
389
        rest.add_trace_step(
390
            tracer.trace_result,
391
            trace_type="trace",
392
            dpid="00:00:00:00:00:00:00:01",
393
            port=1,
394
        )
395
        rest.add_trace_step(
396
            tracer.trace_result,
397
            trace_type="trace",
398
            dpid="00:00:00:00:00:00:00:02",
399
            port=2,
400
        )
401
402
        result = tracer.check_loop()
403
        mock_color.assert_called_once()
404
        mock_switch_colors.assert_called_once()
405
        self.assertEqual(result, 0)
406
407
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
408
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
409
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
410
    def test_check_loop_port_different(
411
        self, mock_get_switch, mock_color, mock_switch_colors
412
    ):
413
        """Test check_loop with same switch and different port."""
414
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
415
416
        # Patch Switches.get_switch
417
        def wrap_get_switch(dpid):
418
            switch = MagicMock()
419
            switch.dpid = dpid
420
            return switch
421
422
        mock_get_switch.side_effect = wrap_get_switch
423
424
        # Trace id to recover the result
425
        trace_id = 111
426
427
        # Creating trace entries
428
        eth = {"dl_vlan": 100, "dl_type": 2048}
429
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
430
        switch = {"switch": dpid, "eth": eth}
431
        entries = {"trace": switch}
432
        trace_entries = self.trace_manager.is_entry_valid(entries)
433
434
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
435
436
        # Patch tracepath loop to create a second result item
437
        rest = FormatRest()
438
        rest.add_trace_step(
439
            tracer.trace_result,
440
            trace_type="trace",
441
            dpid="00:00:00:00:00:00:00:01",
442
            port=1,
443
        )
444
        rest.add_trace_step(
445
            tracer.trace_result,
446
            trace_type="trace",
447
            dpid="00:00:00:00:00:00:00:02",
448
            port=2,
449
        )
450
        rest.add_trace_step(
451
            tracer.trace_result,
452
            trace_type="trace",
453
            dpid="00:00:00:00:00:00:00:01",
454
            port=10,
455
        )
456
457
        result = tracer.check_loop()
458
        mock_color.assert_called_once()
459
        mock_switch_colors.assert_called_once()
460
        self.assertEqual(result, 0)
461
462
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
463
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
464
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
465
    @patch("napps.amlight.sdntrace.tracing.tracer.TracePath.send_trace_probe")
466
    @patch("napps.amlight.sdntrace.tracing.tracer.prepare_next_packet")
467
    def test_tracepath_loop(
468
        self,
469
        mock_next_packet,
470
        mock_probe,
471
        mock_get_switch,
472
        mock_color,
473
        mock_switch_colors,
474
    ):
475
        """Test tracepath loop method. This test force the return
476
        after one normal trace."""
477
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
478
479
        # Patch Switches.get_switch
480
        def wrap_get_switch(dpid):
481
            switch = MagicMock()
482
            switch.dpid = dpid
483
            return switch
484
485
        mock_get_switch.side_effect = wrap_get_switch
486
487
        mock_probe.return_value = [
488
            {"dpid": "00:00:00:00:00:00:00:01", "port": 1},
489
            "fake_event_object",
490
        ]
491
492
        # Trace id to recover the result
493
        trace_id = 111
494
495
        # Creating trace entries
496
        eth = {"dl_vlan": 100}
497
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
498
        switch = {"switch": dpid, "eth": eth}
499
        entries = {"trace": switch}
500
        trace_entries = self.trace_manager.is_entry_valid(entries)
501
502
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
503
504
        # Mock the next packt to stop the trace loop
505
        # pylint: disable=unused-argument
506
        def wrap_next_packet(entries, result, packet_in):
507
            tracer.trace_ended = True
508
            return "", "", ""
509
510
        mock_next_packet.side_effect = wrap_next_packet
511
512
        color = {"color_field": "dl_src", "color_value": "ee:ee:ee:ee:01:2c"}
513
514
        # Execute tracepath
515
        tracer.tracepath_loop(trace_entries, color, switch)
516
        result = tracer.trace_result
517
518
        mock_probe.assert_called_once()
519
        mock_color.assert_called_once()
520
        mock_switch_colors.assert_called_once()
521
        self.assertEqual(result[0]["type"], "trace")
522
        self.assertEqual(result[0]["dpid"], "00:00:00:00:00:00:00:01")
523
524
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
525
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
526
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
527
    @patch("napps.amlight.sdntrace.tracing.tracer.TracePath.send_trace_probe")
528
    def test_tracepath_loop_timeout(
529
        self, mock_probe, mock_get_switch, mock_color, mock_switch_colors
530
    ):
531
        """Test tracepath loop method finishing with timeout."""
532
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
533
534
        # Patch Switches.get_switch
535
        def wrap_get_switch(dpid):
536
            switch = MagicMock()
537
            switch.dpid = dpid
538
            return switch
539
540
        mock_get_switch.side_effect = wrap_get_switch
541
542
        mock_probe.return_value = ["timeout", "fake_event_object"]
543
544
        # Trace id to recover the result
545
        trace_id = 111
546
547
        # Creating trace entries
548
        eth = {"dl_vlan": 100}
549
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
550
        switch = {"switch": dpid, "eth": eth}
551
        entries = {"trace": switch}
552
        trace_entries = self.trace_manager.is_entry_valid(entries)
553
554
        color = {"color_field": "dl_src", "color_value": "ee:ee:ee:ee:01:2c"}
555
556
        # Execute tracepath
557
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
558
        tracer.tracepath_loop(trace_entries, color, switch)
559
560
        result = tracer.trace_result
561
562
        mock_probe.assert_called_once()
563
        mock_color.assert_called_once()
564
        mock_switch_colors.assert_called_once()
565
        self.assertEqual(result[0]["type"], "last")
566
        self.assertEqual(result[0]["reason"], "done")
567
        self.assertEqual(result[0]["msg"], "none")
568
569
    @patch("napps.amlight.sdntrace.shared.colors.Colors.get_switch_color")
570
    @patch("napps.amlight.sdntrace.shared.colors.Colors._get_colors")
571
    @patch("napps.amlight.sdntrace.shared.switches.Switches.get_switch")
572
    @patch("napps.amlight.sdntrace.tracing.tracer.TracePath.send_trace_probe")
573
    @patch("napps.amlight.sdntrace.tracing.tracer.prepare_next_packet")
574
    @patch("napps.amlight.sdntrace.tracing.tracer.TracePath.check_loop")
575
    def test_tracepath_loop_with_loop(
576
        self,
577
        mock_check_loop,
578
        mock_next_packet,
579
        mock_probe,
580
        mock_get_switch,
581
        mock_color,
582
        mock_switch_colors,
583
    ):
584
        """Test tracepath loop method finishing with a loop."""
585
        mock_switch_colors.return_value = "ee:ee:ee:ee:ee:01"
586
        mock_check_loop.return_value = True
587
588
        # Patch Switches.get_switch
589
        def wrap_get_switch(dpid):
590
            switch = MagicMock()
591
            switch.dpid = dpid
592
            return switch
593
594
        mock_get_switch.side_effect = wrap_get_switch
595
596
        mock_probe.return_value = [
597
            {"dpid": "00:00:00:00:00:00:00:01", "port": 1},
598
            "fake_event_object",
599
        ]
600
601
        # Trace id to recover the result
602
        trace_id = 111
603
604
        # Creating trace entries
605
        eth = {"dl_vlan": 100}
606
        dpid = {"dpid": "00:00:00:00:00:00:00:01", "in_port": 1}
607
        switch = {"switch": dpid, "eth": eth}
608
        entries = {"trace": switch}
609
        trace_entries = self.trace_manager.is_entry_valid(entries)
610
611
        tracer = TracePath(self.trace_manager, trace_id, trace_entries)
612
613
        # Mock the next packt to stop the trace loop
614
        # pylint: disable=unused-argument
615
        def wrap_next_packet(entries, result, packet_in):
616
            tracer.trace_ended = True
617
            return "", "", ""
618
619
        mock_next_packet.side_effect = wrap_next_packet
620
621
        color = {"color_field": "dl_src", "color_value": "ee:ee:ee:ee:01:2c"}
622
623
        # Execute tracepath
624
        tracer.tracepath_loop(trace_entries, color, switch)
625
        result = tracer.trace_result
626
627
        mock_check_loop.assert_called_once()
628
        mock_next_packet.assert_not_called()
629
        mock_probe.assert_called_once()
630
        self.assertEqual(mock_get_switch.call_count, 3)
631
        mock_color.assert_called_once()
632
        mock_switch_colors.assert_called_once()
633
634
        self.assertEqual(result[0]["type"], "trace")
635
        self.assertEqual(result[0]["dpid"], "00:00:00:00:00:00:00:01")
636