]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/ldp_topo1/test_ldp_topo1.py
4 # test_bgp_multiview_topo1.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2016 by
8 # Network Device Education Foundation, Inc. ("NetDEF")
10 # Permission to use, copy, modify, and/or distribute this software
11 # for any purpose with or without fee is hereby granted, provided
12 # that the above copyright notice and this permission notice appear
15 # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
16 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
18 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
19 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
21 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26 test_ldp_topo1.py: Simple FRR LDP Test
45 r2-eth2 .2 | | .2 r2-eth1
48 ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
50 ~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~
51 ~~~~~~~~~~~~~ ~~~~~~~~~~~~~
55 r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0
56 +----+--+---+ +----+----+
58 | 3.3.3.3 | | 4.4.4.4 |
59 +-----------+ +---------+
67 from functools
import partial
68 from time
import sleep
69 from lib
.topolog
import logger
71 # Save the Current Working Directory to find configuration files.
72 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
73 sys
.path
.append(os
.path
.join(CWD
, "../"))
75 sys
.path
.append(os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
))))
76 from lib
import topotest
77 from lib
.topogen
import Topogen
, get_topogen
81 pytestmark
= [pytest
.mark
.ldpd
, pytest
.mark
.ospfd
]
83 #####################################################
85 ## Network Topology Definition
87 #####################################################
94 tgen
.add_router("r%s" % i
)
97 switch
= tgen
.add_switch("sw0")
98 switch
.add_link(tgen
.gears
["r1"])
99 switch
.add_link(tgen
.gears
["r2"])
101 switch
= tgen
.add_switch("sw1")
102 switch
.add_link(tgen
.gears
["r2"])
103 switch
.add_link(tgen
.gears
["r3"])
104 switch
.add_link(tgen
.gears
["r4"])
106 switch
= tgen
.add_switch("sw2")
107 switch
.add_link(tgen
.gears
["r2"])
108 switch
.add_link(tgen
.gears
["r3"])
111 #####################################################
115 #####################################################
118 def router_compare_json_output(rname
, command
, reference
, count
=60, wait
=1):
119 "Compare router JSON output"
121 logger
.info('Comparing router "%s" "%s" output', rname
, command
)
124 filename
= "{}/{}/{}".format(CWD
, rname
, reference
)
125 expected
= json
.loads(open(filename
).read())
127 # Run test function until we get an result.
128 test_func
= partial(topotest
.router_json_cmp
, tgen
.gears
[rname
], command
, expected
)
129 _
, diff
= topotest
.run_and_expect(test_func
, None, count
, wait
)
130 assertmsg
= '"{}" JSON output mismatches the expected result'.format(rname
)
131 assert diff
is None, assertmsg
134 #####################################################
138 #####################################################
141 def setup_module(module
):
142 print("\n\n** %s: Setup Topology" % module
.__name
__)
143 print("******************************************\n")
145 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
146 tgen
= Topogen(build_topo
, module
.__name
__)
147 tgen
.start_topology()
152 for i
in range(1, 5):
153 net
["r%s" % i
].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir
, i
))
154 net
["r%s" % i
].loadConf("ospfd", "%s/r%s/ospfd.conf" % (thisDir
, i
))
155 net
["r%s" % i
].loadConf("ldpd", "%s/r%s/ldpd.conf" % (thisDir
, i
))
156 tgen
.gears
["r%s" % i
].start()
158 # For debugging after starting FRR daemons, uncomment the next line
162 def teardown_module(module
):
163 print("\n\n** %s: Shutdown Topology" % module
.__name
__)
164 print("******************************************\n")
169 def test_router_running():
171 net
= get_topogen().net
173 # Skip if previous fatal error condition is raised
174 if fatal_error
!= "":
175 pytest
.skip(fatal_error
)
177 print("\n\n** Check if FRR is running on each Router node")
178 print("******************************************\n")
182 for i
in range(1, 5):
183 fatal_error
= net
["r%s" % i
].checkRouterRunning()
184 assert fatal_error
== "", fatal_error
187 def test_mpls_interfaces():
189 net
= get_topogen().net
191 # Skip if previous fatal error condition is raised
192 if fatal_error
!= "":
193 pytest
.skip(fatal_error
)
195 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
197 # Verify MPLS Interfaces
198 print("\n\n** Verifying MPLS Interfaces")
199 print("******************************************\n")
201 for i
in range(1, 5):
202 refTableFile
= "%s/r%s/show_mpls_ldp_interface.ref"
203 if os
.path
.isfile(refTableFile
):
204 # Read expected result from file
205 expected
= open(refTableFile
).read().rstrip()
206 # Fix newlines (make them all the same)
207 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
209 # Actual output from router
212 .cmd('vtysh -c "show mpls ldp interface" 2> /dev/null')
215 # Mask out Timer in Uptime
216 actual
= re
.sub(r
" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual
)
217 # Fix newlines (make them all the same)
218 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
221 diff
= topotest
.get_textdiff(
224 title1
="actual MPLS LDP interface status",
225 title2
="expected MPLS LDP interface status",
228 # Empty string if it matches, otherwise diff contains unified diff
231 "r%s failed MPLS LDP Interface status Check:\n%s\n" % (i
, diff
)
238 fatal_error
= "MPLS LDP Interface status failed"
242 ), "MPLS LDP Interface status failed for router r%s:\n%s" % (i
, diff
)
244 # Make sure that all daemons are running
245 for i
in range(1, 5):
246 fatal_error
= net
["r%s" % i
].checkRouterRunning()
247 assert fatal_error
== "", fatal_error
250 def test_ospf_convergence():
251 logger
.info("Test: check OSPF adjacencies")
253 # Skip if previous fatal error condition is raised
254 if fatal_error
!= "":
255 pytest
.skip(fatal_error
)
257 for rname
in ["r1", "r2", "r3", "r4"]:
258 router_compare_json_output(
259 rname
, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json"
263 def test_mpls_ldp_neighbor_establish():
265 net
= get_topogen().net
267 # Skip if previous fatal error condition is raised
268 if fatal_error
!= "":
269 pytest
.skip(fatal_error
)
271 neighbors_operational
= {
278 # Wait for MPLS LDP neighbors to establish.
279 print("\n\n** Verify MPLS LDP neighbors to establish")
280 print("******************************************\n")
283 print("Timeout in %s: " % timeout
),
285 # Look for any node not yet converged
286 for i
in range(1, 5):
289 .cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null')
293 # On current version, we need to make sure they all turn to OPERATIONAL on all lines
295 lines
= ("\n".join(established
.splitlines()) + "\n").splitlines(1)
296 # Check all lines to be either table header (starting with ^AF or show OPERATIONAL)
298 operational
= r
"^ip.*OPERATIONAL.*"
299 found_operational
= 0
300 for j
in range(1, len(lines
)):
301 if (not re
.search(header
, lines
[j
])) and (
302 not re
.search(operational
, lines
[j
])
304 established
= "" # Empty string shows NOT established
305 if re
.search(operational
, lines
[j
]):
306 found_operational
+= 1
308 logger
.info("Found operational %d" % found_operational
)
309 if found_operational
< 1:
310 # Need at least one operational neighbor
311 established
= "" # Empty string shows NOT established
313 if found_operational
!= neighbors_operational
[i
]:
316 print("Waiting for r%s" % i
)
326 # Bail out with error if a router fails to converge
327 fatal_error
= "MPLS LDP neighbors did not establish"
328 assert False, "MPLS LDP neighbors did not establish"
330 print("MPLS LDP neighbors established.")
333 # Only wait if we actually went through a convergence
334 print("\nwaiting 15s for LDP sessions to establish")
337 # Make sure that all daemons are running
338 for i
in range(1, 5):
339 fatal_error
= net
["r%s" % i
].checkRouterRunning()
340 assert fatal_error
== "", fatal_error
343 def test_mpls_ldp_discovery():
345 net
= get_topogen().net
347 # Skip if previous fatal error condition is raised
348 if fatal_error
!= "":
349 pytest
.skip(fatal_error
)
351 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
353 # Verify MPLS LDP discovery
354 print("\n\n** Verifying MPLS LDP discovery")
355 print("******************************************\n")
357 for i
in range(1, 5):
358 refTableFile
= "%s/r%s/show_mpls_ldp_discovery.ref" % (thisDir
, i
)
359 if os
.path
.isfile(refTableFile
):
360 # Actual output from router
363 .cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null')
367 # Read expected result from file
368 expected
= open(refTableFile
).read().rstrip()
369 # Fix newlines (make them all the same)
370 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
372 # Actual output from router
375 .cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null')
379 # Fix newlines (make them all the same)
380 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
383 diff
= topotest
.get_textdiff(
386 title1
="actual MPLS LDP discovery output",
387 title2
="expected MPLS LDP discovery output",
390 # Empty string if it matches, otherwise diff contains unified diff
393 "r%s failed MPLS LDP discovery output Check:\n%s\n" % (i
, diff
)
401 ), "MPLS LDP Interface discovery output for router r%s:\n%s" % (i
, diff
)
403 # Make sure that all daemons are running
404 for i
in range(1, 5):
405 fatal_error
= net
["r%s" % i
].checkRouterRunning()
406 assert fatal_error
== "", fatal_error
409 def test_mpls_ldp_neighbor():
411 net
= get_topogen().net
413 # Skip if previous fatal error condition is raised
414 if fatal_error
!= "":
415 pytest
.skip(fatal_error
)
417 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
419 # Verify MPLS LDP neighbor
420 print("\n\n** Verifying MPLS LDP neighbor")
421 print("******************************************\n")
423 for i
in range(1, 5):
424 refTableFile
= "%s/r%s/show_mpls_ldp_neighbor.ref" % (thisDir
, i
)
425 if os
.path
.isfile(refTableFile
):
426 # Read expected result from file
427 expected
= open(refTableFile
).read().rstrip()
428 # Fix newlines (make them all the same)
429 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
431 # Actual output from router
434 .cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null')
438 # Mask out changing parts in output
439 # Mask out Timer in Uptime
441 r
"(ipv4 [0-9\.]+ +OPERATIONAL [0-9\.]+ +)[0-9][0-9]:[0-9][0-9]:[0-9][0-9]",
446 # Fix newlines (make them all the same)
447 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
450 diff
= topotest
.get_textdiff(
453 title1
="actual MPLS LDP neighbor output",
454 title2
="expected MPLS LDP neighbor output",
457 # Empty string if it matches, otherwise diff contains unified diff
460 "r%s failed MPLS LDP neighbor output Check:\n%s\n" % (i
, diff
)
468 ), "MPLS LDP Interface neighbor output for router r%s:\n%s" % (i
, diff
)
470 # Make sure that all daemons are running
471 for i
in range(1, 5):
472 fatal_error
= net
["r%s" % i
].checkRouterRunning()
473 assert fatal_error
== "", fatal_error
476 def test_mpls_ldp_binding():
478 net
= get_topogen().net
480 # Skip this test for now until proper sorting of the output
482 # pytest.skip("Skipping test_mpls_ldp_binding")
484 # Skip if previous fatal error condition is raised
485 if fatal_error
!= "":
486 pytest
.skip(fatal_error
)
488 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
490 # Verify MPLS LDP binding
491 print("\n\n** Verifying MPLS LDP binding")
492 print("******************************************\n")
494 for i
in range(1, 5):
495 refTableFile
= "%s/r%s/show_mpls_ldp_binding.ref" % (thisDir
, i
)
496 if os
.path
.isfile(refTableFile
):
497 # Read expected result from file
498 expected
= open(refTableFile
).read().rstrip()
499 # Fix newlines (make them all the same)
500 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
502 # Actual output from router
505 .cmd('vtysh -c "show mpls ldp binding" 2> /dev/null')
509 # Mask out changing parts in output
512 r
"(ipv4 [0-9\./]+ +[0-9\.]+ +)[0-9][0-9] (.*)", r
"\1xxx\2", actual
515 r
"(ipv4 [0-9\./]+ +[0-9\.]+ +[a-z\-]+ +)[0-9][0-9] (.*)",
520 # Fix newlines (make them all the same)
521 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
523 # Sort lines which start with "xx via inet "
524 pattern
= r
"^\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+"
528 for j
in range(1, len(actual
)):
529 if re
.search(pattern
, actual
[j
]) and re
.search(
530 pattern
, actual
[j
- 1]
532 if actual
[j
- 1] > actual
[j
]:
534 actual
[j
- 1] = actual
[j
]
539 diff
= topotest
.get_textdiff(
542 title1
="actual MPLS LDP binding output",
543 title2
="expected MPLS LDP binding output",
546 # Empty string if it matches, otherwise diff contains unified diff
549 "r%s failed MPLS LDP binding output Check:\n%s\n" % (i
, diff
)
555 assert failures
== 0, "MPLS LDP binding output for router r%s:\n%s" % (
560 # Make sure that all daemons are running
561 for i
in range(1, 5):
562 fatal_error
= net
["r%s" % i
].checkRouterRunning()
563 assert fatal_error
== "", fatal_error
566 def test_zebra_ipv4_routingTable():
568 net
= get_topogen().net
570 # Skip if previous fatal error condition is raised
571 if fatal_error
!= "":
572 pytest
.skip(fatal_error
)
574 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
576 # Verify Zebra IPv4 Routing Table
577 print("\n\n** Verifying Zebra IPv4 Routing Table")
578 print("******************************************\n")
580 for i
in range(1, 5):
581 refTableFile
= "%s/r%s/show_ipv4_route.ref" % (thisDir
, i
)
582 if os
.path
.isfile(refTableFile
):
583 # Read expected result from file
584 expected
= open(refTableFile
).read().rstrip()
586 # Actual output from router
589 .cmd('vtysh -c "show ip route" 2> /dev/null | grep "^O"')
592 # Drop timers on end of line
593 actual
= re
.sub(r
", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual
)
595 # Mask out label - all LDP labels should be >= 10 (2-digit)
596 # leaving the implicit labels unmasked
597 actual
= re
.sub(r
" label [0-9][0-9]+", " label xxx", actual
)
598 # and translating remaining implicit (single-digit) labels to label implicit-null
599 actual
= re
.sub(r
" label [0-9]+", " label implicit-null", actual
)
600 # Check if we have implicit labels - if not, then remove them from reference
601 if not re
.search(r
" label implicit-null", actual
):
602 expected
= re
.sub(r
", label implicit-null", "", expected
)
604 # now fix newlines of expected (make them all the same)
605 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
607 # Fix newlines (make them all the same)
608 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
611 diff
= topotest
.get_textdiff(
614 title1
="actual IPv4 zebra routing table",
615 title2
="expected IPv4 zebra routing table",
618 # Empty string if it matches, otherwise diff contains unified diff
621 "r%s failed IPv4 Zebra Routing Table Check:\n%s\n" % (i
, diff
)
629 ), "IPv4 Zebra Routing Table verification failed for router r%s:\n%s" % (
634 # Make sure that all daemons are running
635 for i
in range(1, 5):
636 fatal_error
= net
["r%s" % i
].checkRouterRunning()
637 assert fatal_error
== "", fatal_error
640 def test_mpls_table():
642 net
= get_topogen().net
644 # Skip if previous fatal error condition is raised
645 if fatal_error
!= "":
646 pytest
.skip(fatal_error
)
648 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
651 print("\n\n** Verifying MPLS table")
652 print("******************************************\n")
655 for i
in range(1, 5):
656 refTableFile
= "%s/r%s/show_mpls_table.ref" % (thisDir
, i
)
657 if os
.path
.isfile(refTableFile
):
658 # Read expected result from file
659 expected
= open(refTableFile
).read()
660 # Fix newlines (make them all the same)
661 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
663 # Actual output from router
664 actual
= net
["r%s" % i
].cmd('vtysh -c "show mpls table" 2> /dev/null')
666 # Fix inconsistent Label numbers at beginning of line
667 actual
= re
.sub(r
"(\s+)[0-9]+(\s+LDP)", r
"\1XX\2", actual
)
668 # Fix inconsistent Label numbers at end of line
670 r
"(\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+)[0-9][0-9]", r
"\1XX", actual
673 # Fix newlines (make them all the same)
674 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
676 # Sort lines which start with " XX LDP"
677 pattern
= r
"^\s+[0-9X]+\s+LDP"
681 for j
in range(1, len(actual
)):
682 if re
.search(pattern
, actual
[j
]) and re
.search(
683 pattern
, actual
[j
- 1]
685 if actual
[j
- 1] > actual
[j
]:
687 actual
[j
- 1] = actual
[j
]
692 diff
= topotest
.get_textdiff(
695 title1
="actual MPLS table output",
696 title2
="expected MPLS table output",
699 # Empty string if it matches, otherwise diff contains unified diff
702 "r%s failed MPLS table output Check:\n%s\n" % (i
, diff
)
708 assert failures
== 0, "MPLS table output for router r%s:\n%s" % (i
, diff
)
710 # Make sure that all daemons are running
711 for i
in range(1, 5):
712 fatal_error
= net
["r%s" % i
].checkRouterRunning()
713 assert fatal_error
== "", fatal_error
716 def test_linux_mpls_routes():
718 net
= get_topogen().net
720 # Skip if previous fatal error condition is raised
721 if fatal_error
!= "":
722 pytest
.skip(fatal_error
)
724 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
726 # Verify Linux Kernel MPLS routes
727 print("\n\n** Verifying Linux Kernel MPLS routes")
728 print("******************************************\n")
730 for i
in range(1, 5):
731 refTableFile
= "%s/r%s/ip_mpls_route.ref" % (thisDir
, i
)
732 if os
.path
.isfile(refTableFile
):
733 # Read expected result from file
734 expected
= open(refTableFile
).read().rstrip()
735 # Fix newlines (make them all the same)
736 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
738 # Actual output from router
740 net
["r%s" % i
].cmd("ip -o -family mpls route 2> /dev/null").rstrip()
743 # Mask out label and protocol
744 actual
= re
.sub(r
"[0-9][0-9] via inet ", "xx via inet ", actual
)
745 actual
= re
.sub(r
"[0-9][0-9] +proto", "xx proto", actual
)
746 actual
= re
.sub(r
"[0-9][0-9] as to ", "xx as to ", actual
)
747 actual
= re
.sub(r
"[ ]+proto \w+", " proto xx", actual
)
751 for line
in actual
.splitlines():
752 tokens
= re
.split(r
"\\\t", line
.strip())
753 nexthop_sorted
.append(
756 " ".join([token
.strip() for token
in sorted(tokens
[1:])]),
760 # Sort lines and fixup differences between old and new iproute
761 actual
= "\n".join(sorted(nexthop_sorted
))
762 actual
= re
.sub(r
"nexthop via", "nexthopvia", actual
)
763 actual
= re
.sub(r
" nexthop as to xx via inet ", " nexthopvia inet ", actual
)
764 actual
= re
.sub(r
" weight 1", "", actual
)
765 actual
= re
.sub(r
" [ ]+", " ", actual
)
767 # put \n back at line ends
768 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
771 diff
= topotest
.get_textdiff(
774 title1
="actual Linux Kernel MPLS route",
775 title2
="expected Linux Kernel MPLS route",
778 # Empty string if it matches, otherwise diff contains unified diff
781 "r%s failed Linux Kernel MPLS route output Check:\n%s\n" % (i
, diff
)
789 ), "Linux Kernel MPLS route output for router r%s:\n%s" % (i
, diff
)
791 # Make sure that all daemons are running
792 for i
in range(1, 5):
793 fatal_error
= net
["r%s" % i
].checkRouterRunning()
794 assert fatal_error
== "", fatal_error
797 def test_shutdown_check_stderr():
799 net
= get_topogen().net
801 # Skip if previous fatal error condition is raised
802 if fatal_error
!= "":
803 pytest
.skip(fatal_error
)
805 if os
.environ
.get("TOPOTESTS_CHECK_STDERR") is None:
807 "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n"
809 pytest
.skip("Skipping test for Stderr output")
811 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
813 print("\n\n** Verifying unexpected STDERR output from daemons")
814 print("******************************************\n")
816 for i
in range(1, 5):
817 net
["r%s" % i
].stopRouter()
818 log
= net
["r%s" % i
].getStdErr("ldpd")
820 print("\nRouter r%s LDPd StdErr Log:\n%s" % (i
, log
))
821 log
= net
["r%s" % i
].getStdErr("ospfd")
823 print("\nRouter r%s OSPFd StdErr Log:\n%s" % (i
, log
))
824 log
= net
["r%s" % i
].getStdErr("zebra")
826 print("\nRouter r%s Zebra StdErr Log:\n%s" % (i
, log
))
829 def test_shutdown_check_memleak():
831 net
= get_topogen().net
833 # Skip if previous fatal error condition is raised
834 if fatal_error
!= "":
835 pytest
.skip(fatal_error
)
837 if os
.environ
.get("TOPOTESTS_CHECK_MEMLEAK") is None:
839 "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n"
841 pytest
.skip("Skipping test for memory leaks")
843 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
845 for i
in range(1, 5):
846 net
["r%s" % i
].stopRouter()
847 net
["r%s" % i
].report_memory_leaks(
848 os
.environ
.get("TOPOTESTS_CHECK_MEMLEAK"), os
.path
.basename(__file__
)
852 if __name__
== "__main__":
854 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
855 # retval = pytest.main(["-s", "--tb=no"])
856 retval
= pytest
.main(["-s"])