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