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