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