1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# Copyright 2018 by Garmin Ltd. or its subsidiaries 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# SPDX-License-Identifier: MIT 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun 7*4882a593Smuzhiyunfrom oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor 8*4882a593Smuzhiyun 9*4882a593Smuzhiyunclass TestSDKBase(object): 10*4882a593Smuzhiyun @staticmethod 11*4882a593Smuzhiyun def get_sdk_configuration(d, test_type): 12*4882a593Smuzhiyun import platform 13*4882a593Smuzhiyun import oe.lsb 14*4882a593Smuzhiyun from oeqa.utils.metadata import get_layers 15*4882a593Smuzhiyun configuration = {'TEST_TYPE': test_type, 16*4882a593Smuzhiyun 'MACHINE': d.getVar("MACHINE"), 17*4882a593Smuzhiyun 'SDKMACHINE': d.getVar("SDKMACHINE"), 18*4882a593Smuzhiyun 'IMAGE_BASENAME': d.getVar("IMAGE_BASENAME"), 19*4882a593Smuzhiyun 'IMAGE_PKGTYPE': d.getVar("IMAGE_PKGTYPE"), 20*4882a593Smuzhiyun 'STARTTIME': d.getVar("DATETIME"), 21*4882a593Smuzhiyun 'HOST_DISTRO': oe.lsb.distro_identifier().replace(' ', '-'), 22*4882a593Smuzhiyun 'LAYERS': get_layers(d.getVar("BBLAYERS"))} 23*4882a593Smuzhiyun return configuration 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun @staticmethod 26*4882a593Smuzhiyun def get_sdk_json_result_dir(d): 27*4882a593Smuzhiyun json_result_dir = os.path.join(d.getVar("LOG_DIR"), 'oeqa') 28*4882a593Smuzhiyun custom_json_result_dir = d.getVar("OEQA_JSON_RESULT_DIR") 29*4882a593Smuzhiyun if custom_json_result_dir: 30*4882a593Smuzhiyun json_result_dir = custom_json_result_dir 31*4882a593Smuzhiyun return json_result_dir 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun @staticmethod 34*4882a593Smuzhiyun def get_sdk_result_id(configuration): 35*4882a593Smuzhiyun return '%s_%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['IMAGE_BASENAME'], configuration['SDKMACHINE'], configuration['MACHINE'], configuration['STARTTIME']) 36*4882a593Smuzhiyun 37*4882a593Smuzhiyunclass TestSDK(TestSDKBase): 38*4882a593Smuzhiyun context_executor_class = OESDKTestContextExecutor 39*4882a593Smuzhiyun context_class = OESDKTestContext 40*4882a593Smuzhiyun test_type = 'sdk' 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun def get_tcname(self, d): 43*4882a593Smuzhiyun """ 44*4882a593Smuzhiyun Get the name of the SDK file 45*4882a593Smuzhiyun """ 46*4882a593Smuzhiyun return d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh") 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun def extract_sdk(self, tcname, sdk_dir, d): 49*4882a593Smuzhiyun """ 50*4882a593Smuzhiyun Extract the SDK to the specified location 51*4882a593Smuzhiyun """ 52*4882a593Smuzhiyun import subprocess 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun try: 55*4882a593Smuzhiyun subprocess.check_output("cd %s; %s <<EOF\n./\nY\nEOF" % (sdk_dir, tcname), shell=True) 56*4882a593Smuzhiyun except subprocess.CalledProcessError as e: 57*4882a593Smuzhiyun bb.fatal("Couldn't install the SDK:\n%s" % e.output.decode("utf-8")) 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun def setup_context(self, d): 60*4882a593Smuzhiyun """ 61*4882a593Smuzhiyun Return a dictionary of additional arguments that should be passed to 62*4882a593Smuzhiyun the context_class on construction 63*4882a593Smuzhiyun """ 64*4882a593Smuzhiyun return dict() 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun def run(self, d): 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun import os 69*4882a593Smuzhiyun import subprocess 70*4882a593Smuzhiyun import json 71*4882a593Smuzhiyun import logging 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun from bb.utils import export_proxies 74*4882a593Smuzhiyun from oeqa.utils import make_logger_bitbake_compatible 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun pn = d.getVar("PN") 77*4882a593Smuzhiyun logger = make_logger_bitbake_compatible(logging.getLogger("BitBake")) 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun # sdk use network for download projects for build 80*4882a593Smuzhiyun export_proxies(d) 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun tcname = self.get_tcname(d) 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun if not os.path.exists(tcname): 85*4882a593Smuzhiyun bb.fatal("The toolchain %s is not built. Build it before running the tests: 'bitbake <image> -c populate_sdk' ." % tcname) 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.testdata.json") 88*4882a593Smuzhiyun test_data = json.load(open(tdname, "r")) 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun target_pkg_manifest = self.context_executor_class._load_manifest( 91*4882a593Smuzhiyun d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.target.manifest")) 92*4882a593Smuzhiyun host_pkg_manifest = self.context_executor_class._load_manifest( 93*4882a593Smuzhiyun d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.host.manifest")) 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun processes = d.getVar("TESTIMAGE_NUMBER_THREADS") or d.getVar("BB_NUMBER_THREADS") 96*4882a593Smuzhiyun if processes: 97*4882a593Smuzhiyun try: 98*4882a593Smuzhiyun import testtools, subunit 99*4882a593Smuzhiyun except ImportError: 100*4882a593Smuzhiyun bb.warn("Failed to import testtools or subunit, the testcases will run serially") 101*4882a593Smuzhiyun processes = None 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun sdk_dir = d.expand("${WORKDIR}/testimage-sdk/") 104*4882a593Smuzhiyun bb.utils.remove(sdk_dir, True) 105*4882a593Smuzhiyun bb.utils.mkdirhier(sdk_dir) 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun context_args = self.setup_context(d) 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun self.extract_sdk(tcname, sdk_dir, d) 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun fail = False 112*4882a593Smuzhiyun sdk_envs = self.context_executor_class._get_sdk_environs(sdk_dir) 113*4882a593Smuzhiyun for s in sdk_envs: 114*4882a593Smuzhiyun sdk_env = sdk_envs[s] 115*4882a593Smuzhiyun bb.plain("SDK testing environment: %s" % s) 116*4882a593Smuzhiyun tc = self.context_class(td=test_data, logger=logger, sdk_dir=sdk_dir, 117*4882a593Smuzhiyun sdk_env=sdk_env, target_pkg_manifest=target_pkg_manifest, 118*4882a593Smuzhiyun host_pkg_manifest=host_pkg_manifest, **context_args) 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun try: 121*4882a593Smuzhiyun tc.loadTests(self.context_executor_class.default_cases) 122*4882a593Smuzhiyun except Exception as e: 123*4882a593Smuzhiyun import traceback 124*4882a593Smuzhiyun bb.fatal("Loading tests failed:\n%s" % traceback.format_exc()) 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun if processes: 127*4882a593Smuzhiyun result = tc.runTests(processes=int(processes)) 128*4882a593Smuzhiyun else: 129*4882a593Smuzhiyun result = tc.runTests() 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun component = "%s %s" % (pn, self.context_executor_class.name) 132*4882a593Smuzhiyun context_msg = "%s:%s" % (os.path.basename(tcname), os.path.basename(sdk_env)) 133*4882a593Smuzhiyun configuration = self.get_sdk_configuration(d, self.test_type) 134*4882a593Smuzhiyun result.logDetails(self.get_sdk_json_result_dir(d), 135*4882a593Smuzhiyun configuration, 136*4882a593Smuzhiyun self.get_sdk_result_id(configuration)) 137*4882a593Smuzhiyun result.logSummary(component, context_msg) 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun if not result.wasSuccessful(): 140*4882a593Smuzhiyun fail = True 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun if fail: 143*4882a593Smuzhiyun bb.fatal("%s - FAILED - check the task log and the commands log" % pn) 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun 146