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