162306a36Sopenharmony_citdc - Linux Traffic Control (tc) unit testing suite
262306a36Sopenharmony_ci
362306a36Sopenharmony_ciAuthor: Lucas Bates - lucasb@mojatatu.com
462306a36Sopenharmony_ci
562306a36Sopenharmony_citdc is a Python script to load tc unit tests from a separate JSON file and
662306a36Sopenharmony_ciexecute them inside a network namespace dedicated to the task.
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciREQUIREMENTS
1062306a36Sopenharmony_ci------------
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci*  Minimum Python version of 3.4. Earlier 3.X versions may work but are not
1362306a36Sopenharmony_ci   guaranteed.
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci*  The kernel must have network namespace support if using nsPlugin
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci*  The kernel must have veth support available, as a veth pair is created
1862306a36Sopenharmony_ci   prior to running the tests when using nsPlugin.
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci*  The kernel must have the appropriate infrastructure enabled to run all tdc
2162306a36Sopenharmony_ci   unit tests. See the config file in this directory for minimum required
2262306a36Sopenharmony_ci   features. As new tests will be added, config options list will be updated.
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci*  All tc-related features being tested must be built in or available as
2562306a36Sopenharmony_ci   modules.  To check what is required in current setup run:
2662306a36Sopenharmony_ci   ./tdc.py -c
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci   Note:
2962306a36Sopenharmony_ci   In the current release, tdc run will abort due to a failure in setup or
3062306a36Sopenharmony_ci   teardown commands - which includes not being able to run a test simply
3162306a36Sopenharmony_ci   because the kernel did not support a specific feature. (This will be
3262306a36Sopenharmony_ci   handled in a future version - the current workaround is to run the tests
3362306a36Sopenharmony_ci   on specific test categories that your kernel supports)
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ciBEFORE YOU RUN
3762306a36Sopenharmony_ci--------------
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciThe path to the tc executable that will be most commonly tested can be defined
4062306a36Sopenharmony_ciin the tdc_config.py file. Find the 'TC' entry in the NAMES dictionary and
4162306a36Sopenharmony_cidefine the path.
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ciIf you need to test a different tc executable on the fly, you can do so by
4462306a36Sopenharmony_ciusing the -p option when running tdc:
4562306a36Sopenharmony_ci	./tdc.py -p /path/to/tc
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ciRUNNING TDC
4962306a36Sopenharmony_ci-----------
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ciTo use tdc, root privileges are required.  This is because the
5262306a36Sopenharmony_cicommands being tested must be run as root.  The code that enforces
5362306a36Sopenharmony_ciexecution by root uid has been moved into a plugin (see PLUGIN
5462306a36Sopenharmony_ciARCHITECTURE, below).
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ciTests that use a network device should have nsPlugin.py listed as a
5762306a36Sopenharmony_cirequirement for that test. nsPlugin executes all commands within a
5862306a36Sopenharmony_cinetwork namespace and creates a veth pair which may be used in those test
5962306a36Sopenharmony_cicases. To disable execution within the namespace, pass the -N option
6062306a36Sopenharmony_cito tdc when starting a test run; the veth pair will still be created
6162306a36Sopenharmony_ciby the plugin.
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ciRunning tdc without any arguments will run all tests. Refer to the section
6462306a36Sopenharmony_cion command line arguments for more information, or run:
6562306a36Sopenharmony_ci	./tdc.py -h
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_citdc will list the test names as they are being run, and print a summary in
6862306a36Sopenharmony_ciTAP (Test Anything Protocol) format when they are done. If tests fail,
6962306a36Sopenharmony_cioutput captured from the failing test will be printed immediately following
7062306a36Sopenharmony_cithe failed test in the TAP output.
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciOVERVIEW OF TDC EXECUTION
7462306a36Sopenharmony_ci-------------------------
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ciOne run of tests is considered a "test suite" (this will be refined in the
7762306a36Sopenharmony_cifuture).  A test suite has one or more test cases in it.
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ciA test case has four stages:
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci  - setup
8262306a36Sopenharmony_ci  - execute
8362306a36Sopenharmony_ci  - verify
8462306a36Sopenharmony_ci  - teardown
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciThe setup and teardown stages can run zero or more commands.  The setup
8762306a36Sopenharmony_cistage does some setup if the test needs it.  The teardown stage undoes
8862306a36Sopenharmony_cithe setup and returns the system to a "neutral" state so any other test
8962306a36Sopenharmony_cican be run next.  These two stages require any commands run to return
9062306a36Sopenharmony_cisuccess, but do not otherwise verify the results.
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ciThe execute and verify stages each run one command.  The execute stage
9362306a36Sopenharmony_citests the return code against one or more acceptable values.  The
9462306a36Sopenharmony_civerify stage checks the return code for success, and also compares
9562306a36Sopenharmony_cithe stdout with a regular expression.
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciEach of the commands in any stage will run in a shell instance.
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciUSER-DEFINED CONSTANTS
10162306a36Sopenharmony_ci----------------------
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ciThe tdc_config.py file contains multiple values that can be altered to suit
10462306a36Sopenharmony_ciyour needs. Any value in the NAMES dictionary can be altered without affecting
10562306a36Sopenharmony_cithe tests to be run. These values are used in the tc commands that will be
10662306a36Sopenharmony_ciexecuted as part of the test. More will be added as test cases require.
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ciExample:
10962306a36Sopenharmony_ci	$TC qdisc add dev $DEV1 ingress
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ciThe NAMES values are used to substitute into the commands in the test cases.
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ciCOMMAND LINE ARGUMENTS
11562306a36Sopenharmony_ci----------------------
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ciRun tdc.py -h to see the full list of available arguments.
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ciusage: tdc.py [-h] [-p PATH] [-D DIR [DIR ...]] [-f FILE [FILE ...]]
12062306a36Sopenharmony_ci              [-c [CATG [CATG ...]]] [-e ID [ID ...]] [-l] [-s] [-i] [-v] [-N]
12162306a36Sopenharmony_ci              [-d DEVICE] [-P] [-n] [-V]
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciLinux TC unit tests
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cioptional arguments:
12662306a36Sopenharmony_ci  -h, --help            show this help message and exit
12762306a36Sopenharmony_ci  -p PATH, --path PATH  The full path to the tc executable to use
12862306a36Sopenharmony_ci  -v, --verbose         Show the commands that are being run
12962306a36Sopenharmony_ci  -N, --notap           Suppress tap results for command under test
13062306a36Sopenharmony_ci  -d DEVICE, --device DEVICE
13162306a36Sopenharmony_ci                        Execute test cases that use a physical device, where
13262306a36Sopenharmony_ci                        DEVICE is its name. (If not defined, tests that require
13362306a36Sopenharmony_ci                        a physical device will be skipped)
13462306a36Sopenharmony_ci  -P, --pause           Pause execution just before post-suite stage
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ciselection:
13762306a36Sopenharmony_ci  select which test cases: files plus directories; filtered by categories
13862306a36Sopenharmony_ci  plus testids
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci  -D DIR [DIR ...], --directory DIR [DIR ...]
14162306a36Sopenharmony_ci                        Collect tests from the specified directory(ies)
14262306a36Sopenharmony_ci                        (default [tc-tests])
14362306a36Sopenharmony_ci  -f FILE [FILE ...], --file FILE [FILE ...]
14462306a36Sopenharmony_ci                        Run tests from the specified file(s)
14562306a36Sopenharmony_ci  -c [CATG [CATG ...]], --category [CATG [CATG ...]]
14662306a36Sopenharmony_ci                        Run tests only from the specified category/ies, or if
14762306a36Sopenharmony_ci                        no category/ies is/are specified, list known
14862306a36Sopenharmony_ci                        categories.
14962306a36Sopenharmony_ci  -e ID [ID ...], --execute ID [ID ...]
15062306a36Sopenharmony_ci                        Execute the specified test cases with specified IDs
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ciaction:
15362306a36Sopenharmony_ci  select action to perform on selected test cases
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci  -l, --list            List all test cases, or those only within the
15662306a36Sopenharmony_ci                        specified category
15762306a36Sopenharmony_ci  -s, --show            Display the selected test cases
15862306a36Sopenharmony_ci  -i, --id              Generate ID numbers for new test cases
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cinetns:
16162306a36Sopenharmony_ci  options for nsPlugin (run commands in net namespace)
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci  -N, --no-namespace
16462306a36Sopenharmony_ci                        Do not run commands in a network namespace.
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_civalgrind:
16762306a36Sopenharmony_ci  options for valgrindPlugin (run command under test under Valgrind)
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci  -V, --valgrind        Run commands under valgrind
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ciPLUGIN ARCHITECTURE
17362306a36Sopenharmony_ci-------------------
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciThere is now a plugin architecture, and some of the functionality that
17662306a36Sopenharmony_ciwas in the tdc.py script has been moved into the plugins.
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ciThe plugins are in the directory plugin-lib.  The are executed from
17962306a36Sopenharmony_cidirectory plugins.  Put symbolic links from plugins to plugin-lib,
18062306a36Sopenharmony_ciand name them according to the order you want them to run. This is not
18162306a36Sopenharmony_cinecessary if a test case being run requires a specific plugin to work.
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ciExample:
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cibjb@bee:~/work/tc-testing$ ls -l plugins
18662306a36Sopenharmony_citotal 4
18762306a36Sopenharmony_cilrwxrwxrwx  1 bjb  bjb    27 Oct  4 16:12 10-rootPlugin.py -> ../plugin-lib/rootPlugin.py
18862306a36Sopenharmony_cilrwxrwxrwx  1 bjb  bjb    25 Oct 12 17:55 20-nsPlugin.py -> ../plugin-lib/nsPlugin.py
18962306a36Sopenharmony_ci-rwxr-xr-x  1 bjb  bjb     0 Sep 29 15:56 __init__.py
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ciThe plugins are a subclass of TdcPlugin, defined in TdcPlugin.py and
19262306a36Sopenharmony_cimust be called "SubPlugin" so tdc can find them.  They are
19362306a36Sopenharmony_cidistinguished from each other in the python program by their module
19462306a36Sopenharmony_ciname.
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ciThis base class supplies "hooks" to run extra functions.  These hooks are as follows:
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cipre- and post-suite
19962306a36Sopenharmony_cipre- and post-case
20062306a36Sopenharmony_cipre- and post-execute stage
20162306a36Sopenharmony_ciadjust-command (runs in all stages and receives the stage name)
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ciThe pre-suite hook receives the number of tests and an array of test ids.
20462306a36Sopenharmony_ciThis allows you to dump out the list of skipped tests in the event of a
20562306a36Sopenharmony_cifailure during setup or teardown stage.
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ciThe pre-case hook receives the ordinal number and test id of the current test.
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ciThe adjust-command hook receives the stage id (see list below) and the
21062306a36Sopenharmony_cifull command to be executed.  This allows for last-minute adjustment
21162306a36Sopenharmony_ciof the command.
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ciThe stages are identified by the following strings:
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci  - pre  (pre-suite)
21662306a36Sopenharmony_ci  - setup
21762306a36Sopenharmony_ci  - command
21862306a36Sopenharmony_ci  - verify
21962306a36Sopenharmony_ci  - teardown
22062306a36Sopenharmony_ci  - post (post-suite)
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ciTo write a plugin, you need to inherit from TdcPlugin in
22462306a36Sopenharmony_ciTdcPlugin.py.  To use the plugin, you have to put the
22562306a36Sopenharmony_ciimplementation file in plugin-lib, and add a symbolic link to it from
22662306a36Sopenharmony_ciplugins.  It will be detected at run time and invoked at the
22762306a36Sopenharmony_ciappropriate times.  There are a few examples in the plugin-lib
22862306a36Sopenharmony_cidirectory:
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci  - rootPlugin.py:
23162306a36Sopenharmony_ci      implements the enforcement of running as root
23262306a36Sopenharmony_ci  - nsPlugin.py:
23362306a36Sopenharmony_ci      sets up a network namespace and runs all commands in that namespace,
23462306a36Sopenharmony_ci      while also setting up dummy devices to be used in testing.
23562306a36Sopenharmony_ci  - valgrindPlugin.py
23662306a36Sopenharmony_ci      runs each command in the execute stage under valgrind,
23762306a36Sopenharmony_ci      and checks for leaks.
23862306a36Sopenharmony_ci      This plugin will output an extra test for each test in the test file,
23962306a36Sopenharmony_ci      one is the existing output as to whether the test passed or failed,
24062306a36Sopenharmony_ci      and the other is a test whether the command leaked memory or not.
24162306a36Sopenharmony_ci      (This one is a preliminary version, it may not work quite right yet,
24262306a36Sopenharmony_ci      but the overall template is there and it should only need tweaks.)
24362306a36Sopenharmony_ci  - buildebpfPlugin.py:
24462306a36Sopenharmony_ci      builds all programs in $EBPFDIR.
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ciACKNOWLEDGEMENTS
24862306a36Sopenharmony_ci----------------
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ciThanks to:
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ciJamal Hadi Salim, for providing valuable test cases
25362306a36Sopenharmony_ciKeara Leibovitz, who wrote the CLI test driver that I used as a base for the
25462306a36Sopenharmony_ci   first version of the tc testing suite. This work was presented at
25562306a36Sopenharmony_ci   Netdev 1.2 Tokyo in October 2016.
25662306a36Sopenharmony_ciSamir Hussain, for providing help while I dove into Python for the first time
25762306a36Sopenharmony_ci    and being a second eye for this code.
258