tdc.py (10a558374f3751cf4eb55143008975641dfc2cf4) tdc.py (f87c7f646c6f704b29504d63c4ab965584c4aacb)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3
4"""
5tdc.py - Linux tc (Traffic Control) unit test driver
6
7Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com>
8"""

--- 195 unchanged lines hidden (view full) ---

204 parser = argparse.ArgumentParser(description='Linux TC unit tests')
205 return parser
206
207
208def set_args(parser):
209 """
210 Set the command line arguments for tdc.
211 """
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3
4"""
5tdc.py - Linux tc (Traffic Control) unit test driver
6
7Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com>
8"""

--- 195 unchanged lines hidden (view full) ---

204 parser = argparse.ArgumentParser(description='Linux TC unit tests')
205 return parser
206
207
208def set_args(parser):
209 """
210 Set the command line arguments for tdc.
211 """
212 parser.add_argument('-p', '--path', type=str,
213 help='The full path to the tc executable to use')
214 parser.add_argument('-c', '--category', type=str, nargs='?', const='+c',
215 help='Run tests only from the specified category, or if no category is specified, list known categories.')
216 parser.add_argument('-f', '--file', type=str,
217 help='Run tests from the specified file')
218 parser.add_argument('-l', '--list', type=str, nargs='?', const="++", metavar='CATEGORY',
219 help='List all test cases, or those only within the specified category')
220 parser.add_argument('-s', '--show', type=str, nargs=1, metavar='ID', dest='showID',
221 help='Display the test case with specified id')
222 parser.add_argument('-e', '--execute', type=str, nargs=1, metavar='ID',
223 help='Execute the single test case with specified ID')
224 parser.add_argument('-i', '--id', action='store_true', dest='gen_id',
225 help='Generate ID numbers for new test cases')
212 parser.add_argument(
213 '-p', '--path', type=str,
214 help='The full path to the tc executable to use')
215 sg = parser.add_argument_group(
216 'selection', 'select which test cases: ' +
217 'files plus directories; filtered by categories plus testids')
218 ag = parser.add_argument_group(
219 'action', 'select action to perform on selected test cases')
220
221 sg.add_argument(
222 '-D', '--directory', nargs='+', metavar='DIR',
223 help='Collect tests from the specified directory(ies) ' +
224 '(default [tc-tests])')
225 sg.add_argument(
226 '-f', '--file', nargs='+', metavar='FILE',
227 help='Run tests from the specified file(s)')
228 sg.add_argument(
229 '-c', '--category', nargs='*', metavar='CATG', default=['+c'],
230 help='Run tests only from the specified category/ies, ' +
231 'or if no category/ies is/are specified, list known categories.')
232 sg.add_argument(
233 '-e', '--execute', nargs='+', metavar='ID',
234 help='Execute the specified test cases with specified IDs')
235 ag.add_argument(
236 '-l', '--list', action='store_true',
237 help='List all test cases, or those only within the specified category')
238 ag.add_argument(
239 '-s', '--show', action='store_true', dest='showID',
240 help='Display the selected test cases')
241 ag.add_argument(
242 '-i', '--id', action='store_true', dest='gen_id',
243 help='Generate ID numbers for new test cases')
244 parser.add_argument(
245 '-v', '--verbose', action='count', default=0,
246 help='Show the commands that are being run')
226 parser.add_argument('-d', '--device',
227 help='Execute the test case in flower category')
228 return parser
229
230
231def check_default_settings(args):
232 """
233 Process any arguments overriding the default settings, and ensure the

--- 18 unchanged lines hidden (view full) ---

252 return [x["id"] for x in alltests]
253
254
255def check_case_id(alltests):
256 """
257 Check for duplicate test case IDs.
258 """
259 idl = get_id_list(alltests)
247 parser.add_argument('-d', '--device',
248 help='Execute the test case in flower category')
249 return parser
250
251
252def check_default_settings(args):
253 """
254 Process any arguments overriding the default settings, and ensure the

--- 18 unchanged lines hidden (view full) ---

273 return [x["id"] for x in alltests]
274
275
276def check_case_id(alltests):
277 """
278 Check for duplicate test case IDs.
279 """
280 idl = get_id_list(alltests)
281 # print('check_case_id: idl is {}'.format(idl))
282 # answer = list()
283 # for x in idl:
284 # print('Looking at {}'.format(x))
285 # print('what the heck is idl.count(x)??? {}'.format(idl.count(x)))
286 # if idl.count(x) > 1:
287 # answer.append(x)
288 # print(' ... append it {}'.format(x))
260 return [x for x in idl if idl.count(x) > 1]
289 return [x for x in idl if idl.count(x) > 1]
290 return answer
261
262
263def does_id_exist(alltests, newid):
264 """
265 Check if a given ID already exists in the list of test cases.
266 """
267 idl = get_id_list(alltests)
268 return (any(newid == x for x in idl))

--- 26 unchanged lines hidden (view full) ---

295 if 'filename' in t:
296 if t['filename'] == f:
297 del t['filename']
298 testlist.append(t)
299 outfile = open(f, "w")
300 json.dump(testlist, outfile, indent=4)
301 outfile.close()
302
291
292
293def does_id_exist(alltests, newid):
294 """
295 Check if a given ID already exists in the list of test cases.
296 """
297 idl = get_id_list(alltests)
298 return (any(newid == x for x in idl))

--- 26 unchanged lines hidden (view full) ---

325 if 'filename' in t:
326 if t['filename'] == f:
327 del t['filename']
328 testlist.append(t)
329 outfile = open(f, "w")
330 json.dump(testlist, outfile, indent=4)
331 outfile.close()
332
333def filter_tests_by_id(args, testlist):
334 '''
335 Remove tests from testlist that are not in the named id list.
336 If id list is empty, return empty list.
337 '''
338 newlist = list()
339 if testlist and args.execute:
340 target_ids = args.execute
303
341
342 if isinstance(target_ids, list) and (len(target_ids) > 0):
343 newlist = list(filter(lambda x: x['id'] in target_ids, testlist))
344 return newlist
345
346def filter_tests_by_category(args, testlist):
347 '''
348 Remove tests from testlist that are not in a named category.
349 '''
350 answer = list()
351 if args.category and testlist:
352 test_ids = list()
353 for catg in set(args.category):
354 if catg == '+c':
355 continue
356 print('considering category {}'.format(catg))
357 for tc in testlist:
358 if catg in tc['category'] and tc['id'] not in test_ids:
359 answer.append(tc)
360 test_ids.append(tc['id'])
361
362 return answer
363
304def get_test_cases(args):
305 """
306 If a test case file is specified, retrieve tests from that file.
307 Otherwise, glob for all json files in subdirectories and load from
308 each one.
364def get_test_cases(args):
365 """
366 If a test case file is specified, retrieve tests from that file.
367 Otherwise, glob for all json files in subdirectories and load from
368 each one.
369 Also, if requested, filter by category, and add tests matching
370 certain ids.
309 """
310 import fnmatch
371 """
372 import fnmatch
311 if args.file != None:
312 if not os.path.isfile(args.file):
313 print("The specified test case file " + args.file + " does not exist.")
314 exit(1)
315 flist = [args.file]
316 else:
317 flist = []
318 for root, dirnames, filenames in os.walk('tc-tests'):
373
374 flist = []
375 testdirs = ['tc-tests']
376
377 if args.file:
378 # at least one file was specified - remove the default directory
379 testdirs = []
380
381 for ff in args.file:
382 if not os.path.isfile(ff):
383 print("IGNORING file " + ff + " \n\tBECAUSE does not exist.")
384 else:
385 flist.append(os.path.abspath(ff))
386
387 if args.directory:
388 testdirs = args.directory
389
390 for testdir in testdirs:
391 for root, dirnames, filenames in os.walk(testdir):
319 for filename in fnmatch.filter(filenames, '*.json'):
392 for filename in fnmatch.filter(filenames, '*.json'):
320 flist.append(os.path.join(root, filename))
321 alltests = list()
393 candidate = os.path.abspath(os.path.join(root, filename))
394 if candidate not in testdirs:
395 flist.append(candidate)
396
397 alltestcases = list()
322 for casefile in flist:
398 for casefile in flist:
323 alltests = alltests + (load_from_file(casefile))
324 return alltests
399 alltestcases = alltestcases + (load_from_file(casefile))
325
400
401 allcatlist = get_test_categories(alltestcases)
402 allidlist = get_id_list(alltestcases)
326
403
404 testcases_by_cats = get_categorized_testlist(alltestcases, allcatlist)
405 idtestcases = filter_tests_by_id(args, alltestcases)
406 cattestcases = filter_tests_by_category(args, alltestcases)
407
408 cat_ids = [x['id'] for x in cattestcases]
409 if args.execute:
410 if args.category:
411 alltestcases = cattestcases + [x for x in idtestcases if x['id'] not in cat_ids]
412 else:
413 alltestcases = idtestcases
414 else:
415 if cat_ids:
416 alltestcases = cattestcases
417 else:
418 # just accept the existing value of alltestcases,
419 # which has been filtered by file/directory
420 pass
421
422 return allcatlist, allidlist, testcases_by_cats, alltestcases
423
424
327def set_operation_mode(args):
328 """
329 Load the test case data and process remaining arguments to determine
330 what the script should do for this run, and call the appropriate
331 function.
332 """
425def set_operation_mode(args):
426 """
427 Load the test case data and process remaining arguments to determine
428 what the script should do for this run, and call the appropriate
429 function.
430 """
333 alltests = get_test_cases(args)
431 ucat, idlist, testcases, alltests = get_test_cases(args)
334
335 if args.gen_id:
432
433 if args.gen_id:
336 idlist = get_id_list(alltests)
337 if (has_blank_ids(idlist)):
338 alltests = generate_case_ids(alltests)
339 else:
340 print("No empty ID fields found in test files.")
341 exit(0)
342
343 duplicate_ids = check_case_id(alltests)
344 if (len(duplicate_ids) > 0):
345 print("The following test case IDs are not unique:")
346 print(str(set(duplicate_ids)))
347 print("Please correct them before continuing.")
348 exit(1)
349
434 if (has_blank_ids(idlist)):
435 alltests = generate_case_ids(alltests)
436 else:
437 print("No empty ID fields found in test files.")
438 exit(0)
439
440 duplicate_ids = check_case_id(alltests)
441 if (len(duplicate_ids) > 0):
442 print("The following test case IDs are not unique:")
443 print(str(set(duplicate_ids)))
444 print("Please correct them before continuing.")
445 exit(1)
446
350 ucat = get_test_categories(alltests)
351
352 if args.showID:
447 if args.showID:
353 show_test_case_by_id(alltests, args.showID[0])
448 for atest in alltests:
449 print_test_case(atest)
354 exit(0)
355
450 exit(0)
451
356 if args.execute:
357 target_id = args.execute[0]
358 else:
359 target_id = ""
452 if isinstance(args.category, list) and (len(args.category) == 0):
453 print("Available categories:")
454 print_sll(ucat)
455 exit(0)
360
456
361 if args.category:
362 if (args.category == '+c'):
363 print("Available categories:")
364 print_sll(ucat)
365 exit(0)
366 else:
367 target_category = args.category
368 else:
369 target_category = ""
370
371
372 testcases = get_categorized_testlist(alltests, ucat)
373
374 if args.list:
457 if args.list:
375 if (args.list == "++"):
458 if args.list:
376 list_test_cases(alltests)
377 exit(0)
459 list_test_cases(alltests)
460 exit(0)
378 elif(len(args.list) > 0):
379 if (args.list not in ucat):
380 print("Unknown category " + args.list)
381 print("Available categories:")
382 print_sll(ucat)
383 exit(1)
384 list_test_cases(testcases[args.list])
385 exit(0)
386
387 if (os.geteuid() != 0):
388 print("This script must be run with root privileges.\n")
389 exit(1)
390
391 ns_create()
392
461
462 if (os.geteuid() != 0):
463 print("This script must be run with root privileges.\n")
464 exit(1)
465
466 ns_create()
467
393 if (len(target_category) == 0):
394 if (len(target_id) > 0):
395 alltests = list(filter(lambda x: target_id in x['id'], alltests))
396 if (len(alltests) == 0):
397 print("Cannot find a test case with ID matching " + target_id)
398 exit(1)
399 catresults = test_runner(alltests, args)
400 print("All test results: " + "\n\n" + catresults)
401 elif (len(target_category) > 0):
402 if (target_category == "flower") and args.device == None:
403 print("Please specify a NIC device (-d) to run category flower")
404 exit(1)
405 if (target_category not in ucat):
406 print("Specified category is not present in this file.")
407 exit(1)
408 else:
409 catresults = test_runner(testcases[target_category], args)
410 print("Category " + target_category + "\n\n" + catresults)
468 catresults = test_runner(alltests, args)
469 print('All test results: \n\n{}'.format(catresults))
411
412 ns_destroy()
413
414
415def main():
416 """
417 Start of execution; set up argument parser and get the arguments,
418 and start operations.

--- 13 unchanged lines hidden ---
470
471 ns_destroy()
472
473
474def main():
475 """
476 Start of execution; set up argument parser and get the arguments,
477 and start operations.

--- 13 unchanged lines hidden ---