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