quic: update config values for large stream tests
[vpp.git] / src / plugins / quic / test / test_quic.py
1 #!/usr/bin/env python3
2 """ Vpp QUIC tests """
3
4 import unittest
5 import os
6 import subprocess
7 import signal
8 from framework import VppTestCase, VppTestRunner, running_extended_tests, \
9     Worker
10 from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
11
12
13 class QUICAppWorker(Worker):
14     """ QUIC Test Application Worker """
15     process = None
16
17     def __init__(self, build_dir, appname, executable_args, logger, role,
18                  testcase, env=None, *args, **kwargs):
19         if env is None:
20             env = {}
21         app = "%s/vpp/bin/%s" % (build_dir, appname)
22         self.args = [app] + executable_args
23         self.role = role
24         self.wait_for_gdb = 'wait-for-gdb'
25         self.testcase = testcase
26         super(QUICAppWorker, self).__init__(self.args, logger, env,
27                                             *args, **kwargs)
28
29     def run(self):
30         super(QUICAppWorker, self).run()
31
32     def teardown(self, logger, timeout):
33         if self.process is None:
34             return False
35         try:
36             logger.debug("Killing worker process (pid %d)" % self.process.pid)
37             os.killpg(os.getpgid(self.process.pid), signal.SIGKILL)
38             self.join(timeout)
39         except OSError as e:
40             logger.debug("Couldn't kill worker process")
41             return True
42         return False
43
44
45 class QUICTestCase(VppTestCase):
46     """ QUIC Test Case """
47
48     timeout = 20
49     pre_test_sleep = 0.3
50     post_test_sleep = 0.3
51
52     @classmethod
53     def setUpClass(cls):
54         cls.extra_vpp_plugin_config.append("plugin quic_plugin.so { enable }")
55         super(QUICTestCase, cls).setUpClass()
56
57     def setUp(self):
58         super(QUICTestCase, self).setUp()
59         var = "VPP_BUILD_DIR"
60         self.build_dir = os.getenv(var, None)
61         if self.build_dir is None:
62             raise Exception("Environment variable `%s' not set" % var)
63         self.vppDebug = 'vpp_debug' in self.build_dir
64
65         self.create_loopback_interfaces(2)
66         self.uri = "quic://%s/1234" % self.loop0.local_ip4
67         table_id = 1
68         for i in self.lo_interfaces:
69             i.admin_up()
70
71             if table_id != 0:
72                 tbl = VppIpTable(self, table_id)
73                 tbl.add_vpp_config()
74
75             i.set_table_ip4(table_id)
76             i.config_ip4()
77             table_id += 1
78
79         # Configure namespaces
80         self.vapi.app_namespace_add_del(namespace_id=b"server",
81                                         sw_if_index=self.loop0.sw_if_index)
82         self.vapi.app_namespace_add_del(namespace_id=b"client",
83                                         sw_if_index=self.loop1.sw_if_index)
84
85         # Add inter-table routes
86         self.ip_t01 = VppIpRoute(self, self.loop1.local_ip4, 32,
87                                  [VppRoutePath("0.0.0.0",
88                                                0xffffffff,
89                                                nh_table_id=2)], table_id=1)
90         self.ip_t10 = VppIpRoute(self, self.loop0.local_ip4, 32,
91                                  [VppRoutePath("0.0.0.0",
92                                                0xffffffff,
93                                                nh_table_id=1)], table_id=2)
94         self.ip_t01.add_vpp_config()
95         self.ip_t10.add_vpp_config()
96         self.logger.debug(self.vapi.cli("show ip fib"))
97
98     def tearDown(self):
99         # Delete inter-table routes
100         self.ip_t01.remove_vpp_config()
101         self.ip_t10.remove_vpp_config()
102
103         for i in self.lo_interfaces:
104             i.unconfig_ip4()
105             i.set_table_ip4(0)
106             i.admin_down()
107         super(QUICTestCase, self).tearDown()
108
109
110 class QUICEchoIntTestCase(QUICTestCase):
111     """QUIC Echo Internal Test Case"""
112     test_bytes = ' test-bytes'
113     extra_vpp_punt_config = ["session", "{", "enable", "}"]
114
115     def setUp(self):
116         super(QUICEchoIntTestCase, self).setUp()
117         self.client_args = 'uri {uri} fifo-size 64{testbytes} appns client' \
118             .format(uri=self.uri, testbytes=self.test_bytes)
119         self.server_args = "uri %s fifo-size 64 appns server" % self.uri
120
121     def tearDown(self):
122         super(QUICEchoIntTestCase, self).tearDown()
123
124     def server(self, *args):
125         error = self.vapi.cli(
126             "test echo server %s %s" %
127             (self.server_args, ' '.join(args)))
128         if error:
129             self.logger.critical(error)
130             self.assertNotIn("failed", error)
131
132     def client(self, *args):
133         error = self.vapi.cli(
134             "test echo client %s %s" %
135             (self.client_args, ' '.join(args)))
136         if error:
137             self.logger.critical(error)
138             self.assertNotIn("failed", error)
139
140
141 class QUICEchoIntTransferTestCase(QUICEchoIntTestCase):
142     """QUIC Echo Internal Transfer Test Case"""
143     def test_quic_int_transfer(self):
144         self.server()
145         self.client("no-output", "mbytes", "2")
146
147
148 class QUICEchoIntSerialTestCase(QUICEchoIntTestCase):
149     """QUIC Echo Internal Serial Transfer Test Case"""
150     def test_quic_serial_int_transfer(self):
151         self.server()
152         self.client("no-output", "mbytes", "2")
153         self.client("no-output", "mbytes", "2")
154         self.client("no-output", "mbytes", "2")
155         self.client("no-output", "mbytes", "2")
156         self.client("no-output", "mbytes", "2")
157
158
159 class QUICEchoIntMStreamTestCase(QUICEchoIntTestCase):
160     """QUIC Echo Internal MultiStream Test Case"""
161     def test_quic_int_multistream_transfer(self):
162         self.server()
163         self.client("nclients", "10", "mbytes", "1", "no-output")
164
165
166 class QUICEchoExtTestCase(QUICTestCase):
167     quic_setup = "default"
168     test_bytes = "test-bytes:assert"
169     pre_test_sleep = 1
170     post_test_sleep = 1
171     app = "vpp_echo"
172     evt_q_len = 16384
173     worker_config = "workers 1"
174     server_fifo_size = "1M"
175     client_fifo_size = "4M"
176     extra_vpp_punt_config = ["session", "{",
177                              "enable", "evt_qs_memfd_seg",
178                              "evt_qs_seg_size", "64M",
179                              "event-queue-length", f"{evt_q_len}",
180                              "preallocated-sessions", "1024",
181                              "v4-session-table-buckets", "20000",
182                              "v4-session-table-memory", "64M",
183                              "v4-halfopen-table-buckets", "20000",
184                              "v4-halfopen-table-memory", "64M",
185                              "local-endpoints-table-buckets", "250000",
186                              "local-endpoints-table-memory", "512M",
187                              "}"]
188
189     def setUp(self):
190         super(QUICEchoExtTestCase, self).setUp()
191         common_args = [
192             "uri", self.uri,
193             "json",
194             self.test_bytes,
195             "socket-name", self.api_sock,
196             "quic-setup", self.quic_setup,
197             "nthreads", "1",
198             "mq-size", f"{self.evt_q_len}"
199         ]
200         self.server_echo_test_args = common_args + \
201             ["server", "appns", "server", "fifo-size",
202              f"{self.server_fifo_size}"]
203         self.client_echo_test_args = common_args + \
204             ["client", "appns", "client", "fifo-size",
205              f"{self.client_fifo_size}"]
206         error = self.vapi.cli("quic set fifo-size 2M")
207         if error:
208             self.logger.critical(error)
209             self.assertNotIn("failed", error)
210
211     def server(self, *args):
212         _args = self.server_echo_test_args + list(args)
213         self.worker_server = QUICAppWorker(
214             self.build_dir,
215             self.app,
216             _args,
217             self.logger,
218             'server',
219             self)
220         self.worker_server.start()
221         self.sleep(self.pre_test_sleep)
222
223     def client(self, *args):
224         _args = self.client_echo_test_args + list(args)
225         self.worker_client = QUICAppWorker(
226             self.build_dir,
227             self.app,
228             _args,
229             self.logger,
230             'client',
231             self)
232         self.worker_client.start()
233         timeout = None if self.debug_all else self.timeout
234         self.worker_client.join(timeout)
235         if self.worker_client.is_alive():
236             error = f"Client failed to complete in {timeout} seconds!"
237             self.logger.critical(error)
238             return
239         self.worker_server.join(timeout)
240         if self.worker_server.is_alive():
241             error = f"Server failed to complete in {timeout} seconds!"
242             self.logger.critical(error)
243         self.sleep(self.post_test_sleep)
244
245     def validate_ext_test_results(self):
246         server_result = self.worker_server.result
247         client_result = self.worker_client.result
248         self.logger.info("Server worker result is `%s'" %
249                          server_result)
250         self.logger.info("Client worker result is `%s'" %
251                          client_result)
252         server_kill_error = False
253         if self.worker_server.result is None:
254             server_kill_error = self.worker_server.teardown(
255                 self.logger, self.timeout)
256         if self.worker_client.result is None:
257             self.worker_client.teardown(self.logger, self.timeout)
258         err_msg = "Wrong server worker return code (%s)" % server_result
259         self.assertEqual(server_result, 0, err_msg)
260         self.assertIsNotNone(
261             client_result,
262             "Timeout! Client worker did not finish in %ss" %
263             self.timeout)
264         err_msg = "Wrong client worker return code (%s)" % client_result
265         self.assertEqual(client_result, 0, err_msg)
266         self.assertFalse(server_kill_error, "Server kill errored")
267
268
269 class QUICEchoExtTransferTestCase(QUICEchoExtTestCase):
270     """QUIC Echo External Transfer Test Case"""
271     timeout = 60
272
273     def test_quic_ext_transfer(self):
274         self.server()
275         self.client()
276         self.validate_ext_test_results()
277
278
279 class QUICEchoExtTransferBigTestCase(QUICEchoExtTestCase):
280     """QUIC Echo External Transfer Big Test Case"""
281     server_fifo_size = '4M'
282     client_fifo_size = '4M'
283     test_bytes = ''
284     timeout = 60
285
286     @unittest.skipUnless(running_extended_tests, "part of extended tests")
287     def test_quic_ext_transfer_big(self):
288         self.server("TX=0", "RX=5G")
289         self.client("TX=5G", "RX=0")
290         self.validate_ext_test_results()
291
292
293 class QUICEchoExtQcloseRxTestCase(QUICEchoExtTestCase):
294     """QUIC Echo External Transfer Qclose Rx Test Case"""
295
296     @unittest.skipUnless(running_extended_tests, "part of extended tests")
297     def test_quic_ext_qclose_rx(self):
298         self.server("TX=0", "RX=10M", "qclose=Y", "sclose=N")
299         self.client("TX=10M", "RX=0", "qclose=W", "sclose=W")
300         self.validate_ext_test_results()
301
302
303 class QUICEchoExtQcloseTxTestCase(QUICEchoExtTestCase):
304     """QUIC Echo External Transfer Qclose Tx Test Case"""
305
306     @unittest.skipUnless(running_extended_tests, "part of extended tests")
307     def test_quic_ext_qclose_tx(self):
308         self.server("TX=0", "RX=10M", "qclose=W", "sclose=W",
309                     "rx-results-diff")
310         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=N")
311         self.validate_ext_test_results()
312
313
314 class QUICEchoExtEarlyQcloseRxTestCase(QUICEchoExtTestCase):
315     """QUIC Echo External Transfer Early Qclose Rx Test Case"""
316
317     @unittest.skipUnless(running_extended_tests, "part of extended tests")
318     def test_quic_ext_early_qclose_rx(self):
319         self.server("TX=0", "RX=10M", "qclose=Y", "sclose=N")
320         self.client("TX=20M", "RX=0", "qclose=W", "sclose=W",
321                     "tx-results-diff")
322         self.validate_ext_test_results()
323
324
325 class QUICEchoExtEarlyQcloseTxTestCase(QUICEchoExtTestCase):
326     """QUIC Echo External Transfer Early Qclose Tx Test Case"""
327
328     @unittest.skipUnless(running_extended_tests, "part of extended tests")
329     def test_quic_ext_early_qclose_tx(self):
330         self.server("TX=0", "RX=20M", "qclose=W", "sclose=W",
331                     "rx-results-diff")
332         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=N")
333         self.validate_ext_test_results()
334
335
336 class QUICEchoExtScloseRxTestCase(QUICEchoExtTestCase):
337     """QUIC Echo External Transfer Sclose Rx Test Case"""
338
339     @unittest.skipUnless(running_extended_tests, "part of extended tests")
340     def test_quic_ext_sclose_rx(self):
341         self.server("TX=0", "RX=10M", "qclose=N", "sclose=Y")
342         self.client("TX=10M", "RX=0", "qclose=W", "sclose=W")
343         self.validate_ext_test_results()
344
345
346 class QUICEchoExtScloseTxTestCase(QUICEchoExtTestCase):
347     """QUIC Echo External Transfer Sclose Tx Test Case"""
348
349     @unittest.skipUnless(running_extended_tests, "part of extended tests")
350     def test_quic_ext_sclose_tx(self):
351         self.server("TX=0", "RX=10M", "qclose=W", "sclose=W")
352         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
353         self.validate_ext_test_results()
354
355
356 class QUICEchoExtEarlyScloseRxTestCase(QUICEchoExtTestCase):
357     """QUIC Echo External Transfer Early Sclose Rx Test Case"""
358
359     @unittest.skipUnless(running_extended_tests, "part of extended tests")
360     def test_quic_ext_early_sclose_rx(self):
361         self.server("TX=0", "RX=10M", "qclose=N", "sclose=Y")
362         self.client("TX=20M", "RX=0", "qclose=W", "sclose=W",
363                     "tx-results-diff")
364         self.validate_ext_test_results()
365
366
367 class QUICEchoExtEarlyScloseTxTestCase(QUICEchoExtTestCase):
368     """QUIC Echo External Transfer Early Sclose Tx Test Case"""
369
370     @unittest.skipUnless(running_extended_tests, "part of extended tests")
371     def test_quic_ext_early_sclose_tx(self):
372         self.server("TX=0", "RX=20M", "qclose=W", "sclose=W",
373                     "rx-results-diff")
374         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
375         self.validate_ext_test_results()
376
377
378 class QUICEchoExtServerStreamTestCase(QUICEchoExtTestCase):
379     """QUIC Echo External Transfer Server Stream Test Case"""
380     quic_setup = "serverstream"
381     timeout = 60
382
383     def test_quic_ext_transfer_server_stream(self):
384         self.server("TX=10M", "RX=0")
385         self.client("TX=0", "RX=10M")
386         self.validate_ext_test_results()
387
388
389 class QUICEchoExtServerStreamBigTestCase(QUICEchoExtTestCase):
390     """QUIC Echo External Transfer Server Stream Big Test Case"""
391     quic_setup = "serverstream"
392     server_fifo_size = '4M'
393     client_fifo_size = '4M'
394     test_bytes = ''
395     timeout = 60
396
397     @unittest.skipUnless(running_extended_tests, "part of extended tests")
398     def test_quic_ext_transfer_server_stream_big(self):
399         self.server("TX=5G", "RX=0")
400         self.client("TX=0", "RX=5G")
401         self.validate_ext_test_results()
402
403
404 class QUICEchoExtServerStreamQcloseRxTestCase(QUICEchoExtTestCase):
405     """QUIC Echo External Transfer Server Stream Qclose Rx Test Case"""
406     quic_setup = "serverstream"
407
408     @unittest.skipUnless(running_extended_tests, "part of extended tests")
409     def test_quic_ext_server_stream_qclose_rx(self):
410         self.server("TX=10M", "RX=0", "qclose=W", "sclose=W")
411         self.client("TX=0", "RX=10M", "qclose=Y", "sclose=N")
412         self.validate_ext_test_results()
413
414
415 class QUICEchoExtServerStreamQcloseTxTestCase(QUICEchoExtTestCase):
416     """QUIC Echo External Transfer Server Stream Qclose Tx Test Case"""
417     quic_setup = "serverstream"
418
419     @unittest.skipUnless(running_extended_tests, "part of extended tests")
420     def test_quic_ext_server_stream_qclose_tx(self):
421         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=N")
422         self.client("TX=0", "RX=10M", "qclose=W", "sclose=W",
423                     "rx-results-diff")
424         self.validate_ext_test_results()
425
426
427 class QUICEchoExtServerStreamEarlyQcloseRxTestCase(QUICEchoExtTestCase):
428     """QUIC Echo External Transfer Server Stream Early Qclose Rx Test Case"""
429     quic_setup = "serverstream"
430
431     @unittest.skipUnless(running_extended_tests, "part of extended tests")
432     def test_quic_ext_server_stream_early_qclose_rx(self):
433         self.server("TX=20M", "RX=0", "qclose=W", "sclose=W",
434                     "tx-results-diff")
435         self.client("TX=0", "RX=10M", "qclose=Y", "sclose=N")
436         self.validate_ext_test_results()
437
438
439 class QUICEchoExtServerStreamEarlyQcloseTxTestCase(QUICEchoExtTestCase):
440     """QUIC Echo External Transfer Server Stream Early Qclose Tx Test Case"""
441     quic_setup = "serverstream"
442
443     @unittest.skipUnless(running_extended_tests, "part of extended tests")
444     def test_quic_ext_server_stream_early_qclose_tx(self):
445         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=N")
446         self.client("TX=0", "RX=20M", "qclose=W", "sclose=W",
447                     "rx-results-diff")
448         self.validate_ext_test_results()
449
450
451 class QUICEchoExtServerStreamScloseRxTestCase(QUICEchoExtTestCase):
452     """QUIC Echo External Transfer Server Stream Sclose Rx Test Case"""
453     quic_setup = "serverstream"
454
455     @unittest.skipUnless(running_extended_tests, "part of extended tests")
456     def test_quic_ext_server_stream_sclose_rx(self):
457         self.server("TX=10M", "RX=0", "qclose=W", "sclose=W")
458         self.client("TX=0", "RX=10M", "qclose=N", "sclose=Y")
459         self.validate_ext_test_results()
460
461
462 class QUICEchoExtServerStreamScloseTxTestCase(QUICEchoExtTestCase):
463     """QUIC Echo External Transfer Server Stream Sclose Tx Test Case"""
464     quic_setup = "serverstream"
465
466     @unittest.skipUnless(running_extended_tests, "part of extended tests")
467     def test_quic_ext_server_stream_sclose_tx(self):
468         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
469         self.client("TX=0", "RX=10M", "qclose=W", "sclose=W")
470         self.validate_ext_test_results()
471
472
473 class QUICEchoExtServerStreamEarlyScloseRxTestCase(QUICEchoExtTestCase):
474     """QUIC Echo External Transfer Server Stream Early Sclose Rx Test Case"""
475     quic_setup = "serverstream"
476
477     @unittest.skipUnless(running_extended_tests, "part of extended tests")
478     def test_quic_ext_server_stream_early_sclose_rx(self):
479         self.server("TX=20M", "RX=0", "qclose=W", "sclose=W",
480                     "tx-results-diff")
481         self.client("TX=0", "RX=10M", "qclose=N", "sclose=Y")
482         self.validate_ext_test_results()
483
484
485 class QUICEchoExtServerStreamEarlyScloseTxTestCase(QUICEchoExtTestCase):
486     """QUIC Echo Ext Transfer Server Stream Early Sclose Tx Test Case"""
487     quic_setup = "serverstream"
488
489     @unittest.skipUnless(running_extended_tests, "part of extended tests")
490     def test_quic_ext_server_stream_early_sclose_tx(self):
491         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
492         self.client("TX=0", "RX=20M", "qclose=W", "sclose=W",
493                     "rx-results-diff")
494         self.validate_ext_test_results()
495
496
497 class QUICEchoExtServerStreamWorkersTestCase(QUICEchoExtTestCase):
498     """QUIC Echo External Transfer Server Stream MultiWorker Test Case"""
499     quic_setup = "serverstream"
500
501     @unittest.skipUnless(running_extended_tests, "part of extended tests")
502     def test_quic_ext_transfer_server_stream_multi_workers(self):
503         self.server("nclients", "4", "quic-streams", "4", "TX=10M", "RX=0")
504         self.client("nclients", "4", "quic-streams", "4", "TX=0", "RX=10M")
505         self.validate_ext_test_results()
506
507
508 if __name__ == '__main__':
509     unittest.main(testRunner=VppTestRunner)