blob: 9e90d3c2565c8c4e230f0b72c5130a3f0903d5e8 [file] [log] [blame]
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001# Copyright (C) 2017 Intel Corporation
2# Released under the MIT license (see COPYING.MIT)
3
4import os
5import time
6import glob
7import sys
8import imp
9import signal
10from shutil import copyfile
11from random import choice
12
13import oeqa
14
15from oeqa.core.context import OETestContext, OETestContextExecutor
16from oeqa.core.exception import OEQAPreRun, OEQATestNotFound
17
18from oeqa.utils.commands import runCmd, get_bb_vars, get_test_layer
19
20class OESelftestTestContext(OETestContext):
21 def __init__(self, td=None, logger=None, machines=None, config_paths=None):
22 super(OESelftestTestContext, self).__init__(td, logger)
23
24 self.machines = machines
25 self.custommachine = None
26 self.config_paths = config_paths
27
28 def runTests(self, machine=None, skips=[]):
29 if machine:
30 self.custommachine = machine
31 if machine == 'random':
32 self.custommachine = choice(self.machines)
33 self.logger.info('Run tests with custom MACHINE set to: %s' % \
34 self.custommachine)
35 return super(OESelftestTestContext, self).runTests(skips)
36
37 def listTests(self, display_type, machine=None):
38 return super(OESelftestTestContext, self).listTests(display_type)
39
40class OESelftestTestContextExecutor(OETestContextExecutor):
41 _context_class = OESelftestTestContext
42 _script_executor = 'oe-selftest'
43
44 name = 'oe-selftest'
45 help = 'oe-selftest test component'
46 description = 'Executes selftest tests'
47
48 def register_commands(self, logger, parser):
49 group = parser.add_mutually_exclusive_group(required=True)
50
51 group.add_argument('-a', '--run-all-tests', default=False,
52 action="store_true", dest="run_all_tests",
53 help='Run all (unhidden) tests')
54 group.add_argument('-R', '--skip-tests', required=False, action='store',
55 nargs='+', dest="skips", default=None,
56 help='Run all (unhidden) tests except the ones specified. Format should be <module>[.<class>[.<test_method>]]')
57 group.add_argument('-r', '--run-tests', required=False, action='store',
58 nargs='+', dest="run_tests", default=None,
59 help='Select what tests to run (modules, classes or test methods). Format should be: <module>.<class>.<test_method>')
60
61 group.add_argument('-m', '--list-modules', required=False,
62 action="store_true", default=False,
63 help='List all available test modules.')
64 group.add_argument('--list-classes', required=False,
65 action="store_true", default=False,
66 help='List all available test classes.')
67 group.add_argument('-l', '--list-tests', required=False,
68 action="store_true", default=False,
69 help='List all available tests.')
70
71 parser.add_argument('--machine', required=False, choices=['random', 'all'],
72 help='Run tests on different machines (random/all).')
73
74 parser.set_defaults(func=self.run)
75
76 def _get_available_machines(self):
77 machines = []
78
79 bbpath = self.tc_kwargs['init']['td']['BBPATH'].split(':')
80
81 for path in bbpath:
82 found_machines = glob.glob(os.path.join(path, 'conf', 'machine', '*.conf'))
83 if found_machines:
84 for i in found_machines:
85 # eg: '/home/<user>/poky/meta-intel/conf/machine/intel-core2-32.conf'
86 machines.append(os.path.splitext(os.path.basename(i))[0])
87
88 return machines
89
90 def _get_cases_paths(self, bbpath):
91 cases_paths = []
92 for layer in bbpath:
93 cases_dir = os.path.join(layer, 'lib', 'oeqa', 'selftest', 'cases')
94 if os.path.isdir(cases_dir):
95 cases_paths.append(cases_dir)
96 return cases_paths
97
98 def _process_args(self, logger, args):
99 args.output_log = '%s-results-%s.log' % (self.name,
100 time.strftime("%Y%m%d%H%M%S"))
101 args.test_data_file = None
102 args.CASES_PATHS = None
103
104 super(OESelftestTestContextExecutor, self)._process_args(logger, args)
105
106 if args.list_modules:
107 args.list_tests = 'module'
108 elif args.list_classes:
109 args.list_tests = 'class'
110 elif args.list_tests:
111 args.list_tests = 'name'
112
113 self.tc_kwargs['init']['td'] = get_bb_vars()
114 self.tc_kwargs['init']['machines'] = self._get_available_machines()
115
116 builddir = os.environ.get("BUILDDIR")
117 self.tc_kwargs['init']['config_paths'] = {}
118 self.tc_kwargs['init']['config_paths']['testlayer_path'] = \
119 get_test_layer()
120 self.tc_kwargs['init']['config_paths']['builddir'] = builddir
121 self.tc_kwargs['init']['config_paths']['localconf'] = \
122 os.path.join(builddir, "conf/local.conf")
123 self.tc_kwargs['init']['config_paths']['localconf_backup'] = \
124 os.path.join(builddir, "conf/local.conf.orig")
125 self.tc_kwargs['init']['config_paths']['localconf_class_backup'] = \
126 os.path.join(builddir, "conf/local.conf.bk")
127 self.tc_kwargs['init']['config_paths']['bblayers'] = \
128 os.path.join(builddir, "conf/bblayers.conf")
129 self.tc_kwargs['init']['config_paths']['bblayers_backup'] = \
130 os.path.join(builddir, "conf/bblayers.conf.orig")
131 self.tc_kwargs['init']['config_paths']['bblayers_class_backup'] = \
132 os.path.join(builddir, "conf/bblayers.conf.bk")
133
134 copyfile(self.tc_kwargs['init']['config_paths']['localconf'],
135 self.tc_kwargs['init']['config_paths']['localconf_backup'])
136 copyfile(self.tc_kwargs['init']['config_paths']['bblayers'],
137 self.tc_kwargs['init']['config_paths']['bblayers_backup'])
138
139 self.tc_kwargs['run']['skips'] = args.skips
140
141 def _pre_run(self):
142 def _check_required_env_variables(vars):
143 for var in vars:
144 if not os.environ.get(var):
145 self.tc.logger.error("%s is not set. Did you forget to source your build environment setup script?" % var)
146 raise OEQAPreRun
147
148 def _check_presence_meta_selftest():
149 builddir = os.environ.get("BUILDDIR")
150 if os.getcwd() != builddir:
151 self.tc.logger.info("Changing cwd to %s" % builddir)
152 os.chdir(builddir)
153
154 if not "meta-selftest" in self.tc.td["BBLAYERS"]:
155 self.tc.logger.warn("meta-selftest layer not found in BBLAYERS, adding it")
156 meta_selftestdir = os.path.join(
157 self.tc.td["BBLAYERS_FETCH_DIR"], 'meta-selftest')
158 if os.path.isdir(meta_selftestdir):
159 runCmd("bitbake-layers add-layer %s" %meta_selftestdir)
160 # reload data is needed because a meta-selftest layer was add
161 self.tc.td = get_bb_vars()
162 self.tc.config_paths['testlayer_path'] = get_test_layer()
163 else:
164 self.tc.logger.error("could not locate meta-selftest in:\n%s" % meta_selftestdir)
165 raise OEQAPreRun
166
167 def _add_layer_libs():
168 bbpath = self.tc.td['BBPATH'].split(':')
169 layer_libdirs = [p for p in (os.path.join(l, 'lib') \
170 for l in bbpath) if os.path.exists(p)]
171 if layer_libdirs:
172 self.tc.logger.info("Adding layer libraries:")
173 for l in layer_libdirs:
174 self.tc.logger.info("\t%s" % l)
175
176 sys.path.extend(layer_libdirs)
177 imp.reload(oeqa.selftest)
178
179 _check_required_env_variables(["BUILDDIR"])
180 _check_presence_meta_selftest()
181
182 if "buildhistory.bbclass" in self.tc.td["BBINCLUDED"]:
183 self.tc.logger.error("You have buildhistory enabled already and this isn't recommended for selftest, please disable it first.")
184 raise OEQAPreRun
185
186 if "PRSERV_HOST" in self.tc.td:
187 self.tc.logger.error("Please unset PRSERV_HOST in order to run oe-selftest")
188 raise OEQAPreRun
189
190 if "SANITY_TESTED_DISTROS" in self.tc.td:
191 self.tc.logger.error("Please unset SANITY_TESTED_DISTROS in order to run oe-selftest")
192 raise OEQAPreRun
193
194 _add_layer_libs()
195
196 self.tc.logger.info("Running bitbake -p")
197 runCmd("bitbake -p")
198
199 def _internal_run(self, logger, args):
200 self.module_paths = self._get_cases_paths(
201 self.tc_kwargs['init']['td']['BBPATH'].split(':'))
202
203 self.tc = self._context_class(**self.tc_kwargs['init'])
204 try:
205 self.tc.loadTests(self.module_paths, **self.tc_kwargs['load'])
206 except OEQATestNotFound as ex:
207 logger.error(ex)
208 sys.exit(1)
209
210 if args.list_tests:
211 rc = self.tc.listTests(args.list_tests, **self.tc_kwargs['list'])
212 else:
213 self._pre_run()
214 rc = self.tc.runTests(**self.tc_kwargs['run'])
215 rc.logDetails()
216 rc.logSummary(self.name)
217
218 return rc
219
220 def _signal_clean_handler(self, signum, frame):
221 sys.exit(1)
222
223 def run(self, logger, args):
224 self._process_args(logger, args)
225
226 signal.signal(signal.SIGTERM, self._signal_clean_handler)
227
228 rc = None
229 try:
230 if args.machine:
231 logger.info('Custom machine mode enabled. MACHINE set to %s' %
232 args.machine)
233
234 if args.machine == 'all':
235 results = []
236 for m in self.tc_kwargs['init']['machines']:
237 self.tc_kwargs['run']['machine'] = m
238 results.append(self._internal_run(logger, args))
239
240 # XXX: the oe-selftest script only needs to know if one
241 # machine run fails
242 for r in results:
243 rc = r
244 if not r.wasSuccessful():
245 break
246
247 else:
248 self.tc_kwargs['run']['machine'] = args.machine
249 return self._internal_run(logger, args)
250
251 else:
252 self.tc_kwargs['run']['machine'] = args.machine
253 rc = self._internal_run(logger, args)
254 finally:
255 config_paths = self.tc_kwargs['init']['config_paths']
256 if os.path.exists(config_paths['localconf_backup']):
257 copyfile(config_paths['localconf_backup'],
258 config_paths['localconf'])
259 os.remove(config_paths['localconf_backup'])
260
261 if os.path.exists(config_paths['bblayers_backup']):
262 copyfile(config_paths['bblayers_backup'],
263 config_paths['bblayers'])
264 os.remove(config_paths['bblayers_backup'])
265
266 if os.path.exists(config_paths['localconf_class_backup']):
267 os.remove(config_paths['localconf_class_backup'])
268 if os.path.exists(config_paths['bblayers_class_backup']):
269 os.remove(config_paths['bblayers_class_backup'])
270
271 output_link = os.path.join(os.path.dirname(args.output_log),
272 "%s-results.log" % self.name)
273 if os.path.exists(output_link):
274 os.remove(output_link)
275 os.symlink(args.output_log, output_link)
276
277 return rc
278
279_executor_class = OESelftestTestContextExecutor