session: add startup option to poll in main
[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="server",
81                                         sw_if_index=self.loop0.sw_if_index)
82         self.vapi.app_namespace_add_del(namespace_id="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", "poll-main", "}"]
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         """QUIC internal transfer"""
145         self.server()
146         self.client("no-output", "mbytes", "2")
147
148
149 class QUICEchoIntSerialTestCase(QUICEchoIntTestCase):
150     """QUIC Echo Internal Serial Transfer Test Case"""
151     def test_quic_serial_int_transfer(self):
152         """QUIC serial internal transfer"""
153         self.server()
154         self.client("no-output", "mbytes", "2")
155         self.client("no-output", "mbytes", "2")
156         self.client("no-output", "mbytes", "2")
157         self.client("no-output", "mbytes", "2")
158         self.client("no-output", "mbytes", "2")
159
160
161 class QUICEchoIntMStreamTestCase(QUICEchoIntTestCase):
162     """QUIC Echo Internal MultiStream Test Case"""
163     def test_quic_int_multistream_transfer(self):
164         """QUIC internal multi-stream transfer"""
165         self.server()
166         self.client("nclients", "10", "mbytes", "1", "no-output")
167
168
169 class QUICEchoExtTestCase(QUICTestCase):
170     quic_setup = "default"
171     test_bytes = "test-bytes:assert"
172     pre_test_sleep = 1
173     post_test_sleep = 1
174     app = "vpp_echo"
175     evt_q_len = 16384
176     worker_config = "workers 1"
177     server_fifo_size = "1M"
178     client_fifo_size = "4M"
179     extra_vpp_punt_config = ["session", "{",
180                              "enable", "poll-main", "evt_qs_memfd_seg",
181                              "evt_qs_seg_size", "64M",
182                              "event-queue-length", f"{evt_q_len}",
183                              "preallocated-sessions", "1024",
184                              "v4-session-table-buckets", "20000",
185                              "v4-session-table-memory", "64M",
186                              "v4-halfopen-table-buckets", "20000",
187                              "v4-halfopen-table-memory", "64M",
188                              "local-endpoints-table-buckets", "250000",
189                              "local-endpoints-table-memory", "512M",
190                              "}"]
191
192     def setUp(self):
193         super(QUICEchoExtTestCase, self).setUp()
194         common_args = [
195             "uri", self.uri,
196             "json",
197             self.test_bytes,
198             "socket-name", self.api_sock,
199             "quic-setup", self.quic_setup,
200             "nthreads", "1",
201             "mq-size", f"{self.evt_q_len}"
202         ]
203         self.server_echo_test_args = common_args + \
204             ["server", "appns", "server", "fifo-size",
205              f"{self.server_fifo_size}"]
206         self.client_echo_test_args = common_args + \
207             ["client", "appns", "client", "fifo-size",
208              f"{self.client_fifo_size}"]
209         error = self.vapi.cli("quic set fifo-size 2M")
210         if error:
211             self.logger.critical(error)
212             self.assertNotIn("failed", error)
213
214     def server(self, *args):
215         _args = self.server_echo_test_args + list(args)
216         self.worker_server = QUICAppWorker(
217             self.build_dir,
218             self.app,
219             _args,
220             self.logger,
221             'server',
222             self)
223         self.worker_server.start()
224         self.sleep(self.pre_test_sleep)
225
226     def client(self, *args):
227         _args = self.client_echo_test_args + list(args)
228         self.worker_client = QUICAppWorker(
229             self.build_dir,
230             self.app,
231             _args,
232             self.logger,
233             'client',
234             self)
235         self.worker_client.start()
236         timeout = None if self.debug_all else self.timeout
237         self.worker_client.join(timeout)
238         if self.worker_client.is_alive():
239             error = f"Client failed to complete in {timeout} seconds!"
240             self.logger.critical(error)
241             return
242         self.worker_server.join(timeout)
243         if self.worker_server.is_alive():
244             error = f"Server failed to complete in {timeout} seconds!"
245             self.logger.critical(error)
246         self.sleep(self.post_test_sleep)
247
248     def validate_ext_test_results(self):
249         server_result = self.worker_server.result
250         client_result = self.worker_client.result
251         self.logger.info("Server worker result is `%s'" %
252                          server_result)
253         self.logger.info("Client worker result is `%s'" %
254                          client_result)
255         server_kill_error = False
256         if self.worker_server.result is None:
257             server_kill_error = self.worker_server.teardown(
258                 self.logger, self.timeout)
259         if self.worker_client.result is None:
260             self.worker_client.teardown(self.logger, self.timeout)
261         err_msg = "Wrong server worker return code (%s)" % server_result
262         self.assertEqual(server_result, 0, err_msg)
263         self.assertIsNotNone(
264             client_result,
265             "Timeout! Client worker did not finish in %ss" %
266             self.timeout)
267         err_msg = "Wrong client worker return code (%s)" % client_result
268         self.assertEqual(client_result, 0, err_msg)
269         self.assertFalse(server_kill_error, "Server kill errored")
270
271
272 class QUICEchoExtTransferTestCase(QUICEchoExtTestCase):
273     """QUIC Echo External Transfer Test Case"""
274     timeout = 60
275
276     def test_quic_ext_transfer(self):
277         """QUIC external transfer"""
278         self.server()
279         self.client()
280         self.validate_ext_test_results()
281
282
283 class QUICEchoExtTransferBigTestCase(QUICEchoExtTestCase):
284     """QUIC Echo External Transfer Big Test Case"""
285     server_fifo_size = '4M'
286     client_fifo_size = '4M'
287     test_bytes = ''
288     timeout = 60
289
290     @unittest.skipUnless(running_extended_tests, "part of extended tests")
291     def test_quic_ext_transfer_big(self):
292         """QUIC external transfer, big stream"""
293         self.server("TX=0", "RX=2G")
294         self.client("TX=2G", "RX=0")
295         self.validate_ext_test_results()
296
297
298 class QUICEchoExtQcloseRxTestCase(QUICEchoExtTestCase):
299     """QUIC Echo External Transfer Qclose Rx Test Case"""
300
301     @unittest.skipUnless(running_extended_tests, "part of extended tests")
302     @unittest.skip("testcase under development")
303     def test_quic_ext_qclose_rx(self):
304         """QUIC external transfer, rx close"""
305         self.server("TX=0", "RX=10M", "qclose=Y", "sclose=N")
306         self.client("TX=10M", "RX=0", "qclose=W", "sclose=W")
307         self.validate_ext_test_results()
308
309
310 class QUICEchoExtQcloseTxTestCase(QUICEchoExtTestCase):
311     """QUIC Echo External Transfer Qclose Tx Test Case"""
312
313     @unittest.skipUnless(running_extended_tests, "part of extended tests")
314     @unittest.skip("testcase under development")
315     def test_quic_ext_qclose_tx(self):
316         """QUIC external transfer, tx close"""
317         self.server("TX=0", "RX=10M", "qclose=W", "sclose=W",
318                     "rx-results-diff")
319         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=N")
320         self.validate_ext_test_results()
321
322
323 class QUICEchoExtEarlyQcloseRxTestCase(QUICEchoExtTestCase):
324     """QUIC Echo External Transfer Early Qclose Rx Test Case"""
325
326     @unittest.skipUnless(running_extended_tests, "part of extended tests")
327     @unittest.skip("testcase under development")
328     def test_quic_ext_early_qclose_rx(self):
329         """QUIC external transfer, early rx close"""
330         self.server("TX=0", "RX=10M", "qclose=Y", "sclose=N")
331         self.client("TX=20M", "RX=0", "qclose=W", "sclose=W",
332                     "tx-results-diff")
333         self.validate_ext_test_results()
334
335
336 class QUICEchoExtEarlyQcloseTxTestCase(QUICEchoExtTestCase):
337     """QUIC Echo External Transfer Early Qclose Tx Test Case"""
338
339     @unittest.skipUnless(running_extended_tests, "part of extended tests")
340     @unittest.skip("testcase under development")
341     def test_quic_ext_early_qclose_tx(self):
342         """QUIC external transfer, early tx close"""
343         self.server("TX=0", "RX=20M", "qclose=W", "sclose=W",
344                     "rx-results-diff")
345         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=N")
346         self.validate_ext_test_results()
347
348
349 class QUICEchoExtScloseRxTestCase(QUICEchoExtTestCase):
350     """QUIC Echo External Transfer Sclose Rx Test Case"""
351
352     @unittest.skipUnless(running_extended_tests, "part of extended tests")
353     @unittest.skip("testcase under development")
354     def test_quic_ext_sclose_rx(self):
355         """QUIC external transfer, rx stream close"""
356         self.server("TX=0", "RX=10M", "qclose=N", "sclose=Y")
357         self.client("TX=10M", "RX=0", "qclose=W", "sclose=W")
358         self.validate_ext_test_results()
359
360
361 class QUICEchoExtScloseTxTestCase(QUICEchoExtTestCase):
362     """QUIC Echo External Transfer Sclose Tx Test Case"""
363
364     @unittest.skipUnless(running_extended_tests, "part of extended tests")
365     @unittest.skip("testcase under development")
366     def test_quic_ext_sclose_tx(self):
367         """QUIC external transfer, tx stream close"""
368         self.server("TX=0", "RX=10M", "qclose=W", "sclose=W")
369         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
370         self.validate_ext_test_results()
371
372
373 class QUICEchoExtEarlyScloseRxTestCase(QUICEchoExtTestCase):
374     """QUIC Echo External Transfer Early Sclose Rx Test Case"""
375
376     @unittest.skipUnless(running_extended_tests, "part of extended tests")
377     @unittest.skip("testcase under development")
378     def test_quic_ext_early_sclose_rx(self):
379         """QUIC external transfer, early rx stream close"""
380         self.server("TX=0", "RX=10M", "qclose=N", "sclose=Y")
381         self.client("TX=20M", "RX=0", "qclose=W", "sclose=W",
382                     "tx-results-diff")
383         self.validate_ext_test_results()
384
385
386 class QUICEchoExtEarlyScloseTxTestCase(QUICEchoExtTestCase):
387     """QUIC Echo External Transfer Early Sclose Tx Test Case"""
388
389     @unittest.skipUnless(running_extended_tests, "part of extended tests")
390     @unittest.skip("testcase under development")
391     def test_quic_ext_early_sclose_tx(self):
392         """QUIC external transfer, early tx stream close"""
393         self.server("TX=0", "RX=20M", "qclose=W", "sclose=W",
394                     "rx-results-diff")
395         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
396         self.validate_ext_test_results()
397
398
399 class QUICEchoExtServerStreamTestCase(QUICEchoExtTestCase):
400     """QUIC Echo External Transfer Server Stream Test Case"""
401     quic_setup = "serverstream"
402     timeout = 60
403
404     def test_quic_ext_transfer_server_stream(self):
405         """QUIC external server transfer"""
406         self.server("TX=10M", "RX=0")
407         self.client("TX=0", "RX=10M")
408         self.validate_ext_test_results()
409
410
411 class QUICEchoExtServerStreamBigTestCase(QUICEchoExtTestCase):
412     """QUIC Echo External Transfer Server Stream Big Test Case"""
413     quic_setup = "serverstream"
414     server_fifo_size = '4M'
415     client_fifo_size = '4M'
416     test_bytes = ''
417     timeout = 60
418
419     @unittest.skipUnless(running_extended_tests, "part of extended tests")
420     def test_quic_ext_transfer_server_stream_big(self):
421         """QUIC external server transfer, big stream"""
422         self.server("TX=2G", "RX=0")
423         self.client("TX=0", "RX=2G")
424         self.validate_ext_test_results()
425
426
427 class QUICEchoExtServerStreamQcloseRxTestCase(QUICEchoExtTestCase):
428     """QUIC Echo External Transfer Server Stream Qclose Rx Test Case"""
429     quic_setup = "serverstream"
430
431     @unittest.skipUnless(running_extended_tests, "part of extended tests")
432     @unittest.skip("testcase under development")
433     def test_quic_ext_server_stream_qclose_rx(self):
434         """QUIC external server transfer, rx close"""
435         self.server("TX=10M", "RX=0", "qclose=W", "sclose=W")
436         self.client("TX=0", "RX=10M", "qclose=Y", "sclose=N")
437         self.validate_ext_test_results()
438
439
440 class QUICEchoExtServerStreamQcloseTxTestCase(QUICEchoExtTestCase):
441     """QUIC Echo External Transfer Server Stream Qclose Tx Test Case"""
442     quic_setup = "serverstream"
443
444     @unittest.skipUnless(running_extended_tests, "part of extended tests")
445     @unittest.skip("testcase under development")
446     def test_quic_ext_server_stream_qclose_tx(self):
447         """QUIC external server transfer, tx close"""
448         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=N")
449         self.client("TX=0", "RX=10M", "qclose=W", "sclose=W",
450                     "rx-results-diff")
451         self.validate_ext_test_results()
452
453
454 class QUICEchoExtServerStreamEarlyQcloseRxTestCase(QUICEchoExtTestCase):
455     """QUIC Echo External Transfer Server Stream Early Qclose Rx Test Case"""
456     quic_setup = "serverstream"
457
458     @unittest.skipUnless(running_extended_tests, "part of extended tests")
459     @unittest.skip("testcase under development")
460     def test_quic_ext_server_stream_early_qclose_rx(self):
461         """QUIC external server transfer, early rx close"""
462         self.server("TX=20M", "RX=0", "qclose=W", "sclose=W",
463                     "tx-results-diff")
464         self.client("TX=0", "RX=10M", "qclose=Y", "sclose=N")
465         self.validate_ext_test_results()
466
467
468 class QUICEchoExtServerStreamEarlyQcloseTxTestCase(QUICEchoExtTestCase):
469     """QUIC Echo External Transfer Server Stream Early Qclose Tx Test Case"""
470     quic_setup = "serverstream"
471
472     @unittest.skipUnless(running_extended_tests, "part of extended tests")
473     @unittest.skip("testcase under development")
474     def test_quic_ext_server_stream_early_qclose_tx(self):
475         """QUIC external server transfer, early tx close"""
476         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=N")
477         self.client("TX=0", "RX=20M", "qclose=W", "sclose=W",
478                     "rx-results-diff")
479         self.validate_ext_test_results()
480
481
482 class QUICEchoExtServerStreamScloseRxTestCase(QUICEchoExtTestCase):
483     """QUIC Echo External Transfer Server Stream Sclose Rx Test Case"""
484     quic_setup = "serverstream"
485
486     @unittest.skipUnless(running_extended_tests, "part of extended tests")
487     @unittest.skip("testcase under development")
488     def test_quic_ext_server_stream_sclose_rx(self):
489         """QUIC external server transfer, rx stream close"""
490         self.server("TX=10M", "RX=0", "qclose=W", "sclose=W")
491         self.client("TX=0", "RX=10M", "qclose=N", "sclose=Y")
492         self.validate_ext_test_results()
493
494
495 class QUICEchoExtServerStreamScloseTxTestCase(QUICEchoExtTestCase):
496     """QUIC Echo External Transfer Server Stream Sclose Tx Test Case"""
497     quic_setup = "serverstream"
498
499     @unittest.skipUnless(running_extended_tests, "part of extended tests")
500     @unittest.skip("testcase under development")
501     def test_quic_ext_server_stream_sclose_tx(self):
502         """QUIC external server transfer, tx stream close"""
503         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
504         self.client("TX=0", "RX=10M", "qclose=W", "sclose=W")
505         self.validate_ext_test_results()
506
507
508 class QUICEchoExtServerStreamEarlyScloseRxTestCase(QUICEchoExtTestCase):
509     """QUIC Echo External Transfer Server Stream Early Sclose Rx Test Case"""
510     quic_setup = "serverstream"
511
512     @unittest.skipUnless(running_extended_tests, "part of extended tests")
513     @unittest.skip("testcase under development")
514     def test_quic_ext_server_stream_early_sclose_rx(self):
515         """QUIC external server transfer, early rx stream close"""
516         self.server("TX=20M", "RX=0", "qclose=W", "sclose=W",
517                     "tx-results-diff")
518         self.client("TX=0", "RX=10M", "qclose=N", "sclose=Y")
519         self.validate_ext_test_results()
520
521
522 class QUICEchoExtServerStreamEarlyScloseTxTestCase(QUICEchoExtTestCase):
523     """QUIC Echo Ext Transfer Server Stream Early Sclose Tx Test Case"""
524     quic_setup = "serverstream"
525
526     @unittest.skipUnless(running_extended_tests, "part of extended tests")
527     @unittest.skip("testcase under development")
528     def test_quic_ext_server_stream_early_sclose_tx(self):
529         """QUIC external server transfer, early tx stream close"""
530         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
531         self.client("TX=0", "RX=20M", "qclose=W", "sclose=W",
532                     "rx-results-diff")
533         self.validate_ext_test_results()
534
535
536 class QUICEchoExtServerStreamWorkersTestCase(QUICEchoExtTestCase):
537     """QUIC Echo External Transfer Server Stream MultiWorker Test Case"""
538     quic_setup = "serverstream"
539
540     @unittest.skipUnless(running_extended_tests, "part of extended tests")
541     @unittest.skip("testcase under development")
542     def test_quic_ext_transfer_server_stream_multi_workers(self):
543         """QUIC external server transfer, multi-worker"""
544         self.server("nclients", "4", "quic-streams", "4", "TX=10M", "RX=0")
545         self.client("nclients", "4", "quic-streams", "4", "TX=0", "RX=10M")
546         self.validate_ext_test_results()
547
548
549 if __name__ == '__main__':
550     unittest.main(testRunner=VppTestRunner)