blob: 2abe353d2739ca817d2deabb054a470d29cd5973 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001## Copyright (C) 2016 Intel Corporation
2#
3# SPDX-License-Identifier: MIT
4#
Brad Bishop6e60e8b2018-02-01 10:27:11 -05005
6import os
7import sys
8import json
9import time
10import logging
11import collections
Brad Bishop15ae2502019-06-18 21:44:24 -040012import unittest
Brad Bishop6e60e8b2018-02-01 10:27:11 -050013
14from oeqa.core.loader import OETestLoader
Brad Bishopd7bf8c12018-02-25 22:55:05 -050015from oeqa.core.runner import OETestRunner
16from oeqa.core.exception import OEQAMissingManifest, OEQATestNotFound
Brad Bishop6e60e8b2018-02-01 10:27:11 -050017
18class OETestContext(object):
19 loaderClass = OETestLoader
20 runnerClass = OETestRunner
Brad Bishop6e60e8b2018-02-01 10:27:11 -050021
22 files_dir = os.path.abspath(os.path.join(os.path.dirname(
23 os.path.abspath(__file__)), "../files"))
24
25 def __init__(self, td=None, logger=None):
26 if not type(td) is dict:
27 raise TypeError("td isn't dictionary type")
28
29 self.td = td
30 self.logger = logger
31 self._registry = {}
32 self._registry['cases'] = collections.OrderedDict()
Brad Bishop6e60e8b2018-02-01 10:27:11 -050033
Andrew Geissler6ce62a22020-11-30 19:58:47 -060034 self.results = unittest.TestResult()
35 unittest.registerResult(self.results)
36
Brad Bishop6e60e8b2018-02-01 10:27:11 -050037 def _read_modules_from_manifest(self, manifest):
38 if not os.path.exists(manifest):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050039 raise OEQAMissingManifest("Manifest does not exist on %s" % manifest)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050040
41 modules = []
42 for line in open(manifest).readlines():
43 line = line.strip()
44 if line and not line.startswith("#"):
45 modules.append(line)
46
47 return modules
48
Brad Bishopd7bf8c12018-02-25 22:55:05 -050049 def skipTests(self, skips):
50 if not skips:
51 return
Brad Bishop15ae2502019-06-18 21:44:24 -040052 def skipfuncgen(skipmsg):
53 def func():
54 raise unittest.SkipTest(skipmsg)
55 return func
Brad Bishopc8f47122019-06-24 09:36:18 -040056 class_ids = {}
Brad Bishopd7bf8c12018-02-25 22:55:05 -050057 for test in self.suites:
Brad Bishopc8f47122019-06-24 09:36:18 -040058 if test.__class__ not in class_ids:
59 class_ids[test.__class__] = '.'.join(test.id().split('.')[:-1])
Brad Bishopd7bf8c12018-02-25 22:55:05 -050060 for skip in skips:
Brad Bishopc8f47122019-06-24 09:36:18 -040061 if (test.id()+'.').startswith(skip+'.'):
Brad Bishop15ae2502019-06-18 21:44:24 -040062 setattr(test, 'setUp', skipfuncgen('Skip by the command line argument "%s"' % skip))
Brad Bishopc8f47122019-06-24 09:36:18 -040063 for tclass in class_ids:
64 cid = class_ids[tclass]
65 for skip in skips:
66 if (cid + '.').startswith(skip + '.'):
67 setattr(tclass, 'setUpHooker', skipfuncgen('Skip by the command line argument "%s"' % skip))
Brad Bishopd7bf8c12018-02-25 22:55:05 -050068
Brad Bishop6e60e8b2018-02-01 10:27:11 -050069 def loadTests(self, module_paths, modules=[], tests=[],
Brad Bishop79641f22019-09-10 07:20:22 -040070 modules_manifest="", modules_required=[], **kwargs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050071 if modules_manifest:
72 modules = self._read_modules_from_manifest(modules_manifest)
73
74 self.loader = self.loaderClass(self, module_paths, modules, tests,
Brad Bishop79641f22019-09-10 07:20:22 -040075 modules_required, **kwargs)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050076 self.suites = self.loader.discover()
77
Andrew Geissler82c905d2020-04-13 13:39:40 -050078 def prepareSuite(self, suites, processes):
79 return suites
80
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080081 def runTests(self, processes=None, skips=[]):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050082 self.runner = self.runnerClass(self, descriptions=False, verbosity=2)
83
84 # Dinamically skip those tests specified though arguments
85 self.skipTests(skips)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050086
87 self._run_start_time = time.time()
Andrew Geissler6ce62a22020-11-30 19:58:47 -060088 self._run_end_time = self._run_start_time
Andrew Geissler82c905d2020-04-13 13:39:40 -050089 if not processes:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080090 self.runner.buffer = True
Andrew Geissler82c905d2020-04-13 13:39:40 -050091 result = self.runner.run(self.prepareSuite(self.suites, processes))
Brad Bishop6e60e8b2018-02-01 10:27:11 -050092 self._run_end_time = time.time()
93
94 return result
95
Brad Bishopd7bf8c12018-02-25 22:55:05 -050096 def listTests(self, display_type):
97 self.runner = self.runnerClass(self, verbosity=2)
98 return self.runner.list_tests(self.suites, display_type)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050099
100class OETestContextExecutor(object):
101 _context_class = OETestContext
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500102 _script_executor = 'oe-test'
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500103
104 name = 'core'
105 help = 'core test component example'
106 description = 'executes core test suite example'
Andrew Geissler82c905d2020-04-13 13:39:40 -0500107 datetime = time.strftime("%Y%m%d%H%M%S")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500108
109 default_cases = [os.path.join(os.path.abspath(os.path.dirname(__file__)),
110 'cases/example')]
111 default_test_data = os.path.join(default_cases[0], 'data.json')
112 default_tests = None
Andrew Geissler82c905d2020-04-13 13:39:40 -0500113 default_json_result_dir = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500114
115 def register_commands(self, logger, subparsers):
116 self.parser = subparsers.add_parser(self.name, help=self.help,
117 description=self.description, group='components')
118
Andrew Geissler82c905d2020-04-13 13:39:40 -0500119 self.default_output_log = '%s-results-%s.log' % (self.name, self.datetime)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500120 self.parser.add_argument('--output-log', action='store',
121 default=self.default_output_log,
122 help="results output log, default: %s" % self.default_output_log)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500123
Andrew Geissler82c905d2020-04-13 13:39:40 -0500124 self.parser.add_argument('--json-result-dir', action='store',
125 default=self.default_json_result_dir,
126 help="json result output dir, default: %s" % self.default_json_result_dir)
127
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500128 group = self.parser.add_mutually_exclusive_group()
129 group.add_argument('--run-tests', action='store', nargs='+',
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500130 default=self.default_tests,
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500131 help="tests to run in <module>[.<class>[.<name>]]")
132 group.add_argument('--list-tests', action='store',
133 choices=('module', 'class', 'name'),
134 help="lists available tests")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500135
136 if self.default_test_data:
137 self.parser.add_argument('--test-data-file', action='store',
138 default=self.default_test_data,
139 help="data file to load, default: %s" % self.default_test_data)
140 else:
141 self.parser.add_argument('--test-data-file', action='store',
142 help="data file to load")
143
144 if self.default_cases:
145 self.parser.add_argument('CASES_PATHS', action='store',
146 default=self.default_cases, nargs='*',
147 help="paths to directories with test cases, default: %s"\
148 % self.default_cases)
149 else:
150 self.parser.add_argument('CASES_PATHS', action='store',
151 nargs='+', help="paths to directories with test cases")
152
153 self.parser.set_defaults(func=self.run)
154
155 def _setup_logger(self, logger, args):
156 formatter = logging.Formatter('%(asctime)s - ' + self.name + \
157 ' - %(levelname)s - %(message)s')
158 sh = logger.handlers[0]
159 sh.setFormatter(formatter)
160 fh = logging.FileHandler(args.output_log)
161 fh.setFormatter(formatter)
162 logger.addHandler(fh)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500163 if getattr(args, 'verbose', False):
164 logger.setLevel('DEBUG')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500165
166 return logger
167
168 def _process_args(self, logger, args):
169 self.tc_kwargs = {}
170 self.tc_kwargs['init'] = {}
171 self.tc_kwargs['load'] = {}
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500172 self.tc_kwargs['list'] = {}
173 self.tc_kwargs['run'] = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500174
175 self.tc_kwargs['init']['logger'] = self._setup_logger(logger, args)
176 if args.test_data_file:
177 self.tc_kwargs['init']['td'] = json.load(
178 open(args.test_data_file, "r"))
179 else:
180 self.tc_kwargs['init']['td'] = {}
181
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500182 if args.run_tests:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500183 self.tc_kwargs['load']['modules'] = args.run_tests
184 self.tc_kwargs['load']['modules_required'] = args.run_tests
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500185 else:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500186 self.tc_kwargs['load']['modules'] = []
187
188 self.tc_kwargs['run']['skips'] = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500189
190 self.module_paths = args.CASES_PATHS
191
Andrew Geissler82c905d2020-04-13 13:39:40 -0500192 def _get_json_result_dir(self, args):
193 return args.json_result_dir
194
195 def _get_configuration(self):
196 td = self.tc_kwargs['init']['td']
197 configuration = {'TEST_TYPE': self.name,
198 'MACHINE': td.get("MACHINE"),
199 'DISTRO': td.get("DISTRO"),
200 'IMAGE_BASENAME': td.get("IMAGE_BASENAME"),
201 'DATETIME': td.get("DATETIME")}
202 return configuration
203
204 def _get_result_id(self, configuration):
205 return '%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['IMAGE_BASENAME'],
206 configuration['MACHINE'], self.datetime)
207
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500208 def _pre_run(self):
209 pass
210
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500211 def run(self, logger, args):
212 self._process_args(logger, args)
213
214 self.tc = self._context_class(**self.tc_kwargs['init'])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500215 try:
216 self.tc.loadTests(self.module_paths, **self.tc_kwargs['load'])
217 except OEQATestNotFound as ex:
218 logger.error(ex)
219 sys.exit(1)
220
221 if args.list_tests:
222 rc = self.tc.listTests(args.list_tests, **self.tc_kwargs['list'])
223 else:
224 self._pre_run()
225 rc = self.tc.runTests(**self.tc_kwargs['run'])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500226
227 json_result_dir = self._get_json_result_dir(args)
228 if json_result_dir:
229 configuration = self._get_configuration()
230 rc.logDetails(json_result_dir,
231 configuration,
232 self._get_result_id(configuration))
233 else:
234 rc.logDetails()
235
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500236 rc.logSummary(self.name)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500237
238 output_link = os.path.join(os.path.dirname(args.output_log),
239 "%s-results.log" % self.name)
240 if os.path.exists(output_link):
241 os.remove(output_link)
242 os.symlink(args.output_log, output_link)
243
244 return rc
245
246_executor_class = OETestContextExecutor