18c2ecf20Sopenharmony_citdc - Linux Traffic Control (tc) unit testing suite 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ciAuthor: Lucas Bates - lucasb@mojatatu.com 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_citdc is a Python script to load tc unit tests from a separate JSON file and 68c2ecf20Sopenharmony_ciexecute them inside a network namespace dedicated to the task. 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ciREQUIREMENTS 108c2ecf20Sopenharmony_ci------------ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci* Minimum Python version of 3.4. Earlier 3.X versions may work but are not 138c2ecf20Sopenharmony_ci guaranteed. 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci* The kernel must have network namespace support if using nsPlugin 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci* The kernel must have veth support available, as a veth pair is created 188c2ecf20Sopenharmony_ci prior to running the tests when using nsPlugin. 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci* The kernel must have the appropriate infrastructure enabled to run all tdc 218c2ecf20Sopenharmony_ci unit tests. See the config file in this directory for minimum required 228c2ecf20Sopenharmony_ci features. As new tests will be added, config options list will be updated. 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci* All tc-related features being tested must be built in or available as 258c2ecf20Sopenharmony_ci modules. To check what is required in current setup run: 268c2ecf20Sopenharmony_ci ./tdc.py -c 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci Note: 298c2ecf20Sopenharmony_ci In the current release, tdc run will abort due to a failure in setup or 308c2ecf20Sopenharmony_ci teardown commands - which includes not being able to run a test simply 318c2ecf20Sopenharmony_ci because the kernel did not support a specific feature. (This will be 328c2ecf20Sopenharmony_ci handled in a future version - the current workaround is to run the tests 338c2ecf20Sopenharmony_ci on specific test categories that your kernel supports) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ciBEFORE YOU RUN 378c2ecf20Sopenharmony_ci-------------- 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ciThe path to the tc executable that will be most commonly tested can be defined 408c2ecf20Sopenharmony_ciin the tdc_config.py file. Find the 'TC' entry in the NAMES dictionary and 418c2ecf20Sopenharmony_cidefine the path. 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciIf you need to test a different tc executable on the fly, you can do so by 448c2ecf20Sopenharmony_ciusing the -p option when running tdc: 458c2ecf20Sopenharmony_ci ./tdc.py -p /path/to/tc 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciRUNNING TDC 498c2ecf20Sopenharmony_ci----------- 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ciTo use tdc, root privileges are required. This is because the 528c2ecf20Sopenharmony_cicommands being tested must be run as root. The code that enforces 538c2ecf20Sopenharmony_ciexecution by root uid has been moved into a plugin (see PLUGIN 548c2ecf20Sopenharmony_ciARCHITECTURE, below). 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciTests that use a network device should have nsPlugin.py listed as a 578c2ecf20Sopenharmony_cirequirement for that test. nsPlugin executes all commands within a 588c2ecf20Sopenharmony_cinetwork namespace and creates a veth pair which may be used in those test 598c2ecf20Sopenharmony_cicases. To disable execution within the namespace, pass the -N option 608c2ecf20Sopenharmony_cito tdc when starting a test run; the veth pair will still be created 618c2ecf20Sopenharmony_ciby the plugin. 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ciRunning tdc without any arguments will run all tests. Refer to the section 648c2ecf20Sopenharmony_cion command line arguments for more information, or run: 658c2ecf20Sopenharmony_ci ./tdc.py -h 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_citdc will list the test names as they are being run, and print a summary in 688c2ecf20Sopenharmony_ciTAP (Test Anything Protocol) format when they are done. If tests fail, 698c2ecf20Sopenharmony_cioutput captured from the failing test will be printed immediately following 708c2ecf20Sopenharmony_cithe failed test in the TAP output. 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciOVERVIEW OF TDC EXECUTION 748c2ecf20Sopenharmony_ci------------------------- 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciOne run of tests is considered a "test suite" (this will be refined in the 778c2ecf20Sopenharmony_cifuture). A test suite has one or more test cases in it. 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ciA test case has four stages: 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci - setup 828c2ecf20Sopenharmony_ci - execute 838c2ecf20Sopenharmony_ci - verify 848c2ecf20Sopenharmony_ci - teardown 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ciThe setup and teardown stages can run zero or more commands. The setup 878c2ecf20Sopenharmony_cistage does some setup if the test needs it. The teardown stage undoes 888c2ecf20Sopenharmony_cithe setup and returns the system to a "neutral" state so any other test 898c2ecf20Sopenharmony_cican be run next. These two stages require any commands run to return 908c2ecf20Sopenharmony_cisuccess, but do not otherwise verify the results. 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciThe execute and verify stages each run one command. The execute stage 938c2ecf20Sopenharmony_citests the return code against one or more acceptable values. The 948c2ecf20Sopenharmony_civerify stage checks the return code for success, and also compares 958c2ecf20Sopenharmony_cithe stdout with a regular expression. 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciEach of the commands in any stage will run in a shell instance. 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ciUSER-DEFINED CONSTANTS 1018c2ecf20Sopenharmony_ci---------------------- 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciThe tdc_config.py file contains multiple values that can be altered to suit 1048c2ecf20Sopenharmony_ciyour needs. Any value in the NAMES dictionary can be altered without affecting 1058c2ecf20Sopenharmony_cithe tests to be run. These values are used in the tc commands that will be 1068c2ecf20Sopenharmony_ciexecuted as part of the test. More will be added as test cases require. 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ciExample: 1098c2ecf20Sopenharmony_ci $TC qdisc add dev $DEV1 ingress 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ciThe NAMES values are used to substitute into the commands in the test cases. 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ciCOMMAND LINE ARGUMENTS 1158c2ecf20Sopenharmony_ci---------------------- 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ciRun tdc.py -h to see the full list of available arguments. 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ciusage: tdc.py [-h] [-p PATH] [-D DIR [DIR ...]] [-f FILE [FILE ...]] 1208c2ecf20Sopenharmony_ci [-c [CATG [CATG ...]]] [-e ID [ID ...]] [-l] [-s] [-i] [-v] [-N] 1218c2ecf20Sopenharmony_ci [-d DEVICE] [-P] [-n] [-V] 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ciLinux TC unit tests 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cioptional arguments: 1268c2ecf20Sopenharmony_ci -h, --help show this help message and exit 1278c2ecf20Sopenharmony_ci -p PATH, --path PATH The full path to the tc executable to use 1288c2ecf20Sopenharmony_ci -v, --verbose Show the commands that are being run 1298c2ecf20Sopenharmony_ci -N, --notap Suppress tap results for command under test 1308c2ecf20Sopenharmony_ci -d DEVICE, --device DEVICE 1318c2ecf20Sopenharmony_ci Execute test cases that use a physical device, where 1328c2ecf20Sopenharmony_ci DEVICE is its name. (If not defined, tests that require 1338c2ecf20Sopenharmony_ci a physical device will be skipped) 1348c2ecf20Sopenharmony_ci -P, --pause Pause execution just before post-suite stage 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ciselection: 1378c2ecf20Sopenharmony_ci select which test cases: files plus directories; filtered by categories 1388c2ecf20Sopenharmony_ci plus testids 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci -D DIR [DIR ...], --directory DIR [DIR ...] 1418c2ecf20Sopenharmony_ci Collect tests from the specified directory(ies) 1428c2ecf20Sopenharmony_ci (default [tc-tests]) 1438c2ecf20Sopenharmony_ci -f FILE [FILE ...], --file FILE [FILE ...] 1448c2ecf20Sopenharmony_ci Run tests from the specified file(s) 1458c2ecf20Sopenharmony_ci -c [CATG [CATG ...]], --category [CATG [CATG ...]] 1468c2ecf20Sopenharmony_ci Run tests only from the specified category/ies, or if 1478c2ecf20Sopenharmony_ci no category/ies is/are specified, list known 1488c2ecf20Sopenharmony_ci categories. 1498c2ecf20Sopenharmony_ci -e ID [ID ...], --execute ID [ID ...] 1508c2ecf20Sopenharmony_ci Execute the specified test cases with specified IDs 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ciaction: 1538c2ecf20Sopenharmony_ci select action to perform on selected test cases 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci -l, --list List all test cases, or those only within the 1568c2ecf20Sopenharmony_ci specified category 1578c2ecf20Sopenharmony_ci -s, --show Display the selected test cases 1588c2ecf20Sopenharmony_ci -i, --id Generate ID numbers for new test cases 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cinetns: 1618c2ecf20Sopenharmony_ci options for nsPlugin (run commands in net namespace) 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci -N, --no-namespace 1648c2ecf20Sopenharmony_ci Do not run commands in a network namespace. 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_civalgrind: 1678c2ecf20Sopenharmony_ci options for valgrindPlugin (run command under test under Valgrind) 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci -V, --valgrind Run commands under valgrind 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ciPLUGIN ARCHITECTURE 1738c2ecf20Sopenharmony_ci------------------- 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ciThere is now a plugin architecture, and some of the functionality that 1768c2ecf20Sopenharmony_ciwas in the tdc.py script has been moved into the plugins. 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ciThe plugins are in the directory plugin-lib. The are executed from 1798c2ecf20Sopenharmony_cidirectory plugins. Put symbolic links from plugins to plugin-lib, 1808c2ecf20Sopenharmony_ciand name them according to the order you want them to run. This is not 1818c2ecf20Sopenharmony_cinecessary if a test case being run requires a specific plugin to work. 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciExample: 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cibjb@bee:~/work/tc-testing$ ls -l plugins 1868c2ecf20Sopenharmony_citotal 4 1878c2ecf20Sopenharmony_cilrwxrwxrwx 1 bjb bjb 27 Oct 4 16:12 10-rootPlugin.py -> ../plugin-lib/rootPlugin.py 1888c2ecf20Sopenharmony_cilrwxrwxrwx 1 bjb bjb 25 Oct 12 17:55 20-nsPlugin.py -> ../plugin-lib/nsPlugin.py 1898c2ecf20Sopenharmony_ci-rwxr-xr-x 1 bjb bjb 0 Sep 29 15:56 __init__.py 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ciThe plugins are a subclass of TdcPlugin, defined in TdcPlugin.py and 1928c2ecf20Sopenharmony_cimust be called "SubPlugin" so tdc can find them. They are 1938c2ecf20Sopenharmony_cidistinguished from each other in the python program by their module 1948c2ecf20Sopenharmony_ciname. 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ciThis base class supplies "hooks" to run extra functions. These hooks are as follows: 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cipre- and post-suite 1998c2ecf20Sopenharmony_cipre- and post-case 2008c2ecf20Sopenharmony_cipre- and post-execute stage 2018c2ecf20Sopenharmony_ciadjust-command (runs in all stages and receives the stage name) 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ciThe pre-suite hook receives the number of tests and an array of test ids. 2048c2ecf20Sopenharmony_ciThis allows you to dump out the list of skipped tests in the event of a 2058c2ecf20Sopenharmony_cifailure during setup or teardown stage. 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ciThe pre-case hook receives the ordinal number and test id of the current test. 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ciThe adjust-command hook receives the stage id (see list below) and the 2108c2ecf20Sopenharmony_cifull command to be executed. This allows for last-minute adjustment 2118c2ecf20Sopenharmony_ciof the command. 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ciThe stages are identified by the following strings: 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci - pre (pre-suite) 2168c2ecf20Sopenharmony_ci - setup 2178c2ecf20Sopenharmony_ci - command 2188c2ecf20Sopenharmony_ci - verify 2198c2ecf20Sopenharmony_ci - teardown 2208c2ecf20Sopenharmony_ci - post (post-suite) 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ciTo write a plugin, you need to inherit from TdcPlugin in 2248c2ecf20Sopenharmony_ciTdcPlugin.py. To use the plugin, you have to put the 2258c2ecf20Sopenharmony_ciimplementation file in plugin-lib, and add a symbolic link to it from 2268c2ecf20Sopenharmony_ciplugins. It will be detected at run time and invoked at the 2278c2ecf20Sopenharmony_ciappropriate times. There are a few examples in the plugin-lib 2288c2ecf20Sopenharmony_cidirectory: 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci - rootPlugin.py: 2318c2ecf20Sopenharmony_ci implements the enforcement of running as root 2328c2ecf20Sopenharmony_ci - nsPlugin.py: 2338c2ecf20Sopenharmony_ci sets up a network namespace and runs all commands in that namespace, 2348c2ecf20Sopenharmony_ci while also setting up dummy devices to be used in testing. 2358c2ecf20Sopenharmony_ci - valgrindPlugin.py 2368c2ecf20Sopenharmony_ci runs each command in the execute stage under valgrind, 2378c2ecf20Sopenharmony_ci and checks for leaks. 2388c2ecf20Sopenharmony_ci This plugin will output an extra test for each test in the test file, 2398c2ecf20Sopenharmony_ci one is the existing output as to whether the test passed or failed, 2408c2ecf20Sopenharmony_ci and the other is a test whether the command leaked memory or not. 2418c2ecf20Sopenharmony_ci (This one is a preliminary version, it may not work quite right yet, 2428c2ecf20Sopenharmony_ci but the overall template is there and it should only need tweaks.) 2438c2ecf20Sopenharmony_ci - buildebpfPlugin.py: 2448c2ecf20Sopenharmony_ci builds all programs in $EBPFDIR. 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ciACKNOWLEDGEMENTS 2488c2ecf20Sopenharmony_ci---------------- 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ciThanks to: 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ciJamal Hadi Salim, for providing valuable test cases 2538c2ecf20Sopenharmony_ciKeara Leibovitz, who wrote the CLI test driver that I used as a base for the 2548c2ecf20Sopenharmony_ci first version of the tc testing suite. This work was presented at 2558c2ecf20Sopenharmony_ci Netdev 1.2 Tokyo in October 2016. 2568c2ecf20Sopenharmony_ciSamir Hussain, for providing help while I dove into Python for the first time 2578c2ecf20Sopenharmony_ci and being a second eye for this code. 258