blob: ac3308d8a448b7f83f48f21fd67a8c8538f898c4 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002# Copyright (C) 2013-2017 Intel Corporation
Brad Bishopc342db32019-05-15 21:57:59 -04003#
4# SPDX-License-Identifier: MIT
5#
Brad Bishopd7bf8c12018-02-25 22:55:05 -05006
7import sys
8import os
9import shutil
10import glob
11import errno
12from unittest.util import safe_repr
13
14import oeqa.utils.ftools as ftools
15from oeqa.utils.commands import runCmd, bitbake, get_bb_var
16from oeqa.core.case import OETestCase
17
Brad Bishopf86d0552018-12-04 14:18:15 -080018import bb.utils
19
Brad Bishopd7bf8c12018-02-25 22:55:05 -050020class OESelftestTestCase(OETestCase):
21 def __init__(self, methodName="runTest"):
22 self._extra_tear_down_commands = []
23 super(OESelftestTestCase, self).__init__(methodName)
24
25 @classmethod
26 def setUpClass(cls):
27 super(OESelftestTestCase, cls).setUpClass()
28
29 cls.testlayer_path = cls.tc.config_paths['testlayer_path']
30 cls.builddir = cls.tc.config_paths['builddir']
31
32 cls.localconf_path = cls.tc.config_paths['localconf']
33 cls.localconf_backup = cls.tc.config_paths['localconf_class_backup']
34 cls.local_bblayers_path = cls.tc.config_paths['bblayers']
35 cls.local_bblayers_backup = cls.tc.config_paths['bblayers_class_backup']
36
37 cls.testinc_path = os.path.join(cls.tc.config_paths['builddir'],
38 "conf/selftest.inc")
39 cls.testinc_bblayers_path = os.path.join(cls.tc.config_paths['builddir'],
40 "conf/bblayers.inc")
41 cls.machineinc_path = os.path.join(cls.tc.config_paths['builddir'],
42 "conf/machine.inc")
43
44 cls._track_for_cleanup = [
45 cls.testinc_path, cls.testinc_bblayers_path,
46 cls.machineinc_path, cls.localconf_backup,
47 cls.local_bblayers_backup]
48
49 cls.add_include()
50
51 @classmethod
52 def tearDownClass(cls):
53 cls.remove_include()
54 cls.remove_inc_files()
55 super(OESelftestTestCase, cls).tearDownClass()
56
57 @classmethod
58 def add_include(cls):
59 if "#include added by oe-selftest" \
60 not in ftools.read_file(os.path.join(cls.builddir, "conf/local.conf")):
61 cls.logger.info("Adding: \"include selftest.inc\" in %s" % os.path.join(cls.builddir, "conf/local.conf"))
62 ftools.append_file(os.path.join(cls.builddir, "conf/local.conf"), \
63 "\n#include added by oe-selftest\ninclude machine.inc\ninclude selftest.inc")
64
65 if "#include added by oe-selftest" \
66 not in ftools.read_file(os.path.join(cls.builddir, "conf/bblayers.conf")):
67 cls.logger.info("Adding: \"include bblayers.inc\" in bblayers.conf")
68 ftools.append_file(os.path.join(cls.builddir, "conf/bblayers.conf"), \
69 "\n#include added by oe-selftest\ninclude bblayers.inc")
70
71 @classmethod
72 def remove_include(cls):
73 if "#include added by oe-selftest.py" \
74 in ftools.read_file(os.path.join(cls.builddir, "conf/local.conf")):
75 cls.logger.info("Removing the include from local.conf")
76 ftools.remove_from_file(os.path.join(cls.builddir, "conf/local.conf"), \
77 "\n#include added by oe-selftest.py\ninclude machine.inc\ninclude selftest.inc")
78
79 if "#include added by oe-selftest.py" \
80 in ftools.read_file(os.path.join(cls.builddir, "conf/bblayers.conf")):
81 cls.logger.info("Removing the include from bblayers.conf")
82 ftools.remove_from_file(os.path.join(cls.builddir, "conf/bblayers.conf"), \
83 "\n#include added by oe-selftest.py\ninclude bblayers.inc")
84
85 @classmethod
86 def remove_inc_files(cls):
87 try:
88 os.remove(os.path.join(cls.builddir, "conf/selftest.inc"))
89 for root, _, files in os.walk(cls.testlayer_path):
90 for f in files:
91 if f == 'test_recipe.inc':
92 os.remove(os.path.join(root, f))
93 except OSError as e:
94 pass
95
96 for incl_file in ['conf/bblayers.inc', 'conf/machine.inc']:
97 try:
98 os.remove(os.path.join(cls.builddir, incl_file))
99 except:
100 pass
101
102 def setUp(self):
103 super(OESelftestTestCase, self).setUp()
104 os.chdir(self.builddir)
105 # Check if local.conf or bblayers.conf files backup exists
106 # from a previous failed test and restore them
107 if os.path.isfile(self.localconf_backup) or os.path.isfile(
108 self.local_bblayers_backup):
109 self.logger.debug("\
110Found a local.conf and/or bblayers.conf backup from a previously aborted test.\
111Restoring these files now, but tests should be re-executed from a clean environment\
112to ensure accurate results.")
113 try:
114 shutil.copyfile(self.localconf_backup, self.localconf_path)
115 except OSError as e:
116 if e.errno != errno.ENOENT:
117 raise
118 try:
119 shutil.copyfile(self.local_bblayers_backup,
120 self.local_bblayers_path)
121 except OSError as e:
122 if e.errno != errno.ENOENT:
123 raise
124 else:
125 # backup local.conf and bblayers.conf
126 shutil.copyfile(self.localconf_path, self.localconf_backup)
127 shutil.copyfile(self.local_bblayers_path, self.local_bblayers_backup)
128 self.logger.debug("Creating local.conf and bblayers.conf backups.")
129 # we don't know what the previous test left around in config or inc files
130 # if it failed so we need a fresh start
131 try:
132 os.remove(self.testinc_path)
133 except OSError as e:
134 if e.errno != errno.ENOENT:
135 raise
136 for root, _, files in os.walk(self.testlayer_path):
137 for f in files:
138 if f == 'test_recipe.inc':
139 os.remove(os.path.join(root, f))
140
141 for incl_file in [self.testinc_bblayers_path, self.machineinc_path]:
142 try:
143 os.remove(incl_file)
144 except OSError as e:
145 if e.errno != errno.ENOENT:
146 raise
147
148 if self.tc.custommachine:
149 machine_conf = 'MACHINE ??= "%s"\n' % self.tc.custommachine
150 self.set_machine_config(machine_conf)
151
152 # tests might need their own setup
153 # but if they overwrite this one they have to call
154 # super each time, so let's give them an alternative
155 self.setUpLocal()
156
157 def setUpLocal(self):
158 pass
159
160 def tearDown(self):
161 if self._extra_tear_down_commands:
162 failed_extra_commands = []
163 for command in self._extra_tear_down_commands:
164 result = runCmd(command, ignore_status=True)
165 if not result.status == 0:
166 failed_extra_commands.append(command)
167 if failed_extra_commands:
168 self.logger.warning("tearDown commands have failed: %s" % ', '.join(map(str, failed_extra_commands)))
169 self.logger.debug("Trying to move on.")
170 self._extra_tear_down_commands = []
171
172 if self._track_for_cleanup:
173 for path in self._track_for_cleanup:
174 if os.path.isdir(path):
Brad Bishopf86d0552018-12-04 14:18:15 -0800175 bb.utils.remove(path, recurse=True)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500176 if os.path.isfile(path):
177 os.remove(path)
178 self._track_for_cleanup = []
179
180 self.tearDownLocal()
181 super(OESelftestTestCase, self).tearDown()
182
183 def tearDownLocal(self):
184 pass
185
186 def add_command_to_tearDown(self, command):
187 """Add test specific commands to the tearDown method"""
188 self.logger.debug("Adding command '%s' to tearDown for this test." % command)
189 self._extra_tear_down_commands.append(command)
190
191 def track_for_cleanup(self, path):
192 """Add test specific files or directories to be removed in the tearDown method"""
193 self.logger.debug("Adding path '%s' to be cleaned up when test is over" % path)
194 self._track_for_cleanup.append(path)
195
Brad Bishop00e122a2019-10-05 11:10:57 -0400196 def write_config(self, data, multiconfig=None):
197 """Write to config file"""
198 if multiconfig:
199 multiconfigdir = "%s/conf/multiconfig" % self.builddir
200 os.makedirs(multiconfigdir, exist_ok=True)
201 dest_path = '%s/%s.conf' % (multiconfigdir, multiconfig)
202 self.track_for_cleanup(dest_path)
203 else:
204 dest_path = self.testinc_path
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500205
Brad Bishop00e122a2019-10-05 11:10:57 -0400206 self.logger.debug("Writing to: %s\n%s\n" % (dest_path, data))
207 ftools.write_file(dest_path, data)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500208
Brad Bishop00e122a2019-10-05 11:10:57 -0400209 if not multiconfig and self.tc.custommachine and 'MACHINE' in data:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500210 machine = get_bb_var('MACHINE')
211 self.logger.warning('MACHINE overridden: %s' % machine)
212
213 def append_config(self, data):
214 """Append to <builddir>/conf/selftest.inc"""
215 self.logger.debug("Appending to: %s\n%s\n" % (self.testinc_path, data))
216 ftools.append_file(self.testinc_path, data)
217
218 if self.tc.custommachine and 'MACHINE' in data:
219 machine = get_bb_var('MACHINE')
220 self.logger.warning('MACHINE overridden: %s' % machine)
221
222 def remove_config(self, data):
223 """Remove data from <builddir>/conf/selftest.inc"""
224 self.logger.debug("Removing from: %s\n%s\n" % (self.testinc_path, data))
225 ftools.remove_from_file(self.testinc_path, data)
226
227 def recipeinc(self, recipe):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800228 """Return absolute path of meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500229 return os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
230
231 def write_recipeinc(self, recipe, data):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800232 """Write to meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500233 inc_file = self.recipeinc(recipe)
234 self.logger.debug("Writing to: %s\n%s\n" % (inc_file, data))
235 ftools.write_file(inc_file, data)
236 return inc_file
237
238 def append_recipeinc(self, recipe, data):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800239 """Append data to meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500240 inc_file = self.recipeinc(recipe)
241 self.logger.debug("Appending to: %s\n%s\n" % (inc_file, data))
242 ftools.append_file(inc_file, data)
243 return inc_file
244
245 def remove_recipeinc(self, recipe, data):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800246 """Remove data from meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500247 inc_file = self.recipeinc(recipe)
248 self.logger.debug("Removing from: %s\n%s\n" % (inc_file, data))
249 ftools.remove_from_file(inc_file, data)
250
251 def delete_recipeinc(self, recipe):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800252 """Delete meta-selftest/recipes-test/<recipe>/test_recipe.inc file"""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500253 inc_file = self.recipeinc(recipe)
254 self.logger.debug("Deleting file: %s" % inc_file)
255 try:
256 os.remove(inc_file)
257 except OSError as e:
258 if e.errno != errno.ENOENT:
259 raise
260 def write_bblayers_config(self, data):
261 """Write to <builddir>/conf/bblayers.inc"""
262 self.logger.debug("Writing to: %s\n%s\n" % (self.testinc_bblayers_path, data))
263 ftools.write_file(self.testinc_bblayers_path, data)
264
265 def append_bblayers_config(self, data):
266 """Append to <builddir>/conf/bblayers.inc"""
267 self.logger.debug("Appending to: %s\n%s\n" % (self.testinc_bblayers_path, data))
268 ftools.append_file(self.testinc_bblayers_path, data)
269
270 def remove_bblayers_config(self, data):
271 """Remove data from <builddir>/conf/bblayers.inc"""
272 self.logger.debug("Removing from: %s\n%s\n" % (self.testinc_bblayers_path, data))
273 ftools.remove_from_file(self.testinc_bblayers_path, data)
274
275 def set_machine_config(self, data):
276 """Write to <builddir>/conf/machine.inc"""
277 self.logger.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data))
278 ftools.write_file(self.machineinc_path, data)
279
280 # check does path exist
281 def assertExists(self, expr, msg=None):
282 if not os.path.exists(expr):
283 msg = self._formatMessage(msg, "%s does not exist" % safe_repr(expr))
284 raise self.failureException(msg)
285
286 # check does path not exist
287 def assertNotExists(self, expr, msg=None):
288 if os.path.exists(expr):
289 msg = self._formatMessage(msg, "%s exists when it should not" % safe_repr(expr))
290 raise self.failureException(msg)