1c342db35SBrad Bishop#
2*92b42cb3SPatrick Williams# Copyright OpenEmbedded Contributors
3*92b42cb3SPatrick Williams#
4c342db35SBrad Bishop# SPDX-License-Identifier: MIT
5c342db35SBrad Bishop#
6c342db35SBrad Bishop
7eb8dc403SDave Cobbleyimport os
8eb8dc403SDave Cobbleyimport json
9eb8dc403SDave Cobbleyimport shutil
10eb8dc403SDave Cobbley
11eb8dc403SDave Cobbleyfrom oeqa.core.utils.test import getCaseFile, getCaseMethod
12eb8dc403SDave Cobbley
13eb8dc403SDave Cobbleydef get_package_manager(d, root_path):
14eb8dc403SDave Cobbley    """
15eb8dc403SDave Cobbley    Returns an OE package manager that can install packages in root_path.
16eb8dc403SDave Cobbley    """
17635e0e46SAndrew Geissler    from oe.package_manager.rpm import RpmPM
18635e0e46SAndrew Geissler    from oe.package_manager.ipk import OpkgPM
19635e0e46SAndrew Geissler    from oe.package_manager.deb import DpkgPM
20eb8dc403SDave Cobbley
21eb8dc403SDave Cobbley    pkg_class = d.getVar("IMAGE_PKGTYPE")
22eb8dc403SDave Cobbley    if pkg_class == "rpm":
23eb8dc403SDave Cobbley        pm = RpmPM(d,
24eb8dc403SDave Cobbley                   root_path,
25eb8dc403SDave Cobbley                   d.getVar('TARGET_VENDOR'),
26eb8dc403SDave Cobbley                   filterbydependencies=False)
27eb8dc403SDave Cobbley        pm.create_configs()
28eb8dc403SDave Cobbley
29eb8dc403SDave Cobbley    elif pkg_class == "ipk":
30eb8dc403SDave Cobbley        pm = OpkgPM(d,
31eb8dc403SDave Cobbley                    root_path,
32eb8dc403SDave Cobbley                    d.getVar("IPKGCONF_TARGET"),
331a4b7ee2SBrad Bishop                    d.getVar("ALL_MULTILIB_PACKAGE_ARCHS"),
341a4b7ee2SBrad Bishop                    filterbydependencies=False)
35eb8dc403SDave Cobbley
36eb8dc403SDave Cobbley    elif pkg_class == "deb":
37eb8dc403SDave Cobbley        pm = DpkgPM(d,
38eb8dc403SDave Cobbley                    root_path,
39eb8dc403SDave Cobbley                    d.getVar('PACKAGE_ARCHS'),
401a4b7ee2SBrad Bishop                    d.getVar('DPKG_ARCH'),
411a4b7ee2SBrad Bishop                    filterbydependencies=False)
42eb8dc403SDave Cobbley
43eb8dc403SDave Cobbley    pm.write_index()
44eb8dc403SDave Cobbley    pm.update()
45eb8dc403SDave Cobbley
46eb8dc403SDave Cobbley    return pm
47eb8dc403SDave Cobbley
48eb8dc403SDave Cobbleydef find_packages_to_extract(test_suite):
49eb8dc403SDave Cobbley    """
50eb8dc403SDave Cobbley    Returns packages to extract required by runtime tests.
51eb8dc403SDave Cobbley    """
52eb8dc403SDave Cobbley    from oeqa.core.utils.test import getSuiteCasesFiles
53eb8dc403SDave Cobbley
54eb8dc403SDave Cobbley    needed_packages = {}
55eb8dc403SDave Cobbley    files = getSuiteCasesFiles(test_suite)
56eb8dc403SDave Cobbley
57eb8dc403SDave Cobbley    for f in set(files):
58eb8dc403SDave Cobbley        json_file = _get_json_file(f)
59eb8dc403SDave Cobbley        if json_file:
60eb8dc403SDave Cobbley            needed_packages.update(_get_needed_packages(json_file))
61eb8dc403SDave Cobbley
62eb8dc403SDave Cobbley    return needed_packages
63eb8dc403SDave Cobbley
64eb8dc403SDave Cobbleydef _get_json_file(module_path):
65eb8dc403SDave Cobbley    """
66eb8dc403SDave Cobbley    Returns the path of the JSON file for a module, empty if doesn't exitst.
67eb8dc403SDave Cobbley    """
68eb8dc403SDave Cobbley
69eb8dc403SDave Cobbley    json_file = '%s.json' % module_path.rsplit('.', 1)[0]
70eb8dc403SDave Cobbley    if os.path.isfile(module_path) and os.path.isfile(json_file):
71eb8dc403SDave Cobbley        return json_file
72eb8dc403SDave Cobbley    else:
73eb8dc403SDave Cobbley        return ''
74eb8dc403SDave Cobbley
75eb8dc403SDave Cobbleydef _get_needed_packages(json_file, test=None):
76eb8dc403SDave Cobbley    """
77eb8dc403SDave Cobbley    Returns a dict with needed packages based on a JSON file.
78eb8dc403SDave Cobbley
79eb8dc403SDave Cobbley    If a test is specified it will return the dict just for that test.
80eb8dc403SDave Cobbley    """
81eb8dc403SDave Cobbley    needed_packages = {}
82eb8dc403SDave Cobbley
83eb8dc403SDave Cobbley    with open(json_file) as f:
84eb8dc403SDave Cobbley        test_packages = json.load(f)
85eb8dc403SDave Cobbley    for key,value in test_packages.items():
86eb8dc403SDave Cobbley        needed_packages[key] = value
87eb8dc403SDave Cobbley
88eb8dc403SDave Cobbley    if test:
89eb8dc403SDave Cobbley        if test in needed_packages:
90eb8dc403SDave Cobbley            needed_packages = needed_packages[test]
91eb8dc403SDave Cobbley        else:
92eb8dc403SDave Cobbley            needed_packages = {}
93eb8dc403SDave Cobbley
94eb8dc403SDave Cobbley    return needed_packages
95eb8dc403SDave Cobbley
96eb8dc403SDave Cobbleydef extract_packages(d, needed_packages):
97eb8dc403SDave Cobbley    """
98eb8dc403SDave Cobbley    Extract packages that will be needed during runtime.
99eb8dc403SDave Cobbley    """
100eb8dc403SDave Cobbley
101eb8dc403SDave Cobbley    import bb
102eb8dc403SDave Cobbley    import oe.path
103eb8dc403SDave Cobbley
104eb8dc403SDave Cobbley    extracted_path = d.getVar('TEST_EXTRACTED_DIR')
105eb8dc403SDave Cobbley
106eb8dc403SDave Cobbley    for key,value in needed_packages.items():
107eb8dc403SDave Cobbley        packages = ()
108eb8dc403SDave Cobbley        if isinstance(value, dict):
109eb8dc403SDave Cobbley            packages = (value, )
110eb8dc403SDave Cobbley        elif isinstance(value, list):
111eb8dc403SDave Cobbley            packages = value
112eb8dc403SDave Cobbley        else:
113eb8dc403SDave Cobbley            bb.fatal('Failed to process needed packages for %s; '
114eb8dc403SDave Cobbley                     'Value must be a dict or list' % key)
115eb8dc403SDave Cobbley
116eb8dc403SDave Cobbley        for package in packages:
117eb8dc403SDave Cobbley            pkg = package['pkg']
118eb8dc403SDave Cobbley            rm = package.get('rm', False)
119eb8dc403SDave Cobbley            extract = package.get('extract', True)
120eb8dc403SDave Cobbley
121eb8dc403SDave Cobbley            if extract:
122d1e89497SAndrew Geissler                #logger.debug('Extracting %s' % pkg)
123eb8dc403SDave Cobbley                dst_dir = os.path.join(extracted_path, pkg)
124eb8dc403SDave Cobbley                # Same package used for more than one test,
125eb8dc403SDave Cobbley                # don't need to extract again.
126eb8dc403SDave Cobbley                if os.path.exists(dst_dir):
127eb8dc403SDave Cobbley                    continue
128eb8dc403SDave Cobbley
129eb8dc403SDave Cobbley                # Extract package and copy it to TEST_EXTRACTED_DIR
130eb8dc403SDave Cobbley                pkg_dir = _extract_in_tmpdir(d, pkg)
131eb8dc403SDave Cobbley                oe.path.copytree(pkg_dir, dst_dir)
132eb8dc403SDave Cobbley                shutil.rmtree(pkg_dir)
133eb8dc403SDave Cobbley
134eb8dc403SDave Cobbley            else:
135d1e89497SAndrew Geissler                #logger.debug('Copying %s' % pkg)
136eb8dc403SDave Cobbley                _copy_package(d, pkg)
137eb8dc403SDave Cobbley
138eb8dc403SDave Cobbleydef _extract_in_tmpdir(d, pkg):
139eb8dc403SDave Cobbley    """"
140eb8dc403SDave Cobbley    Returns path to a temp directory where the package was
141eb8dc403SDave Cobbley    extracted without dependencies.
142eb8dc403SDave Cobbley    """
143eb8dc403SDave Cobbley
144eb8dc403SDave Cobbley    from oeqa.utils.package_manager import get_package_manager
145eb8dc403SDave Cobbley
146eb8dc403SDave Cobbley    pkg_path = os.path.join(d.getVar('TEST_INSTALL_TMP_DIR'), pkg)
147eb8dc403SDave Cobbley    pm = get_package_manager(d, pkg_path)
148eb8dc403SDave Cobbley    extract_dir = pm.extract(pkg)
149eb8dc403SDave Cobbley    shutil.rmtree(pkg_path)
150eb8dc403SDave Cobbley
151eb8dc403SDave Cobbley    return extract_dir
152eb8dc403SDave Cobbley
153eb8dc403SDave Cobbleydef _copy_package(d, pkg):
154eb8dc403SDave Cobbley    """
155eb8dc403SDave Cobbley    Copy the RPM, DEB or IPK package to dst_dir
156eb8dc403SDave Cobbley    """
157eb8dc403SDave Cobbley
158eb8dc403SDave Cobbley    from oeqa.utils.package_manager import get_package_manager
159eb8dc403SDave Cobbley
160eb8dc403SDave Cobbley    pkg_path = os.path.join(d.getVar('TEST_INSTALL_TMP_DIR'), pkg)
161eb8dc403SDave Cobbley    dst_dir = d.getVar('TEST_PACKAGED_DIR')
162eb8dc403SDave Cobbley    pm = get_package_manager(d, pkg_path)
163eb8dc403SDave Cobbley    pkg_info = pm.package_info(pkg)
164eb8dc403SDave Cobbley    file_path = pkg_info[pkg]['filepath']
165eb8dc403SDave Cobbley    shutil.copy2(file_path, dst_dir)
166eb8dc403SDave Cobbley    shutil.rmtree(pkg_path)
167eb8dc403SDave Cobbley
168eb8dc403SDave Cobbleydef install_package(test_case):
169eb8dc403SDave Cobbley    """
170eb8dc403SDave Cobbley    Installs package in DUT if required.
171eb8dc403SDave Cobbley    """
172eb8dc403SDave Cobbley    needed_packages = test_needs_package(test_case)
173eb8dc403SDave Cobbley    if needed_packages:
174eb8dc403SDave Cobbley        _install_uninstall_packages(needed_packages, test_case, True)
175eb8dc403SDave Cobbley
176eb8dc403SDave Cobbleydef uninstall_package(test_case):
177eb8dc403SDave Cobbley    """
178eb8dc403SDave Cobbley    Uninstalls package in DUT if required.
179eb8dc403SDave Cobbley    """
180eb8dc403SDave Cobbley    needed_packages = test_needs_package(test_case)
181eb8dc403SDave Cobbley    if needed_packages:
182eb8dc403SDave Cobbley        _install_uninstall_packages(needed_packages, test_case, False)
183eb8dc403SDave Cobbley
184eb8dc403SDave Cobbleydef test_needs_package(test_case):
185eb8dc403SDave Cobbley    """
186eb8dc403SDave Cobbley    Checks if a test case requires to install/uninstall packages.
187eb8dc403SDave Cobbley    """
188eb8dc403SDave Cobbley    test_file = getCaseFile(test_case)
189eb8dc403SDave Cobbley    json_file = _get_json_file(test_file)
190eb8dc403SDave Cobbley
191eb8dc403SDave Cobbley    if json_file:
192eb8dc403SDave Cobbley        test_method = getCaseMethod(test_case)
193eb8dc403SDave Cobbley        needed_packages = _get_needed_packages(json_file, test_method)
194eb8dc403SDave Cobbley        if needed_packages:
195eb8dc403SDave Cobbley            return needed_packages
196eb8dc403SDave Cobbley
197eb8dc403SDave Cobbley    return None
198eb8dc403SDave Cobbley
199eb8dc403SDave Cobbleydef _install_uninstall_packages(needed_packages, test_case, install=True):
200eb8dc403SDave Cobbley    """
201eb8dc403SDave Cobbley    Install/Uninstall packages in the DUT without using a package manager
202eb8dc403SDave Cobbley    """
203eb8dc403SDave Cobbley
204eb8dc403SDave Cobbley    if isinstance(needed_packages, dict):
205eb8dc403SDave Cobbley        packages = [needed_packages]
206eb8dc403SDave Cobbley    elif isinstance(needed_packages, list):
207eb8dc403SDave Cobbley        packages = needed_packages
208eb8dc403SDave Cobbley
209eb8dc403SDave Cobbley    for package in packages:
210eb8dc403SDave Cobbley        pkg = package['pkg']
211eb8dc403SDave Cobbley        rm = package.get('rm', False)
212eb8dc403SDave Cobbley        extract = package.get('extract', True)
213eb8dc403SDave Cobbley        src_dir = os.path.join(test_case.tc.extract_dir, pkg)
214eb8dc403SDave Cobbley
215eb8dc403SDave Cobbley        # Install package
216eb8dc403SDave Cobbley        if install and extract:
217eb8dc403SDave Cobbley            test_case.tc.target.copyDirTo(src_dir, '/')
218eb8dc403SDave Cobbley
219eb8dc403SDave Cobbley        # Uninstall package
220eb8dc403SDave Cobbley        elif not install and rm:
221eb8dc403SDave Cobbley            test_case.tc.target.deleteDirStructure(src_dir, '/')
222