diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | classes/qemuboot-testimage-network.bbclass | 17 | ||||
| -rw-r--r-- | lib/oeqa/runtime/cases/xtf_minimal.py | 116 | ||||
| -rw-r--r-- | recipes-extended/images/xen-image-minimal.bb | 2 | ||||
| -rw-r--r-- | recipes-extended/images/xtf-image.bb | 15 |
5 files changed, 150 insertions, 1 deletions
| @@ -6,3 +6,4 @@ pyshtables.py | |||
| 6 | /*.patch | 6 | /*.patch |
| 7 | *~ | 7 | *~ |
| 8 | scripts/lib/wic/plugins/source/__pycache__ | 8 | scripts/lib/wic/plugins/source/__pycache__ |
| 9 | lib/oeqa/runtime/cases/__pycache__ | ||
diff --git a/classes/qemuboot-testimage-network.bbclass b/classes/qemuboot-testimage-network.bbclass new file mode 100644 index 00000000..18af1eea --- /dev/null +++ b/classes/qemuboot-testimage-network.bbclass | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | # The recipe for init-ifupdown in core has a special-case for all | ||
| 2 | # the Qemu MACHINES: it removes all external network interfaces | ||
| 3 | # by default. However, eth0 is needed for testimage, so enable it here. | ||
| 4 | enable_runqemu_network() { | ||
| 5 | : # no-op for non-qemu MACHINES | ||
| 6 | } | ||
| 7 | enable_runqemu_network:qemuall() { | ||
| 8 | if ! grep -q eth0 "${IMAGE_ROOTFS}${sysconfdir}/network/interfaces" ; then | ||
| 9 | cat <<EOF >>${IMAGE_ROOTFS}${sysconfdir}/network/interfaces | ||
| 10 | |||
| 11 | # Network for testimage | ||
| 12 | auto eth0 | ||
| 13 | iface eth0 inet dhcp | ||
| 14 | EOF | ||
| 15 | fi | ||
| 16 | } | ||
| 17 | ROOTFS_POSTPROCESS_COMMAND += 'enable_runqemu_network;' | ||
diff --git a/lib/oeqa/runtime/cases/xtf_minimal.py b/lib/oeqa/runtime/cases/xtf_minimal.py new file mode 100644 index 00000000..6094cd92 --- /dev/null +++ b/lib/oeqa/runtime/cases/xtf_minimal.py | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | # | ||
| 2 | # SPDX-License-Identifier: MIT | ||
| 3 | # | ||
| 4 | # Author: Christopher Clark | ||
| 5 | # Copyright (c) Star Lab Corp, 2021 | ||
| 6 | # | ||
| 7 | # Integration of the Xen Test Framework (XTF) into OpenEmbedded QA | ||
| 8 | # | ||
| 9 | # Since not all XTF test cases are appropriate for all test environments, | ||
| 10 | # images or machine configurations the selection of XTF test cases to run | ||
| 11 | # is determined by variables that can be set in an image recipe. | ||
| 12 | # | ||
| 13 | # * XTF_TEST_CASES_POPULATE | ||
| 14 | # Specifies the list of queries passed to xtf-runner to populate the test list. | ||
| 15 | # eg. 'pv64 livepatch-priv-check' | ||
| 16 | # | ||
| 17 | # Since the space character is meaningful and may be required within a populate clause, | ||
| 18 | # the '|' character is used for separating multiple queries. | ||
| 19 | # eg. 'pv64 livepatch-priv-check|pv32pae selftest' | ||
| 20 | # | ||
| 21 | # * XTF_TEST_CASES_SKIP | ||
| 22 | # A space-separate list of test cases that should be skipped even if returned | ||
| 23 | # from the queries specified in XTF_TEST_CASES_POPULATE. | ||
| 24 | # eg. 'test-pv64-livepatch-priv-check' | ||
| 25 | # | ||
| 26 | # * XTF_TEST_CASES_REQUIRE | ||
| 27 | # A space-separate list of test cases that must not be skipped even if missing | ||
| 28 | # from the results of the queries specified in XTF_TEST_CASES_POPULATE. | ||
| 29 | |||
| 30 | #---------- | ||
| 31 | # The default single test case here is chosen because it exercises XTF | ||
| 32 | # and just Xen itself rather than any specifics of the hardware | ||
| 33 | # (virtual or not) that Xen is running on. | ||
| 34 | # TODO: this is an x86-specific test - revisit this choice when XTF supports Arm | ||
| 35 | DEFAULT_POPULATE = 'pv64 livepatch-priv-check' | ||
| 36 | #---------- | ||
| 37 | |||
| 38 | import json | ||
| 39 | from oeqa.runtime.case import OERuntimeTestCase | ||
| 40 | from oeqa.core.decorator.depends import OETestDepends | ||
| 41 | from oeqa.core.decorator.oetimeout import OETimeout | ||
| 42 | from oeqa.runtime.decorator.package import OEHasPackage | ||
| 43 | |||
| 44 | def xtf_runner_exit_status(state): | ||
| 45 | """ Convert a xtf-runner exit code to a test result. """ | ||
| 46 | return { 0: "SUCCESS", | ||
| 47 | 1: "sys.exit 1", | ||
| 48 | 2: "sys.exit 2", | ||
| 49 | 3: "SKIP", | ||
| 50 | 4: "ERROR", | ||
| 51 | 5: "FAILURE", | ||
| 52 | 6: "CRASH", | ||
| 53 | }[state] | ||
| 54 | |||
| 55 | xtf_rundir = '/usr/libexec/xtf' | ||
| 56 | |||
| 57 | class XTFMinimalTest(OERuntimeTestCase): | ||
| 58 | |||
| 59 | def query_xtf_cases(self, query_item): | ||
| 60 | (status, output) = self.target.run( | ||
| 61 | 'cd %s; ./xtf-runner --list %s' % \ | ||
| 62 | (xtf_rundir, query_item)) | ||
| 63 | self.assertTrue(status == 0, msg='XTF runner failed') | ||
| 64 | |||
| 65 | populate_case_lines = output.split('\n') | ||
| 66 | while '' in populate_case_lines: | ||
| 67 | populate_case_lines.remove('') | ||
| 68 | |||
| 69 | return list(map(lambda x: x.lstrip().rstrip(), populate_case_lines)) | ||
| 70 | |||
| 71 | def get_xtf_case_list(self): | ||
| 72 | xtf_cases = [] | ||
| 73 | |||
| 74 | populate = self.tc.td.get('XTF_TEST_CASES_POPULATE') | ||
| 75 | skip = self.tc.td.get('XTF_TEST_CASES_SKIP') | ||
| 76 | require = self.tc.td.get('XTF_TEST_CASES_REQUIRE') | ||
| 77 | |||
| 78 | if populate is None: | ||
| 79 | populate = DEFAULT_POPULATE | ||
| 80 | |||
| 81 | for query_item in populate.split('|'): | ||
| 82 | xtf_cases.extend( self.query_xtf_cases(query_item) ) | ||
| 83 | |||
| 84 | if skip is not None: | ||
| 85 | for skip_item in skip.split(' '): | ||
| 86 | while skip_item in xtf_cases: | ||
| 87 | xtf_cases.remove(skip_item) | ||
| 88 | |||
| 89 | if require is not None: | ||
| 90 | for require_item in require.split(' '): | ||
| 91 | if require_item == '': | ||
| 92 | continue | ||
| 93 | if not require_item in xtf_cases: | ||
| 94 | xtf_cases.append(require_item) | ||
| 95 | |||
| 96 | self.logger.info('XTF cases: %s' % str(xtf_cases)) | ||
| 97 | return xtf_cases | ||
| 98 | |||
| 99 | def run_xtf_case(self, xtf_case_name): | ||
| 100 | (status, output) = self.target.run('cd %s; ./xtf-runner %s' % \ | ||
| 101 | (xtf_rundir, xtf_case_name)) | ||
| 102 | self.assertTrue(status == 0, msg='XTF test %s failed: %s' % \ | ||
| 103 | (xtf_case_name, xtf_runner_exit_status(status))) | ||
| 104 | |||
| 105 | @OETimeout(2400) | ||
| 106 | @OETestDepends(['ssh.SSHTest.test_ssh']) | ||
| 107 | @OEHasPackage(['xtf']) | ||
| 108 | @OEHasPackage(['xen-tools']) | ||
| 109 | def test_xtf_minimal(self): | ||
| 110 | |||
| 111 | xtf_cases = self.get_xtf_case_list() | ||
| 112 | |||
| 113 | for xtf_case_name in xtf_cases: | ||
| 114 | self.logger.debug('Running XTF case: %s' % xtf_case_name) | ||
| 115 | |||
| 116 | self.run_xtf_case(xtf_case_name) | ||
diff --git a/recipes-extended/images/xen-image-minimal.bb b/recipes-extended/images/xen-image-minimal.bb index fbdd007b..ea596ceb 100644 --- a/recipes-extended/images/xen-image-minimal.bb +++ b/recipes-extended/images/xen-image-minimal.bb | |||
| @@ -31,7 +31,7 @@ XEN_PCIBACK_MODULE:x86-64 = "kernel-module-xen-pciback" | |||
| 31 | 31 | ||
| 32 | LICENSE = "MIT" | 32 | LICENSE = "MIT" |
| 33 | 33 | ||
| 34 | inherit core-image qemuboot-xen-defaults qemuboot-xen-dtb | 34 | inherit core-image qemuboot-xen-defaults qemuboot-xen-dtb qemuboot-testimage-network |
| 35 | 35 | ||
| 36 | do_check_xen_state() { | 36 | do_check_xen_state() { |
| 37 | if [ "${@bb.utils.contains('DISTRO_FEATURES', 'xen', ' yes', 'no', d)}" = "no" ]; then | 37 | if [ "${@bb.utils.contains('DISTRO_FEATURES', 'xen', ' yes', 'no', d)}" = "no" ]; then |
diff --git a/recipes-extended/images/xtf-image.bb b/recipes-extended/images/xtf-image.bb index b73e4a59..a78959df 100644 --- a/recipes-extended/images/xtf-image.bb +++ b/recipes-extended/images/xtf-image.bb | |||
| @@ -11,9 +11,24 @@ DESCRIPTION = "A minimal Xen Test Framework (XTF) image for testing the Xen hype | |||
| 11 | # ./xtf-runner --list pv | 11 | # ./xtf-runner --list pv |
| 12 | # # run an example test: | 12 | # # run an example test: |
| 13 | # ./xtf-runner test-pv64-livepatch-priv-check | 13 | # ./xtf-runner test-pv64-livepatch-priv-check |
| 14 | # | ||
| 15 | # This image also supports the OE QA framework, so XTF tests can be | ||
| 16 | # run from bitbake by adding the following (or similar) to local.conf: | ||
| 17 | # | ||
| 18 | # INHERIT += "testimage" | ||
| 19 | # QEMU_USE_SLIRP = "1" | ||
| 20 | # TEST_SERVER_IP = "127.0.0.1" | ||
| 21 | # | ||
| 22 | # and the tests that are configured (see the xtf-oeqa-conf package) | ||
| 23 | # can be run with: bitbake -c testimage xtf-image | ||
| 24 | # | ||
| 25 | # For testimage, see the qemu boot log: ${WORKDIR}/testimage/qemu_boot_log.* | ||
| 26 | # and the test log: ${WORKDIR}/temp/log.do_testimage | ||
| 14 | 27 | ||
| 15 | IMAGE_NAME="xtf" | 28 | IMAGE_NAME="xtf" |
| 16 | 29 | ||
| 17 | IMAGE_INSTALL:append = " xtf" | 30 | IMAGE_INSTALL:append = " xtf" |
| 18 | 31 | ||
| 32 | DEFAULT_TEST_SUITES:append = " xtf_minimal" | ||
| 33 | |||
| 19 | QB_DEFAULT_FSTYPE_x86-64 = "wic" | 34 | QB_DEFAULT_FSTYPE_x86-64 = "wic" |
