Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'net-Introduction-of-the-tc-tests'

Lucas Bates says:

====================
net: Introduction of the tc tests

Apologies for sending this as one big patch. I've been sitting on this a little
too long, but it's ready and I wanted to get it out.

There are a limited number of tests to start - I plan to add more on a regular
basis.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+1863
+1
tools/testing/selftests/tc-testing/.gitignore
··· 1 + __pycache__/
+102
tools/testing/selftests/tc-testing/README
··· 1 + tdc - Linux Traffic Control (tc) unit testing suite 2 + 3 + Author: Lucas Bates - lucasb@mojatatu.com 4 + 5 + tdc is a Python script to load tc unit tests from a separate JSON file and 6 + execute them inside a network namespace dedicated to the task. 7 + 8 + 9 + REQUIREMENTS 10 + ------------ 11 + 12 + * Minimum Python version of 3.4. Earlier 3.X versions may work but are not 13 + guaranteed. 14 + 15 + * The kernel must have network namespace support 16 + 17 + * The kernel must have veth support available, as a veth pair is created 18 + prior to running the tests. 19 + 20 + * All tc-related features must be built in or available as modules. 21 + To check what is required in current setup run: 22 + ./tdc.py -c 23 + 24 + Note: 25 + In the current release, tdc run will abort due to a failure in setup or 26 + teardown commands - which includes not being able to run a test simply 27 + because the kernel did not support a specific feature. (This will be 28 + handled in a future version - the current workaround is to run the tests 29 + on specific test categories that your kernel supports) 30 + 31 + 32 + BEFORE YOU RUN 33 + -------------- 34 + 35 + The path to the tc executable that will be most commonly tested can be defined 36 + in the tdc_config.py file. Find the 'TC' entry in the NAMES dictionary and 37 + define the path. 38 + 39 + If you need to test a different tc executable on the fly, you can do so by 40 + using the -p option when running tdc: 41 + ./tdc.py -p /path/to/tc 42 + 43 + 44 + RUNNING TDC 45 + ----------- 46 + 47 + To use tdc, root privileges are required. tdc will not run otherwise. 48 + 49 + All tests are executed inside a network namespace to prevent conflicts 50 + within the host. 51 + 52 + Running tdc without any arguments will run all tests. Refer to the section 53 + on command line arguments for more information, or run: 54 + ./tdc.py -h 55 + 56 + tdc will list the test names as they are being run, and print a summary in 57 + TAP (Test Anything Protocol) format when they are done. If tests fail, 58 + output captured from the failing test will be printed immediately following 59 + the failed test in the TAP output. 60 + 61 + 62 + USER-DEFINED CONSTANTS 63 + ---------------------- 64 + 65 + The tdc_config.py file contains multiple values that can be altered to suit 66 + your needs. Any value in the NAMES dictionary can be altered without affecting 67 + the tests to be run. These values are used in the tc commands that will be 68 + executed as part of the test. More will be added as test cases require. 69 + 70 + Example: 71 + $TC qdisc add dev $DEV1 ingress 72 + 73 + 74 + COMMAND LINE ARGUMENTS 75 + ---------------------- 76 + 77 + Run tdc.py -h to see the full list of available arguments. 78 + 79 + -p PATH Specify the tc executable located at PATH to be used on this 80 + test run 81 + -c Show the available test case categories in this test file 82 + -c CATEGORY Run only tests that belong to CATEGORY 83 + -f FILE Read test cases from the JSON file named FILE 84 + -l [CATEGORY] List all test cases in the JSON file. If CATEGORY is 85 + specified, list test cases matching that category. 86 + -s ID Show the test case matching ID 87 + -e ID Execute the test case identified by ID 88 + -i Generate unique ID numbers for test cases with no existing 89 + ID number 90 + 91 + 92 + ACKNOWLEDGEMENTS 93 + ---------------- 94 + 95 + Thanks to: 96 + 97 + Jamal Hadi Salim, for providing valuable test cases 98 + Keara Leibovitz, who wrote the CLI test driver that I used as a base for the 99 + first version of the tc testing suite. This work was presented at 100 + Netdev 1.2 Tokyo in October 2016. 101 + Samir Hussain, for providing help while I dove into Python for the first time 102 + and being a second eye for this code.
+10
tools/testing/selftests/tc-testing/TODO.txt
··· 1 + tc Testing Suite To-Do list: 2 + 3 + - Determine what tc features are supported in the kernel. If features are not 4 + present, prevent the related categories from running. 5 + 6 + - Add support for multiple versions of tc to run successively 7 + 8 + - Improve error messages when tdc aborts its run 9 + 10 + - Allow tdc to write its results to file
+69
tools/testing/selftests/tc-testing/creating-testcases/AddingTestCases.txt
··· 1 + tdc - Adding test cases for tdc 2 + 3 + Author: Lucas Bates - lucasb@mojatatu.com 4 + 5 + ADDING TEST CASES 6 + ----------------- 7 + 8 + User-defined tests should be added by defining a separate JSON file. This 9 + will help prevent conflicts when updating the repository. Refer to 10 + template.json for the required JSON format for test cases. 11 + 12 + Include the 'id' field, but do not assign a value. Running tdc with the -i 13 + option will generate a unique ID for that test case. 14 + 15 + tdc will recursively search the 'tc' subdirectory for .json files. Any 16 + test case files you create in these directories will automatically be included. 17 + If you wish to store your custom test cases elsewhere, be sure to run tdc 18 + with the -f argument and the path to your file. 19 + 20 + Be aware of required escape characters in the JSON data - particularly when 21 + defining the match pattern. Refer to the tctests.json file for examples when 22 + in doubt. 23 + 24 + 25 + TEST CASE STRUCTURE 26 + ------------------- 27 + 28 + Each test case has required data: 29 + 30 + id: A unique alphanumeric value to identify a particular test case 31 + name: Descriptive name that explains the command under test 32 + category: A list of single-word descriptions covering what the command 33 + under test is testing. Example: filter, actions, u32, gact, etc. 34 + setup: The list of commands required to ensure the command under test 35 + succeeds. For example: if testing a filter, the command to create 36 + the qdisc would appear here. 37 + cmdUnderTest: The tc command being tested itself. 38 + expExitCode: The code returned by the command under test upon its termination. 39 + tdc will compare this value against the actual returned value. 40 + verifyCmd: The tc command to be run to verify successful execution. 41 + For example: if the command under test creates a gact action, 42 + verifyCmd should be "$TC actions show action gact" 43 + matchPattern: A regular expression to be applied against the output of the 44 + verifyCmd to prove the command under test succeeded. This pattern 45 + should be as specific as possible so that a false positive is not 46 + matched. 47 + matchCount: How many times the regex in matchPattern should match. A value 48 + of 0 is acceptable. 49 + teardown: The list of commands to clean up after the test is completed. 50 + The environment should be returned to the same state as when 51 + this test was started: qdiscs deleted, actions flushed, etc. 52 + 53 + 54 + SETUP/TEARDOWN ERRORS 55 + --------------------- 56 + 57 + If an error is detected during the setup/teardown process, execution of the 58 + tests will immediately stop with an error message and the namespace in which 59 + the tests are run will be destroyed. This is to prevent inaccurate results 60 + in the test cases. 61 + 62 + Repeated failures of the setup/teardown may indicate a problem with the test 63 + case, or possibly even a bug in one of the commands that are not being tested. 64 + 65 + It's possible to include acceptable exit codes with the setup/teardown command 66 + so that it doesn't halt the script for an error that doesn't matter. Turn the 67 + individual command into a list, with the command being first, followed by all 68 + acceptable exit codes for the command. 69 +
+40
tools/testing/selftests/tc-testing/creating-testcases/template.json
··· 1 + [ 2 + { 3 + "id": "", 4 + "name": "", 5 + "category": [ 6 + "", 7 + "" 8 + ], 9 + "setup": [ 10 + "" 11 + ], 12 + "cmdUnderTest": "", 13 + "expExitCode": "", 14 + "verifyCmd": "", 15 + "matchPattern": "", 16 + "matchCount": "", 17 + "teardown": [ 18 + "" 19 + ] 20 + }, 21 + { 22 + "id": "", 23 + "name": "", 24 + "category": [ 25 + "", 26 + "" 27 + ], 28 + "setup": [ 29 + "" 30 + ], 31 + "cmdUnderTest": "", 32 + "expExitCode": "", 33 + "verifyCmd": "", 34 + "matchPattern": "", 35 + "matchCount": "", 36 + "teardown": [ 37 + "" 38 + ] 39 + } 40 + ]
+1115
tools/testing/selftests/tc-testing/tc-tests/actions/tests.json
··· 1 + [ 2 + { 3 + "id": "e89a", 4 + "name": "Add valid pass action", 5 + "category": [ 6 + "actions", 7 + "gact" 8 + ], 9 + "setup": [ 10 + [ 11 + "$TC actions flush action gact", 12 + 0, 13 + 1, 14 + 255 15 + ] 16 + ], 17 + "cmdUnderTest": "$TC actions add action pass index 8", 18 + "expExitCode": "0", 19 + "verifyCmd": "$TC actions list action gact", 20 + "matchPattern": "action order [0-9]*: gact action pass.*index 8 ref", 21 + "matchCount": "1", 22 + "teardown": [ 23 + "$TC actions flush action gact" 24 + ] 25 + }, 26 + { 27 + "id": "a02c", 28 + "name": "Add valid pipe action", 29 + "category": [ 30 + "actions", 31 + "gact" 32 + ], 33 + "setup": [ 34 + [ 35 + "$TC actions flush action gact", 36 + 0, 37 + 1, 38 + 255 39 + ] 40 + ], 41 + "cmdUnderTest": "$TC actions add action pipe index 6", 42 + "expExitCode": "0", 43 + "verifyCmd": "$TC actions list action gact", 44 + "matchPattern": "action order [0-9]*: gact action pipe.*index 6 ref", 45 + "matchCount": "1", 46 + "teardown": [ 47 + "$TC actions flush action gact" 48 + ] 49 + }, 50 + { 51 + "id": "feef", 52 + "name": "Add valid reclassify action", 53 + "category": [ 54 + "actions", 55 + "gact" 56 + ], 57 + "setup": [ 58 + [ 59 + "$TC actions flush action gact", 60 + 0, 61 + 1, 62 + 255 63 + ] 64 + ], 65 + "cmdUnderTest": "$TC actions add action reclassify index 5", 66 + "expExitCode": "0", 67 + "verifyCmd": "$TC actions list action gact", 68 + "matchPattern": "action order [0-9]*: gact action reclassify.*index 5 ref", 69 + "matchCount": "1", 70 + "teardown": [ 71 + "$TC actions flush action gact" 72 + ] 73 + }, 74 + { 75 + "id": "8a7a", 76 + "name": "Add valid drop action", 77 + "category": [ 78 + "actions", 79 + "gact" 80 + ], 81 + "setup": [ 82 + [ 83 + "$TC actions flush action gact", 84 + 0, 85 + 1, 86 + 255 87 + ] 88 + ], 89 + "cmdUnderTest": "$TC actions add action drop index 30", 90 + "expExitCode": "0", 91 + "verifyCmd": "$TC actions list action gact", 92 + "matchPattern": "action order [0-9]*: gact action drop.*index 30 ref", 93 + "matchCount": "1", 94 + "teardown": [ 95 + "$TC actions flush action gact" 96 + ] 97 + }, 98 + { 99 + "id": "9a52", 100 + "name": "Add valid continue action", 101 + "category": [ 102 + "actions", 103 + "gact" 104 + ], 105 + "setup": [ 106 + [ 107 + "$TC actions flush action gact", 108 + 0, 109 + 1, 110 + 255 111 + ] 112 + ], 113 + "cmdUnderTest": "$TC actions add action continue index 432", 114 + "expExitCode": "0", 115 + "verifyCmd": "$TC actions list action gact", 116 + "matchPattern": "action order [0-9]*: gact action continue.*index 432 ref", 117 + "matchCount": "1", 118 + "teardown": [ 119 + "$TC actions flush action gact" 120 + ] 121 + }, 122 + { 123 + "id": "d700", 124 + "name": "Add invalid action", 125 + "category": [ 126 + "actions", 127 + "gact" 128 + ], 129 + "setup": [ 130 + [ 131 + "$TC actions flush action gact", 132 + 0, 133 + 1, 134 + 255 135 + ] 136 + ], 137 + "cmdUnderTest": "$TC actions add action pump index 386", 138 + "expExitCode": "255", 139 + "verifyCmd": "$TC actions list action gact", 140 + "matchPattern": "action order [0-9]*: gact action.*index 386 ref", 141 + "matchCount": "0", 142 + "teardown": [ 143 + "$TC actions flush action gact" 144 + ] 145 + }, 146 + { 147 + "id": "9215", 148 + "name": "Add action with duplicate index", 149 + "category": [ 150 + "actions", 151 + "gact" 152 + ], 153 + "setup": [ 154 + [ 155 + "$TC actions flush action gact", 156 + 0, 157 + 1, 158 + 255 159 + ], 160 + "$TC actions add action pipe index 15" 161 + ], 162 + "cmdUnderTest": "$TC actions add action drop index 15", 163 + "expExitCode": "255", 164 + "verifyCmd": "$TC actions list action gact", 165 + "matchPattern": "action order [0-9]*: gact action drop.*index 15 ref", 166 + "matchCount": "0", 167 + "teardown": [ 168 + "$TC actions flush action gact" 169 + ] 170 + }, 171 + { 172 + "id": "798e", 173 + "name": "Add action with index exceeding 32-bit maximum", 174 + "category": [ 175 + "actions", 176 + "gact" 177 + ], 178 + "setup": [ 179 + [ 180 + "$TC actions flush action gact", 181 + 0, 182 + 1, 183 + 255 184 + ] 185 + ], 186 + "cmdUnderTest": "$TC actions add action drop index 4294967296", 187 + "expExitCode": "255", 188 + "verifyCmd": "actions list action gact", 189 + "matchPattern": "action order [0-9]*: gact action drop.*index 4294967296 ref", 190 + "matchCount": "0", 191 + "teardown": [ 192 + "$TC actions flush action gact" 193 + ] 194 + }, 195 + { 196 + "id": "22be", 197 + "name": "Add action with index at 32-bit maximum", 198 + "category": [ 199 + "actions", 200 + "gact" 201 + ], 202 + "setup": [ 203 + [ 204 + "$TC actions flush action gact", 205 + 0, 206 + 1, 207 + 255 208 + ] 209 + ], 210 + "cmdUnderTest": "$TC actions add action drop index 4294967295", 211 + "expExitCode": "0", 212 + "verifyCmd": "$TC actions list action gact", 213 + "matchPattern": "action order [0-9]*: gact action drop.*index 4294967295 ref", 214 + "matchCount": "1", 215 + "teardown": [ 216 + "$TC actions flush action gact" 217 + ] 218 + }, 219 + { 220 + "id": "ac2a", 221 + "name": "List actions", 222 + "category": [ 223 + "actions", 224 + "gact" 225 + ], 226 + "setup": [ 227 + [ 228 + "$TC actions flush action gact", 229 + 0, 230 + 1, 231 + 255 232 + ], 233 + "$TC actions add action reclassify index 101", 234 + "$TC actions add action reclassify index 102", 235 + "$TC actions add action reclassify index 103", 236 + "$TC actions add action reclassify index 104", 237 + "$TC actions add action reclassify index 105" 238 + ], 239 + "cmdUnderTest": "$TC actions list action gact", 240 + "expExitCode": "0", 241 + "verifyCmd": "$TC actions list action gact", 242 + "matchPattern": "action order [0-9]*: gact action reclassify", 243 + "matchCount": "5", 244 + "teardown": [ 245 + "$TC actions flush action gact" 246 + ] 247 + }, 248 + { 249 + "id": "63ec", 250 + "name": "Delete pass action", 251 + "category": [ 252 + "actions", 253 + "gact" 254 + ], 255 + "setup": [ 256 + [ 257 + "$TC actions flush action gact", 258 + 0, 259 + 1, 260 + 255 261 + ], 262 + "$TC actions add action pass index 1" 263 + ], 264 + "cmdUnderTest": "$TC actions del action gact index 1", 265 + "expExitCode": "0", 266 + "verifyCmd": "$TC actions list action gact", 267 + "matchPattern": "action order [0-9]*: gact action pass.*index 1 ref", 268 + "matchCount": "0", 269 + "teardown": [ 270 + "$TC actions flush action gact" 271 + ] 272 + }, 273 + { 274 + "id": "46be", 275 + "name": "Delete pipe action", 276 + "category": [ 277 + "actions", 278 + "gact" 279 + ], 280 + "setup": [ 281 + [ 282 + "$TC actions flush action gact", 283 + 0, 284 + 1, 285 + 255 286 + ], 287 + "$TC actions add action pipe index 9" 288 + ], 289 + "cmdUnderTest": "$TC actions del action gact index 9", 290 + "expExitCode": "0", 291 + "verifyCmd": "$TC actions list action gact", 292 + "matchPattern": "action order [0-9]*: gact action pipe.*index 9 ref", 293 + "matchCount": "0", 294 + "teardown": [ 295 + "$TC actions flush action gact" 296 + ] 297 + }, 298 + { 299 + "id": "2e08", 300 + "name": "Delete reclassify action", 301 + "category": [ 302 + "actions", 303 + "gact" 304 + ], 305 + "setup": [ 306 + [ 307 + "$TC actions flush action gact", 308 + 0, 309 + 1, 310 + 255 311 + ], 312 + "$TC actions add action reclassify index 65536" 313 + ], 314 + "cmdUnderTest": "$TC actions del action gact index 65536", 315 + "expExitCode": "0", 316 + "verifyCmd": "$TC actions list action gact", 317 + "matchPattern": "action order [0-9]*: gact action reclassify.*index 65536 ref", 318 + "matchCount": "0", 319 + "teardown": [ 320 + "$TC actions flush action gact" 321 + ] 322 + }, 323 + { 324 + "id": "99c4", 325 + "name": "Delete drop action", 326 + "category": [ 327 + "actions", 328 + "gact" 329 + ], 330 + "setup": [ 331 + [ 332 + "$TC actions flush action gact", 333 + 0, 334 + 1, 335 + 255 336 + ], 337 + "$TC actions add action drop index 16" 338 + ], 339 + "cmdUnderTest": "$TC actions del action gact index 16", 340 + "expExitCode": "0", 341 + "verifyCmd": "$TC actions list action gact", 342 + "matchPattern": "action order [0-9]*: gact action drop.*index 16 ref", 343 + "matchCount": "0", 344 + "teardown": [ 345 + "$TC actions flush action gact" 346 + ] 347 + }, 348 + { 349 + "id": "fb6b", 350 + "name": "Delete continue action", 351 + "category": [ 352 + "actions", 353 + "gact" 354 + ], 355 + "setup": [ 356 + [ 357 + "$TC actions flush action gact", 358 + 0, 359 + 1, 360 + 255 361 + ], 362 + "$TC actions add action continue index 32" 363 + ], 364 + "cmdUnderTest": "$TC actions del action gact index 32", 365 + "expExitCode": "0", 366 + "verifyCmd": "actions list action gact", 367 + "matchPattern": "action order [0-9]*: gact action continue.*index 32 ref", 368 + "matchCount": "0", 369 + "teardown": [ 370 + "$TC actions flush action gact" 371 + ] 372 + }, 373 + { 374 + "id": "0eb3", 375 + "name": "Delete non-existent action", 376 + "category": [ 377 + "actions", 378 + "gact" 379 + ], 380 + "setup": [ 381 + [ 382 + "$TC actions flush action gact", 383 + 0, 384 + 1, 385 + 255 386 + ] 387 + ], 388 + "cmdUnderTest": "$TC actions del action gact index 2", 389 + "expExitCode": "255", 390 + "verifyCmd": "$TC actions list action gact", 391 + "matchPattern": "action order [0-9]*: gact action", 392 + "matchCount": "0", 393 + "teardown": [ 394 + "$TC actions flush action gact" 395 + ] 396 + }, 397 + { 398 + "id": "5124", 399 + "name": "Add mirred mirror to egress action", 400 + "category": [ 401 + "actions", 402 + "mirred" 403 + ], 404 + "setup": [ 405 + [ 406 + "$TC actions flush action mirred", 407 + 0, 408 + 1, 409 + 255 410 + ] 411 + ], 412 + "cmdUnderTest": "$TC actions add action mirred egress mirror index 1 dev lo", 413 + "expExitCode": "0", 414 + "verifyCmd": "$TC actions list action mirred", 415 + "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 1 ref", 416 + "matchCount": "1", 417 + "teardown": [ 418 + "$TC actions flush action mirred" 419 + ] 420 + }, 421 + { 422 + "id": "6fb4", 423 + "name": "Add mirred redirect to egress action", 424 + "category": [ 425 + "actions", 426 + "mirred" 427 + ], 428 + "setup": [ 429 + [ 430 + "$TC actions flush action mirred", 431 + 0, 432 + 1, 433 + 255 434 + ] 435 + ], 436 + "cmdUnderTest": "$TC actions add action mirred egress redirect index 2 dev lo action pipe", 437 + "expExitCode": "0", 438 + "verifyCmd": "$TC actions list action mirred", 439 + "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 2 ref", 440 + "matchCount": "1", 441 + "teardown": [ 442 + "$TC actions flush action mirred" 443 + ] 444 + }, 445 + { 446 + "id": "ba38", 447 + "name": "Get mirred actions", 448 + "category": [ 449 + "actions", 450 + "mirred" 451 + ], 452 + "setup": [ 453 + [ 454 + "$TC actions flush action mirred", 455 + 0, 456 + 1, 457 + 255 458 + ], 459 + "$TC actions add action mirred egress mirror index 1 dev lo", 460 + "$TC actions add action mirred egress redirect index 2 dev lo" 461 + ], 462 + "cmdUnderTest": "$TC actions show action mirred", 463 + "expExitCode": "0", 464 + "verifyCmd": "$TC actions list action mirred", 465 + "matchPattern": "[Mirror|Redirect] to device lo", 466 + "matchCount": "2", 467 + "teardown": [ 468 + "$TC actions flush action mirred" 469 + ] 470 + }, 471 + { 472 + "id": "d7c0", 473 + "name": "Add invalid mirred direction", 474 + "category": [ 475 + "actions", 476 + "mirred" 477 + ], 478 + "setup": [ 479 + [ 480 + "$TC actions flush action mirred", 481 + 0, 482 + 1, 483 + 255 484 + ] 485 + ], 486 + "cmdUnderTest": "$TC actions add action mirred inbound mirror index 20 dev lo", 487 + "expExitCode": "255", 488 + "verifyCmd": "$TC actions list action mirred", 489 + "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 20 ref", 490 + "matchCount": "0", 491 + "teardown": [ 492 + "$TC actions flush action mirred" 493 + ] 494 + }, 495 + { 496 + "id": "e213", 497 + "name": "Add invalid mirred action", 498 + "category": [ 499 + "actions", 500 + "mirred" 501 + ], 502 + "setup": [ 503 + [ 504 + "$TC actions flush action mirred", 505 + 0, 506 + 1, 507 + 255 508 + ] 509 + ], 510 + "cmdUnderTest": "$TC actions add action mirred egress remirror index 20 dev lo", 511 + "expExitCode": "255", 512 + "verifyCmd": "$TC actions list action mirred", 513 + "matchPattern": "action order [0-9]*: mirred \\(Egress.*to device lo\\).*index 20 ref", 514 + "matchCount": "0", 515 + "teardown": [ 516 + "$TC actions flush action mirred" 517 + ] 518 + }, 519 + { 520 + "id": "2d89", 521 + "name": "Add mirred action with invalid device", 522 + "category": [ 523 + "actions", 524 + "mirred" 525 + ], 526 + "setup": [ 527 + [ 528 + "$TC actions flush action mirred", 529 + 0, 530 + 1, 531 + 255 532 + ] 533 + ], 534 + "cmdUnderTest": "$TC actions add action mirred egress mirror index 20 dev eltoh", 535 + "expExitCode": "255", 536 + "verifyCmd": "$TC actions list action mirred", 537 + "matchPattern": "action order [0-9]*: mirred \\(.*to device eltoh\\).*index 20 ref", 538 + "matchCount": "0", 539 + "teardown": [ 540 + "$TC actions flush action mirred" 541 + ] 542 + }, 543 + { 544 + "id": "300b", 545 + "name": "Add mirred action with duplicate index", 546 + "category": [ 547 + "actions", 548 + "mirred" 549 + ], 550 + "setup": [ 551 + [ 552 + "$TC actions flush action mirred", 553 + 0, 554 + 1, 555 + 255 556 + ], 557 + "$TC actions add action mirred egress redirect index 15 dev lo" 558 + ], 559 + "cmdUnderTest": "$TC actions add action mirred egress mirror index 15 dev lo", 560 + "expExitCode": "255", 561 + "verifyCmd": "$TC actions list action mirred", 562 + "matchPattern": "action order [0-9]*: mirred \\(.*to device lo\\).*index 15 ref", 563 + "matchCount": "1", 564 + "teardown": [ 565 + "$TC actions flush action mirred" 566 + ] 567 + }, 568 + { 569 + "id": "a70e", 570 + "name": "Delete mirred mirror action", 571 + "category": [ 572 + "actions", 573 + "mirred" 574 + ], 575 + "setup": [ 576 + [ 577 + "$TC actions flush action mirred", 578 + 0, 579 + 1, 580 + 255 581 + ], 582 + "$TC actions add action mirred egress mirror index 5 dev lo" 583 + ], 584 + "cmdUnderTest": "$TC actions del action mirred index 5", 585 + "expExitCode": "0", 586 + "verifyCmd": "$TC actions list action mirred", 587 + "matchPattern": "action order [0-9]*: mirred \\(Egress Mirror to device lo\\).*index 5 ref", 588 + "matchCount": "0", 589 + "teardown": [ 590 + "$TC actions flush action mirred" 591 + ] 592 + }, 593 + { 594 + "id": "3fb3", 595 + "name": "Delete mirred redirect action", 596 + "category": [ 597 + "actions", 598 + "mirred" 599 + ], 600 + "setup": [ 601 + [ 602 + "$TC actions flush action mirred", 603 + 0, 604 + 1, 605 + 255 606 + ], 607 + "$TC actions add action mirred egress redirect index 5 dev lo" 608 + ], 609 + "cmdUnderTest": "$TC actions del action mirred index 5", 610 + "expExitCode": "0", 611 + "verifyCmd": "$TC actions list action mirred", 612 + "matchPattern": "action order [0-9]*: mirred \\(Egress Redirect to device lo\\).*index 5 ref", 613 + "matchCount": "0", 614 + "teardown": [ 615 + "$TC actions flush action mirred" 616 + ] 617 + }, 618 + { 619 + "id": "b078", 620 + "name": "Add simple action", 621 + "category": [ 622 + "actions", 623 + "simple" 624 + ], 625 + "setup": [ 626 + [ 627 + "$TC actions flush action simple", 628 + 0, 629 + 1, 630 + 255 631 + ] 632 + ], 633 + "cmdUnderTest": "$TC actions add action simple sdata \"A triumph\" index 60", 634 + "expExitCode": "0", 635 + "verifyCmd": "$TC actions list action simple", 636 + "matchPattern": "action order [0-9]*: Simple <A triumph>.*index 60 ref", 637 + "matchCount": "1", 638 + "teardown": [ 639 + "$TC actions flush action simple" 640 + ] 641 + }, 642 + { 643 + "id": "6d4c", 644 + "name": "Add simple action with duplicate index", 645 + "category": [ 646 + "actions", 647 + "simple" 648 + ], 649 + "setup": [ 650 + [ 651 + "$TC actions flush action simple", 652 + 0, 653 + 1, 654 + 255 655 + ], 656 + "$TC actions add action simple sdata \"Aruba\" index 4" 657 + ], 658 + "cmdUnderTest": "$TC actions add action simple sdata \"Jamaica\" index 4", 659 + "expExitCode": "255", 660 + "verifyCmd": "$TC actions list action simple", 661 + "matchPattern": "action order [0-9]*: Simple <Jamaica>.*ref", 662 + "matchCount": "0", 663 + "teardown": [ 664 + "$TC actions flush action simple" 665 + ] 666 + }, 667 + { 668 + "id": "2542", 669 + "name": "List simple actions", 670 + "category": [ 671 + "actions", 672 + "simple" 673 + ], 674 + "setup": [ 675 + [ 676 + "$TC actions flush action simple", 677 + 0, 678 + 1, 679 + 255 680 + ], 681 + "$TC actions add action simple sdata \"Rock\"", 682 + "$TC actions add action simple sdata \"Paper\"", 683 + "$TC actions add action simple sdata \"Scissors\" index 98" 684 + ], 685 + "cmdUnderTest": "$TC actions list action simple", 686 + "expExitCode": "0", 687 + "verifyCmd": "$TC actions list action simple", 688 + "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>", 689 + "matchCount": "3", 690 + "teardown": [ 691 + "$TC actions flush action simple" 692 + ] 693 + }, 694 + { 695 + "id": "ea67", 696 + "name": "Delete simple action", 697 + "category": [ 698 + "actions", 699 + "simple" 700 + ], 701 + "setup": [ 702 + [ 703 + "$TC actions flush action simple", 704 + 0, 705 + 1, 706 + 255 707 + ], 708 + "$TC actions add action simple sdata \"Blinkenlights\" index 1" 709 + ], 710 + "cmdUnderTest": "$TC actions delete action simple index 1", 711 + "expExitCode": "0", 712 + "verifyCmd": "$TC actions list action simple", 713 + "matchPattern": "action order [0-9]*: Simple <Blinkenlights>.*index 1 ref", 714 + "matchCount": "0", 715 + "teardown": [ 716 + "$TC actions flush action simple" 717 + ] 718 + }, 719 + { 720 + "id": "8ff1", 721 + "name": "Flush simple actions", 722 + "category": [ 723 + "actions", 724 + "simple" 725 + ], 726 + "setup": [ 727 + [ 728 + "$TC actions flush action simple", 729 + 0, 730 + 1, 731 + 255 732 + ], 733 + "$TC actions add action simple sdata \"Kirk\"", 734 + "$TC actions add action simple sdata \"Spock\" index 50", 735 + "$TC actions add action simple sdata \"McCoy\" index 9" 736 + ], 737 + "cmdUnderTest": "$TC actions flush action simple", 738 + "expExitCode": "0", 739 + "verifyCmd": "$TC actions list action simple", 740 + "matchPattern": "action order [0-9]*: Simple <[A-Z][a-z]*>", 741 + "matchCount": "0", 742 + "teardown": [ 743 + "" 744 + ] 745 + }, 746 + { 747 + "id": "6236", 748 + "name": "Add skbedit action with valid mark", 749 + "category": [ 750 + "actions", 751 + "skbedit" 752 + ], 753 + "setup": [ 754 + [ 755 + "$TC actions flush action skbedit", 756 + 0, 757 + 1, 758 + 255 759 + ] 760 + ], 761 + "cmdUnderTest": "$TC actions add action skbedit mark 1", 762 + "expExitCode": "0", 763 + "verifyCmd": "$TC actions list action skbedit", 764 + "matchPattern": "action order [0-9]*: skbedit mark 1", 765 + "matchCount": "1", 766 + "teardown": [ 767 + "$TC actions flush action skbedit" 768 + ] 769 + }, 770 + { 771 + "id": "407b", 772 + "name": "Add skbedit action with invalid mark", 773 + "category": [ 774 + "actions", 775 + "skbedit" 776 + ], 777 + "setup": [ 778 + [ 779 + "$TC actions flush action skbedit", 780 + 0, 781 + 1, 782 + 255 783 + ] 784 + ], 785 + "cmdUnderTest": "$TC actions add action skbedit mark 666777888999", 786 + "expExitCode": "255", 787 + "verifyCmd": "$TC actions list action skbedit", 788 + "matchPattern": "action order [0-9]*: skbedit mark", 789 + "matchCount": "0", 790 + "teardown": [ 791 + "$TC actions flush action skbedit" 792 + ] 793 + }, 794 + { 795 + "id": "081d", 796 + "name": "Add skbedit action with priority", 797 + "category": [ 798 + "actions", 799 + "skbedit" 800 + ], 801 + "setup": [ 802 + [ 803 + "$TC actions flush action skbedit", 804 + 0, 805 + 1, 806 + 255 807 + ] 808 + ], 809 + "cmdUnderTest": "$TC actions add action skbedit prio 99", 810 + "expExitCode": "0", 811 + "verifyCmd": "$TC actions list action skbedit", 812 + "matchPattern": "action order [0-9]*: skbedit priority :99", 813 + "matchCount": "1", 814 + "teardown": [ 815 + "$TC actions flush action skbedit" 816 + ] 817 + }, 818 + { 819 + "id": "cc37", 820 + "name": "Add skbedit action with invalid priority", 821 + "category": [ 822 + "actions", 823 + "skbedit" 824 + ], 825 + "setup": [ 826 + [ 827 + "$TC actions flush action skbedit", 828 + 0, 829 + 1, 830 + 255 831 + ] 832 + ], 833 + "cmdUnderTest": "$TC actions add action skbedit prio foo", 834 + "expExitCode": "255", 835 + "verifyCmd": "$TC actions list action skbedit", 836 + "matchPattern": "action order [0-9]*: skbedit priority", 837 + "matchCount": "0", 838 + "teardown": [ 839 + "$TC actions flush action skbedit" 840 + ] 841 + }, 842 + { 843 + "id": "3c95", 844 + "name": "Add skbedit action with queue_mapping", 845 + "category": [ 846 + "actions", 847 + "skbedit" 848 + ], 849 + "setup": [ 850 + [ 851 + "$TC actions flush action skbedit", 852 + 0, 853 + 1, 854 + 255 855 + ] 856 + ], 857 + "cmdUnderTest": "$TC actions add action skbedit queue_mapping 909", 858 + "expExitCode": "0", 859 + "verifyCmd": "$TC actions list action skbedit", 860 + "matchPattern": "action order [0-9]*: skbedit queue_mapping 909", 861 + "matchCount": "1", 862 + "teardown": [ 863 + "$TC actions flush action skbedit" 864 + ] 865 + }, 866 + { 867 + "id": "985c", 868 + "name": "Add skbedit action with invalid queue_mapping", 869 + "category": [ 870 + "actions", 871 + "skbedit" 872 + ], 873 + "setup": [ 874 + [ 875 + "$TC actions flush action skbedit", 876 + 0, 877 + 1, 878 + 255 879 + ] 880 + ], 881 + "cmdUnderTest": "$TC actions add action skbedit queue_mapping 67000", 882 + "expExitCode": "255", 883 + "verifyCmd": "$TC actions list action skbedit", 884 + "matchPattern": "action order [0-9]*: skbedit queue_mapping", 885 + "matchCount": "0", 886 + "teardown": [ 887 + "$TC actions flush action skbedit" 888 + ] 889 + }, 890 + { 891 + "id": "224f", 892 + "name": "Add skbedit action with ptype host", 893 + "category": [ 894 + "actions", 895 + "skbedit" 896 + ], 897 + "setup": [ 898 + [ 899 + "$TC actions flush action skbedit", 900 + 0, 901 + 1, 902 + 255 903 + ] 904 + ], 905 + "cmdUnderTest": "$TC actions add action skbedit ptype host", 906 + "expExitCode": "0", 907 + "verifyCmd": "$TC actions list action skbedit", 908 + "matchPattern": "action order [0-9]*: skbedit ptype host", 909 + "matchCount": "1", 910 + "teardown": [ 911 + "$TC actions flush action skbedit" 912 + ] 913 + }, 914 + { 915 + "id": "d1a3", 916 + "name": "Add skbedit action with ptype otherhost", 917 + "category": [ 918 + "actions", 919 + "skbedit" 920 + ], 921 + "setup": [ 922 + [ 923 + "$TC actions flush action skbedit", 924 + 0, 925 + 1, 926 + 255 927 + ] 928 + ], 929 + "cmdUnderTest": "$TC actions add action skbedit ptype otherhost", 930 + "expExitCode": "0", 931 + "verifyCmd": "$TC actions list action skbedit", 932 + "matchPattern": "action order [0-9]*: skbedit ptype otherhost", 933 + "matchCount": "1", 934 + "teardown": [ 935 + "$TC actions flush action skbedit" 936 + ] 937 + }, 938 + { 939 + "id": "b9c6", 940 + "name": "Add skbedit action with invalid ptype", 941 + "category": [ 942 + "actions", 943 + "skbedit" 944 + ], 945 + "setup": [ 946 + [ 947 + "$TC actions flush action skbedit", 948 + 0, 949 + 1, 950 + 255 951 + ] 952 + ], 953 + "cmdUnderTest": "$TC actions add action skbedit ptype openair", 954 + "expExitCode": "255", 955 + "verifyCmd": "$TC actions list action skbedit", 956 + "matchPattern": "action order [0-9]*: skbedit ptype openair", 957 + "matchCount": "0", 958 + "teardown": [ 959 + "$TC actions flush action skbedit" 960 + ] 961 + }, 962 + { 963 + "id": "5172", 964 + "name": "List skbedit actions", 965 + "category": [ 966 + "actions", 967 + "skbedit" 968 + ], 969 + "setup": [ 970 + [ 971 + "$TC actions flush action skbedit", 972 + 0, 973 + 1, 974 + 255 975 + ], 976 + "$TC actions add action skbedit ptype otherhost", 977 + "$TC actions add action skbedit ptype broadcast", 978 + "$TC actions add action skbedit mark 59", 979 + "$TC actions add action skbedit mark 409" 980 + ], 981 + "cmdUnderTest": "$TC actions list action skbedit", 982 + "expExitCode": "0", 983 + "verifyCmd": "$TC actions list action skbedit", 984 + "matchPattern": "action order [0-9]*: skbedit", 985 + "matchCount": "4", 986 + "teardown": [ 987 + "$TC actions flush action skbedit" 988 + ] 989 + }, 990 + { 991 + "id": "a6d6", 992 + "name": "Add skbedit action with index", 993 + "category": [ 994 + "actions", 995 + "skbedit" 996 + ], 997 + "setup": [ 998 + [ 999 + "$TC actions flush action skbedit", 1000 + 0, 1001 + 1, 1002 + 255 1003 + ] 1004 + ], 1005 + "cmdUnderTest": "$TC actions add action skbedit mark 808 index 4040404040", 1006 + "expExitCode": "0", 1007 + "verifyCmd": "$TC actions list action skbedit", 1008 + "matchPattern": "index 4040404040", 1009 + "matchCount": "1", 1010 + "teardown": [ 1011 + "$TC actions flush action skbedit" 1012 + ] 1013 + }, 1014 + { 1015 + "id": "38f3", 1016 + "name": "Delete skbedit action", 1017 + "category": [ 1018 + "actions", 1019 + "skbedit" 1020 + ], 1021 + "setup": [ 1022 + [ 1023 + "$TC actions flush action skbedit", 1024 + 0, 1025 + 1, 1026 + 255 1027 + ], 1028 + "$TC actions add action skbedit mark 42 index 9009" 1029 + ], 1030 + "cmdUnderTest": "$TC actions del action skbedit index 9009", 1031 + "expExitCode": "0", 1032 + "verifyCmd": "$TC actions list action skbedit", 1033 + "matchPattern": "action order [0-9]*: skbedit mark 42", 1034 + "matchCount": "0", 1035 + "teardown": [ 1036 + "$TC actions flush action skbedit" 1037 + ] 1038 + }, 1039 + { 1040 + "id": "ce97", 1041 + "name": "Flush skbedit actions", 1042 + "category": [ 1043 + "actions", 1044 + "skbedit" 1045 + ], 1046 + "setup": [ 1047 + "$TC actions add action skbedit mark 500", 1048 + "$TC actions add action skbedit mark 501", 1049 + "$TC actions add action skbedit mark 502", 1050 + "$TC actions add action skbedit mark 503", 1051 + "$TC actions add action skbedit mark 504", 1052 + "$TC actions add action skbedit mark 505", 1053 + "$TC actions add action skbedit mark 506" 1054 + ], 1055 + "cmdUnderTest": "$TC actions flush action skbedit", 1056 + "expExitCode": "0", 1057 + "verifyCmd": "$TC actions list action skbedit", 1058 + "matchPattern": "action order [0-9]*: skbedit", 1059 + "matchCount": "0", 1060 + "teardown": [ 1061 + "$TC actions flush action skbedit" 1062 + ] 1063 + }, 1064 + { 1065 + "id": "f02c", 1066 + "name": "Replace gact action", 1067 + "category": [ 1068 + "actions", 1069 + "gact" 1070 + ], 1071 + "setup": [ 1072 + [ 1073 + "$TC actions flush action gact", 1074 + 0, 1075 + 1, 1076 + 255 1077 + ], 1078 + "$TC actions add action drop index 10", 1079 + "$TC actions add action drop index 12" 1080 + ], 1081 + "cmdUnderTest": "$TC actions replace action ok index 12", 1082 + "expExitCode": "0", 1083 + "verifyCmd": "$TC actions ls action gact", 1084 + "matchPattern": "action order [0-9]*: gact action pass", 1085 + "matchCount": "1", 1086 + "teardown": [ 1087 + "$TC actions flush action gact" 1088 + ] 1089 + }, 1090 + { 1091 + "id": "525f", 1092 + "name": "Get gact action by index", 1093 + "category": [ 1094 + "actions", 1095 + "gact" 1096 + ], 1097 + "setup": [ 1098 + [ 1099 + "$TC actions flush action gact", 1100 + 0, 1101 + 1, 1102 + 255 1103 + ], 1104 + "$TC actions add action drop index 3900800700" 1105 + ], 1106 + "cmdUnderTest": "$TC actions get action gact index 3900800700", 1107 + "expExitCode": "0", 1108 + "verifyCmd": "$TC actions get action gact index 3900800700", 1109 + "matchPattern": "index 3900800700", 1110 + "matchCount": "1", 1111 + "teardown": [ 1112 + "$TC actions flush action gact" 1113 + ] 1114 + } 1115 + ]
+21
tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
··· 1 + [ 2 + { 3 + "id": "e9a3", 4 + "name": "Add u32 with source match", 5 + "category": [ 6 + "filter", 7 + "u32" 8 + ], 9 + "setup": [ 10 + "$TC qdisc add dev $DEV1 ingress" 11 + ], 12 + "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: protocol ip prio 1 u32 match ip src 127.0.0.1/32 flowid 1:1 action ok", 13 + "expExitCode": "0", 14 + "verifyCmd": "$TC filter show dev $DEV1 parent ffff:", 15 + "matchPattern": "match 7f000002/ffffffff at 12", 16 + "matchCount": "0", 17 + "teardown": [ 18 + "$TC qdisc del dev $DEV1 ingress" 19 + ] 20 + } 21 + ]
+413
tools/testing/selftests/tc-testing/tdc.py
··· 1 + #!/usr/bin/env python3 2 + 3 + """ 4 + tdc.py - Linux tc (Traffic Control) unit test driver 5 + 6 + Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com> 7 + """ 8 + 9 + import re 10 + import os 11 + import sys 12 + import argparse 13 + import json 14 + import subprocess 15 + from collections import OrderedDict 16 + from string import Template 17 + 18 + from tdc_config import * 19 + from tdc_helper import * 20 + 21 + 22 + USE_NS = True 23 + 24 + 25 + def replace_keywords(cmd): 26 + """ 27 + For a given executable command, substitute any known 28 + variables contained within NAMES with the correct values 29 + """ 30 + tcmd = Template(cmd) 31 + subcmd = tcmd.safe_substitute(NAMES) 32 + return subcmd 33 + 34 + 35 + def exec_cmd(command, nsonly=True): 36 + """ 37 + Perform any required modifications on an executable command, then run 38 + it in a subprocess and return the results. 39 + """ 40 + if (USE_NS and nsonly): 41 + command = 'ip netns exec $NS ' + command 42 + 43 + if '$' in command: 44 + command = replace_keywords(command) 45 + 46 + proc = subprocess.Popen(command, 47 + shell=True, 48 + stdout=subprocess.PIPE, 49 + stderr=subprocess.PIPE) 50 + (rawout, serr) = proc.communicate() 51 + 52 + if proc.returncode != 0: 53 + foutput = serr.decode("utf-8") 54 + else: 55 + foutput = rawout.decode("utf-8") 56 + 57 + proc.stdout.close() 58 + proc.stderr.close() 59 + return proc, foutput 60 + 61 + 62 + def prepare_env(cmdlist): 63 + """ 64 + Execute the setup/teardown commands for a test case. Optionally 65 + terminate test execution if the command fails. 66 + """ 67 + for cmdinfo in cmdlist: 68 + if (type(cmdinfo) == list): 69 + exit_codes = cmdinfo[1:] 70 + cmd = cmdinfo[0] 71 + else: 72 + exit_codes = [0] 73 + cmd = cmdinfo 74 + 75 + if (len(cmd) == 0): 76 + continue 77 + 78 + (proc, foutput) = exec_cmd(cmd) 79 + 80 + if proc.returncode not in exit_codes: 81 + print 82 + print("Could not execute:") 83 + print(cmd) 84 + print("\nError message:") 85 + print(foutput) 86 + print("\nAborting test run.") 87 + ns_destroy() 88 + exit(1) 89 + 90 + 91 + def test_runner(filtered_tests): 92 + """ 93 + Driver function for the unit tests. 94 + 95 + Prints information about the tests being run, executes the setup and 96 + teardown commands and the command under test itself. Also determines 97 + success/failure based on the information in the test case and generates 98 + TAP output accordingly. 99 + """ 100 + testlist = filtered_tests 101 + tcount = len(testlist) 102 + index = 1 103 + tap = str(index) + ".." + str(tcount) + "\n" 104 + 105 + for tidx in testlist: 106 + result = True 107 + tresult = "" 108 + print("Test " + tidx["id"] + ": " + tidx["name"]) 109 + prepare_env(tidx["setup"]) 110 + (p, procout) = exec_cmd(tidx["cmdUnderTest"]) 111 + exit_code = p.returncode 112 + 113 + if (exit_code != int(tidx["expExitCode"])): 114 + result = False 115 + print("exit:", exit_code, int(tidx["expExitCode"])) 116 + print(procout) 117 + else: 118 + match_pattern = re.compile(str(tidx["matchPattern"]), re.DOTALL) 119 + (p, procout) = exec_cmd(tidx["verifyCmd"]) 120 + match_index = re.findall(match_pattern, procout) 121 + if len(match_index) != int(tidx["matchCount"]): 122 + result = False 123 + 124 + if result == True: 125 + tresult += "ok " 126 + else: 127 + tresult += "not ok " 128 + tap += tresult + str(index) + " " + tidx["id"] + " " + tidx["name"] + "\n" 129 + 130 + if result == False: 131 + tap += procout 132 + 133 + prepare_env(tidx["teardown"]) 134 + index += 1 135 + 136 + return tap 137 + 138 + 139 + def ns_create(): 140 + """ 141 + Create the network namespace in which the tests will be run and set up 142 + the required network devices for it. 143 + """ 144 + if (USE_NS): 145 + cmd = 'ip netns add $NS' 146 + exec_cmd(cmd, False) 147 + cmd = 'ip link add $DEV0 type veth peer name $DEV1' 148 + exec_cmd(cmd, False) 149 + cmd = 'ip link set $DEV1 netns $NS' 150 + exec_cmd(cmd, False) 151 + cmd = 'ip link set $DEV0 up' 152 + exec_cmd(cmd, False) 153 + cmd = 'ip -s $NS link set $DEV1 up' 154 + exec_cmd(cmd, False) 155 + 156 + 157 + def ns_destroy(): 158 + """ 159 + Destroy the network namespace for testing (and any associated network 160 + devices as well) 161 + """ 162 + if (USE_NS): 163 + cmd = 'ip netns delete $NS' 164 + exec_cmd(cmd, False) 165 + 166 + 167 + def has_blank_ids(idlist): 168 + """ 169 + Search the list for empty ID fields and return true/false accordingly. 170 + """ 171 + return not(all(k for k in idlist)) 172 + 173 + 174 + def load_from_file(filename): 175 + """ 176 + Open the JSON file containing the test cases and return them as an 177 + ordered dictionary object. 178 + """ 179 + with open(filename) as test_data: 180 + testlist = json.load(test_data, object_pairs_hook=OrderedDict) 181 + idlist = get_id_list(testlist) 182 + if (has_blank_ids(idlist)): 183 + for k in testlist: 184 + k['filename'] = filename 185 + return testlist 186 + 187 + 188 + def args_parse(): 189 + """ 190 + Create the argument parser. 191 + """ 192 + parser = argparse.ArgumentParser(description='Linux TC unit tests') 193 + return parser 194 + 195 + 196 + def set_args(parser): 197 + """ 198 + Set the command line arguments for tdc. 199 + """ 200 + parser.add_argument('-p', '--path', type=str, 201 + help='The full path to the tc executable to use') 202 + parser.add_argument('-c', '--category', type=str, nargs='?', const='+c', 203 + help='Run tests only from the specified category, or if no category is specified, list known categories.') 204 + parser.add_argument('-f', '--file', type=str, 205 + help='Run tests from the specified file') 206 + parser.add_argument('-l', '--list', type=str, nargs='?', const="", metavar='CATEGORY', 207 + help='List all test cases, or those only within the specified category') 208 + parser.add_argument('-s', '--show', type=str, nargs=1, metavar='ID', dest='showID', 209 + help='Display the test case with specified id') 210 + parser.add_argument('-e', '--execute', type=str, nargs=1, metavar='ID', 211 + help='Execute the single test case with specified ID') 212 + parser.add_argument('-i', '--id', action='store_true', dest='gen_id', 213 + help='Generate ID numbers for new test cases') 214 + return parser 215 + return parser 216 + 217 + 218 + def check_default_settings(args): 219 + """ 220 + Process any arguments overriding the default settings, and ensure the 221 + settings are correct. 222 + """ 223 + # Allow for overriding specific settings 224 + global NAMES 225 + 226 + if args.path != None: 227 + NAMES['TC'] = args.path 228 + if not os.path.isfile(NAMES['TC']): 229 + print("The specified tc path " + NAMES['TC'] + " does not exist.") 230 + exit(1) 231 + 232 + 233 + def get_id_list(alltests): 234 + """ 235 + Generate a list of all IDs in the test cases. 236 + """ 237 + return [x["id"] for x in alltests] 238 + 239 + 240 + def check_case_id(alltests): 241 + """ 242 + Check for duplicate test case IDs. 243 + """ 244 + idl = get_id_list(alltests) 245 + return [x for x in idl if idl.count(x) > 1] 246 + 247 + 248 + def does_id_exist(alltests, newid): 249 + """ 250 + Check if a given ID already exists in the list of test cases. 251 + """ 252 + idl = get_id_list(alltests) 253 + return (any(newid == x for x in idl)) 254 + 255 + 256 + def generate_case_ids(alltests): 257 + """ 258 + If a test case has a blank ID field, generate a random hex ID for it 259 + and then write the test cases back to disk. 260 + """ 261 + import random 262 + for c in alltests: 263 + if (c["id"] == ""): 264 + while True: 265 + newid = str('%04x' % random.randrange(16**4)) 266 + if (does_id_exist(alltests, newid)): 267 + continue 268 + else: 269 + c['id'] = newid 270 + break 271 + 272 + ufilename = [] 273 + for c in alltests: 274 + if ('filename' in c): 275 + ufilename.append(c['filename']) 276 + ufilename = get_unique_item(ufilename) 277 + for f in ufilename: 278 + testlist = [] 279 + for t in alltests: 280 + if 'filename' in t: 281 + if t['filename'] == f: 282 + del t['filename'] 283 + testlist.append(t) 284 + outfile = open(f, "w") 285 + json.dump(testlist, outfile, indent=4) 286 + outfile.close() 287 + 288 + 289 + def get_test_cases(args): 290 + """ 291 + If a test case file is specified, retrieve tests from that file. 292 + Otherwise, glob for all json files in subdirectories and load from 293 + each one. 294 + """ 295 + import fnmatch 296 + if args.file != None: 297 + if not os.path.isfile(args.file): 298 + print("The specified test case file " + args.file + " does not exist.") 299 + exit(1) 300 + flist = [args.file] 301 + else: 302 + flist = [] 303 + for root, dirnames, filenames in os.walk('tc-tests'): 304 + for filename in fnmatch.filter(filenames, '*.json'): 305 + flist.append(os.path.join(root, filename)) 306 + alltests = list() 307 + for casefile in flist: 308 + alltests = alltests + (load_from_file(casefile)) 309 + return alltests 310 + 311 + 312 + def set_operation_mode(args): 313 + """ 314 + Load the test case data and process remaining arguments to determine 315 + what the script should do for this run, and call the appropriate 316 + function. 317 + """ 318 + alltests = get_test_cases(args) 319 + 320 + if args.gen_id: 321 + idlist = get_id_list(alltests) 322 + if (has_blank_ids(idlist)): 323 + alltests = generate_case_ids(alltests) 324 + else: 325 + print("No empty ID fields found in test files.") 326 + exit(0) 327 + 328 + duplicate_ids = check_case_id(alltests) 329 + if (len(duplicate_ids) > 0): 330 + print("The following test case IDs are not unique:") 331 + print(str(set(duplicate_ids))) 332 + print("Please correct them before continuing.") 333 + exit(1) 334 + 335 + ucat = get_test_categories(alltests) 336 + 337 + if args.showID: 338 + show_test_case_by_id(alltests, args.showID[0]) 339 + exit(0) 340 + 341 + if args.execute: 342 + target_id = args.execute[0] 343 + else: 344 + target_id = "" 345 + 346 + if args.category: 347 + if (args.category == '+c'): 348 + print("Available categories:") 349 + print_sll(ucat) 350 + exit(0) 351 + else: 352 + target_category = args.category 353 + else: 354 + target_category = "" 355 + 356 + 357 + testcases = get_categorized_testlist(alltests, ucat) 358 + 359 + if args.list: 360 + if (len(args.list) == 0): 361 + list_test_cases(alltests) 362 + exit(0) 363 + elif(len(args.list > 0)): 364 + if (args.list not in ucat): 365 + print("Unknown category " + args.list) 366 + print("Available categories:") 367 + print_sll(ucat) 368 + exit(1) 369 + list_test_cases(testcases[args.list]) 370 + exit(0) 371 + 372 + if (os.geteuid() != 0): 373 + print("This script must be run with root privileges.\n") 374 + exit(1) 375 + 376 + ns_create() 377 + 378 + if (len(target_category) == 0): 379 + if (len(target_id) > 0): 380 + alltests = list(filter(lambda x: target_id in x['id'], alltests)) 381 + if (len(alltests) == 0): 382 + print("Cannot find a test case with ID matching " + target_id) 383 + exit(1) 384 + catresults = test_runner(alltests) 385 + print("All test results: " + "\n\n" + catresults) 386 + elif (len(target_category) > 0): 387 + if (target_category not in ucat): 388 + print("Specified category is not present in this file.") 389 + exit(1) 390 + else: 391 + catresults = test_runner(testcases[target_category]) 392 + print("Category " + target_category + "\n\n" + catresults) 393 + 394 + ns_destroy() 395 + 396 + 397 + def main(): 398 + """ 399 + Start of execution; set up argument parser and get the arguments, 400 + and start operations. 401 + """ 402 + parser = args_parse() 403 + parser = set_args(parser) 404 + (args, remaining) = parser.parse_known_args() 405 + check_default_settings(args) 406 + 407 + set_operation_mode(args) 408 + 409 + exit(0) 410 + 411 + 412 + if __name__ == "__main__": 413 + main()
+17
tools/testing/selftests/tc-testing/tdc_config.py
··· 1 + """ 2 + tdc_config.py - tdc user-specified values 3 + 4 + Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com> 5 + """ 6 + 7 + # Dictionary containing all values that can be substituted in executable 8 + # commands. 9 + NAMES = { 10 + # Substitute your own tc path here 11 + 'TC': '/sbin/tc', 12 + # Name of veth devices to be created for the namespace 13 + 'DEV0': 'v0p0', 14 + 'DEV1': 'v0p1', 15 + # Name of the namespace to use 16 + 'NS': 'tcut' 17 + }
+75
tools/testing/selftests/tc-testing/tdc_helper.py
··· 1 + """ 2 + tdc_helper.py - tdc helper functions 3 + 4 + Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com> 5 + """ 6 + 7 + def get_categorized_testlist(alltests, ucat): 8 + """ Sort the master test list into categories. """ 9 + testcases = dict() 10 + 11 + for category in ucat: 12 + testcases[category] = list(filter(lambda x: category in x['category'], alltests)) 13 + 14 + return(testcases) 15 + 16 + 17 + def get_unique_item(lst): 18 + """ For a list, return a set of the unique items in the list. """ 19 + return list(set(lst)) 20 + 21 + 22 + def get_test_categories(alltests): 23 + """ Discover all unique test categories present in the test case file. """ 24 + ucat = [] 25 + for t in alltests: 26 + ucat.extend(get_unique_item(t['category'])) 27 + ucat = get_unique_item(ucat) 28 + return ucat 29 + 30 + def list_test_cases(testlist): 31 + """ Print IDs and names of all test cases. """ 32 + for curcase in testlist: 33 + print(curcase['id'] + ': (' + ', '.join(curcase['category']) + ") " + curcase['name']) 34 + 35 + 36 + def list_categories(testlist): 37 + """ Show all categories that are present in a test case file. """ 38 + categories = set(map(lambda x: x['category'], testlist)) 39 + print("Available categories:") 40 + print(", ".join(str(s) for s in categories)) 41 + print("") 42 + 43 + 44 + def print_list(cmdlist): 45 + """ Print a list of strings prepended with a tab. """ 46 + for l in cmdlist: 47 + if (type(l) == list): 48 + print("\t" + str(l[0])) 49 + else: 50 + print("\t" + str(l)) 51 + 52 + 53 + def print_sll(items): 54 + print("\n".join(str(s) for s in items)) 55 + 56 + 57 + def print_test_case(tcase): 58 + """ Pretty-printing of a given test case. """ 59 + for k in tcase.keys(): 60 + if (type(tcase[k]) == list): 61 + print(k + ":") 62 + print_list(tcase[k]) 63 + else: 64 + print(k + ": " + tcase[k]) 65 + 66 + 67 + def show_test_case_by_id(testlist, caseID): 68 + """ Find the specified test case to pretty-print. """ 69 + if not any(d.get('id', None) == caseID for d in testlist): 70 + print("That ID does not exist.") 71 + exit(1) 72 + else: 73 + print_test_case(next((d for d in testlist if d['id'] == caseID))) 74 + 75 +