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