1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7import os
8
9from oeqa.selftest.case import OESelftestTestCase
10from oeqa.utils.commands import get_bb_var, bitbake
11
12class ManifestEntry:
13    '''A manifest item of a collection able to list missing packages'''
14    def __init__(self, entry):
15        self.file = entry
16        self.missing = []
17
18class VerifyManifest(OESelftestTestCase):
19    '''Tests for the manifest files and contents of an image'''
20
21    @classmethod
22    def check_manifest_entries(self, manifest, path):
23        manifest_errors = []
24        try:
25            with open(manifest, "r") as mfile:
26                for line in mfile:
27                    manifest_entry = os.path.join(path, line.split()[0])
28                    self.logger.debug("{}: looking for {}"\
29                                    .format(self.classname, manifest_entry))
30                    if not os.path.isfile(manifest_entry):
31                        manifest_errors.append(manifest_entry)
32                        self.logger.debug("{}: {} not found"\
33                                    .format(self.classname, manifest_entry))
34        except OSError as e:
35            self.logger.debug("{}: checking of {} failed"\
36                    .format(self.classname, manifest))
37            raise e
38
39        return manifest_errors
40
41    #this will possibly move from here
42    @classmethod
43    def get_dir_from_bb_var(self, bb_var, target = None):
44        target == self.buildtarget if target == None else target
45        directory = get_bb_var(bb_var, target);
46        if not directory or not os.path.isdir(directory):
47            self.logger.debug("{}: {} points to {} when target = {}"\
48                    .format(self.classname, bb_var, directory, target))
49            raise OSError
50        return directory
51
52    @classmethod
53    def setUpClass(self):
54
55        super(VerifyManifest, self).setUpClass()
56        self.buildtarget = 'core-image-minimal'
57        self.classname = 'VerifyManifest'
58
59        self.logger.info("{}: doing bitbake {} as a prerequisite of the test"\
60                .format(self.classname, self.buildtarget))
61        if bitbake(self.buildtarget).status:
62            self.logger.debug("{} Failed to setup {}"\
63                    .format(self.classname, self.buildtarget))
64            self.skipTest("{}: Cannot setup testing scenario"\
65                    .format(self.classname))
66
67    def test_SDK_manifest_entries(self):
68        '''Verifying the SDK manifest entries exist, this may take a build'''
69
70        # the setup should bitbake core-image-minimal and here it is required
71        # to do an additional setup for the sdk
72        sdktask = '-c populate_sdk'
73        bbargs = sdktask + ' ' + self.buildtarget
74        self.logger.debug("{}: doing bitbake {} as a prerequisite of the test"\
75                .format(self.classname, bbargs))
76        if bitbake(bbargs).status:
77            self.logger.debug("{} Failed to bitbake {}"\
78                    .format(self.classname, bbargs))
79            self.skipTest("{}: Cannot setup testing scenario"\
80                    .format(self.classname))
81
82
83        pkgdata_dir = reverse_dir = {}
84        mfilename = mpath = m_entry = {}
85        # get manifest location based on target to query about
86        d_target= dict(target = self.buildtarget,
87                         host = 'nativesdk-packagegroup-sdk-host')
88        try:
89            mdir = self.get_dir_from_bb_var('SDK_DEPLOY', self.buildtarget)
90            for k in d_target.keys():
91                toolchain_outputname = get_bb_var('TOOLCHAIN_OUTPUTNAME', self.buildtarget)
92                mfilename[k] = "{}.{}.manifest".format(toolchain_outputname, k)
93                mpath[k] = os.path.join(mdir, mfilename[k])
94                if not os.path.isfile(mpath[k]):
95                    self.logger.debug("{}: {} does not exist".format(
96                        self.classname, mpath[k]))
97                    raise IOError
98                m_entry[k] = ManifestEntry(mpath[k])
99
100                pkgdata_dir[k] = self.get_dir_from_bb_var('PKGDATA_DIR',
101                        d_target[k])
102                reverse_dir[k] = os.path.join(pkgdata_dir[k],
103                        'runtime-reverse')
104                if not os.path.exists(reverse_dir[k]):
105                    self.logger.debug("{}: {} does not exist".format(
106                        self.classname, reverse_dir[k]))
107                    raise IOError
108        except OSError:
109            raise self.skipTest("{}: Error in obtaining manifest dirs"\
110                .format(self.classname))
111        except IOError:
112            msg = "{}: Error cannot find manifests in the specified dir:\n{}"\
113                    .format(self.classname, mdir)
114            self.fail(msg)
115
116        for k in d_target.keys():
117            self.logger.debug("{}: Check manifest {}".format(
118                self.classname, m_entry[k].file))
119
120            m_entry[k].missing = self.check_manifest_entries(\
121                                               m_entry[k].file,reverse_dir[k])
122            if m_entry[k].missing:
123                msg = '{}: {} Error has the following missing entries'\
124                        .format(self.classname, m_entry[k].file)
125                logmsg = msg+':\n'+'\n'.join(m_entry[k].missing)
126                self.logger.debug(logmsg)
127                self.logger.info(msg)
128                self.fail(logmsg)
129
130    def test_image_manifest_entries(self):
131        '''Verifying the image manifest entries exist'''
132
133        # get manifest location based on target to query about
134        try:
135            mdir = self.get_dir_from_bb_var('DEPLOY_DIR_IMAGE',
136                                                self.buildtarget)
137            mfilename = get_bb_var("IMAGE_LINK_NAME", self.buildtarget)\
138                    + ".manifest"
139            mpath = os.path.join(mdir, mfilename)
140            if not os.path.isfile(mpath): raise IOError
141            m_entry = ManifestEntry(mpath)
142
143            pkgdata_dir = {}
144            pkgdata_dir = self.get_dir_from_bb_var('PKGDATA_DIR',
145                                                self.buildtarget)
146            revdir = os.path.join(pkgdata_dir, 'runtime-reverse')
147            if not os.path.exists(revdir): raise IOError
148        except OSError:
149            raise self.skipTest("{}: Error in obtaining manifest dirs"\
150                .format(self.classname))
151        except IOError:
152            msg = "{}: Error cannot find manifests in dir:\n{}"\
153                    .format(self.classname, mdir)
154            self.fail(msg)
155
156        self.logger.debug("{}: Check manifest {}"\
157                            .format(self.classname, m_entry.file))
158        m_entry.missing = self.check_manifest_entries(\
159                                                    m_entry.file, revdir)
160        if m_entry.missing:
161            msg = '{}: {} Error has the following missing entries'\
162                    .format(self.classname, m_entry.file)
163            logmsg = msg+':\n'+'\n'.join(m_entry.missing)
164            self.logger.debug(logmsg)
165            self.logger.info(msg)
166            self.fail(logmsg)
167