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