session: API cleanup
[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", "}"]
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=2G")
289         self.client("TX=2G", "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     @unittest.skip("testcase under development")
298     def test_quic_ext_qclose_rx(self):
299         self.server("TX=0", "RX=10M", "qclose=Y", "sclose=N")
300         self.client("TX=10M", "RX=0", "qclose=W", "sclose=W")
301         self.validate_ext_test_results()
302
303
304 class QUICEchoExtQcloseTxTestCase(QUICEchoExtTestCase):
305     """QUIC Echo External Transfer Qclose Tx Test Case"""
306
307     @unittest.skipUnless(running_extended_tests, "part of extended tests")
308     @unittest.skip("testcase under development")
309     def test_quic_ext_qclose_tx(self):
310         self.server("TX=0", "RX=10M", "qclose=W", "sclose=W",
311                     "rx-results-diff")
312         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=N")
313         self.validate_ext_test_results()
314
315
316 class QUICEchoExtEarlyQcloseRxTestCase(QUICEchoExtTestCase):
317     """QUIC Echo External Transfer Early Qclose Rx Test Case"""
318
319     @unittest.skipUnless(running_extended_tests, "part of extended tests")
320     @unittest.skip("testcase under development")
321     def test_quic_ext_early_qclose_rx(self):
322         self.server("TX=0", "RX=10M", "qclose=Y", "sclose=N")
323         self.client("TX=20M", "RX=0", "qclose=W", "sclose=W",
324                     "tx-results-diff")
325         self.validate_ext_test_results()
326
327
328 class QUICEchoExtEarlyQcloseTxTestCase(QUICEchoExtTestCase):
329     """QUIC Echo External Transfer Early Qclose Tx Test Case"""
330
331     @unittest.skipUnless(running_extended_tests, "part of extended tests")
332     @unittest.skip("testcase under development")
333     def test_quic_ext_early_qclose_tx(self):
334         self.server("TX=0", "RX=20M", "qclose=W", "sclose=W",
335                     "rx-results-diff")
336         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=N")
337         self.validate_ext_test_results()
338
339
340 class QUICEchoExtScloseRxTestCase(QUICEchoExtTestCase):
341     """QUIC Echo External Transfer Sclose Rx Test Case"""
342
343     @unittest.skipUnless(running_extended_tests, "part of extended tests")
344     @unittest.skip("testcase under development")
345     def test_quic_ext_sclose_rx(self):
346         self.server("TX=0", "RX=10M", "qclose=N", "sclose=Y")
347         self.client("TX=10M", "RX=0", "qclose=W", "sclose=W")
348         self.validate_ext_test_results()
349
350
351 class QUICEchoExtScloseTxTestCase(QUICEchoExtTestCase):
352     """QUIC Echo External Transfer Sclose Tx Test Case"""
353
354     @unittest.skipUnless(running_extended_tests, "part of extended tests")
355     @unittest.skip("testcase under development")
356     def test_quic_ext_sclose_tx(self):
357         self.server("TX=0", "RX=10M", "qclose=W", "sclose=W")
358         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
359         self.validate_ext_test_results()
360
361
362 class QUICEchoExtEarlyScloseRxTestCase(QUICEchoExtTestCase):
363     """QUIC Echo External Transfer Early Sclose Rx Test Case"""
364
365     @unittest.skipUnless(running_extended_tests, "part of extended tests")
366     @unittest.skip("testcase under development")
367     def test_quic_ext_early_sclose_rx(self):
368         self.server("TX=0", "RX=10M", "qclose=N", "sclose=Y")
369         self.client("TX=20M", "RX=0", "qclose=W", "sclose=W",
370                     "tx-results-diff")
371         self.validate_ext_test_results()
372
373
374 class QUICEchoExtEarlyScloseTxTestCase(QUICEchoExtTestCase):
375     """QUIC Echo External Transfer Early Sclose Tx Test Case"""
376
377     @unittest.skipUnless(running_extended_tests, "part of extended tests")
378     @unittest.skip("testcase under development")
379     def test_quic_ext_early_sclose_tx(self):
380         self.server("TX=0", "RX=20M", "qclose=W", "sclose=W",
381                     "rx-results-diff")
382         self.client("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
383         self.validate_ext_test_results()
384
385
386 class QUICEchoExtServerStreamTestCase(QUICEchoExtTestCase):
387     """QUIC Echo External Transfer Server Stream Test Case"""
388     quic_setup = "serverstream"
389     timeout = 60
390
391     def test_quic_ext_transfer_server_stream(self):
392         self.server("TX=10M", "RX=0")
393         self.client("TX=0", "RX=10M")
394         self.validate_ext_test_results()
395
396
397 class QUICEchoExtServerStreamBigTestCase(QUICEchoExtTestCase):
398     """QUIC Echo External Transfer Server Stream Big Test Case"""
399     quic_setup = "serverstream"
400     server_fifo_size = '4M'
401     client_fifo_size = '4M'
402     test_bytes = ''
403     timeout = 60
404
405     @unittest.skipUnless(running_extended_tests, "part of extended tests")
406     def test_quic_ext_transfer_server_stream_big(self):
407         self.server("TX=2G", "RX=0")
408         self.client("TX=0", "RX=2G")
409         self.validate_ext_test_results()
410
411
412 class QUICEchoExtServerStreamQcloseRxTestCase(QUICEchoExtTestCase):
413     """QUIC Echo External Transfer Server Stream Qclose Rx Test Case"""
414     quic_setup = "serverstream"
415
416     @unittest.skipUnless(running_extended_tests, "part of extended tests")
417     @unittest.skip("testcase under development")
418     def test_quic_ext_server_stream_qclose_rx(self):
419         self.server("TX=10M", "RX=0", "qclose=W", "sclose=W")
420         self.client("TX=0", "RX=10M", "qclose=Y", "sclose=N")
421         self.validate_ext_test_results()
422
423
424 class QUICEchoExtServerStreamQcloseTxTestCase(QUICEchoExtTestCase):
425     """QUIC Echo External Transfer Server Stream Qclose Tx Test Case"""
426     quic_setup = "serverstream"
427
428     @unittest.skipUnless(running_extended_tests, "part of extended tests")
429     @unittest.skip("testcase under development")
430     def test_quic_ext_server_stream_qclose_tx(self):
431         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=N")
432         self.client("TX=0", "RX=10M", "qclose=W", "sclose=W",
433                     "rx-results-diff")
434         self.validate_ext_test_results()
435
436
437 class QUICEchoExtServerStreamEarlyQcloseRxTestCase(QUICEchoExtTestCase):
438     """QUIC Echo External Transfer Server Stream Early Qclose Rx Test Case"""
439     quic_setup = "serverstream"
440
441     @unittest.skipUnless(running_extended_tests, "part of extended tests")
442     @unittest.skip("testcase under development")
443     def test_quic_ext_server_stream_early_qclose_rx(self):
444         self.server("TX=20M", "RX=0", "qclose=W", "sclose=W",
445                     "tx-results-diff")
446         self.client("TX=0", "RX=10M", "qclose=Y", "sclose=N")
447         self.validate_ext_test_results()
448
449
450 class QUICEchoExtServerStreamEarlyQcloseTxTestCase(QUICEchoExtTestCase):
451     """QUIC Echo External Transfer Server Stream Early Qclose Tx Test Case"""
452     quic_setup = "serverstream"
453
454     @unittest.skipUnless(running_extended_tests, "part of extended tests")
455     @unittest.skip("testcase under development")
456     def test_quic_ext_server_stream_early_qclose_tx(self):
457         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=N")
458         self.client("TX=0", "RX=20M", "qclose=W", "sclose=W",
459                     "rx-results-diff")
460         self.validate_ext_test_results()
461
462
463 class QUICEchoExtServerStreamScloseRxTestCase(QUICEchoExtTestCase):
464     """QUIC Echo External Transfer Server Stream Sclose Rx Test Case"""
465     quic_setup = "serverstream"
466
467     @unittest.skipUnless(running_extended_tests, "part of extended tests")
468     @unittest.skip("testcase under development")
469     def test_quic_ext_server_stream_sclose_rx(self):
470         self.server("TX=10M", "RX=0", "qclose=W", "sclose=W")
471         self.client("TX=0", "RX=10M", "qclose=N", "sclose=Y")
472         self.validate_ext_test_results()
473
474
475 class QUICEchoExtServerStreamScloseTxTestCase(QUICEchoExtTestCase):
476     """QUIC Echo External Transfer Server Stream Sclose Tx Test Case"""
477     quic_setup = "serverstream"
478
479     @unittest.skipUnless(running_extended_tests, "part of extended tests")
480     @unittest.skip("testcase under development")
481     def test_quic_ext_server_stream_sclose_tx(self):
482         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
483         self.client("TX=0", "RX=10M", "qclose=W", "sclose=W")
484         self.validate_ext_test_results()
485
486
487 class QUICEchoExtServerStreamEarlyScloseRxTestCase(QUICEchoExtTestCase):
488     """QUIC Echo External Transfer Server Stream Early Sclose Rx Test Case"""
489     quic_setup = "serverstream"
490
491     @unittest.skipUnless(running_extended_tests, "part of extended tests")
492     @unittest.skip("testcase under development")
493     def test_quic_ext_server_stream_early_sclose_rx(self):
494         self.server("TX=20M", "RX=0", "qclose=W", "sclose=W",
495                     "tx-results-diff")
496         self.client("TX=0", "RX=10M", "qclose=N", "sclose=Y")
497         self.validate_ext_test_results()
498
499
500 class QUICEchoExtServerStreamEarlyScloseTxTestCase(QUICEchoExtTestCase):
501     """QUIC Echo Ext Transfer Server Stream Early Sclose Tx Test Case"""
502     quic_setup = "serverstream"
503
504     @unittest.skipUnless(running_extended_tests, "part of extended tests")
505     @unittest.skip("testcase under development")
506     def test_quic_ext_server_stream_early_sclose_tx(self):
507         self.server("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
508         self.client("TX=0", "RX=20M", "qclose=W", "sclose=W",
509                     "rx-results-diff")
510         self.validate_ext_test_results()
511
512
513 class QUICEchoExtServerStreamWorkersTestCase(QUICEchoExtTestCase):
514     """QUIC Echo External Transfer Server Stream MultiWorker Test Case"""
515     quic_setup = "serverstream"
516
517     @unittest.skipUnless(running_extended_tests, "part of extended tests")
518     @unittest.skip("testcase under development")
519     def test_quic_ext_transfer_server_stream_multi_workers(self):
520         self.server("nclients", "4", "quic-streams", "4", "TX=10M", "RX=0")
521         self.client("nclients", "4", "quic-streams", "4", "TX=0", "RX=10M")
522         self.validate_ext_test_results()
523
524
525 if __name__ == '__main__':
526     unittest.main(testRunner=VppTestRunner)