tdc.py (2a267e7c41aa88215de2b542de797d03d16ecdfd) tdc.py (489ce2f42514b4324e5c63e93ae7570cab995254)
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"""

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

20from string import Template
21
22from tdc_config import *
23from tdc_helper import *
24
25import TdcPlugin
26from TdcResults import *
27
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"""

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

20from string import Template
21
22from tdc_config import *
23from tdc_helper import *
24
25import TdcPlugin
26from TdcResults import *
27
28class PluginDependencyException(Exception):
29 def __init__(self, missing_pg):
30 self.missing_pg = missing_pg
28
29class PluginMgrTestFail(Exception):
30 def __init__(self, stage, output, message):
31 self.stage = stage
32 self.output = output
33 self.message = message
34
35class PluginMgr:
36 def __init__(self, argparser):
37 super().__init__()
38 self.plugins = {}
39 self.plugin_instances = []
31
32class PluginMgrTestFail(Exception):
33 def __init__(self, stage, output, message):
34 self.stage = stage
35 self.output = output
36 self.message = message
37
38class PluginMgr:
39 def __init__(self, argparser):
40 super().__init__()
41 self.plugins = {}
42 self.plugin_instances = []
40 self.args = []
43 self.failed_plugins = {}
41 self.argparser = argparser
42
43 # TODO, put plugins in order
44 plugindir = os.getenv('TDC_PLUGIN_DIR', './plugins')
45 for dirpath, dirnames, filenames in os.walk(plugindir):
46 for fn in filenames:
47 if (fn.endswith('.py') and
48 not fn == '__init__.py' and
49 not fn.startswith('#') and
50 not fn.startswith('.#')):
51 mn = fn[0:-3]
52 foo = importlib.import_module('plugins.' + mn)
53 self.plugins[mn] = foo
54 self.plugin_instances.append(foo.SubPlugin())
55
44 self.argparser = argparser
45
46 # TODO, put plugins in order
47 plugindir = os.getenv('TDC_PLUGIN_DIR', './plugins')
48 for dirpath, dirnames, filenames in os.walk(plugindir):
49 for fn in filenames:
50 if (fn.endswith('.py') and
51 not fn == '__init__.py' and
52 not fn.startswith('#') and
53 not fn.startswith('.#')):
54 mn = fn[0:-3]
55 foo = importlib.import_module('plugins.' + mn)
56 self.plugins[mn] = foo
57 self.plugin_instances.append(foo.SubPlugin())
58
59 def load_plugin(self, pgdir, pgname):
60 pgname = pgname[0:-3]
61 foo = importlib.import_module('{}.{}'.format(pgdir, pgname))
62 self.plugins[pgname] = foo
63 self.plugin_instances.append(foo.SubPlugin())
64 self.plugin_instances[-1].check_args(self.args, None)
65
66 def get_required_plugins(self, testlist):
67 '''
68 Get all required plugins from the list of test cases and return
69 all unique items.
70 '''
71 reqs = []
72 for t in testlist:
73 try:
74 if 'requires' in t['plugins']:
75 if isinstance(t['plugins']['requires'], list):
76 reqs.extend(t['plugins']['requires'])
77 else:
78 reqs.append(t['plugins']['requires'])
79 except KeyError:
80 continue
81 reqs = get_unique_item(reqs)
82 return reqs
83
84 def load_required_plugins(self, reqs, parser, args, remaining):
85 '''
86 Get all required plugins from the list of test cases and load any plugin
87 that is not already enabled.
88 '''
89 pgd = ['plugin-lib', 'plugin-lib-custom']
90 pnf = []
91
92 for r in reqs:
93 if r not in self.plugins:
94 fname = '{}.py'.format(r)
95 source_path = []
96 for d in pgd:
97 pgpath = '{}/{}'.format(d, fname)
98 if os.path.isfile(pgpath):
99 source_path.append(pgpath)
100 if len(source_path) == 0:
101 print('ERROR: unable to find required plugin {}'.format(r))
102 pnf.append(fname)
103 continue
104 elif len(source_path) > 1:
105 print('WARNING: multiple copies of plugin {} found, using version found')
106 print('at {}'.format(source_path[0]))
107 pgdir = source_path[0]
108 pgdir = pgdir.split('/')[0]
109 self.load_plugin(pgdir, fname)
110 if len(pnf) > 0:
111 raise PluginDependencyException(pnf)
112
113 parser = self.call_add_args(parser)
114 (args, remaining) = parser.parse_known_args(args=remaining, namespace=args)
115 return args
116
56 def call_pre_suite(self, testcount, testidlist):
57 for pgn_inst in self.plugin_instances:
58 pgn_inst.pre_suite(testcount, testidlist)
59
60 def call_post_suite(self, index):
61 for pgn_inst in reversed(self.plugin_instances):
62 pgn_inst.post_suite(index)
63

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

93 for pgn_inst in self.plugin_instances:
94 pgn_inst.check_args(args, remaining)
95
96 def call_adjust_command(self, stage, command):
97 for pgn_inst in self.plugin_instances:
98 command = pgn_inst.adjust_command(stage, command)
99 return command
100
117 def call_pre_suite(self, testcount, testidlist):
118 for pgn_inst in self.plugin_instances:
119 pgn_inst.pre_suite(testcount, testidlist)
120
121 def call_post_suite(self, index):
122 for pgn_inst in reversed(self.plugin_instances):
123 pgn_inst.post_suite(index)
124

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

154 for pgn_inst in self.plugin_instances:
155 pgn_inst.check_args(args, remaining)
156
157 def call_adjust_command(self, stage, command):
158 for pgn_inst in self.plugin_instances:
159 command = pgn_inst.adjust_command(stage, command)
160 return command
161
162 def set_args(self, args):
163 self.args = args
164
101 @staticmethod
102 def _make_argparser(args):
103 self.argparser = argparse.ArgumentParser(
104 description='Linux TC unit tests')
105
106def replace_keywords(cmd):
107 """
108 For a given executable command, substitute any known

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

545 print('considering category {}'.format(catg))
546 for tc in testlist:
547 if catg in tc['category'] and tc['id'] not in test_ids:
548 answer.append(tc)
549 test_ids.append(tc['id'])
550
551 return answer
552
165 @staticmethod
166 def _make_argparser(args):
167 self.argparser = argparse.ArgumentParser(
168 description='Linux TC unit tests')
169
170def replace_keywords(cmd):
171 """
172 For a given executable command, substitute any known

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

609 print('considering category {}'.format(catg))
610 for tc in testlist:
611 if catg in tc['category'] and tc['id'] not in test_ids:
612 answer.append(tc)
613 test_ids.append(tc['id'])
614
615 return answer
616
617
553def get_test_cases(args):
554 """
555 If a test case file is specified, retrieve tests from that file.
556 Otherwise, glob for all json files in subdirectories and load from
557 each one.
558 Also, if requested, filter by category, and add tests matching
559 certain ids.
560 """

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

606 else:
607 # just accept the existing value of alltestcases,
608 # which has been filtered by file/directory
609 pass
610
611 return allcatlist, allidlist, testcases_by_cats, alltestcases
612
613
618def get_test_cases(args):
619 """
620 If a test case file is specified, retrieve tests from that file.
621 Otherwise, glob for all json files in subdirectories and load from
622 each one.
623 Also, if requested, filter by category, and add tests matching
624 certain ids.
625 """

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

671 else:
672 # just accept the existing value of alltestcases,
673 # which has been filtered by file/directory
674 pass
675
676 return allcatlist, allidlist, testcases_by_cats, alltestcases
677
678
614def set_operation_mode(pm, args):
679def set_operation_mode(pm, parser, args, remaining):
615 """
616 Load the test case data and process remaining arguments to determine
617 what the script should do for this run, and call the appropriate
618 function.
619 """
620 ucat, idlist, testcases, alltests = get_test_cases(args)
621
622 if args.gen_id:

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

644 exit(0)
645
646 if args.list:
647 if args.list:
648 list_test_cases(alltests)
649 exit(0)
650
651 if len(alltests):
680 """
681 Load the test case data and process remaining arguments to determine
682 what the script should do for this run, and call the appropriate
683 function.
684 """
685 ucat, idlist, testcases, alltests = get_test_cases(args)
686
687 if args.gen_id:

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

709 exit(0)
710
711 if args.list:
712 if args.list:
713 list_test_cases(alltests)
714 exit(0)
715
716 if len(alltests):
717 req_plugins = pm.get_required_plugins(alltests)
718 try:
719 args = pm.load_required_plugins(req_plugins, parser, args, remaining)
720 except PluginDependencyException as pde:
721 print('The following plugins were not found:')
722 print('{}'.format(pde.missing_pg))
652 catresults = test_runner(pm, args, alltests)
653 if args.format == 'none':
654 print('Test results output suppression requested\n')
655 else:
656 print('\nAll test results: \n')
657 if args.format == 'xunit':
658 suffix = 'xml'
659 res = catresults.format_xunit()

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

681 and start operations.
682 """
683 parser = args_parse()
684 parser = set_args(parser)
685 pm = PluginMgr(parser)
686 parser = pm.call_add_args(parser)
687 (args, remaining) = parser.parse_known_args()
688 args.NAMES = NAMES
723 catresults = test_runner(pm, args, alltests)
724 if args.format == 'none':
725 print('Test results output suppression requested\n')
726 else:
727 print('\nAll test results: \n')
728 if args.format == 'xunit':
729 suffix = 'xml'
730 res = catresults.format_xunit()

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

752 and start operations.
753 """
754 parser = args_parse()
755 parser = set_args(parser)
756 pm = PluginMgr(parser)
757 parser = pm.call_add_args(parser)
758 (args, remaining) = parser.parse_known_args()
759 args.NAMES = NAMES
760 pm.set_args(args)
689 check_default_settings(args, remaining, pm)
690 if args.verbose > 2:
691 print('args is {}'.format(args))
692
761 check_default_settings(args, remaining, pm)
762 if args.verbose > 2:
763 print('args is {}'.format(args))
764
693 set_operation_mode(pm, args)
765 set_operation_mode(pm, parser, args, remaining)
694
695 exit(0)
696
697
698if __name__ == "__main__":
699 main()
766
767 exit(0)
768
769
770if __name__ == "__main__":
771 main()