case.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #
  2. # Copyright (C) 2013-2017 Intel Corporation
  3. #
  4. # SPDX-License-Identifier: MIT
  5. #
  6. import sys
  7. import os
  8. import glob
  9. import errno
  10. from unittest.util import safe_repr
  11. import oeqa.utils.ftools as ftools
  12. from oeqa.utils.commands import runCmd, bitbake, get_bb_var
  13. from oeqa.core.case import OETestCase
  14. import bb.utils
  15. class OESelftestTestCase(OETestCase):
  16. def __init__(self, methodName="runTest"):
  17. self._extra_tear_down_commands = []
  18. super(OESelftestTestCase, self).__init__(methodName)
  19. @classmethod
  20. def setUpClass(cls):
  21. super(OESelftestTestCase, cls).setUpClass()
  22. cls.testlayer_path = cls.tc.config_paths['testlayer_path']
  23. cls.builddir = cls.tc.config_paths['builddir']
  24. cls.localconf_path = cls.tc.config_paths['localconf']
  25. cls.local_bblayers_path = cls.tc.config_paths['bblayers']
  26. cls.testinc_path = os.path.join(cls.tc.config_paths['builddir'],
  27. "conf/selftest.inc")
  28. cls.testinc_bblayers_path = os.path.join(cls.tc.config_paths['builddir'],
  29. "conf/bblayers.inc")
  30. cls.machineinc_path = os.path.join(cls.tc.config_paths['builddir'],
  31. "conf/machine.inc")
  32. cls._track_for_cleanup = [
  33. cls.testinc_path, cls.testinc_bblayers_path,
  34. cls.machineinc_path]
  35. cls.add_include()
  36. @classmethod
  37. def tearDownClass(cls):
  38. cls.remove_include()
  39. cls.remove_inc_files()
  40. super(OESelftestTestCase, cls).tearDownClass()
  41. @classmethod
  42. def add_include(cls):
  43. if "#include added by oe-selftest" \
  44. not in ftools.read_file(os.path.join(cls.builddir, "conf/local.conf")):
  45. cls.logger.info("Adding: \"include selftest.inc\" in %s" % os.path.join(cls.builddir, "conf/local.conf"))
  46. ftools.append_file(os.path.join(cls.builddir, "conf/local.conf"), \
  47. "\n#include added by oe-selftest\ninclude machine.inc\ninclude selftest.inc")
  48. if "#include added by oe-selftest" \
  49. not in ftools.read_file(os.path.join(cls.builddir, "conf/bblayers.conf")):
  50. cls.logger.info("Adding: \"include bblayers.inc\" in bblayers.conf")
  51. ftools.append_file(os.path.join(cls.builddir, "conf/bblayers.conf"), \
  52. "\n#include added by oe-selftest\ninclude bblayers.inc")
  53. @classmethod
  54. def remove_include(cls):
  55. if "#include added by oe-selftest.py" \
  56. in ftools.read_file(os.path.join(cls.builddir, "conf/local.conf")):
  57. cls.logger.info("Removing the include from local.conf")
  58. ftools.remove_from_file(os.path.join(cls.builddir, "conf/local.conf"), \
  59. "\n#include added by oe-selftest.py\ninclude machine.inc\ninclude selftest.inc")
  60. if "#include added by oe-selftest.py" \
  61. in ftools.read_file(os.path.join(cls.builddir, "conf/bblayers.conf")):
  62. cls.logger.info("Removing the include from bblayers.conf")
  63. ftools.remove_from_file(os.path.join(cls.builddir, "conf/bblayers.conf"), \
  64. "\n#include added by oe-selftest.py\ninclude bblayers.inc")
  65. @classmethod
  66. def remove_inc_files(cls):
  67. try:
  68. os.remove(os.path.join(cls.builddir, "conf/selftest.inc"))
  69. for root, _, files in os.walk(cls.testlayer_path):
  70. for f in files:
  71. if f == 'test_recipe.inc':
  72. os.remove(os.path.join(root, f))
  73. except OSError as e:
  74. pass
  75. for incl_file in ['conf/bblayers.inc', 'conf/machine.inc']:
  76. try:
  77. os.remove(os.path.join(cls.builddir, incl_file))
  78. except:
  79. pass
  80. def setUp(self):
  81. super(OESelftestTestCase, self).setUp()
  82. os.chdir(self.builddir)
  83. # we don't know what the previous test left around in config or inc files
  84. # if it failed so we need a fresh start
  85. try:
  86. os.remove(self.testinc_path)
  87. except OSError as e:
  88. if e.errno != errno.ENOENT:
  89. raise
  90. for root, _, files in os.walk(self.testlayer_path):
  91. for f in files:
  92. if f == 'test_recipe.inc':
  93. os.remove(os.path.join(root, f))
  94. for incl_file in [self.testinc_bblayers_path, self.machineinc_path]:
  95. try:
  96. os.remove(incl_file)
  97. except OSError as e:
  98. if e.errno != errno.ENOENT:
  99. raise
  100. # tests might need their own setup
  101. # but if they overwrite this one they have to call
  102. # super each time, so let's give them an alternative
  103. self.setUpLocal()
  104. def setUpLocal(self):
  105. pass
  106. def tearDown(self):
  107. if self._extra_tear_down_commands:
  108. failed_extra_commands = []
  109. for command in self._extra_tear_down_commands:
  110. result = runCmd(command, ignore_status=True)
  111. if not result.status == 0:
  112. failed_extra_commands.append(command)
  113. if failed_extra_commands:
  114. self.logger.warning("tearDown commands have failed: %s" % ', '.join(map(str, failed_extra_commands)))
  115. self.logger.debug("Trying to move on.")
  116. self._extra_tear_down_commands = []
  117. if self._track_for_cleanup:
  118. for path in self._track_for_cleanup:
  119. if os.path.isdir(path):
  120. bb.utils.remove(path, recurse=True)
  121. if os.path.isfile(path):
  122. os.remove(path)
  123. self._track_for_cleanup = []
  124. self.tearDownLocal()
  125. super(OESelftestTestCase, self).tearDown()
  126. def tearDownLocal(self):
  127. pass
  128. def add_command_to_tearDown(self, command):
  129. """Add test specific commands to the tearDown method"""
  130. self.logger.debug("Adding command '%s' to tearDown for this test." % command)
  131. self._extra_tear_down_commands.append(command)
  132. def track_for_cleanup(self, path):
  133. """Add test specific files or directories to be removed in the tearDown method"""
  134. self.logger.debug("Adding path '%s' to be cleaned up when test is over" % path)
  135. self._track_for_cleanup.append(path)
  136. def write_config(self, data, multiconfig=None):
  137. """Write to config file"""
  138. if multiconfig:
  139. multiconfigdir = "%s/conf/multiconfig" % self.builddir
  140. os.makedirs(multiconfigdir, exist_ok=True)
  141. dest_path = '%s/%s.conf' % (multiconfigdir, multiconfig)
  142. self.track_for_cleanup(dest_path)
  143. else:
  144. dest_path = self.testinc_path
  145. self.logger.debug("Writing to: %s\n%s\n" % (dest_path, data))
  146. ftools.write_file(dest_path, data)
  147. def append_config(self, data):
  148. """Append to <builddir>/conf/selftest.inc"""
  149. self.logger.debug("Appending to: %s\n%s\n" % (self.testinc_path, data))
  150. ftools.append_file(self.testinc_path, data)
  151. def remove_config(self, data):
  152. """Remove data from <builddir>/conf/selftest.inc"""
  153. self.logger.debug("Removing from: %s\n%s\n" % (self.testinc_path, data))
  154. ftools.remove_from_file(self.testinc_path, data)
  155. def recipeinc(self, recipe):
  156. """Return absolute path of meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
  157. return os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
  158. def write_recipeinc(self, recipe, data):
  159. """Write to meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
  160. inc_file = self.recipeinc(recipe)
  161. self.logger.debug("Writing to: %s\n%s\n" % (inc_file, data))
  162. ftools.write_file(inc_file, data)
  163. return inc_file
  164. def append_recipeinc(self, recipe, data):
  165. """Append data to meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
  166. inc_file = self.recipeinc(recipe)
  167. self.logger.debug("Appending to: %s\n%s\n" % (inc_file, data))
  168. ftools.append_file(inc_file, data)
  169. return inc_file
  170. def remove_recipeinc(self, recipe, data):
  171. """Remove data from meta-selftest/recipes-test/<recipe>/test_recipe.inc"""
  172. inc_file = self.recipeinc(recipe)
  173. self.logger.debug("Removing from: %s\n%s\n" % (inc_file, data))
  174. ftools.remove_from_file(inc_file, data)
  175. def delete_recipeinc(self, recipe):
  176. """Delete meta-selftest/recipes-test/<recipe>/test_recipe.inc file"""
  177. inc_file = self.recipeinc(recipe)
  178. self.logger.debug("Deleting file: %s" % inc_file)
  179. try:
  180. os.remove(inc_file)
  181. except OSError as e:
  182. if e.errno != errno.ENOENT:
  183. raise
  184. def write_bblayers_config(self, data):
  185. """Write to <builddir>/conf/bblayers.inc"""
  186. self.logger.debug("Writing to: %s\n%s\n" % (self.testinc_bblayers_path, data))
  187. ftools.write_file(self.testinc_bblayers_path, data)
  188. def append_bblayers_config(self, data):
  189. """Append to <builddir>/conf/bblayers.inc"""
  190. self.logger.debug("Appending to: %s\n%s\n" % (self.testinc_bblayers_path, data))
  191. ftools.append_file(self.testinc_bblayers_path, data)
  192. def remove_bblayers_config(self, data):
  193. """Remove data from <builddir>/conf/bblayers.inc"""
  194. self.logger.debug("Removing from: %s\n%s\n" % (self.testinc_bblayers_path, data))
  195. ftools.remove_from_file(self.testinc_bblayers_path, data)
  196. def set_machine_config(self, data):
  197. """Write to <builddir>/conf/machine.inc"""
  198. self.logger.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data))
  199. ftools.write_file(self.machineinc_path, data)
  200. def disable_class(self, classname):
  201. destfile = "%s/classes/%s.bbclass" % (self.builddir, classname)
  202. os.makedirs(os.path.dirname(destfile), exist_ok=True)
  203. self.track_for_cleanup(destfile)
  204. self.logger.debug("Creating empty class: %s\n" % (destfile))
  205. ftools.write_file(destfile, "")
  206. # check does path exist
  207. def assertExists(self, expr, msg=None):
  208. if not os.path.exists(expr):
  209. msg = self._formatMessage(msg, "%s does not exist" % safe_repr(expr))
  210. raise self.failureException(msg)
  211. # check does path not exist
  212. def assertNotExists(self, expr, msg=None):
  213. if os.path.exists(expr):
  214. msg = self._formatMessage(msg, "%s exists when it should not" % safe_repr(expr))
  215. raise self.failureException(msg)