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