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