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