]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/cspf_topo1/test_cspf_topo1.py
Merge pull request #10447 from ton31337/fix/json_with_whitespaces
[mirror_frr.git] / tests / topotests / cspf_topo1 / test_cspf_topo1.py
1 #!/usr/bin/env python
2
3 #
4 # test_cspf_topo1.py
5 # Part of NetDEF Topology Tests
6 #
7 # Copyright (c) 2022 by Orange
8 # Author: Olivier Dugeon <olivier.dugeon@orange.com>
9 #
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
13 # in all copies.
14 #
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
22 # OF THIS SOFTWARE.
23 #
24
25 """
26 test_cspf_topo1.py: Test the FRR Constraint Shortest Path First algorithm.
27
28 +------------+
29 | |
30 | R1 |
31 | 10.0.225.1 |
32 | |
33 +------------+
34 r1-eth0| |r1-eth1
35 | |
36 10.0.0.0/24| |10.0.1.0/24
37 | |2001:db8:1:/64
38 | |
39 r2-eth0| |r2-eth1
40 +------------+ +------------+
41 | | | |
42 | R2 |r2-eth2 r3-eth0| R3 |
43 | 10.0.255.2 +------------------+ 10.0.255.3 |
44 | | 10.0.3.0/24 | |
45 +------------+ 2001:db8:3:/64 +------+-----+
46 r2-eth3| r3-eth1|
47 | |
48 10.0.4.0/24| |
49 | |
50 | |
51 r4-eth0| 2001:db8:5:/64|
52 +------------+ |
53 | | |
54 | R4 |r4-eth1 |
55 | 10.0.255.4 +-------------------------+
56 | |
57 +------------+
58
59 """
60
61 import os
62 import sys
63 import json
64 from functools import partial
65
66 # Save the Current Working Directory to find configuration files.
67 CWD = os.path.dirname(os.path.realpath(__file__))
68 sys.path.append(os.path.join(CWD, "../"))
69
70 # pylint: disable=C0413
71
72 # Import topogen and topotest helpers
73 from lib import topotest
74 from lib.topogen import Topogen, TopoRouter, get_topogen
75 from lib.topolog import logger
76
77 # and Finally pytest
78 import pytest
79
80 pytestmark = [pytest.mark.isisd]
81
82
83 def build_topo(tgen):
84 "Build function"
85
86 # Create 4 routers
87 for routern in range(1, 5):
88 tgen.add_router("r{}".format(routern))
89
90 # Interconect router 1 and 2 with 2 links
91 switch = tgen.add_switch("s1")
92 switch.add_link(tgen.gears["r1"])
93 switch.add_link(tgen.gears["r2"])
94 switch = tgen.add_switch("s2")
95 switch.add_link(tgen.gears["r1"])
96 switch.add_link(tgen.gears["r2"])
97
98 # Interconect router 3 and 2
99 switch = tgen.add_switch("s3")
100 switch.add_link(tgen.gears["r3"])
101 switch.add_link(tgen.gears["r2"])
102
103 # Interconect router 4 and 2
104 switch = tgen.add_switch("s4")
105 switch.add_link(tgen.gears["r4"])
106 switch.add_link(tgen.gears["r2"])
107
108 # Interconnect router 3 and 4
109 switch = tgen.add_switch("s5")
110 switch.add_link(tgen.gears["r3"])
111 switch.add_link(tgen.gears["r4"])
112
113
114 def setup_module(mod):
115 "Sets up the pytest environment"
116
117 logger.info("\n\n---- Starting CSPF tests ----\n")
118
119 tgen = Topogen(build_topo, mod.__name__)
120 tgen.start_topology()
121
122 router_list = tgen.routers()
123
124 for rname, router in router_list.items():
125 router.load_config(
126 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
127 )
128 router.load_config(
129 TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
130 )
131 if rname == "r1":
132 router.load_config(
133 TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format("r1"))
134 )
135
136 # Initialize all routers.
137 tgen.start_router()
138
139
140 def teardown_module():
141 "Teardown the pytest environment"
142
143 tgen = get_topogen()
144 tgen.stop_topology()
145
146 logger.info("\n\n---- CSPF tests End ----\n")
147
148
149 def compare_ted_json_output(tgen, rname, fileref):
150 "Compare TED JSON output"
151
152 logger.info('Comparing router "%s" TED output', rname)
153
154 filename = "{}/reference/{}".format(CWD, fileref)
155 expected = json.loads(open(filename).read())
156 command = "show sharp ted json"
157
158 # Run test function until we get an result. Wait at most 60 seconds.
159 test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
160 _, diff = topotest.run_and_expect(test_func, None, count=60, wait=2)
161 assertmsg = '"{}" TED JSON output mismatches the expected result'.format(rname)
162 assert diff is None, assertmsg
163
164
165 def compare_cspf_output(tgen, rname, fileref, src, dst, cost, bw=""):
166 "Compare CSPF output"
167
168 logger.info('Comparing router "%s" CSPF output', rname)
169
170 filename = "{}/reference/{}".format(CWD, fileref)
171 expected = open(filename).read()
172 command = "show sharp cspf source {} destination {} {} {}".format(src, dst, cost, bw)
173
174 # Run test function until we get an result. Wait at most 60 seconds.
175 test_func = partial(topotest.router_output_cmp, tgen.gears[rname], command, expected)
176 result, diff = topotest.run_and_expect(test_func, "", count=2, wait=2)
177 assert result, "CSPF output mismatches the expected result on {}:\n{}".format(rname, diff)
178
179
180 def setup_testcase(msg):
181 "Setup test case"
182
183 logger.info(msg)
184 tgen = get_topogen()
185
186 # Skip if previous fatal error condition is raised
187 if tgen.routers_have_failure():
188 pytest.skip(tgen.errors)
189
190 return tgen
191
192
193 # Note that all routers must discover the same Network Topology, so the same TED.
194
195
196 def test_step1():
197 "Step1: Check initial topology"
198
199 tgen = setup_testcase("Step1: test initial IS-IS TE Data Base import")
200 tgen.net["r1"].cmd('vtysh -c "sharp import-te"')
201
202 compare_ted_json_output(tgen, "r1", "sharp-ted.json")
203
204
205 def test_step2():
206 "Step2: Test CSPF from r1 to r4 for IPv4 with various metric"
207
208 tgen = setup_testcase("Step2: CSPF(r1, r4, IPv4)")
209
210 compare_cspf_output(tgen, "r1", "cspf-ipv4-metric.txt", "10.0.0.1", "10.0.255.4", "metric 50")
211 compare_cspf_output(tgen, "r1", "cspf-ipv4-te-metric.txt", "10.0.255.1", "10.0.4.4", "te-metric 50")
212 compare_cspf_output(tgen, "r1", "cspf-ipv4-delay.txt", "10.0.255.1", "10.0.255.4", "delay 50000")
213 compare_cspf_output(tgen, "r1", "cspf-ipv4-delay.txt", "10.0.255.1", "10.0.255.4", "delay 50000", "rsv 7 100000000")
214
215
216 def test_step3():
217 "Step3: Test CSPF from r1 to r4 for IPv6 with various metric"
218
219 tgen = setup_testcase("Step2: CSPF(r1, r4, IPv6)")
220
221 compare_cspf_output(tgen, "r1", "cspf-ipv6-metric.txt", "2001:db8:1::1:1", "2001:db8::4", "metric 50")
222 compare_cspf_output(tgen, "r1", "cspf-ipv6-te-metric.txt", "2001:db8::1", "2001:db8:5::3:4", "te-metric 80")
223 compare_cspf_output(tgen, "r1", "cspf-ipv6-delay.txt", "2001:db8::1", "2001:db8::4", "delay 80000")
224 compare_cspf_output(tgen, "r1", "cspf-ipv6-delay.txt", "2001:db8::1", "2001:db8::4", "delay 80000", "rsv 7 100000000")
225
226
227 def test_step4():
228 "Step4: Test CSPF from r1 to r4 with no possible path"
229
230 tgen = setup_testcase("Step2: CSPF(r1, r4, failure)")
231
232 compare_cspf_output(tgen, "r1", "cspf-failed.txt", "10.0.255.1", "10.0.255.4", "metric 10")
233 compare_cspf_output(tgen, "r1", "cspf-failed.txt", "2001:db8::1", "2001:db8::4", "te-metric 50")
234 compare_cspf_output(tgen, "r1", "cspf-failed.txt", "10.0.255.1", "10.0.255.4", "delay 5000")
235 compare_cspf_output(tgen, "r1", "cspf-failed.txt", "2001:db8::1", "2001:db8::4", "delay 80000", "rsv 7 1000000000")
236 compare_cspf_output(tgen, "r1", "cspf-failed-src.txt", "10.0.0.3", "10.0.255.4", "metric 10")
237 compare_cspf_output(tgen, "r1", "cspf-failed-dst.txt", "10.0.0.1", "10.0.4.40", "metric 10")
238 compare_cspf_output(tgen, "r1", "cspf-failed-same.txt", "10.0.0.1", "10.0.0.1", "metric 10")
239
240
241 def test_memory_leak():
242 "Run the memory leak test and report results."
243
244 tgen = get_topogen()
245 if not tgen.is_memleak_enabled():
246 pytest.skip("Memory leak test/report is disabled")
247
248 tgen.report_memory_leaks()
249
250
251 if __name__ == "__main__":
252 args = ["-s"] + sys.argv[1:]
253 sys.exit(pytest.main(args))