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