summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/selftest/base.py
blob: b5a52fe57a235cf5339dc7a2ca819f91cdee4052 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# Copyright (c) 2013 Intel Corporation
#
# Released under the MIT license (see COPYING.MIT)


# DESCRIPTION
# Base class inherited by test classes in meta/lib/oeqa/selftest

import unittest
import os
import sys
import shutil
import logging
import errno

import oeqa.utils.ftools as ftools
from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer
from oeqa.utils.decorators import LogResults
from random import choice
import glob

@LogResults
class oeSelfTest(unittest.TestCase):

    log = logging.getLogger("selftest.base")
    longMessage = True

    def __init__(self, methodName="runTest"):
        self.builddir = os.environ.get("BUILDDIR")
        self.localconf_path = os.path.join(self.builddir, "conf/local.conf")
        self.testinc_path = os.path.join(self.builddir, "conf/selftest.inc")
        self.local_bblayers_path = os.path.join(self.builddir, "conf/bblayers.conf")
        self.testinc_bblayers_path = os.path.join(self.builddir, "conf/bblayers.inc")
        self.machineinc_path = os.path.join(self.builddir, "conf/machine.inc")
        self.testlayer_path = oeSelfTest.testlayer_path
        self._extra_tear_down_commands = []
        self._track_for_cleanup = [self.testinc_path, self.testinc_bblayers_path, self.machineinc_path]
        super(oeSelfTest, self).__init__(methodName)

    def setUp(self):
        os.chdir(self.builddir)
        # we don't know what the previous test left around in config or inc files
        # if it failed so we need a fresh start
        try:
            os.remove(self.testinc_path)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise
        for root, _, files in os.walk(self.testlayer_path):
            for f in files:
                if f == 'test_recipe.inc':
                    os.remove(os.path.join(root, f))

        for incl_file in [self.testinc_bblayers_path, self.machineinc_path]:
            try:
                os.remove(incl_file)
            except OSError as e:
                if e.errno != errno.ENOENT:
                    raise

        # Get CUSTOMMACHINE from env (set by --machine argument to oe-selftest)
        custommachine = os.getenv('CUSTOMMACHINE')
        if custommachine:
            if custommachine == 'random':
                machine = get_random_machine()
            else:
                machine = custommachine
            machine_conf = 'MACHINE ??= "%s"\n' % machine
            self.set_machine_config(machine_conf)
            print('MACHINE: %s' % machine)

        # tests might need their own setup
        # but if they overwrite this one they have to call
        # super each time, so let's give them an alternative
        self.setUpLocal()

    def setUpLocal(self):
        pass

    def tearDown(self):
        if self._extra_tear_down_commands:
            failed_extra_commands = []
            for command in self._extra_tear_down_commands:
                result = runCmd(command, ignore_status=True)
                if not result.status ==  0:
                    failed_extra_commands.append(command)
            if failed_extra_commands:
                self.log.warning("tearDown commands have failed: %s" % ', '.join(map(str, failed_extra_commands)))
                self.log.debug("Trying to move on.")
            self._extra_tear_down_commands = []

        if self._track_for_cleanup:
            for path in self._track_for_cleanup:
                if os.path.isdir(path):
                    shutil.rmtree(path)
                if os.path.isfile(path):
                    os.remove(path)
            self._track_for_cleanup = []

        self.tearDownLocal()

    def tearDownLocal(self):
        pass

    # add test specific commands to the tearDown method.
    def add_command_to_tearDown(self, command):
        self.log.debug("Adding command '%s' to tearDown for this test." % command)
        self._extra_tear_down_commands.append(command)
    # add test specific files or directories to be removed in the tearDown method
    def track_for_cleanup(self, path):
        self.log.debug("Adding path '%s' to be cleaned up when test is over" % path)
        self._track_for_cleanup.append(path)

    # write to <builddir>/conf/selftest.inc
    def write_config(self, data):
        self.log.debug("Writing to: %s\n%s\n" % (self.testinc_path, data))
        ftools.write_file(self.testinc_path, data)

        custommachine = os.getenv('CUSTOMMACHINE')
        if custommachine and 'MACHINE' in data:
            machine = get_bb_var('MACHINE')
            self.log.warning('MACHINE overridden: %s' % machine)

    # append to <builddir>/conf/selftest.inc
    def append_config(self, data):
        self.log.debug("Appending to: %s\n%s\n" % (self.testinc_path, data))
        ftools.append_file(self.testinc_path, data)

        custommachine = os.getenv('CUSTOMMACHINE')
        if custommachine and 'MACHINE' in data:
            machine = get_bb_var('MACHINE')
            self.log.warning('MACHINE overridden: %s' % machine)

    # remove data from <builddir>/conf/selftest.inc
    def remove_config(self, data):
        self.log.debug("Removing from: %s\n\%s\n" % (self.testinc_path, data))
        ftools.remove_from_file(self.testinc_path, data)

    # write to meta-sefltest/recipes-test/<recipe>/test_recipe.inc
    def write_recipeinc(self, recipe, data):
        inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
        self.log.debug("Writing to: %s\n%s\n" % (inc_file, data))
        ftools.write_file(inc_file, data)

    # append data to meta-sefltest/recipes-test/<recipe>/test_recipe.inc
    def append_recipeinc(self, recipe, data):
        inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
        self.log.debug("Appending to: %s\n%s\n" % (inc_file, data))
        ftools.append_file(inc_file, data)

    # remove data from meta-sefltest/recipes-test/<recipe>/test_recipe.inc
    def remove_recipeinc(self, recipe, data):
        inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
        self.log.debug("Removing from: %s\n%s\n" % (inc_file, data))
        ftools.remove_from_file(inc_file, data)

    # delete meta-sefltest/recipes-test/<recipe>/test_recipe.inc file
    def delete_recipeinc(self, recipe):
        inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc')
        self.log.debug("Deleting file: %s" % inc_file)
        try:
            os.remove(inc_file)
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise

    # write to <builddir>/conf/bblayers.inc
    def write_bblayers_config(self, data):
        self.log.debug("Writing to: %s\n%s\n" % (self.testinc_bblayers_path, data))
        ftools.write_file(self.testinc_bblayers_path, data)

    # append to <builddir>/conf/bblayers.inc
    def append_bblayers_config(self, data):
        self.log.debug("Appending to: %s\n%s\n" % (self.testinc_bblayers_path, data))
        ftools.append_file(self.testinc_bblayers_path, data)

    # remove data from <builddir>/conf/bblayers.inc
    def remove_bblayers_config(self, data):
        self.log.debug("Removing from: %s\n\%s\n" % (self.testinc_bblayers_path, data))
        ftools.remove_from_file(self.testinc_bblayers_path, data)

    # write to <builddir>/conf/machine.inc
    def set_machine_config(self, data):
        self.log.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data))
        ftools.write_file(self.machineinc_path, data)


def get_available_machines():
    # Get a list of all available machines
    bbpath = get_bb_var('BBPATH').split(':')
    machines = []

    for path in bbpath:
        found_machines = glob.glob(os.path.join(path, 'conf', 'machine', '*.conf'))
        if found_machines:
            for i in found_machines:
                # eg: '/home/<user>/poky/meta-intel/conf/machine/intel-core2-32.conf'
                machines.append(os.path.splitext(os.path.basename(i))[0])

    return machines


def get_random_machine():
    # Get a random machine
    return choice(get_available_machines())