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