]>
Commit | Line | Data |
---|---|---|
d6df723b | 1 | #!/usr/bin/env python |
acddc0ed | 2 | # SPDX-License-Identifier: ISC |
d6df723b MW |
3 | |
4 | # | |
5 | # test_rip_topo1.py | |
6 | # Part of NetDEF Topology Tests | |
7 | # | |
8 | # Copyright (c) 2017 by | |
9 | # Network Device Education Foundation, Inc. ("NetDEF") | |
10 | # | |
d6df723b MW |
11 | |
12 | """ | |
13 | test_rip_topo1.py: Testing RIPv2 | |
14 | ||
15 | """ | |
16 | ||
17 | import os | |
18 | import re | |
19 | import sys | |
d6df723b MW |
20 | import pytest |
21 | from time import sleep | |
22 | ||
d6df723b | 23 | |
d6df723b MW |
24 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
25 | from lib import topotest | |
e82b531d | 26 | from lib.topogen import Topogen, get_topogen |
d6df723b MW |
27 | |
28 | fatal_error = "" | |
29 | ||
6907ac7e | 30 | pytestmark = [pytest.mark.ripd] |
d6df723b MW |
31 | |
32 | ##################################################### | |
33 | ## | |
34 | ## Network Topology Definition | |
35 | ## | |
36 | ##################################################### | |
37 | ||
787e7624 | 38 | |
e82b531d CH |
39 | def build_topo(tgen): |
40 | # Setup RIP Routers | |
41 | for i in range(1, 4): | |
42 | tgen.add_router("r%s" % i) | |
43 | ||
44 | # | |
45 | # On main router | |
46 | # First switch is for a dummy interface (for local network) | |
47 | switch = tgen.add_switch("sw1") | |
48 | switch.add_link(tgen.gears["r1"]) | |
49 | # | |
50 | # Switches for RIP | |
51 | ||
52 | # switch 2 switch is for connection to RIP router | |
53 | switch = tgen.add_switch("sw2") | |
54 | switch.add_link(tgen.gears["r1"]) | |
55 | switch.add_link(tgen.gears["r2"]) | |
56 | ||
57 | # switch 3 is between RIP routers | |
58 | switch = tgen.add_switch("sw3") | |
59 | switch.add_link(tgen.gears["r2"]) | |
60 | switch.add_link(tgen.gears["r3"], nodeif="r3-eth1") | |
61 | ||
62 | # switch 4 is stub on remote RIP router | |
63 | switch = tgen.add_switch("sw4") | |
64 | switch.add_link(tgen.gears["r3"], nodeif="r3-eth0") | |
65 | ||
66 | switch = tgen.add_switch("sw5") | |
67 | switch.add_link(tgen.gears["r1"]) | |
68 | ||
69 | switch = tgen.add_switch("sw6") | |
70 | switch.add_link(tgen.gears["r1"]) | |
cfe9a587 | 71 | |
d6df723b MW |
72 | |
73 | ##################################################### | |
74 | ## | |
75 | ## Tests starting | |
76 | ## | |
77 | ##################################################### | |
78 | ||
6907ac7e | 79 | |
d6df723b | 80 | def setup_module(module): |
d6df723b MW |
81 | print("\n\n** %s: Setup Topology" % module.__name__) |
82 | print("******************************************\n") | |
83 | ||
d6df723b | 84 | thisDir = os.path.dirname(os.path.realpath(__file__)) |
e82b531d CH |
85 | tgen = Topogen(build_topo, module.__name__) |
86 | tgen.start_topology() | |
d6df723b | 87 | |
e82b531d | 88 | net = tgen.net |
d6df723b MW |
89 | |
90 | # Starting Routers | |
91 | # | |
92 | for i in range(1, 4): | |
787e7624 | 93 | net["r%s" % i].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir, i)) |
94 | net["r%s" % i].loadConf("ripd", "%s/r%s/ripd.conf" % (thisDir, i)) | |
e82b531d | 95 | tgen.gears["r%s" % i].start() |
d6df723b | 96 | |
622c4996 | 97 | # For debugging after starting FRR daemons, uncomment the next line |
a1985a2d | 98 | # tgen.mininet_cli() |
d6df723b MW |
99 | |
100 | ||
101 | def teardown_module(module): | |
d6df723b MW |
102 | print("\n\n** %s: Shutdown Topology" % module.__name__) |
103 | print("******************************************\n") | |
e82b531d CH |
104 | tgen = get_topogen() |
105 | tgen.stop_topology() | |
d6df723b MW |
106 | |
107 | ||
108 | def test_router_running(): | |
109 | global fatal_error | |
e82b531d | 110 | net = get_topogen().net |
d6df723b MW |
111 | |
112 | # Skip if previous fatal error condition is raised | |
787e7624 | 113 | if fatal_error != "": |
d6df723b MW |
114 | pytest.skip(fatal_error) |
115 | ||
622c4996 | 116 | print("\n\n** Check if FRR is running on each Router node") |
d6df723b | 117 | print("******************************************\n") |
d6df723b | 118 | |
28aa9ae6 | 119 | # Make sure that all daemons are running |
d6df723b | 120 | for i in range(1, 4): |
787e7624 | 121 | fatal_error = net["r%s" % i].checkRouterRunning() |
d6df723b MW |
122 | assert fatal_error == "", fatal_error |
123 | ||
d6df723b MW |
124 | |
125 | def test_converge_protocols(): | |
126 | global fatal_error | |
e82b531d | 127 | net = get_topogen().net |
d6df723b MW |
128 | |
129 | # Skip if previous fatal error condition is raised | |
787e7624 | 130 | if fatal_error != "": |
d6df723b MW |
131 | pytest.skip(fatal_error) |
132 | ||
133 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
134 | ||
135 | print("\n\n** Waiting for protocols convergence") | |
136 | print("******************************************\n") | |
137 | ||
b01c46b9 | 138 | # Not really implemented yet - just sleep 11 secs for now |
e82b531d | 139 | sleep(21) |
d6df723b | 140 | |
28aa9ae6 MW |
141 | # Make sure that all daemons are still running |
142 | for i in range(1, 4): | |
787e7624 | 143 | fatal_error = net["r%s" % i].checkRouterRunning() |
28aa9ae6 MW |
144 | assert fatal_error == "", fatal_error |
145 | ||
d6df723b MW |
146 | |
147 | def test_rip_status(): | |
148 | global fatal_error | |
e82b531d | 149 | net = get_topogen().net |
d6df723b MW |
150 | |
151 | # Skip if previous fatal error condition is raised | |
787e7624 | 152 | if fatal_error != "": |
d6df723b MW |
153 | pytest.skip(fatal_error) |
154 | ||
155 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
156 | ||
157 | # Verify RIP Status | |
158 | print("\n\n** Verifing RIP status") | |
159 | print("******************************************\n") | |
160 | failures = 0 | |
161 | for i in range(1, 4): | |
787e7624 | 162 | refTableFile = "%s/r%s/rip_status.ref" % (thisDir, i) |
d6df723b MW |
163 | if os.path.isfile(refTableFile): |
164 | # Read expected result from file | |
165 | expected = open(refTableFile).read().rstrip() | |
166 | # Fix newlines (make them all the same) | |
787e7624 | 167 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
d6df723b MW |
168 | |
169 | # Actual output from router | |
787e7624 | 170 | actual = ( |
171 | net["r%s" % i] | |
172 | .cmd('vtysh -c "show ip rip status" 2> /dev/null') | |
173 | .rstrip() | |
174 | ) | |
175 | # Drop time in next due | |
d6df723b MW |
176 | actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) |
177 | # Drop time in last update | |
178 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
179 | # Fix newlines (make them all the same) | |
787e7624 | 180 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
d6df723b MW |
181 | |
182 | # Generate Diff | |
787e7624 | 183 | diff = topotest.get_textdiff( |
184 | actual, | |
185 | expected, | |
17070436 | 186 | title1="actual IP RIP status", |
787e7624 | 187 | title2="expected IP RIP status", |
188 | ) | |
d6df723b MW |
189 | |
190 | # Empty string if it matches, otherwise diff contains unified diff | |
191 | if diff: | |
787e7624 | 192 | sys.stderr.write("r%s failed IP RIP status check:\n%s\n" % (i, diff)) |
d6df723b MW |
193 | failures += 1 |
194 | else: | |
195 | print("r%s ok" % i) | |
196 | ||
197 | assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff) | |
198 | ||
28aa9ae6 MW |
199 | # Make sure that all daemons are still running |
200 | for i in range(1, 4): | |
787e7624 | 201 | fatal_error = net["r%s" % i].checkRouterRunning() |
28aa9ae6 MW |
202 | assert fatal_error == "", fatal_error |
203 | ||
d6df723b MW |
204 | |
205 | def test_rip_routes(): | |
206 | global fatal_error | |
e82b531d | 207 | net = get_topogen().net |
d6df723b MW |
208 | |
209 | # Skip if previous fatal error condition is raised | |
787e7624 | 210 | if fatal_error != "": |
d6df723b MW |
211 | pytest.skip(fatal_error) |
212 | ||
213 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
214 | ||
215 | # Verify RIP Status | |
216 | print("\n\n** Verifing RIP routes") | |
217 | print("******************************************\n") | |
218 | failures = 0 | |
219 | for i in range(1, 4): | |
787e7624 | 220 | refTableFile = "%s/r%s/show_ip_rip.ref" % (thisDir, i) |
d6df723b MW |
221 | if os.path.isfile(refTableFile): |
222 | # Read expected result from file | |
223 | expected = open(refTableFile).read().rstrip() | |
224 | # Fix newlines (make them all the same) | |
787e7624 | 225 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
d6df723b MW |
226 | |
227 | # Actual output from router | |
787e7624 | 228 | actual = net["r%s" % i].cmd('vtysh -c "show ip rip" 2> /dev/null').rstrip() |
d6df723b MW |
229 | # Drop Time |
230 | actual = re.sub(r"[0-9][0-9]:[0-5][0-9]", "XX:XX", actual) | |
231 | # Fix newlines (make them all the same) | |
787e7624 | 232 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
d6df723b MW |
233 | |
234 | # Generate Diff | |
787e7624 | 235 | diff = topotest.get_textdiff( |
236 | actual, | |
237 | expected, | |
17070436 | 238 | title1="actual SHOW IP RIP", |
787e7624 | 239 | title2="expected SHOW IP RIP", |
240 | ) | |
d6df723b MW |
241 | |
242 | # Empty string if it matches, otherwise diff contains unified diff | |
243 | if diff: | |
787e7624 | 244 | sys.stderr.write("r%s failed SHOW IP RIP check:\n%s\n" % (i, diff)) |
d6df723b MW |
245 | failures += 1 |
246 | else: | |
247 | print("r%s ok" % i) | |
248 | ||
249 | assert failures == 0, "SHOW IP RIP failed for router r%s:\n%s" % (i, diff) | |
250 | ||
28aa9ae6 MW |
251 | # Make sure that all daemons are still running |
252 | for i in range(1, 4): | |
787e7624 | 253 | fatal_error = net["r%s" % i].checkRouterRunning() |
28aa9ae6 MW |
254 | assert fatal_error == "", fatal_error |
255 | ||
d6df723b MW |
256 | |
257 | def test_zebra_ipv4_routingTable(): | |
258 | global fatal_error | |
e82b531d | 259 | net = get_topogen().net |
d6df723b MW |
260 | |
261 | # Skip if previous fatal error condition is raised | |
787e7624 | 262 | if fatal_error != "": |
d6df723b MW |
263 | pytest.skip(fatal_error) |
264 | ||
265 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
266 | ||
267 | # Verify OSPFv3 Routing Table | |
268 | print("\n\n** Verifing Zebra IPv4 Routing Table") | |
269 | print("******************************************\n") | |
270 | failures = 0 | |
271 | for i in range(1, 4): | |
787e7624 | 272 | refTableFile = "%s/r%s/show_ip_route.ref" % (thisDir, i) |
d6df723b MW |
273 | if os.path.isfile(refTableFile): |
274 | # Read expected result from file | |
275 | expected = open(refTableFile).read().rstrip() | |
276 | # Fix newlines (make them all the same) | |
787e7624 | 277 | expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1) |
d6df723b MW |
278 | |
279 | # Actual output from router | |
787e7624 | 280 | actual = ( |
281 | net["r%s" % i] | |
282 | .cmd('vtysh -c "show ip route" 2> /dev/null | grep "^R"') | |
283 | .rstrip() | |
284 | ) | |
622c4996 | 285 | # Drop timers on end of line |
d6df723b MW |
286 | actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual) |
287 | # Fix newlines (make them all the same) | |
787e7624 | 288 | actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) |
d6df723b MW |
289 | |
290 | # Generate Diff | |
787e7624 | 291 | diff = topotest.get_textdiff( |
292 | actual, | |
293 | expected, | |
17070436 | 294 | title1="actual Zebra IPv4 routing table", |
787e7624 | 295 | title2="expected Zebra IPv4 routing table", |
296 | ) | |
d6df723b MW |
297 | |
298 | # Empty string if it matches, otherwise diff contains unified diff | |
299 | if diff: | |
787e7624 | 300 | sys.stderr.write( |
301 | "r%s failed Zebra IPv4 Routing Table Check:\n%s\n" % (i, diff) | |
302 | ) | |
d6df723b MW |
303 | failures += 1 |
304 | else: | |
305 | print("r%s ok" % i) | |
306 | ||
9fa6ec14 | 307 | assert ( |
308 | failures == 0 | |
309 | ), "Zebra IPv4 Routing Table verification failed for router r%s:\n%s" % ( | |
310 | i, | |
311 | diff, | |
787e7624 | 312 | ) |
d6df723b | 313 | |
28aa9ae6 MW |
314 | # Make sure that all daemons are still running |
315 | for i in range(1, 4): | |
787e7624 | 316 | fatal_error = net["r%s" % i].checkRouterRunning() |
28aa9ae6 MW |
317 | assert fatal_error == "", fatal_error |
318 | ||
d6df723b MW |
319 | |
320 | def test_shutdown_check_stderr(): | |
321 | global fatal_error | |
e82b531d | 322 | net = get_topogen().net |
d6df723b MW |
323 | |
324 | # Skip if previous fatal error condition is raised | |
787e7624 | 325 | if fatal_error != "": |
d6df723b MW |
326 | pytest.skip(fatal_error) |
327 | ||
787e7624 | 328 | if os.environ.get("TOPOTESTS_CHECK_STDERR") is None: |
329 | pytest.skip("Skipping test for Stderr output and memory leaks") | |
d6df723b MW |
330 | |
331 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
332 | ||
333 | print("\n\n** Verifing unexpected STDERR output from daemons") | |
334 | print("******************************************\n") | |
335 | ||
787e7624 | 336 | net["r1"].stopRouter() |
d6df723b | 337 | |
787e7624 | 338 | log = net["r1"].getStdErr("ripd") |
8e957dbb MW |
339 | if log: |
340 | print("\nRIPd StdErr Log:\n" + log) | |
787e7624 | 341 | log = net["r1"].getStdErr("zebra") |
8e957dbb MW |
342 | if log: |
343 | print("\nZebra StdErr Log:\n" + log) | |
d6df723b MW |
344 | |
345 | ||
787e7624 | 346 | if __name__ == "__main__": |
d6df723b | 347 | |
d6df723b MW |
348 | # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli |
349 | # retval = pytest.main(["-s", "--tb=no"]) | |
350 | retval = pytest.main(["-s"]) | |
351 | sys.exit(retval) |