From 333d7036ef6cf959a1f883fe93042047bef73497 Mon Sep 17 00:00:00 2001 From: Willian Rampazzo Date: Fri, 5 Nov 2021 12:53:53 -0300 Subject: tests/acceptance: introduce new check-avocado target This introduces a new `make` target, `check-avocado`, and adds a deprecation message about the `check-acceptance` target. This is a preparation for renaming the `tests/acceptance` folder to `tests/avocado`. The plan is to remove the call to the `check-avocado` target one or two months after the release and leave the warning to force people to move to the new `check-avocado` target. Later, the `check-acceptance` target can be removed. The intent is to avoid a direct impact during the current soft freeze. Suggested-by: Philippe Mathieu-Daudé Signed-off-by: Willian Rampazzo Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Acked-by: Thomas Huth Message-Id: <20211105155354.154864-2-willianr@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- tests/Makefile.include | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index 8434a33fe6..8e8ee58493 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -16,7 +16,7 @@ ifneq ($(filter $(all-check-targets), check-softfloat),) @echo " $(MAKE) check-tcg Run TCG tests" @echo " $(MAKE) check-softfloat Run FPU emulation tests" endif - @echo " $(MAKE) check-acceptance Run acceptance (functional) tests for currently configured targets" + @echo " $(MAKE) check-avocado Run avocado (integration) tests for currently configured targets" @echo @echo " $(MAKE) check-report.tap Generates an aggregated TAP test report" @echo " $(MAKE) check-venv Creates a Python venv for tests" @@ -24,7 +24,7 @@ endif @echo @echo "The following are useful for CI builds" @echo " $(MAKE) check-build Build most test binaris" - @echo " $(MAKE) get-vm-images Downloads all images used by acceptance tests, according to configured targets (~350 MB each, 1.5 GB max)" + @echo " $(MAKE) get-vm-images Downloads all images used by avocado tests, according to configured targets (~350 MB each, 1.5 GB max)" @echo @echo @echo "The variable SPEED can be set to control the gtester speed setting." @@ -83,7 +83,7 @@ clean-tcg: $(CLEAN_TCG_TARGET_RULES) # Python venv for running tests -.PHONY: check-venv check-acceptance +.PHONY: check-venv check-avocado check-acceptance check-acceptance-deprecated-warning TESTS_VENV_DIR=$(BUILD_DIR)/tests/venv TESTS_VENV_REQ=$(SRC_PATH)/tests/requirements.txt @@ -127,12 +127,12 @@ get-vm-image-fedora-31-%: check-venv $(call quiet-command, \ $(TESTS_VENV_DIR)/bin/python -m avocado vmimage get \ --distro=fedora --distro-version=31 --arch=$*, \ - "AVOCADO", "Downloading acceptance tests VM image for $*") + "AVOCADO", "Downloading avocado tests VM image for $*") # download all vm images, according to defined targets get-vm-images: check-venv $(patsubst %,get-vm-image-fedora-31-%, $(FEDORA_31_DOWNLOAD)) -check-acceptance: check-venv $(TESTS_RESULTS_DIR) get-vm-images +check-avocado: check-venv $(TESTS_RESULTS_DIR) get-vm-images $(call quiet-command, \ $(TESTS_VENV_DIR)/bin/python -m avocado \ --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \ @@ -142,6 +142,13 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) get-vm-images $(if $(GITLAB_CI),,--failfast) $(AVOCADO_TESTS), \ "AVOCADO", "tests/acceptance") +check-acceptance-deprecated-warning: + @echo + @echo "Note '$(MAKE) check-acceptance' is deprecated, use '$(MAKE) check-avocado' instead." + @echo + +check-acceptance: check-acceptance-deprecated-warning | check-avocado + # Consolidated targets .PHONY: check-block check check-clean get-vm-images -- cgit v1.2.3-55-g7522 From bbbd9b6ec645ca45c2195e894537da4964f1aa12 Mon Sep 17 00:00:00 2001 From: Willian Rampazzo Date: Fri, 5 Nov 2021 12:53:54 -0300 Subject: tests/acceptance: rename tests acceptance to tests avocado In the discussion about renaming the `tests/acceptance` [1], the conclusion was that the folders inside `tests` are related to the framework running the tests and not directly related to the type of the tests. This changes the folder to `tests/avocado` and adjusts the MAKEFILE, the CI related files and the documentation. [1] https://lists.gnu.org/archive/html/qemu-devel/2021-05/msg06553.html Reviewed-by: Niek Linnenbank Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Signed-off-by: Willian Rampazzo Message-Id: <20211105155354.154864-3-willianr@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- .gitlab-ci.d/buildtest-template.yml | 2 +- .gitlab-ci.d/buildtest.yml | 56 +- MAINTAINERS | 52 +- configure | 2 +- docs/devel/build-system.rst | 2 +- docs/devel/ci-definitions.rst.inc | 2 +- docs/devel/testing.rst | 49 +- docs/system/arm/orangepi.rst | 8 +- python/qemu/machine/README.rst | 2 +- python/qemu/qmp/README.rst | 2 +- python/qemu/utils/README.rst | 2 +- tests/Makefile.include | 4 +- tests/acceptance/README.rst | 10 - tests/acceptance/avocado_qemu/__init__.py | 558 --------- tests/acceptance/boot_linux.py | 138 --- tests/acceptance/boot_linux_console.py | 1256 -------------------- tests/acceptance/boot_xen.py | 116 -- tests/acceptance/cpu_queries.py | 34 - tests/acceptance/empty_cpu_model.py | 19 - tests/acceptance/hotplug_cpu.py | 37 - tests/acceptance/info_usernet.py | 29 - tests/acceptance/intel_iommu.py | 119 -- tests/acceptance/linux_initrd.py | 89 -- tests/acceptance/linux_ssh_mips_malta.py | 209 ---- tests/acceptance/machine_arm_canona1100.py | 35 - tests/acceptance/machine_arm_integratorcp.py | 99 -- tests/acceptance/machine_arm_n8x0.py | 49 - tests/acceptance/machine_avr6.py | 50 - tests/acceptance/machine_m68k_nextcube.py | 79 -- tests/acceptance/machine_microblaze.py | 35 - tests/acceptance/machine_mips_fuloong2e.py | 42 - tests/acceptance/machine_mips_loongson3v.py | 39 - tests/acceptance/machine_mips_malta.py | 120 -- tests/acceptance/machine_rx_gdbsim.py | 73 -- tests/acceptance/machine_s390_ccw_virtio.py | 272 ----- tests/acceptance/machine_sparc64_sun4u.py | 36 - tests/acceptance/machine_sparc_leon3.py | 37 - tests/acceptance/migration.py | 81 -- tests/acceptance/multiprocess.py | 95 -- tests/acceptance/pc_cpu_hotplug_props.py | 35 - tests/acceptance/ppc_405.py | 42 - tests/acceptance/ppc_bamboo.py | 39 - tests/acceptance/ppc_mpc8544ds.py | 32 - tests/acceptance/ppc_prep_40p.py | 79 -- tests/acceptance/ppc_pseries.py | 35 - tests/acceptance/ppc_virtex_ml507.py | 34 - tests/acceptance/replay_kernel.py | 524 -------- tests/acceptance/replay_linux.py | 116 -- tests/acceptance/reverse_debugging.py | 210 ---- tests/acceptance/smmu.py | 137 --- tests/acceptance/tcg_plugins.py | 147 --- tests/acceptance/tesseract_utils.py | 46 - tests/acceptance/version.py | 24 - tests/acceptance/virtio-gpu.py | 155 --- tests/acceptance/virtio_check_params.py | 144 --- tests/acceptance/virtio_version.py | 175 --- tests/acceptance/virtiofs_submounts.py | 272 ----- .../virtiofs_submounts.py.data/cleanup.sh | 46 - .../virtiofs_submounts.py.data/guest-cleanup.sh | 30 - .../acceptance/virtiofs_submounts.py.data/guest.sh | 138 --- .../acceptance/virtiofs_submounts.py.data/host.sh | 127 -- tests/acceptance/vnc.py | 53 - tests/acceptance/x86_cpu_model_versions.py | 358 ------ tests/avocado/README.rst | 10 + tests/avocado/avocado_qemu/__init__.py | 558 +++++++++ tests/avocado/boot_linux.py | 138 +++ tests/avocado/boot_linux_console.py | 1256 ++++++++++++++++++++ tests/avocado/boot_xen.py | 116 ++ tests/avocado/cpu_queries.py | 34 + tests/avocado/empty_cpu_model.py | 19 + tests/avocado/hotplug_cpu.py | 37 + tests/avocado/info_usernet.py | 29 + tests/avocado/intel_iommu.py | 119 ++ tests/avocado/linux_initrd.py | 89 ++ tests/avocado/linux_ssh_mips_malta.py | 209 ++++ tests/avocado/machine_arm_canona1100.py | 35 + tests/avocado/machine_arm_integratorcp.py | 99 ++ tests/avocado/machine_arm_n8x0.py | 49 + tests/avocado/machine_avr6.py | 50 + tests/avocado/machine_m68k_nextcube.py | 79 ++ tests/avocado/machine_microblaze.py | 35 + tests/avocado/machine_mips_fuloong2e.py | 42 + tests/avocado/machine_mips_loongson3v.py | 39 + tests/avocado/machine_mips_malta.py | 120 ++ tests/avocado/machine_rx_gdbsim.py | 73 ++ tests/avocado/machine_s390_ccw_virtio.py | 272 +++++ tests/avocado/machine_sparc64_sun4u.py | 36 + tests/avocado/machine_sparc_leon3.py | 37 + tests/avocado/migration.py | 81 ++ tests/avocado/multiprocess.py | 95 ++ tests/avocado/pc_cpu_hotplug_props.py | 35 + tests/avocado/ppc_405.py | 42 + tests/avocado/ppc_bamboo.py | 39 + tests/avocado/ppc_mpc8544ds.py | 32 + tests/avocado/ppc_prep_40p.py | 79 ++ tests/avocado/ppc_pseries.py | 35 + tests/avocado/ppc_virtex_ml507.py | 34 + tests/avocado/replay_kernel.py | 524 ++++++++ tests/avocado/replay_linux.py | 116 ++ tests/avocado/reverse_debugging.py | 210 ++++ tests/avocado/smmu.py | 137 +++ tests/avocado/tcg_plugins.py | 147 +++ tests/avocado/tesseract_utils.py | 46 + tests/avocado/version.py | 24 + tests/avocado/virtio-gpu.py | 155 +++ tests/avocado/virtio_check_params.py | 144 +++ tests/avocado/virtio_version.py | 175 +++ tests/avocado/virtiofs_submounts.py | 272 +++++ .../avocado/virtiofs_submounts.py.data/cleanup.sh | 46 + .../virtiofs_submounts.py.data/guest-cleanup.sh | 30 + tests/avocado/virtiofs_submounts.py.data/guest.sh | 138 +++ tests/avocado/virtiofs_submounts.py.data/host.sh | 127 ++ tests/avocado/vnc.py | 53 + tests/avocado/x86_cpu_model_versions.py | 358 ++++++ 114 files changed, 6845 insertions(+), 6846 deletions(-) delete mode 100644 tests/acceptance/README.rst delete mode 100644 tests/acceptance/avocado_qemu/__init__.py delete mode 100644 tests/acceptance/boot_linux.py delete mode 100644 tests/acceptance/boot_linux_console.py delete mode 100644 tests/acceptance/boot_xen.py delete mode 100644 tests/acceptance/cpu_queries.py delete mode 100644 tests/acceptance/empty_cpu_model.py delete mode 100644 tests/acceptance/hotplug_cpu.py delete mode 100644 tests/acceptance/info_usernet.py delete mode 100644 tests/acceptance/intel_iommu.py delete mode 100644 tests/acceptance/linux_initrd.py delete mode 100644 tests/acceptance/linux_ssh_mips_malta.py delete mode 100644 tests/acceptance/machine_arm_canona1100.py delete mode 100644 tests/acceptance/machine_arm_integratorcp.py delete mode 100644 tests/acceptance/machine_arm_n8x0.py delete mode 100644 tests/acceptance/machine_avr6.py delete mode 100644 tests/acceptance/machine_m68k_nextcube.py delete mode 100644 tests/acceptance/machine_microblaze.py delete mode 100644 tests/acceptance/machine_mips_fuloong2e.py delete mode 100644 tests/acceptance/machine_mips_loongson3v.py delete mode 100644 tests/acceptance/machine_mips_malta.py delete mode 100644 tests/acceptance/machine_rx_gdbsim.py delete mode 100644 tests/acceptance/machine_s390_ccw_virtio.py delete mode 100644 tests/acceptance/machine_sparc64_sun4u.py delete mode 100644 tests/acceptance/machine_sparc_leon3.py delete mode 100644 tests/acceptance/migration.py delete mode 100644 tests/acceptance/multiprocess.py delete mode 100644 tests/acceptance/pc_cpu_hotplug_props.py delete mode 100644 tests/acceptance/ppc_405.py delete mode 100644 tests/acceptance/ppc_bamboo.py delete mode 100644 tests/acceptance/ppc_mpc8544ds.py delete mode 100644 tests/acceptance/ppc_prep_40p.py delete mode 100644 tests/acceptance/ppc_pseries.py delete mode 100644 tests/acceptance/ppc_virtex_ml507.py delete mode 100644 tests/acceptance/replay_kernel.py delete mode 100644 tests/acceptance/replay_linux.py delete mode 100644 tests/acceptance/reverse_debugging.py delete mode 100644 tests/acceptance/smmu.py delete mode 100644 tests/acceptance/tcg_plugins.py delete mode 100644 tests/acceptance/tesseract_utils.py delete mode 100644 tests/acceptance/version.py delete mode 100644 tests/acceptance/virtio-gpu.py delete mode 100644 tests/acceptance/virtio_check_params.py delete mode 100644 tests/acceptance/virtio_version.py delete mode 100644 tests/acceptance/virtiofs_submounts.py delete mode 100644 tests/acceptance/virtiofs_submounts.py.data/cleanup.sh delete mode 100644 tests/acceptance/virtiofs_submounts.py.data/guest-cleanup.sh delete mode 100644 tests/acceptance/virtiofs_submounts.py.data/guest.sh delete mode 100644 tests/acceptance/virtiofs_submounts.py.data/host.sh delete mode 100644 tests/acceptance/vnc.py delete mode 100644 tests/acceptance/x86_cpu_model_versions.py create mode 100644 tests/avocado/README.rst create mode 100644 tests/avocado/avocado_qemu/__init__.py create mode 100644 tests/avocado/boot_linux.py create mode 100644 tests/avocado/boot_linux_console.py create mode 100644 tests/avocado/boot_xen.py create mode 100644 tests/avocado/cpu_queries.py create mode 100644 tests/avocado/empty_cpu_model.py create mode 100644 tests/avocado/hotplug_cpu.py create mode 100644 tests/avocado/info_usernet.py create mode 100644 tests/avocado/intel_iommu.py create mode 100644 tests/avocado/linux_initrd.py create mode 100644 tests/avocado/linux_ssh_mips_malta.py create mode 100644 tests/avocado/machine_arm_canona1100.py create mode 100644 tests/avocado/machine_arm_integratorcp.py create mode 100644 tests/avocado/machine_arm_n8x0.py create mode 100644 tests/avocado/machine_avr6.py create mode 100644 tests/avocado/machine_m68k_nextcube.py create mode 100644 tests/avocado/machine_microblaze.py create mode 100644 tests/avocado/machine_mips_fuloong2e.py create mode 100644 tests/avocado/machine_mips_loongson3v.py create mode 100644 tests/avocado/machine_mips_malta.py create mode 100644 tests/avocado/machine_rx_gdbsim.py create mode 100644 tests/avocado/machine_s390_ccw_virtio.py create mode 100644 tests/avocado/machine_sparc64_sun4u.py create mode 100644 tests/avocado/machine_sparc_leon3.py create mode 100644 tests/avocado/migration.py create mode 100644 tests/avocado/multiprocess.py create mode 100644 tests/avocado/pc_cpu_hotplug_props.py create mode 100644 tests/avocado/ppc_405.py create mode 100644 tests/avocado/ppc_bamboo.py create mode 100644 tests/avocado/ppc_mpc8544ds.py create mode 100644 tests/avocado/ppc_prep_40p.py create mode 100644 tests/avocado/ppc_pseries.py create mode 100644 tests/avocado/ppc_virtex_ml507.py create mode 100644 tests/avocado/replay_kernel.py create mode 100644 tests/avocado/replay_linux.py create mode 100644 tests/avocado/reverse_debugging.py create mode 100644 tests/avocado/smmu.py create mode 100644 tests/avocado/tcg_plugins.py create mode 100644 tests/avocado/tesseract_utils.py create mode 100644 tests/avocado/version.py create mode 100644 tests/avocado/virtio-gpu.py create mode 100644 tests/avocado/virtio_check_params.py create mode 100644 tests/avocado/virtio_version.py create mode 100644 tests/avocado/virtiofs_submounts.py create mode 100644 tests/avocado/virtiofs_submounts.py.data/cleanup.sh create mode 100644 tests/avocado/virtiofs_submounts.py.data/guest-cleanup.sh create mode 100644 tests/avocado/virtiofs_submounts.py.data/guest.sh create mode 100644 tests/avocado/virtiofs_submounts.py.data/host.sh create mode 100644 tests/avocado/vnc.py create mode 100644 tests/avocado/x86_cpu_model_versions.py diff --git a/.gitlab-ci.d/buildtest-template.yml b/.gitlab-ci.d/buildtest-template.yml index fcbcc4e627..2c7980a4f6 100644 --- a/.gitlab-ci.d/buildtest-template.yml +++ b/.gitlab-ci.d/buildtest-template.yml @@ -37,7 +37,7 @@ # Avoid recompiling by hiding ninja with NINJA=":" - make NINJA=":" $MAKE_CHECK_ARGS -.acceptance_test_job_template: +.avocado_test_job_template: extends: .native_test_job_template cache: key: "${CI_JOB_NAME}-cache" diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 6c1301e912..71d0f407ad 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -26,14 +26,14 @@ check-system-alpine: IMAGE: alpine MAKE_CHECK_ARGS: check -acceptance-system-alpine: - extends: .acceptance_test_job_template +avocado-system-alpine: + extends: .avocado_test_job_template needs: - job: build-system-alpine artifacts: true variables: IMAGE: alpine - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado build-system-ubuntu: extends: .native_build_job_template @@ -59,14 +59,14 @@ check-system-ubuntu: IMAGE: ubuntu2004 MAKE_CHECK_ARGS: check -acceptance-system-ubuntu: - extends: .acceptance_test_job_template +avocado-system-ubuntu: + extends: .avocado_test_job_template needs: - job: build-system-ubuntu artifacts: true variables: IMAGE: ubuntu2004 - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado build-system-debian: extends: .native_build_job_template @@ -91,14 +91,14 @@ check-system-debian: IMAGE: debian-amd64 MAKE_CHECK_ARGS: check -acceptance-system-debian: - extends: .acceptance_test_job_template +avocado-system-debian: + extends: .avocado_test_job_template needs: - job: build-system-debian artifacts: true variables: IMAGE: debian-amd64 - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado build-system-fedora: extends: .native_build_job_template @@ -125,14 +125,14 @@ check-system-fedora: IMAGE: fedora MAKE_CHECK_ARGS: check -acceptance-system-fedora: - extends: .acceptance_test_job_template +avocado-system-fedora: + extends: .avocado_test_job_template needs: - job: build-system-fedora artifacts: true variables: IMAGE: fedora - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado build-system-centos: extends: .native_build_job_template @@ -159,14 +159,14 @@ check-system-centos: IMAGE: centos8 MAKE_CHECK_ARGS: check -acceptance-system-centos: - extends: .acceptance_test_job_template +avocado-system-centos: + extends: .avocado_test_job_template needs: - job: build-system-centos artifacts: true variables: IMAGE: centos8 - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado build-system-opensuse: extends: .native_build_job_template @@ -191,14 +191,14 @@ check-system-opensuse: IMAGE: opensuse-leap MAKE_CHECK_ARGS: check -acceptance-system-opensuse: - extends: .acceptance_test_job_template +avocado-system-opensuse: + extends: .avocado_test_job_template needs: - job: build-system-opensuse artifacts: true variables: IMAGE: opensuse-leap - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado # This jobs explicitly disable TCG (--disable-tcg), KVM is detected by @@ -317,7 +317,7 @@ clang-user: # This can be accomplished by using -enable-slirp=git, which avoids the use of # a system-wide version of the library # -# Split in three sets of build/check/acceptance to limit the execution time of each +# Split in three sets of build/check/avocado to limit the execution time of each # job build-cfi-aarch64: extends: .native_build_job_template @@ -352,14 +352,14 @@ check-cfi-aarch64: IMAGE: fedora MAKE_CHECK_ARGS: check -acceptance-cfi-aarch64: - extends: .acceptance_test_job_template +avocado-cfi-aarch64: + extends: .avocado_test_job_template needs: - job: build-cfi-aarch64 artifacts: true variables: IMAGE: fedora - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado build-cfi-ppc64-s390x: extends: .native_build_job_template @@ -394,14 +394,14 @@ check-cfi-ppc64-s390x: IMAGE: fedora MAKE_CHECK_ARGS: check -acceptance-cfi-ppc64-s390x: - extends: .acceptance_test_job_template +avocado-cfi-ppc64-s390x: + extends: .avocado_test_job_template needs: - job: build-cfi-ppc64-s390x artifacts: true variables: IMAGE: fedora - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado build-cfi-x86_64: extends: .native_build_job_template @@ -430,14 +430,14 @@ check-cfi-x86_64: IMAGE: fedora MAKE_CHECK_ARGS: check -acceptance-cfi-x86_64: - extends: .acceptance_test_job_template +avocado-cfi-x86_64: + extends: .avocado_test_job_template needs: - job: build-cfi-x86_64 artifacts: true variables: IMAGE: fedora - MAKE_CHECK_ARGS: check-acceptance + MAKE_CHECK_ARGS: check-avocado tsan-build: extends: .native_build_job_template diff --git a/MAINTAINERS b/MAINTAINERS index 797be5b366..53b63df407 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -177,7 +177,7 @@ L: qemu-arm@nongnu.org S: Maintained F: hw/arm/smmu* F: include/hw/arm/smmu* -F: tests/acceptance/smmu.py +F: tests/avocado/smmu.py AVR TCG CPUs M: Michael Rolnik @@ -185,7 +185,7 @@ S: Maintained F: docs/system/target-avr.rst F: gdb-xml/avr-cpu.xml F: target/avr/ -F: tests/acceptance/machine_avr6.py +F: tests/avocado/machine_avr6.py CRIS TCG CPUs M: Edgar E. Iglesias @@ -657,7 +657,7 @@ S: Odd Fixes F: include/hw/arm/digic.h F: hw/*/digic* F: include/hw/*/digic* -F: tests/acceptance/machine_arm_canona1100.py +F: tests/avocado/machine_arm_canona1100.py F: docs/system/arm/digic.rst Goldfish RTC @@ -708,7 +708,7 @@ S: Maintained F: hw/arm/integratorcp.c F: hw/misc/arm_integrator_debug.c F: include/hw/misc/arm_integrator_debug.h -F: tests/acceptance/machine_arm_integratorcp.py +F: tests/avocado/machine_arm_integratorcp.py F: docs/system/arm/integratorcp.rst MCIMX6UL EVK / i.MX6ul @@ -805,7 +805,7 @@ F: include/hw/display/blizzard.h F: include/hw/input/lm832x.h F: include/hw/input/tsc2xxx.h F: include/hw/misc/cbus.h -F: tests/acceptance/machine_arm_n8x0.py +F: tests/avocado/machine_arm_n8x0.py F: docs/system/arm/nseries.rst Palm @@ -1159,7 +1159,7 @@ M: Edgar E. Iglesias S: Maintained F: hw/microblaze/petalogix_s3adsp1800_mmu.c F: include/hw/char/xilinx_uartlite.h -F: tests/acceptance/machine_microblaze.py +F: tests/avocado/machine_microblaze.py petalogix_ml605 M: Edgar E. Iglesias @@ -1192,8 +1192,8 @@ F: hw/acpi/piix4.c F: hw/mips/malta.c F: hw/mips/gt64xxx_pci.c F: include/hw/southbridge/piix.h -F: tests/acceptance/linux_ssh_mips_malta.py -F: tests/acceptance/machine_mips_malta.py +F: tests/avocado/linux_ssh_mips_malta.py +F: tests/avocado/machine_mips_malta.py Mipssim R: Aleksandar Rikalo @@ -1211,7 +1211,7 @@ F: hw/isa/vt82c686.c F: hw/pci-host/bonito.c F: hw/usb/vt82c686-uhci-pci.c F: include/hw/isa/vt82c686.h -F: tests/acceptance/machine_mips_fuloong2e.py +F: tests/avocado/machine_mips_fuloong2e.py Loongson-3 virtual platforms M: Huacai Chen @@ -1221,7 +1221,7 @@ F: hw/intc/loongson_liointc.c F: hw/mips/loongson3_bootp.c F: hw/mips/loongson3_bootp.h F: hw/mips/loongson3_virt.c -F: tests/acceptance/machine_mips_loongson3v.py +F: tests/avocado/machine_mips_loongson3v.py Boston M: Paul Burton @@ -1250,7 +1250,7 @@ Bamboo L: qemu-ppc@nongnu.org S: Orphan F: hw/ppc/ppc440_bamboo.c -F: tests/acceptance/ppc_bamboo.py +F: tests/avocado/ppc_bamboo.py e500 L: qemu-ppc@nongnu.org @@ -1271,7 +1271,7 @@ L: qemu-ppc@nongnu.org S: Orphan F: hw/ppc/mpc8544ds.c F: hw/ppc/mpc8544_guts.c -F: tests/acceptance/ppc_mpc8544ds.py +F: tests/avocado/ppc_mpc8544ds.py New World (mac99) M: Mark Cave-Ayland @@ -1318,7 +1318,7 @@ F: hw/dma/i82374.c F: hw/rtc/m48t59-isa.c F: include/hw/isa/pc87312.h F: include/hw/rtc/m48t59.h -F: tests/acceptance/ppc_prep_40p.py +F: tests/avocado/ppc_prep_40p.py sPAPR M: David Gibson @@ -1336,7 +1336,7 @@ F: tests/qtest/spapr* F: tests/qtest/libqos/*spapr* F: tests/qtest/rtas* F: tests/qtest/libqos/rtas* -F: tests/acceptance/ppc_pseries.py +F: tests/avocado/ppc_pseries.py PowerNV (Non-Virtualized) M: Cédric Le Goater @@ -1356,7 +1356,7 @@ M: Edgar E. Iglesias L: qemu-ppc@nongnu.org S: Odd Fixes F: hw/ppc/virtex_ml507.c -F: tests/acceptance/ppc_virtex_ml507.py +F: tests/avocado/ppc_virtex_ml507.py sam460ex M: BALATON Zoltan @@ -1443,7 +1443,7 @@ R: Yoshinori Sato S: Orphan F: docs/system/target-rx.rst F: hw/rx/rx-gdbsim.c -F: tests/acceptance/machine_rx_gdbsim.py +F: tests/avocado/machine_rx_gdbsim.py SH4 Machines ------------ @@ -1497,7 +1497,7 @@ F: include/hw/pci-host/sabre.h F: hw/pci-bridge/simba.c F: include/hw/pci-bridge/simba.h F: pc-bios/openbios-sparc64 -F: tests/acceptance/machine_sparc64_sun4u.py +F: tests/avocado/machine_sparc64_sun4u.py Sun4v M: Artyom Tarasenko @@ -1513,7 +1513,7 @@ S: Maintained F: hw/sparc/leon3.c F: hw/*/grlib* F: include/hw/*/grlib* -F: tests/acceptance/machine_sparc_leon3.py +F: tests/avocado/machine_sparc_leon3.py S390 Machines ------------- @@ -1528,7 +1528,7 @@ F: include/hw/s390x/ F: hw/watchdog/wdt_diag288.c F: include/hw/watchdog/wdt_diag288.h F: configs/devices/s390x-softmmu/default.mak -F: tests/acceptance/machine_s390_ccw_virtio.py +F: tests/avocado/machine_s390_ccw_virtio.py T: git https://github.com/borntraeger/qemu.git s390-next L: qemu-s390x@nongnu.org @@ -2112,7 +2112,7 @@ M: Alex Bennée S: Maintained F: hw/core/guest-loader.c F: docs/system/guest-loader.rst -F: tests/acceptance/boot_xen.py +F: tests/avocado/boot_xen.py Intel Hexadecimal Object File Loader M: Su Hang @@ -2986,9 +2986,9 @@ F: net/filter-replay.c F: include/sysemu/replay.h F: docs/replay.txt F: stubs/replay.c -F: tests/acceptance/replay_kernel.py -F: tests/acceptance/replay_linux.py -F: tests/acceptance/reverse_debugging.py +F: tests/avocado/replay_kernel.py +F: tests/avocado/replay_linux.py +F: tests/avocado/reverse_debugging.py F: qapi/replay.json IOVA Tree @@ -3105,7 +3105,7 @@ S: Maintained F: docs/devel/tcg-plugins.rst F: plugins/ F: tests/plugin/ -F: tests/acceptance/tcg_plugins.py +F: tests/avocado/tcg_plugins.py F: contrib/plugins/ AArch64 TCG target @@ -3494,14 +3494,14 @@ S: Maintained F: tests/tcg/Makefile F: tests/tcg/Makefile.include -Acceptance (Integration) Testing with the Avocado framework +Integration Testing with the Avocado framework W: https://trello.com/b/6Qi1pxVn/avocado-qemu R: Cleber Rosa R: Philippe Mathieu-Daudé R: Wainer dos Santos Moschetta R: Willian Rampazzo S: Odd Fixes -F: tests/acceptance/ +F: tests/avocado/ Documentation ------------- diff --git a/configure b/configure index 33682cb971..19d5e97b27 100755 --- a/configure +++ b/configure @@ -3832,7 +3832,7 @@ LINKS="$LINKS pc-bios/s390-ccw/Makefile" LINKS="$LINKS roms/seabios/Makefile" LINKS="$LINKS pc-bios/qemu-icon.bmp" LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit -LINKS="$LINKS tests/acceptance tests/data" +LINKS="$LINKS tests/avocado tests/data" LINKS="$LINKS tests/qemu-iotests/check" LINKS="$LINKS python" LINKS="$LINKS contrib/plugins/Makefile " diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst index ae536ef75d..aca1f5a273 100644 --- a/docs/devel/build-system.rst +++ b/docs/devel/build-system.rst @@ -416,7 +416,7 @@ number of dynamically created files listed later. ``tests/Makefile.include`` Rules for external test harnesses. These include the TCG tests, - ``qemu-iotests`` and the Avocado-based acceptance tests. + ``qemu-iotests`` and the Avocado-based integration tests. ``tests/docker/Makefile.include`` Rules for Docker tests. Like tests/Makefile, this file is included diff --git a/docs/devel/ci-definitions.rst.inc b/docs/devel/ci-definitions.rst.inc index 32e22ff468..6d5c6fd9f2 100644 --- a/docs/devel/ci-definitions.rst.inc +++ b/docs/devel/ci-definitions.rst.inc @@ -59,7 +59,7 @@ to system testing [5]_. Note that, in some cases, system testing may require interaction with third-party software, like operating system images, databases, networks, and so on. -On QEMU, system testing is represented by the 'check-acceptance' target from +On QEMU, system testing is represented by the 'check-avocado' target from 'make'. Flaky tests diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index 7500f076c2..dc5dbd057d 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -653,17 +653,16 @@ supported. To start the fuzzer, run Alternatively, some command different from "qemu-img info" can be tested, by changing the ``-c`` option. -Acceptance tests using the Avocado Framework --------------------------------------------- +Integration tests using the Avocado Framework +--------------------------------------------- -The ``tests/acceptance`` directory hosts functional tests, also known -as acceptance level tests. They're usually higher level tests, and -may interact with external resources and with various guest operating -systems. +The ``tests/avocado`` directory hosts integration tests. They're usually +higher level tests, and may interact with external resources and with +various guest operating systems. These tests are written using the Avocado Testing Framework (which must be installed separately) in conjunction with a the ``avocado_qemu.Test`` -class, implemented at ``tests/acceptance/avocado_qemu``. +class, implemented at ``tests/avocado/avocado_qemu``. Tests based on ``avocado_qemu.Test`` can easily: @@ -695,11 +694,11 @@ Tests based on ``avocado_qemu.Test`` can easily: Running tests ~~~~~~~~~~~~~ -You can run the acceptance tests simply by executing: +You can run the avocado tests simply by executing: .. code:: - make check-acceptance + make check-avocado This involves the automatic creation of Python virtual environment within the build tree (at ``tests/venv``) which will have all the @@ -714,12 +713,12 @@ specific version, they may be on packages named ``python3-venv`` and ``python3-pip``. It is also possible to run tests based on tags using the -``make check-acceptance`` command and the ``AVOCADO_TAGS`` environment +``make check-avocado`` command and the ``AVOCADO_TAGS`` environment variable: .. code:: - make check-acceptance AVOCADO_TAGS=quick + make check-avocado AVOCADO_TAGS=quick Note that tags separated with commas have an AND behavior, while tags separated by spaces have an OR behavior. For more information on Avocado @@ -728,31 +727,31 @@ tags, see: https://avocado-framework.readthedocs.io/en/latest/guides/user/chapters/tags.html To run a single test file, a couple of them, or a test within a file -using the ``make check-acceptance`` command, set the ``AVOCADO_TESTS`` +using the ``make check-avocado`` command, set the ``AVOCADO_TESTS`` environment variable with the test files or test names. To run all tests from a single file, use: .. code:: - make check-acceptance AVOCADO_TESTS=$FILEPATH + make check-avocado AVOCADO_TESTS=$FILEPATH The same is valid to run tests from multiple test files: .. code:: - make check-acceptance AVOCADO_TESTS='$FILEPATH1 $FILEPATH2' + make check-avocado AVOCADO_TESTS='$FILEPATH1 $FILEPATH2' To run a single test within a file, use: .. code:: - make check-acceptance AVOCADO_TESTS=$FILEPATH:$TESTCLASS.$TESTNAME + make check-avocado AVOCADO_TESTS=$FILEPATH:$TESTCLASS.$TESTNAME The same is valid to run single tests from multiple test files: .. code:: - make check-acceptance AVOCADO_TESTS='$FILEPATH1:$TESTCLASS1.$TESTNAME1 $FILEPATH2:$TESTCLASS2.$TESTNAME2' + make check-avocado AVOCADO_TESTS='$FILEPATH1:$TESTCLASS1.$TESTNAME1 $FILEPATH2:$TESTCLASS2.$TESTNAME2' The scripts installed inside the virtual environment may be used without an "activation". For instance, the Avocado test runner @@ -760,9 +759,9 @@ may be invoked by running: .. code:: - tests/venv/bin/avocado run $OPTION1 $OPTION2 tests/acceptance/ + tests/venv/bin/avocado run $OPTION1 $OPTION2 tests/avocado/ -Note that if ``make check-acceptance`` was not executed before, it is +Note that if ``make check-avocado`` was not executed before, it is possible to create the Python virtual environment with the dependencies needed running: @@ -775,20 +774,20 @@ a test file. To run tests from a single file within the build tree, use: .. code:: - tests/venv/bin/avocado run tests/acceptance/$TESTFILE + tests/venv/bin/avocado run tests/avocado/$TESTFILE To run a single test within a test file, use: .. code:: - tests/venv/bin/avocado run tests/acceptance/$TESTFILE:$TESTCLASS.$TESTNAME + tests/venv/bin/avocado run tests/avocado/$TESTFILE:$TESTCLASS.$TESTNAME Valid test names are visible in the output from any previous execution -of Avocado or ``make check-acceptance``, and can also be queried using: +of Avocado or ``make check-avocado``, and can also be queried using: .. code:: - tests/venv/bin/avocado list tests/acceptance + tests/venv/bin/avocado list tests/avocado Manual Installation ~~~~~~~~~~~~~~~~~~~ @@ -806,7 +805,7 @@ Alternatively, follow the instructions on this link: Overview ~~~~~~~~ -The ``tests/acceptance/avocado_qemu`` directory provides the +The ``tests/avocado/avocado_qemu`` directory provides the ``avocado_qemu`` Python module, containing the ``avocado_qemu.Test`` class. Here's a simple usage example: @@ -913,7 +912,7 @@ like this: self.ssh_command('some_command_to_be_run_in_the_guest') Please refer to tests that use ``avocado_qemu.LinuxTest`` under -``tests/acceptance`` for more examples. +``tests/avocado`` for more examples. QEMUMachine ~~~~~~~~~~~ @@ -1204,7 +1203,7 @@ And remove any package you want with:: pip uninstall -If you've used ``make check-acceptance``, the Python virtual environment where +If you've used ``make check-avocado``, the Python virtual environment where Avocado is installed will be cleaned up as part of ``make check-clean``. .. _checktcg-ref: diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst index 6f23907fb6..c55694dd91 100644 --- a/docs/system/arm/orangepi.rst +++ b/docs/system/arm/orangepi.rst @@ -250,14 +250,14 @@ and set the following environment variables before booting: Optionally you may save the environment variables to SD card with 'saveenv'. To continue booting simply give the 'boot' command and NetBSD boots. -Orange Pi PC acceptance tests -""""""""""""""""""""""""""""" +Orange Pi PC integration tests +"""""""""""""""""""""""""""""" -The Orange Pi PC machine has several acceptance tests included. +The Orange Pi PC machine has several integration tests included. To run the whole set of tests, build QEMU from source and simply provide the following command: .. code-block:: bash $ AVOCADO_ALLOW_LARGE_STORAGE=yes avocado --show=app,console run \ - -t machine:orangepi-pc tests/acceptance/boot_linux_console.py + -t machine:orangepi-pc tests/avocado/boot_linux_console.py diff --git a/python/qemu/machine/README.rst b/python/qemu/machine/README.rst index ac2b4fffb4..8de2c3d772 100644 --- a/python/qemu/machine/README.rst +++ b/python/qemu/machine/README.rst @@ -2,7 +2,7 @@ qemu.machine package ==================== This package provides core utilities used for testing and debugging -QEMU. It is used by the iotests, vm tests, acceptance tests, and several +QEMU. It is used by the iotests, vm tests, avocado tests, and several other utilities in the ./scripts directory. It is not a fully-fledged SDK and it is subject to change at any time. diff --git a/python/qemu/qmp/README.rst b/python/qemu/qmp/README.rst index c21951491c..5bfb82535f 100644 --- a/python/qemu/qmp/README.rst +++ b/python/qemu/qmp/README.rst @@ -3,7 +3,7 @@ qemu.qmp package This package provides a library used for connecting to and communicating with QMP servers. It is used extensively by iotests, vm tests, -acceptance tests, and other utilities in the ./scripts directory. It is +avocado tests, and other utilities in the ./scripts directory. It is not a fully-fledged SDK and is subject to change at any time. See the documentation in ``__init__.py`` for more information. diff --git a/python/qemu/utils/README.rst b/python/qemu/utils/README.rst index 975fbf4d7d..d5f2da1454 100644 --- a/python/qemu/utils/README.rst +++ b/python/qemu/utils/README.rst @@ -2,6 +2,6 @@ qemu.utils package ================== This package provides miscellaneous utilities used for testing and -debugging QEMU. It is used primarily by the vm and acceptance tests. +debugging QEMU. It is used primarily by the vm and avocado tests. See the documentation in ``__init__.py`` for more information. diff --git a/tests/Makefile.include b/tests/Makefile.include index 8e8ee58493..4c564cf789 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -89,7 +89,7 @@ TESTS_VENV_DIR=$(BUILD_DIR)/tests/venv TESTS_VENV_REQ=$(SRC_PATH)/tests/requirements.txt TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results ifndef AVOCADO_TESTS - AVOCADO_TESTS=tests/acceptance + AVOCADO_TESTS=tests/avocado endif # Controls the output generated by Avocado when running tests. # Any number of command separated loggers are accepted. For more @@ -140,7 +140,7 @@ check-avocado: check-venv $(TESTS_RESULTS_DIR) get-vm-images --filter-by-tags-include-empty-key) \ $(AVOCADO_CMDLINE_TAGS) \ $(if $(GITLAB_CI),,--failfast) $(AVOCADO_TESTS), \ - "AVOCADO", "tests/acceptance") + "AVOCADO", "tests/avocado") check-acceptance-deprecated-warning: @echo diff --git a/tests/acceptance/README.rst b/tests/acceptance/README.rst deleted file mode 100644 index 89260faed6..0000000000 --- a/tests/acceptance/README.rst +++ /dev/null @@ -1,10 +0,0 @@ -============================================ -Acceptance tests using the Avocado Framework -============================================ - -This directory contains functional tests, also known as acceptance -level tests. They're usually higher level, and may interact with -external resources and with various guest operating systems. - -For more information, please refer to ``docs/devel/testing.rst``, -section "Acceptance tests using the Avocado Framework". diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py deleted file mode 100644 index 1841053e2c..0000000000 --- a/tests/acceptance/avocado_qemu/__init__.py +++ /dev/null @@ -1,558 +0,0 @@ -# Test class and utilities for functional tests -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import logging -import os -import shutil -import sys -import tempfile -import time -import uuid - -import avocado -from avocado.utils import cloudinit, datadrainer, network, ssh, vmimage -from avocado.utils.path import find_command - -#: The QEMU build root directory. It may also be the source directory -#: if building from the source dir, but it's safer to use BUILD_DIR for -#: that purpose. Be aware that if this code is moved outside of a source -#: and build tree, it will not be accurate. -BUILD_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) - -if os.path.islink(os.path.dirname(os.path.dirname(__file__))): - # The link to the acceptance tests dir in the source code directory - lnk = os.path.dirname(os.path.dirname(__file__)) - #: The QEMU root source directory - SOURCE_DIR = os.path.dirname(os.path.dirname(os.readlink(lnk))) -else: - SOURCE_DIR = BUILD_DIR - -sys.path.append(os.path.join(SOURCE_DIR, 'python')) - -from qemu.machine import QEMUMachine -from qemu.utils import (get_info_usernet_hostfwd_port, kvm_available, - tcg_available) - - -def is_readable_executable_file(path): - return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK) - - -def pick_default_qemu_bin(arch=None): - """ - Picks the path of a QEMU binary, starting either in the current working - directory or in the source tree root directory. - - :param arch: the arch to use when looking for a QEMU binary (the target - will match the arch given). If None (the default), arch - will be the current host system arch (as given by - :func:`os.uname`). - :type arch: str - :returns: the path to the default QEMU binary or None if one could not - be found - :rtype: str or None - """ - if arch is None: - arch = os.uname()[4] - # qemu binary path does not match arch for powerpc, handle it - if 'ppc64le' in arch: - arch = 'ppc64' - qemu_bin_relative_path = "./qemu-system-%s" % arch - if is_readable_executable_file(qemu_bin_relative_path): - return qemu_bin_relative_path - - qemu_bin_from_bld_dir_path = os.path.join(BUILD_DIR, - qemu_bin_relative_path) - if is_readable_executable_file(qemu_bin_from_bld_dir_path): - return qemu_bin_from_bld_dir_path - return None - - -def _console_interaction(test, success_message, failure_message, - send_string, keep_sending=False, vm=None): - assert not keep_sending or send_string - if vm is None: - vm = test.vm - console = vm.console_socket.makefile(mode='rb', encoding='utf-8') - console_logger = logging.getLogger('console') - while True: - if send_string: - vm.console_socket.sendall(send_string.encode()) - if not keep_sending: - send_string = None # send only once - try: - msg = console.readline().decode().strip() - except UnicodeDecodeError: - msg = None - if not msg: - continue - console_logger.debug(msg) - if success_message is None or success_message in msg: - break - if failure_message and failure_message in msg: - console.close() - fail = 'Failure message found in console: "%s". Expected: "%s"' % \ - (failure_message, success_message) - test.fail(fail) - -def interrupt_interactive_console_until_pattern(test, success_message, - failure_message=None, - interrupt_string='\r'): - """ - Keep sending a string to interrupt a console prompt, while logging the - console output. Typical use case is to break a boot loader prompt, such: - - Press a key within 5 seconds to interrupt boot process. - 5 - 4 - 3 - 2 - 1 - Booting default image... - - :param test: an Avocado test containing a VM that will have its console - read and probed for a success or failure message - :type test: :class:`avocado_qemu.Test` - :param success_message: if this message appears, test succeeds - :param failure_message: if this message appears, test fails - :param interrupt_string: a string to send to the console before trying - to read a new line - """ - _console_interaction(test, success_message, failure_message, - interrupt_string, True) - -def wait_for_console_pattern(test, success_message, failure_message=None, - vm=None): - """ - Waits for messages to appear on the console, while logging the content - - :param test: an Avocado test containing a VM that will have its console - read and probed for a success or failure message - :type test: :class:`avocado_qemu.Test` - :param success_message: if this message appears, test succeeds - :param failure_message: if this message appears, test fails - """ - _console_interaction(test, success_message, failure_message, None, vm=vm) - -def exec_command(test, command): - """ - Send a command to a console (appending CRLF characters), while logging - the content. - - :param test: an Avocado test containing a VM. - :type test: :class:`avocado_qemu.Test` - :param command: the command to send - :type command: str - """ - _console_interaction(test, None, None, command + '\r') - -def exec_command_and_wait_for_pattern(test, command, - success_message, failure_message=None): - """ - Send a command to a console (appending CRLF characters), then wait - for success_message to appear on the console, while logging the. - content. Mark the test as failed if failure_message is found instead. - - :param test: an Avocado test containing a VM that will have its console - read and probed for a success or failure message - :type test: :class:`avocado_qemu.Test` - :param command: the command to send - :param success_message: if this message appears, test succeeds - :param failure_message: if this message appears, test fails - """ - _console_interaction(test, success_message, failure_message, command + '\r') - -class Test(avocado.Test): - def _get_unique_tag_val(self, tag_name): - """ - Gets a tag value, if unique for a key - """ - vals = self.tags.get(tag_name, []) - if len(vals) == 1: - return vals.pop() - return None - - def require_accelerator(self, accelerator): - """ - Requires an accelerator to be available for the test to continue - - It takes into account the currently set qemu binary. - - If the check fails, the test is canceled. If the check itself - for the given accelerator is not available, the test is also - canceled. - - :param accelerator: name of the accelerator, such as "kvm" or "tcg" - :type accelerator: str - """ - checker = {'tcg': tcg_available, - 'kvm': kvm_available}.get(accelerator) - if checker is None: - self.cancel("Don't know how to check for the presence " - "of accelerator %s" % accelerator) - if not checker(qemu_bin=self.qemu_bin): - self.cancel("%s accelerator does not seem to be " - "available" % accelerator) - - def setUp(self): - self._vms = {} - - self.arch = self.params.get('arch', - default=self._get_unique_tag_val('arch')) - - self.cpu = self.params.get('cpu', - default=self._get_unique_tag_val('cpu')) - - self.machine = self.params.get('machine', - default=self._get_unique_tag_val('machine')) - - default_qemu_bin = pick_default_qemu_bin(arch=self.arch) - self.qemu_bin = self.params.get('qemu_bin', - default=default_qemu_bin) - if self.qemu_bin is None: - self.cancel("No QEMU binary defined or found in the build tree") - - def _new_vm(self, name, *args): - self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") - vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir, - sock_dir=self._sd.name, log_dir=self.logdir) - self.log.debug('QEMUMachine "%s" created', name) - self.log.debug('QEMUMachine "%s" temp_dir: %s', name, vm.temp_dir) - self.log.debug('QEMUMachine "%s" log_dir: %s', name, vm.log_dir) - if args: - vm.add_args(*args) - return vm - - @property - def vm(self): - return self.get_vm(name='default') - - def get_vm(self, *args, name=None): - if not name: - name = str(uuid.uuid4()) - if self._vms.get(name) is None: - self._vms[name] = self._new_vm(name, *args) - if self.cpu is not None: - self._vms[name].add_args('-cpu', self.cpu) - if self.machine is not None: - self._vms[name].set_machine(self.machine) - return self._vms[name] - - def set_vm_arg(self, arg, value): - """ - Set an argument to list of extra arguments to be given to the QEMU - binary. If the argument already exists then its value is replaced. - - :param arg: the QEMU argument, such as "-cpu" in "-cpu host" - :type arg: str - :param value: the argument value, such as "host" in "-cpu host" - :type value: str - """ - if not arg or not value: - return - if arg not in self.vm.args: - self.vm.args.extend([arg, value]) - else: - idx = self.vm.args.index(arg) + 1 - if idx < len(self.vm.args): - self.vm.args[idx] = value - else: - self.vm.args.append(value) - - def tearDown(self): - for vm in self._vms.values(): - vm.shutdown() - self._sd = None - super().tearDown() - - def fetch_asset(self, name, - asset_hash=None, algorithm=None, - locations=None, expire=None, - find_only=False, cancel_on_missing=True): - return super().fetch_asset(name, - asset_hash=asset_hash, - algorithm=algorithm, - locations=locations, - expire=expire, - find_only=find_only, - cancel_on_missing=cancel_on_missing) - - -class LinuxSSHMixIn: - """Contains utility methods for interacting with a guest via SSH.""" - - def ssh_connect(self, username, credential, credential_is_key=True): - self.ssh_logger = logging.getLogger('ssh') - res = self.vm.command('human-monitor-command', - command_line='info usernet') - port = get_info_usernet_hostfwd_port(res) - self.assertIsNotNone(port) - self.assertGreater(port, 0) - self.log.debug('sshd listening on port: %d', port) - if credential_is_key: - self.ssh_session = ssh.Session('127.0.0.1', port=port, - user=username, key=credential) - else: - self.ssh_session = ssh.Session('127.0.0.1', port=port, - user=username, password=credential) - for i in range(10): - try: - self.ssh_session.connect() - return - except: - time.sleep(i) - self.fail('ssh connection timeout') - - def ssh_command(self, command): - self.ssh_logger.info(command) - result = self.ssh_session.cmd(command) - stdout_lines = [line.rstrip() for line - in result.stdout_text.splitlines()] - for line in stdout_lines: - self.ssh_logger.info(line) - stderr_lines = [line.rstrip() for line - in result.stderr_text.splitlines()] - for line in stderr_lines: - self.ssh_logger.warning(line) - - self.assertEqual(result.exit_status, 0, - f'Guest command failed: {command}') - return stdout_lines, stderr_lines - -class LinuxDistro: - """Represents a Linux distribution - - Holds information of known distros. - """ - #: A collection of known distros and their respective image checksum - KNOWN_DISTROS = { - 'fedora': { - '31': { - 'x86_64': - {'checksum': ('e3c1b309d9203604922d6e255c2c5d09' - '8a309c2d46215d8fc026954f3c5c27a0'), - 'pxeboot_url': ('https://archives.fedoraproject.org/' - 'pub/archive/fedora/linux/releases/31/' - 'Everything/x86_64/os/images/pxeboot/'), - 'kernel_params': ('root=UUID=b1438b9b-2cab-4065-a99a-' - '08a96687f73c ro no_timer_check ' - 'net.ifnames=0 console=tty1 ' - 'console=ttyS0,115200n8'), - }, - 'aarch64': - {'checksum': ('1e18d9c0cf734940c4b5d5ec592facae' - 'd2af0ad0329383d5639c997fdf16fe49'), - 'pxeboot_url': 'https://archives.fedoraproject.org/' - 'pub/archive/fedora/linux/releases/31/' - 'Everything/aarch64/os/images/pxeboot/', - 'kernel_params': ('root=UUID=b6950a44-9f3c-4076-a9c2-' - '355e8475b0a7 ro earlyprintk=pl011,0x9000000' - ' ignore_loglevel no_timer_check' - ' printk.time=1 rd_NO_PLYMOUTH' - ' console=ttyAMA0'), - }, - 'ppc64': - {'checksum': ('7c3528b85a3df4b2306e892199a9e1e4' - '3f991c506f2cc390dc4efa2026ad2f58')}, - 's390x': - {'checksum': ('4caaab5a434fd4d1079149a072fdc789' - '1e354f834d355069ca982fdcaf5a122d')}, - }, - '32': { - 'aarch64': - {'checksum': ('b367755c664a2d7a26955bbfff985855' - 'adfa2ca15e908baf15b4b176d68d3967'), - 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/' - 'releases/32/Server/aarch64/os/images/' - 'pxeboot/'), - 'kernel_params': ('root=UUID=3df75b65-be8d-4db4-8655-' - '14d95c0e90c5 ro no_timer_check net.ifnames=0' - ' console=tty1 console=ttyS0,115200n8'), - }, - }, - '33': { - 'aarch64': - {'checksum': ('e7f75cdfd523fe5ac2ca9eeece68edc1' - 'a81f386a17f969c1d1c7c87031008a6b'), - 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/' - 'releases/33/Server/aarch64/os/images/' - 'pxeboot/'), - 'kernel_params': ('root=UUID=d20b3ffa-6397-4a63-a734-' - '1126a0208f8a ro no_timer_check net.ifnames=0' - ' console=tty1 console=ttyS0,115200n8' - ' console=tty0'), - }, - }, - } - } - - def __init__(self, name, version, arch): - self.name = name - self.version = version - self.arch = arch - try: - info = self.KNOWN_DISTROS.get(name).get(version).get(arch) - except AttributeError: - # Unknown distro - info = None - self._info = info or {} - - @property - def checksum(self): - """Gets the cloud-image file checksum""" - return self._info.get('checksum', None) - - @checksum.setter - def checksum(self, value): - self._info['checksum'] = value - - @property - def pxeboot_url(self): - """Gets the repository url where pxeboot files can be found""" - return self._info.get('pxeboot_url', None) - - @property - def default_kernel_params(self): - """Gets the default kernel parameters""" - return self._info.get('kernel_params', None) - - -class LinuxTest(LinuxSSHMixIn, Test): - """Facilitates having a cloud-image Linux based available. - - For tests that indend to interact with guests, this is a better choice - to start with than the more vanilla `Test` class. - """ - - timeout = 900 - distro = None - username = 'root' - password = 'password' - - def _set_distro(self): - distro_name = self.params.get( - 'distro', - default=self._get_unique_tag_val('distro')) - if not distro_name: - distro_name = 'fedora' - - distro_version = self.params.get( - 'distro_version', - default=self._get_unique_tag_val('distro_version')) - if not distro_version: - distro_version = '31' - - self.distro = LinuxDistro(distro_name, distro_version, self.arch) - - # The distro checksum behaves differently than distro name and - # version. First, it does not respect a tag with the same - # name, given that it's not expected to be used for filtering - # (distro name versions are the natural choice). Second, the - # order of precedence is: parameter, attribute and then value - # from KNOWN_DISTROS. - distro_checksum = self.params.get('distro_checksum', - default=None) - if distro_checksum: - self.distro.checksum = distro_checksum - - def setUp(self, ssh_pubkey=None, network_device_type='virtio-net'): - super().setUp() - self._set_distro() - self.vm.add_args('-smp', '2') - self.vm.add_args('-m', '1024') - # The following network device allows for SSH connections - self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', - '-device', '%s,netdev=vnet' % network_device_type) - self.set_up_boot() - if ssh_pubkey is None: - ssh_pubkey, self.ssh_key = self.set_up_existing_ssh_keys() - self.set_up_cloudinit(ssh_pubkey) - - def set_up_existing_ssh_keys(self): - ssh_public_key = os.path.join(SOURCE_DIR, 'tests', 'keys', 'id_rsa.pub') - source_private_key = os.path.join(SOURCE_DIR, 'tests', 'keys', 'id_rsa') - ssh_dir = os.path.join(self.workdir, '.ssh') - os.mkdir(ssh_dir, mode=0o700) - ssh_private_key = os.path.join(ssh_dir, - os.path.basename(source_private_key)) - shutil.copyfile(source_private_key, ssh_private_key) - os.chmod(ssh_private_key, 0o600) - return (ssh_public_key, ssh_private_key) - - def download_boot(self): - self.log.debug('Looking for and selecting a qemu-img binary to be ' - 'used to create the bootable snapshot image') - # If qemu-img has been built, use it, otherwise the system wide one - # will be used. If none is available, the test will cancel. - qemu_img = os.path.join(BUILD_DIR, 'qemu-img') - if not os.path.exists(qemu_img): - qemu_img = find_command('qemu-img', False) - if qemu_img is False: - self.cancel('Could not find "qemu-img", which is required to ' - 'create the bootable image') - vmimage.QEMU_IMG = qemu_img - - self.log.info('Downloading/preparing boot image') - # Fedora 31 only provides ppc64le images - image_arch = self.arch - if self.distro.name == 'fedora': - if image_arch == 'ppc64': - image_arch = 'ppc64le' - - try: - boot = vmimage.get( - self.distro.name, arch=image_arch, version=self.distro.version, - checksum=self.distro.checksum, - algorithm='sha256', - cache_dir=self.cache_dirs[0], - snapshot_dir=self.workdir) - except: - self.cancel('Failed to download/prepare boot image') - return boot.path - - def prepare_cloudinit(self, ssh_pubkey=None): - self.log.info('Preparing cloudinit image') - try: - cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso') - self.phone_home_port = network.find_free_port() - pubkey_content = None - if ssh_pubkey: - with open(ssh_pubkey) as pubkey: - pubkey_content = pubkey.read() - cloudinit.iso(cloudinit_iso, self.name, - username=self.username, - password=self.password, - # QEMU's hard coded usermode router address - phone_home_host='10.0.2.2', - phone_home_port=self.phone_home_port, - authorized_key=pubkey_content) - except Exception: - self.cancel('Failed to prepare the cloudinit image') - return cloudinit_iso - - def set_up_boot(self): - path = self.download_boot() - self.vm.add_args('-drive', 'file=%s' % path) - - def set_up_cloudinit(self, ssh_pubkey=None): - cloudinit_iso = self.prepare_cloudinit(ssh_pubkey) - self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) - - def launch_and_wait(self, set_up_ssh_connection=True): - self.vm.set_console() - self.vm.launch() - console_drainer = datadrainer.LineLogger(self.vm.console_socket.fileno(), - logger=self.log.getChild('console')) - console_drainer.start() - self.log.info('VM launched, waiting for boot confirmation from guest') - cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), self.name) - if set_up_ssh_connection: - self.log.info('Setting up the SSH connection') - self.ssh_connect(self.username, self.ssh_key) diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py deleted file mode 100644 index ab19146d1e..0000000000 --- a/tests/acceptance/boot_linux.py +++ /dev/null @@ -1,138 +0,0 @@ -# Functional test that boots a complete Linux system via a cloud image -# -# Copyright (c) 2018-2020 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os - -from avocado_qemu import LinuxTest, BUILD_DIR - -from avocado import skipIf - - -class BootLinuxX8664(LinuxTest): - """ - :avocado: tags=arch:x86_64 - """ - - def test_pc_i440fx_tcg(self): - """ - :avocado: tags=machine:pc - :avocado: tags=accel:tcg - """ - self.require_accelerator("tcg") - self.vm.add_args("-accel", "tcg") - self.launch_and_wait(set_up_ssh_connection=False) - - def test_pc_i440fx_kvm(self): - """ - :avocado: tags=machine:pc - :avocado: tags=accel:kvm - """ - self.require_accelerator("kvm") - self.vm.add_args("-accel", "kvm") - self.launch_and_wait(set_up_ssh_connection=False) - - def test_pc_q35_tcg(self): - """ - :avocado: tags=machine:q35 - :avocado: tags=accel:tcg - """ - self.require_accelerator("tcg") - self.vm.add_args("-accel", "tcg") - self.launch_and_wait(set_up_ssh_connection=False) - - def test_pc_q35_kvm(self): - """ - :avocado: tags=machine:q35 - :avocado: tags=accel:kvm - """ - self.require_accelerator("kvm") - self.vm.add_args("-accel", "kvm") - self.launch_and_wait(set_up_ssh_connection=False) - - -class BootLinuxAarch64(LinuxTest): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=machine:gic-version=2 - """ - - def add_common_args(self): - self.vm.add_args('-bios', - os.path.join(BUILD_DIR, 'pc-bios', - 'edk2-aarch64-code.fd')) - self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') - self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom') - - def test_virt_tcg_gicv2(self): - """ - :avocado: tags=accel:tcg - :avocado: tags=cpu:max - :avocado: tags=device:gicv2 - """ - self.require_accelerator("tcg") - self.vm.add_args("-accel", "tcg") - self.vm.add_args("-machine", "virt,gic-version=2") - self.add_common_args() - self.launch_and_wait(set_up_ssh_connection=False) - - def test_virt_tcg_gicv3(self): - """ - :avocado: tags=accel:tcg - :avocado: tags=cpu:max - :avocado: tags=device:gicv3 - """ - self.require_accelerator("tcg") - self.vm.add_args("-accel", "tcg") - self.vm.add_args("-machine", "virt,gic-version=3") - self.add_common_args() - self.launch_and_wait(set_up_ssh_connection=False) - - def test_virt_kvm(self): - """ - :avocado: tags=accel:kvm - :avocado: tags=cpu:host - """ - self.require_accelerator("kvm") - self.vm.add_args("-accel", "kvm") - self.vm.add_args("-machine", "virt,gic-version=host") - self.add_common_args() - self.launch_and_wait(set_up_ssh_connection=False) - - -class BootLinuxPPC64(LinuxTest): - """ - :avocado: tags=arch:ppc64 - """ - - def test_pseries_tcg(self): - """ - :avocado: tags=machine:pseries - :avocado: tags=accel:tcg - """ - self.require_accelerator("tcg") - self.vm.add_args("-accel", "tcg") - self.launch_and_wait(set_up_ssh_connection=False) - - -class BootLinuxS390X(LinuxTest): - """ - :avocado: tags=arch:s390x - """ - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_s390_ccw_virtio_tcg(self): - """ - :avocado: tags=machine:s390-ccw-virtio - :avocado: tags=accel:tcg - """ - self.require_accelerator("tcg") - self.vm.add_args("-accel", "tcg") - self.launch_and_wait(set_up_ssh_connection=False) diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py deleted file mode 100644 index 06fc967f6c..0000000000 --- a/tests/acceptance/boot_linux_console.py +++ /dev/null @@ -1,1256 +0,0 @@ -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import lzma -import gzip -import shutil - -from avocado import skip -from avocado import skipUnless -from avocado_qemu import Test -from avocado_qemu import exec_command -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import interrupt_interactive_console_until_pattern -from avocado_qemu import wait_for_console_pattern -from avocado.utils import process -from avocado.utils import archive -from avocado.utils.path import find_command, CmdNotFoundError - -P7ZIP_AVAILABLE = True -try: - find_command('7z') -except CmdNotFoundError: - P7ZIP_AVAILABLE = False - -""" -Round up to next power of 2 -""" -def pow2ceil(x): - return 1 if x == 0 else 2**(x - 1).bit_length() - -""" -Expand file size to next power of 2 -""" -def image_pow2ceil_expand(path): - size = os.path.getsize(path) - size_aligned = pow2ceil(size) - if size != size_aligned: - with open(path, 'ab+') as fd: - fd.truncate(size_aligned) - -class LinuxKernelTest(Test): - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - def wait_for_console_pattern(self, success_message, vm=None): - wait_for_console_pattern(self, success_message, - failure_message='Kernel panic - not syncing', - vm=vm) - - def extract_from_deb(self, deb, path): - """ - Extracts a file from a deb package into the test workdir - - :param deb: path to the deb archive - :param path: path within the deb archive of the file to be extracted - :returns: path of the extracted file - """ - cwd = os.getcwd() - os.chdir(self.workdir) - file_path = process.run("ar t %s" % deb).stdout_text.split()[2] - process.run("ar x %s %s" % (deb, file_path)) - archive.extract(file_path, self.workdir) - os.chdir(cwd) - # Return complete path to extracted file. Because callers to - # extract_from_deb() specify 'path' with a leading slash, it is - # necessary to use os.path.relpath() as otherwise os.path.join() - # interprets it as an absolute path and drops the self.workdir part. - return os.path.normpath(os.path.join(self.workdir, - os.path.relpath(path, '/'))) - - def extract_from_rpm(self, rpm, path): - """ - Extracts a file from an RPM package into the test workdir. - - :param rpm: path to the rpm archive - :param path: path within the rpm archive of the file to be extracted - needs to be a relative path (starting with './') because - cpio(1), which is used to extract the file, expects that. - :returns: path of the extracted file - """ - cwd = os.getcwd() - os.chdir(self.workdir) - process.run("rpm2cpio %s | cpio -id %s" % (rpm, path), shell=True) - os.chdir(cwd) - return os.path.normpath(os.path.join(self.workdir, path)) - -class BootLinuxConsole(LinuxKernelTest): - """ - Boots a Linux kernel and checks that the console is operational and the - kernel command line is properly passed from QEMU to the kernel - """ - timeout = 90 - - def test_x86_64_pc(self): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=machine:pc - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/29/Everything/x86_64/os/images/pxeboot' - '/vmlinuz') - kernel_hash = '23bebd2680757891cf7adedb033532163a792495' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_mips_malta(self): - """ - :avocado: tags=arch:mips - :avocado: tags=machine:malta - :avocado: tags=endian:big - """ - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20130217T032700Z/pool/main/l/linux-2.6/' - 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb') - deb_hash = 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-2.6.32-5-4kc-malta') - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_mips64el_malta(self): - """ - This test requires the ar tool to extract "data.tar.gz" from - the Debian package. - - The kernel can be rebuilt using this Debian kernel source [1] and - following the instructions on [2]. - - [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/ - #linux-source-2.6.32_2.6.32-48 - [2] https://kernel-team.pages.debian.net/kernel-handbook/ - ch-common-tasks.html#s-common-official - - :avocado: tags=arch:mips64el - :avocado: tags=machine:malta - """ - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20130217T032700Z/pool/main/l/linux-2.6/' - 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb') - deb_hash = '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-2.6.32-5-5kc-malta') - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_mips64el_fuloong2e(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=machine:fuloong2e - :avocado: tags=endian:little - """ - deb_url = ('http://archive.debian.org/debian/pool/main/l/linux/' - 'linux-image-3.16.0-6-loongson-2e_3.16.56-1+deb8u1_mipsel.deb') - deb_hash = 'd04d446045deecf7b755ef576551de0c4184dd44' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-3.16.0-6-loongson-2e') - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_mips_malta_cpio(self): - """ - :avocado: tags=arch:mips - :avocado: tags=machine:malta - :avocado: tags=endian:big - """ - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20160601T041800Z/pool/main/l/linux/' - 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb') - deb_hash = 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-4.5.0-2-4kc-malta') - initrd_url = ('https://github.com/groeck/linux-build-test/raw/' - '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' - 'mips/rootfs.cpio.gz') - initrd_hash = 'bf806e17009360a866bf537f6de66590de349a99' - initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - initrd_path = self.workdir + "rootfs.cpio" - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 console=tty ' - + 'rdinit=/sbin/init noreboot') - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'BogoMIPS') - exec_command_and_wait_for_pattern(self, 'uname -a', - 'Debian') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_mips64el_malta_5KEc_cpio(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=machine:malta - :avocado: tags=endian:little - :avocado: tags=cpu:5KEc - """ - kernel_url = ('https://github.com/philmd/qemu-testing-blob/' - 'raw/9ad2df38/mips/malta/mips64el/' - 'vmlinux-3.19.3.mtoman.20150408') - kernel_hash = '00d1d268fb9f7d8beda1de6bebcc46e884d71754' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - initrd_url = ('https://github.com/groeck/linux-build-test/' - 'raw/8584a59e/rootfs/' - 'mipsel64/rootfs.mipsel64r1.cpio.gz') - initrd_hash = '1dbb8a396e916847325284dbe2151167' - initrd_path_gz = self.fetch_asset(initrd_url, algorithm='md5', - asset_hash=initrd_hash) - initrd_path = self.workdir + "rootfs.cpio" - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 console=tty ' - + 'rdinit=/sbin/init noreboot') - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - wait_for_console_pattern(self, 'Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'MIPS 5KE') - exec_command_and_wait_for_pattern(self, 'uname -a', - '3.19.3.mtoman.20150408') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - - def do_test_mips_malta32el_nanomips(self, kernel_url, kernel_hash): - kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - kernel_path = self.workdir + "kernel" - with lzma.open(kernel_path_xz, 'rb') as f_in: - with open(kernel_path, 'wb') as f_out: - shutil.copyfileobj(f_in, f_out) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'mem=256m@@0x0 ' - + 'console=ttyS0') - self.vm.add_args('-no-reboot', - '-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_mips_malta32el_nanomips_4k(self): - """ - :avocado: tags=arch:mipsel - :avocado: tags=machine:malta - :avocado: tags=endian:little - :avocado: tags=cpu:I7200 - """ - kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page4k.xz') - kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6' - self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash) - - def test_mips_malta32el_nanomips_16k_up(self): - """ - :avocado: tags=arch:mipsel - :avocado: tags=machine:malta - :avocado: tags=endian:little - :avocado: tags=cpu:I7200 - """ - kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page16k_up.xz') - kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc' - self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash) - - def test_mips_malta32el_nanomips_64k_dbg(self): - """ - :avocado: tags=arch:mipsel - :avocado: tags=machine:malta - :avocado: tags=endian:little - :avocado: tags=cpu:I7200 - """ - kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page64k_dbg.xz') - kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180' - self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash) - - def test_aarch64_virt(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=accel:tcg - :avocado: tags=cpu:cortex-a53 - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/29/Everything/aarch64/os/images/pxeboot' - '/vmlinuz') - kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - self.require_accelerator("tcg") - self.vm.add_args('-cpu', 'cortex-a53', - '-accel', 'tcg', - '-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_aarch64_xlnx_versal_virt(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:xlnx-versal-virt - :avocado: tags=device:pl011 - :avocado: tags=device:arm_gicv3 - :avocado: tags=accel:tcg - """ - images_url = ('http://ports.ubuntu.com/ubuntu-ports/dists/' - 'bionic-updates/main/installer-arm64/' - '20101020ubuntu543.15/images/') - kernel_url = images_url + 'netboot/ubuntu-installer/arm64/linux' - kernel_hash = '5bfc54cf7ed8157d93f6e5b0241e727b6dc22c50' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - initrd_url = images_url + 'netboot/ubuntu-installer/arm64/initrd.gz' - initrd_hash = 'd385d3e88d53e2004c5d43cbe668b458a094f772' - initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - - self.vm.set_console() - self.vm.add_args('-m', '2G', - '-accel', 'tcg', - '-kernel', kernel_path, - '-initrd', initrd_path) - self.vm.launch() - self.wait_for_console_pattern('Checked W+X mappings: passed') - - def test_arm_virt(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:virt - :avocado: tags=accel:tcg - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/29/Everything/armhfp/os/images/pxeboot' - '/vmlinuz') - kernel_hash = 'e9826d741b4fb04cadba8d4824d1ed3b7fb8b4d4' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_arm_emcraft_sf2(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:emcraft-sf2 - :avocado: tags=endian:little - :avocado: tags=u-boot - :avocado: tags=accel:tcg - """ - uboot_url = ('https://raw.githubusercontent.com/' - 'Subbaraya-Sundeep/qemu-test-binaries/' - 'fe371d32e50ca682391e1e70ab98c2942aeffb01/u-boot') - uboot_hash = 'cbb8cbab970f594bf6523b9855be209c08374ae2' - uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) - spi_url = ('https://raw.githubusercontent.com/' - 'Subbaraya-Sundeep/qemu-test-binaries/' - 'fe371d32e50ca682391e1e70ab98c2942aeffb01/spi.bin') - spi_hash = '65523a1835949b6f4553be96dec1b6a38fb05501' - spi_path = self.fetch_asset(spi_url, asset_hash=spi_hash) - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE - self.vm.add_args('-kernel', uboot_path, - '-append', kernel_command_line, - '-drive', 'file=' + spi_path + ',if=mtd,format=raw', - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Enter \'help\' for a list') - - exec_command_and_wait_for_pattern(self, 'ifconfig eth0 10.0.2.15', - 'eth0: link becomes ready') - exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', - '3 packets transmitted, 3 packets received, 0% packet loss') - - def do_test_arm_raspi2(self, uart_id): - """ - :avocado: tags=accel:tcg - - The kernel can be rebuilt using the kernel source referenced - and following the instructions on the on: - https://www.raspberrypi.org/documentation/linux/kernel/building.md - """ - serial_kernel_cmdline = { - 0: 'earlycon=pl011,0x3f201000 console=ttyAMA0', - } - deb_url = ('http://archive.raspberrypi.org/debian/' - 'pool/main/r/raspberrypi-firmware/' - 'raspberrypi-kernel_1.20190215-1_armhf.deb') - deb_hash = 'cd284220b32128c5084037553db3c482426f3972' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, '/boot/kernel7.img') - dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2709-rpi-2-b.dtb') - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - serial_kernel_cmdline[uart_id] + - ' root=/dev/mmcblk0p2 rootwait ' + - 'dwc_otg.fiq_fsm_enable=0') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-append', kernel_command_line, - '-device', 'usb-kbd') - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - console_pattern = 'Product: QEMU USB Keyboard' - self.wait_for_console_pattern(console_pattern) - - def test_arm_raspi2_uart0(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:raspi2b - :avocado: tags=device:pl011 - :avocado: tags=accel:tcg - """ - self.do_test_arm_raspi2(0) - - def test_arm_raspi2_initrd(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:raspi2b - """ - deb_url = ('http://archive.raspberrypi.org/debian/' - 'pool/main/r/raspberrypi-firmware/' - 'raspberrypi-kernel_1.20190215-1_armhf.deb') - deb_hash = 'cd284220b32128c5084037553db3c482426f3972' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, '/boot/kernel7.img') - dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2709-rpi-2-b.dtb') - - initrd_url = ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv7a.cpio.gz') - initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c' - initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - initrd_path = os.path.join(self.workdir, 'rootfs.cpio') - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'earlycon=pl011,0x3f201000 console=ttyAMA0 ' - 'panic=-1 noreboot ' + - 'dwc_otg.fiq_fsm_enable=0') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'BCM2835') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - '/soc/cprman@7e101000') - exec_command(self, 'halt') - # Wait for VM to shut down gracefully - self.vm.wait() - - def test_arm_exynos4210_initrd(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:smdkc210 - :avocado: tags=accel:tcg - """ - deb_url = ('https://snapshot.debian.org/archive/debian/' - '20190928T224601Z/pool/main/l/linux/' - 'linux-image-4.19.0-6-armmp_4.19.67-2+deb10u1_armhf.deb') - deb_hash = 'fa9df4a0d38936cb50084838f2cb933f570d7d82' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinuz-4.19.0-6-armmp') - dtb_path = '/usr/lib/linux-image-4.19.0-6-armmp/exynos4210-smdkv310.dtb' - dtb_path = self.extract_from_deb(deb_path, dtb_path) - - initrd_url = ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv5.cpio.gz') - initrd_hash = '2b50f1873e113523967806f4da2afe385462ff9b' - initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - initrd_path = os.path.join(self.workdir, 'rootfs.cpio') - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'earlycon=exynos4210,0x13800000 earlyprintk ' + - 'console=ttySAC0,115200n8 ' + - 'random.trust_cpu=off cryptomgr.notests ' + - 'cpuidle.off=1 panic=-1 noreboot') - - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - - self.wait_for_console_pattern('Boot successful.') - # TODO user command, for now the uart is stuck - - def test_arm_cubieboard_initrd(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:cubieboard - :avocado: tags=accel:tcg - """ - deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') - deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinuz-5.10.16-sunxi') - dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb' - dtb_path = self.extract_from_deb(deb_path, dtb_path) - initrd_url = ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv5.cpio.gz') - initrd_hash = '2b50f1873e113523967806f4da2afe385462ff9b' - initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - initrd_path = os.path.join(self.workdir, 'rootfs.cpio') - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'usbcore.nousb ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun4i/sun5i') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - 'system-control@1c00000') - # cubieboard's reboot is not functioning; omit reboot test. - - def test_arm_cubieboard_sata(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:cubieboard - :avocado: tags=accel:tcg - """ - deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') - deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinuz-5.10.16-sunxi') - dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb' - dtb_path = self.extract_from_deb(deb_path, dtb_path) - rootfs_url = ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv5.ext2.gz') - rootfs_hash = '093e89d2b4d982234bf528bc9fb2f2f17a9d1f93' - rootfs_path_gz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash) - rootfs_path = os.path.join(self.workdir, 'rootfs.cpio') - archive.gzip_uncompress(rootfs_path_gz, rootfs_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'usbcore.nousb ' - 'root=/dev/sda ro ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-drive', 'if=none,format=raw,id=disk0,file=' - + rootfs_path, - '-device', 'ide-hd,bus=ide.0,drive=disk0', - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun4i/sun5i') - exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', - 'sda') - # cubieboard's reboot is not functioning; omit reboot test. - - @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') - def test_arm_quanta_gsj(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:quanta-gsj - :avocado: tags=accel:tcg - """ - # 25 MiB compressed, 32 MiB uncompressed. - image_url = ( - 'https://github.com/hskinnemoen/openbmc/releases/download/' - '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz') - image_hash = '14895e634923345cb5c8776037ff7876df96f6b1' - image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash) - image_name = 'obmc.mtd' - image_path = os.path.join(self.workdir, image_name) - archive.gzip_uncompress(image_path_gz, image_path) - - self.vm.set_console() - drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0' - self.vm.add_args('-drive', drive_args) - self.vm.launch() - - # Disable drivers and services that stall for a long time during boot, - # to avoid running past the 90-second timeout. These may be removed - # as the corresponding device support is added. - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + ( - 'console=${console} ' - 'mem=${mem} ' - 'initcall_blacklist=npcm_i2c_bus_driver_init ' - 'systemd.mask=systemd-random-seed.service ' - 'systemd.mask=dropbearkey.service ' - ) - - self.wait_for_console_pattern('> BootBlock by Nuvoton') - self.wait_for_console_pattern('>Device: Poleg BMC NPCM730') - self.wait_for_console_pattern('>Skip DDR init.') - self.wait_for_console_pattern('U-Boot ') - interrupt_interactive_console_until_pattern( - self, 'Hit any key to stop autoboot:', 'U-Boot>') - exec_command_and_wait_for_pattern( - self, "setenv bootargs ${bootargs} " + kernel_command_line, - 'U-Boot>') - exec_command_and_wait_for_pattern( - self, 'run romboot', 'Booting Kernel from flash') - self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') - self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') - self.wait_for_console_pattern('OpenBMC Project Reference Distro') - self.wait_for_console_pattern('gsj login:') - - def test_arm_quanta_gsj_initrd(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:quanta-gsj - :avocado: tags=accel:tcg - """ - initrd_url = ( - 'https://github.com/hskinnemoen/openbmc/releases/download/' - '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz') - initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300' - initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - kernel_url = ( - 'https://github.com/hskinnemoen/openbmc/releases/download/' - '20200711-gsj-qemu-0/uImage-gsj.bin') - kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - dtb_url = ( - 'https://github.com/hskinnemoen/openbmc/releases/download/' - '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb') - dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4' - dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200n8 ' - 'earlycon=uart8250,mmio32,0xf0001000') - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-dtb', dtb_path, - '-append', kernel_command_line) - self.vm.launch() - - self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') - self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') - self.wait_for_console_pattern( - 'Give root password for system maintenance') - - def test_arm_orangepi(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:orangepi-pc - :avocado: tags=accel:tcg - """ - deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') - deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinuz-5.10.16-sunxi') - dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb' - dtb_path = self.extract_from_deb(deb_path, dtb_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200n8 ' - 'earlycon=uart,mmio32,0x1c28000') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_arm_orangepi_initrd(self): - """ - :avocado: tags=arch:arm - :avocado: tags=accel:tcg - :avocado: tags=machine:orangepi-pc - """ - deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') - deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinuz-5.10.16-sunxi') - dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb' - dtb_path = self.extract_from_deb(deb_path, dtb_path) - initrd_url = ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv7a.cpio.gz') - initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c' - initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - initrd_path = os.path.join(self.workdir, 'rootfs.cpio') - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun8i Family') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - 'system-control@1c00000') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - - def test_arm_orangepi_sd(self): - """ - :avocado: tags=arch:arm - :avocado: tags=accel:tcg - :avocado: tags=machine:orangepi-pc - :avocado: tags=device:sd - """ - deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') - deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinuz-5.10.16-sunxi') - dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb' - dtb_path = self.extract_from_deb(deb_path, dtb_path) - rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/' - 'kci-2019.02/armel/base/rootfs.ext2.xz') - rootfs_hash = '692510cb625efda31640d1de0a8d60e26040f061' - rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash) - rootfs_path = os.path.join(self.workdir, 'rootfs.cpio') - archive.lzma_uncompress(rootfs_path_xz, rootfs_path) - image_pow2ceil_expand(rootfs_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'root=/dev/mmcblk0 rootwait rw ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-drive', 'file=' + rootfs_path + ',if=sd,format=raw', - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - shell_ready = "/bin/sh: can't access tty; job control turned off" - self.wait_for_console_pattern(shell_ready) - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun8i Family') - exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', - 'mmcblk0') - exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up', - 'eth0: Link is Up') - exec_command_and_wait_for_pattern(self, 'udhcpc eth0', - 'udhcpc: lease of 10.0.2.15 obtained') - exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', - '3 packets transmitted, 3 packets received, 0% packet loss') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - - @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited') - def test_arm_orangepi_bionic_20_08(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:orangepi-pc - :avocado: tags=device:sd - """ - - # This test download a 275 MiB compressed image and expand it - # to 1036 MiB, but the underlying filesystem is 1552 MiB... - # As we expand it to 2 GiB we are safe. - - image_url = ('https://archive.armbian.com/orangepipc/archive/' - 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz') - image_hash = ('b4d6775f5673486329e45a0586bf06b6' - 'dbe792199fd182ac6b9c7bb6c7d3e6dd') - image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash, - algorithm='sha256') - image_path = archive.extract(image_path_xz, self.workdir) - image_pow2ceil_expand(image_path) - - self.vm.set_console() - self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', - '-nic', 'user', - '-no-reboot') - self.vm.launch() - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'loglevel=7 ' - 'nosmp ' - 'systemd.default_timeout_start_sec=9000 ' - 'systemd.mask=armbian-zram-config.service ' - 'systemd.mask=armbian-ramlog.service') - - self.wait_for_console_pattern('U-Boot SPL') - self.wait_for_console_pattern('Autoboot in ') - exec_command_and_wait_for_pattern(self, ' ', '=>') - exec_command_and_wait_for_pattern(self, "setenv extraargs '" + - kernel_command_line + "'", '=>') - exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...'); - - self.wait_for_console_pattern('systemd[1]: Set hostname ' + - 'to ') - self.wait_for_console_pattern('Starting Load Kernel Modules...') - - @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited') - def test_arm_orangepi_uboot_netbsd9(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:orangepi-pc - :avocado: tags=device:sd - :avocado: tags=os:netbsd - """ - # This test download a 304MB compressed image and expand it to 2GB - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20200108T145233Z/pool/main/u/u-boot/' - 'u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb') - deb_hash = 'f67f404a80753ca3d1258f13e38f2b060e13db99' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - # We use the common OrangePi PC 'plus' build of U-Boot for our secondary - # program loader (SPL). We will then set the path to the more specific - # OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt, - # before to boot NetBSD. - uboot_path = '/usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin' - uboot_path = self.extract_from_deb(deb_path, uboot_path) - image_url = ('https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/' - 'evbarm-earmv7hf/binary/gzimg/armv7.img.gz') - image_hash = '2babb29d36d8360adcb39c09e31060945259917a' - image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash) - image_path = os.path.join(self.workdir, 'armv7.img') - archive.gzip_uncompress(image_path_gz, image_path) - image_pow2ceil_expand(image_path) - image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path - - # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc - with open(uboot_path, 'rb') as f_in: - with open(image_path, 'r+b') as f_out: - f_out.seek(8 * 1024) - shutil.copyfileobj(f_in, f_out) - - self.vm.set_console() - self.vm.add_args('-nic', 'user', - '-drive', image_drive_args, - '-global', 'allwinner-rtc.base-year=2000', - '-no-reboot') - self.vm.launch() - wait_for_console_pattern(self, 'U-Boot 2020.01+dfsg-1') - interrupt_interactive_console_until_pattern(self, - 'Hit any key to stop autoboot:', - 'switch to partitions #0, OK') - - exec_command_and_wait_for_pattern(self, '', '=>') - cmd = 'setenv bootargs root=ld0a' - exec_command_and_wait_for_pattern(self, cmd, '=>') - cmd = 'setenv kernel netbsd-GENERIC.ub' - exec_command_and_wait_for_pattern(self, cmd, '=>') - cmd = 'setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb' - exec_command_and_wait_for_pattern(self, cmd, '=>') - cmd = ("setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; " - "fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; " - "fdt addr ${fdt_addr_r}; " - "bootm ${kernel_addr_r} - ${fdt_addr_r}'") - exec_command_and_wait_for_pattern(self, cmd, '=>') - - exec_command_and_wait_for_pattern(self, 'boot', - 'Booting kernel from Legacy Image') - wait_for_console_pattern(self, 'Starting kernel ...') - wait_for_console_pattern(self, 'NetBSD 9.0 (GENERIC)') - # Wait for user-space - wait_for_console_pattern(self, 'Starting root file system check') - - def test_aarch64_raspi3_atf(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:raspi3b - :avocado: tags=cpu:cortex-a53 - :avocado: tags=device:pl011 - :avocado: tags=atf - """ - zip_url = ('https://github.com/pbatard/RPi3/releases/download/' - 'v1.15/RPi3_UEFI_Firmware_v1.15.zip') - zip_hash = '74b3bd0de92683cadb14e008a7575e1d0c3cafb9' - zip_path = self.fetch_asset(zip_url, asset_hash=zip_hash) - - archive.extract(zip_path, self.workdir) - efi_fd = os.path.join(self.workdir, 'RPI_EFI.fd') - - self.vm.set_console(console_index=1) - self.vm.add_args('-nodefaults', - '-device', 'loader,file=%s,force-raw=true' % efi_fd) - self.vm.launch() - self.wait_for_console_pattern('version UEFI Firmware v1.15') - - def test_s390x_s390_ccw_virtio(self): - """ - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/29/Everything/s390x/os/images' - '/kernel.img') - kernel_hash = 'e8e8439103ef8053418ef062644ffd46a7919313' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=sclp0' - self.vm.add_args('-nodefaults', - '-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_alpha_clipper(self): - """ - :avocado: tags=arch:alpha - :avocado: tags=machine:clipper - """ - kernel_url = ('http://archive.debian.org/debian/dists/lenny/main/' - 'installer-alpha/20090123lenny10/images/cdrom/vmlinuz') - kernel_hash = '3a943149335529e2ed3e74d0d787b85fb5671ba3' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - uncompressed_kernel = archive.uncompress(kernel_path, self.workdir) - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-nodefaults', - '-kernel', uncompressed_kernel, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_m68k_q800(self): - """ - :avocado: tags=arch:m68k - :avocado: tags=machine:q800 - """ - deb_url = ('https://snapshot.debian.org/archive/debian-ports' - '/20191021T083923Z/pool-m68k/main' - '/l/linux/kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb') - deb_hash = '044954bb9be4160a3ce81f8bc1b5e856b75cccd1' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-5.3.0-1-m68k') - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 vga=off') - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - console_pattern = 'No filesystem could mount root' - self.wait_for_console_pattern(console_pattern) - - def do_test_advcal_2018(self, day, tar_hash, kernel_name, console=0): - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day' + day + '.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console(console_index=console) - self.vm.add_args('-kernel', - self.workdir + '/day' + day + '/' + kernel_name) - self.vm.launch() - self.wait_for_console_pattern('QEMU advent calendar') - - def test_arm_vexpressa9(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:vexpress-a9 - """ - tar_hash = '32b7677ce8b6f1471fb0059865f451169934245b' - self.vm.add_args('-dtb', self.workdir + '/day16/vexpress-v2p-ca9.dtb') - self.do_test_advcal_2018('16', tar_hash, 'winter.zImage') - - def test_arm_ast2400_palmetto_openbmc_v2_9_0(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:palmetto-bmc - """ - - image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' - 'obmc-phosphor-image-palmetto.static.mtd') - image_hash = ('3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d') - image_path = self.fetch_asset(image_url, asset_hash=image_hash, - algorithm='sha256') - - self.do_test_arm_aspeed(image_path) - - def test_arm_ast2500_romulus_openbmc_v2_9_0(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:romulus-bmc - """ - - image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' - 'obmc-phosphor-image-romulus.static.mtd') - image_hash = ('820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25') - image_path = self.fetch_asset(image_url, asset_hash=image_hash, - algorithm='sha256') - - self.do_test_arm_aspeed(image_path) - - def do_test_arm_aspeed(self, image): - self.vm.set_console() - self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', - '-net', 'nic') - self.vm.launch() - - self.wait_for_console_pattern("U-Boot 2016.07") - self.wait_for_console_pattern("## Loading kernel from FIT Image at 20080000") - self.wait_for_console_pattern("Starting kernel ...") - self.wait_for_console_pattern("Booting Linux on physical CPU 0x0") - self.wait_for_console_pattern( - "aspeed-smc 1e620000.spi: read control register: 203b0641") - self.wait_for_console_pattern("ftgmac100 1e660000.ethernet eth0: irq ") - self.wait_for_console_pattern("systemd[1]: Set hostname to") - - def test_arm_ast2600_debian(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:tacoma-bmc - """ - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20210302T203551Z/' - 'pool/main/l/linux/' - 'linux-image-5.10.0-3-armmp_5.10.13-1_armhf.deb') - deb_hash = 'db40d32fe39255d05482bea48d72467b67d6225bb2a2a4d6f618cb8976f1e09e' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash, - algorithm='sha256') - kernel_path = self.extract_from_deb(deb_path, '/boot/vmlinuz-5.10.0-3-armmp') - dtb_path = self.extract_from_deb(deb_path, - '/usr/lib/linux-image-5.10.0-3-armmp/aspeed-bmc-opp-tacoma.dtb') - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-net', 'nic') - self.vm.launch() - self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") - self.wait_for_console_pattern("SMP: Total of 2 processors activated") - self.wait_for_console_pattern("No filesystem could mount root") - - def test_m68k_mcf5208evb(self): - """ - :avocado: tags=arch:m68k - :avocado: tags=machine:mcf5208evb - """ - tar_hash = 'ac688fd00561a2b6ce1359f9ff6aa2b98c9a570c' - self.do_test_advcal_2018('07', tar_hash, 'sanity-clause.elf') - - def test_or1k_sim(self): - """ - :avocado: tags=arch:or1k - :avocado: tags=machine:or1k-sim - """ - tar_hash = '20334cdaf386108c530ff0badaecc955693027dd' - self.do_test_advcal_2018('20', tar_hash, 'vmlinux') - - def test_nios2_10m50(self): - """ - :avocado: tags=arch:nios2 - :avocado: tags=machine:10m50-ghrd - """ - tar_hash = 'e4251141726c412ac0407c5a6bceefbbff018918' - self.do_test_advcal_2018('14', tar_hash, 'vmlinux.elf') - - def test_ppc64_e500(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:ppce500 - :avocado: tags=cpu:e5500 - """ - tar_hash = '6951d86d644b302898da2fd701739c9406527fe1' - self.do_test_advcal_2018('19', tar_hash, 'uImage') - - def do_test_ppc64_powernv(self, proc): - images_url = ('https://github.com/open-power/op-build/releases/download/v2.7/') - - kernel_url = images_url + 'zImage.epapr' - kernel_hash = '0ab237df661727e5392cee97460e8674057a883c5f74381a128fa772588d45cd' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash, - algorithm='sha256') - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-append', 'console=tty0 console=hvc0', - '-device', 'pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0', - '-device', 'nvme,bus=pcie.2,addr=0x0,serial=1234', - '-device', 'e1000e,bus=bridge1,addr=0x3', - '-device', 'nec-usb-xhci,bus=bridge1,addr=0x2') - self.vm.launch() - - self.wait_for_console_pattern("CPU: " + proc + " generation processor") - self.wait_for_console_pattern("zImage starting: loaded") - self.wait_for_console_pattern("Run /init as init process") - self.wait_for_console_pattern("Creating 1 MTD partitions") - - def test_ppc_powernv8(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:powernv8 - """ - self.do_test_ppc64_powernv('P8') - - def test_ppc_powernv9(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:powernv9 - """ - self.do_test_ppc64_powernv('P9') - - def test_ppc_g3beige(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:g3beige - """ - tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' - self.vm.add_args('-M', 'graphics=off') - self.do_test_advcal_2018('15', tar_hash, 'invaders.elf') - - def test_ppc_mac99(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:mac99 - """ - tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' - self.vm.add_args('-M', 'graphics=off') - self.do_test_advcal_2018('15', tar_hash, 'invaders.elf') - - def test_sh4_r2d(self): - """ - :avocado: tags=arch:sh4 - :avocado: tags=machine:r2d - """ - tar_hash = 'fe06a4fd8ccbf2e27928d64472939d47829d4c7e' - self.vm.add_args('-append', 'console=ttySC1') - self.do_test_advcal_2018('09', tar_hash, 'zImage', console=1) - - def test_sparc_ss20(self): - """ - :avocado: tags=arch:sparc - :avocado: tags=machine:SS-20 - """ - tar_hash = 'b18550d5d61c7615d989a06edace051017726a9f' - self.do_test_advcal_2018('11', tar_hash, 'zImage.elf') - - def test_xtensa_lx60(self): - """ - :avocado: tags=arch:xtensa - :avocado: tags=machine:lx60 - :avocado: tags=cpu:dc233c - """ - tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34' - self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf') diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py deleted file mode 100644 index fc2faeedb5..0000000000 --- a/tests/acceptance/boot_xen.py +++ /dev/null @@ -1,116 +0,0 @@ -# Functional test that boots a Xen hypervisor with a domU kernel and -# checks the console output is vaguely sane . -# -# Copyright (c) 2020 Linaro -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os - -from avocado_qemu import wait_for_console_pattern -from boot_linux_console import LinuxKernelTest - - -class BootXenBase(LinuxKernelTest): - """ - Boots a Xen hypervisor with a Linux DomU kernel. - """ - - timeout = 90 - XEN_COMMON_COMMAND_LINE = 'dom0_mem=128M loglvl=all guest_loglvl=all' - - def fetch_guest_kernel(self): - # Using my own built kernel - which works - kernel_url = ('https://fileserver.linaro.org/' - 's/JSsewXGZ6mqxPr5/download?path=%2F&files=' - 'linux-5.9.9-arm64-ajb') - kernel_sha1 = '4f92bc4b9f88d5ab792fa7a43a68555d344e1b83' - kernel_path = self.fetch_asset(kernel_url, - asset_hash=kernel_sha1) - - return kernel_path - - def launch_xen(self, xen_path): - """ - Launch Xen with a dom0 guest kernel - """ - self.log.info("launch with xen_path: %s", xen_path) - kernel_path = self.fetch_guest_kernel() - - self.vm.set_console() - - xen_command_line = self.XEN_COMMON_COMMAND_LINE - self.vm.add_args('-machine', 'virtualization=on', - '-m', '768', - '-kernel', xen_path, - '-append', xen_command_line, - '-device', - 'guest-loader,addr=0x47000000,kernel=%s,bootargs=console=hvc0' - % (kernel_path)) - - self.vm.launch() - - console_pattern = 'VFS: Cannot open root device' - wait_for_console_pattern(self, console_pattern, "Panic on CPU 0:") - - -class BootXen(BootXenBase): - - def test_arm64_xen_411_and_dom0(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=accel:tcg - :avocado: tags=cpu:cortex-a57 - :avocado: tags=machine:virt - """ - - # archive of file from https://deb.debian.org/debian/pool/main/x/xen/ - xen_url = ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/' - 'download?path=%2F&files=' - 'xen-hypervisor-4.11-arm64_4.11.4%2B37-g3263f257ca-1_arm64.deb') - xen_sha1 = '034e634d4416adbad1212d59b62bccdcda63e62a' - xen_deb = self.fetch_asset(xen_url, asset_hash=xen_sha1) - xen_path = self.extract_from_deb(xen_deb, "/boot/xen-4.11-arm64") - - self.launch_xen(xen_path) - - def test_arm64_xen_414_and_dom0(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=accel:tcg - :avocado: tags=cpu:cortex-a57 - :avocado: tags=machine:virt - """ - - # archive of file from https://deb.debian.org/debian/pool/main/x/xen/ - xen_url = ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/' - 'download?path=%2F&files=' - 'xen-hypervisor-4.14-arm64_4.14.0%2B80-gd101b417b7-1_arm64.deb') - xen_sha1 = 'b9d209dd689ed2b393e625303a225badefec1160' - xen_deb = self.fetch_asset(xen_url, asset_hash=xen_sha1) - xen_path = self.extract_from_deb(xen_deb, "/boot/xen-4.14-arm64") - - self.launch_xen(xen_path) - - def test_arm64_xen_415_and_dom0(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=accel:tcg - :avocado: tags=cpu:cortex-a57 - :avocado: tags=machine:virt - """ - - xen_url = ('https://fileserver.linaro.org/' - 's/JSsewXGZ6mqxPr5/download' - '?path=%2F&files=xen-upstream-4.15-unstable.deb') - xen_sha1 = 'fc191172b85cf355abb95d275a24cc0f6d6579d8' - xen_deb = self.fetch_asset(xen_url, asset_hash=xen_sha1) - xen_path = self.extract_from_deb(xen_deb, "/boot/xen-4.15-unstable") - - self.launch_xen(xen_path) diff --git a/tests/acceptance/cpu_queries.py b/tests/acceptance/cpu_queries.py deleted file mode 100644 index cc9e380cc7..0000000000 --- a/tests/acceptance/cpu_queries.py +++ /dev/null @@ -1,34 +0,0 @@ -# Sanity check of query-cpu-* results -# -# Copyright (c) 2019 Red Hat, Inc. -# -# Author: -# Eduardo Habkost -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado_qemu import Test - -class QueryCPUModelExpansion(Test): - """ - Run query-cpu-model-expansion for each CPU model, and validate results - """ - - def test(self): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=machine:none - """ - self.vm.add_args('-S') - self.vm.launch() - - cpus = self.vm.command('query-cpu-definitions') - for c in cpus: - self.log.info("Checking CPU: %s", c) - self.assertNotIn('', c['unavailable-features'], c['name']) - - for c in cpus: - model = {'name': c['name']} - e = self.vm.command('query-cpu-model-expansion', model=model, type='full') - self.assertEquals(e['model']['name'], c['name']) diff --git a/tests/acceptance/empty_cpu_model.py b/tests/acceptance/empty_cpu_model.py deleted file mode 100644 index a1e59e45e4..0000000000 --- a/tests/acceptance/empty_cpu_model.py +++ /dev/null @@ -1,19 +0,0 @@ -# Check for crash when using empty -cpu option -# -# Copyright (c) 2019 Red Hat, Inc. -# -# Author: -# Eduardo Habkost -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. -from avocado_qemu import Test - -class EmptyCPUModel(Test): - def test(self): - self.vm.add_args('-S', '-display', 'none', '-machine', 'none', '-cpu', '') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty') diff --git a/tests/acceptance/hotplug_cpu.py b/tests/acceptance/hotplug_cpu.py deleted file mode 100644 index 6374bf1b54..0000000000 --- a/tests/acceptance/hotplug_cpu.py +++ /dev/null @@ -1,37 +0,0 @@ -# Functional test that hotplugs a CPU and checks it on a Linux guest -# -# Copyright (c) 2021 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado_qemu import LinuxTest - - -class HotPlugCPU(LinuxTest): - - def test(self): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=machine:q35 - :avocado: tags=accel:kvm - """ - self.require_accelerator('kvm') - self.vm.add_args('-accel', 'kvm') - self.vm.add_args('-cpu', 'Haswell') - self.vm.add_args('-smp', '1,sockets=1,cores=2,threads=1,maxcpus=2') - self.launch_and_wait() - - self.ssh_command('test -e /sys/devices/system/cpu/cpu0') - with self.assertRaises(AssertionError): - self.ssh_command('test -e /sys/devices/system/cpu/cpu1') - - self.vm.command('device_add', - driver='Haswell-x86_64-cpu', - socket_id=0, - core_id=1, - thread_id=0) - self.ssh_command('test -e /sys/devices/system/cpu/cpu1') diff --git a/tests/acceptance/info_usernet.py b/tests/acceptance/info_usernet.py deleted file mode 100644 index 9c1fd903a0..0000000000 --- a/tests/acceptance/info_usernet.py +++ /dev/null @@ -1,29 +0,0 @@ -# Test for the hmp command "info usernet" -# -# Copyright (c) 2021 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado_qemu import Test - -from qemu.utils import get_info_usernet_hostfwd_port - - -class InfoUsernet(Test): - - def test_hostfwd(self): - self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22') - self.vm.launch() - res = self.vm.command('human-monitor-command', - command_line='info usernet') - port = get_info_usernet_hostfwd_port(res) - self.assertIsNotNone(port, - ('"info usernet" output content does not seem to ' - 'contain the redirected port')) - self.assertGreater(port, 0, - ('Found a redirected port that is not greater than' - ' zero')) diff --git a/tests/acceptance/intel_iommu.py b/tests/acceptance/intel_iommu.py deleted file mode 100644 index 474d62f6bf..0000000000 --- a/tests/acceptance/intel_iommu.py +++ /dev/null @@ -1,119 +0,0 @@ -# INTEL_IOMMU Functional tests -# -# Copyright (c) 2021 Red Hat, Inc. -# -# Author: -# Eric Auger -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. -import os - -from avocado import skipIf -from avocado_qemu import LinuxTest - -@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') -class IntelIOMMU(LinuxTest): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=distro:fedora - :avocado: tags=distro_version:31 - :avocado: tags=machine:q35 - :avocado: tags=accel:kvm - :avocado: tags=intel_iommu - """ - - IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' - kernel_path = None - initrd_path = None - kernel_params = None - - def set_up_boot(self): - path = self.download_boot() - self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,scsi=off,' + - 'drive=drv0,id=virtio-disk0,bootindex=1,' - 'werror=stop,rerror=stop' + self.IOMMU_ADDON) - self.vm.add_args('-device', 'virtio-gpu-pci' + self.IOMMU_ADDON) - self.vm.add_args('-drive', - 'file=%s,if=none,cache=writethrough,id=drv0' % path) - - def setUp(self): - super(IntelIOMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) - - def add_common_args(self): - self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') - self.vm.add_args('-object', - 'rng-random,id=rng0,filename=/dev/urandom') - - def common_vm_setup(self, custom_kernel=None): - self.require_accelerator("kvm") - self.add_common_args() - self.vm.add_args("-accel", "kvm") - - if custom_kernel is None: - return - - kernel_url = self.distro.pxeboot_url + 'vmlinuz' - initrd_url = self.distro.pxeboot_url + 'initrd.img' - self.kernel_path = self.fetch_asset(kernel_url) - self.initrd_path = self.fetch_asset(initrd_url) - - def run_and_check(self): - if self.kernel_path: - self.vm.add_args('-kernel', self.kernel_path, - '-append', self.kernel_params, - '-initrd', self.initrd_path) - self.launch_and_wait() - self.ssh_command('cat /proc/cmdline') - self.ssh_command('dmesg | grep -e DMAR -e IOMMU') - self.ssh_command('find /sys/kernel/iommu_groups/ -type l') - self.ssh_command('dnf -y install numactl-devel') - - def test_intel_iommu(self): - """ - :avocado: tags=intel_iommu_intremap - """ - - self.common_vm_setup(True) - self.vm.add_args('-device', 'intel-iommu,intremap=on') - self.vm.add_args('-machine', 'kernel_irqchip=split') - - self.kernel_params = (self.distro.default_kernel_params + - ' quiet intel_iommu=on') - self.run_and_check() - - def test_intel_iommu_strict(self): - """ - :avocado: tags=intel_iommu_strict - """ - - self.common_vm_setup(True) - self.vm.add_args('-device', 'intel-iommu,intremap=on') - self.vm.add_args('-machine', 'kernel_irqchip=split') - self.kernel_params = (self.distro.default_kernel_params + - ' quiet intel_iommu=on,strict') - self.run_and_check() - - def test_intel_iommu_strict_cm(self): - """ - :avocado: tags=intel_iommu_strict_cm - """ - - self.common_vm_setup(True) - self.vm.add_args('-device', 'intel-iommu,intremap=on,caching-mode=on') - self.vm.add_args('-machine', 'kernel_irqchip=split') - self.kernel_params = (self.distro.default_kernel_params + - ' quiet intel_iommu=on,strict') - self.run_and_check() - - def test_intel_iommu_pt(self): - """ - :avocado: tags=intel_iommu_pt - """ - - self.common_vm_setup(True) - self.vm.add_args('-device', 'intel-iommu,intremap=on') - self.vm.add_args('-machine', 'kernel_irqchip=split') - self.kernel_params = (self.distro.default_kernel_params + - ' quiet intel_iommu=on iommu=pt') - self.run_and_check() diff --git a/tests/acceptance/linux_initrd.py b/tests/acceptance/linux_initrd.py deleted file mode 100644 index a249e2f14a..0000000000 --- a/tests/acceptance/linux_initrd.py +++ /dev/null @@ -1,89 +0,0 @@ -# Linux initrd acceptance test. -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Wainer dos Santos Moschetta -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import logging -import tempfile - -from avocado_qemu import Test -from avocado import skipIf - - -class LinuxInitrd(Test): - """ - Checks QEMU evaluates correctly the initrd file passed as -initrd option. - - :avocado: tags=arch:x86_64 - :avocado: tags=machine:pc - """ - - timeout = 300 - - def test_with_2gib_file_should_exit_error_msg_with_linux_v3_6(self): - """ - Pretends to boot QEMU with an initrd file with size of 2GiB - and expect it exits with error message. - Fedora-18 shipped with linux-3.6 which have not supported xloadflags - cannot support more than 2GiB initrd. - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora/li' - 'nux/releases/18/Fedora/x86_64/os/images/pxeboot/vmlinuz') - kernel_hash = '41464f68efe42b9991250bed86c7081d2ccdbb21' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - max_size = 2 * (1024 ** 3) - 1 - - with tempfile.NamedTemporaryFile() as initrd: - initrd.seek(max_size) - initrd.write(b'\0') - initrd.flush() - self.vm.add_args('-kernel', kernel_path, '-initrd', initrd.name, - '-m', '4096') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1) - expected_msg = r'.*initrd is too large.*max: \d+, need %s.*' % ( - max_size + 1) - self.assertRegex(self.vm.get_log(), expected_msg) - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_with_2gib_file_should_work_with_linux_v4_16(self): - """ - QEMU has supported up to 4 GiB initrd for recent kernel - Expect guest can reach 'Unpacking initramfs...' - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/28/Everything/x86_64/os/images/pxeboot/' - 'vmlinuz') - kernel_hash = '238e083e114c48200f80d889f7e32eeb2793e02a' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - max_size = 2 * (1024 ** 3) + 1 - - with tempfile.NamedTemporaryFile() as initrd: - initrd.seek(max_size) - initrd.write(b'\0') - initrd.flush() - - self.vm.set_console() - kernel_command_line = 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line, - '-initrd', initrd.name, - '-m', '5120') - self.vm.launch() - console = self.vm.console_socket.makefile() - console_logger = logging.getLogger('console') - while True: - msg = console.readline() - console_logger.debug(msg.strip()) - if 'Unpacking initramfs...' in msg: - break - if 'Kernel panic - not syncing' in msg: - self.fail("Kernel panic reached") diff --git a/tests/acceptance/linux_ssh_mips_malta.py b/tests/acceptance/linux_ssh_mips_malta.py deleted file mode 100644 index 4de1947418..0000000000 --- a/tests/acceptance/linux_ssh_mips_malta.py +++ /dev/null @@ -1,209 +0,0 @@ -# Functional test that boots a VM and run commands via a SSH session -# -# Copyright (c) Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import re -import base64 -import logging -import time - -from avocado import skipUnless -from avocado_qemu import Test, LinuxSSHMixIn -from avocado_qemu import wait_for_console_pattern -from avocado.utils import process -from avocado.utils import archive -from avocado.utils import ssh - - -@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') -@skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available') -class LinuxSSH(Test, LinuxSSHMixIn): - - timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg' - - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - VM_IP = '127.0.0.1' - - BASE_URL = 'https://people.debian.org/~aurel32/qemu/' - IMAGE_INFO = { - 'be': {'base_url': 'mips', - 'image_name': 'debian_wheezy_mips_standard.qcow2', - 'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5', - 'kernel_hash': { - 32: '592e384a4edc16dade52a6cd5c785c637bcbc9ad', - 64: 'db6eea7de35d36c77d8c165b6bcb222e16eb91db'} - }, - 'le': {'base_url': 'mipsel', - 'image_name': 'debian_wheezy_mipsel_standard.qcow2', - 'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802', - 'kernel_hash': { - 32: 'a66bea5a8adaa2cb3d36a1d4e0ccdb01be8f6c2a', - 64: '6a7f77245acf231415a0e8b725d91ed2f3487794'} - } - } - CPU_INFO = { - 32: {'cpu': 'MIPS 24Kc', 'kernel_release': '3.2.0-4-4kc-malta'}, - 64: {'cpu': 'MIPS 20Kc', 'kernel_release': '3.2.0-4-5kc-malta'} - } - - def get_url(self, endianess, path=''): - qkey = {'le': 'el', 'be': ''} - return '%s/mips%s/%s' % (self.BASE_URL, qkey[endianess], path) - - def get_image_info(self, endianess): - dinfo = self.IMAGE_INFO[endianess] - image_url = self.get_url(endianess, dinfo['image_name']) - image_hash = dinfo['image_hash'] - return (image_url, image_hash) - - def get_kernel_info(self, endianess, wordsize): - minfo = self.CPU_INFO[wordsize] - kernel_url = self.get_url(endianess, - 'vmlinux-%s' % minfo['kernel_release']) - kernel_hash = self.IMAGE_INFO[endianess]['kernel_hash'][wordsize] - return kernel_url, kernel_hash - - def ssh_disconnect_vm(self): - self.ssh_session.quit() - - def boot_debian_wheezy_image_and_ssh_login(self, endianess, kernel_path): - image_url, image_hash = self.get_image_info(endianess) - image_path = self.fetch_asset(image_url, asset_hash=image_hash) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 root=/dev/sda1') - self.vm.add_args('-no-reboot', - '-kernel', kernel_path, - '-append', kernel_command_line, - '-drive', 'file=%s,snapshot=on' % image_path, - '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', - '-device', 'pcnet,netdev=vnet') - self.vm.launch() - - self.log.info('VM launched, waiting for sshd') - console_pattern = 'Starting OpenBSD Secure Shell server: sshd' - wait_for_console_pattern(self, console_pattern, 'Oops') - self.log.info('sshd ready') - - self.ssh_connect('root', 'root', False) - - def shutdown_via_ssh(self): - self.ssh_command('poweroff') - self.ssh_disconnect_vm() - wait_for_console_pattern(self, 'Power down', 'Oops') - - def ssh_command_output_contains(self, cmd, exp): - stdout, _ = self.ssh_command(cmd) - for line in stdout: - if exp in line: - break - else: - self.fail('"%s" output does not contain "%s"' % (cmd, exp)) - - def run_common_commands(self, wordsize): - self.ssh_command_output_contains( - 'cat /proc/cpuinfo', - self.CPU_INFO[wordsize]['cpu']) - self.ssh_command_output_contains( - 'uname -m', - 'mips') - self.ssh_command_output_contains( - 'uname -r', - self.CPU_INFO[wordsize]['kernel_release']) - self.ssh_command_output_contains( - 'cat /proc/interrupts', - 'XT-PIC timer') - self.ssh_command_output_contains( - 'cat /proc/interrupts', - 'XT-PIC i8042') - self.ssh_command_output_contains( - 'cat /proc/interrupts', - 'XT-PIC serial') - self.ssh_command_output_contains( - 'cat /proc/interrupts', - 'XT-PIC ata_piix') - self.ssh_command_output_contains( - 'cat /proc/interrupts', - 'XT-PIC eth0') - self.ssh_command_output_contains( - 'cat /proc/devices', - 'input') - self.ssh_command_output_contains( - 'cat /proc/devices', - 'usb') - self.ssh_command_output_contains( - 'cat /proc/devices', - 'fb') - self.ssh_command_output_contains( - 'cat /proc/ioports', - ' : serial') - self.ssh_command_output_contains( - 'cat /proc/ioports', - ' : ata_piix') - self.ssh_command_output_contains( - 'cat /proc/ioports', - ' : piix4_smbus') - self.ssh_command_output_contains( - 'lspci -d 11ab:4620', - 'GT-64120') - self.ssh_command_output_contains( - 'cat /sys/bus/i2c/devices/i2c-0/name', - 'SMBus PIIX4 adapter') - self.ssh_command_output_contains( - 'cat /proc/mtd', - 'YAMON') - # Empty 'Board Config' (64KB) - self.ssh_command_output_contains( - 'md5sum /dev/mtd2ro', - '0dfbe8aa4c20b52e1b8bf3cb6cbdf193') - - def check_mips_malta(self, uname_m, endianess): - wordsize = 64 if '64' in uname_m else 32 - kernel_url, kernel_hash = self.get_kernel_info(endianess, wordsize) - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - self.boot_debian_wheezy_image_and_ssh_login(endianess, kernel_path) - - stdout, _ = self.ssh_command('uname -a') - self.assertIn(True, [uname_m + " GNU/Linux" in line for line in stdout]) - - self.run_common_commands(wordsize) - self.shutdown_via_ssh() - # Wait for VM to shut down gracefully - self.vm.wait() - - def test_mips_malta32eb_kernel3_2_0(self): - """ - :avocado: tags=arch:mips - :avocado: tags=endian:big - :avocado: tags=device:pcnet32 - """ - self.check_mips_malta('mips', 'be') - - def test_mips_malta32el_kernel3_2_0(self): - """ - :avocado: tags=arch:mipsel - :avocado: tags=endian:little - :avocado: tags=device:pcnet32 - """ - self.check_mips_malta('mips', 'le') - - def test_mips_malta64eb_kernel3_2_0(self): - """ - :avocado: tags=arch:mips64 - :avocado: tags=endian:big - :avocado: tags=device:pcnet32 - """ - self.check_mips_malta('mips64', 'be') - - def test_mips_malta64el_kernel3_2_0(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=endian:little - :avocado: tags=device:pcnet32 - """ - self.check_mips_malta('mips64', 'le') diff --git a/tests/acceptance/machine_arm_canona1100.py b/tests/acceptance/machine_arm_canona1100.py deleted file mode 100644 index 0e5c43dbcf..0000000000 --- a/tests/acceptance/machine_arm_canona1100.py +++ /dev/null @@ -1,35 +0,0 @@ -# Functional test that boots the canon-a1100 machine with firmware -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Thomas Huth -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive - -class CanonA1100Machine(Test): - """Boots the barebox firmware and checks that the console is operational""" - - timeout = 90 - - def test_arm_canona1100(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:canon-a1100 - :avocado: tags=device:pflash_cfi02 - """ - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day18.tar.xz') - tar_hash = '068b5fc4242b29381acee94713509f8a876e9db6' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console() - self.vm.add_args('-bios', - self.workdir + '/day18/barebox.canon-a1100.bin') - self.vm.launch() - wait_for_console_pattern(self, 'running /env/bin/init') diff --git a/tests/acceptance/machine_arm_integratorcp.py b/tests/acceptance/machine_arm_integratorcp.py deleted file mode 100644 index 49c8ebff78..0000000000 --- a/tests/acceptance/machine_arm_integratorcp.py +++ /dev/null @@ -1,99 +0,0 @@ -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Thomas Huth -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import logging - -from avocado import skipUnless -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern - - -NUMPY_AVAILABLE = True -try: - import numpy as np -except ImportError: - NUMPY_AVAILABLE = False - -CV2_AVAILABLE = True -try: - import cv2 -except ImportError: - CV2_AVAILABLE = False - - -class IntegratorMachine(Test): - - timeout = 90 - - def boot_integratorcp(self): - kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/' - 'arm-test/kernel/zImage.integrator') - kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - initrd_url = ('https://github.com/zayac/qemu-arm/raw/master/' - 'arm-test/kernel/arm_root.img') - initrd_hash = 'b51e4154285bf784e017a37586428332d8c7bd8b' - initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-append', 'printk.time=0 console=ttyAMA0') - self.vm.launch() - - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_integratorcp_console(self): - """ - Boots the Linux kernel and checks that the console is operational - :avocado: tags=arch:arm - :avocado: tags=machine:integratorcp - :avocado: tags=device:pl011 - """ - self.boot_integratorcp() - wait_for_console_pattern(self, 'Log in as root') - - @skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed') - @skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed') - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_framebuffer_tux_logo(self): - """ - Boot Linux and verify the Tux logo is displayed on the framebuffer. - :avocado: tags=arch:arm - :avocado: tags=machine:integratorcp - :avocado: tags=device:pl110 - :avocado: tags=device:framebuffer - """ - screendump_path = os.path.join(self.workdir, "screendump.pbm") - tuxlogo_url = ('https://github.com/torvalds/linux/raw/v2.6.12/' - 'drivers/video/logo/logo_linux_vga16.ppm') - tuxlogo_hash = '3991c2ddbd1ddaecda7601f8aafbcf5b02dc86af' - tuxlogo_path = self.fetch_asset(tuxlogo_url, asset_hash=tuxlogo_hash) - - self.boot_integratorcp() - framebuffer_ready = 'Console: switching to colour frame buffer device' - wait_for_console_pattern(self, framebuffer_ready) - self.vm.command('human-monitor-command', command_line='stop') - self.vm.command('human-monitor-command', - command_line='screendump %s' % screendump_path) - logger = logging.getLogger('framebuffer') - - cpu_count = 1 - match_threshold = 0.92 - screendump_bgr = cv2.imread(screendump_path) - screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY) - result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 0), - cv2.TM_CCOEFF_NORMED) - loc = np.where(result >= match_threshold) - tux_count = 0 - for tux_count, pt in enumerate(zip(*loc[::-1]), start=1): - logger.debug('found Tux at position [x, y] = %s', pt) - self.assertGreaterEqual(tux_count, cpu_count) diff --git a/tests/acceptance/machine_arm_n8x0.py b/tests/acceptance/machine_arm_n8x0.py deleted file mode 100644 index e5741f2d8d..0000000000 --- a/tests/acceptance/machine_arm_n8x0.py +++ /dev/null @@ -1,49 +0,0 @@ -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Thomas Huth -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os - -from avocado import skipUnless -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern - -class N8x0Machine(Test): - """Boots the Linux kernel and checks that the console is operational""" - - timeout = 90 - - def __do_test_n8x0(self): - kernel_url = ('http://stskeeps.subnetmask.net/meego-n8x0/' - 'meego-arm-n8x0-1.0.80.20100712.1431-' - 'vmlinuz-2.6.35~rc4-129.1-n8x0') - kernel_hash = 'e9d5ab8d7548923a0061b6fbf601465e479ed269' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console(console_index=1) - self.vm.add_args('-kernel', kernel_path, - '-append', 'printk.time=0 console=ttyS1') - self.vm.launch() - wait_for_console_pattern(self, 'TSC2005 driver initializing') - - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_n800(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:n800 - """ - self.__do_test_n8x0() - - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_n810(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:n810 - """ - self.__do_test_n8x0() diff --git a/tests/acceptance/machine_avr6.py b/tests/acceptance/machine_avr6.py deleted file mode 100644 index 6baf4e9c7f..0000000000 --- a/tests/acceptance/machine_avr6.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# QEMU AVR acceptance tests -# -# Copyright (c) 2019-2020 Michael Rolnik -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -import time - -from avocado_qemu import Test - -class AVR6Machine(Test): - timeout = 5 - - def test_freertos(self): - """ - :avocado: tags=arch:avr - :avocado: tags=machine:arduino-mega-2560-v3 - """ - """ - https://github.com/seharris/qemu-avr-tests/raw/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf - constantly prints out 'ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX' - """ - rom_url = ('https://github.com/seharris/qemu-avr-tests' - '/raw/36c3e67b8755dcf/free-rtos/Demo' - '/AVR_ATMega2560_GCC/demo.elf') - rom_hash = '7eb521f511ca8f2622e0a3c5e8dd686efbb911d4' - rom_path = self.fetch_asset(rom_url, asset_hash=rom_hash) - - self.vm.add_args('-bios', rom_path) - self.vm.add_args('-nographic') - self.vm.launch() - - time.sleep(2) - self.vm.shutdown() - - self.assertIn('ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX', - self.vm.get_log()) diff --git a/tests/acceptance/machine_m68k_nextcube.py b/tests/acceptance/machine_m68k_nextcube.py deleted file mode 100644 index 09e2745cc5..0000000000 --- a/tests/acceptance/machine_m68k_nextcube.py +++ /dev/null @@ -1,79 +0,0 @@ -# Functional test that boots a VM and run OCR on the framebuffer -# -# Copyright (c) 2019 Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import time - -from avocado_qemu import Test -from avocado import skipUnless - -from tesseract_utils import tesseract_available, tesseract_ocr - -PIL_AVAILABLE = True -try: - from PIL import Image -except ImportError: - PIL_AVAILABLE = False - - -class NextCubeMachine(Test): - """ - :avocado: tags=arch:m68k - :avocado: tags=machine:next-cube - :avocado: tags=device:framebuffer - """ - - timeout = 15 - - def check_bootrom_framebuffer(self, screenshot_path): - rom_url = ('http://www.nextcomputers.org/NeXTfiles/Software/ROM_Files/' - '68040_Non-Turbo_Chipset/Rev_2.5_v66.BIN') - rom_hash = 'b3534796abae238a0111299fc406a9349f7fee24' - rom_path = self.fetch_asset(rom_url, asset_hash=rom_hash) - - self.vm.add_args('-bios', rom_path) - self.vm.launch() - - self.log.info('VM launched, waiting for display') - # TODO: Use avocado.utils.wait.wait_for to catch the - # 'displaysurface_create 1120x832' trace-event. - time.sleep(2) - - self.vm.command('human-monitor-command', - command_line='screendump %s' % screenshot_path) - - @skipUnless(PIL_AVAILABLE, 'Python PIL not installed') - def test_bootrom_framebuffer_size(self): - screenshot_path = os.path.join(self.workdir, "dump.ppm") - self.check_bootrom_framebuffer(screenshot_path) - - width, height = Image.open(screenshot_path).size - self.assertEqual(width, 1120) - self.assertEqual(height, 832) - - @skipUnless(tesseract_available(3), 'tesseract v3 OCR tool not available') - def test_bootrom_framebuffer_ocr_with_tesseract_v3(self): - screenshot_path = os.path.join(self.workdir, "dump.ppm") - self.check_bootrom_framebuffer(screenshot_path) - lines = tesseract_ocr(screenshot_path, tesseract_version=3) - text = '\n'.join(lines) - self.assertIn('Backplane', text) - self.assertIn('Ethernet address', text) - - # Tesseract 4 adds a new OCR engine based on LSTM neural networks. The - # new version is faster and more accurate than version 3. The drawback is - # that it is still alpha-level software. - @skipUnless(tesseract_available(4), 'tesseract v4 OCR tool not available') - def test_bootrom_framebuffer_ocr_with_tesseract_v4(self): - screenshot_path = os.path.join(self.workdir, "dump.ppm") - self.check_bootrom_framebuffer(screenshot_path) - lines = tesseract_ocr(screenshot_path, tesseract_version=4) - text = '\n'.join(lines) - self.assertIn('Testing the FPU, SCC', text) - self.assertIn('System test failed. Error code', text) - self.assertIn('Boot command', text) - self.assertIn('Next>', text) diff --git a/tests/acceptance/machine_microblaze.py b/tests/acceptance/machine_microblaze.py deleted file mode 100644 index 7f6d18495d..0000000000 --- a/tests/acceptance/machine_microblaze.py +++ /dev/null @@ -1,35 +0,0 @@ -# Functional test that boots a microblaze Linux kernel and checks the console -# -# Copyright (c) 2018, 2021 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive - -class MicroblazeMachine(Test): - - timeout = 90 - - def test_microblaze_s3adsp1800(self): - """ - :avocado: tags=arch:microblaze - :avocado: tags=machine:petalogix-s3adsp1800 - """ - - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day17.tar.xz') - tar_hash = '08bf3e3bfb6b6c7ce1e54ab65d54e189f2caf13f' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console() - self.vm.add_args('-kernel', self.workdir + '/day17/ballerina.bin') - self.vm.launch() - wait_for_console_pattern(self, 'This architecture does not have ' - 'kernel memory protection') - # Note: - # The kernel sometimes gets stuck after the "This architecture ..." - # message, that's why we don't test for a later string here. This - # needs some investigation by a microblaze wizard one day... diff --git a/tests/acceptance/machine_mips_fuloong2e.py b/tests/acceptance/machine_mips_fuloong2e.py deleted file mode 100644 index 0ac285e2af..0000000000 --- a/tests/acceptance/machine_mips_fuloong2e.py +++ /dev/null @@ -1,42 +0,0 @@ -# Functional tests for the Lemote Fuloong-2E machine. -# -# Copyright (c) 2019 Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. -# See the COPYING file in the top-level directory. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from avocado import skipUnless -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern - -class MipsFuloong2e(Test): - - timeout = 60 - - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - @skipUnless(os.getenv('RESCUE_YL_PATH'), 'RESCUE_YL_PATH not available') - def test_linux_kernel_isa_serial(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=machine:fuloong2e - :avocado: tags=endian:little - :avocado: tags=device:bonito64 - :avocado: tags=device:via686b - """ - # Recovery system for the Yeeloong laptop - # (enough to test the fuloong2e southbridge, accessing its ISA bus) - # http://dev.lemote.com/files/resource/download/rescue/rescue-yl - kernel_hash = 'ec4d1bd89a8439c41033ca63db60160cc6d6f09a' - kernel_path = self.fetch_asset('file://' + os.getenv('RESCUE_YL_PATH'), - asset_hash=kernel_hash) - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path) - self.vm.launch() - wait_for_console_pattern(self, 'Linux version 2.6.27.7lemote') - cpu_revision = 'CPU revision is: 00006302 (ICT Loongson-2)' - wait_for_console_pattern(self, cpu_revision) diff --git a/tests/acceptance/machine_mips_loongson3v.py b/tests/acceptance/machine_mips_loongson3v.py deleted file mode 100644 index 85b131a40f..0000000000 --- a/tests/acceptance/machine_mips_loongson3v.py +++ /dev/null @@ -1,39 +0,0 @@ -# Functional tests for the Generic Loongson-3 Platform. -# -# Copyright (c) 2021 Jiaxun Yang -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. -# See the COPYING file in the top-level directory. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import time - -from avocado import skipUnless -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern - -class MipsLoongson3v(Test): - timeout = 60 - - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_pmon_serial_console(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=endian:little - :avocado: tags=machine:loongson3-virt - :avocado: tags=cpu:Loongson-3A1000 - :avocado: tags=device:liointc - :avocado: tags=device:goldfish_rtc - """ - - pmon_hash = '7c8b45dd81ccfc55ff28f5aa267a41c3' - pmon_path = self.fetch_asset('https://github.com/loongson-community/pmon/' - 'releases/download/20210112/pmon-3avirt.bin', - asset_hash=pmon_hash, algorithm='md5') - - self.vm.set_console() - self.vm.add_args('-bios', pmon_path) - self.vm.launch() - wait_for_console_pattern(self, 'CPU GODSON3 BogoMIPS:') diff --git a/tests/acceptance/machine_mips_malta.py b/tests/acceptance/machine_mips_malta.py deleted file mode 100644 index b67d8cb141..0000000000 --- a/tests/acceptance/machine_mips_malta.py +++ /dev/null @@ -1,120 +0,0 @@ -# Functional tests for the MIPS Malta board -# -# Copyright (c) Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. -# See the COPYING file in the top-level directory. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import gzip -import logging - -from avocado import skipUnless -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive -from avocado import skipIf - - -NUMPY_AVAILABLE = True -try: - import numpy as np -except ImportError: - NUMPY_AVAILABLE = False - -CV2_AVAILABLE = True -try: - import cv2 -except ImportError: - CV2_AVAILABLE = False - - -@skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed') -@skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed') -class MaltaMachineFramebuffer(Test): - - timeout = 30 - - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - def do_test_i6400_framebuffer_logo(self, cpu_cores_count): - """ - Boot Linux kernel and check Tux logo is displayed on the framebuffer. - """ - screendump_path = os.path.join(self.workdir, 'screendump.pbm') - - kernel_url = ('https://github.com/philmd/qemu-testing-blob/raw/' - 'a5966ca4b5/mips/malta/mips64el/' - 'vmlinux-4.7.0-rc1.I6400.gz') - kernel_hash = '096f50c377ec5072e6a366943324622c312045f6' - kernel_path_gz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - kernel_path = self.workdir + "vmlinux" - archive.gzip_uncompress(kernel_path_gz, kernel_path) - - tuxlogo_url = ('https://github.com/torvalds/linux/raw/v2.6.12/' - 'drivers/video/logo/logo_linux_vga16.ppm') - tuxlogo_hash = '3991c2ddbd1ddaecda7601f8aafbcf5b02dc86af' - tuxlogo_path = self.fetch_asset(tuxlogo_url, asset_hash=tuxlogo_hash) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'clocksource=GIC console=tty0 console=ttyS0') - self.vm.add_args('-kernel', kernel_path, - '-smp', '%u' % cpu_cores_count, - '-vga', 'std', - '-append', kernel_command_line) - self.vm.launch() - framebuffer_ready = 'Console: switching to colour frame buffer device' - wait_for_console_pattern(self, framebuffer_ready, - failure_message='Kernel panic - not syncing') - self.vm.command('human-monitor-command', command_line='stop') - self.vm.command('human-monitor-command', - command_line='screendump %s' % screendump_path) - logger = logging.getLogger('framebuffer') - - match_threshold = 0.95 - screendump_bgr = cv2.imread(screendump_path, cv2.IMREAD_COLOR) - tuxlogo_bgr = cv2.imread(tuxlogo_path, cv2.IMREAD_COLOR) - result = cv2.matchTemplate(screendump_bgr, tuxlogo_bgr, - cv2.TM_CCOEFF_NORMED) - loc = np.where(result >= match_threshold) - tuxlogo_count = 0 - h, w = tuxlogo_bgr.shape[:2] - debug_png = os.getenv('AVOCADO_CV2_SCREENDUMP_PNG_PATH') - for tuxlogo_count, pt in enumerate(zip(*loc[::-1]), start=1): - logger.debug('found Tux at position (x, y) = %s', pt) - cv2.rectangle(screendump_bgr, pt, - (pt[0] + w, pt[1] + h), (0, 0, 255), 2) - if debug_png: - cv2.imwrite(debug_png, screendump_bgr) - self.assertGreaterEqual(tuxlogo_count, cpu_cores_count) - - def test_mips_malta_i6400_framebuffer_logo_1core(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=machine:malta - :avocado: tags=cpu:I6400 - """ - self.do_test_i6400_framebuffer_logo(1) - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_mips_malta_i6400_framebuffer_logo_7cores(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=machine:malta - :avocado: tags=cpu:I6400 - :avocado: tags=mips:smp - """ - self.do_test_i6400_framebuffer_logo(7) - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_mips_malta_i6400_framebuffer_logo_8cores(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=machine:malta - :avocado: tags=cpu:I6400 - :avocado: tags=mips:smp - """ - self.do_test_i6400_framebuffer_logo(8) diff --git a/tests/acceptance/machine_rx_gdbsim.py b/tests/acceptance/machine_rx_gdbsim.py deleted file mode 100644 index 32b737b6d8..0000000000 --- a/tests/acceptance/machine_rx_gdbsim.py +++ /dev/null @@ -1,73 +0,0 @@ -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os - -from avocado import skipIf -from avocado_qemu import Test -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive - - -class RxGdbSimMachine(Test): - - timeout = 30 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_uboot(self): - """ - U-Boot and checks that the console is operational. - - :avocado: tags=arch:rx - :avocado: tags=machine:gdbsim-r5f562n8 - :avocado: tags=endian:little - """ - uboot_url = ('https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz') - uboot_hash = '9b78dbd43b40b2526848c0b1ce9de02c24f4dcdb' - uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) - uboot_path = archive.uncompress(uboot_path, self.workdir) - - self.vm.set_console() - self.vm.add_args('-bios', uboot_path, - '-no-reboot') - self.vm.launch() - uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty' - wait_for_console_pattern(self, uboot_version) - gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)' - # FIXME limit baudrate on chardev, else we type too fast - #exec_command_and_wait_for_pattern(self, 'version', gcc_version) - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_linux_sash(self): - """ - Boots a Linux kernel and checks that the console is operational. - - :avocado: tags=arch:rx - :avocado: tags=machine:gdbsim-r5f562n7 - :avocado: tags=endian:little - """ - dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb') - dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18' - dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash) - kernel_url = ('http://acc.dl.osdn.jp/users/23/23845/zImage') - kernel_hash = '39a81067f8d72faad90866ddfefa19165d68fc99' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon' - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-no-reboot') - self.vm.launch() - wait_for_console_pattern(self, 'Sash command shell (version 1.1.1)', - failure_message='Kernel panic - not syncing') - exec_command_and_wait_for_pattern(self, 'printenv', 'TERM=linux') diff --git a/tests/acceptance/machine_s390_ccw_virtio.py b/tests/acceptance/machine_s390_ccw_virtio.py deleted file mode 100644 index 4028c99afc..0000000000 --- a/tests/acceptance/machine_s390_ccw_virtio.py +++ /dev/null @@ -1,272 +0,0 @@ -# Functional test that boots an s390x Linux guest with ccw and PCI devices -# attached and checks whether the devices are recognized by Linux -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Cornelia Huck -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import tempfile - -from avocado import skipIf -from avocado_qemu import Test -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive - -class S390CCWVirtioMachine(Test): - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - timeout = 120 - - def wait_for_console_pattern(self, success_message, vm=None): - wait_for_console_pattern(self, success_message, - failure_message='Kernel panic - not syncing', - vm=vm) - - def wait_for_crw_reports(self): - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg -c | grep CRW) ; do sleep 1 ; done', - 'CRW reports') - - dmesg_clear_count = 1 - def clear_guest_dmesg(self): - exec_command_and_wait_for_pattern(self, 'dmesg -c > /dev/null; ' - 'echo dm_clear\ ' + str(self.dmesg_clear_count), - 'dm_clear ' + str(self.dmesg_clear_count)) - self.dmesg_clear_count += 1 - - def test_s390x_devices(self): - - """ - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio - """ - - kernel_url = ('https://snapshot.debian.org/archive/debian/' - '20201126T092837Z/dists/buster/main/installer-s390x/' - '20190702+deb10u6/images/generic/kernel.debian') - kernel_hash = '5821fbee57d6220a067a8b967d24595621aa1eb6' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - initrd_url = ('https://snapshot.debian.org/archive/debian/' - '20201126T092837Z/dists/buster/main/installer-s390x/' - '20190702+deb10u6/images/generic/initrd.debian') - initrd_hash = '81ba09c97bef46e8f4660ac25b4ac0a5be3a94d6' - initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=sclp0 root=/dev/ram0 BOOT_DEBUG=3') - self.vm.add_args('-nographic', - '-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-device', 'virtio-net-ccw,devno=fe.1.1111', - '-device', - 'virtio-rng-ccw,devno=fe.2.0000,max_revision=0,id=rn1', - '-device', - 'virtio-rng-ccw,devno=fe.3.1234,max_revision=2,id=rn2', - '-device', 'zpci,uid=5,target=zzz', - '-device', 'virtio-net-pci,id=zzz', - '-device', 'zpci,uid=0xa,fid=12,target=serial', - '-device', 'virtio-serial-pci,id=serial', - '-device', 'virtio-balloon-ccw') - self.vm.launch() - - shell_ready = "sh: can't access tty; job control turned off" - self.wait_for_console_pattern(shell_ready) - # first debug shell is too early, we need to wait for device detection - exec_command_and_wait_for_pattern(self, 'exit', shell_ready) - - ccw_bus_ids="0.1.1111 0.2.0000 0.3.1234" - pci_bus_ids="0005:00:00.0 000a:00:00.0" - exec_command_and_wait_for_pattern(self, 'ls /sys/bus/ccw/devices/', - ccw_bus_ids) - exec_command_and_wait_for_pattern(self, 'ls /sys/bus/pci/devices/', - pci_bus_ids) - # check that the device at 0.2.0000 is in legacy mode, while the - # device at 0.3.1234 has the virtio-1 feature bit set - virtio_rng_features="00000000000000000000000000001100" + \ - "10000000000000000000000000000000" - virtio_rng_features_legacy="00000000000000000000000000001100" + \ - "00000000000000000000000000000000" - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/ccw/devices/0.2.0000/virtio?/features', - virtio_rng_features_legacy) - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/ccw/devices/0.3.1234/virtio?/features', - virtio_rng_features) - # check that /dev/hwrng works - and that it's gone after ejecting - exec_command_and_wait_for_pattern(self, - 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', - '10+0 records out') - self.clear_guest_dmesg() - self.vm.command('device_del', id='rn1') - self.wait_for_crw_reports() - self.clear_guest_dmesg() - self.vm.command('device_del', id='rn2') - self.wait_for_crw_reports() - exec_command_and_wait_for_pattern(self, - 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', - 'dd: /dev/hwrng: No such device') - # verify that we indeed have virtio-net devices (without having the - # virtio-net driver handy) - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/ccw/devices/0.1.1111/cutype', - '3832/01') - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_vendor', - '0x1af4') - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_device', - '0x0001') - # check fid propagation - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/pci/devices/000a\:00\:00.0/function_id', - '0x0000000c') - # add another device - self.clear_guest_dmesg() - self.vm.command('device_add', driver='virtio-net-ccw', - devno='fe.0.4711', id='net_4711') - self.wait_for_crw_reports() - exec_command_and_wait_for_pattern(self, 'for i in 1 2 3 4 5 6 7 ; do ' - 'if [ -e /sys/bus/ccw/devices/*4711 ]; then break; fi ;' - 'sleep 1 ; done ; ls /sys/bus/ccw/devices/', - '0.0.4711') - # and detach it again - self.clear_guest_dmesg() - self.vm.command('device_del', id='net_4711') - self.vm.event_wait(name='DEVICE_DELETED', - match={'data': {'device': 'net_4711'}}) - self.wait_for_crw_reports() - exec_command_and_wait_for_pattern(self, - 'ls /sys/bus/ccw/devices/0.0.4711', - 'No such file or directory') - # test the virtio-balloon device - exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', - 'MemTotal: 115640 kB') - self.vm.command('human-monitor-command', command_line='balloon 96') - exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', - 'MemTotal: 82872 kB') - self.vm.command('human-monitor-command', command_line='balloon 128') - exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', - 'MemTotal: 115640 kB') - - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_s390x_fedora(self): - - """ - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio - :avocado: tags=device:virtio-gpu - :avocado: tags=device:virtio-crypto - :avocado: tags=device:virtio-net - """ - - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/31/Server/s390x/os' - '/images/kernel.img') - kernel_hash = 'b93d1efcafcf29c1673a4ce371a1f8b43941cfeb' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - initrd_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/31/Server/s390x/os' - '/images/initrd.img') - initrd_hash = '3de45d411df5624b8d8ef21cd0b44419ab59b12f' - initrd_path_xz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - initrd_path = os.path.join(self.workdir, 'initrd-raw.img') - archive.lzma_uncompress(initrd_path_xz, initrd_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + ' audit=0 ' - 'rd.plymouth=0 plymouth.enable=0 rd.rescue') - self.vm.add_args('-nographic', - '-smp', '4', - '-m', '512', - '-name', 'Some Guest Name', - '-uuid', '30de4fd9-b4d5-409e-86a5-09b387f70bfa', - '-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-device', 'zpci,uid=7,target=n', - '-device', 'virtio-net-pci,id=n,mac=02:ca:fe:fa:ce:12', - '-device', 'virtio-rng-ccw,devno=fe.1.9876', - '-device', 'virtio-gpu-ccw,devno=fe.2.5432') - self.vm.launch() - self.wait_for_console_pattern('Entering emergency mode') - - # Some tests to see whether the CLI options have been considered: - self.log.info("Test whether QEMU CLI options have been considered") - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg | grep enP7p0s0) ; do sleep 1 ; done', - 'virtio_net virtio0 enP7p0s0: renamed') - exec_command_and_wait_for_pattern(self, 'lspci', - '0007:00:00.0 Class 0200: Device 1af4:1000') - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/net/enP7p0s0/address', - '02:ca:fe:fa:ce:12') - exec_command_and_wait_for_pattern(self, 'lscss', '0.1.9876') - exec_command_and_wait_for_pattern(self, 'lscss', '0.2.5432') - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'processors : 4') - exec_command_and_wait_for_pattern(self, 'grep MemTotal /proc/meminfo', - 'MemTotal: 499848 kB') - exec_command_and_wait_for_pattern(self, 'grep Name /proc/sysinfo', - 'Extended Name: Some Guest Name') - exec_command_and_wait_for_pattern(self, 'grep UUID /proc/sysinfo', - '30de4fd9-b4d5-409e-86a5-09b387f70bfa') - - # Disable blinking cursor, then write some stuff into the framebuffer. - # QEMU's PPM screendumps contain uncompressed 24-bit values, while the - # framebuffer uses 32-bit, so we pad our text with some spaces when - # writing to the framebuffer. Since the PPM is uncompressed, we then - # can simply read the written "magic bytes" back from the PPM file to - # check whether the framebuffer is working as expected. - self.log.info("Test screendump of virtio-gpu device") - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg | grep gpudrmfb) ; do sleep 1 ; done', - 'virtio_gpudrmfb frame buffer device') - exec_command_and_wait_for_pattern(self, - 'echo -e "\e[?25l" > /dev/tty0', ':/#') - exec_command_and_wait_for_pattern(self, 'for ((i=0;i<250;i++)); do ' - 'echo " The qu ick fo x j ump s o ver a laz y d og" >> fox.txt;' - 'done', - ':/#') - exec_command_and_wait_for_pattern(self, - 'dd if=fox.txt of=/dev/fb0 bs=1000 oflag=sync,nocache ; rm fox.txt', - '12+0 records out') - with tempfile.NamedTemporaryFile(suffix='.ppm', - prefix='qemu-scrdump-') as ppmfile: - self.vm.command('screendump', filename=ppmfile.name) - ppmfile.seek(0) - line = ppmfile.readline() - self.assertEqual(line, b"P6\n") - line = ppmfile.readline() - self.assertEqual(line, b"1024 768\n") - line = ppmfile.readline() - self.assertEqual(line, b"255\n") - line = ppmfile.readline(256) - self.assertEqual(line, b"The quick fox jumps over a lazy dog\n") - - # Hot-plug a virtio-crypto device and see whether it gets accepted - self.log.info("Test hot-plug virtio-crypto device") - self.clear_guest_dmesg() - self.vm.command('object-add', qom_type='cryptodev-backend-builtin', - id='cbe0') - self.vm.command('device_add', driver='virtio-crypto-ccw', id='crypdev0', - cryptodev='cbe0', devno='fe.0.2342') - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg -c | grep Accelerator.device) ; do' - ' sleep 1 ; done', 'Accelerator device is ready') - exec_command_and_wait_for_pattern(self, 'lscss', '0.0.2342') - self.vm.command('device_del', id='crypdev0') - self.vm.command('object-del', id='cbe0') - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg -c | grep Start.virtcrypto_remove) ; do' - ' sleep 1 ; done', 'Start virtcrypto_remove.') diff --git a/tests/acceptance/machine_sparc64_sun4u.py b/tests/acceptance/machine_sparc64_sun4u.py deleted file mode 100644 index 458165500e..0000000000 --- a/tests/acceptance/machine_sparc64_sun4u.py +++ /dev/null @@ -1,36 +0,0 @@ -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Thomas Huth -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os - -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive -from boot_linux_console import LinuxKernelTest - -class Sun4uMachine(LinuxKernelTest): - """Boots the Linux kernel and checks that the console is operational""" - - timeout = 90 - - def test_sparc64_sun4u(self): - """ - :avocado: tags=arch:sparc64 - :avocado: tags=machine:sun4u - """ - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day23.tar.xz') - tar_hash = '142db83cd974ffadc4f75c8a5cad5bcc5722c240' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console() - self.vm.add_args('-kernel', self.workdir + '/day23/vmlinux', - '-append', self.KERNEL_COMMON_COMMAND_LINE) - self.vm.launch() - wait_for_console_pattern(self, 'Starting logging: OK') diff --git a/tests/acceptance/machine_sparc_leon3.py b/tests/acceptance/machine_sparc_leon3.py deleted file mode 100644 index 2405cd7a0d..0000000000 --- a/tests/acceptance/machine_sparc_leon3.py +++ /dev/null @@ -1,37 +0,0 @@ -# Functional test that boots a Leon3 machine and checks its serial console. -# -# Copyright (c) Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern -from avocado import skip - - -class Leon3Machine(Test): - - timeout = 60 - - @skip("Test currently broken") - # A Window Underflow exception occurs before booting the kernel, - # and QEMU exit calling cpu_abort(), which makes this test to fail. - def test_leon3_helenos_uimage(self): - """ - :avocado: tags=arch:sparc - :avocado: tags=machine:leon3_generic - :avocado: tags=binfmt:uimage - """ - kernel_url = ('http://www.helenos.org/releases/' - 'HelenOS-0.6.0-sparc32-leon3.bin') - kernel_hash = 'a88c9cfdb8430c66650e5290a08765f9bf049a30' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path) - - self.vm.launch() - - wait_for_console_pattern(self, 'Copyright (c) 2001-2014 HelenOS project') - wait_for_console_pattern(self, 'Booting the kernel ...') diff --git a/tests/acceptance/migration.py b/tests/acceptance/migration.py deleted file mode 100644 index 792639cb69..0000000000 --- a/tests/acceptance/migration.py +++ /dev/null @@ -1,81 +0,0 @@ -# Migration test -# -# Copyright (c) 2019 Red Hat, Inc. -# -# Authors: -# Cleber Rosa -# Caio Carrara -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - - -import tempfile -from avocado_qemu import Test -from avocado import skipUnless - -from avocado.utils import network -from avocado.utils import wait -from avocado.utils.path import find_command - - -class Migration(Test): - """ - :avocado: tags=migration - """ - - timeout = 10 - - @staticmethod - def migration_finished(vm): - return vm.command('query-migrate')['status'] in ('completed', 'failed') - - def assert_migration(self, src_vm, dst_vm): - wait.wait_for(self.migration_finished, - timeout=self.timeout, - step=0.1, - args=(src_vm,)) - wait.wait_for(self.migration_finished, - timeout=self.timeout, - step=0.1, - args=(dst_vm,)) - self.assertEqual(src_vm.command('query-migrate')['status'], 'completed') - self.assertEqual(dst_vm.command('query-migrate')['status'], 'completed') - self.assertEqual(dst_vm.command('query-status')['status'], 'running') - self.assertEqual(src_vm.command('query-status')['status'],'postmigrate') - - def do_migrate(self, dest_uri, src_uri=None): - dest_vm = self.get_vm('-incoming', dest_uri) - dest_vm.add_args('-nodefaults') - dest_vm.launch() - if src_uri is None: - src_uri = dest_uri - source_vm = self.get_vm() - source_vm.add_args('-nodefaults') - source_vm.launch() - source_vm.qmp('migrate', uri=src_uri) - self.assert_migration(source_vm, dest_vm) - - def _get_free_port(self): - port = network.find_free_port() - if port is None: - self.cancel('Failed to find a free port') - return port - - - def test_migration_with_tcp_localhost(self): - dest_uri = 'tcp:localhost:%u' % self._get_free_port() - self.do_migrate(dest_uri) - - def test_migration_with_unix(self): - with tempfile.TemporaryDirectory(prefix='socket_') as socket_path: - dest_uri = 'unix:%s/qemu-test.sock' % socket_path - self.do_migrate(dest_uri) - - @skipUnless(find_command('nc', default=False), "'nc' command not found") - def test_migration_with_exec(self): - """The test works for both netcat-traditional and netcat-openbsd packages.""" - free_port = self._get_free_port() - dest_uri = 'exec:nc -l localhost %u' % free_port - src_uri = 'exec:nc localhost %u' % free_port - self.do_migrate(dest_uri, src_uri) diff --git a/tests/acceptance/multiprocess.py b/tests/acceptance/multiprocess.py deleted file mode 100644 index 96627f022a..0000000000 --- a/tests/acceptance/multiprocess.py +++ /dev/null @@ -1,95 +0,0 @@ -# Test for multiprocess qemu -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - - -import os -import socket - -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import exec_command -from avocado_qemu import exec_command_and_wait_for_pattern - -class Multiprocess(Test): - """ - :avocado: tags=multiprocess - """ - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - def do_test(self, kernel_url, initrd_url, kernel_command_line, - machine_type): - """Main test method""" - self.require_accelerator('kvm') - - # Create socketpair to connect proxy and remote processes - proxy_sock, remote_sock = socket.socketpair(socket.AF_UNIX, - socket.SOCK_STREAM) - os.set_inheritable(proxy_sock.fileno(), True) - os.set_inheritable(remote_sock.fileno(), True) - - kernel_path = self.fetch_asset(kernel_url) - initrd_path = self.fetch_asset(initrd_url) - - # Create remote process - remote_vm = self.get_vm() - remote_vm.add_args('-machine', 'x-remote') - remote_vm.add_args('-nodefaults') - remote_vm.add_args('-device', 'lsi53c895a,id=lsi1') - remote_vm.add_args('-object', 'x-remote-object,id=robj1,' - 'devid=lsi1,fd='+str(remote_sock.fileno())) - remote_vm.launch() - - # Create proxy process - self.vm.set_console() - self.vm.add_args('-machine', machine_type) - self.vm.add_args('-accel', 'kvm') - self.vm.add_args('-cpu', 'host') - self.vm.add_args('-object', - 'memory-backend-memfd,id=sysmem-file,size=2G') - self.vm.add_args('--numa', 'node,memdev=sysmem-file') - self.vm.add_args('-m', '2048') - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line) - self.vm.add_args('-device', - 'x-pci-proxy-dev,' - 'id=lsi1,fd='+str(proxy_sock.fileno())) - self.vm.launch() - wait_for_console_pattern(self, 'as init process', - 'Kernel panic - not syncing') - exec_command(self, 'mount -t sysfs sysfs /sys') - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/pci/devices/*/uevent', - 'PCI_ID=1000:0012') - - def test_multiprocess_x86_64(self): - """ - :avocado: tags=arch:x86_64 - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/31/Everything/x86_64/os/images' - '/pxeboot/vmlinuz') - initrd_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/31/Everything/x86_64/os/images' - '/pxeboot/initrd.img') - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 rdinit=/bin/bash') - machine_type = 'pc' - self.do_test(kernel_url, initrd_url, kernel_command_line, machine_type) - - def test_multiprocess_aarch64(self): - """ - :avocado: tags=arch:aarch64 - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/31/Everything/aarch64/os/images' - '/pxeboot/vmlinuz') - initrd_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/31/Everything/aarch64/os/images' - '/pxeboot/initrd.img') - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'rdinit=/bin/bash console=ttyAMA0') - machine_type = 'virt,gic-version=3' - self.do_test(kernel_url, initrd_url, kernel_command_line, machine_type) diff --git a/tests/acceptance/pc_cpu_hotplug_props.py b/tests/acceptance/pc_cpu_hotplug_props.py deleted file mode 100644 index 2e86d5017a..0000000000 --- a/tests/acceptance/pc_cpu_hotplug_props.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# Ensure CPU die-id can be omitted on -device -# -# Copyright (c) 2019 Red Hat Inc -# -# Author: -# Eduardo Habkost -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, see . -# - -from avocado_qemu import Test - -class OmittedCPUProps(Test): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=cpu:qemu64 - """ - def test_no_die_id(self): - self.vm.add_args('-nodefaults', '-S') - self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') - self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') - self.vm.launch() - self.assertEquals(len(self.vm.command('query-cpus-fast')), 2) diff --git a/tests/acceptance/ppc_405.py b/tests/acceptance/ppc_405.py deleted file mode 100644 index c534d5d32f..0000000000 --- a/tests/acceptance/ppc_405.py +++ /dev/null @@ -1,42 +0,0 @@ -# Test that the U-Boot firmware boots on ppc 405 machines and check the console -# -# Copyright (c) 2021 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado.utils import archive -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import exec_command_and_wait_for_pattern - -class Ppc405Machine(Test): - - timeout = 90 - - def do_test_ppc405(self): - uboot_url = ('https://gitlab.com/huth/u-boot/-/raw/' - 'taihu-2021-10-09/u-boot-taihu.bin') - uboot_hash = ('3208940e908a5edc7c03eab072c60f0dcfadc2ab'); - file_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) - self.vm.set_console(console_index=1) - self.vm.add_args('-bios', file_path) - self.vm.launch() - wait_for_console_pattern(self, 'AMCC PPC405EP Evaluation Board') - exec_command_and_wait_for_pattern(self, 'reset', 'AMCC PowerPC 405EP') - - def test_ppc_taihu(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:taihu - :avocado: tags=cpu:405ep - """ - self.do_test_ppc405() - - def test_ppc_ref405ep(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:ref405ep - :avocado: tags=cpu:405ep - """ - self.do_test_ppc405() diff --git a/tests/acceptance/ppc_bamboo.py b/tests/acceptance/ppc_bamboo.py deleted file mode 100644 index dd33bf66f3..0000000000 --- a/tests/acceptance/ppc_bamboo.py +++ /dev/null @@ -1,39 +0,0 @@ -# Test that Linux kernel boots on the ppc bamboo board and check the console -# -# Copyright (c) 2021 Red Hat -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado.utils import archive -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import exec_command_and_wait_for_pattern - -class BambooMachine(Test): - - timeout = 90 - - def test_ppc_bamboo(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:bamboo - :avocado: tags=cpu:440epb - :avocado: tags=device:rtl8139 - """ - tar_url = ('http://landley.net/aboriginal/downloads/binaries/' - 'system-image-powerpc-440fp.tar.gz') - tar_hash = '53e5f16414b195b82d2c70272f81c2eedb39bad9' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console() - self.vm.add_args('-kernel', self.workdir + - '/system-image-powerpc-440fp/linux', - '-initrd', self.workdir + - '/system-image-powerpc-440fp/rootfs.cpio.gz', - '-nic', 'user,model=rtl8139,restrict=on') - self.vm.launch() - wait_for_console_pattern(self, 'Type exit when done') - exec_command_and_wait_for_pattern(self, 'ping 10.0.2.2', - '10.0.2.2 is alive!') - exec_command_and_wait_for_pattern(self, 'halt', 'System Halted') diff --git a/tests/acceptance/ppc_mpc8544ds.py b/tests/acceptance/ppc_mpc8544ds.py deleted file mode 100644 index ce840600c1..0000000000 --- a/tests/acceptance/ppc_mpc8544ds.py +++ /dev/null @@ -1,32 +0,0 @@ -# Test that Linux kernel boots on ppc machines and check the console -# -# Copyright (c) 2018, 2020 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado.utils import archive -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern - -class Mpc8544dsMachine(Test): - - timeout = 90 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - panic_message = 'Kernel panic - not syncing' - - def test_ppc_mpc8544ds(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:mpc8544ds - """ - tar_url = ('https://www.qemu-advent-calendar.org' - '/2020/download/day17.tar.gz') - tar_hash = '7a5239542a7c4257aa4d3b7f6ddf08fb6775c494' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console() - self.vm.add_args('-kernel', self.workdir + '/creek/creek.bin') - self.vm.launch() - wait_for_console_pattern(self, 'QEMU advent calendar 2020', - self.panic_message) diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py deleted file mode 100644 index 5e61e686bd..0000000000 --- a/tests/acceptance/ppc_prep_40p.py +++ /dev/null @@ -1,79 +0,0 @@ -# Functional test that boots a PReP/40p machine and checks its serial console. -# -# Copyright (c) Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os - -from avocado import skipUnless -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern - - -class IbmPrep40pMachine(Test): - - timeout = 60 - - # 12H0455 PPS Firmware Licensed Materials - # Property of IBM (C) Copyright IBM Corp. 1994. - # All rights reserved. - # U.S. Government Users Restricted Rights - Use, duplication or disclosure - # restricted by GSA ADP Schedule Contract with IBM Corp. - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_factory_firmware_and_netbsd(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:40p - :avocado: tags=os:netbsd - :avocado: tags=slowness:high - """ - bios_url = ('http://ftpmirror.your.org/pub/misc/' - 'ftp.software.ibm.com/rs6000/firmware/' - '7020-40p/P12H0456.IMG') - bios_hash = '1775face4e6dc27f3a6ed955ef6eb331bf817f03' - bios_path = self.fetch_asset(bios_url, asset_hash=bios_hash) - drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/' - 'NetBSD-4.0/prep/installation/floppy/generic_com0.fs') - drive_hash = 'dbcfc09912e71bd5f0d82c7c1ee43082fb596ceb' - drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash) - - self.vm.set_console() - self.vm.add_args('-bios', bios_path, - '-fda', drive_path) - self.vm.launch() - os_banner = 'NetBSD 4.0 (GENERIC) #0: Sun Dec 16 00:49:40 PST 2007' - wait_for_console_pattern(self, os_banner) - wait_for_console_pattern(self, 'Model: IBM PPS Model 6015') - - def test_openbios_192m(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:40p - """ - self.vm.set_console() - self.vm.add_args('-m', '192') # test fw_cfg - - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> Memory: 192M') - wait_for_console_pattern(self, '>> CPU type PowerPC,604') - - def test_openbios_and_netbsd(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:40p - :avocado: tags=os:netbsd - """ - drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/' - 'NetBSD-7.1.2/iso/NetBSD-7.1.2-prep.iso') - drive_hash = 'ac6fa2707d888b36d6fa64de6e7fe48e' - drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash, - algorithm='md5') - self.vm.set_console() - self.vm.add_args('-cdrom', drive_path, - '-boot', 'd') - - self.vm.launch() - wait_for_console_pattern(self, 'NetBSD/prep BOOT, Revision 1.9') diff --git a/tests/acceptance/ppc_pseries.py b/tests/acceptance/ppc_pseries.py deleted file mode 100644 index f14a884ee1..0000000000 --- a/tests/acceptance/ppc_pseries.py +++ /dev/null @@ -1,35 +0,0 @@ -# Test that Linux kernel boots on ppc machines and check the console -# -# Copyright (c) 2018, 2020 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado.utils import archive -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern - -class pseriesMachine(Test): - - timeout = 90 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - panic_message = 'Kernel panic - not syncing' - - def test_ppc64_pseries(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/29/Everything/ppc64le/os' - '/ppc/ppc64/vmlinuz') - kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - wait_for_console_pattern(self, console_pattern, self.panic_message) diff --git a/tests/acceptance/ppc_virtex_ml507.py b/tests/acceptance/ppc_virtex_ml507.py deleted file mode 100644 index 27f7bf2d49..0000000000 --- a/tests/acceptance/ppc_virtex_ml507.py +++ /dev/null @@ -1,34 +0,0 @@ -# Test that Linux kernel boots on ppc machines and check the console -# -# Copyright (c) 2018, 2020 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado.utils import archive -from avocado_qemu import Test -from avocado_qemu import wait_for_console_pattern - -class VirtexMl507Machine(Test): - - timeout = 90 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - panic_message = 'Kernel panic - not syncing' - - def test_ppc_virtex_ml507(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:virtex-ml507 - """ - tar_url = ('https://www.qemu-advent-calendar.org' - '/2020/download/hippo.tar.gz') - tar_hash = '306b95bfe7d147f125aa176a877e266db8ef914a' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console() - self.vm.add_args('-kernel', self.workdir + '/hippo/hippo.linux', - '-dtb', self.workdir + '/hippo/virtex440-ml507.dtb', - '-m', '512') - self.vm.launch() - wait_for_console_pattern(self, 'QEMU advent calendar 2020', - self.panic_message) diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py deleted file mode 100644 index c68a953730..0000000000 --- a/tests/acceptance/replay_kernel.py +++ /dev/null @@ -1,524 +0,0 @@ -# Record/replay test that boots a Linux kernel -# -# Copyright (c) 2020 ISP RAS -# -# Author: -# Pavel Dovgalyuk -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import lzma -import shutil -import logging -import time - -from avocado import skip -from avocado import skipIf -from avocado import skipUnless -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive -from avocado.utils import process -from boot_linux_console import LinuxKernelTest - -class ReplayKernelBase(LinuxKernelTest): - """ - Boots a Linux kernel in record mode and checks that the console - is operational and the kernel command line is properly passed - from QEMU to the kernel. - Then replays the same scenario and verifies, that QEMU correctly - terminates. - """ - - timeout = 120 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' - - def run_vm(self, kernel_path, kernel_command_line, console_pattern, - record, shift, args, replay_path): - logger = logging.getLogger('replay') - start_time = time.time() - vm = self.get_vm() - vm.set_console() - if record: - logger.info('recording the execution...') - mode = 'record' - else: - logger.info('replaying the execution...') - mode = 'replay' - vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' % - (shift, mode, replay_path), - '-kernel', kernel_path, - '-append', kernel_command_line, - '-net', 'none', - '-no-reboot') - if args: - vm.add_args(*args) - vm.launch() - self.wait_for_console_pattern(console_pattern, vm) - if record: - vm.shutdown() - logger.info('finished the recording with log size %s bytes' - % os.path.getsize(replay_path)) - else: - vm.wait() - logger.info('successfully finished the replay') - elapsed = time.time() - start_time - logger.info('elapsed time %.2f sec' % elapsed) - return elapsed - - def run_rr(self, kernel_path, kernel_command_line, console_pattern, - shift=7, args=None): - replay_path = os.path.join(self.workdir, 'replay.bin') - t1 = self.run_vm(kernel_path, kernel_command_line, console_pattern, - True, shift, args, replay_path) - t2 = self.run_vm(kernel_path, kernel_command_line, console_pattern, - False, shift, args, replay_path) - logger = logging.getLogger('replay') - logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) - -class ReplayKernelNormal(ReplayKernelBase): - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_x86_64_pc(self): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=machine:pc - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/29/Everything/x86_64/os/images/pxeboot' - '/vmlinuz') - kernel_hash = '23bebd2680757891cf7adedb033532163a792495' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - console_pattern = 'VFS: Cannot open root device' - - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) - - def test_mips_malta(self): - """ - :avocado: tags=arch:mips - :avocado: tags=machine:malta - :avocado: tags=endian:big - """ - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20130217T032700Z/pool/main/l/linux-2.6/' - 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb') - deb_hash = 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-2.6.32-5-4kc-malta') - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - console_pattern = 'Kernel command line: %s' % kernel_command_line - - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) - - def test_mips64el_malta(self): - """ - This test requires the ar tool to extract "data.tar.gz" from - the Debian package. - - The kernel can be rebuilt using this Debian kernel source [1] and - following the instructions on [2]. - - [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/ - #linux-source-2.6.32_2.6.32-48 - [2] https://kernel-team.pages.debian.net/kernel-handbook/ - ch-common-tasks.html#s-common-official - - :avocado: tags=arch:mips64el - :avocado: tags=machine:malta - """ - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20130217T032700Z/pool/main/l/linux-2.6/' - 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb') - deb_hash = '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-2.6.32-5-5kc-malta') - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) - - def test_aarch64_virt(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a53 - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/29/Everything/aarch64/os/images/pxeboot' - '/vmlinuz') - kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - console_pattern = 'VFS: Cannot open root device' - - self.run_rr(kernel_path, kernel_command_line, console_pattern) - - def test_arm_virt(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:virt - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/29/Everything/armhfp/os/images/pxeboot' - '/vmlinuz') - kernel_hash = 'e9826d741b4fb04cadba8d4824d1ed3b7fb8b4d4' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - console_pattern = 'VFS: Cannot open root device' - - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1) - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_arm_cubieboard_initrd(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:cubieboard - """ - deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') - deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinuz-5.10.16-sunxi') - dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb' - dtb_path = self.extract_from_deb(deb_path, dtb_path) - initrd_url = ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv5.cpio.gz') - initrd_hash = '2b50f1873e113523967806f4da2afe385462ff9b' - initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - initrd_path = os.path.join(self.workdir, 'rootfs.cpio') - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'usbcore.nousb ' - 'panic=-1 noreboot') - console_pattern = 'Boot successful.' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1, - args=('-dtb', dtb_path, - '-initrd', initrd_path, - '-no-reboot')) - - def test_s390x_s390_ccw_virtio(self): - """ - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/29/Everything/s390x/os/images' - '/kernel.img') - kernel_hash = 'e8e8439103ef8053418ef062644ffd46a7919313' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=sclp0' - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=9) - - def test_alpha_clipper(self): - """ - :avocado: tags=arch:alpha - :avocado: tags=machine:clipper - """ - kernel_url = ('http://archive.debian.org/debian/dists/lenny/main/' - 'installer-alpha/20090123lenny10/images/cdrom/vmlinuz') - kernel_hash = '3a943149335529e2ed3e74d0d787b85fb5671ba3' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - uncompressed_kernel = archive.uncompress(kernel_path, self.workdir) - - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(uncompressed_kernel, kernel_command_line, console_pattern, shift=9, - args=('-nodefaults', )) - - def test_ppc64_pseries(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/29/Everything/ppc64le/os' - '/ppc/ppc64/vmlinuz') - kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' - # icount is not good enough for PPC64 for complete boot yet - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern) - - def test_m68k_q800(self): - """ - :avocado: tags=arch:m68k - :avocado: tags=machine:q800 - """ - deb_url = ('https://snapshot.debian.org/archive/debian-ports' - '/20191021T083923Z/pool-m68k/main' - '/l/linux/kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb') - deb_hash = '044954bb9be4160a3ce81f8bc1b5e856b75cccd1' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-5.3.0-1-m68k') - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 vga=off') - console_pattern = 'No filesystem could mount root' - self.run_rr(kernel_path, kernel_command_line, console_pattern) - - def do_test_advcal_2018(self, file_path, kernel_name, args=None): - archive.extract(file_path, self.workdir) - - for entry in os.scandir(self.workdir): - if entry.name.startswith('day') and entry.is_dir(): - kernel_path = os.path.join(entry.path, kernel_name) - break - - kernel_command_line = '' - console_pattern = 'QEMU advent calendar' - self.run_rr(kernel_path, kernel_command_line, console_pattern, - args=args) - - def test_arm_vexpressa9(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:vexpress-a9 - """ - tar_hash = '32b7677ce8b6f1471fb0059865f451169934245b' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day16.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - dtb_path = self.workdir + '/day16/vexpress-v2p-ca9.dtb' - self.do_test_advcal_2018(file_path, 'winter.zImage', - args=('-dtb', dtb_path)) - - def test_m68k_mcf5208evb(self): - """ - :avocado: tags=arch:m68k - :avocado: tags=machine:mcf5208evb - """ - tar_hash = 'ac688fd00561a2b6ce1359f9ff6aa2b98c9a570c' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day07.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'sanity-clause.elf') - - @skip("Test currently broken") # Console stuck as of 5.2-rc1 - def test_microblaze_s3adsp1800(self): - """ - :avocado: tags=arch:microblaze - :avocado: tags=machine:petalogix-s3adsp1800 - """ - tar_hash = '08bf3e3bfb6b6c7ce1e54ab65d54e189f2caf13f' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day17.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'ballerina.bin') - - def test_ppc64_e500(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:ppce500 - :avocado: tags=cpu:e5500 - """ - tar_hash = '6951d86d644b302898da2fd701739c9406527fe1' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day19.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'uImage') - - def test_or1k_sim(self): - """ - :avocado: tags=arch:or1k - :avocado: tags=machine:or1k-sim - """ - tar_hash = '20334cdaf386108c530ff0badaecc955693027dd' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day20.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'vmlinux') - - def test_nios2_10m50(self): - """ - :avocado: tags=arch:nios2 - :avocado: tags=machine:10m50-ghrd - """ - tar_hash = 'e4251141726c412ac0407c5a6bceefbbff018918' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day14.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'vmlinux.elf') - - def test_ppc_g3beige(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:g3beige - """ - tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day15.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'invaders.elf', - args=('-M', 'graphics=off')) - - def test_ppc_mac99(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:mac99 - """ - tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day15.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'invaders.elf', - args=('-M', 'graphics=off')) - - def test_sparc_ss20(self): - """ - :avocado: tags=arch:sparc - :avocado: tags=machine:SS-20 - """ - tar_hash = 'b18550d5d61c7615d989a06edace051017726a9f' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day11.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'zImage.elf') - - def test_xtensa_lx60(self): - """ - :avocado: tags=arch:xtensa - :avocado: tags=machine:lx60 - :avocado: tags=cpu:dc233c - """ - tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34' - tar_url = ('https://www.qemu-advent-calendar.org' - '/2018/download/day02.tar.xz') - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - self.do_test_advcal_2018(file_path, 'santas-sleigh-ride.elf') - -@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') -class ReplayKernelSlow(ReplayKernelBase): - # Override the timeout, because this kernel includes an inner - # loop which is executed with TB recompilings during replay, - # making it very slow. - timeout = 180 - - def test_mips_malta_cpio(self): - """ - :avocado: tags=arch:mips - :avocado: tags=machine:malta - :avocado: tags=endian:big - :avocado: tags=slowness:high - """ - deb_url = ('http://snapshot.debian.org/archive/debian/' - '20160601T041800Z/pool/main/l/linux/' - 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb') - deb_hash = 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8' - deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) - kernel_path = self.extract_from_deb(deb_path, - '/boot/vmlinux-4.5.0-2-4kc-malta') - initrd_url = ('https://github.com/groeck/linux-build-test/raw/' - '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' - 'mips/rootfs.cpio.gz') - initrd_hash = 'bf806e17009360a866bf537f6de66590de349a99' - initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - initrd_path = self.workdir + "rootfs.cpio" - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 console=tty ' - 'rdinit=/sbin/init noreboot') - console_pattern = 'Boot successful.' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=('-initrd', initrd_path)) - - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_mips64el_malta_5KEc_cpio(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=machine:malta - :avocado: tags=endian:little - :avocado: tags=slowness:high - :avocado: tags=cpu:5KEc - """ - kernel_url = ('https://github.com/philmd/qemu-testing-blob/' - 'raw/9ad2df38/mips/malta/mips64el/' - 'vmlinux-3.19.3.mtoman.20150408') - kernel_hash = '00d1d268fb9f7d8beda1de6bebcc46e884d71754' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - initrd_url = ('https://github.com/groeck/linux-build-test/' - 'raw/8584a59e/rootfs/' - 'mipsel64/rootfs.mipsel64r1.cpio.gz') - initrd_hash = '1dbb8a396e916847325284dbe2151167' - initrd_path_gz = self.fetch_asset(initrd_url, algorithm='md5', - asset_hash=initrd_hash) - initrd_path = self.workdir + "rootfs.cpio" - archive.gzip_uncompress(initrd_path_gz, initrd_path) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 console=tty ' - 'rdinit=/sbin/init noreboot') - console_pattern = 'Boot successful.' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=('-initrd', initrd_path)) - - def do_test_mips_malta32el_nanomips(self, kernel_path_xz): - kernel_path = self.workdir + "kernel" - with lzma.open(kernel_path_xz, 'rb') as f_in: - with open(kernel_path, 'wb') as f_out: - shutil.copyfileobj(f_in, f_out) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'mem=256m@@0x0 ' - 'console=ttyS0') - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) - - def test_mips_malta32el_nanomips_4k(self): - """ - :avocado: tags=arch:mipsel - :avocado: tags=machine:malta - :avocado: tags=endian:little - :avocado: tags=cpu:I7200 - """ - kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page4k.xz') - kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6' - kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - self.do_test_mips_malta32el_nanomips(kernel_path_xz) - - def test_mips_malta32el_nanomips_16k_up(self): - """ - :avocado: tags=arch:mipsel - :avocado: tags=machine:malta - :avocado: tags=endian:little - :avocado: tags=cpu:I7200 - """ - kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page16k_up.xz') - kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc' - kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - self.do_test_mips_malta32el_nanomips(kernel_path_xz) - - def test_mips_malta32el_nanomips_64k_dbg(self): - """ - :avocado: tags=arch:mipsel - :avocado: tags=machine:malta - :avocado: tags=endian:little - :avocado: tags=cpu:I7200 - """ - kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page64k_dbg.xz') - kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180' - kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - self.do_test_mips_malta32el_nanomips(kernel_path_xz) diff --git a/tests/acceptance/replay_linux.py b/tests/acceptance/replay_linux.py deleted file mode 100644 index 15953f9e49..0000000000 --- a/tests/acceptance/replay_linux.py +++ /dev/null @@ -1,116 +0,0 @@ -# Record/replay test that boots a complete Linux system via a cloud image -# -# Copyright (c) 2020 ISP RAS -# -# Author: -# Pavel Dovgalyuk -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import logging -import time - -from avocado import skipUnless -from avocado.utils import cloudinit -from avocado.utils import network -from avocado.utils import vmimage -from avocado.utils import datadrainer -from avocado.utils.path import find_command -from avocado_qemu import LinuxTest - -class ReplayLinux(LinuxTest): - """ - Boots a Linux system, checking for a successful initialization - """ - - timeout = 1800 - chksum = None - hdd = 'ide-hd' - cd = 'ide-cd' - bus = 'ide' - - def setUp(self): - super(ReplayLinux, self).setUp() - self.boot_path = self.download_boot() - self.cloudinit_path = self.prepare_cloudinit() - - def vm_add_disk(self, vm, path, id, device): - bus_string = '' - if self.bus: - bus_string = ',bus=%s.%d' % (self.bus, id,) - vm.add_args('-drive', 'file=%s,snapshot,id=disk%s,if=none' % (path, id)) - vm.add_args('-drive', - 'driver=blkreplay,id=disk%s-rr,if=none,image=disk%s' % (id, id)) - vm.add_args('-device', - '%s,drive=disk%s-rr%s' % (device, id, bus_string)) - - def launch_and_wait(self, record, args, shift): - vm = self.get_vm() - vm.add_args('-smp', '1') - vm.add_args('-m', '1024') - vm.add_args('-object', 'filter-replay,id=replay,netdev=hub0port0') - if args: - vm.add_args(*args) - self.vm_add_disk(vm, self.boot_path, 0, self.hdd) - self.vm_add_disk(vm, self.cloudinit_path, 1, self.cd) - logger = logging.getLogger('replay') - if record: - logger.info('recording the execution...') - mode = 'record' - else: - logger.info('replaying the execution...') - mode = 'replay' - replay_path = os.path.join(self.workdir, 'replay.bin') - vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' % - (shift, mode, replay_path)) - - start_time = time.time() - - vm.set_console() - vm.launch() - console_drainer = datadrainer.LineLogger(vm.console_socket.fileno(), - logger=self.log.getChild('console'), - stop_check=(lambda : not vm.is_running())) - console_drainer.start() - if record: - cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), - self.name) - vm.shutdown() - logger.info('finished the recording with log size %s bytes' - % os.path.getsize(replay_path)) - else: - vm.event_wait('SHUTDOWN', self.timeout) - vm.shutdown(True) - logger.info('successfully fihished the replay') - elapsed = time.time() - start_time - logger.info('elapsed time %.2f sec' % elapsed) - return elapsed - - def run_rr(self, args=None, shift=7): - t1 = self.launch_and_wait(True, args, shift) - t2 = self.launch_and_wait(False, args, shift) - logger = logging.getLogger('replay') - logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) - -@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') -class ReplayLinuxX8664(ReplayLinux): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=accel:tcg - """ - - chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0' - - def test_pc_i440fx(self): - """ - :avocado: tags=machine:pc - """ - self.run_rr(shift=1) - - def test_pc_q35(self): - """ - :avocado: tags=machine:q35 - """ - self.run_rr(shift=3) diff --git a/tests/acceptance/reverse_debugging.py b/tests/acceptance/reverse_debugging.py deleted file mode 100644 index d2921e70c3..0000000000 --- a/tests/acceptance/reverse_debugging.py +++ /dev/null @@ -1,210 +0,0 @@ -# Reverse debugging test -# -# Copyright (c) 2020 ISP RAS -# -# Author: -# Pavel Dovgalyuk -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. -import os -import logging - -from avocado import skipIf -from avocado_qemu import BUILD_DIR -from avocado.utils import gdb -from avocado.utils import process -from avocado.utils.network.ports import find_free_port -from avocado.utils.path import find_command -from boot_linux_console import LinuxKernelTest - -class ReverseDebugging(LinuxKernelTest): - """ - Test GDB reverse debugging commands: reverse step and reverse continue. - Recording saves the execution of some instructions and makes an initial - VM snapshot to allow reverse execution. - Replay saves the order of the first instructions and then checks that they - are executed backwards in the correct order. - After that the execution is replayed to the end, and reverse continue - command is checked by setting several breakpoints, and asserting - that the execution is stopped at the last of them. - """ - - timeout = 10 - STEPS = 10 - endian_is_le = True - - def run_vm(self, record, shift, args, replay_path, image_path, port): - logger = logging.getLogger('replay') - vm = self.get_vm() - vm.set_console() - if record: - logger.info('recording the execution...') - mode = 'record' - else: - logger.info('replaying the execution...') - mode = 'replay' - vm.add_args('-gdb', 'tcp::%d' % port, '-S') - vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s,rrsnapshot=init' % - (shift, mode, replay_path), - '-net', 'none') - vm.add_args('-drive', 'file=%s,if=none' % image_path) - if args: - vm.add_args(*args) - vm.launch() - return vm - - @staticmethod - def get_reg_le(g, reg): - res = g.cmd(b'p%x' % reg) - num = 0 - for i in range(len(res))[-2::-2]: - num = 0x100 * num + int(res[i:i + 2], 16) - return num - - @staticmethod - def get_reg_be(g, reg): - res = g.cmd(b'p%x' % reg) - return int(res, 16) - - def get_reg(self, g, reg): - # value may be encoded in BE or LE order - if self.endian_is_le: - return self.get_reg_le(g, reg) - else: - return self.get_reg_be(g, reg) - - def get_pc(self, g): - return self.get_reg(g, self.REG_PC) - - def check_pc(self, g, addr): - pc = self.get_pc(g) - if pc != addr: - self.fail('Invalid PC (read %x instead of %x)' % (pc, addr)) - - @staticmethod - def gdb_step(g): - g.cmd(b's', b'T05thread:01;') - - @staticmethod - def gdb_bstep(g): - g.cmd(b'bs', b'T05thread:01;') - - @staticmethod - def vm_get_icount(vm): - return vm.qmp('query-replay')['return']['icount'] - - def reverse_debugging(self, shift=7, args=None): - logger = logging.getLogger('replay') - - # create qcow2 for snapshots - logger.info('creating qcow2 image for VM snapshots') - image_path = os.path.join(self.workdir, 'disk.qcow2') - qemu_img = os.path.join(BUILD_DIR, 'qemu-img') - if not os.path.exists(qemu_img): - qemu_img = find_command('qemu-img', False) - if qemu_img is False: - self.cancel('Could not find "qemu-img", which is required to ' - 'create the temporary qcow2 image') - cmd = '%s create -f qcow2 %s 128M' % (qemu_img, image_path) - process.run(cmd) - - replay_path = os.path.join(self.workdir, 'replay.bin') - port = find_free_port() - - # record the log - vm = self.run_vm(True, shift, args, replay_path, image_path, port) - while self.vm_get_icount(vm) <= self.STEPS: - pass - last_icount = self.vm_get_icount(vm) - vm.shutdown() - - logger.info("recorded log with %s+ steps" % last_icount) - - # replay and run debug commands - vm = self.run_vm(False, shift, args, replay_path, image_path, port) - logger.info('connecting to gdbstub') - g = gdb.GDBRemote('127.0.0.1', port, False, False) - g.connect() - r = g.cmd(b'qSupported') - if b'qXfer:features:read+' in r: - g.cmd(b'qXfer:features:read:target.xml:0,ffb') - if b'ReverseStep+' not in r: - self.fail('Reverse step is not supported by QEMU') - if b'ReverseContinue+' not in r: - self.fail('Reverse continue is not supported by QEMU') - - logger.info('stepping forward') - steps = [] - # record first instruction addresses - for _ in range(self.STEPS): - pc = self.get_pc(g) - logger.info('saving position %x' % pc) - steps.append(pc) - self.gdb_step(g) - - # visit the recorded instruction in reverse order - logger.info('stepping backward') - for addr in steps[::-1]: - self.gdb_bstep(g) - self.check_pc(g, addr) - logger.info('found position %x' % addr) - - logger.info('seeking to the end (icount %s)' % (last_icount - 1)) - vm.qmp('replay-break', icount=last_icount - 1) - # continue - will return after pausing - g.cmd(b'c', b'T02thread:01;') - - logger.info('setting breakpoints') - for addr in steps: - # hardware breakpoint at addr with len=1 - g.cmd(b'Z1,%x,1' % addr, b'OK') - - logger.info('running reverse continue to reach %x' % steps[-1]) - # reverse continue - will return after stopping at the breakpoint - g.cmd(b'bc', b'T05thread:01;') - - # assume that none of the first instructions is executed again - # breaking the order of the breakpoints - self.check_pc(g, steps[-1]) - logger.info('successfully reached %x' % steps[-1]) - - logger.info('exitting gdb and qemu') - vm.shutdown() - -class ReverseDebugging_X86_64(ReverseDebugging): - REG_PC = 0x10 - REG_CS = 0x12 - def get_pc(self, g): - return self.get_reg_le(g, self.REG_PC) \ - + self.get_reg_le(g, self.REG_CS) * 0x10 - - # unidentified gitlab timeout problem - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_x86_64_pc(self): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=machine:pc - """ - # start with BIOS only - self.reverse_debugging() - -class ReverseDebugging_AArch64(ReverseDebugging): - REG_PC = 32 - - # unidentified gitlab timeout problem - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test_aarch64_virt(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a53 - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/29/Everything/aarch64/os/images/pxeboot' - '/vmlinuz') - kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.reverse_debugging( - args=('-kernel', kernel_path)) diff --git a/tests/acceptance/smmu.py b/tests/acceptance/smmu.py deleted file mode 100644 index b3c4de6bf4..0000000000 --- a/tests/acceptance/smmu.py +++ /dev/null @@ -1,137 +0,0 @@ -# SMMUv3 Functional tests -# -# Copyright (c) 2021 Red Hat, Inc. -# -# Author: -# Eric Auger -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. -import os - -from avocado import skipIf -from avocado_qemu import LinuxTest, BUILD_DIR - -@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') -class SMMU(LinuxTest): - """ - :avocado: tags=accel:kvm - :avocado: tags=cpu:host - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=distro:fedora - :avocado: tags=smmu - """ - - IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' - kernel_path = None - initrd_path = None - kernel_params = None - - def set_up_boot(self): - path = self.download_boot() - self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,scsi=off,' + - 'drive=drv0,id=virtio-disk0,bootindex=1,' - 'werror=stop,rerror=stop' + self.IOMMU_ADDON) - self.vm.add_args('-drive', - 'file=%s,if=none,cache=writethrough,id=drv0' % path) - - def setUp(self): - super(SMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) - - def common_vm_setup(self, custom_kernel=False): - self.require_accelerator("kvm") - self.vm.add_args("-accel", "kvm") - self.vm.add_args("-cpu", "host") - self.vm.add_args("-machine", "iommu=smmuv3") - self.vm.add_args("-d", "guest_errors") - self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', - 'edk2-aarch64-code.fd')) - self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') - self.vm.add_args('-object', - 'rng-random,id=rng0,filename=/dev/urandom') - - if custom_kernel is False: - return - - kernel_url = self.distro.pxeboot_url + 'vmlinuz' - initrd_url = self.distro.pxeboot_url + 'initrd.img' - self.kernel_path = self.fetch_asset(kernel_url) - self.initrd_path = self.fetch_asset(initrd_url) - - def run_and_check(self): - if self.kernel_path: - self.vm.add_args('-kernel', self.kernel_path, - '-append', self.kernel_params, - '-initrd', self.initrd_path) - self.launch_and_wait() - self.ssh_command('cat /proc/cmdline') - self.ssh_command('dnf -y install numactl-devel') - - - # 5.3 kernel without RIL # - - def test_smmu_noril(self): - """ - :avocado: tags=smmu_noril - :avocado: tags=smmu_noril_tests - :avocado: tags=distro_version:31 - """ - self.common_vm_setup() - self.run_and_check() - - def test_smmu_noril_passthrough(self): - """ - :avocado: tags=smmu_noril_passthrough - :avocado: tags=smmu_noril_tests - :avocado: tags=distro_version:31 - """ - self.common_vm_setup(True) - self.kernel_params = (self.distro.default_kernel_params + - ' iommu.passthrough=on') - self.run_and_check() - - def test_smmu_noril_nostrict(self): - """ - :avocado: tags=smmu_noril_nostrict - :avocado: tags=smmu_noril_tests - :avocado: tags=distro_version:31 - """ - self.common_vm_setup(True) - self.kernel_params = (self.distro.default_kernel_params + - ' iommu.strict=0') - self.run_and_check() - - # 5.8 kernel featuring range invalidation - # >= v5.7 kernel - - def test_smmu_ril(self): - """ - :avocado: tags=smmu_ril - :avocado: tags=smmu_ril_tests - :avocado: tags=distro_version:33 - """ - self.common_vm_setup() - self.run_and_check() - - def test_smmu_ril_passthrough(self): - """ - :avocado: tags=smmu_ril_passthrough - :avocado: tags=smmu_ril_tests - :avocado: tags=distro_version:33 - """ - self.common_vm_setup(True) - self.kernel_params = (self.distro.default_kernel_params + - ' iommu.passthrough=on') - self.run_and_check() - - def test_smmu_ril_nostrict(self): - """ - :avocado: tags=smmu_ril_nostrict - :avocado: tags=smmu_ril_tests - :avocado: tags=distro_version:33 - """ - self.common_vm_setup(True) - self.kernel_params = (self.distro.default_kernel_params + - ' iommu.strict=0') - self.run_and_check() diff --git a/tests/acceptance/tcg_plugins.py b/tests/acceptance/tcg_plugins.py deleted file mode 100644 index 9ca1515c3b..0000000000 --- a/tests/acceptance/tcg_plugins.py +++ /dev/null @@ -1,147 +0,0 @@ -# TCG Plugins tests -# -# These are a little more involved than the basic tests run by check-tcg. -# -# Copyright (c) 2021 Linaro -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import tempfile -import mmap -import re - -from boot_linux_console import LinuxKernelTest - - -class PluginKernelBase(LinuxKernelTest): - """ - Boots a Linux kernel with a TCG plugin enabled. - """ - - timeout = 120 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' - - def run_vm(self, kernel_path, kernel_command_line, - plugin, plugin_log, console_pattern, args=None): - - vm = self.get_vm() - vm.set_console() - vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line, - '-plugin', plugin, - '-d', 'plugin', - '-D', plugin_log, - '-net', 'none', - '-no-reboot') - if args: - vm.add_args(*args) - - try: - vm.launch() - except: - # TODO: probably fails because plugins not enabled but we - # can't currently probe for the feature. - self.cancel("TCG Plugins not enabled?") - - self.wait_for_console_pattern(console_pattern, vm) - # ensure logs are flushed - vm.shutdown() - - -class PluginKernelNormal(PluginKernelBase): - - def _grab_aarch64_kernel(self): - kernel_url = ('http://security.debian.org/' - 'debian-security/pool/updates/main/l/linux-signed-arm64/' - 'linux-image-4.19.0-12-arm64_4.19.152-1_arm64.deb') - kernel_sha1 = '2036c2792f80ac9c4ccaae742b2e0a28385b6010' - kernel_deb = self.fetch_asset(kernel_url, asset_hash=kernel_sha1) - kernel_path = self.extract_from_deb(kernel_deb, - "/boot/vmlinuz-4.19.0-12-arm64") - return kernel_path - - def test_aarch64_virt_insn(self): - """ - :avocado: tags=accel:tcg - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a53 - """ - kernel_path = self._grab_aarch64_kernel() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - console_pattern = 'Kernel panic - not syncing: VFS:' - - plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", - suffix=".log") - - self.run_vm(kernel_path, kernel_command_line, - "tests/plugin/libinsn.so", plugin_log.name, - console_pattern) - - with plugin_log as lf, \ - mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: - - m = re.search(br"insns: (?P\d+)", s) - if "count" not in m.groupdict(): - self.fail("Failed to find instruction count") - - def test_aarch64_virt_insn_icount(self): - """ - :avocado: tags=accel:tcg - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a53 - """ - kernel_path = self._grab_aarch64_kernel() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - console_pattern = 'Kernel panic - not syncing: VFS:' - - plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", - suffix=".log") - - self.run_vm(kernel_path, kernel_command_line, - "tests/plugin/libinsn.so", plugin_log.name, - console_pattern, - args=('-icount', 'shift=1')) - - with plugin_log as lf, \ - mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: - m = re.search(br"detected repeat execution @ (?P0x[0-9A-Fa-f]+)", s) - if m is not None and "addr" in m.groupdict(): - self.fail("detected repeated instructions") - - def test_aarch64_virt_mem_icount(self): - """ - :avocado: tags=accel:tcg - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=cpu:cortex-a53 - """ - kernel_path = self._grab_aarch64_kernel() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - console_pattern = 'Kernel panic - not syncing: VFS:' - - plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", - suffix=".log") - - self.run_vm(kernel_path, kernel_command_line, - "tests/plugin/libmem.so,arg=both", plugin_log.name, - console_pattern, - args=('-icount', 'shift=1')) - - with plugin_log as lf, \ - mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: - m = re.findall(br"mem accesses: (?P\d+)", s) - if m is None or len(m) != 2: - self.fail("no memory access counts found") - else: - inline = int(m[0]) - callback = int(m[1]) - if inline != callback: - self.fail("mismatched access counts") diff --git a/tests/acceptance/tesseract_utils.py b/tests/acceptance/tesseract_utils.py deleted file mode 100644 index 72cd9ab798..0000000000 --- a/tests/acceptance/tesseract_utils.py +++ /dev/null @@ -1,46 +0,0 @@ -# ... -# -# Copyright (c) 2019 Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import re -import logging - -from avocado.utils import process -from avocado.utils.path import find_command, CmdNotFoundError - -def tesseract_available(expected_version): - try: - find_command('tesseract') - except CmdNotFoundError: - return False - res = process.run('tesseract --version') - try: - version = res.stdout_text.split()[1] - except IndexError: - version = res.stderr_text.split()[1] - return int(version.split('.')[0]) == expected_version - - match = re.match(r'tesseract\s(\d)', res) - if match is None: - return False - # now this is guaranteed to be a digit - return int(match.groups()[0]) == expected_version - - -def tesseract_ocr(image_path, tesseract_args='', tesseract_version=3): - console_logger = logging.getLogger('tesseract') - console_logger.debug(image_path) - if tesseract_version == 4: - tesseract_args += ' --oem 1' - proc = process.run("tesseract {} {} stdout".format(tesseract_args, - image_path)) - lines = [] - for line in proc.stdout_text.split('\n'): - sline = line.strip() - if len(sline): - console_logger.debug(sline) - lines += [sline] - return lines diff --git a/tests/acceptance/version.py b/tests/acceptance/version.py deleted file mode 100644 index 79b923d4fc..0000000000 --- a/tests/acceptance/version.py +++ /dev/null @@ -1,24 +0,0 @@ -# Version check example test -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - - -from avocado_qemu import Test - - -class Version(Test): - """ - :avocado: tags=quick - """ - def test_qmp_human_info_version(self): - self.vm.add_args('-nodefaults') - self.vm.launch() - res = self.vm.command('human-monitor-command', - command_line='info version') - self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)') diff --git a/tests/acceptance/virtio-gpu.py b/tests/acceptance/virtio-gpu.py deleted file mode 100644 index 4acc1e6d5f..0000000000 --- a/tests/acceptance/virtio-gpu.py +++ /dev/null @@ -1,155 +0,0 @@ -# virtio-gpu tests -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - - -from avocado_qemu import Test -from avocado_qemu import BUILD_DIR -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import is_readable_executable_file - -from qemu.utils import kvm_available - -import os -import socket -import subprocess - - -def pick_default_vug_bin(): - relative_path = "./contrib/vhost-user-gpu/vhost-user-gpu" - if is_readable_executable_file(relative_path): - return relative_path - - bld_dir_path = os.path.join(BUILD_DIR, relative_path) - if is_readable_executable_file(bld_dir_path): - return bld_dir_path - - -class VirtioGPUx86(Test): - """ - :avocado: tags=virtio-gpu - :avocado: tags=arch:x86_64 - :avocado: tags=cpu:host - """ - - KERNEL_COMMAND_LINE = "printk.time=0 console=ttyS0 rdinit=/bin/bash" - KERNEL_URL = ( - "https://archives.fedoraproject.org/pub/fedora" - "/linux/releases/33/Everything/x86_64/os/images" - "/pxeboot/vmlinuz" - ) - KERNEL_HASH = '1433cfe3f2ffaa44de4ecfb57ec25dc2399cdecf' - INITRD_URL = ( - "https://archives.fedoraproject.org/pub/fedora" - "/linux/releases/33/Everything/x86_64/os/images" - "/pxeboot/initrd.img" - ) - INITRD_HASH = 'c828d68a027b53e5220536585efe03412332c2d9' - - def wait_for_console_pattern(self, success_message, vm=None): - wait_for_console_pattern( - self, - success_message, - failure_message="Kernel panic - not syncing", - vm=vm, - ) - - def test_virtio_vga_virgl(self): - """ - :avocado: tags=device:virtio-vga-gl - """ - # FIXME: should check presence of virtio, virgl etc - self.require_accelerator('kvm') - - kernel_path = self.fetch_asset(self.KERNEL_URL, self.KERNEL_HASH) - initrd_path = self.fetch_asset(self.INITRD_URL, self.INITRD_HASH) - - self.vm.set_console() - self.vm.add_args("-m", "2G") - self.vm.add_args("-machine", "pc,accel=kvm") - self.vm.add_args("-device", "virtio-vga-gl") - self.vm.add_args("-display", "egl-headless") - self.vm.add_args( - "-kernel", - kernel_path, - "-initrd", - initrd_path, - "-append", - self.KERNEL_COMMAND_LINE, - ) - try: - self.vm.launch() - except: - # TODO: probably fails because we are missing the VirGL features - self.cancel("VirGL not enabled?") - - self.wait_for_console_pattern("as init process") - exec_command_and_wait_for_pattern( - self, "/usr/sbin/modprobe virtio_gpu", "" - ) - self.wait_for_console_pattern("features: +virgl +edid") - - def test_vhost_user_vga_virgl(self): - """ - :avocado: tags=device:vhost-user-vga - """ - # FIXME: should check presence of vhost-user-gpu, virgl, memfd etc - self.require_accelerator('kvm') - - vug = pick_default_vug_bin() - if not vug: - self.cancel("Could not find vhost-user-gpu") - - kernel_path = self.fetch_asset(self.KERNEL_URL, self.KERNEL_HASH) - initrd_path = self.fetch_asset(self.INITRD_URL, self.INITRD_HASH) - - # Create socketpair to connect proxy and remote processes - qemu_sock, vug_sock = socket.socketpair( - socket.AF_UNIX, socket.SOCK_STREAM - ) - os.set_inheritable(qemu_sock.fileno(), True) - os.set_inheritable(vug_sock.fileno(), True) - - self._vug_log_path = os.path.join( - self.logdir, "vhost-user-gpu.log" - ) - self._vug_log_file = open(self._vug_log_path, "wb") - self.log.info('Complete vhost-user-gpu.log file can be ' - 'found at %s', self._vug_log_path) - - vugp = subprocess.Popen( - [vug, "--virgl", "--fd=%d" % vug_sock.fileno()], - stdin=subprocess.DEVNULL, - stdout=self._vug_log_file, - stderr=subprocess.STDOUT, - shell=False, - close_fds=False, - ) - - self.vm.set_console() - self.vm.add_args("-m", "2G") - self.vm.add_args("-object", "memory-backend-memfd,id=mem,size=2G") - self.vm.add_args("-machine", "pc,memory-backend=mem,accel=kvm") - self.vm.add_args("-chardev", "socket,id=vug,fd=%d" % qemu_sock.fileno()) - self.vm.add_args("-device", "vhost-user-vga,chardev=vug") - self.vm.add_args("-display", "egl-headless") - self.vm.add_args( - "-kernel", - kernel_path, - "-initrd", - initrd_path, - "-append", - self.KERNEL_COMMAND_LINE, - ) - self.vm.launch() - self.wait_for_console_pattern("as init process") - exec_command_and_wait_for_pattern( - self, "/usr/sbin/modprobe virtio_gpu", "" - ) - self.wait_for_console_pattern("features: +virgl -edid") - self.vm.shutdown() - qemu_sock.close() - vugp.terminate() - vugp.wait() diff --git a/tests/acceptance/virtio_check_params.py b/tests/acceptance/virtio_check_params.py deleted file mode 100644 index 87e6c839d1..0000000000 --- a/tests/acceptance/virtio_check_params.py +++ /dev/null @@ -1,144 +0,0 @@ -# -# Test virtio-scsi and virtio-blk queue settings for all machine types -# -# Copyright (c) 2019 Virtuozzo International GmbH -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -import sys -import os -import re -import logging - -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.machine import QEMUMachine -from avocado_qemu import Test -from avocado import skip - -#list of machine types and virtqueue properties to test -VIRTIO_SCSI_PROPS = {'seg_max_adjust': 'seg_max_adjust'} -VIRTIO_BLK_PROPS = {'seg_max_adjust': 'seg-max-adjust'} - -DEV_TYPES = {'virtio-scsi-pci': VIRTIO_SCSI_PROPS, - 'virtio-blk-pci': VIRTIO_BLK_PROPS} - -VM_DEV_PARAMS = {'virtio-scsi-pci': ['-device', 'virtio-scsi-pci,id=scsi0'], - 'virtio-blk-pci': ['-device', - 'virtio-blk-pci,id=scsi0,drive=drive0', - '-drive', - 'driver=null-co,id=drive0,if=none']} - - -class VirtioMaxSegSettingsCheck(Test): - @staticmethod - def make_pattern(props): - pattern_items = ['{0} = \w+'.format(prop) for prop in props] - return '|'.join(pattern_items) - - def query_virtqueue(self, vm, dev_type_name): - query_ok = False - error = None - props = None - - output = vm.command('human-monitor-command', - command_line = 'info qtree') - props_list = DEV_TYPES[dev_type_name].values(); - pattern = self.make_pattern(props_list) - res = re.findall(pattern, output) - - if len(res) != len(props_list): - props_list = set(props_list) - res = set(res) - not_found = props_list.difference(res) - not_found = ', '.join(not_found) - error = '({0}): The following properties not found: {1}'\ - .format(dev_type_name, not_found) - else: - query_ok = True - props = dict() - for prop in res: - p = prop.split(' = ') - props[p[0]] = p[1] - return query_ok, props, error - - def check_mt(self, mt, dev_type_name): - mt['device'] = dev_type_name # Only for the debug() call. - logger = logging.getLogger('machine') - logger.debug(mt) - with QEMUMachine(self.qemu_bin) as vm: - vm.set_machine(mt["name"]) - vm.add_args('-nodefaults') - for s in VM_DEV_PARAMS[dev_type_name]: - vm.add_args(s) - try: - vm.launch() - query_ok, props, error = self.query_virtqueue(vm, dev_type_name) - except: - query_ok = False - error = sys.exc_info()[0] - - if not query_ok: - self.fail('machine type {0}: {1}'.format(mt['name'], error)) - - for prop_name, prop_val in props.items(): - expected_val = mt[prop_name] - self.assertEqual(expected_val, prop_val) - - @staticmethod - def seg_max_adjust_enabled(mt): - # machine types >= 5.0 should have seg_max_adjust = true - # others seg_max_adjust = false - mt = mt.split("-") - - # machine types with one line name and name like pc-x.x - if len(mt) <= 2: - return False - - # machine types like pc--x.x[.x] - ver = mt[2] - ver = ver.split("."); - - # versions >= 5.0 goes with seg_max_adjust enabled - major = int(ver[0]) - - if major >= 5: - return True - return False - - @skip("break multi-arch CI") - def test_machine_types(self): - # collect all machine types except 'none', 'isapc', 'microvm' - with QEMUMachine(self.qemu_bin) as vm: - vm.launch() - machines = [m['name'] for m in vm.command('query-machines')] - vm.shutdown() - machines.remove('none') - machines.remove('isapc') - machines.remove('microvm') - - for dev_type in DEV_TYPES: - # create the list of machine types and their parameters. - mtypes = list() - for m in machines: - if self.seg_max_adjust_enabled(m): - enabled = 'true' - else: - enabled = 'false' - mtypes.append({'name': m, - DEV_TYPES[dev_type]['seg_max_adjust']: enabled}) - - # test each machine type for a device type - for mt in mtypes: - self.check_mt(mt, dev_type) diff --git a/tests/acceptance/virtio_version.py b/tests/acceptance/virtio_version.py deleted file mode 100644 index 33593c29dd..0000000000 --- a/tests/acceptance/virtio_version.py +++ /dev/null @@ -1,175 +0,0 @@ -""" -Check compatibility of virtio device types -""" -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Eduardo Habkost -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. -import sys -import os - -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.machine import QEMUMachine -from avocado_qemu import Test - -# Virtio Device IDs: -VIRTIO_NET = 1 -VIRTIO_BLOCK = 2 -VIRTIO_CONSOLE = 3 -VIRTIO_RNG = 4 -VIRTIO_BALLOON = 5 -VIRTIO_RPMSG = 7 -VIRTIO_SCSI = 8 -VIRTIO_9P = 9 -VIRTIO_RPROC_SERIAL = 11 -VIRTIO_CAIF = 12 -VIRTIO_GPU = 16 -VIRTIO_INPUT = 18 -VIRTIO_VSOCK = 19 -VIRTIO_CRYPTO = 20 - -PCI_VENDOR_ID_REDHAT_QUMRANET = 0x1af4 - -# Device IDs for legacy/transitional devices: -PCI_LEGACY_DEVICE_IDS = { - VIRTIO_NET: 0x1000, - VIRTIO_BLOCK: 0x1001, - VIRTIO_BALLOON: 0x1002, - VIRTIO_CONSOLE: 0x1003, - VIRTIO_SCSI: 0x1004, - VIRTIO_RNG: 0x1005, - VIRTIO_9P: 0x1009, - VIRTIO_VSOCK: 0x1012, -} - -def pci_modern_device_id(virtio_devid): - return virtio_devid + 0x1040 - -def devtype_implements(vm, devtype, implements): - return devtype in [d['name'] for d in vm.command('qom-list-types', implements=implements)] - -def get_pci_interfaces(vm, devtype): - interfaces = ('pci-express-device', 'conventional-pci-device') - return [i for i in interfaces if devtype_implements(vm, devtype, i)] - -class VirtioVersionCheck(Test): - """ - Check if virtio-version-specific device types result in the - same device tree created by `disable-modern` and - `disable-legacy`. - - :avocado: tags=arch:x86_64 - """ - - # just in case there are failures, show larger diff: - maxDiff = 4096 - - def run_device(self, devtype, opts=None, machine='pc'): - """ - Run QEMU with `-device DEVTYPE`, return device info from `query-pci` - """ - with QEMUMachine(self.qemu_bin) as vm: - vm.set_machine(machine) - if opts: - devtype += ',' + opts - vm.add_args('-device', '%s,id=devfortest' % (devtype)) - vm.add_args('-S') - vm.launch() - - pcibuses = vm.command('query-pci') - alldevs = [dev for bus in pcibuses for dev in bus['devices']] - devfortest = [dev for dev in alldevs - if dev['qdev_id'] == 'devfortest'] - return devfortest[0], get_pci_interfaces(vm, devtype) - - - def assert_devids(self, dev, devid, non_transitional=False): - self.assertEqual(dev['id']['vendor'], PCI_VENDOR_ID_REDHAT_QUMRANET) - self.assertEqual(dev['id']['device'], devid) - if non_transitional: - self.assertTrue(0x1040 <= dev['id']['device'] <= 0x107f) - self.assertGreaterEqual(dev['id']['subsystem'], 0x40) - - def check_all_variants(self, qemu_devtype, virtio_devid): - """Check if a virtio device type and its variants behave as expected""" - # Force modern mode: - dev_modern, _ = self.run_device(qemu_devtype, - 'disable-modern=off,disable-legacy=on') - self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid), - non_transitional=True) - - # -non-transitional device types should be 100% equivalent to - # ,disable-modern=off,disable-legacy=on - dev_1_0, nt_ifaces = self.run_device('%s-non-transitional' % (qemu_devtype)) - self.assertEqual(dev_modern, dev_1_0) - - # Force transitional mode: - dev_trans, _ = self.run_device(qemu_devtype, - 'disable-modern=off,disable-legacy=off') - self.assert_devids(dev_trans, PCI_LEGACY_DEVICE_IDS[virtio_devid]) - - # Force legacy mode: - dev_legacy, _ = self.run_device(qemu_devtype, - 'disable-modern=on,disable-legacy=off') - self.assert_devids(dev_legacy, PCI_LEGACY_DEVICE_IDS[virtio_devid]) - - # No options: default to transitional on PC machine-type: - no_opts_pc, generic_ifaces = self.run_device(qemu_devtype) - self.assertEqual(dev_trans, no_opts_pc) - - #TODO: check if plugging on a PCI Express bus will make the - # device non-transitional - #no_opts_q35 = self.run_device(qemu_devtype, machine='q35') - #self.assertEqual(dev_modern, no_opts_q35) - - # -transitional device types should be 100% equivalent to - # ,disable-modern=off,disable-legacy=off - dev_trans, trans_ifaces = self.run_device('%s-transitional' % (qemu_devtype)) - self.assertEqual(dev_trans, dev_trans) - - # ensure the interface information is correct: - self.assertIn('conventional-pci-device', generic_ifaces) - self.assertIn('pci-express-device', generic_ifaces) - - self.assertIn('conventional-pci-device', nt_ifaces) - self.assertIn('pci-express-device', nt_ifaces) - - self.assertIn('conventional-pci-device', trans_ifaces) - self.assertNotIn('pci-express-device', trans_ifaces) - - - def test_conventional_devs(self): - self.check_all_variants('virtio-net-pci', VIRTIO_NET) - # virtio-blk requires 'driver' parameter - #self.check_all_variants('virtio-blk-pci', VIRTIO_BLOCK) - self.check_all_variants('virtio-serial-pci', VIRTIO_CONSOLE) - self.check_all_variants('virtio-rng-pci', VIRTIO_RNG) - self.check_all_variants('virtio-balloon-pci', VIRTIO_BALLOON) - self.check_all_variants('virtio-scsi-pci', VIRTIO_SCSI) - # virtio-9p requires 'fsdev' parameter - #self.check_all_variants('virtio-9p-pci', VIRTIO_9P) - - def check_modern_only(self, qemu_devtype, virtio_devid): - """Check if a modern-only virtio device type behaves as expected""" - # Force modern mode: - dev_modern, _ = self.run_device(qemu_devtype, - 'disable-modern=off,disable-legacy=on') - self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid), - non_transitional=True) - - # No options: should be modern anyway - dev_no_opts, ifaces = self.run_device(qemu_devtype) - self.assertEqual(dev_modern, dev_no_opts) - - self.assertIn('conventional-pci-device', ifaces) - self.assertIn('pci-express-device', ifaces) - - def test_modern_only_devs(self): - self.check_modern_only('virtio-vga', VIRTIO_GPU) - self.check_modern_only('virtio-gpu-pci', VIRTIO_GPU) - self.check_modern_only('virtio-mouse-pci', VIRTIO_INPUT) - self.check_modern_only('virtio-tablet-pci', VIRTIO_INPUT) - self.check_modern_only('virtio-keyboard-pci', VIRTIO_INPUT) diff --git a/tests/acceptance/virtiofs_submounts.py b/tests/acceptance/virtiofs_submounts.py deleted file mode 100644 index 21ad7d792e..0000000000 --- a/tests/acceptance/virtiofs_submounts.py +++ /dev/null @@ -1,272 +0,0 @@ -import logging -import re -import os -import subprocess -import time - -from avocado import skipUnless -from avocado_qemu import LinuxTest, BUILD_DIR -from avocado_qemu import wait_for_console_pattern -from avocado.utils import ssh - - -def run_cmd(args): - subp = subprocess.Popen(args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True) - stdout, stderr = subp.communicate() - ret = subp.returncode - - return (stdout, stderr, ret) - -def has_cmd(name, args=None): - """ - This function is for use in a @avocado.skipUnless decorator, e.g.: - - @skipUnless(*has_cmd('sudo -n', ('sudo', '-n', 'true'))) - def test_something_that_needs_sudo(self): - ... - """ - - if args is None: - args = ('which', name) - - try: - _, stderr, exitcode = run_cmd(args) - except Exception as e: - exitcode = -1 - stderr = str(e) - - if exitcode != 0: - cmd_line = ' '.join(args) - err = f'{name} required, but "{cmd_line}" failed: {stderr.strip()}' - return (False, err) - else: - return (True, '') - -def has_cmds(*cmds): - """ - This function is for use in a @avocado.skipUnless decorator and - allows checking for the availability of multiple commands, e.g.: - - @skipUnless(*has_cmds(('cmd1', ('cmd1', '--some-parameter')), - 'cmd2', 'cmd3')) - def test_something_that_needs_cmd1_and_cmd2(self): - ... - """ - - for cmd in cmds: - if isinstance(cmd, str): - cmd = (cmd,) - - ok, errstr = has_cmd(*cmd) - if not ok: - return (False, errstr) - - return (True, '') - - -class VirtiofsSubmountsTest(LinuxTest): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=accel:kvm - """ - - def run(self, args, ignore_error=False): - stdout, stderr, ret = run_cmd(args) - - if ret != 0: - cmdline = ' '.join(args) - if not ignore_error: - self.fail(f'{cmdline}: Returned {ret}: {stderr}') - else: - self.log.warn(f'{cmdline}: Returned {ret}: {stderr}') - - return (stdout, stderr, ret) - - def set_up_shared_dir(self): - self.shared_dir = os.path.join(self.workdir, 'virtiofs-shared') - - os.mkdir(self.shared_dir) - - self.run(('cp', self.get_data('guest.sh'), - os.path.join(self.shared_dir, 'check.sh'))) - - self.run(('cp', self.get_data('guest-cleanup.sh'), - os.path.join(self.shared_dir, 'cleanup.sh'))) - - def set_up_virtiofs(self): - attmp = os.getenv('AVOCADO_TESTS_COMMON_TMPDIR') - self.vfsdsock = os.path.join(attmp, 'vfsdsock') - - self.run(('sudo', '-n', 'rm', '-f', self.vfsdsock), ignore_error=True) - - self.virtiofsd = \ - subprocess.Popen(('sudo', '-n', - 'tools/virtiofsd/virtiofsd', - f'--socket-path={self.vfsdsock}', - '-o', f'source={self.shared_dir}', - '-o', 'cache=always', - '-o', 'xattr', - '-o', 'announce_submounts', - '-f'), - stdout=subprocess.DEVNULL, - stderr=subprocess.PIPE, - universal_newlines=True) - - while not os.path.exists(self.vfsdsock): - if self.virtiofsd.poll() is not None: - self.fail('virtiofsd exited prematurely: ' + - self.virtiofsd.communicate()[1]) - time.sleep(0.1) - - self.run(('sudo', '-n', 'chmod', 'go+rw', self.vfsdsock)) - - self.vm.add_args('-chardev', - f'socket,id=vfsdsock,path={self.vfsdsock}', - '-device', - 'vhost-user-fs-pci,queue-size=1024,chardev=vfsdsock' \ - ',tag=host', - '-object', - 'memory-backend-file,id=mem,size=1G,' \ - 'mem-path=/dev/shm,share=on', - '-numa', - 'node,memdev=mem') - - def set_up_nested_mounts(self): - scratch_dir = os.path.join(self.shared_dir, 'scratch') - try: - os.mkdir(scratch_dir) - except FileExistsError: - pass - - args = ['bash', self.get_data('host.sh'), scratch_dir] - if self.seed: - args += [self.seed] - - out, _, _ = self.run(args) - seed = re.search(r'^Seed: \d+', out) - self.log.info(seed[0]) - - def mount_in_guest(self): - self.ssh_command('mkdir -p /mnt/host') - self.ssh_command('mount -t virtiofs host /mnt/host') - - def check_in_guest(self): - self.ssh_command('bash /mnt/host/check.sh /mnt/host/scratch/share') - - def live_cleanup(self): - self.ssh_command('bash /mnt/host/cleanup.sh /mnt/host/scratch') - - # It would be nice if the above was sufficient to make virtiofsd clear - # all references to the mounted directories (so they can be unmounted - # on the host), but unfortunately it is not. To do so, we have to - # resort to a remount. - self.ssh_command('mount -o remount /mnt/host') - - scratch_dir = os.path.join(self.shared_dir, 'scratch') - self.run(('bash', self.get_data('cleanup.sh'), scratch_dir)) - - @skipUnless(*has_cmds(('sudo -n', ('sudo', '-n', 'true')), - 'ssh-keygen', 'bash', 'losetup', 'mkfs.xfs', 'mount')) - def setUp(self): - vmlinuz = self.params.get('vmlinuz') - if vmlinuz is None: - """ - The Linux kernel supports FUSE auto-submounts only as of 5.10. - boot_linux.py currently provides Fedora 31, whose kernel is too - old, so this test cannot pass with the on-image kernel (you are - welcome to try, hence the option to force such a test with - -p vmlinuz=''). Therefore, for now the user must provide a - sufficiently new custom kernel, or effectively explicitly - request failure with -p vmlinuz=''. - Once an image with a sufficiently new kernel is available - (probably Fedora 34), we can make -p vmlinuz='' the default, so - that this parameter no longer needs to be specified. - """ - self.cancel('vmlinuz parameter not set; you must point it to a ' - 'Linux kernel binary to test (to run this test with ' \ - 'the on-image kernel, set it to an empty string)') - - self.seed = self.params.get('seed') - - self.ssh_key = os.path.join(self.workdir, 'id_ed25519') - - self.run(('ssh-keygen', '-N', '', '-t', 'ed25519', '-f', self.ssh_key)) - - pubkey = self.ssh_key + '.pub' - - super(VirtiofsSubmountsTest, self).setUp(pubkey) - - if vmlinuz: - self.vm.add_args('-kernel', vmlinuz, - '-append', 'console=ttyS0 root=/dev/sda1') - - self.require_accelerator("kvm") - self.vm.add_args('-accel', 'kvm') - - def tearDown(self): - try: - self.vm.shutdown() - except: - pass - - scratch_dir = os.path.join(self.shared_dir, 'scratch') - self.run(('bash', self.get_data('cleanup.sh'), scratch_dir), - ignore_error=True) - - def test_pre_virtiofsd_set_up(self): - self.set_up_shared_dir() - - self.set_up_nested_mounts() - - self.set_up_virtiofs() - self.launch_and_wait() - self.mount_in_guest() - self.check_in_guest() - - def test_pre_launch_set_up(self): - self.set_up_shared_dir() - self.set_up_virtiofs() - - self.set_up_nested_mounts() - - self.launch_and_wait() - self.mount_in_guest() - self.check_in_guest() - - def test_post_launch_set_up(self): - self.set_up_shared_dir() - self.set_up_virtiofs() - self.launch_and_wait() - - self.set_up_nested_mounts() - - self.mount_in_guest() - self.check_in_guest() - - def test_post_mount_set_up(self): - self.set_up_shared_dir() - self.set_up_virtiofs() - self.launch_and_wait() - self.mount_in_guest() - - self.set_up_nested_mounts() - - self.check_in_guest() - - def test_two_runs(self): - self.set_up_shared_dir() - - self.set_up_nested_mounts() - - self.set_up_virtiofs() - self.launch_and_wait() - self.mount_in_guest() - self.check_in_guest() - - self.live_cleanup() - self.set_up_nested_mounts() - - self.check_in_guest() diff --git a/tests/acceptance/virtiofs_submounts.py.data/cleanup.sh b/tests/acceptance/virtiofs_submounts.py.data/cleanup.sh deleted file mode 100644 index 2a6579a0fe..0000000000 --- a/tests/acceptance/virtiofs_submounts.py.data/cleanup.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -function print_usage() -{ - if [ -n "$2" ]; then - echo "Error: $2" - echo - fi - echo "Usage: $1 " -} - -scratch_dir=$1 -if [ -z "$scratch_dir" ]; then - print_usage "$0" 'Scratch dir not given' >&2 - exit 1 -fi - -cd "$scratch_dir/share" || exit 1 -mps=(mnt*) -mp_i=0 -for mp in "${mps[@]}"; do - mp_i=$((mp_i + 1)) - printf "Unmounting %i/%i...\r" "$mp_i" "${#mps[@]}" - - sudo umount -R "$mp" - rm -rf "$mp" -done -echo - -rm some-file -cd .. -rmdir share - -imgs=(fs*.img) -img_i=0 -for img in "${imgs[@]}"; do - img_i=$((img_i + 1)) - printf "Detaching and deleting %i/%i...\r" "$img_i" "${#imgs[@]}" - - dev=$(losetup -j "$img" | sed -e 's/:.*//') - sudo losetup -d "$dev" - rm -f "$img" -done -echo - -echo 'Done.' diff --git a/tests/acceptance/virtiofs_submounts.py.data/guest-cleanup.sh b/tests/acceptance/virtiofs_submounts.py.data/guest-cleanup.sh deleted file mode 100644 index 729cb2d1a5..0000000000 --- a/tests/acceptance/virtiofs_submounts.py.data/guest-cleanup.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -function print_usage() -{ - if [ -n "$2" ]; then - echo "Error: $2" - echo - fi - echo "Usage: $1 " -} - -scratch_dir=$1 -if [ -z "$scratch_dir" ]; then - print_usage "$0" 'Scratch dir not given' >&2 - exit 1 -fi - -cd "$scratch_dir/share" || exit 1 - -mps=(mnt*) -mp_i=0 -for mp in "${mps[@]}"; do - mp_i=$((mp_i + 1)) - printf "Unmounting %i/%i...\r" "$mp_i" "${#mps[@]}" - - sudo umount -R "$mp" -done -echo - -echo 'Done.' diff --git a/tests/acceptance/virtiofs_submounts.py.data/guest.sh b/tests/acceptance/virtiofs_submounts.py.data/guest.sh deleted file mode 100644 index 59ba40fde1..0000000000 --- a/tests/acceptance/virtiofs_submounts.py.data/guest.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash - -function print_usage() -{ - if [ -n "$2" ]; then - echo "Error: $2" - echo - fi - echo "Usage: $1 " - echo '(The shared directory is the "share" directory in the scratch' \ - 'directory)' -} - -shared_dir=$1 -if [ -z "$shared_dir" ]; then - print_usage "$0" 'Shared dir not given' >&2 - exit 1 -fi - -cd "$shared_dir" - -# FIXME: This should not be necessary, but it is. In order for all -# submounts to be proper mount points, we need to visit them. -# (Before we visit them, they will not be auto-mounted, and so just -# appear as normal directories, with the catch that their st_ino will -# be the st_ino of the filesystem they host, while the st_dev will -# still be the st_dev of the parent.) -# `find` does not work, because it will refuse to touch the mount -# points as long as they are not mounted; their st_dev being shared -# with the parent and st_ino just being the root node's inode ID -# will practically ensure that this node exists elsewhere on the -# filesystem, and `find` is required to recognize loops and not to -# follow them. -# Thus, we have to manually visit all nodes first. - -mnt_i=0 - -function recursively_visit() -{ - pushd "$1" >/dev/null - for entry in *; do - if [[ "$entry" == mnt* ]]; then - mnt_i=$((mnt_i + 1)) - printf "Triggering auto-mount $mnt_i...\r" - fi - - if [ -d "$entry" ]; then - recursively_visit "$entry" - fi - done - popd >/dev/null -} - -recursively_visit . -echo - - -if [ -n "$(find -name not-mounted)" ]; then - echo "Error: not-mounted files visible on mount points:" >&2 - find -name not-mounted >&2 - exit 1 -fi - -if [ ! -f some-file -o "$(cat some-file)" != 'root' ]; then - echo "Error: Bad file in the share root" >&2 - exit 1 -fi - -shopt -s nullglob - -function check_submounts() -{ - local base_path=$1 - - for mp in mnt*; do - printf "Checking submount %i...\r" "$((${#devs[@]} + 1))" - - mp_i=$(echo "$mp" | sed -e 's/mnt//') - dev=$(stat -c '%D' "$mp") - - if [ -n "${devs[mp_i]}" ]; then - echo "Error: $mp encountered twice" >&2 - exit 1 - fi - devs[mp_i]=$dev - - pushd "$mp" >/dev/null - path="$base_path$mp" - while true; do - expected_content="$(printf '%s\n%s\n' "$mp_i" "$path")" - if [ ! -f some-file ]; then - echo "Error: $PWD/some-file does not exist" >&2 - exit 1 - fi - - if [ "$(cat some-file)" != "$expected_content" ]; then - echo "Error: Bad content in $PWD/some-file:" >&2 - echo '--- found ---' - cat some-file - echo '--- expected ---' - echo "$expected_content" - exit 1 - fi - if [ "$(stat -c '%D' some-file)" != "$dev" ]; then - echo "Error: $PWD/some-file has the wrong device ID" >&2 - exit 1 - fi - - if [ -d sub ]; then - if [ "$(stat -c '%D' sub)" != "$dev" ]; then - echo "Error: $PWD/some-file has the wrong device ID" >&2 - exit 1 - fi - cd sub - path="$path/sub" - else - if [ -n "$(echo mnt*)" ]; then - check_submounts "$path/" - fi - break - fi - done - popd >/dev/null - done -} - -root_dev=$(stat -c '%D' some-file) -devs=() -check_submounts '' -echo - -reused_devs=$(echo "$root_dev ${devs[@]}" | tr ' ' '\n' | sort | uniq -d) -if [ -n "$reused_devs" ]; then - echo "Error: Reused device IDs: $reused_devs" >&2 - exit 1 -fi - -echo "Test passed for ${#devs[@]} submounts." diff --git a/tests/acceptance/virtiofs_submounts.py.data/host.sh b/tests/acceptance/virtiofs_submounts.py.data/host.sh deleted file mode 100644 index d8a9afebdb..0000000000 --- a/tests/acceptance/virtiofs_submounts.py.data/host.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/bin/bash - -mount_count=128 - -function print_usage() -{ - if [ -n "$2" ]; then - echo "Error: $2" - echo - fi - echo "Usage: $1 [seed]" - echo "(If no seed is given, it will be randomly generated.)" -} - -scratch_dir=$1 -if [ -z "$scratch_dir" ]; then - print_usage "$0" 'No scratch dir given' >&2 - exit 1 -fi - -if [ ! -d "$scratch_dir" ]; then - print_usage "$0" "$scratch_dir is not a directory" >&2 - exit 1 -fi - -seed=$2 -if [ -z "$seed" ]; then - seed=$RANDOM -fi -RANDOM=$seed - -echo "Seed: $seed" - -set -e -shopt -s nullglob - -cd "$scratch_dir" -if [ -d share ]; then - echo 'Error: This directory seems to be in use already' >&2 - exit 1 -fi - -for ((i = 0; i < $mount_count; i++)); do - printf "Setting up fs %i/%i...\r" "$((i + 1))" "$mount_count" - - rm -f fs$i.img - truncate -s 512M fs$i.img - mkfs.xfs -q fs$i.img - devs[i]=$(sudo losetup -f --show fs$i.img) -done -echo - -top_level_mounts=$((RANDOM % mount_count + 1)) - -mkdir -p share -echo 'root' > share/some-file - -for ((i = 0; i < $top_level_mounts; i++)); do - printf "Mounting fs %i/%i...\r" "$((i + 1))" "$mount_count" - - mkdir -p share/mnt$i - touch share/mnt$i/not-mounted - sudo mount "${devs[i]}" share/mnt$i - sudo chown "$(id -u):$(id -g)" share/mnt$i - - pushd share/mnt$i >/dev/null - path=mnt$i - nesting=$((RANDOM % 4)) - for ((j = 0; j < $nesting; j++)); do - cat > some-file < some-file </dev/null -done - -for ((; i < $mount_count; i++)); do - printf "Mounting fs %i/%i...\r" "$((i + 1))" "$mount_count" - - mp_i=$((i % top_level_mounts)) - - pushd share/mnt$mp_i >/dev/null - path=mnt$mp_i - while true; do - sub_mp="$(echo mnt*)" - if cd sub 2>/dev/null; then - path="$path/sub" - elif [ -n "$sub_mp" ] && cd "$sub_mp" 2>/dev/null; then - path="$path/$sub_mp" - else - break - fi - done - mkdir mnt$i - touch mnt$i/not-mounted - sudo mount "${devs[i]}" mnt$i - sudo chown "$(id -u):$(id -g)" mnt$i - - cd mnt$i - path="$path/mnt$i" - nesting=$((RANDOM % 4)) - for ((j = 0; j < $nesting; j++)); do - cat > some-file < some-file </dev/null -done -echo - -echo 'Done.' diff --git a/tests/acceptance/vnc.py b/tests/acceptance/vnc.py deleted file mode 100644 index f301fbb4f5..0000000000 --- a/tests/acceptance/vnc.py +++ /dev/null @@ -1,53 +0,0 @@ -# Simple functional tests for VNC functionality -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado_qemu import Test - - -class Vnc(Test): - """ - :avocado: tags=vnc,quick - """ - def test_no_vnc(self): - self.vm.add_args('-nodefaults', '-S') - self.vm.launch() - self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled']) - - def test_no_vnc_change_password(self): - self.vm.add_args('-nodefaults', '-S') - self.vm.launch() - self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled']) - set_password_response = self.vm.qmp('change-vnc-password', - password='new_password') - self.assertIn('error', set_password_response) - self.assertEqual(set_password_response['error']['class'], - 'GenericError') - self.assertEqual(set_password_response['error']['desc'], - 'Could not set password') - - def test_change_password_requires_a_password(self): - self.vm.add_args('-nodefaults', '-S', '-vnc', ':0') - self.vm.launch() - self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) - set_password_response = self.vm.qmp('change-vnc-password', - password='new_password') - self.assertIn('error', set_password_response) - self.assertEqual(set_password_response['error']['class'], - 'GenericError') - self.assertEqual(set_password_response['error']['desc'], - 'Could not set password') - - def test_change_password(self): - self.vm.add_args('-nodefaults', '-S', '-vnc', ':0,password=on') - self.vm.launch() - self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) - set_password_response = self.vm.qmp('change-vnc-password', - password='new_password') - self.assertEqual(set_password_response['return'], {}) diff --git a/tests/acceptance/x86_cpu_model_versions.py b/tests/acceptance/x86_cpu_model_versions.py deleted file mode 100644 index 0e9feda62d..0000000000 --- a/tests/acceptance/x86_cpu_model_versions.py +++ /dev/null @@ -1,358 +0,0 @@ -# -# Basic validation of x86 versioned CPU models and CPU model aliases -# -# Copyright (c) 2019 Red Hat Inc -# -# Author: -# Eduardo Habkost -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, see . -# - - -import avocado_qemu -import re - -class X86CPUModelAliases(avocado_qemu.Test): - """ - Validation of PC CPU model versions and CPU model aliases - - :avocado: tags=arch:x86_64 - """ - def validate_aliases(self, cpus): - for c in cpus.values(): - if 'alias-of' in c: - # all aliases must point to a valid CPU model name: - self.assertIn(c['alias-of'], cpus, - '%s.alias-of (%s) is not a valid CPU model name' % (c['name'], c['alias-of'])) - # aliases must not point to aliases - self.assertNotIn('alias-of', cpus[c['alias-of']], - '%s.alias-of (%s) points to another alias' % (c['name'], c['alias-of'])) - - # aliases must not be static - self.assertFalse(c['static']) - - def validate_variant_aliases(self, cpus): - # -noTSX, -IBRS and -IBPB variants of CPU models are special: - # they shouldn't have their own versions: - self.assertNotIn("Haswell-noTSX-v1", cpus, - "Haswell-noTSX shouldn't be versioned") - self.assertNotIn("Broadwell-noTSX-v1", cpus, - "Broadwell-noTSX shouldn't be versioned") - self.assertNotIn("Nehalem-IBRS-v1", cpus, - "Nehalem-IBRS shouldn't be versioned") - self.assertNotIn("Westmere-IBRS-v1", cpus, - "Westmere-IBRS shouldn't be versioned") - self.assertNotIn("SandyBridge-IBRS-v1", cpus, - "SandyBridge-IBRS shouldn't be versioned") - self.assertNotIn("IvyBridge-IBRS-v1", cpus, - "IvyBridge-IBRS shouldn't be versioned") - self.assertNotIn("Haswell-noTSX-IBRS-v1", cpus, - "Haswell-noTSX-IBRS shouldn't be versioned") - self.assertNotIn("Haswell-IBRS-v1", cpus, - "Haswell-IBRS shouldn't be versioned") - self.assertNotIn("Broadwell-noTSX-IBRS-v1", cpus, - "Broadwell-noTSX-IBRS shouldn't be versioned") - self.assertNotIn("Broadwell-IBRS-v1", cpus, - "Broadwell-IBRS shouldn't be versioned") - self.assertNotIn("Skylake-Client-IBRS-v1", cpus, - "Skylake-Client-IBRS shouldn't be versioned") - self.assertNotIn("Skylake-Server-IBRS-v1", cpus, - "Skylake-Server-IBRS shouldn't be versioned") - self.assertNotIn("EPYC-IBPB-v1", cpus, - "EPYC-IBPB shouldn't be versioned") - - def test_4_0_alias_compatibility(self): - """ - Check if pc-*-4.0 unversioned CPU model won't be reported as aliases - - :avocado: tags=machine:pc-i440fx-4.0 - """ - # pc-*-4.0 won't expose non-versioned CPU models as aliases - # We do this to help management software to keep compatibility - # with older QEMU versions that didn't have the versioned CPU model - self.vm.add_args('-S') - self.vm.launch() - cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions')) - - self.assertFalse(cpus['Cascadelake-Server']['static'], - 'unversioned Cascadelake-Server CPU model must not be static') - self.assertNotIn('alias-of', cpus['Cascadelake-Server'], - 'Cascadelake-Server must not be an alias') - self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], - 'Cascadelake-Server-v1 must not be an alias') - - self.assertFalse(cpus['qemu64']['static'], - 'unversioned qemu64 CPU model must not be static') - self.assertNotIn('alias-of', cpus['qemu64'], - 'qemu64 must not be an alias') - self.assertNotIn('alias-of', cpus['qemu64-v1'], - 'qemu64-v1 must not be an alias') - - self.validate_variant_aliases(cpus) - - # On pc-*-4.0, no CPU model should be reported as an alias: - for name,c in cpus.items(): - self.assertNotIn('alias-of', c, "%s shouldn't be an alias" % (name)) - - def test_4_1_alias(self): - """ - Check if unversioned CPU model is an alias pointing to right version - - :avocado: tags=machine:pc-i440fx-4.1 - """ - self.vm.add_args('-S') - self.vm.launch() - - cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions')) - - self.assertFalse(cpus['Cascadelake-Server']['static'], - 'unversioned Cascadelake-Server CPU model must not be static') - self.assertEquals(cpus['Cascadelake-Server'].get('alias-of'), 'Cascadelake-Server-v1', - 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') - self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], - 'Cascadelake-Server-v1 must not be an alias') - - self.assertFalse(cpus['qemu64']['static'], - 'unversioned qemu64 CPU model must not be static') - self.assertEquals(cpus['qemu64'].get('alias-of'), 'qemu64-v1', - 'qemu64 must be an alias of qemu64-v1') - self.assertNotIn('alias-of', cpus['qemu64-v1'], - 'qemu64-v1 must not be an alias') - - self.validate_variant_aliases(cpus) - - # On pc-*-4.1, -noTSX and -IBRS models should be aliases: - self.assertEquals(cpus["Haswell"].get('alias-of'), - "Haswell-v1", - "Haswell must be an alias") - self.assertEquals(cpus["Haswell-noTSX"].get('alias-of'), - "Haswell-v2", - "Haswell-noTSX must be an alias") - self.assertEquals(cpus["Haswell-IBRS"].get('alias-of'), - "Haswell-v3", - "Haswell-IBRS must be an alias") - self.assertEquals(cpus["Haswell-noTSX-IBRS"].get('alias-of'), - "Haswell-v4", - "Haswell-noTSX-IBRS must be an alias") - - self.assertEquals(cpus["Broadwell"].get('alias-of'), - "Broadwell-v1", - "Broadwell must be an alias") - self.assertEquals(cpus["Broadwell-noTSX"].get('alias-of'), - "Broadwell-v2", - "Broadwell-noTSX must be an alias") - self.assertEquals(cpus["Broadwell-IBRS"].get('alias-of'), - "Broadwell-v3", - "Broadwell-IBRS must be an alias") - self.assertEquals(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), - "Broadwell-v4", - "Broadwell-noTSX-IBRS must be an alias") - - self.assertEquals(cpus["Nehalem"].get('alias-of'), - "Nehalem-v1", - "Nehalem must be an alias") - self.assertEquals(cpus["Nehalem-IBRS"].get('alias-of'), - "Nehalem-v2", - "Nehalem-IBRS must be an alias") - - self.assertEquals(cpus["Westmere"].get('alias-of'), - "Westmere-v1", - "Westmere must be an alias") - self.assertEquals(cpus["Westmere-IBRS"].get('alias-of'), - "Westmere-v2", - "Westmere-IBRS must be an alias") - - self.assertEquals(cpus["SandyBridge"].get('alias-of'), - "SandyBridge-v1", - "SandyBridge must be an alias") - self.assertEquals(cpus["SandyBridge-IBRS"].get('alias-of'), - "SandyBridge-v2", - "SandyBridge-IBRS must be an alias") - - self.assertEquals(cpus["IvyBridge"].get('alias-of'), - "IvyBridge-v1", - "IvyBridge must be an alias") - self.assertEquals(cpus["IvyBridge-IBRS"].get('alias-of'), - "IvyBridge-v2", - "IvyBridge-IBRS must be an alias") - - self.assertEquals(cpus["Skylake-Client"].get('alias-of'), - "Skylake-Client-v1", - "Skylake-Client must be an alias") - self.assertEquals(cpus["Skylake-Client-IBRS"].get('alias-of'), - "Skylake-Client-v2", - "Skylake-Client-IBRS must be an alias") - - self.assertEquals(cpus["Skylake-Server"].get('alias-of'), - "Skylake-Server-v1", - "Skylake-Server must be an alias") - self.assertEquals(cpus["Skylake-Server-IBRS"].get('alias-of'), - "Skylake-Server-v2", - "Skylake-Server-IBRS must be an alias") - - self.assertEquals(cpus["EPYC"].get('alias-of'), - "EPYC-v1", - "EPYC must be an alias") - self.assertEquals(cpus["EPYC-IBPB"].get('alias-of'), - "EPYC-v2", - "EPYC-IBPB must be an alias") - - self.validate_aliases(cpus) - - def test_none_alias(self): - """ - Check if unversioned CPU model is an alias pointing to some version - - :avocado: tags=machine:none - """ - self.vm.add_args('-S') - self.vm.launch() - - cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions')) - - self.assertFalse(cpus['Cascadelake-Server']['static'], - 'unversioned Cascadelake-Server CPU model must not be static') - self.assertTrue(re.match('Cascadelake-Server-v[0-9]+', cpus['Cascadelake-Server']['alias-of']), - 'Cascadelake-Server must be an alias of versioned CPU model') - self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], - 'Cascadelake-Server-v1 must not be an alias') - - self.assertFalse(cpus['qemu64']['static'], - 'unversioned qemu64 CPU model must not be static') - self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']), - 'qemu64 must be an alias of versioned CPU model') - self.assertNotIn('alias-of', cpus['qemu64-v1'], - 'qemu64-v1 must not be an alias') - - self.validate_aliases(cpus) - - -class CascadelakeArchCapabilities(avocado_qemu.Test): - """ - Validation of Cascadelake arch-capabilities - - :avocado: tags=arch:x86_64 - """ - def get_cpu_prop(self, prop): - cpu_path = self.vm.command('query-cpus-fast')[0].get('qom-path') - return self.vm.command('qom-get', path=cpu_path, property=prop) - - def test_4_1(self): - """ - :avocado: tags=machine:pc-i440fx-4.1 - :avocado: tags=cpu:Cascadelake-Server - """ - # machine-type only: - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server,x-force-features=on,check=off,' - 'enforce=off') - self.vm.launch() - self.assertFalse(self.get_cpu_prop('arch-capabilities'), - 'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities') - - def test_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server,x-force-features=on,check=off,' - 'enforce=off') - self.vm.launch() - self.assertFalse(self.get_cpu_prop('arch-capabilities'), - 'pc-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities') - - def test_set_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ - # command line must override machine-type if CPU model is not versioned: - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server,x-force-features=on,check=off,' - 'enforce=off,+arch-capabilities') - self.vm.launch() - self.assertTrue(self.get_cpu_prop('arch-capabilities'), - 'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities') - - def test_unset_4_1(self): - """ - :avocado: tags=machine:pc-i440fx-4.1 - :avocado: tags=cpu:Cascadelake-Server - """ - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server,x-force-features=on,check=off,' - 'enforce=off,-arch-capabilities') - self.vm.launch() - self.assertFalse(self.get_cpu_prop('arch-capabilities'), - 'pc-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') - - def test_v1_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ - # versioned CPU model overrides machine-type: - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server-v1,x-force-features=on,check=off,' - 'enforce=off') - self.vm.launch() - self.assertFalse(self.get_cpu_prop('arch-capabilities'), - 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not have arch-capabilities') - - def test_v2_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server-v2,x-force-features=on,check=off,' - 'enforce=off') - self.vm.launch() - self.assertTrue(self.get_cpu_prop('arch-capabilities'), - 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have arch-capabilities') - - def test_v1_set_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ - # command line must override machine-type and versioned CPU model: - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server-v1,x-force-features=on,check=off,' - 'enforce=off,+arch-capabilities') - self.vm.launch() - self.assertTrue(self.get_cpu_prop('arch-capabilities'), - 'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities') - - def test_v2_unset_4_1(self): - """ - :avocado: tags=machine:pc-i440fx-4.1 - :avocado: tags=cpu:Cascadelake-Server - """ - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server-v2,x-force-features=on,check=off,' - 'enforce=off,-arch-capabilities') - self.vm.launch() - self.assertFalse(self.get_cpu_prop('arch-capabilities'), - 'pc-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') diff --git a/tests/avocado/README.rst b/tests/avocado/README.rst new file mode 100644 index 0000000000..94488371bb --- /dev/null +++ b/tests/avocado/README.rst @@ -0,0 +1,10 @@ +============================================= +Integration tests using the Avocado Framework +============================================= + +This directory contains integration tests. They're usually higher +level, and may interact with external resources and with various +guest operating systems. + +For more information, please refer to ``docs/devel/testing.rst``, +section "Integration tests using the Avocado Framework". diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py new file mode 100644 index 0000000000..cd21b59e04 --- /dev/null +++ b/tests/avocado/avocado_qemu/__init__.py @@ -0,0 +1,558 @@ +# Test class and utilities for functional tests +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import logging +import os +import shutil +import sys +import tempfile +import time +import uuid + +import avocado +from avocado.utils import cloudinit, datadrainer, network, ssh, vmimage +from avocado.utils.path import find_command + +#: The QEMU build root directory. It may also be the source directory +#: if building from the source dir, but it's safer to use BUILD_DIR for +#: that purpose. Be aware that if this code is moved outside of a source +#: and build tree, it will not be accurate. +BUILD_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) + +if os.path.islink(os.path.dirname(os.path.dirname(__file__))): + # The link to the avocado tests dir in the source code directory + lnk = os.path.dirname(os.path.dirname(__file__)) + #: The QEMU root source directory + SOURCE_DIR = os.path.dirname(os.path.dirname(os.readlink(lnk))) +else: + SOURCE_DIR = BUILD_DIR + +sys.path.append(os.path.join(SOURCE_DIR, 'python')) + +from qemu.machine import QEMUMachine +from qemu.utils import (get_info_usernet_hostfwd_port, kvm_available, + tcg_available) + + +def is_readable_executable_file(path): + return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK) + + +def pick_default_qemu_bin(arch=None): + """ + Picks the path of a QEMU binary, starting either in the current working + directory or in the source tree root directory. + + :param arch: the arch to use when looking for a QEMU binary (the target + will match the arch given). If None (the default), arch + will be the current host system arch (as given by + :func:`os.uname`). + :type arch: str + :returns: the path to the default QEMU binary or None if one could not + be found + :rtype: str or None + """ + if arch is None: + arch = os.uname()[4] + # qemu binary path does not match arch for powerpc, handle it + if 'ppc64le' in arch: + arch = 'ppc64' + qemu_bin_relative_path = "./qemu-system-%s" % arch + if is_readable_executable_file(qemu_bin_relative_path): + return qemu_bin_relative_path + + qemu_bin_from_bld_dir_path = os.path.join(BUILD_DIR, + qemu_bin_relative_path) + if is_readable_executable_file(qemu_bin_from_bld_dir_path): + return qemu_bin_from_bld_dir_path + return None + + +def _console_interaction(test, success_message, failure_message, + send_string, keep_sending=False, vm=None): + assert not keep_sending or send_string + if vm is None: + vm = test.vm + console = vm.console_socket.makefile(mode='rb', encoding='utf-8') + console_logger = logging.getLogger('console') + while True: + if send_string: + vm.console_socket.sendall(send_string.encode()) + if not keep_sending: + send_string = None # send only once + try: + msg = console.readline().decode().strip() + except UnicodeDecodeError: + msg = None + if not msg: + continue + console_logger.debug(msg) + if success_message is None or success_message in msg: + break + if failure_message and failure_message in msg: + console.close() + fail = 'Failure message found in console: "%s". Expected: "%s"' % \ + (failure_message, success_message) + test.fail(fail) + +def interrupt_interactive_console_until_pattern(test, success_message, + failure_message=None, + interrupt_string='\r'): + """ + Keep sending a string to interrupt a console prompt, while logging the + console output. Typical use case is to break a boot loader prompt, such: + + Press a key within 5 seconds to interrupt boot process. + 5 + 4 + 3 + 2 + 1 + Booting default image... + + :param test: an Avocado test containing a VM that will have its console + read and probed for a success or failure message + :type test: :class:`avocado_qemu.Test` + :param success_message: if this message appears, test succeeds + :param failure_message: if this message appears, test fails + :param interrupt_string: a string to send to the console before trying + to read a new line + """ + _console_interaction(test, success_message, failure_message, + interrupt_string, True) + +def wait_for_console_pattern(test, success_message, failure_message=None, + vm=None): + """ + Waits for messages to appear on the console, while logging the content + + :param test: an Avocado test containing a VM that will have its console + read and probed for a success or failure message + :type test: :class:`avocado_qemu.Test` + :param success_message: if this message appears, test succeeds + :param failure_message: if this message appears, test fails + """ + _console_interaction(test, success_message, failure_message, None, vm=vm) + +def exec_command(test, command): + """ + Send a command to a console (appending CRLF characters), while logging + the content. + + :param test: an Avocado test containing a VM. + :type test: :class:`avocado_qemu.Test` + :param command: the command to send + :type command: str + """ + _console_interaction(test, None, None, command + '\r') + +def exec_command_and_wait_for_pattern(test, command, + success_message, failure_message=None): + """ + Send a command to a console (appending CRLF characters), then wait + for success_message to appear on the console, while logging the. + content. Mark the test as failed if failure_message is found instead. + + :param test: an Avocado test containing a VM that will have its console + read and probed for a success or failure message + :type test: :class:`avocado_qemu.Test` + :param command: the command to send + :param success_message: if this message appears, test succeeds + :param failure_message: if this message appears, test fails + """ + _console_interaction(test, success_message, failure_message, command + '\r') + +class Test(avocado.Test): + def _get_unique_tag_val(self, tag_name): + """ + Gets a tag value, if unique for a key + """ + vals = self.tags.get(tag_name, []) + if len(vals) == 1: + return vals.pop() + return None + + def require_accelerator(self, accelerator): + """ + Requires an accelerator to be available for the test to continue + + It takes into account the currently set qemu binary. + + If the check fails, the test is canceled. If the check itself + for the given accelerator is not available, the test is also + canceled. + + :param accelerator: name of the accelerator, such as "kvm" or "tcg" + :type accelerator: str + """ + checker = {'tcg': tcg_available, + 'kvm': kvm_available}.get(accelerator) + if checker is None: + self.cancel("Don't know how to check for the presence " + "of accelerator %s" % accelerator) + if not checker(qemu_bin=self.qemu_bin): + self.cancel("%s accelerator does not seem to be " + "available" % accelerator) + + def setUp(self): + self._vms = {} + + self.arch = self.params.get('arch', + default=self._get_unique_tag_val('arch')) + + self.cpu = self.params.get('cpu', + default=self._get_unique_tag_val('cpu')) + + self.machine = self.params.get('machine', + default=self._get_unique_tag_val('machine')) + + default_qemu_bin = pick_default_qemu_bin(arch=self.arch) + self.qemu_bin = self.params.get('qemu_bin', + default=default_qemu_bin) + if self.qemu_bin is None: + self.cancel("No QEMU binary defined or found in the build tree") + + def _new_vm(self, name, *args): + self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") + vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir, + sock_dir=self._sd.name, log_dir=self.logdir) + self.log.debug('QEMUMachine "%s" created', name) + self.log.debug('QEMUMachine "%s" temp_dir: %s', name, vm.temp_dir) + self.log.debug('QEMUMachine "%s" log_dir: %s', name, vm.log_dir) + if args: + vm.add_args(*args) + return vm + + @property + def vm(self): + return self.get_vm(name='default') + + def get_vm(self, *args, name=None): + if not name: + name = str(uuid.uuid4()) + if self._vms.get(name) is None: + self._vms[name] = self._new_vm(name, *args) + if self.cpu is not None: + self._vms[name].add_args('-cpu', self.cpu) + if self.machine is not None: + self._vms[name].set_machine(self.machine) + return self._vms[name] + + def set_vm_arg(self, arg, value): + """ + Set an argument to list of extra arguments to be given to the QEMU + binary. If the argument already exists then its value is replaced. + + :param arg: the QEMU argument, such as "-cpu" in "-cpu host" + :type arg: str + :param value: the argument value, such as "host" in "-cpu host" + :type value: str + """ + if not arg or not value: + return + if arg not in self.vm.args: + self.vm.args.extend([arg, value]) + else: + idx = self.vm.args.index(arg) + 1 + if idx < len(self.vm.args): + self.vm.args[idx] = value + else: + self.vm.args.append(value) + + def tearDown(self): + for vm in self._vms.values(): + vm.shutdown() + self._sd = None + super().tearDown() + + def fetch_asset(self, name, + asset_hash=None, algorithm=None, + locations=None, expire=None, + find_only=False, cancel_on_missing=True): + return super().fetch_asset(name, + asset_hash=asset_hash, + algorithm=algorithm, + locations=locations, + expire=expire, + find_only=find_only, + cancel_on_missing=cancel_on_missing) + + +class LinuxSSHMixIn: + """Contains utility methods for interacting with a guest via SSH.""" + + def ssh_connect(self, username, credential, credential_is_key=True): + self.ssh_logger = logging.getLogger('ssh') + res = self.vm.command('human-monitor-command', + command_line='info usernet') + port = get_info_usernet_hostfwd_port(res) + self.assertIsNotNone(port) + self.assertGreater(port, 0) + self.log.debug('sshd listening on port: %d', port) + if credential_is_key: + self.ssh_session = ssh.Session('127.0.0.1', port=port, + user=username, key=credential) + else: + self.ssh_session = ssh.Session('127.0.0.1', port=port, + user=username, password=credential) + for i in range(10): + try: + self.ssh_session.connect() + return + except: + time.sleep(i) + self.fail('ssh connection timeout') + + def ssh_command(self, command): + self.ssh_logger.info(command) + result = self.ssh_session.cmd(command) + stdout_lines = [line.rstrip() for line + in result.stdout_text.splitlines()] + for line in stdout_lines: + self.ssh_logger.info(line) + stderr_lines = [line.rstrip() for line + in result.stderr_text.splitlines()] + for line in stderr_lines: + self.ssh_logger.warning(line) + + self.assertEqual(result.exit_status, 0, + f'Guest command failed: {command}') + return stdout_lines, stderr_lines + +class LinuxDistro: + """Represents a Linux distribution + + Holds information of known distros. + """ + #: A collection of known distros and their respective image checksum + KNOWN_DISTROS = { + 'fedora': { + '31': { + 'x86_64': + {'checksum': ('e3c1b309d9203604922d6e255c2c5d09' + '8a309c2d46215d8fc026954f3c5c27a0'), + 'pxeboot_url': ('https://archives.fedoraproject.org/' + 'pub/archive/fedora/linux/releases/31/' + 'Everything/x86_64/os/images/pxeboot/'), + 'kernel_params': ('root=UUID=b1438b9b-2cab-4065-a99a-' + '08a96687f73c ro no_timer_check ' + 'net.ifnames=0 console=tty1 ' + 'console=ttyS0,115200n8'), + }, + 'aarch64': + {'checksum': ('1e18d9c0cf734940c4b5d5ec592facae' + 'd2af0ad0329383d5639c997fdf16fe49'), + 'pxeboot_url': 'https://archives.fedoraproject.org/' + 'pub/archive/fedora/linux/releases/31/' + 'Everything/aarch64/os/images/pxeboot/', + 'kernel_params': ('root=UUID=b6950a44-9f3c-4076-a9c2-' + '355e8475b0a7 ro earlyprintk=pl011,0x9000000' + ' ignore_loglevel no_timer_check' + ' printk.time=1 rd_NO_PLYMOUTH' + ' console=ttyAMA0'), + }, + 'ppc64': + {'checksum': ('7c3528b85a3df4b2306e892199a9e1e4' + '3f991c506f2cc390dc4efa2026ad2f58')}, + 's390x': + {'checksum': ('4caaab5a434fd4d1079149a072fdc789' + '1e354f834d355069ca982fdcaf5a122d')}, + }, + '32': { + 'aarch64': + {'checksum': ('b367755c664a2d7a26955bbfff985855' + 'adfa2ca15e908baf15b4b176d68d3967'), + 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/' + 'releases/32/Server/aarch64/os/images/' + 'pxeboot/'), + 'kernel_params': ('root=UUID=3df75b65-be8d-4db4-8655-' + '14d95c0e90c5 ro no_timer_check net.ifnames=0' + ' console=tty1 console=ttyS0,115200n8'), + }, + }, + '33': { + 'aarch64': + {'checksum': ('e7f75cdfd523fe5ac2ca9eeece68edc1' + 'a81f386a17f969c1d1c7c87031008a6b'), + 'pxeboot_url': ('http://dl.fedoraproject.org/pub/fedora/linux/' + 'releases/33/Server/aarch64/os/images/' + 'pxeboot/'), + 'kernel_params': ('root=UUID=d20b3ffa-6397-4a63-a734-' + '1126a0208f8a ro no_timer_check net.ifnames=0' + ' console=tty1 console=ttyS0,115200n8' + ' console=tty0'), + }, + }, + } + } + + def __init__(self, name, version, arch): + self.name = name + self.version = version + self.arch = arch + try: + info = self.KNOWN_DISTROS.get(name).get(version).get(arch) + except AttributeError: + # Unknown distro + info = None + self._info = info or {} + + @property + def checksum(self): + """Gets the cloud-image file checksum""" + return self._info.get('checksum', None) + + @checksum.setter + def checksum(self, value): + self._info['checksum'] = value + + @property + def pxeboot_url(self): + """Gets the repository url where pxeboot files can be found""" + return self._info.get('pxeboot_url', None) + + @property + def default_kernel_params(self): + """Gets the default kernel parameters""" + return self._info.get('kernel_params', None) + + +class LinuxTest(LinuxSSHMixIn, Test): + """Facilitates having a cloud-image Linux based available. + + For tests that indend to interact with guests, this is a better choice + to start with than the more vanilla `Test` class. + """ + + timeout = 900 + distro = None + username = 'root' + password = 'password' + + def _set_distro(self): + distro_name = self.params.get( + 'distro', + default=self._get_unique_tag_val('distro')) + if not distro_name: + distro_name = 'fedora' + + distro_version = self.params.get( + 'distro_version', + default=self._get_unique_tag_val('distro_version')) + if not distro_version: + distro_version = '31' + + self.distro = LinuxDistro(distro_name, distro_version, self.arch) + + # The distro checksum behaves differently than distro name and + # version. First, it does not respect a tag with the same + # name, given that it's not expected to be used for filtering + # (distro name versions are the natural choice). Second, the + # order of precedence is: parameter, attribute and then value + # from KNOWN_DISTROS. + distro_checksum = self.params.get('distro_checksum', + default=None) + if distro_checksum: + self.distro.checksum = distro_checksum + + def setUp(self, ssh_pubkey=None, network_device_type='virtio-net'): + super().setUp() + self._set_distro() + self.vm.add_args('-smp', '2') + self.vm.add_args('-m', '1024') + # The following network device allows for SSH connections + self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', + '-device', '%s,netdev=vnet' % network_device_type) + self.set_up_boot() + if ssh_pubkey is None: + ssh_pubkey, self.ssh_key = self.set_up_existing_ssh_keys() + self.set_up_cloudinit(ssh_pubkey) + + def set_up_existing_ssh_keys(self): + ssh_public_key = os.path.join(SOURCE_DIR, 'tests', 'keys', 'id_rsa.pub') + source_private_key = os.path.join(SOURCE_DIR, 'tests', 'keys', 'id_rsa') + ssh_dir = os.path.join(self.workdir, '.ssh') + os.mkdir(ssh_dir, mode=0o700) + ssh_private_key = os.path.join(ssh_dir, + os.path.basename(source_private_key)) + shutil.copyfile(source_private_key, ssh_private_key) + os.chmod(ssh_private_key, 0o600) + return (ssh_public_key, ssh_private_key) + + def download_boot(self): + self.log.debug('Looking for and selecting a qemu-img binary to be ' + 'used to create the bootable snapshot image') + # If qemu-img has been built, use it, otherwise the system wide one + # will be used. If none is available, the test will cancel. + qemu_img = os.path.join(BUILD_DIR, 'qemu-img') + if not os.path.exists(qemu_img): + qemu_img = find_command('qemu-img', False) + if qemu_img is False: + self.cancel('Could not find "qemu-img", which is required to ' + 'create the bootable image') + vmimage.QEMU_IMG = qemu_img + + self.log.info('Downloading/preparing boot image') + # Fedora 31 only provides ppc64le images + image_arch = self.arch + if self.distro.name == 'fedora': + if image_arch == 'ppc64': + image_arch = 'ppc64le' + + try: + boot = vmimage.get( + self.distro.name, arch=image_arch, version=self.distro.version, + checksum=self.distro.checksum, + algorithm='sha256', + cache_dir=self.cache_dirs[0], + snapshot_dir=self.workdir) + except: + self.cancel('Failed to download/prepare boot image') + return boot.path + + def prepare_cloudinit(self, ssh_pubkey=None): + self.log.info('Preparing cloudinit image') + try: + cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso') + self.phone_home_port = network.find_free_port() + pubkey_content = None + if ssh_pubkey: + with open(ssh_pubkey) as pubkey: + pubkey_content = pubkey.read() + cloudinit.iso(cloudinit_iso, self.name, + username=self.username, + password=self.password, + # QEMU's hard coded usermode router address + phone_home_host='10.0.2.2', + phone_home_port=self.phone_home_port, + authorized_key=pubkey_content) + except Exception: + self.cancel('Failed to prepare the cloudinit image') + return cloudinit_iso + + def set_up_boot(self): + path = self.download_boot() + self.vm.add_args('-drive', 'file=%s' % path) + + def set_up_cloudinit(self, ssh_pubkey=None): + cloudinit_iso = self.prepare_cloudinit(ssh_pubkey) + self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso) + + def launch_and_wait(self, set_up_ssh_connection=True): + self.vm.set_console() + self.vm.launch() + console_drainer = datadrainer.LineLogger(self.vm.console_socket.fileno(), + logger=self.log.getChild('console')) + console_drainer.start() + self.log.info('VM launched, waiting for boot confirmation from guest') + cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), self.name) + if set_up_ssh_connection: + self.log.info('Setting up the SSH connection') + self.ssh_connect(self.username, self.ssh_key) diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py new file mode 100644 index 0000000000..ab19146d1e --- /dev/null +++ b/tests/avocado/boot_linux.py @@ -0,0 +1,138 @@ +# Functional test that boots a complete Linux system via a cloud image +# +# Copyright (c) 2018-2020 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os + +from avocado_qemu import LinuxTest, BUILD_DIR + +from avocado import skipIf + + +class BootLinuxX8664(LinuxTest): + """ + :avocado: tags=arch:x86_64 + """ + + def test_pc_i440fx_tcg(self): + """ + :avocado: tags=machine:pc + :avocado: tags=accel:tcg + """ + self.require_accelerator("tcg") + self.vm.add_args("-accel", "tcg") + self.launch_and_wait(set_up_ssh_connection=False) + + def test_pc_i440fx_kvm(self): + """ + :avocado: tags=machine:pc + :avocado: tags=accel:kvm + """ + self.require_accelerator("kvm") + self.vm.add_args("-accel", "kvm") + self.launch_and_wait(set_up_ssh_connection=False) + + def test_pc_q35_tcg(self): + """ + :avocado: tags=machine:q35 + :avocado: tags=accel:tcg + """ + self.require_accelerator("tcg") + self.vm.add_args("-accel", "tcg") + self.launch_and_wait(set_up_ssh_connection=False) + + def test_pc_q35_kvm(self): + """ + :avocado: tags=machine:q35 + :avocado: tags=accel:kvm + """ + self.require_accelerator("kvm") + self.vm.add_args("-accel", "kvm") + self.launch_and_wait(set_up_ssh_connection=False) + + +class BootLinuxAarch64(LinuxTest): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=machine:gic-version=2 + """ + + def add_common_args(self): + self.vm.add_args('-bios', + os.path.join(BUILD_DIR, 'pc-bios', + 'edk2-aarch64-code.fd')) + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom') + + def test_virt_tcg_gicv2(self): + """ + :avocado: tags=accel:tcg + :avocado: tags=cpu:max + :avocado: tags=device:gicv2 + """ + self.require_accelerator("tcg") + self.vm.add_args("-accel", "tcg") + self.vm.add_args("-machine", "virt,gic-version=2") + self.add_common_args() + self.launch_and_wait(set_up_ssh_connection=False) + + def test_virt_tcg_gicv3(self): + """ + :avocado: tags=accel:tcg + :avocado: tags=cpu:max + :avocado: tags=device:gicv3 + """ + self.require_accelerator("tcg") + self.vm.add_args("-accel", "tcg") + self.vm.add_args("-machine", "virt,gic-version=3") + self.add_common_args() + self.launch_and_wait(set_up_ssh_connection=False) + + def test_virt_kvm(self): + """ + :avocado: tags=accel:kvm + :avocado: tags=cpu:host + """ + self.require_accelerator("kvm") + self.vm.add_args("-accel", "kvm") + self.vm.add_args("-machine", "virt,gic-version=host") + self.add_common_args() + self.launch_and_wait(set_up_ssh_connection=False) + + +class BootLinuxPPC64(LinuxTest): + """ + :avocado: tags=arch:ppc64 + """ + + def test_pseries_tcg(self): + """ + :avocado: tags=machine:pseries + :avocado: tags=accel:tcg + """ + self.require_accelerator("tcg") + self.vm.add_args("-accel", "tcg") + self.launch_and_wait(set_up_ssh_connection=False) + + +class BootLinuxS390X(LinuxTest): + """ + :avocado: tags=arch:s390x + """ + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_s390_ccw_virtio_tcg(self): + """ + :avocado: tags=machine:s390-ccw-virtio + :avocado: tags=accel:tcg + """ + self.require_accelerator("tcg") + self.vm.add_args("-accel", "tcg") + self.launch_and_wait(set_up_ssh_connection=False) diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py new file mode 100644 index 0000000000..06fc967f6c --- /dev/null +++ b/tests/avocado/boot_linux_console.py @@ -0,0 +1,1256 @@ +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import lzma +import gzip +import shutil + +from avocado import skip +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import exec_command +from avocado_qemu import exec_command_and_wait_for_pattern +from avocado_qemu import interrupt_interactive_console_until_pattern +from avocado_qemu import wait_for_console_pattern +from avocado.utils import process +from avocado.utils import archive +from avocado.utils.path import find_command, CmdNotFoundError + +P7ZIP_AVAILABLE = True +try: + find_command('7z') +except CmdNotFoundError: + P7ZIP_AVAILABLE = False + +""" +Round up to next power of 2 +""" +def pow2ceil(x): + return 1 if x == 0 else 2**(x - 1).bit_length() + +""" +Expand file size to next power of 2 +""" +def image_pow2ceil_expand(path): + size = os.path.getsize(path) + size_aligned = pow2ceil(size) + if size != size_aligned: + with open(path, 'ab+') as fd: + fd.truncate(size_aligned) + +class LinuxKernelTest(Test): + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern(self, success_message, + failure_message='Kernel panic - not syncing', + vm=vm) + + def extract_from_deb(self, deb, path): + """ + Extracts a file from a deb package into the test workdir + + :param deb: path to the deb archive + :param path: path within the deb archive of the file to be extracted + :returns: path of the extracted file + """ + cwd = os.getcwd() + os.chdir(self.workdir) + file_path = process.run("ar t %s" % deb).stdout_text.split()[2] + process.run("ar x %s %s" % (deb, file_path)) + archive.extract(file_path, self.workdir) + os.chdir(cwd) + # Return complete path to extracted file. Because callers to + # extract_from_deb() specify 'path' with a leading slash, it is + # necessary to use os.path.relpath() as otherwise os.path.join() + # interprets it as an absolute path and drops the self.workdir part. + return os.path.normpath(os.path.join(self.workdir, + os.path.relpath(path, '/'))) + + def extract_from_rpm(self, rpm, path): + """ + Extracts a file from an RPM package into the test workdir. + + :param rpm: path to the rpm archive + :param path: path within the rpm archive of the file to be extracted + needs to be a relative path (starting with './') because + cpio(1), which is used to extract the file, expects that. + :returns: path of the extracted file + """ + cwd = os.getcwd() + os.chdir(self.workdir) + process.run("rpm2cpio %s | cpio -id %s" % (rpm, path), shell=True) + os.chdir(cwd) + return os.path.normpath(os.path.join(self.workdir, path)) + +class BootLinuxConsole(LinuxKernelTest): + """ + Boots a Linux kernel and checks that the console is operational and the + kernel command line is properly passed from QEMU to the kernel + """ + timeout = 90 + + def test_x86_64_pc(self): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=machine:pc + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/x86_64/os/images/pxeboot' + '/vmlinuz') + kernel_hash = '23bebd2680757891cf7adedb033532163a792495' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_mips_malta(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb') + deb_hash = 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-2.6.32-5-4kc-malta') + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_mips64el_malta(self): + """ + This test requires the ar tool to extract "data.tar.gz" from + the Debian package. + + The kernel can be rebuilt using this Debian kernel source [1] and + following the instructions on [2]. + + [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/ + #linux-source-2.6.32_2.6.32-48 + [2] https://kernel-team.pages.debian.net/kernel-handbook/ + ch-common-tasks.html#s-common-official + + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb') + deb_hash = '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-2.6.32-5-5kc-malta') + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_mips64el_fuloong2e(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:fuloong2e + :avocado: tags=endian:little + """ + deb_url = ('http://archive.debian.org/debian/pool/main/l/linux/' + 'linux-image-3.16.0-6-loongson-2e_3.16.56-1+deb8u1_mipsel.deb') + deb_hash = 'd04d446045deecf7b755ef576551de0c4184dd44' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-3.16.0-6-loongson-2e') + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_mips_malta_cpio(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20160601T041800Z/pool/main/l/linux/' + 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb') + deb_hash = 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-4.5.0-2-4kc-malta') + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' + 'mips/rootfs.cpio.gz') + initrd_hash = 'bf806e17009360a866bf537f6de66590de349a99' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = self.workdir + "rootfs.cpio" + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + + 'rdinit=/sbin/init noreboot') + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'BogoMIPS') + exec_command_and_wait_for_pattern(self, 'uname -a', + 'Debian') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_mips64el_malta_5KEc_cpio(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=cpu:5KEc + """ + kernel_url = ('https://github.com/philmd/qemu-testing-blob/' + 'raw/9ad2df38/mips/malta/mips64el/' + 'vmlinux-3.19.3.mtoman.20150408') + kernel_hash = '00d1d268fb9f7d8beda1de6bebcc46e884d71754' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + initrd_url = ('https://github.com/groeck/linux-build-test/' + 'raw/8584a59e/rootfs/' + 'mipsel64/rootfs.mipsel64r1.cpio.gz') + initrd_hash = '1dbb8a396e916847325284dbe2151167' + initrd_path_gz = self.fetch_asset(initrd_url, algorithm='md5', + asset_hash=initrd_hash) + initrd_path = self.workdir + "rootfs.cpio" + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + + 'rdinit=/sbin/init noreboot') + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + wait_for_console_pattern(self, 'Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'MIPS 5KE') + exec_command_and_wait_for_pattern(self, 'uname -a', + '3.19.3.mtoman.20150408') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + + def do_test_mips_malta32el_nanomips(self, kernel_url, kernel_hash): + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + kernel_path = self.workdir + "kernel" + with lzma.open(kernel_path_xz, 'rb') as f_in: + with open(kernel_path, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'mem=256m@@0x0 ' + + 'console=ttyS0') + self.vm.add_args('-no-reboot', + '-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_mips_malta32el_nanomips_4k(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=cpu:I7200 + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page4k.xz') + kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6' + self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash) + + def test_mips_malta32el_nanomips_16k_up(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=cpu:I7200 + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page16k_up.xz') + kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc' + self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash) + + def test_mips_malta32el_nanomips_64k_dbg(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=cpu:I7200 + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page64k_dbg.xz') + kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180' + self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash) + + def test_aarch64_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=accel:tcg + :avocado: tags=cpu:cortex-a53 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/aarch64/os/images/pxeboot' + '/vmlinuz') + kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + self.require_accelerator("tcg") + self.vm.add_args('-cpu', 'cortex-a53', + '-accel', 'tcg', + '-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_aarch64_xlnx_versal_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:xlnx-versal-virt + :avocado: tags=device:pl011 + :avocado: tags=device:arm_gicv3 + :avocado: tags=accel:tcg + """ + images_url = ('http://ports.ubuntu.com/ubuntu-ports/dists/' + 'bionic-updates/main/installer-arm64/' + '20101020ubuntu543.15/images/') + kernel_url = images_url + 'netboot/ubuntu-installer/arm64/linux' + kernel_hash = '5bfc54cf7ed8157d93f6e5b0241e727b6dc22c50' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + initrd_url = images_url + 'netboot/ubuntu-installer/arm64/initrd.gz' + initrd_hash = 'd385d3e88d53e2004c5d43cbe668b458a094f772' + initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + + self.vm.set_console() + self.vm.add_args('-m', '2G', + '-accel', 'tcg', + '-kernel', kernel_path, + '-initrd', initrd_path) + self.vm.launch() + self.wait_for_console_pattern('Checked W+X mappings: passed') + + def test_arm_virt(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:virt + :avocado: tags=accel:tcg + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/armhfp/os/images/pxeboot' + '/vmlinuz') + kernel_hash = 'e9826d741b4fb04cadba8d4824d1ed3b7fb8b4d4' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_arm_emcraft_sf2(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:emcraft-sf2 + :avocado: tags=endian:little + :avocado: tags=u-boot + :avocado: tags=accel:tcg + """ + uboot_url = ('https://raw.githubusercontent.com/' + 'Subbaraya-Sundeep/qemu-test-binaries/' + 'fe371d32e50ca682391e1e70ab98c2942aeffb01/u-boot') + uboot_hash = 'cbb8cbab970f594bf6523b9855be209c08374ae2' + uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) + spi_url = ('https://raw.githubusercontent.com/' + 'Subbaraya-Sundeep/qemu-test-binaries/' + 'fe371d32e50ca682391e1e70ab98c2942aeffb01/spi.bin') + spi_hash = '65523a1835949b6f4553be96dec1b6a38fb05501' + spi_path = self.fetch_asset(spi_url, asset_hash=spi_hash) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + self.vm.add_args('-kernel', uboot_path, + '-append', kernel_command_line, + '-drive', 'file=' + spi_path + ',if=mtd,format=raw', + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Enter \'help\' for a list') + + exec_command_and_wait_for_pattern(self, 'ifconfig eth0 10.0.2.15', + 'eth0: link becomes ready') + exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', + '3 packets transmitted, 3 packets received, 0% packet loss') + + def do_test_arm_raspi2(self, uart_id): + """ + :avocado: tags=accel:tcg + + The kernel can be rebuilt using the kernel source referenced + and following the instructions on the on: + https://www.raspberrypi.org/documentation/linux/kernel/building.md + """ + serial_kernel_cmdline = { + 0: 'earlycon=pl011,0x3f201000 console=ttyAMA0', + } + deb_url = ('http://archive.raspberrypi.org/debian/' + 'pool/main/r/raspberrypi-firmware/' + 'raspberrypi-kernel_1.20190215-1_armhf.deb') + deb_hash = 'cd284220b32128c5084037553db3c482426f3972' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, '/boot/kernel7.img') + dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2709-rpi-2-b.dtb') + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + serial_kernel_cmdline[uart_id] + + ' root=/dev/mmcblk0p2 rootwait ' + + 'dwc_otg.fiq_fsm_enable=0') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-append', kernel_command_line, + '-device', 'usb-kbd') + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + console_pattern = 'Product: QEMU USB Keyboard' + self.wait_for_console_pattern(console_pattern) + + def test_arm_raspi2_uart0(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:raspi2b + :avocado: tags=device:pl011 + :avocado: tags=accel:tcg + """ + self.do_test_arm_raspi2(0) + + def test_arm_raspi2_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:raspi2b + """ + deb_url = ('http://archive.raspberrypi.org/debian/' + 'pool/main/r/raspberrypi-firmware/' + 'raspberrypi-kernel_1.20190215-1_armhf.deb') + deb_hash = 'cd284220b32128c5084037553db3c482426f3972' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, '/boot/kernel7.img') + dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2709-rpi-2-b.dtb') + + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv7a.cpio.gz') + initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'earlycon=pl011,0x3f201000 console=ttyAMA0 ' + 'panic=-1 noreboot ' + + 'dwc_otg.fiq_fsm_enable=0') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'BCM2835') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + '/soc/cprman@7e101000') + exec_command(self, 'halt') + # Wait for VM to shut down gracefully + self.vm.wait() + + def test_arm_exynos4210_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:smdkc210 + :avocado: tags=accel:tcg + """ + deb_url = ('https://snapshot.debian.org/archive/debian/' + '20190928T224601Z/pool/main/l/linux/' + 'linux-image-4.19.0-6-armmp_4.19.67-2+deb10u1_armhf.deb') + deb_hash = 'fa9df4a0d38936cb50084838f2cb933f570d7d82' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-4.19.0-6-armmp') + dtb_path = '/usr/lib/linux-image-4.19.0-6-armmp/exynos4210-smdkv310.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.cpio.gz') + initrd_hash = '2b50f1873e113523967806f4da2afe385462ff9b' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'earlycon=exynos4210,0x13800000 earlyprintk ' + + 'console=ttySAC0,115200n8 ' + + 'random.trust_cpu=off cryptomgr.notests ' + + 'cpuidle.off=1 panic=-1 noreboot') + + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + + self.wait_for_console_pattern('Boot successful.') + # TODO user command, for now the uart is stuck + + def test_arm_cubieboard_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:cubieboard + :avocado: tags=accel:tcg + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') + deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-5.10.16-sunxi') + dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.cpio.gz') + initrd_hash = '2b50f1873e113523967806f4da2afe385462ff9b' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun4i/sun5i') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + 'system-control@1c00000') + # cubieboard's reboot is not functioning; omit reboot test. + + def test_arm_cubieboard_sata(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:cubieboard + :avocado: tags=accel:tcg + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') + deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-5.10.16-sunxi') + dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + rootfs_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.ext2.gz') + rootfs_hash = '093e89d2b4d982234bf528bc9fb2f2f17a9d1f93' + rootfs_path_gz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash) + rootfs_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(rootfs_path_gz, rootfs_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'root=/dev/sda ro ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-drive', 'if=none,format=raw,id=disk0,file=' + + rootfs_path, + '-device', 'ide-hd,bus=ide.0,drive=disk0', + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun4i/sun5i') + exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', + 'sda') + # cubieboard's reboot is not functioning; omit reboot test. + + @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') + def test_arm_quanta_gsj(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:quanta-gsj + :avocado: tags=accel:tcg + """ + # 25 MiB compressed, 32 MiB uncompressed. + image_url = ( + 'https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz') + image_hash = '14895e634923345cb5c8776037ff7876df96f6b1' + image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash) + image_name = 'obmc.mtd' + image_path = os.path.join(self.workdir, image_name) + archive.gzip_uncompress(image_path_gz, image_path) + + self.vm.set_console() + drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0' + self.vm.add_args('-drive', drive_args) + self.vm.launch() + + # Disable drivers and services that stall for a long time during boot, + # to avoid running past the 90-second timeout. These may be removed + # as the corresponding device support is added. + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + ( + 'console=${console} ' + 'mem=${mem} ' + 'initcall_blacklist=npcm_i2c_bus_driver_init ' + 'systemd.mask=systemd-random-seed.service ' + 'systemd.mask=dropbearkey.service ' + ) + + self.wait_for_console_pattern('> BootBlock by Nuvoton') + self.wait_for_console_pattern('>Device: Poleg BMC NPCM730') + self.wait_for_console_pattern('>Skip DDR init.') + self.wait_for_console_pattern('U-Boot ') + interrupt_interactive_console_until_pattern( + self, 'Hit any key to stop autoboot:', 'U-Boot>') + exec_command_and_wait_for_pattern( + self, "setenv bootargs ${bootargs} " + kernel_command_line, + 'U-Boot>') + exec_command_and_wait_for_pattern( + self, 'run romboot', 'Booting Kernel from flash') + self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') + self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') + self.wait_for_console_pattern('OpenBMC Project Reference Distro') + self.wait_for_console_pattern('gsj login:') + + def test_arm_quanta_gsj_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:quanta-gsj + :avocado: tags=accel:tcg + """ + initrd_url = ( + 'https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz') + initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300' + initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + kernel_url = ( + 'https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/uImage-gsj.bin') + kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + dtb_url = ( + 'https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb') + dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4' + dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200n8 ' + 'earlycon=uart8250,mmio32,0xf0001000') + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-dtb', dtb_path, + '-append', kernel_command_line) + self.vm.launch() + + self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') + self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') + self.wait_for_console_pattern( + 'Give root password for system maintenance') + + def test_arm_orangepi(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:orangepi-pc + :avocado: tags=accel:tcg + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') + deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-5.10.16-sunxi') + dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200n8 ' + 'earlycon=uart,mmio32,0x1c28000') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_arm_orangepi_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=accel:tcg + :avocado: tags=machine:orangepi-pc + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') + deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-5.10.16-sunxi') + dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv7a.cpio.gz') + initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun8i Family') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + 'system-control@1c00000') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + + def test_arm_orangepi_sd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=accel:tcg + :avocado: tags=machine:orangepi-pc + :avocado: tags=device:sd + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') + deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-5.10.16-sunxi') + dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/' + 'kci-2019.02/armel/base/rootfs.ext2.xz') + rootfs_hash = '692510cb625efda31640d1de0a8d60e26040f061' + rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash) + rootfs_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.lzma_uncompress(rootfs_path_xz, rootfs_path) + image_pow2ceil_expand(rootfs_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'root=/dev/mmcblk0 rootwait rw ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-drive', 'file=' + rootfs_path + ',if=sd,format=raw', + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + shell_ready = "/bin/sh: can't access tty; job control turned off" + self.wait_for_console_pattern(shell_ready) + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun8i Family') + exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', + 'mmcblk0') + exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up', + 'eth0: Link is Up') + exec_command_and_wait_for_pattern(self, 'udhcpc eth0', + 'udhcpc: lease of 10.0.2.15 obtained') + exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', + '3 packets transmitted, 3 packets received, 0% packet loss') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + + @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited') + def test_arm_orangepi_bionic_20_08(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:orangepi-pc + :avocado: tags=device:sd + """ + + # This test download a 275 MiB compressed image and expand it + # to 1036 MiB, but the underlying filesystem is 1552 MiB... + # As we expand it to 2 GiB we are safe. + + image_url = ('https://archive.armbian.com/orangepipc/archive/' + 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz') + image_hash = ('b4d6775f5673486329e45a0586bf06b6' + 'dbe792199fd182ac6b9c7bb6c7d3e6dd') + image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash, + algorithm='sha256') + image_path = archive.extract(image_path_xz, self.workdir) + image_pow2ceil_expand(image_path) + + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', + '-nic', 'user', + '-no-reboot') + self.vm.launch() + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'loglevel=7 ' + 'nosmp ' + 'systemd.default_timeout_start_sec=9000 ' + 'systemd.mask=armbian-zram-config.service ' + 'systemd.mask=armbian-ramlog.service') + + self.wait_for_console_pattern('U-Boot SPL') + self.wait_for_console_pattern('Autoboot in ') + exec_command_and_wait_for_pattern(self, ' ', '=>') + exec_command_and_wait_for_pattern(self, "setenv extraargs '" + + kernel_command_line + "'", '=>') + exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...'); + + self.wait_for_console_pattern('systemd[1]: Set hostname ' + + 'to ') + self.wait_for_console_pattern('Starting Load Kernel Modules...') + + @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited') + def test_arm_orangepi_uboot_netbsd9(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:orangepi-pc + :avocado: tags=device:sd + :avocado: tags=os:netbsd + """ + # This test download a 304MB compressed image and expand it to 2GB + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20200108T145233Z/pool/main/u/u-boot/' + 'u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb') + deb_hash = 'f67f404a80753ca3d1258f13e38f2b060e13db99' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + # We use the common OrangePi PC 'plus' build of U-Boot for our secondary + # program loader (SPL). We will then set the path to the more specific + # OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt, + # before to boot NetBSD. + uboot_path = '/usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin' + uboot_path = self.extract_from_deb(deb_path, uboot_path) + image_url = ('https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/' + 'evbarm-earmv7hf/binary/gzimg/armv7.img.gz') + image_hash = '2babb29d36d8360adcb39c09e31060945259917a' + image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash) + image_path = os.path.join(self.workdir, 'armv7.img') + archive.gzip_uncompress(image_path_gz, image_path) + image_pow2ceil_expand(image_path) + image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path + + # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc + with open(uboot_path, 'rb') as f_in: + with open(image_path, 'r+b') as f_out: + f_out.seek(8 * 1024) + shutil.copyfileobj(f_in, f_out) + + self.vm.set_console() + self.vm.add_args('-nic', 'user', + '-drive', image_drive_args, + '-global', 'allwinner-rtc.base-year=2000', + '-no-reboot') + self.vm.launch() + wait_for_console_pattern(self, 'U-Boot 2020.01+dfsg-1') + interrupt_interactive_console_until_pattern(self, + 'Hit any key to stop autoboot:', + 'switch to partitions #0, OK') + + exec_command_and_wait_for_pattern(self, '', '=>') + cmd = 'setenv bootargs root=ld0a' + exec_command_and_wait_for_pattern(self, cmd, '=>') + cmd = 'setenv kernel netbsd-GENERIC.ub' + exec_command_and_wait_for_pattern(self, cmd, '=>') + cmd = 'setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb' + exec_command_and_wait_for_pattern(self, cmd, '=>') + cmd = ("setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; " + "fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; " + "fdt addr ${fdt_addr_r}; " + "bootm ${kernel_addr_r} - ${fdt_addr_r}'") + exec_command_and_wait_for_pattern(self, cmd, '=>') + + exec_command_and_wait_for_pattern(self, 'boot', + 'Booting kernel from Legacy Image') + wait_for_console_pattern(self, 'Starting kernel ...') + wait_for_console_pattern(self, 'NetBSD 9.0 (GENERIC)') + # Wait for user-space + wait_for_console_pattern(self, 'Starting root file system check') + + def test_aarch64_raspi3_atf(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:raspi3b + :avocado: tags=cpu:cortex-a53 + :avocado: tags=device:pl011 + :avocado: tags=atf + """ + zip_url = ('https://github.com/pbatard/RPi3/releases/download/' + 'v1.15/RPi3_UEFI_Firmware_v1.15.zip') + zip_hash = '74b3bd0de92683cadb14e008a7575e1d0c3cafb9' + zip_path = self.fetch_asset(zip_url, asset_hash=zip_hash) + + archive.extract(zip_path, self.workdir) + efi_fd = os.path.join(self.workdir, 'RPI_EFI.fd') + + self.vm.set_console(console_index=1) + self.vm.add_args('-nodefaults', + '-device', 'loader,file=%s,force-raw=true' % efi_fd) + self.vm.launch() + self.wait_for_console_pattern('version UEFI Firmware v1.15') + + def test_s390x_s390_ccw_virtio(self): + """ + :avocado: tags=arch:s390x + :avocado: tags=machine:s390-ccw-virtio + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/s390x/os/images' + '/kernel.img') + kernel_hash = 'e8e8439103ef8053418ef062644ffd46a7919313' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=sclp0' + self.vm.add_args('-nodefaults', + '-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_alpha_clipper(self): + """ + :avocado: tags=arch:alpha + :avocado: tags=machine:clipper + """ + kernel_url = ('http://archive.debian.org/debian/dists/lenny/main/' + 'installer-alpha/20090123lenny10/images/cdrom/vmlinuz') + kernel_hash = '3a943149335529e2ed3e74d0d787b85fb5671ba3' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + uncompressed_kernel = archive.uncompress(kernel_path, self.workdir) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-nodefaults', + '-kernel', uncompressed_kernel, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_m68k_q800(self): + """ + :avocado: tags=arch:m68k + :avocado: tags=machine:q800 + """ + deb_url = ('https://snapshot.debian.org/archive/debian-ports' + '/20191021T083923Z/pool-m68k/main' + '/l/linux/kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb') + deb_hash = '044954bb9be4160a3ce81f8bc1b5e856b75cccd1' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-5.3.0-1-m68k') + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 vga=off') + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + console_pattern = 'No filesystem could mount root' + self.wait_for_console_pattern(console_pattern) + + def do_test_advcal_2018(self, day, tar_hash, kernel_name, console=0): + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day' + day + '.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + archive.extract(file_path, self.workdir) + self.vm.set_console(console_index=console) + self.vm.add_args('-kernel', + self.workdir + '/day' + day + '/' + kernel_name) + self.vm.launch() + self.wait_for_console_pattern('QEMU advent calendar') + + def test_arm_vexpressa9(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:vexpress-a9 + """ + tar_hash = '32b7677ce8b6f1471fb0059865f451169934245b' + self.vm.add_args('-dtb', self.workdir + '/day16/vexpress-v2p-ca9.dtb') + self.do_test_advcal_2018('16', tar_hash, 'winter.zImage') + + def test_arm_ast2400_palmetto_openbmc_v2_9_0(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:palmetto-bmc + """ + + image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' + 'obmc-phosphor-image-palmetto.static.mtd') + image_hash = ('3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d') + image_path = self.fetch_asset(image_url, asset_hash=image_hash, + algorithm='sha256') + + self.do_test_arm_aspeed(image_path) + + def test_arm_ast2500_romulus_openbmc_v2_9_0(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:romulus-bmc + """ + + image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' + 'obmc-phosphor-image-romulus.static.mtd') + image_hash = ('820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25') + image_path = self.fetch_asset(image_url, asset_hash=image_hash, + algorithm='sha256') + + self.do_test_arm_aspeed(image_path) + + def do_test_arm_aspeed(self, image): + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', + '-net', 'nic') + self.vm.launch() + + self.wait_for_console_pattern("U-Boot 2016.07") + self.wait_for_console_pattern("## Loading kernel from FIT Image at 20080000") + self.wait_for_console_pattern("Starting kernel ...") + self.wait_for_console_pattern("Booting Linux on physical CPU 0x0") + self.wait_for_console_pattern( + "aspeed-smc 1e620000.spi: read control register: 203b0641") + self.wait_for_console_pattern("ftgmac100 1e660000.ethernet eth0: irq ") + self.wait_for_console_pattern("systemd[1]: Set hostname to") + + def test_arm_ast2600_debian(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:tacoma-bmc + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20210302T203551Z/' + 'pool/main/l/linux/' + 'linux-image-5.10.0-3-armmp_5.10.13-1_armhf.deb') + deb_hash = 'db40d32fe39255d05482bea48d72467b67d6225bb2a2a4d6f618cb8976f1e09e' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash, + algorithm='sha256') + kernel_path = self.extract_from_deb(deb_path, '/boot/vmlinuz-5.10.0-3-armmp') + dtb_path = self.extract_from_deb(deb_path, + '/usr/lib/linux-image-5.10.0-3-armmp/aspeed-bmc-opp-tacoma.dtb') + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-net', 'nic') + self.vm.launch() + self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") + self.wait_for_console_pattern("SMP: Total of 2 processors activated") + self.wait_for_console_pattern("No filesystem could mount root") + + def test_m68k_mcf5208evb(self): + """ + :avocado: tags=arch:m68k + :avocado: tags=machine:mcf5208evb + """ + tar_hash = 'ac688fd00561a2b6ce1359f9ff6aa2b98c9a570c' + self.do_test_advcal_2018('07', tar_hash, 'sanity-clause.elf') + + def test_or1k_sim(self): + """ + :avocado: tags=arch:or1k + :avocado: tags=machine:or1k-sim + """ + tar_hash = '20334cdaf386108c530ff0badaecc955693027dd' + self.do_test_advcal_2018('20', tar_hash, 'vmlinux') + + def test_nios2_10m50(self): + """ + :avocado: tags=arch:nios2 + :avocado: tags=machine:10m50-ghrd + """ + tar_hash = 'e4251141726c412ac0407c5a6bceefbbff018918' + self.do_test_advcal_2018('14', tar_hash, 'vmlinux.elf') + + def test_ppc64_e500(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:ppce500 + :avocado: tags=cpu:e5500 + """ + tar_hash = '6951d86d644b302898da2fd701739c9406527fe1' + self.do_test_advcal_2018('19', tar_hash, 'uImage') + + def do_test_ppc64_powernv(self, proc): + images_url = ('https://github.com/open-power/op-build/releases/download/v2.7/') + + kernel_url = images_url + 'zImage.epapr' + kernel_hash = '0ab237df661727e5392cee97460e8674057a883c5f74381a128fa772588d45cd' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash, + algorithm='sha256') + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-append', 'console=tty0 console=hvc0', + '-device', 'pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0', + '-device', 'nvme,bus=pcie.2,addr=0x0,serial=1234', + '-device', 'e1000e,bus=bridge1,addr=0x3', + '-device', 'nec-usb-xhci,bus=bridge1,addr=0x2') + self.vm.launch() + + self.wait_for_console_pattern("CPU: " + proc + " generation processor") + self.wait_for_console_pattern("zImage starting: loaded") + self.wait_for_console_pattern("Run /init as init process") + self.wait_for_console_pattern("Creating 1 MTD partitions") + + def test_ppc_powernv8(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv8 + """ + self.do_test_ppc64_powernv('P8') + + def test_ppc_powernv9(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv9 + """ + self.do_test_ppc64_powernv('P9') + + def test_ppc_g3beige(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:g3beige + """ + tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' + self.vm.add_args('-M', 'graphics=off') + self.do_test_advcal_2018('15', tar_hash, 'invaders.elf') + + def test_ppc_mac99(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:mac99 + """ + tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' + self.vm.add_args('-M', 'graphics=off') + self.do_test_advcal_2018('15', tar_hash, 'invaders.elf') + + def test_sh4_r2d(self): + """ + :avocado: tags=arch:sh4 + :avocado: tags=machine:r2d + """ + tar_hash = 'fe06a4fd8ccbf2e27928d64472939d47829d4c7e' + self.vm.add_args('-append', 'console=ttySC1') + self.do_test_advcal_2018('09', tar_hash, 'zImage', console=1) + + def test_sparc_ss20(self): + """ + :avocado: tags=arch:sparc + :avocado: tags=machine:SS-20 + """ + tar_hash = 'b18550d5d61c7615d989a06edace051017726a9f' + self.do_test_advcal_2018('11', tar_hash, 'zImage.elf') + + def test_xtensa_lx60(self): + """ + :avocado: tags=arch:xtensa + :avocado: tags=machine:lx60 + :avocado: tags=cpu:dc233c + """ + tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34' + self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf') diff --git a/tests/avocado/boot_xen.py b/tests/avocado/boot_xen.py new file mode 100644 index 0000000000..fc2faeedb5 --- /dev/null +++ b/tests/avocado/boot_xen.py @@ -0,0 +1,116 @@ +# Functional test that boots a Xen hypervisor with a domU kernel and +# checks the console output is vaguely sane . +# +# Copyright (c) 2020 Linaro +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os + +from avocado_qemu import wait_for_console_pattern +from boot_linux_console import LinuxKernelTest + + +class BootXenBase(LinuxKernelTest): + """ + Boots a Xen hypervisor with a Linux DomU kernel. + """ + + timeout = 90 + XEN_COMMON_COMMAND_LINE = 'dom0_mem=128M loglvl=all guest_loglvl=all' + + def fetch_guest_kernel(self): + # Using my own built kernel - which works + kernel_url = ('https://fileserver.linaro.org/' + 's/JSsewXGZ6mqxPr5/download?path=%2F&files=' + 'linux-5.9.9-arm64-ajb') + kernel_sha1 = '4f92bc4b9f88d5ab792fa7a43a68555d344e1b83' + kernel_path = self.fetch_asset(kernel_url, + asset_hash=kernel_sha1) + + return kernel_path + + def launch_xen(self, xen_path): + """ + Launch Xen with a dom0 guest kernel + """ + self.log.info("launch with xen_path: %s", xen_path) + kernel_path = self.fetch_guest_kernel() + + self.vm.set_console() + + xen_command_line = self.XEN_COMMON_COMMAND_LINE + self.vm.add_args('-machine', 'virtualization=on', + '-m', '768', + '-kernel', xen_path, + '-append', xen_command_line, + '-device', + 'guest-loader,addr=0x47000000,kernel=%s,bootargs=console=hvc0' + % (kernel_path)) + + self.vm.launch() + + console_pattern = 'VFS: Cannot open root device' + wait_for_console_pattern(self, console_pattern, "Panic on CPU 0:") + + +class BootXen(BootXenBase): + + def test_arm64_xen_411_and_dom0(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=accel:tcg + :avocado: tags=cpu:cortex-a57 + :avocado: tags=machine:virt + """ + + # archive of file from https://deb.debian.org/debian/pool/main/x/xen/ + xen_url = ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/' + 'download?path=%2F&files=' + 'xen-hypervisor-4.11-arm64_4.11.4%2B37-g3263f257ca-1_arm64.deb') + xen_sha1 = '034e634d4416adbad1212d59b62bccdcda63e62a' + xen_deb = self.fetch_asset(xen_url, asset_hash=xen_sha1) + xen_path = self.extract_from_deb(xen_deb, "/boot/xen-4.11-arm64") + + self.launch_xen(xen_path) + + def test_arm64_xen_414_and_dom0(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=accel:tcg + :avocado: tags=cpu:cortex-a57 + :avocado: tags=machine:virt + """ + + # archive of file from https://deb.debian.org/debian/pool/main/x/xen/ + xen_url = ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/' + 'download?path=%2F&files=' + 'xen-hypervisor-4.14-arm64_4.14.0%2B80-gd101b417b7-1_arm64.deb') + xen_sha1 = 'b9d209dd689ed2b393e625303a225badefec1160' + xen_deb = self.fetch_asset(xen_url, asset_hash=xen_sha1) + xen_path = self.extract_from_deb(xen_deb, "/boot/xen-4.14-arm64") + + self.launch_xen(xen_path) + + def test_arm64_xen_415_and_dom0(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=accel:tcg + :avocado: tags=cpu:cortex-a57 + :avocado: tags=machine:virt + """ + + xen_url = ('https://fileserver.linaro.org/' + 's/JSsewXGZ6mqxPr5/download' + '?path=%2F&files=xen-upstream-4.15-unstable.deb') + xen_sha1 = 'fc191172b85cf355abb95d275a24cc0f6d6579d8' + xen_deb = self.fetch_asset(xen_url, asset_hash=xen_sha1) + xen_path = self.extract_from_deb(xen_deb, "/boot/xen-4.15-unstable") + + self.launch_xen(xen_path) diff --git a/tests/avocado/cpu_queries.py b/tests/avocado/cpu_queries.py new file mode 100644 index 0000000000..cc9e380cc7 --- /dev/null +++ b/tests/avocado/cpu_queries.py @@ -0,0 +1,34 @@ +# Sanity check of query-cpu-* results +# +# Copyright (c) 2019 Red Hat, Inc. +# +# Author: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado_qemu import Test + +class QueryCPUModelExpansion(Test): + """ + Run query-cpu-model-expansion for each CPU model, and validate results + """ + + def test(self): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=machine:none + """ + self.vm.add_args('-S') + self.vm.launch() + + cpus = self.vm.command('query-cpu-definitions') + for c in cpus: + self.log.info("Checking CPU: %s", c) + self.assertNotIn('', c['unavailable-features'], c['name']) + + for c in cpus: + model = {'name': c['name']} + e = self.vm.command('query-cpu-model-expansion', model=model, type='full') + self.assertEquals(e['model']['name'], c['name']) diff --git a/tests/avocado/empty_cpu_model.py b/tests/avocado/empty_cpu_model.py new file mode 100644 index 0000000000..a1e59e45e4 --- /dev/null +++ b/tests/avocado/empty_cpu_model.py @@ -0,0 +1,19 @@ +# Check for crash when using empty -cpu option +# +# Copyright (c) 2019 Red Hat, Inc. +# +# Author: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +from avocado_qemu import Test + +class EmptyCPUModel(Test): + def test(self): + self.vm.add_args('-S', '-display', 'none', '-machine', 'none', '-cpu', '') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty') diff --git a/tests/avocado/hotplug_cpu.py b/tests/avocado/hotplug_cpu.py new file mode 100644 index 0000000000..6374bf1b54 --- /dev/null +++ b/tests/avocado/hotplug_cpu.py @@ -0,0 +1,37 @@ +# Functional test that hotplugs a CPU and checks it on a Linux guest +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado_qemu import LinuxTest + + +class HotPlugCPU(LinuxTest): + + def test(self): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=machine:q35 + :avocado: tags=accel:kvm + """ + self.require_accelerator('kvm') + self.vm.add_args('-accel', 'kvm') + self.vm.add_args('-cpu', 'Haswell') + self.vm.add_args('-smp', '1,sockets=1,cores=2,threads=1,maxcpus=2') + self.launch_and_wait() + + self.ssh_command('test -e /sys/devices/system/cpu/cpu0') + with self.assertRaises(AssertionError): + self.ssh_command('test -e /sys/devices/system/cpu/cpu1') + + self.vm.command('device_add', + driver='Haswell-x86_64-cpu', + socket_id=0, + core_id=1, + thread_id=0) + self.ssh_command('test -e /sys/devices/system/cpu/cpu1') diff --git a/tests/avocado/info_usernet.py b/tests/avocado/info_usernet.py new file mode 100644 index 0000000000..9c1fd903a0 --- /dev/null +++ b/tests/avocado/info_usernet.py @@ -0,0 +1,29 @@ +# Test for the hmp command "info usernet" +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado_qemu import Test + +from qemu.utils import get_info_usernet_hostfwd_port + + +class InfoUsernet(Test): + + def test_hostfwd(self): + self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22') + self.vm.launch() + res = self.vm.command('human-monitor-command', + command_line='info usernet') + port = get_info_usernet_hostfwd_port(res) + self.assertIsNotNone(port, + ('"info usernet" output content does not seem to ' + 'contain the redirected port')) + self.assertGreater(port, 0, + ('Found a redirected port that is not greater than' + ' zero')) diff --git a/tests/avocado/intel_iommu.py b/tests/avocado/intel_iommu.py new file mode 100644 index 0000000000..474d62f6bf --- /dev/null +++ b/tests/avocado/intel_iommu.py @@ -0,0 +1,119 @@ +# INTEL_IOMMU Functional tests +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Eric Auger +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import os + +from avocado import skipIf +from avocado_qemu import LinuxTest + +@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') +class IntelIOMMU(LinuxTest): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=distro:fedora + :avocado: tags=distro_version:31 + :avocado: tags=machine:q35 + :avocado: tags=accel:kvm + :avocado: tags=intel_iommu + """ + + IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' + kernel_path = None + initrd_path = None + kernel_params = None + + def set_up_boot(self): + path = self.download_boot() + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,scsi=off,' + + 'drive=drv0,id=virtio-disk0,bootindex=1,' + 'werror=stop,rerror=stop' + self.IOMMU_ADDON) + self.vm.add_args('-device', 'virtio-gpu-pci' + self.IOMMU_ADDON) + self.vm.add_args('-drive', + 'file=%s,if=none,cache=writethrough,id=drv0' % path) + + def setUp(self): + super(IntelIOMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) + + def add_common_args(self): + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + + def common_vm_setup(self, custom_kernel=None): + self.require_accelerator("kvm") + self.add_common_args() + self.vm.add_args("-accel", "kvm") + + if custom_kernel is None: + return + + kernel_url = self.distro.pxeboot_url + 'vmlinuz' + initrd_url = self.distro.pxeboot_url + 'initrd.img' + self.kernel_path = self.fetch_asset(kernel_url) + self.initrd_path = self.fetch_asset(initrd_url) + + def run_and_check(self): + if self.kernel_path: + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-initrd', self.initrd_path) + self.launch_and_wait() + self.ssh_command('cat /proc/cmdline') + self.ssh_command('dmesg | grep -e DMAR -e IOMMU') + self.ssh_command('find /sys/kernel/iommu_groups/ -type l') + self.ssh_command('dnf -y install numactl-devel') + + def test_intel_iommu(self): + """ + :avocado: tags=intel_iommu_intremap + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on') + self.run_and_check() + + def test_intel_iommu_strict(self): + """ + :avocado: tags=intel_iommu_strict + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on,strict') + self.run_and_check() + + def test_intel_iommu_strict_cm(self): + """ + :avocado: tags=intel_iommu_strict_cm + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on,caching-mode=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on,strict') + self.run_and_check() + + def test_intel_iommu_pt(self): + """ + :avocado: tags=intel_iommu_pt + """ + + self.common_vm_setup(True) + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params = (self.distro.default_kernel_params + + ' quiet intel_iommu=on iommu=pt') + self.run_and_check() diff --git a/tests/avocado/linux_initrd.py b/tests/avocado/linux_initrd.py new file mode 100644 index 0000000000..9b4880cd8c --- /dev/null +++ b/tests/avocado/linux_initrd.py @@ -0,0 +1,89 @@ +# Linux initrd integration test. +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Wainer dos Santos Moschetta +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import logging +import tempfile + +from avocado_qemu import Test +from avocado import skipIf + + +class LinuxInitrd(Test): + """ + Checks QEMU evaluates correctly the initrd file passed as -initrd option. + + :avocado: tags=arch:x86_64 + :avocado: tags=machine:pc + """ + + timeout = 300 + + def test_with_2gib_file_should_exit_error_msg_with_linux_v3_6(self): + """ + Pretends to boot QEMU with an initrd file with size of 2GiB + and expect it exits with error message. + Fedora-18 shipped with linux-3.6 which have not supported xloadflags + cannot support more than 2GiB initrd. + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora/li' + 'nux/releases/18/Fedora/x86_64/os/images/pxeboot/vmlinuz') + kernel_hash = '41464f68efe42b9991250bed86c7081d2ccdbb21' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + max_size = 2 * (1024 ** 3) - 1 + + with tempfile.NamedTemporaryFile() as initrd: + initrd.seek(max_size) + initrd.write(b'\0') + initrd.flush() + self.vm.add_args('-kernel', kernel_path, '-initrd', initrd.name, + '-m', '4096') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1) + expected_msg = r'.*initrd is too large.*max: \d+, need %s.*' % ( + max_size + 1) + self.assertRegex(self.vm.get_log(), expected_msg) + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_with_2gib_file_should_work_with_linux_v4_16(self): + """ + QEMU has supported up to 4 GiB initrd for recent kernel + Expect guest can reach 'Unpacking initramfs...' + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/28/Everything/x86_64/os/images/pxeboot/' + 'vmlinuz') + kernel_hash = '238e083e114c48200f80d889f7e32eeb2793e02a' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + max_size = 2 * (1024 ** 3) + 1 + + with tempfile.NamedTemporaryFile() as initrd: + initrd.seek(max_size) + initrd.write(b'\0') + initrd.flush() + + self.vm.set_console() + kernel_command_line = 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-initrd', initrd.name, + '-m', '5120') + self.vm.launch() + console = self.vm.console_socket.makefile() + console_logger = logging.getLogger('console') + while True: + msg = console.readline() + console_logger.debug(msg.strip()) + if 'Unpacking initramfs...' in msg: + break + if 'Kernel panic - not syncing' in msg: + self.fail("Kernel panic reached") diff --git a/tests/avocado/linux_ssh_mips_malta.py b/tests/avocado/linux_ssh_mips_malta.py new file mode 100644 index 0000000000..4de1947418 --- /dev/null +++ b/tests/avocado/linux_ssh_mips_malta.py @@ -0,0 +1,209 @@ +# Functional test that boots a VM and run commands via a SSH session +# +# Copyright (c) Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import re +import base64 +import logging +import time + +from avocado import skipUnless +from avocado_qemu import Test, LinuxSSHMixIn +from avocado_qemu import wait_for_console_pattern +from avocado.utils import process +from avocado.utils import archive +from avocado.utils import ssh + + +@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') +@skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available') +class LinuxSSH(Test, LinuxSSHMixIn): + + timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg' + + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + VM_IP = '127.0.0.1' + + BASE_URL = 'https://people.debian.org/~aurel32/qemu/' + IMAGE_INFO = { + 'be': {'base_url': 'mips', + 'image_name': 'debian_wheezy_mips_standard.qcow2', + 'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5', + 'kernel_hash': { + 32: '592e384a4edc16dade52a6cd5c785c637bcbc9ad', + 64: 'db6eea7de35d36c77d8c165b6bcb222e16eb91db'} + }, + 'le': {'base_url': 'mipsel', + 'image_name': 'debian_wheezy_mipsel_standard.qcow2', + 'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802', + 'kernel_hash': { + 32: 'a66bea5a8adaa2cb3d36a1d4e0ccdb01be8f6c2a', + 64: '6a7f77245acf231415a0e8b725d91ed2f3487794'} + } + } + CPU_INFO = { + 32: {'cpu': 'MIPS 24Kc', 'kernel_release': '3.2.0-4-4kc-malta'}, + 64: {'cpu': 'MIPS 20Kc', 'kernel_release': '3.2.0-4-5kc-malta'} + } + + def get_url(self, endianess, path=''): + qkey = {'le': 'el', 'be': ''} + return '%s/mips%s/%s' % (self.BASE_URL, qkey[endianess], path) + + def get_image_info(self, endianess): + dinfo = self.IMAGE_INFO[endianess] + image_url = self.get_url(endianess, dinfo['image_name']) + image_hash = dinfo['image_hash'] + return (image_url, image_hash) + + def get_kernel_info(self, endianess, wordsize): + minfo = self.CPU_INFO[wordsize] + kernel_url = self.get_url(endianess, + 'vmlinux-%s' % minfo['kernel_release']) + kernel_hash = self.IMAGE_INFO[endianess]['kernel_hash'][wordsize] + return kernel_url, kernel_hash + + def ssh_disconnect_vm(self): + self.ssh_session.quit() + + def boot_debian_wheezy_image_and_ssh_login(self, endianess, kernel_path): + image_url, image_hash = self.get_image_info(endianess) + image_path = self.fetch_asset(image_url, asset_hash=image_hash) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 root=/dev/sda1') + self.vm.add_args('-no-reboot', + '-kernel', kernel_path, + '-append', kernel_command_line, + '-drive', 'file=%s,snapshot=on' % image_path, + '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', + '-device', 'pcnet,netdev=vnet') + self.vm.launch() + + self.log.info('VM launched, waiting for sshd') + console_pattern = 'Starting OpenBSD Secure Shell server: sshd' + wait_for_console_pattern(self, console_pattern, 'Oops') + self.log.info('sshd ready') + + self.ssh_connect('root', 'root', False) + + def shutdown_via_ssh(self): + self.ssh_command('poweroff') + self.ssh_disconnect_vm() + wait_for_console_pattern(self, 'Power down', 'Oops') + + def ssh_command_output_contains(self, cmd, exp): + stdout, _ = self.ssh_command(cmd) + for line in stdout: + if exp in line: + break + else: + self.fail('"%s" output does not contain "%s"' % (cmd, exp)) + + def run_common_commands(self, wordsize): + self.ssh_command_output_contains( + 'cat /proc/cpuinfo', + self.CPU_INFO[wordsize]['cpu']) + self.ssh_command_output_contains( + 'uname -m', + 'mips') + self.ssh_command_output_contains( + 'uname -r', + self.CPU_INFO[wordsize]['kernel_release']) + self.ssh_command_output_contains( + 'cat /proc/interrupts', + 'XT-PIC timer') + self.ssh_command_output_contains( + 'cat /proc/interrupts', + 'XT-PIC i8042') + self.ssh_command_output_contains( + 'cat /proc/interrupts', + 'XT-PIC serial') + self.ssh_command_output_contains( + 'cat /proc/interrupts', + 'XT-PIC ata_piix') + self.ssh_command_output_contains( + 'cat /proc/interrupts', + 'XT-PIC eth0') + self.ssh_command_output_contains( + 'cat /proc/devices', + 'input') + self.ssh_command_output_contains( + 'cat /proc/devices', + 'usb') + self.ssh_command_output_contains( + 'cat /proc/devices', + 'fb') + self.ssh_command_output_contains( + 'cat /proc/ioports', + ' : serial') + self.ssh_command_output_contains( + 'cat /proc/ioports', + ' : ata_piix') + self.ssh_command_output_contains( + 'cat /proc/ioports', + ' : piix4_smbus') + self.ssh_command_output_contains( + 'lspci -d 11ab:4620', + 'GT-64120') + self.ssh_command_output_contains( + 'cat /sys/bus/i2c/devices/i2c-0/name', + 'SMBus PIIX4 adapter') + self.ssh_command_output_contains( + 'cat /proc/mtd', + 'YAMON') + # Empty 'Board Config' (64KB) + self.ssh_command_output_contains( + 'md5sum /dev/mtd2ro', + '0dfbe8aa4c20b52e1b8bf3cb6cbdf193') + + def check_mips_malta(self, uname_m, endianess): + wordsize = 64 if '64' in uname_m else 32 + kernel_url, kernel_hash = self.get_kernel_info(endianess, wordsize) + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.boot_debian_wheezy_image_and_ssh_login(endianess, kernel_path) + + stdout, _ = self.ssh_command('uname -a') + self.assertIn(True, [uname_m + " GNU/Linux" in line for line in stdout]) + + self.run_common_commands(wordsize) + self.shutdown_via_ssh() + # Wait for VM to shut down gracefully + self.vm.wait() + + def test_mips_malta32eb_kernel3_2_0(self): + """ + :avocado: tags=arch:mips + :avocado: tags=endian:big + :avocado: tags=device:pcnet32 + """ + self.check_mips_malta('mips', 'be') + + def test_mips_malta32el_kernel3_2_0(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=endian:little + :avocado: tags=device:pcnet32 + """ + self.check_mips_malta('mips', 'le') + + def test_mips_malta64eb_kernel3_2_0(self): + """ + :avocado: tags=arch:mips64 + :avocado: tags=endian:big + :avocado: tags=device:pcnet32 + """ + self.check_mips_malta('mips64', 'be') + + def test_mips_malta64el_kernel3_2_0(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=endian:little + :avocado: tags=device:pcnet32 + """ + self.check_mips_malta('mips64', 'le') diff --git a/tests/avocado/machine_arm_canona1100.py b/tests/avocado/machine_arm_canona1100.py new file mode 100644 index 0000000000..0e5c43dbcf --- /dev/null +++ b/tests/avocado/machine_arm_canona1100.py @@ -0,0 +1,35 @@ +# Functional test that boots the canon-a1100 machine with firmware +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive + +class CanonA1100Machine(Test): + """Boots the barebox firmware and checks that the console is operational""" + + timeout = 90 + + def test_arm_canona1100(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:canon-a1100 + :avocado: tags=device:pflash_cfi02 + """ + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day18.tar.xz') + tar_hash = '068b5fc4242b29381acee94713509f8a876e9db6' + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + archive.extract(file_path, self.workdir) + self.vm.set_console() + self.vm.add_args('-bios', + self.workdir + '/day18/barebox.canon-a1100.bin') + self.vm.launch() + wait_for_console_pattern(self, 'running /env/bin/init') diff --git a/tests/avocado/machine_arm_integratorcp.py b/tests/avocado/machine_arm_integratorcp.py new file mode 100644 index 0000000000..49c8ebff78 --- /dev/null +++ b/tests/avocado/machine_arm_integratorcp.py @@ -0,0 +1,99 @@ +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import logging + +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + + +NUMPY_AVAILABLE = True +try: + import numpy as np +except ImportError: + NUMPY_AVAILABLE = False + +CV2_AVAILABLE = True +try: + import cv2 +except ImportError: + CV2_AVAILABLE = False + + +class IntegratorMachine(Test): + + timeout = 90 + + def boot_integratorcp(self): + kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/' + 'arm-test/kernel/zImage.integrator') + kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + initrd_url = ('https://github.com/zayac/qemu-arm/raw/master/' + 'arm-test/kernel/arm_root.img') + initrd_hash = 'b51e4154285bf784e017a37586428332d8c7bd8b' + initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-append', 'printk.time=0 console=ttyAMA0') + self.vm.launch() + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_integratorcp_console(self): + """ + Boots the Linux kernel and checks that the console is operational + :avocado: tags=arch:arm + :avocado: tags=machine:integratorcp + :avocado: tags=device:pl011 + """ + self.boot_integratorcp() + wait_for_console_pattern(self, 'Log in as root') + + @skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed') + @skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed') + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_framebuffer_tux_logo(self): + """ + Boot Linux and verify the Tux logo is displayed on the framebuffer. + :avocado: tags=arch:arm + :avocado: tags=machine:integratorcp + :avocado: tags=device:pl110 + :avocado: tags=device:framebuffer + """ + screendump_path = os.path.join(self.workdir, "screendump.pbm") + tuxlogo_url = ('https://github.com/torvalds/linux/raw/v2.6.12/' + 'drivers/video/logo/logo_linux_vga16.ppm') + tuxlogo_hash = '3991c2ddbd1ddaecda7601f8aafbcf5b02dc86af' + tuxlogo_path = self.fetch_asset(tuxlogo_url, asset_hash=tuxlogo_hash) + + self.boot_integratorcp() + framebuffer_ready = 'Console: switching to colour frame buffer device' + wait_for_console_pattern(self, framebuffer_ready) + self.vm.command('human-monitor-command', command_line='stop') + self.vm.command('human-monitor-command', + command_line='screendump %s' % screendump_path) + logger = logging.getLogger('framebuffer') + + cpu_count = 1 + match_threshold = 0.92 + screendump_bgr = cv2.imread(screendump_path) + screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY) + result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 0), + cv2.TM_CCOEFF_NORMED) + loc = np.where(result >= match_threshold) + tux_count = 0 + for tux_count, pt in enumerate(zip(*loc[::-1]), start=1): + logger.debug('found Tux at position [x, y] = %s', pt) + self.assertGreaterEqual(tux_count, cpu_count) diff --git a/tests/avocado/machine_arm_n8x0.py b/tests/avocado/machine_arm_n8x0.py new file mode 100644 index 0000000000..e5741f2d8d --- /dev/null +++ b/tests/avocado/machine_arm_n8x0.py @@ -0,0 +1,49 @@ +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os + +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + +class N8x0Machine(Test): + """Boots the Linux kernel and checks that the console is operational""" + + timeout = 90 + + def __do_test_n8x0(self): + kernel_url = ('http://stskeeps.subnetmask.net/meego-n8x0/' + 'meego-arm-n8x0-1.0.80.20100712.1431-' + 'vmlinuz-2.6.35~rc4-129.1-n8x0') + kernel_hash = 'e9d5ab8d7548923a0061b6fbf601465e479ed269' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console(console_index=1) + self.vm.add_args('-kernel', kernel_path, + '-append', 'printk.time=0 console=ttyS1') + self.vm.launch() + wait_for_console_pattern(self, 'TSC2005 driver initializing') + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_n800(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:n800 + """ + self.__do_test_n8x0() + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_n810(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:n810 + """ + self.__do_test_n8x0() diff --git a/tests/avocado/machine_avr6.py b/tests/avocado/machine_avr6.py new file mode 100644 index 0000000000..6bab31342a --- /dev/null +++ b/tests/avocado/machine_avr6.py @@ -0,0 +1,50 @@ +# +# QEMU AVR integration tests +# +# Copyright (c) 2019-2020 Michael Rolnik +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import time + +from avocado_qemu import Test + +class AVR6Machine(Test): + timeout = 5 + + def test_freertos(self): + """ + :avocado: tags=arch:avr + :avocado: tags=machine:arduino-mega-2560-v3 + """ + """ + https://github.com/seharris/qemu-avr-tests/raw/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf + constantly prints out 'ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX' + """ + rom_url = ('https://github.com/seharris/qemu-avr-tests' + '/raw/36c3e67b8755dcf/free-rtos/Demo' + '/AVR_ATMega2560_GCC/demo.elf') + rom_hash = '7eb521f511ca8f2622e0a3c5e8dd686efbb911d4' + rom_path = self.fetch_asset(rom_url, asset_hash=rom_hash) + + self.vm.add_args('-bios', rom_path) + self.vm.add_args('-nographic') + self.vm.launch() + + time.sleep(2) + self.vm.shutdown() + + self.assertIn('ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX', + self.vm.get_log()) diff --git a/tests/avocado/machine_m68k_nextcube.py b/tests/avocado/machine_m68k_nextcube.py new file mode 100644 index 0000000000..09e2745cc5 --- /dev/null +++ b/tests/avocado/machine_m68k_nextcube.py @@ -0,0 +1,79 @@ +# Functional test that boots a VM and run OCR on the framebuffer +# +# Copyright (c) 2019 Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import time + +from avocado_qemu import Test +from avocado import skipUnless + +from tesseract_utils import tesseract_available, tesseract_ocr + +PIL_AVAILABLE = True +try: + from PIL import Image +except ImportError: + PIL_AVAILABLE = False + + +class NextCubeMachine(Test): + """ + :avocado: tags=arch:m68k + :avocado: tags=machine:next-cube + :avocado: tags=device:framebuffer + """ + + timeout = 15 + + def check_bootrom_framebuffer(self, screenshot_path): + rom_url = ('http://www.nextcomputers.org/NeXTfiles/Software/ROM_Files/' + '68040_Non-Turbo_Chipset/Rev_2.5_v66.BIN') + rom_hash = 'b3534796abae238a0111299fc406a9349f7fee24' + rom_path = self.fetch_asset(rom_url, asset_hash=rom_hash) + + self.vm.add_args('-bios', rom_path) + self.vm.launch() + + self.log.info('VM launched, waiting for display') + # TODO: Use avocado.utils.wait.wait_for to catch the + # 'displaysurface_create 1120x832' trace-event. + time.sleep(2) + + self.vm.command('human-monitor-command', + command_line='screendump %s' % screenshot_path) + + @skipUnless(PIL_AVAILABLE, 'Python PIL not installed') + def test_bootrom_framebuffer_size(self): + screenshot_path = os.path.join(self.workdir, "dump.ppm") + self.check_bootrom_framebuffer(screenshot_path) + + width, height = Image.open(screenshot_path).size + self.assertEqual(width, 1120) + self.assertEqual(height, 832) + + @skipUnless(tesseract_available(3), 'tesseract v3 OCR tool not available') + def test_bootrom_framebuffer_ocr_with_tesseract_v3(self): + screenshot_path = os.path.join(self.workdir, "dump.ppm") + self.check_bootrom_framebuffer(screenshot_path) + lines = tesseract_ocr(screenshot_path, tesseract_version=3) + text = '\n'.join(lines) + self.assertIn('Backplane', text) + self.assertIn('Ethernet address', text) + + # Tesseract 4 adds a new OCR engine based on LSTM neural networks. The + # new version is faster and more accurate than version 3. The drawback is + # that it is still alpha-level software. + @skipUnless(tesseract_available(4), 'tesseract v4 OCR tool not available') + def test_bootrom_framebuffer_ocr_with_tesseract_v4(self): + screenshot_path = os.path.join(self.workdir, "dump.ppm") + self.check_bootrom_framebuffer(screenshot_path) + lines = tesseract_ocr(screenshot_path, tesseract_version=4) + text = '\n'.join(lines) + self.assertIn('Testing the FPU, SCC', text) + self.assertIn('System test failed. Error code', text) + self.assertIn('Boot command', text) + self.assertIn('Next>', text) diff --git a/tests/avocado/machine_microblaze.py b/tests/avocado/machine_microblaze.py new file mode 100644 index 0000000000..7f6d18495d --- /dev/null +++ b/tests/avocado/machine_microblaze.py @@ -0,0 +1,35 @@ +# Functional test that boots a microblaze Linux kernel and checks the console +# +# Copyright (c) 2018, 2021 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive + +class MicroblazeMachine(Test): + + timeout = 90 + + def test_microblaze_s3adsp1800(self): + """ + :avocado: tags=arch:microblaze + :avocado: tags=machine:petalogix-s3adsp1800 + """ + + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day17.tar.xz') + tar_hash = '08bf3e3bfb6b6c7ce1e54ab65d54e189f2caf13f' + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + archive.extract(file_path, self.workdir) + self.vm.set_console() + self.vm.add_args('-kernel', self.workdir + '/day17/ballerina.bin') + self.vm.launch() + wait_for_console_pattern(self, 'This architecture does not have ' + 'kernel memory protection') + # Note: + # The kernel sometimes gets stuck after the "This architecture ..." + # message, that's why we don't test for a later string here. This + # needs some investigation by a microblaze wizard one day... diff --git a/tests/avocado/machine_mips_fuloong2e.py b/tests/avocado/machine_mips_fuloong2e.py new file mode 100644 index 0000000000..0ac285e2af --- /dev/null +++ b/tests/avocado/machine_mips_fuloong2e.py @@ -0,0 +1,42 @@ +# Functional tests for the Lemote Fuloong-2E machine. +# +# Copyright (c) 2019 Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + +class MipsFuloong2e(Test): + + timeout = 60 + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + @skipUnless(os.getenv('RESCUE_YL_PATH'), 'RESCUE_YL_PATH not available') + def test_linux_kernel_isa_serial(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:fuloong2e + :avocado: tags=endian:little + :avocado: tags=device:bonito64 + :avocado: tags=device:via686b + """ + # Recovery system for the Yeeloong laptop + # (enough to test the fuloong2e southbridge, accessing its ISA bus) + # http://dev.lemote.com/files/resource/download/rescue/rescue-yl + kernel_hash = 'ec4d1bd89a8439c41033ca63db60160cc6d6f09a' + kernel_path = self.fetch_asset('file://' + os.getenv('RESCUE_YL_PATH'), + asset_hash=kernel_hash) + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path) + self.vm.launch() + wait_for_console_pattern(self, 'Linux version 2.6.27.7lemote') + cpu_revision = 'CPU revision is: 00006302 (ICT Loongson-2)' + wait_for_console_pattern(self, cpu_revision) diff --git a/tests/avocado/machine_mips_loongson3v.py b/tests/avocado/machine_mips_loongson3v.py new file mode 100644 index 0000000000..85b131a40f --- /dev/null +++ b/tests/avocado/machine_mips_loongson3v.py @@ -0,0 +1,39 @@ +# Functional tests for the Generic Loongson-3 Platform. +# +# Copyright (c) 2021 Jiaxun Yang +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import time + +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + +class MipsLoongson3v(Test): + timeout = 60 + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_pmon_serial_console(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=endian:little + :avocado: tags=machine:loongson3-virt + :avocado: tags=cpu:Loongson-3A1000 + :avocado: tags=device:liointc + :avocado: tags=device:goldfish_rtc + """ + + pmon_hash = '7c8b45dd81ccfc55ff28f5aa267a41c3' + pmon_path = self.fetch_asset('https://github.com/loongson-community/pmon/' + 'releases/download/20210112/pmon-3avirt.bin', + asset_hash=pmon_hash, algorithm='md5') + + self.vm.set_console() + self.vm.add_args('-bios', pmon_path) + self.vm.launch() + wait_for_console_pattern(self, 'CPU GODSON3 BogoMIPS:') diff --git a/tests/avocado/machine_mips_malta.py b/tests/avocado/machine_mips_malta.py new file mode 100644 index 0000000000..b67d8cb141 --- /dev/null +++ b/tests/avocado/machine_mips_malta.py @@ -0,0 +1,120 @@ +# Functional tests for the MIPS Malta board +# +# Copyright (c) Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import gzip +import logging + +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive +from avocado import skipIf + + +NUMPY_AVAILABLE = True +try: + import numpy as np +except ImportError: + NUMPY_AVAILABLE = False + +CV2_AVAILABLE = True +try: + import cv2 +except ImportError: + CV2_AVAILABLE = False + + +@skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed') +@skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed') +class MaltaMachineFramebuffer(Test): + + timeout = 30 + + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + def do_test_i6400_framebuffer_logo(self, cpu_cores_count): + """ + Boot Linux kernel and check Tux logo is displayed on the framebuffer. + """ + screendump_path = os.path.join(self.workdir, 'screendump.pbm') + + kernel_url = ('https://github.com/philmd/qemu-testing-blob/raw/' + 'a5966ca4b5/mips/malta/mips64el/' + 'vmlinux-4.7.0-rc1.I6400.gz') + kernel_hash = '096f50c377ec5072e6a366943324622c312045f6' + kernel_path_gz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + kernel_path = self.workdir + "vmlinux" + archive.gzip_uncompress(kernel_path_gz, kernel_path) + + tuxlogo_url = ('https://github.com/torvalds/linux/raw/v2.6.12/' + 'drivers/video/logo/logo_linux_vga16.ppm') + tuxlogo_hash = '3991c2ddbd1ddaecda7601f8aafbcf5b02dc86af' + tuxlogo_path = self.fetch_asset(tuxlogo_url, asset_hash=tuxlogo_hash) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'clocksource=GIC console=tty0 console=ttyS0') + self.vm.add_args('-kernel', kernel_path, + '-smp', '%u' % cpu_cores_count, + '-vga', 'std', + '-append', kernel_command_line) + self.vm.launch() + framebuffer_ready = 'Console: switching to colour frame buffer device' + wait_for_console_pattern(self, framebuffer_ready, + failure_message='Kernel panic - not syncing') + self.vm.command('human-monitor-command', command_line='stop') + self.vm.command('human-monitor-command', + command_line='screendump %s' % screendump_path) + logger = logging.getLogger('framebuffer') + + match_threshold = 0.95 + screendump_bgr = cv2.imread(screendump_path, cv2.IMREAD_COLOR) + tuxlogo_bgr = cv2.imread(tuxlogo_path, cv2.IMREAD_COLOR) + result = cv2.matchTemplate(screendump_bgr, tuxlogo_bgr, + cv2.TM_CCOEFF_NORMED) + loc = np.where(result >= match_threshold) + tuxlogo_count = 0 + h, w = tuxlogo_bgr.shape[:2] + debug_png = os.getenv('AVOCADO_CV2_SCREENDUMP_PNG_PATH') + for tuxlogo_count, pt in enumerate(zip(*loc[::-1]), start=1): + logger.debug('found Tux at position (x, y) = %s', pt) + cv2.rectangle(screendump_bgr, pt, + (pt[0] + w, pt[1] + h), (0, 0, 255), 2) + if debug_png: + cv2.imwrite(debug_png, screendump_bgr) + self.assertGreaterEqual(tuxlogo_count, cpu_cores_count) + + def test_mips_malta_i6400_framebuffer_logo_1core(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=cpu:I6400 + """ + self.do_test_i6400_framebuffer_logo(1) + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_mips_malta_i6400_framebuffer_logo_7cores(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=cpu:I6400 + :avocado: tags=mips:smp + """ + self.do_test_i6400_framebuffer_logo(7) + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_mips_malta_i6400_framebuffer_logo_8cores(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=cpu:I6400 + :avocado: tags=mips:smp + """ + self.do_test_i6400_framebuffer_logo(8) diff --git a/tests/avocado/machine_rx_gdbsim.py b/tests/avocado/machine_rx_gdbsim.py new file mode 100644 index 0000000000..32b737b6d8 --- /dev/null +++ b/tests/avocado/machine_rx_gdbsim.py @@ -0,0 +1,73 @@ +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os + +from avocado import skipIf +from avocado_qemu import Test +from avocado_qemu import exec_command_and_wait_for_pattern +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive + + +class RxGdbSimMachine(Test): + + timeout = 30 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_uboot(self): + """ + U-Boot and checks that the console is operational. + + :avocado: tags=arch:rx + :avocado: tags=machine:gdbsim-r5f562n8 + :avocado: tags=endian:little + """ + uboot_url = ('https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz') + uboot_hash = '9b78dbd43b40b2526848c0b1ce9de02c24f4dcdb' + uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) + uboot_path = archive.uncompress(uboot_path, self.workdir) + + self.vm.set_console() + self.vm.add_args('-bios', uboot_path, + '-no-reboot') + self.vm.launch() + uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty' + wait_for_console_pattern(self, uboot_version) + gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)' + # FIXME limit baudrate on chardev, else we type too fast + #exec_command_and_wait_for_pattern(self, 'version', gcc_version) + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_linux_sash(self): + """ + Boots a Linux kernel and checks that the console is operational. + + :avocado: tags=arch:rx + :avocado: tags=machine:gdbsim-r5f562n7 + :avocado: tags=endian:little + """ + dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb') + dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18' + dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash) + kernel_url = ('http://acc.dl.osdn.jp/users/23/23845/zImage') + kernel_hash = '39a81067f8d72faad90866ddfefa19165d68fc99' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon' + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-no-reboot') + self.vm.launch() + wait_for_console_pattern(self, 'Sash command shell (version 1.1.1)', + failure_message='Kernel panic - not syncing') + exec_command_and_wait_for_pattern(self, 'printenv', 'TERM=linux') diff --git a/tests/avocado/machine_s390_ccw_virtio.py b/tests/avocado/machine_s390_ccw_virtio.py new file mode 100644 index 0000000000..4028c99afc --- /dev/null +++ b/tests/avocado/machine_s390_ccw_virtio.py @@ -0,0 +1,272 @@ +# Functional test that boots an s390x Linux guest with ccw and PCI devices +# attached and checks whether the devices are recognized by Linux +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Cornelia Huck +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import tempfile + +from avocado import skipIf +from avocado_qemu import Test +from avocado_qemu import exec_command_and_wait_for_pattern +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive + +class S390CCWVirtioMachine(Test): + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + timeout = 120 + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern(self, success_message, + failure_message='Kernel panic - not syncing', + vm=vm) + + def wait_for_crw_reports(self): + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg -c | grep CRW) ; do sleep 1 ; done', + 'CRW reports') + + dmesg_clear_count = 1 + def clear_guest_dmesg(self): + exec_command_and_wait_for_pattern(self, 'dmesg -c > /dev/null; ' + 'echo dm_clear\ ' + str(self.dmesg_clear_count), + 'dm_clear ' + str(self.dmesg_clear_count)) + self.dmesg_clear_count += 1 + + def test_s390x_devices(self): + + """ + :avocado: tags=arch:s390x + :avocado: tags=machine:s390-ccw-virtio + """ + + kernel_url = ('https://snapshot.debian.org/archive/debian/' + '20201126T092837Z/dists/buster/main/installer-s390x/' + '20190702+deb10u6/images/generic/kernel.debian') + kernel_hash = '5821fbee57d6220a067a8b967d24595621aa1eb6' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + initrd_url = ('https://snapshot.debian.org/archive/debian/' + '20201126T092837Z/dists/buster/main/installer-s390x/' + '20190702+deb10u6/images/generic/initrd.debian') + initrd_hash = '81ba09c97bef46e8f4660ac25b4ac0a5be3a94d6' + initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=sclp0 root=/dev/ram0 BOOT_DEBUG=3') + self.vm.add_args('-nographic', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-device', 'virtio-net-ccw,devno=fe.1.1111', + '-device', + 'virtio-rng-ccw,devno=fe.2.0000,max_revision=0,id=rn1', + '-device', + 'virtio-rng-ccw,devno=fe.3.1234,max_revision=2,id=rn2', + '-device', 'zpci,uid=5,target=zzz', + '-device', 'virtio-net-pci,id=zzz', + '-device', 'zpci,uid=0xa,fid=12,target=serial', + '-device', 'virtio-serial-pci,id=serial', + '-device', 'virtio-balloon-ccw') + self.vm.launch() + + shell_ready = "sh: can't access tty; job control turned off" + self.wait_for_console_pattern(shell_ready) + # first debug shell is too early, we need to wait for device detection + exec_command_and_wait_for_pattern(self, 'exit', shell_ready) + + ccw_bus_ids="0.1.1111 0.2.0000 0.3.1234" + pci_bus_ids="0005:00:00.0 000a:00:00.0" + exec_command_and_wait_for_pattern(self, 'ls /sys/bus/ccw/devices/', + ccw_bus_ids) + exec_command_and_wait_for_pattern(self, 'ls /sys/bus/pci/devices/', + pci_bus_ids) + # check that the device at 0.2.0000 is in legacy mode, while the + # device at 0.3.1234 has the virtio-1 feature bit set + virtio_rng_features="00000000000000000000000000001100" + \ + "10000000000000000000000000000000" + virtio_rng_features_legacy="00000000000000000000000000001100" + \ + "00000000000000000000000000000000" + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/ccw/devices/0.2.0000/virtio?/features', + virtio_rng_features_legacy) + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/ccw/devices/0.3.1234/virtio?/features', + virtio_rng_features) + # check that /dev/hwrng works - and that it's gone after ejecting + exec_command_and_wait_for_pattern(self, + 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', + '10+0 records out') + self.clear_guest_dmesg() + self.vm.command('device_del', id='rn1') + self.wait_for_crw_reports() + self.clear_guest_dmesg() + self.vm.command('device_del', id='rn2') + self.wait_for_crw_reports() + exec_command_and_wait_for_pattern(self, + 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', + 'dd: /dev/hwrng: No such device') + # verify that we indeed have virtio-net devices (without having the + # virtio-net driver handy) + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/ccw/devices/0.1.1111/cutype', + '3832/01') + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_vendor', + '0x1af4') + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_device', + '0x0001') + # check fid propagation + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/pci/devices/000a\:00\:00.0/function_id', + '0x0000000c') + # add another device + self.clear_guest_dmesg() + self.vm.command('device_add', driver='virtio-net-ccw', + devno='fe.0.4711', id='net_4711') + self.wait_for_crw_reports() + exec_command_and_wait_for_pattern(self, 'for i in 1 2 3 4 5 6 7 ; do ' + 'if [ -e /sys/bus/ccw/devices/*4711 ]; then break; fi ;' + 'sleep 1 ; done ; ls /sys/bus/ccw/devices/', + '0.0.4711') + # and detach it again + self.clear_guest_dmesg() + self.vm.command('device_del', id='net_4711') + self.vm.event_wait(name='DEVICE_DELETED', + match={'data': {'device': 'net_4711'}}) + self.wait_for_crw_reports() + exec_command_and_wait_for_pattern(self, + 'ls /sys/bus/ccw/devices/0.0.4711', + 'No such file or directory') + # test the virtio-balloon device + exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', + 'MemTotal: 115640 kB') + self.vm.command('human-monitor-command', command_line='balloon 96') + exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', + 'MemTotal: 82872 kB') + self.vm.command('human-monitor-command', command_line='balloon 128') + exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', + 'MemTotal: 115640 kB') + + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_s390x_fedora(self): + + """ + :avocado: tags=arch:s390x + :avocado: tags=machine:s390-ccw-virtio + :avocado: tags=device:virtio-gpu + :avocado: tags=device:virtio-crypto + :avocado: tags=device:virtio-net + """ + + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/31/Server/s390x/os' + '/images/kernel.img') + kernel_hash = 'b93d1efcafcf29c1673a4ce371a1f8b43941cfeb' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + initrd_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/31/Server/s390x/os' + '/images/initrd.img') + initrd_hash = '3de45d411df5624b8d8ef21cd0b44419ab59b12f' + initrd_path_xz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = os.path.join(self.workdir, 'initrd-raw.img') + archive.lzma_uncompress(initrd_path_xz, initrd_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + ' audit=0 ' + 'rd.plymouth=0 plymouth.enable=0 rd.rescue') + self.vm.add_args('-nographic', + '-smp', '4', + '-m', '512', + '-name', 'Some Guest Name', + '-uuid', '30de4fd9-b4d5-409e-86a5-09b387f70bfa', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-device', 'zpci,uid=7,target=n', + '-device', 'virtio-net-pci,id=n,mac=02:ca:fe:fa:ce:12', + '-device', 'virtio-rng-ccw,devno=fe.1.9876', + '-device', 'virtio-gpu-ccw,devno=fe.2.5432') + self.vm.launch() + self.wait_for_console_pattern('Entering emergency mode') + + # Some tests to see whether the CLI options have been considered: + self.log.info("Test whether QEMU CLI options have been considered") + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg | grep enP7p0s0) ; do sleep 1 ; done', + 'virtio_net virtio0 enP7p0s0: renamed') + exec_command_and_wait_for_pattern(self, 'lspci', + '0007:00:00.0 Class 0200: Device 1af4:1000') + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/net/enP7p0s0/address', + '02:ca:fe:fa:ce:12') + exec_command_and_wait_for_pattern(self, 'lscss', '0.1.9876') + exec_command_and_wait_for_pattern(self, 'lscss', '0.2.5432') + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'processors : 4') + exec_command_and_wait_for_pattern(self, 'grep MemTotal /proc/meminfo', + 'MemTotal: 499848 kB') + exec_command_and_wait_for_pattern(self, 'grep Name /proc/sysinfo', + 'Extended Name: Some Guest Name') + exec_command_and_wait_for_pattern(self, 'grep UUID /proc/sysinfo', + '30de4fd9-b4d5-409e-86a5-09b387f70bfa') + + # Disable blinking cursor, then write some stuff into the framebuffer. + # QEMU's PPM screendumps contain uncompressed 24-bit values, while the + # framebuffer uses 32-bit, so we pad our text with some spaces when + # writing to the framebuffer. Since the PPM is uncompressed, we then + # can simply read the written "magic bytes" back from the PPM file to + # check whether the framebuffer is working as expected. + self.log.info("Test screendump of virtio-gpu device") + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg | grep gpudrmfb) ; do sleep 1 ; done', + 'virtio_gpudrmfb frame buffer device') + exec_command_and_wait_for_pattern(self, + 'echo -e "\e[?25l" > /dev/tty0', ':/#') + exec_command_and_wait_for_pattern(self, 'for ((i=0;i<250;i++)); do ' + 'echo " The qu ick fo x j ump s o ver a laz y d og" >> fox.txt;' + 'done', + ':/#') + exec_command_and_wait_for_pattern(self, + 'dd if=fox.txt of=/dev/fb0 bs=1000 oflag=sync,nocache ; rm fox.txt', + '12+0 records out') + with tempfile.NamedTemporaryFile(suffix='.ppm', + prefix='qemu-scrdump-') as ppmfile: + self.vm.command('screendump', filename=ppmfile.name) + ppmfile.seek(0) + line = ppmfile.readline() + self.assertEqual(line, b"P6\n") + line = ppmfile.readline() + self.assertEqual(line, b"1024 768\n") + line = ppmfile.readline() + self.assertEqual(line, b"255\n") + line = ppmfile.readline(256) + self.assertEqual(line, b"The quick fox jumps over a lazy dog\n") + + # Hot-plug a virtio-crypto device and see whether it gets accepted + self.log.info("Test hot-plug virtio-crypto device") + self.clear_guest_dmesg() + self.vm.command('object-add', qom_type='cryptodev-backend-builtin', + id='cbe0') + self.vm.command('device_add', driver='virtio-crypto-ccw', id='crypdev0', + cryptodev='cbe0', devno='fe.0.2342') + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg -c | grep Accelerator.device) ; do' + ' sleep 1 ; done', 'Accelerator device is ready') + exec_command_and_wait_for_pattern(self, 'lscss', '0.0.2342') + self.vm.command('device_del', id='crypdev0') + self.vm.command('object-del', id='cbe0') + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg -c | grep Start.virtcrypto_remove) ; do' + ' sleep 1 ; done', 'Start virtcrypto_remove.') diff --git a/tests/avocado/machine_sparc64_sun4u.py b/tests/avocado/machine_sparc64_sun4u.py new file mode 100644 index 0000000000..458165500e --- /dev/null +++ b/tests/avocado/machine_sparc64_sun4u.py @@ -0,0 +1,36 @@ +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os + +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive +from boot_linux_console import LinuxKernelTest + +class Sun4uMachine(LinuxKernelTest): + """Boots the Linux kernel and checks that the console is operational""" + + timeout = 90 + + def test_sparc64_sun4u(self): + """ + :avocado: tags=arch:sparc64 + :avocado: tags=machine:sun4u + """ + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day23.tar.xz') + tar_hash = '142db83cd974ffadc4f75c8a5cad5bcc5722c240' + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + archive.extract(file_path, self.workdir) + self.vm.set_console() + self.vm.add_args('-kernel', self.workdir + '/day23/vmlinux', + '-append', self.KERNEL_COMMON_COMMAND_LINE) + self.vm.launch() + wait_for_console_pattern(self, 'Starting logging: OK') diff --git a/tests/avocado/machine_sparc_leon3.py b/tests/avocado/machine_sparc_leon3.py new file mode 100644 index 0000000000..2405cd7a0d --- /dev/null +++ b/tests/avocado/machine_sparc_leon3.py @@ -0,0 +1,37 @@ +# Functional test that boots a Leon3 machine and checks its serial console. +# +# Copyright (c) Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern +from avocado import skip + + +class Leon3Machine(Test): + + timeout = 60 + + @skip("Test currently broken") + # A Window Underflow exception occurs before booting the kernel, + # and QEMU exit calling cpu_abort(), which makes this test to fail. + def test_leon3_helenos_uimage(self): + """ + :avocado: tags=arch:sparc + :avocado: tags=machine:leon3_generic + :avocado: tags=binfmt:uimage + """ + kernel_url = ('http://www.helenos.org/releases/' + 'HelenOS-0.6.0-sparc32-leon3.bin') + kernel_hash = 'a88c9cfdb8430c66650e5290a08765f9bf049a30' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path) + + self.vm.launch() + + wait_for_console_pattern(self, 'Copyright (c) 2001-2014 HelenOS project') + wait_for_console_pattern(self, 'Booting the kernel ...') diff --git a/tests/avocado/migration.py b/tests/avocado/migration.py new file mode 100644 index 0000000000..792639cb69 --- /dev/null +++ b/tests/avocado/migration.py @@ -0,0 +1,81 @@ +# Migration test +# +# Copyright (c) 2019 Red Hat, Inc. +# +# Authors: +# Cleber Rosa +# Caio Carrara +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + + +import tempfile +from avocado_qemu import Test +from avocado import skipUnless + +from avocado.utils import network +from avocado.utils import wait +from avocado.utils.path import find_command + + +class Migration(Test): + """ + :avocado: tags=migration + """ + + timeout = 10 + + @staticmethod + def migration_finished(vm): + return vm.command('query-migrate')['status'] in ('completed', 'failed') + + def assert_migration(self, src_vm, dst_vm): + wait.wait_for(self.migration_finished, + timeout=self.timeout, + step=0.1, + args=(src_vm,)) + wait.wait_for(self.migration_finished, + timeout=self.timeout, + step=0.1, + args=(dst_vm,)) + self.assertEqual(src_vm.command('query-migrate')['status'], 'completed') + self.assertEqual(dst_vm.command('query-migrate')['status'], 'completed') + self.assertEqual(dst_vm.command('query-status')['status'], 'running') + self.assertEqual(src_vm.command('query-status')['status'],'postmigrate') + + def do_migrate(self, dest_uri, src_uri=None): + dest_vm = self.get_vm('-incoming', dest_uri) + dest_vm.add_args('-nodefaults') + dest_vm.launch() + if src_uri is None: + src_uri = dest_uri + source_vm = self.get_vm() + source_vm.add_args('-nodefaults') + source_vm.launch() + source_vm.qmp('migrate', uri=src_uri) + self.assert_migration(source_vm, dest_vm) + + def _get_free_port(self): + port = network.find_free_port() + if port is None: + self.cancel('Failed to find a free port') + return port + + + def test_migration_with_tcp_localhost(self): + dest_uri = 'tcp:localhost:%u' % self._get_free_port() + self.do_migrate(dest_uri) + + def test_migration_with_unix(self): + with tempfile.TemporaryDirectory(prefix='socket_') as socket_path: + dest_uri = 'unix:%s/qemu-test.sock' % socket_path + self.do_migrate(dest_uri) + + @skipUnless(find_command('nc', default=False), "'nc' command not found") + def test_migration_with_exec(self): + """The test works for both netcat-traditional and netcat-openbsd packages.""" + free_port = self._get_free_port() + dest_uri = 'exec:nc -l localhost %u' % free_port + src_uri = 'exec:nc localhost %u' % free_port + self.do_migrate(dest_uri, src_uri) diff --git a/tests/avocado/multiprocess.py b/tests/avocado/multiprocess.py new file mode 100644 index 0000000000..96627f022a --- /dev/null +++ b/tests/avocado/multiprocess.py @@ -0,0 +1,95 @@ +# Test for multiprocess qemu +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + + +import os +import socket + +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern +from avocado_qemu import exec_command +from avocado_qemu import exec_command_and_wait_for_pattern + +class Multiprocess(Test): + """ + :avocado: tags=multiprocess + """ + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + def do_test(self, kernel_url, initrd_url, kernel_command_line, + machine_type): + """Main test method""" + self.require_accelerator('kvm') + + # Create socketpair to connect proxy and remote processes + proxy_sock, remote_sock = socket.socketpair(socket.AF_UNIX, + socket.SOCK_STREAM) + os.set_inheritable(proxy_sock.fileno(), True) + os.set_inheritable(remote_sock.fileno(), True) + + kernel_path = self.fetch_asset(kernel_url) + initrd_path = self.fetch_asset(initrd_url) + + # Create remote process + remote_vm = self.get_vm() + remote_vm.add_args('-machine', 'x-remote') + remote_vm.add_args('-nodefaults') + remote_vm.add_args('-device', 'lsi53c895a,id=lsi1') + remote_vm.add_args('-object', 'x-remote-object,id=robj1,' + 'devid=lsi1,fd='+str(remote_sock.fileno())) + remote_vm.launch() + + # Create proxy process + self.vm.set_console() + self.vm.add_args('-machine', machine_type) + self.vm.add_args('-accel', 'kvm') + self.vm.add_args('-cpu', 'host') + self.vm.add_args('-object', + 'memory-backend-memfd,id=sysmem-file,size=2G') + self.vm.add_args('--numa', 'node,memdev=sysmem-file') + self.vm.add_args('-m', '2048') + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line) + self.vm.add_args('-device', + 'x-pci-proxy-dev,' + 'id=lsi1,fd='+str(proxy_sock.fileno())) + self.vm.launch() + wait_for_console_pattern(self, 'as init process', + 'Kernel panic - not syncing') + exec_command(self, 'mount -t sysfs sysfs /sys') + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/pci/devices/*/uevent', + 'PCI_ID=1000:0012') + + def test_multiprocess_x86_64(self): + """ + :avocado: tags=arch:x86_64 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/31/Everything/x86_64/os/images' + '/pxeboot/vmlinuz') + initrd_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/31/Everything/x86_64/os/images' + '/pxeboot/initrd.img') + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 rdinit=/bin/bash') + machine_type = 'pc' + self.do_test(kernel_url, initrd_url, kernel_command_line, machine_type) + + def test_multiprocess_aarch64(self): + """ + :avocado: tags=arch:aarch64 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/31/Everything/aarch64/os/images' + '/pxeboot/vmlinuz') + initrd_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/31/Everything/aarch64/os/images' + '/pxeboot/initrd.img') + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'rdinit=/bin/bash console=ttyAMA0') + machine_type = 'virt,gic-version=3' + self.do_test(kernel_url, initrd_url, kernel_command_line, machine_type) diff --git a/tests/avocado/pc_cpu_hotplug_props.py b/tests/avocado/pc_cpu_hotplug_props.py new file mode 100644 index 0000000000..2e86d5017a --- /dev/null +++ b/tests/avocado/pc_cpu_hotplug_props.py @@ -0,0 +1,35 @@ +# +# Ensure CPU die-id can be omitted on -device +# +# Copyright (c) 2019 Red Hat Inc +# +# Author: +# Eduardo Habkost +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# + +from avocado_qemu import Test + +class OmittedCPUProps(Test): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=cpu:qemu64 + """ + def test_no_die_id(self): + self.vm.add_args('-nodefaults', '-S') + self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') + self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') + self.vm.launch() + self.assertEquals(len(self.vm.command('query-cpus-fast')), 2) diff --git a/tests/avocado/ppc_405.py b/tests/avocado/ppc_405.py new file mode 100644 index 0000000000..c534d5d32f --- /dev/null +++ b/tests/avocado/ppc_405.py @@ -0,0 +1,42 @@ +# Test that the U-Boot firmware boots on ppc 405 machines and check the console +# +# Copyright (c) 2021 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado.utils import archive +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern +from avocado_qemu import exec_command_and_wait_for_pattern + +class Ppc405Machine(Test): + + timeout = 90 + + def do_test_ppc405(self): + uboot_url = ('https://gitlab.com/huth/u-boot/-/raw/' + 'taihu-2021-10-09/u-boot-taihu.bin') + uboot_hash = ('3208940e908a5edc7c03eab072c60f0dcfadc2ab'); + file_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) + self.vm.set_console(console_index=1) + self.vm.add_args('-bios', file_path) + self.vm.launch() + wait_for_console_pattern(self, 'AMCC PPC405EP Evaluation Board') + exec_command_and_wait_for_pattern(self, 'reset', 'AMCC PowerPC 405EP') + + def test_ppc_taihu(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:taihu + :avocado: tags=cpu:405ep + """ + self.do_test_ppc405() + + def test_ppc_ref405ep(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:ref405ep + :avocado: tags=cpu:405ep + """ + self.do_test_ppc405() diff --git a/tests/avocado/ppc_bamboo.py b/tests/avocado/ppc_bamboo.py new file mode 100644 index 0000000000..dd33bf66f3 --- /dev/null +++ b/tests/avocado/ppc_bamboo.py @@ -0,0 +1,39 @@ +# Test that Linux kernel boots on the ppc bamboo board and check the console +# +# Copyright (c) 2021 Red Hat +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado.utils import archive +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern +from avocado_qemu import exec_command_and_wait_for_pattern + +class BambooMachine(Test): + + timeout = 90 + + def test_ppc_bamboo(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:bamboo + :avocado: tags=cpu:440epb + :avocado: tags=device:rtl8139 + """ + tar_url = ('http://landley.net/aboriginal/downloads/binaries/' + 'system-image-powerpc-440fp.tar.gz') + tar_hash = '53e5f16414b195b82d2c70272f81c2eedb39bad9' + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + archive.extract(file_path, self.workdir) + self.vm.set_console() + self.vm.add_args('-kernel', self.workdir + + '/system-image-powerpc-440fp/linux', + '-initrd', self.workdir + + '/system-image-powerpc-440fp/rootfs.cpio.gz', + '-nic', 'user,model=rtl8139,restrict=on') + self.vm.launch() + wait_for_console_pattern(self, 'Type exit when done') + exec_command_and_wait_for_pattern(self, 'ping 10.0.2.2', + '10.0.2.2 is alive!') + exec_command_and_wait_for_pattern(self, 'halt', 'System Halted') diff --git a/tests/avocado/ppc_mpc8544ds.py b/tests/avocado/ppc_mpc8544ds.py new file mode 100644 index 0000000000..ce840600c1 --- /dev/null +++ b/tests/avocado/ppc_mpc8544ds.py @@ -0,0 +1,32 @@ +# Test that Linux kernel boots on ppc machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado.utils import archive +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + +class Mpc8544dsMachine(Test): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + panic_message = 'Kernel panic - not syncing' + + def test_ppc_mpc8544ds(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:mpc8544ds + """ + tar_url = ('https://www.qemu-advent-calendar.org' + '/2020/download/day17.tar.gz') + tar_hash = '7a5239542a7c4257aa4d3b7f6ddf08fb6775c494' + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + archive.extract(file_path, self.workdir) + self.vm.set_console() + self.vm.add_args('-kernel', self.workdir + '/creek/creek.bin') + self.vm.launch() + wait_for_console_pattern(self, 'QEMU advent calendar 2020', + self.panic_message) diff --git a/tests/avocado/ppc_prep_40p.py b/tests/avocado/ppc_prep_40p.py new file mode 100644 index 0000000000..5e61e686bd --- /dev/null +++ b/tests/avocado/ppc_prep_40p.py @@ -0,0 +1,79 @@ +# Functional test that boots a PReP/40p machine and checks its serial console. +# +# Copyright (c) Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os + +from avocado import skipUnless +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + + +class IbmPrep40pMachine(Test): + + timeout = 60 + + # 12H0455 PPS Firmware Licensed Materials + # Property of IBM (C) Copyright IBM Corp. 1994. + # All rights reserved. + # U.S. Government Users Restricted Rights - Use, duplication or disclosure + # restricted by GSA ADP Schedule Contract with IBM Corp. + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_factory_firmware_and_netbsd(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:40p + :avocado: tags=os:netbsd + :avocado: tags=slowness:high + """ + bios_url = ('http://ftpmirror.your.org/pub/misc/' + 'ftp.software.ibm.com/rs6000/firmware/' + '7020-40p/P12H0456.IMG') + bios_hash = '1775face4e6dc27f3a6ed955ef6eb331bf817f03' + bios_path = self.fetch_asset(bios_url, asset_hash=bios_hash) + drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/' + 'NetBSD-4.0/prep/installation/floppy/generic_com0.fs') + drive_hash = 'dbcfc09912e71bd5f0d82c7c1ee43082fb596ceb' + drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash) + + self.vm.set_console() + self.vm.add_args('-bios', bios_path, + '-fda', drive_path) + self.vm.launch() + os_banner = 'NetBSD 4.0 (GENERIC) #0: Sun Dec 16 00:49:40 PST 2007' + wait_for_console_pattern(self, os_banner) + wait_for_console_pattern(self, 'Model: IBM PPS Model 6015') + + def test_openbios_192m(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:40p + """ + self.vm.set_console() + self.vm.add_args('-m', '192') # test fw_cfg + + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> Memory: 192M') + wait_for_console_pattern(self, '>> CPU type PowerPC,604') + + def test_openbios_and_netbsd(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:40p + :avocado: tags=os:netbsd + """ + drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/' + 'NetBSD-7.1.2/iso/NetBSD-7.1.2-prep.iso') + drive_hash = 'ac6fa2707d888b36d6fa64de6e7fe48e' + drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash, + algorithm='md5') + self.vm.set_console() + self.vm.add_args('-cdrom', drive_path, + '-boot', 'd') + + self.vm.launch() + wait_for_console_pattern(self, 'NetBSD/prep BOOT, Revision 1.9') diff --git a/tests/avocado/ppc_pseries.py b/tests/avocado/ppc_pseries.py new file mode 100644 index 0000000000..f14a884ee1 --- /dev/null +++ b/tests/avocado/ppc_pseries.py @@ -0,0 +1,35 @@ +# Test that Linux kernel boots on ppc machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado.utils import archive +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + +class pseriesMachine(Test): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + panic_message = 'Kernel panic - not syncing' + + def test_ppc64_pseries(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:pseries + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/ppc64le/os' + '/ppc/ppc64/vmlinuz') + kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + wait_for_console_pattern(self, console_pattern, self.panic_message) diff --git a/tests/avocado/ppc_virtex_ml507.py b/tests/avocado/ppc_virtex_ml507.py new file mode 100644 index 0000000000..27f7bf2d49 --- /dev/null +++ b/tests/avocado/ppc_virtex_ml507.py @@ -0,0 +1,34 @@ +# Test that Linux kernel boots on ppc machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado.utils import archive +from avocado_qemu import Test +from avocado_qemu import wait_for_console_pattern + +class VirtexMl507Machine(Test): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + panic_message = 'Kernel panic - not syncing' + + def test_ppc_virtex_ml507(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:virtex-ml507 + """ + tar_url = ('https://www.qemu-advent-calendar.org' + '/2020/download/hippo.tar.gz') + tar_hash = '306b95bfe7d147f125aa176a877e266db8ef914a' + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + archive.extract(file_path, self.workdir) + self.vm.set_console() + self.vm.add_args('-kernel', self.workdir + '/hippo/hippo.linux', + '-dtb', self.workdir + '/hippo/virtex440-ml507.dtb', + '-m', '512') + self.vm.launch() + wait_for_console_pattern(self, 'QEMU advent calendar 2020', + self.panic_message) diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py new file mode 100644 index 0000000000..c68a953730 --- /dev/null +++ b/tests/avocado/replay_kernel.py @@ -0,0 +1,524 @@ +# Record/replay test that boots a Linux kernel +# +# Copyright (c) 2020 ISP RAS +# +# Author: +# Pavel Dovgalyuk +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import lzma +import shutil +import logging +import time + +from avocado import skip +from avocado import skipIf +from avocado import skipUnless +from avocado_qemu import wait_for_console_pattern +from avocado.utils import archive +from avocado.utils import process +from boot_linux_console import LinuxKernelTest + +class ReplayKernelBase(LinuxKernelTest): + """ + Boots a Linux kernel in record mode and checks that the console + is operational and the kernel command line is properly passed + from QEMU to the kernel. + Then replays the same scenario and verifies, that QEMU correctly + terminates. + """ + + timeout = 120 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' + + def run_vm(self, kernel_path, kernel_command_line, console_pattern, + record, shift, args, replay_path): + logger = logging.getLogger('replay') + start_time = time.time() + vm = self.get_vm() + vm.set_console() + if record: + logger.info('recording the execution...') + mode = 'record' + else: + logger.info('replaying the execution...') + mode = 'replay' + vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' % + (shift, mode, replay_path), + '-kernel', kernel_path, + '-append', kernel_command_line, + '-net', 'none', + '-no-reboot') + if args: + vm.add_args(*args) + vm.launch() + self.wait_for_console_pattern(console_pattern, vm) + if record: + vm.shutdown() + logger.info('finished the recording with log size %s bytes' + % os.path.getsize(replay_path)) + else: + vm.wait() + logger.info('successfully finished the replay') + elapsed = time.time() - start_time + logger.info('elapsed time %.2f sec' % elapsed) + return elapsed + + def run_rr(self, kernel_path, kernel_command_line, console_pattern, + shift=7, args=None): + replay_path = os.path.join(self.workdir, 'replay.bin') + t1 = self.run_vm(kernel_path, kernel_command_line, console_pattern, + True, shift, args, replay_path) + t2 = self.run_vm(kernel_path, kernel_command_line, console_pattern, + False, shift, args, replay_path) + logger = logging.getLogger('replay') + logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) + +class ReplayKernelNormal(ReplayKernelBase): + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_x86_64_pc(self): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=machine:pc + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/x86_64/os/images/pxeboot' + '/vmlinuz') + kernel_hash = '23bebd2680757891cf7adedb033532163a792495' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'VFS: Cannot open root device' + + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + def test_mips_malta(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb') + deb_hash = 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-2.6.32-5-4kc-malta') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + def test_mips64el_malta(self): + """ + This test requires the ar tool to extract "data.tar.gz" from + the Debian package. + + The kernel can be rebuilt using this Debian kernel source [1] and + following the instructions on [2]. + + [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/ + #linux-source-2.6.32_2.6.32-48 + [2] https://kernel-team.pages.debian.net/kernel-handbook/ + ch-common-tasks.html#s-common-official + + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb') + deb_hash = '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-2.6.32-5-5kc-malta') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + def test_aarch64_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a53 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/aarch64/os/images/pxeboot' + '/vmlinuz') + kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'VFS: Cannot open root device' + + self.run_rr(kernel_path, kernel_command_line, console_pattern) + + def test_arm_virt(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:virt + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/armhfp/os/images/pxeboot' + '/vmlinuz') + kernel_hash = 'e9826d741b4fb04cadba8d4824d1ed3b7fb8b4d4' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'VFS: Cannot open root device' + + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1) + + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_arm_cubieboard_initrd(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:cubieboard + """ + deb_url = ('https://apt.armbian.com/pool/main/l/' + 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') + deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinuz-5.10.16-sunxi') + dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb' + dtb_path = self.extract_from_deb(deb_path, dtb_path) + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.cpio.gz') + initrd_hash = '2b50f1873e113523967806f4da2afe385462ff9b' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = os.path.join(self.workdir, 'rootfs.cpio') + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'panic=-1 noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1, + args=('-dtb', dtb_path, + '-initrd', initrd_path, + '-no-reboot')) + + def test_s390x_s390_ccw_virtio(self): + """ + :avocado: tags=arch:s390x + :avocado: tags=machine:s390-ccw-virtio + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/s390x/os/images' + '/kernel.img') + kernel_hash = 'e8e8439103ef8053418ef062644ffd46a7919313' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=sclp0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=9) + + def test_alpha_clipper(self): + """ + :avocado: tags=arch:alpha + :avocado: tags=machine:clipper + """ + kernel_url = ('http://archive.debian.org/debian/dists/lenny/main/' + 'installer-alpha/20090123lenny10/images/cdrom/vmlinuz') + kernel_hash = '3a943149335529e2ed3e74d0d787b85fb5671ba3' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + uncompressed_kernel = archive.uncompress(kernel_path, self.workdir) + + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(uncompressed_kernel, kernel_command_line, console_pattern, shift=9, + args=('-nodefaults', )) + + def test_ppc64_pseries(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:pseries + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/ppc64le/os' + '/ppc/ppc64/vmlinuz') + kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' + # icount is not good enough for PPC64 for complete boot yet + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern) + + def test_m68k_q800(self): + """ + :avocado: tags=arch:m68k + :avocado: tags=machine:q800 + """ + deb_url = ('https://snapshot.debian.org/archive/debian-ports' + '/20191021T083923Z/pool-m68k/main' + '/l/linux/kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb') + deb_hash = '044954bb9be4160a3ce81f8bc1b5e856b75cccd1' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-5.3.0-1-m68k') + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 vga=off') + console_pattern = 'No filesystem could mount root' + self.run_rr(kernel_path, kernel_command_line, console_pattern) + + def do_test_advcal_2018(self, file_path, kernel_name, args=None): + archive.extract(file_path, self.workdir) + + for entry in os.scandir(self.workdir): + if entry.name.startswith('day') and entry.is_dir(): + kernel_path = os.path.join(entry.path, kernel_name) + break + + kernel_command_line = '' + console_pattern = 'QEMU advent calendar' + self.run_rr(kernel_path, kernel_command_line, console_pattern, + args=args) + + def test_arm_vexpressa9(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:vexpress-a9 + """ + tar_hash = '32b7677ce8b6f1471fb0059865f451169934245b' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day16.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + dtb_path = self.workdir + '/day16/vexpress-v2p-ca9.dtb' + self.do_test_advcal_2018(file_path, 'winter.zImage', + args=('-dtb', dtb_path)) + + def test_m68k_mcf5208evb(self): + """ + :avocado: tags=arch:m68k + :avocado: tags=machine:mcf5208evb + """ + tar_hash = 'ac688fd00561a2b6ce1359f9ff6aa2b98c9a570c' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day07.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'sanity-clause.elf') + + @skip("Test currently broken") # Console stuck as of 5.2-rc1 + def test_microblaze_s3adsp1800(self): + """ + :avocado: tags=arch:microblaze + :avocado: tags=machine:petalogix-s3adsp1800 + """ + tar_hash = '08bf3e3bfb6b6c7ce1e54ab65d54e189f2caf13f' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day17.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'ballerina.bin') + + def test_ppc64_e500(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:ppce500 + :avocado: tags=cpu:e5500 + """ + tar_hash = '6951d86d644b302898da2fd701739c9406527fe1' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day19.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'uImage') + + def test_or1k_sim(self): + """ + :avocado: tags=arch:or1k + :avocado: tags=machine:or1k-sim + """ + tar_hash = '20334cdaf386108c530ff0badaecc955693027dd' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day20.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'vmlinux') + + def test_nios2_10m50(self): + """ + :avocado: tags=arch:nios2 + :avocado: tags=machine:10m50-ghrd + """ + tar_hash = 'e4251141726c412ac0407c5a6bceefbbff018918' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day14.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'vmlinux.elf') + + def test_ppc_g3beige(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:g3beige + """ + tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day15.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'invaders.elf', + args=('-M', 'graphics=off')) + + def test_ppc_mac99(self): + """ + :avocado: tags=arch:ppc + :avocado: tags=machine:mac99 + """ + tar_hash = 'e0b872a5eb8fdc5bed19bd43ffe863900ebcedfc' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day15.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'invaders.elf', + args=('-M', 'graphics=off')) + + def test_sparc_ss20(self): + """ + :avocado: tags=arch:sparc + :avocado: tags=machine:SS-20 + """ + tar_hash = 'b18550d5d61c7615d989a06edace051017726a9f' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day11.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'zImage.elf') + + def test_xtensa_lx60(self): + """ + :avocado: tags=arch:xtensa + :avocado: tags=machine:lx60 + :avocado: tags=cpu:dc233c + """ + tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34' + tar_url = ('https://www.qemu-advent-calendar.org' + '/2018/download/day02.tar.xz') + file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) + self.do_test_advcal_2018(file_path, 'santas-sleigh-ride.elf') + +@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') +class ReplayKernelSlow(ReplayKernelBase): + # Override the timeout, because this kernel includes an inner + # loop which is executed with TB recompilings during replay, + # making it very slow. + timeout = 180 + + def test_mips_malta_cpio(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + :avocado: tags=slowness:high + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20160601T041800Z/pool/main/l/linux/' + 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb') + deb_hash = 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-4.5.0-2-4kc-malta') + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' + 'mips/rootfs.cpio.gz') + initrd_hash = 'bf806e17009360a866bf537f6de66590de349a99' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = self.workdir + "rootfs.cpio" + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=('-initrd', initrd_path)) + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_mips64el_malta_5KEc_cpio(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=slowness:high + :avocado: tags=cpu:5KEc + """ + kernel_url = ('https://github.com/philmd/qemu-testing-blob/' + 'raw/9ad2df38/mips/malta/mips64el/' + 'vmlinux-3.19.3.mtoman.20150408') + kernel_hash = '00d1d268fb9f7d8beda1de6bebcc46e884d71754' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + initrd_url = ('https://github.com/groeck/linux-build-test/' + 'raw/8584a59e/rootfs/' + 'mipsel64/rootfs.mipsel64r1.cpio.gz') + initrd_hash = '1dbb8a396e916847325284dbe2151167' + initrd_path_gz = self.fetch_asset(initrd_url, algorithm='md5', + asset_hash=initrd_hash) + initrd_path = self.workdir + "rootfs.cpio" + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=('-initrd', initrd_path)) + + def do_test_mips_malta32el_nanomips(self, kernel_path_xz): + kernel_path = self.workdir + "kernel" + with lzma.open(kernel_path_xz, 'rb') as f_in: + with open(kernel_path, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'mem=256m@@0x0 ' + 'console=ttyS0') + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + def test_mips_malta32el_nanomips_4k(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=cpu:I7200 + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page4k.xz') + kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) + + def test_mips_malta32el_nanomips_16k_up(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=cpu:I7200 + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page16k_up.xz') + kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) + + def test_mips_malta32el_nanomips_64k_dbg(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=cpu:I7200 + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page64k_dbg.xz') + kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) diff --git a/tests/avocado/replay_linux.py b/tests/avocado/replay_linux.py new file mode 100644 index 0000000000..15953f9e49 --- /dev/null +++ b/tests/avocado/replay_linux.py @@ -0,0 +1,116 @@ +# Record/replay test that boots a complete Linux system via a cloud image +# +# Copyright (c) 2020 ISP RAS +# +# Author: +# Pavel Dovgalyuk +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import logging +import time + +from avocado import skipUnless +from avocado.utils import cloudinit +from avocado.utils import network +from avocado.utils import vmimage +from avocado.utils import datadrainer +from avocado.utils.path import find_command +from avocado_qemu import LinuxTest + +class ReplayLinux(LinuxTest): + """ + Boots a Linux system, checking for a successful initialization + """ + + timeout = 1800 + chksum = None + hdd = 'ide-hd' + cd = 'ide-cd' + bus = 'ide' + + def setUp(self): + super(ReplayLinux, self).setUp() + self.boot_path = self.download_boot() + self.cloudinit_path = self.prepare_cloudinit() + + def vm_add_disk(self, vm, path, id, device): + bus_string = '' + if self.bus: + bus_string = ',bus=%s.%d' % (self.bus, id,) + vm.add_args('-drive', 'file=%s,snapshot,id=disk%s,if=none' % (path, id)) + vm.add_args('-drive', + 'driver=blkreplay,id=disk%s-rr,if=none,image=disk%s' % (id, id)) + vm.add_args('-device', + '%s,drive=disk%s-rr%s' % (device, id, bus_string)) + + def launch_and_wait(self, record, args, shift): + vm = self.get_vm() + vm.add_args('-smp', '1') + vm.add_args('-m', '1024') + vm.add_args('-object', 'filter-replay,id=replay,netdev=hub0port0') + if args: + vm.add_args(*args) + self.vm_add_disk(vm, self.boot_path, 0, self.hdd) + self.vm_add_disk(vm, self.cloudinit_path, 1, self.cd) + logger = logging.getLogger('replay') + if record: + logger.info('recording the execution...') + mode = 'record' + else: + logger.info('replaying the execution...') + mode = 'replay' + replay_path = os.path.join(self.workdir, 'replay.bin') + vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' % + (shift, mode, replay_path)) + + start_time = time.time() + + vm.set_console() + vm.launch() + console_drainer = datadrainer.LineLogger(vm.console_socket.fileno(), + logger=self.log.getChild('console'), + stop_check=(lambda : not vm.is_running())) + console_drainer.start() + if record: + cloudinit.wait_for_phone_home(('0.0.0.0', self.phone_home_port), + self.name) + vm.shutdown() + logger.info('finished the recording with log size %s bytes' + % os.path.getsize(replay_path)) + else: + vm.event_wait('SHUTDOWN', self.timeout) + vm.shutdown(True) + logger.info('successfully fihished the replay') + elapsed = time.time() - start_time + logger.info('elapsed time %.2f sec' % elapsed) + return elapsed + + def run_rr(self, args=None, shift=7): + t1 = self.launch_and_wait(True, args, shift) + t2 = self.launch_and_wait(False, args, shift) + logger = logging.getLogger('replay') + logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) + +@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') +class ReplayLinuxX8664(ReplayLinux): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=accel:tcg + """ + + chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0' + + def test_pc_i440fx(self): + """ + :avocado: tags=machine:pc + """ + self.run_rr(shift=1) + + def test_pc_q35(self): + """ + :avocado: tags=machine:q35 + """ + self.run_rr(shift=3) diff --git a/tests/avocado/reverse_debugging.py b/tests/avocado/reverse_debugging.py new file mode 100644 index 0000000000..d2921e70c3 --- /dev/null +++ b/tests/avocado/reverse_debugging.py @@ -0,0 +1,210 @@ +# Reverse debugging test +# +# Copyright (c) 2020 ISP RAS +# +# Author: +# Pavel Dovgalyuk +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import os +import logging + +from avocado import skipIf +from avocado_qemu import BUILD_DIR +from avocado.utils import gdb +from avocado.utils import process +from avocado.utils.network.ports import find_free_port +from avocado.utils.path import find_command +from boot_linux_console import LinuxKernelTest + +class ReverseDebugging(LinuxKernelTest): + """ + Test GDB reverse debugging commands: reverse step and reverse continue. + Recording saves the execution of some instructions and makes an initial + VM snapshot to allow reverse execution. + Replay saves the order of the first instructions and then checks that they + are executed backwards in the correct order. + After that the execution is replayed to the end, and reverse continue + command is checked by setting several breakpoints, and asserting + that the execution is stopped at the last of them. + """ + + timeout = 10 + STEPS = 10 + endian_is_le = True + + def run_vm(self, record, shift, args, replay_path, image_path, port): + logger = logging.getLogger('replay') + vm = self.get_vm() + vm.set_console() + if record: + logger.info('recording the execution...') + mode = 'record' + else: + logger.info('replaying the execution...') + mode = 'replay' + vm.add_args('-gdb', 'tcp::%d' % port, '-S') + vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s,rrsnapshot=init' % + (shift, mode, replay_path), + '-net', 'none') + vm.add_args('-drive', 'file=%s,if=none' % image_path) + if args: + vm.add_args(*args) + vm.launch() + return vm + + @staticmethod + def get_reg_le(g, reg): + res = g.cmd(b'p%x' % reg) + num = 0 + for i in range(len(res))[-2::-2]: + num = 0x100 * num + int(res[i:i + 2], 16) + return num + + @staticmethod + def get_reg_be(g, reg): + res = g.cmd(b'p%x' % reg) + return int(res, 16) + + def get_reg(self, g, reg): + # value may be encoded in BE or LE order + if self.endian_is_le: + return self.get_reg_le(g, reg) + else: + return self.get_reg_be(g, reg) + + def get_pc(self, g): + return self.get_reg(g, self.REG_PC) + + def check_pc(self, g, addr): + pc = self.get_pc(g) + if pc != addr: + self.fail('Invalid PC (read %x instead of %x)' % (pc, addr)) + + @staticmethod + def gdb_step(g): + g.cmd(b's', b'T05thread:01;') + + @staticmethod + def gdb_bstep(g): + g.cmd(b'bs', b'T05thread:01;') + + @staticmethod + def vm_get_icount(vm): + return vm.qmp('query-replay')['return']['icount'] + + def reverse_debugging(self, shift=7, args=None): + logger = logging.getLogger('replay') + + # create qcow2 for snapshots + logger.info('creating qcow2 image for VM snapshots') + image_path = os.path.join(self.workdir, 'disk.qcow2') + qemu_img = os.path.join(BUILD_DIR, 'qemu-img') + if not os.path.exists(qemu_img): + qemu_img = find_command('qemu-img', False) + if qemu_img is False: + self.cancel('Could not find "qemu-img", which is required to ' + 'create the temporary qcow2 image') + cmd = '%s create -f qcow2 %s 128M' % (qemu_img, image_path) + process.run(cmd) + + replay_path = os.path.join(self.workdir, 'replay.bin') + port = find_free_port() + + # record the log + vm = self.run_vm(True, shift, args, replay_path, image_path, port) + while self.vm_get_icount(vm) <= self.STEPS: + pass + last_icount = self.vm_get_icount(vm) + vm.shutdown() + + logger.info("recorded log with %s+ steps" % last_icount) + + # replay and run debug commands + vm = self.run_vm(False, shift, args, replay_path, image_path, port) + logger.info('connecting to gdbstub') + g = gdb.GDBRemote('127.0.0.1', port, False, False) + g.connect() + r = g.cmd(b'qSupported') + if b'qXfer:features:read+' in r: + g.cmd(b'qXfer:features:read:target.xml:0,ffb') + if b'ReverseStep+' not in r: + self.fail('Reverse step is not supported by QEMU') + if b'ReverseContinue+' not in r: + self.fail('Reverse continue is not supported by QEMU') + + logger.info('stepping forward') + steps = [] + # record first instruction addresses + for _ in range(self.STEPS): + pc = self.get_pc(g) + logger.info('saving position %x' % pc) + steps.append(pc) + self.gdb_step(g) + + # visit the recorded instruction in reverse order + logger.info('stepping backward') + for addr in steps[::-1]: + self.gdb_bstep(g) + self.check_pc(g, addr) + logger.info('found position %x' % addr) + + logger.info('seeking to the end (icount %s)' % (last_icount - 1)) + vm.qmp('replay-break', icount=last_icount - 1) + # continue - will return after pausing + g.cmd(b'c', b'T02thread:01;') + + logger.info('setting breakpoints') + for addr in steps: + # hardware breakpoint at addr with len=1 + g.cmd(b'Z1,%x,1' % addr, b'OK') + + logger.info('running reverse continue to reach %x' % steps[-1]) + # reverse continue - will return after stopping at the breakpoint + g.cmd(b'bc', b'T05thread:01;') + + # assume that none of the first instructions is executed again + # breaking the order of the breakpoints + self.check_pc(g, steps[-1]) + logger.info('successfully reached %x' % steps[-1]) + + logger.info('exitting gdb and qemu') + vm.shutdown() + +class ReverseDebugging_X86_64(ReverseDebugging): + REG_PC = 0x10 + REG_CS = 0x12 + def get_pc(self, g): + return self.get_reg_le(g, self.REG_PC) \ + + self.get_reg_le(g, self.REG_CS) * 0x10 + + # unidentified gitlab timeout problem + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_x86_64_pc(self): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=machine:pc + """ + # start with BIOS only + self.reverse_debugging() + +class ReverseDebugging_AArch64(ReverseDebugging): + REG_PC = 32 + + # unidentified gitlab timeout problem + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + def test_aarch64_virt(self): + """ + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a53 + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' + '/linux/releases/29/Everything/aarch64/os/images/pxeboot' + '/vmlinuz') + kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.reverse_debugging( + args=('-kernel', kernel_path)) diff --git a/tests/avocado/smmu.py b/tests/avocado/smmu.py new file mode 100644 index 0000000000..b3c4de6bf4 --- /dev/null +++ b/tests/avocado/smmu.py @@ -0,0 +1,137 @@ +# SMMUv3 Functional tests +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Eric Auger +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import os + +from avocado import skipIf +from avocado_qemu import LinuxTest, BUILD_DIR + +@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') +class SMMU(LinuxTest): + """ + :avocado: tags=accel:kvm + :avocado: tags=cpu:host + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=distro:fedora + :avocado: tags=smmu + """ + + IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' + kernel_path = None + initrd_path = None + kernel_params = None + + def set_up_boot(self): + path = self.download_boot() + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,scsi=off,' + + 'drive=drv0,id=virtio-disk0,bootindex=1,' + 'werror=stop,rerror=stop' + self.IOMMU_ADDON) + self.vm.add_args('-drive', + 'file=%s,if=none,cache=writethrough,id=drv0' % path) + + def setUp(self): + super(SMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) + + def common_vm_setup(self, custom_kernel=False): + self.require_accelerator("kvm") + self.vm.add_args("-accel", "kvm") + self.vm.add_args("-cpu", "host") + self.vm.add_args("-machine", "iommu=smmuv3") + self.vm.add_args("-d", "guest_errors") + self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', + 'edk2-aarch64-code.fd')) + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + + if custom_kernel is False: + return + + kernel_url = self.distro.pxeboot_url + 'vmlinuz' + initrd_url = self.distro.pxeboot_url + 'initrd.img' + self.kernel_path = self.fetch_asset(kernel_url) + self.initrd_path = self.fetch_asset(initrd_url) + + def run_and_check(self): + if self.kernel_path: + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-initrd', self.initrd_path) + self.launch_and_wait() + self.ssh_command('cat /proc/cmdline') + self.ssh_command('dnf -y install numactl-devel') + + + # 5.3 kernel without RIL # + + def test_smmu_noril(self): + """ + :avocado: tags=smmu_noril + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup() + self.run_and_check() + + def test_smmu_noril_passthrough(self): + """ + :avocado: tags=smmu_noril_passthrough + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.passthrough=on') + self.run_and_check() + + def test_smmu_noril_nostrict(self): + """ + :avocado: tags=smmu_noril_nostrict + :avocado: tags=smmu_noril_tests + :avocado: tags=distro_version:31 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.strict=0') + self.run_and_check() + + # 5.8 kernel featuring range invalidation + # >= v5.7 kernel + + def test_smmu_ril(self): + """ + :avocado: tags=smmu_ril + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup() + self.run_and_check() + + def test_smmu_ril_passthrough(self): + """ + :avocado: tags=smmu_ril_passthrough + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.passthrough=on') + self.run_and_check() + + def test_smmu_ril_nostrict(self): + """ + :avocado: tags=smmu_ril_nostrict + :avocado: tags=smmu_ril_tests + :avocado: tags=distro_version:33 + """ + self.common_vm_setup(True) + self.kernel_params = (self.distro.default_kernel_params + + ' iommu.strict=0') + self.run_and_check() diff --git a/tests/avocado/tcg_plugins.py b/tests/avocado/tcg_plugins.py new file mode 100644 index 0000000000..9ca1515c3b --- /dev/null +++ b/tests/avocado/tcg_plugins.py @@ -0,0 +1,147 @@ +# TCG Plugins tests +# +# These are a little more involved than the basic tests run by check-tcg. +# +# Copyright (c) 2021 Linaro +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import tempfile +import mmap +import re + +from boot_linux_console import LinuxKernelTest + + +class PluginKernelBase(LinuxKernelTest): + """ + Boots a Linux kernel with a TCG plugin enabled. + """ + + timeout = 120 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' + + def run_vm(self, kernel_path, kernel_command_line, + plugin, plugin_log, console_pattern, args=None): + + vm = self.get_vm() + vm.set_console() + vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-plugin', plugin, + '-d', 'plugin', + '-D', plugin_log, + '-net', 'none', + '-no-reboot') + if args: + vm.add_args(*args) + + try: + vm.launch() + except: + # TODO: probably fails because plugins not enabled but we + # can't currently probe for the feature. + self.cancel("TCG Plugins not enabled?") + + self.wait_for_console_pattern(console_pattern, vm) + # ensure logs are flushed + vm.shutdown() + + +class PluginKernelNormal(PluginKernelBase): + + def _grab_aarch64_kernel(self): + kernel_url = ('http://security.debian.org/' + 'debian-security/pool/updates/main/l/linux-signed-arm64/' + 'linux-image-4.19.0-12-arm64_4.19.152-1_arm64.deb') + kernel_sha1 = '2036c2792f80ac9c4ccaae742b2e0a28385b6010' + kernel_deb = self.fetch_asset(kernel_url, asset_hash=kernel_sha1) + kernel_path = self.extract_from_deb(kernel_deb, + "/boot/vmlinuz-4.19.0-12-arm64") + return kernel_path + + def test_aarch64_virt_insn(self): + """ + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a53 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'Kernel panic - not syncing: VFS:' + + plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", + suffix=".log") + + self.run_vm(kernel_path, kernel_command_line, + "tests/plugin/libinsn.so", plugin_log.name, + console_pattern) + + with plugin_log as lf, \ + mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: + + m = re.search(br"insns: (?P\d+)", s) + if "count" not in m.groupdict(): + self.fail("Failed to find instruction count") + + def test_aarch64_virt_insn_icount(self): + """ + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a53 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'Kernel panic - not syncing: VFS:' + + plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", + suffix=".log") + + self.run_vm(kernel_path, kernel_command_line, + "tests/plugin/libinsn.so", plugin_log.name, + console_pattern, + args=('-icount', 'shift=1')) + + with plugin_log as lf, \ + mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: + m = re.search(br"detected repeat execution @ (?P0x[0-9A-Fa-f]+)", s) + if m is not None and "addr" in m.groupdict(): + self.fail("detected repeated instructions") + + def test_aarch64_virt_mem_icount(self): + """ + :avocado: tags=accel:tcg + :avocado: tags=arch:aarch64 + :avocado: tags=machine:virt + :avocado: tags=cpu:cortex-a53 + """ + kernel_path = self._grab_aarch64_kernel() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'Kernel panic - not syncing: VFS:' + + plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", + suffix=".log") + + self.run_vm(kernel_path, kernel_command_line, + "tests/plugin/libmem.so,arg=both", plugin_log.name, + console_pattern, + args=('-icount', 'shift=1')) + + with plugin_log as lf, \ + mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: + m = re.findall(br"mem accesses: (?P\d+)", s) + if m is None or len(m) != 2: + self.fail("no memory access counts found") + else: + inline = int(m[0]) + callback = int(m[1]) + if inline != callback: + self.fail("mismatched access counts") diff --git a/tests/avocado/tesseract_utils.py b/tests/avocado/tesseract_utils.py new file mode 100644 index 0000000000..72cd9ab798 --- /dev/null +++ b/tests/avocado/tesseract_utils.py @@ -0,0 +1,46 @@ +# ... +# +# Copyright (c) 2019 Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import re +import logging + +from avocado.utils import process +from avocado.utils.path import find_command, CmdNotFoundError + +def tesseract_available(expected_version): + try: + find_command('tesseract') + except CmdNotFoundError: + return False + res = process.run('tesseract --version') + try: + version = res.stdout_text.split()[1] + except IndexError: + version = res.stderr_text.split()[1] + return int(version.split('.')[0]) == expected_version + + match = re.match(r'tesseract\s(\d)', res) + if match is None: + return False + # now this is guaranteed to be a digit + return int(match.groups()[0]) == expected_version + + +def tesseract_ocr(image_path, tesseract_args='', tesseract_version=3): + console_logger = logging.getLogger('tesseract') + console_logger.debug(image_path) + if tesseract_version == 4: + tesseract_args += ' --oem 1' + proc = process.run("tesseract {} {} stdout".format(tesseract_args, + image_path)) + lines = [] + for line in proc.stdout_text.split('\n'): + sline = line.strip() + if len(sline): + console_logger.debug(sline) + lines += [sline] + return lines diff --git a/tests/avocado/version.py b/tests/avocado/version.py new file mode 100644 index 0000000000..79b923d4fc --- /dev/null +++ b/tests/avocado/version.py @@ -0,0 +1,24 @@ +# Version check example test +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + + +from avocado_qemu import Test + + +class Version(Test): + """ + :avocado: tags=quick + """ + def test_qmp_human_info_version(self): + self.vm.add_args('-nodefaults') + self.vm.launch() + res = self.vm.command('human-monitor-command', + command_line='info version') + self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)') diff --git a/tests/avocado/virtio-gpu.py b/tests/avocado/virtio-gpu.py new file mode 100644 index 0000000000..4acc1e6d5f --- /dev/null +++ b/tests/avocado/virtio-gpu.py @@ -0,0 +1,155 @@ +# virtio-gpu tests +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + + +from avocado_qemu import Test +from avocado_qemu import BUILD_DIR +from avocado_qemu import wait_for_console_pattern +from avocado_qemu import exec_command_and_wait_for_pattern +from avocado_qemu import is_readable_executable_file + +from qemu.utils import kvm_available + +import os +import socket +import subprocess + + +def pick_default_vug_bin(): + relative_path = "./contrib/vhost-user-gpu/vhost-user-gpu" + if is_readable_executable_file(relative_path): + return relative_path + + bld_dir_path = os.path.join(BUILD_DIR, relative_path) + if is_readable_executable_file(bld_dir_path): + return bld_dir_path + + +class VirtioGPUx86(Test): + """ + :avocado: tags=virtio-gpu + :avocado: tags=arch:x86_64 + :avocado: tags=cpu:host + """ + + KERNEL_COMMAND_LINE = "printk.time=0 console=ttyS0 rdinit=/bin/bash" + KERNEL_URL = ( + "https://archives.fedoraproject.org/pub/fedora" + "/linux/releases/33/Everything/x86_64/os/images" + "/pxeboot/vmlinuz" + ) + KERNEL_HASH = '1433cfe3f2ffaa44de4ecfb57ec25dc2399cdecf' + INITRD_URL = ( + "https://archives.fedoraproject.org/pub/fedora" + "/linux/releases/33/Everything/x86_64/os/images" + "/pxeboot/initrd.img" + ) + INITRD_HASH = 'c828d68a027b53e5220536585efe03412332c2d9' + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern( + self, + success_message, + failure_message="Kernel panic - not syncing", + vm=vm, + ) + + def test_virtio_vga_virgl(self): + """ + :avocado: tags=device:virtio-vga-gl + """ + # FIXME: should check presence of virtio, virgl etc + self.require_accelerator('kvm') + + kernel_path = self.fetch_asset(self.KERNEL_URL, self.KERNEL_HASH) + initrd_path = self.fetch_asset(self.INITRD_URL, self.INITRD_HASH) + + self.vm.set_console() + self.vm.add_args("-m", "2G") + self.vm.add_args("-machine", "pc,accel=kvm") + self.vm.add_args("-device", "virtio-vga-gl") + self.vm.add_args("-display", "egl-headless") + self.vm.add_args( + "-kernel", + kernel_path, + "-initrd", + initrd_path, + "-append", + self.KERNEL_COMMAND_LINE, + ) + try: + self.vm.launch() + except: + # TODO: probably fails because we are missing the VirGL features + self.cancel("VirGL not enabled?") + + self.wait_for_console_pattern("as init process") + exec_command_and_wait_for_pattern( + self, "/usr/sbin/modprobe virtio_gpu", "" + ) + self.wait_for_console_pattern("features: +virgl +edid") + + def test_vhost_user_vga_virgl(self): + """ + :avocado: tags=device:vhost-user-vga + """ + # FIXME: should check presence of vhost-user-gpu, virgl, memfd etc + self.require_accelerator('kvm') + + vug = pick_default_vug_bin() + if not vug: + self.cancel("Could not find vhost-user-gpu") + + kernel_path = self.fetch_asset(self.KERNEL_URL, self.KERNEL_HASH) + initrd_path = self.fetch_asset(self.INITRD_URL, self.INITRD_HASH) + + # Create socketpair to connect proxy and remote processes + qemu_sock, vug_sock = socket.socketpair( + socket.AF_UNIX, socket.SOCK_STREAM + ) + os.set_inheritable(qemu_sock.fileno(), True) + os.set_inheritable(vug_sock.fileno(), True) + + self._vug_log_path = os.path.join( + self.logdir, "vhost-user-gpu.log" + ) + self._vug_log_file = open(self._vug_log_path, "wb") + self.log.info('Complete vhost-user-gpu.log file can be ' + 'found at %s', self._vug_log_path) + + vugp = subprocess.Popen( + [vug, "--virgl", "--fd=%d" % vug_sock.fileno()], + stdin=subprocess.DEVNULL, + stdout=self._vug_log_file, + stderr=subprocess.STDOUT, + shell=False, + close_fds=False, + ) + + self.vm.set_console() + self.vm.add_args("-m", "2G") + self.vm.add_args("-object", "memory-backend-memfd,id=mem,size=2G") + self.vm.add_args("-machine", "pc,memory-backend=mem,accel=kvm") + self.vm.add_args("-chardev", "socket,id=vug,fd=%d" % qemu_sock.fileno()) + self.vm.add_args("-device", "vhost-user-vga,chardev=vug") + self.vm.add_args("-display", "egl-headless") + self.vm.add_args( + "-kernel", + kernel_path, + "-initrd", + initrd_path, + "-append", + self.KERNEL_COMMAND_LINE, + ) + self.vm.launch() + self.wait_for_console_pattern("as init process") + exec_command_and_wait_for_pattern( + self, "/usr/sbin/modprobe virtio_gpu", "" + ) + self.wait_for_console_pattern("features: +virgl -edid") + self.vm.shutdown() + qemu_sock.close() + vugp.terminate() + vugp.wait() diff --git a/tests/avocado/virtio_check_params.py b/tests/avocado/virtio_check_params.py new file mode 100644 index 0000000000..87e6c839d1 --- /dev/null +++ b/tests/avocado/virtio_check_params.py @@ -0,0 +1,144 @@ +# +# Test virtio-scsi and virtio-blk queue settings for all machine types +# +# Copyright (c) 2019 Virtuozzo International GmbH +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import sys +import os +import re +import logging + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) +from qemu.machine import QEMUMachine +from avocado_qemu import Test +from avocado import skip + +#list of machine types and virtqueue properties to test +VIRTIO_SCSI_PROPS = {'seg_max_adjust': 'seg_max_adjust'} +VIRTIO_BLK_PROPS = {'seg_max_adjust': 'seg-max-adjust'} + +DEV_TYPES = {'virtio-scsi-pci': VIRTIO_SCSI_PROPS, + 'virtio-blk-pci': VIRTIO_BLK_PROPS} + +VM_DEV_PARAMS = {'virtio-scsi-pci': ['-device', 'virtio-scsi-pci,id=scsi0'], + 'virtio-blk-pci': ['-device', + 'virtio-blk-pci,id=scsi0,drive=drive0', + '-drive', + 'driver=null-co,id=drive0,if=none']} + + +class VirtioMaxSegSettingsCheck(Test): + @staticmethod + def make_pattern(props): + pattern_items = ['{0} = \w+'.format(prop) for prop in props] + return '|'.join(pattern_items) + + def query_virtqueue(self, vm, dev_type_name): + query_ok = False + error = None + props = None + + output = vm.command('human-monitor-command', + command_line = 'info qtree') + props_list = DEV_TYPES[dev_type_name].values(); + pattern = self.make_pattern(props_list) + res = re.findall(pattern, output) + + if len(res) != len(props_list): + props_list = set(props_list) + res = set(res) + not_found = props_list.difference(res) + not_found = ', '.join(not_found) + error = '({0}): The following properties not found: {1}'\ + .format(dev_type_name, not_found) + else: + query_ok = True + props = dict() + for prop in res: + p = prop.split(' = ') + props[p[0]] = p[1] + return query_ok, props, error + + def check_mt(self, mt, dev_type_name): + mt['device'] = dev_type_name # Only for the debug() call. + logger = logging.getLogger('machine') + logger.debug(mt) + with QEMUMachine(self.qemu_bin) as vm: + vm.set_machine(mt["name"]) + vm.add_args('-nodefaults') + for s in VM_DEV_PARAMS[dev_type_name]: + vm.add_args(s) + try: + vm.launch() + query_ok, props, error = self.query_virtqueue(vm, dev_type_name) + except: + query_ok = False + error = sys.exc_info()[0] + + if not query_ok: + self.fail('machine type {0}: {1}'.format(mt['name'], error)) + + for prop_name, prop_val in props.items(): + expected_val = mt[prop_name] + self.assertEqual(expected_val, prop_val) + + @staticmethod + def seg_max_adjust_enabled(mt): + # machine types >= 5.0 should have seg_max_adjust = true + # others seg_max_adjust = false + mt = mt.split("-") + + # machine types with one line name and name like pc-x.x + if len(mt) <= 2: + return False + + # machine types like pc--x.x[.x] + ver = mt[2] + ver = ver.split("."); + + # versions >= 5.0 goes with seg_max_adjust enabled + major = int(ver[0]) + + if major >= 5: + return True + return False + + @skip("break multi-arch CI") + def test_machine_types(self): + # collect all machine types except 'none', 'isapc', 'microvm' + with QEMUMachine(self.qemu_bin) as vm: + vm.launch() + machines = [m['name'] for m in vm.command('query-machines')] + vm.shutdown() + machines.remove('none') + machines.remove('isapc') + machines.remove('microvm') + + for dev_type in DEV_TYPES: + # create the list of machine types and their parameters. + mtypes = list() + for m in machines: + if self.seg_max_adjust_enabled(m): + enabled = 'true' + else: + enabled = 'false' + mtypes.append({'name': m, + DEV_TYPES[dev_type]['seg_max_adjust']: enabled}) + + # test each machine type for a device type + for mt in mtypes: + self.check_mt(mt, dev_type) diff --git a/tests/avocado/virtio_version.py b/tests/avocado/virtio_version.py new file mode 100644 index 0000000000..33593c29dd --- /dev/null +++ b/tests/avocado/virtio_version.py @@ -0,0 +1,175 @@ +""" +Check compatibility of virtio device types +""" +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +import sys +import os + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) +from qemu.machine import QEMUMachine +from avocado_qemu import Test + +# Virtio Device IDs: +VIRTIO_NET = 1 +VIRTIO_BLOCK = 2 +VIRTIO_CONSOLE = 3 +VIRTIO_RNG = 4 +VIRTIO_BALLOON = 5 +VIRTIO_RPMSG = 7 +VIRTIO_SCSI = 8 +VIRTIO_9P = 9 +VIRTIO_RPROC_SERIAL = 11 +VIRTIO_CAIF = 12 +VIRTIO_GPU = 16 +VIRTIO_INPUT = 18 +VIRTIO_VSOCK = 19 +VIRTIO_CRYPTO = 20 + +PCI_VENDOR_ID_REDHAT_QUMRANET = 0x1af4 + +# Device IDs for legacy/transitional devices: +PCI_LEGACY_DEVICE_IDS = { + VIRTIO_NET: 0x1000, + VIRTIO_BLOCK: 0x1001, + VIRTIO_BALLOON: 0x1002, + VIRTIO_CONSOLE: 0x1003, + VIRTIO_SCSI: 0x1004, + VIRTIO_RNG: 0x1005, + VIRTIO_9P: 0x1009, + VIRTIO_VSOCK: 0x1012, +} + +def pci_modern_device_id(virtio_devid): + return virtio_devid + 0x1040 + +def devtype_implements(vm, devtype, implements): + return devtype in [d['name'] for d in vm.command('qom-list-types', implements=implements)] + +def get_pci_interfaces(vm, devtype): + interfaces = ('pci-express-device', 'conventional-pci-device') + return [i for i in interfaces if devtype_implements(vm, devtype, i)] + +class VirtioVersionCheck(Test): + """ + Check if virtio-version-specific device types result in the + same device tree created by `disable-modern` and + `disable-legacy`. + + :avocado: tags=arch:x86_64 + """ + + # just in case there are failures, show larger diff: + maxDiff = 4096 + + def run_device(self, devtype, opts=None, machine='pc'): + """ + Run QEMU with `-device DEVTYPE`, return device info from `query-pci` + """ + with QEMUMachine(self.qemu_bin) as vm: + vm.set_machine(machine) + if opts: + devtype += ',' + opts + vm.add_args('-device', '%s,id=devfortest' % (devtype)) + vm.add_args('-S') + vm.launch() + + pcibuses = vm.command('query-pci') + alldevs = [dev for bus in pcibuses for dev in bus['devices']] + devfortest = [dev for dev in alldevs + if dev['qdev_id'] == 'devfortest'] + return devfortest[0], get_pci_interfaces(vm, devtype) + + + def assert_devids(self, dev, devid, non_transitional=False): + self.assertEqual(dev['id']['vendor'], PCI_VENDOR_ID_REDHAT_QUMRANET) + self.assertEqual(dev['id']['device'], devid) + if non_transitional: + self.assertTrue(0x1040 <= dev['id']['device'] <= 0x107f) + self.assertGreaterEqual(dev['id']['subsystem'], 0x40) + + def check_all_variants(self, qemu_devtype, virtio_devid): + """Check if a virtio device type and its variants behave as expected""" + # Force modern mode: + dev_modern, _ = self.run_device(qemu_devtype, + 'disable-modern=off,disable-legacy=on') + self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid), + non_transitional=True) + + # -non-transitional device types should be 100% equivalent to + # ,disable-modern=off,disable-legacy=on + dev_1_0, nt_ifaces = self.run_device('%s-non-transitional' % (qemu_devtype)) + self.assertEqual(dev_modern, dev_1_0) + + # Force transitional mode: + dev_trans, _ = self.run_device(qemu_devtype, + 'disable-modern=off,disable-legacy=off') + self.assert_devids(dev_trans, PCI_LEGACY_DEVICE_IDS[virtio_devid]) + + # Force legacy mode: + dev_legacy, _ = self.run_device(qemu_devtype, + 'disable-modern=on,disable-legacy=off') + self.assert_devids(dev_legacy, PCI_LEGACY_DEVICE_IDS[virtio_devid]) + + # No options: default to transitional on PC machine-type: + no_opts_pc, generic_ifaces = self.run_device(qemu_devtype) + self.assertEqual(dev_trans, no_opts_pc) + + #TODO: check if plugging on a PCI Express bus will make the + # device non-transitional + #no_opts_q35 = self.run_device(qemu_devtype, machine='q35') + #self.assertEqual(dev_modern, no_opts_q35) + + # -transitional device types should be 100% equivalent to + # ,disable-modern=off,disable-legacy=off + dev_trans, trans_ifaces = self.run_device('%s-transitional' % (qemu_devtype)) + self.assertEqual(dev_trans, dev_trans) + + # ensure the interface information is correct: + self.assertIn('conventional-pci-device', generic_ifaces) + self.assertIn('pci-express-device', generic_ifaces) + + self.assertIn('conventional-pci-device', nt_ifaces) + self.assertIn('pci-express-device', nt_ifaces) + + self.assertIn('conventional-pci-device', trans_ifaces) + self.assertNotIn('pci-express-device', trans_ifaces) + + + def test_conventional_devs(self): + self.check_all_variants('virtio-net-pci', VIRTIO_NET) + # virtio-blk requires 'driver' parameter + #self.check_all_variants('virtio-blk-pci', VIRTIO_BLOCK) + self.check_all_variants('virtio-serial-pci', VIRTIO_CONSOLE) + self.check_all_variants('virtio-rng-pci', VIRTIO_RNG) + self.check_all_variants('virtio-balloon-pci', VIRTIO_BALLOON) + self.check_all_variants('virtio-scsi-pci', VIRTIO_SCSI) + # virtio-9p requires 'fsdev' parameter + #self.check_all_variants('virtio-9p-pci', VIRTIO_9P) + + def check_modern_only(self, qemu_devtype, virtio_devid): + """Check if a modern-only virtio device type behaves as expected""" + # Force modern mode: + dev_modern, _ = self.run_device(qemu_devtype, + 'disable-modern=off,disable-legacy=on') + self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid), + non_transitional=True) + + # No options: should be modern anyway + dev_no_opts, ifaces = self.run_device(qemu_devtype) + self.assertEqual(dev_modern, dev_no_opts) + + self.assertIn('conventional-pci-device', ifaces) + self.assertIn('pci-express-device', ifaces) + + def test_modern_only_devs(self): + self.check_modern_only('virtio-vga', VIRTIO_GPU) + self.check_modern_only('virtio-gpu-pci', VIRTIO_GPU) + self.check_modern_only('virtio-mouse-pci', VIRTIO_INPUT) + self.check_modern_only('virtio-tablet-pci', VIRTIO_INPUT) + self.check_modern_only('virtio-keyboard-pci', VIRTIO_INPUT) diff --git a/tests/avocado/virtiofs_submounts.py b/tests/avocado/virtiofs_submounts.py new file mode 100644 index 0000000000..21ad7d792e --- /dev/null +++ b/tests/avocado/virtiofs_submounts.py @@ -0,0 +1,272 @@ +import logging +import re +import os +import subprocess +import time + +from avocado import skipUnless +from avocado_qemu import LinuxTest, BUILD_DIR +from avocado_qemu import wait_for_console_pattern +from avocado.utils import ssh + + +def run_cmd(args): + subp = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + stdout, stderr = subp.communicate() + ret = subp.returncode + + return (stdout, stderr, ret) + +def has_cmd(name, args=None): + """ + This function is for use in a @avocado.skipUnless decorator, e.g.: + + @skipUnless(*has_cmd('sudo -n', ('sudo', '-n', 'true'))) + def test_something_that_needs_sudo(self): + ... + """ + + if args is None: + args = ('which', name) + + try: + _, stderr, exitcode = run_cmd(args) + except Exception as e: + exitcode = -1 + stderr = str(e) + + if exitcode != 0: + cmd_line = ' '.join(args) + err = f'{name} required, but "{cmd_line}" failed: {stderr.strip()}' + return (False, err) + else: + return (True, '') + +def has_cmds(*cmds): + """ + This function is for use in a @avocado.skipUnless decorator and + allows checking for the availability of multiple commands, e.g.: + + @skipUnless(*has_cmds(('cmd1', ('cmd1', '--some-parameter')), + 'cmd2', 'cmd3')) + def test_something_that_needs_cmd1_and_cmd2(self): + ... + """ + + for cmd in cmds: + if isinstance(cmd, str): + cmd = (cmd,) + + ok, errstr = has_cmd(*cmd) + if not ok: + return (False, errstr) + + return (True, '') + + +class VirtiofsSubmountsTest(LinuxTest): + """ + :avocado: tags=arch:x86_64 + :avocado: tags=accel:kvm + """ + + def run(self, args, ignore_error=False): + stdout, stderr, ret = run_cmd(args) + + if ret != 0: + cmdline = ' '.join(args) + if not ignore_error: + self.fail(f'{cmdline}: Returned {ret}: {stderr}') + else: + self.log.warn(f'{cmdline}: Returned {ret}: {stderr}') + + return (stdout, stderr, ret) + + def set_up_shared_dir(self): + self.shared_dir = os.path.join(self.workdir, 'virtiofs-shared') + + os.mkdir(self.shared_dir) + + self.run(('cp', self.get_data('guest.sh'), + os.path.join(self.shared_dir, 'check.sh'))) + + self.run(('cp', self.get_data('guest-cleanup.sh'), + os.path.join(self.shared_dir, 'cleanup.sh'))) + + def set_up_virtiofs(self): + attmp = os.getenv('AVOCADO_TESTS_COMMON_TMPDIR') + self.vfsdsock = os.path.join(attmp, 'vfsdsock') + + self.run(('sudo', '-n', 'rm', '-f', self.vfsdsock), ignore_error=True) + + self.virtiofsd = \ + subprocess.Popen(('sudo', '-n', + 'tools/virtiofsd/virtiofsd', + f'--socket-path={self.vfsdsock}', + '-o', f'source={self.shared_dir}', + '-o', 'cache=always', + '-o', 'xattr', + '-o', 'announce_submounts', + '-f'), + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE, + universal_newlines=True) + + while not os.path.exists(self.vfsdsock): + if self.virtiofsd.poll() is not None: + self.fail('virtiofsd exited prematurely: ' + + self.virtiofsd.communicate()[1]) + time.sleep(0.1) + + self.run(('sudo', '-n', 'chmod', 'go+rw', self.vfsdsock)) + + self.vm.add_args('-chardev', + f'socket,id=vfsdsock,path={self.vfsdsock}', + '-device', + 'vhost-user-fs-pci,queue-size=1024,chardev=vfsdsock' \ + ',tag=host', + '-object', + 'memory-backend-file,id=mem,size=1G,' \ + 'mem-path=/dev/shm,share=on', + '-numa', + 'node,memdev=mem') + + def set_up_nested_mounts(self): + scratch_dir = os.path.join(self.shared_dir, 'scratch') + try: + os.mkdir(scratch_dir) + except FileExistsError: + pass + + args = ['bash', self.get_data('host.sh'), scratch_dir] + if self.seed: + args += [self.seed] + + out, _, _ = self.run(args) + seed = re.search(r'^Seed: \d+', out) + self.log.info(seed[0]) + + def mount_in_guest(self): + self.ssh_command('mkdir -p /mnt/host') + self.ssh_command('mount -t virtiofs host /mnt/host') + + def check_in_guest(self): + self.ssh_command('bash /mnt/host/check.sh /mnt/host/scratch/share') + + def live_cleanup(self): + self.ssh_command('bash /mnt/host/cleanup.sh /mnt/host/scratch') + + # It would be nice if the above was sufficient to make virtiofsd clear + # all references to the mounted directories (so they can be unmounted + # on the host), but unfortunately it is not. To do so, we have to + # resort to a remount. + self.ssh_command('mount -o remount /mnt/host') + + scratch_dir = os.path.join(self.shared_dir, 'scratch') + self.run(('bash', self.get_data('cleanup.sh'), scratch_dir)) + + @skipUnless(*has_cmds(('sudo -n', ('sudo', '-n', 'true')), + 'ssh-keygen', 'bash', 'losetup', 'mkfs.xfs', 'mount')) + def setUp(self): + vmlinuz = self.params.get('vmlinuz') + if vmlinuz is None: + """ + The Linux kernel supports FUSE auto-submounts only as of 5.10. + boot_linux.py currently provides Fedora 31, whose kernel is too + old, so this test cannot pass with the on-image kernel (you are + welcome to try, hence the option to force such a test with + -p vmlinuz=''). Therefore, for now the user must provide a + sufficiently new custom kernel, or effectively explicitly + request failure with -p vmlinuz=''. + Once an image with a sufficiently new kernel is available + (probably Fedora 34), we can make -p vmlinuz='' the default, so + that this parameter no longer needs to be specified. + """ + self.cancel('vmlinuz parameter not set; you must point it to a ' + 'Linux kernel binary to test (to run this test with ' \ + 'the on-image kernel, set it to an empty string)') + + self.seed = self.params.get('seed') + + self.ssh_key = os.path.join(self.workdir, 'id_ed25519') + + self.run(('ssh-keygen', '-N', '', '-t', 'ed25519', '-f', self.ssh_key)) + + pubkey = self.ssh_key + '.pub' + + super(VirtiofsSubmountsTest, self).setUp(pubkey) + + if vmlinuz: + self.vm.add_args('-kernel', vmlinuz, + '-append', 'console=ttyS0 root=/dev/sda1') + + self.require_accelerator("kvm") + self.vm.add_args('-accel', 'kvm') + + def tearDown(self): + try: + self.vm.shutdown() + except: + pass + + scratch_dir = os.path.join(self.shared_dir, 'scratch') + self.run(('bash', self.get_data('cleanup.sh'), scratch_dir), + ignore_error=True) + + def test_pre_virtiofsd_set_up(self): + self.set_up_shared_dir() + + self.set_up_nested_mounts() + + self.set_up_virtiofs() + self.launch_and_wait() + self.mount_in_guest() + self.check_in_guest() + + def test_pre_launch_set_up(self): + self.set_up_shared_dir() + self.set_up_virtiofs() + + self.set_up_nested_mounts() + + self.launch_and_wait() + self.mount_in_guest() + self.check_in_guest() + + def test_post_launch_set_up(self): + self.set_up_shared_dir() + self.set_up_virtiofs() + self.launch_and_wait() + + self.set_up_nested_mounts() + + self.mount_in_guest() + self.check_in_guest() + + def test_post_mount_set_up(self): + self.set_up_shared_dir() + self.set_up_virtiofs() + self.launch_and_wait() + self.mount_in_guest() + + self.set_up_nested_mounts() + + self.check_in_guest() + + def test_two_runs(self): + self.set_up_shared_dir() + + self.set_up_nested_mounts() + + self.set_up_virtiofs() + self.launch_and_wait() + self.mount_in_guest() + self.check_in_guest() + + self.live_cleanup() + self.set_up_nested_mounts() + + self.check_in_guest() diff --git a/tests/avocado/virtiofs_submounts.py.data/cleanup.sh b/tests/avocado/virtiofs_submounts.py.data/cleanup.sh new file mode 100644 index 0000000000..2a6579a0fe --- /dev/null +++ b/tests/avocado/virtiofs_submounts.py.data/cleanup.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +function print_usage() +{ + if [ -n "$2" ]; then + echo "Error: $2" + echo + fi + echo "Usage: $1 " +} + +scratch_dir=$1 +if [ -z "$scratch_dir" ]; then + print_usage "$0" 'Scratch dir not given' >&2 + exit 1 +fi + +cd "$scratch_dir/share" || exit 1 +mps=(mnt*) +mp_i=0 +for mp in "${mps[@]}"; do + mp_i=$((mp_i + 1)) + printf "Unmounting %i/%i...\r" "$mp_i" "${#mps[@]}" + + sudo umount -R "$mp" + rm -rf "$mp" +done +echo + +rm some-file +cd .. +rmdir share + +imgs=(fs*.img) +img_i=0 +for img in "${imgs[@]}"; do + img_i=$((img_i + 1)) + printf "Detaching and deleting %i/%i...\r" "$img_i" "${#imgs[@]}" + + dev=$(losetup -j "$img" | sed -e 's/:.*//') + sudo losetup -d "$dev" + rm -f "$img" +done +echo + +echo 'Done.' diff --git a/tests/avocado/virtiofs_submounts.py.data/guest-cleanup.sh b/tests/avocado/virtiofs_submounts.py.data/guest-cleanup.sh new file mode 100644 index 0000000000..729cb2d1a5 --- /dev/null +++ b/tests/avocado/virtiofs_submounts.py.data/guest-cleanup.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +function print_usage() +{ + if [ -n "$2" ]; then + echo "Error: $2" + echo + fi + echo "Usage: $1 " +} + +scratch_dir=$1 +if [ -z "$scratch_dir" ]; then + print_usage "$0" 'Scratch dir not given' >&2 + exit 1 +fi + +cd "$scratch_dir/share" || exit 1 + +mps=(mnt*) +mp_i=0 +for mp in "${mps[@]}"; do + mp_i=$((mp_i + 1)) + printf "Unmounting %i/%i...\r" "$mp_i" "${#mps[@]}" + + sudo umount -R "$mp" +done +echo + +echo 'Done.' diff --git a/tests/avocado/virtiofs_submounts.py.data/guest.sh b/tests/avocado/virtiofs_submounts.py.data/guest.sh new file mode 100644 index 0000000000..59ba40fde1 --- /dev/null +++ b/tests/avocado/virtiofs_submounts.py.data/guest.sh @@ -0,0 +1,138 @@ +#!/bin/bash + +function print_usage() +{ + if [ -n "$2" ]; then + echo "Error: $2" + echo + fi + echo "Usage: $1 " + echo '(The shared directory is the "share" directory in the scratch' \ + 'directory)' +} + +shared_dir=$1 +if [ -z "$shared_dir" ]; then + print_usage "$0" 'Shared dir not given' >&2 + exit 1 +fi + +cd "$shared_dir" + +# FIXME: This should not be necessary, but it is. In order for all +# submounts to be proper mount points, we need to visit them. +# (Before we visit them, they will not be auto-mounted, and so just +# appear as normal directories, with the catch that their st_ino will +# be the st_ino of the filesystem they host, while the st_dev will +# still be the st_dev of the parent.) +# `find` does not work, because it will refuse to touch the mount +# points as long as they are not mounted; their st_dev being shared +# with the parent and st_ino just being the root node's inode ID +# will practically ensure that this node exists elsewhere on the +# filesystem, and `find` is required to recognize loops and not to +# follow them. +# Thus, we have to manually visit all nodes first. + +mnt_i=0 + +function recursively_visit() +{ + pushd "$1" >/dev/null + for entry in *; do + if [[ "$entry" == mnt* ]]; then + mnt_i=$((mnt_i + 1)) + printf "Triggering auto-mount $mnt_i...\r" + fi + + if [ -d "$entry" ]; then + recursively_visit "$entry" + fi + done + popd >/dev/null +} + +recursively_visit . +echo + + +if [ -n "$(find -name not-mounted)" ]; then + echo "Error: not-mounted files visible on mount points:" >&2 + find -name not-mounted >&2 + exit 1 +fi + +if [ ! -f some-file -o "$(cat some-file)" != 'root' ]; then + echo "Error: Bad file in the share root" >&2 + exit 1 +fi + +shopt -s nullglob + +function check_submounts() +{ + local base_path=$1 + + for mp in mnt*; do + printf "Checking submount %i...\r" "$((${#devs[@]} + 1))" + + mp_i=$(echo "$mp" | sed -e 's/mnt//') + dev=$(stat -c '%D' "$mp") + + if [ -n "${devs[mp_i]}" ]; then + echo "Error: $mp encountered twice" >&2 + exit 1 + fi + devs[mp_i]=$dev + + pushd "$mp" >/dev/null + path="$base_path$mp" + while true; do + expected_content="$(printf '%s\n%s\n' "$mp_i" "$path")" + if [ ! -f some-file ]; then + echo "Error: $PWD/some-file does not exist" >&2 + exit 1 + fi + + if [ "$(cat some-file)" != "$expected_content" ]; then + echo "Error: Bad content in $PWD/some-file:" >&2 + echo '--- found ---' + cat some-file + echo '--- expected ---' + echo "$expected_content" + exit 1 + fi + if [ "$(stat -c '%D' some-file)" != "$dev" ]; then + echo "Error: $PWD/some-file has the wrong device ID" >&2 + exit 1 + fi + + if [ -d sub ]; then + if [ "$(stat -c '%D' sub)" != "$dev" ]; then + echo "Error: $PWD/some-file has the wrong device ID" >&2 + exit 1 + fi + cd sub + path="$path/sub" + else + if [ -n "$(echo mnt*)" ]; then + check_submounts "$path/" + fi + break + fi + done + popd >/dev/null + done +} + +root_dev=$(stat -c '%D' some-file) +devs=() +check_submounts '' +echo + +reused_devs=$(echo "$root_dev ${devs[@]}" | tr ' ' '\n' | sort | uniq -d) +if [ -n "$reused_devs" ]; then + echo "Error: Reused device IDs: $reused_devs" >&2 + exit 1 +fi + +echo "Test passed for ${#devs[@]} submounts." diff --git a/tests/avocado/virtiofs_submounts.py.data/host.sh b/tests/avocado/virtiofs_submounts.py.data/host.sh new file mode 100644 index 0000000000..d8a9afebdb --- /dev/null +++ b/tests/avocado/virtiofs_submounts.py.data/host.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +mount_count=128 + +function print_usage() +{ + if [ -n "$2" ]; then + echo "Error: $2" + echo + fi + echo "Usage: $1 [seed]" + echo "(If no seed is given, it will be randomly generated.)" +} + +scratch_dir=$1 +if [ -z "$scratch_dir" ]; then + print_usage "$0" 'No scratch dir given' >&2 + exit 1 +fi + +if [ ! -d "$scratch_dir" ]; then + print_usage "$0" "$scratch_dir is not a directory" >&2 + exit 1 +fi + +seed=$2 +if [ -z "$seed" ]; then + seed=$RANDOM +fi +RANDOM=$seed + +echo "Seed: $seed" + +set -e +shopt -s nullglob + +cd "$scratch_dir" +if [ -d share ]; then + echo 'Error: This directory seems to be in use already' >&2 + exit 1 +fi + +for ((i = 0; i < $mount_count; i++)); do + printf "Setting up fs %i/%i...\r" "$((i + 1))" "$mount_count" + + rm -f fs$i.img + truncate -s 512M fs$i.img + mkfs.xfs -q fs$i.img + devs[i]=$(sudo losetup -f --show fs$i.img) +done +echo + +top_level_mounts=$((RANDOM % mount_count + 1)) + +mkdir -p share +echo 'root' > share/some-file + +for ((i = 0; i < $top_level_mounts; i++)); do + printf "Mounting fs %i/%i...\r" "$((i + 1))" "$mount_count" + + mkdir -p share/mnt$i + touch share/mnt$i/not-mounted + sudo mount "${devs[i]}" share/mnt$i + sudo chown "$(id -u):$(id -g)" share/mnt$i + + pushd share/mnt$i >/dev/null + path=mnt$i + nesting=$((RANDOM % 4)) + for ((j = 0; j < $nesting; j++)); do + cat > some-file < some-file </dev/null +done + +for ((; i < $mount_count; i++)); do + printf "Mounting fs %i/%i...\r" "$((i + 1))" "$mount_count" + + mp_i=$((i % top_level_mounts)) + + pushd share/mnt$mp_i >/dev/null + path=mnt$mp_i + while true; do + sub_mp="$(echo mnt*)" + if cd sub 2>/dev/null; then + path="$path/sub" + elif [ -n "$sub_mp" ] && cd "$sub_mp" 2>/dev/null; then + path="$path/$sub_mp" + else + break + fi + done + mkdir mnt$i + touch mnt$i/not-mounted + sudo mount "${devs[i]}" mnt$i + sudo chown "$(id -u):$(id -g)" mnt$i + + cd mnt$i + path="$path/mnt$i" + nesting=$((RANDOM % 4)) + for ((j = 0; j < $nesting; j++)); do + cat > some-file < some-file </dev/null +done +echo + +echo 'Done.' diff --git a/tests/avocado/vnc.py b/tests/avocado/vnc.py new file mode 100644 index 0000000000..f301fbb4f5 --- /dev/null +++ b/tests/avocado/vnc.py @@ -0,0 +1,53 @@ +# Simple functional tests for VNC functionality +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado_qemu import Test + + +class Vnc(Test): + """ + :avocado: tags=vnc,quick + """ + def test_no_vnc(self): + self.vm.add_args('-nodefaults', '-S') + self.vm.launch() + self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled']) + + def test_no_vnc_change_password(self): + self.vm.add_args('-nodefaults', '-S') + self.vm.launch() + self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled']) + set_password_response = self.vm.qmp('change-vnc-password', + password='new_password') + self.assertIn('error', set_password_response) + self.assertEqual(set_password_response['error']['class'], + 'GenericError') + self.assertEqual(set_password_response['error']['desc'], + 'Could not set password') + + def test_change_password_requires_a_password(self): + self.vm.add_args('-nodefaults', '-S', '-vnc', ':0') + self.vm.launch() + self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) + set_password_response = self.vm.qmp('change-vnc-password', + password='new_password') + self.assertIn('error', set_password_response) + self.assertEqual(set_password_response['error']['class'], + 'GenericError') + self.assertEqual(set_password_response['error']['desc'], + 'Could not set password') + + def test_change_password(self): + self.vm.add_args('-nodefaults', '-S', '-vnc', ':0,password=on') + self.vm.launch() + self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) + set_password_response = self.vm.qmp('change-vnc-password', + password='new_password') + self.assertEqual(set_password_response['return'], {}) diff --git a/tests/avocado/x86_cpu_model_versions.py b/tests/avocado/x86_cpu_model_versions.py new file mode 100644 index 0000000000..0e9feda62d --- /dev/null +++ b/tests/avocado/x86_cpu_model_versions.py @@ -0,0 +1,358 @@ +# +# Basic validation of x86 versioned CPU models and CPU model aliases +# +# Copyright (c) 2019 Red Hat Inc +# +# Author: +# Eduardo Habkost +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# + + +import avocado_qemu +import re + +class X86CPUModelAliases(avocado_qemu.Test): + """ + Validation of PC CPU model versions and CPU model aliases + + :avocado: tags=arch:x86_64 + """ + def validate_aliases(self, cpus): + for c in cpus.values(): + if 'alias-of' in c: + # all aliases must point to a valid CPU model name: + self.assertIn(c['alias-of'], cpus, + '%s.alias-of (%s) is not a valid CPU model name' % (c['name'], c['alias-of'])) + # aliases must not point to aliases + self.assertNotIn('alias-of', cpus[c['alias-of']], + '%s.alias-of (%s) points to another alias' % (c['name'], c['alias-of'])) + + # aliases must not be static + self.assertFalse(c['static']) + + def validate_variant_aliases(self, cpus): + # -noTSX, -IBRS and -IBPB variants of CPU models are special: + # they shouldn't have their own versions: + self.assertNotIn("Haswell-noTSX-v1", cpus, + "Haswell-noTSX shouldn't be versioned") + self.assertNotIn("Broadwell-noTSX-v1", cpus, + "Broadwell-noTSX shouldn't be versioned") + self.assertNotIn("Nehalem-IBRS-v1", cpus, + "Nehalem-IBRS shouldn't be versioned") + self.assertNotIn("Westmere-IBRS-v1", cpus, + "Westmere-IBRS shouldn't be versioned") + self.assertNotIn("SandyBridge-IBRS-v1", cpus, + "SandyBridge-IBRS shouldn't be versioned") + self.assertNotIn("IvyBridge-IBRS-v1", cpus, + "IvyBridge-IBRS shouldn't be versioned") + self.assertNotIn("Haswell-noTSX-IBRS-v1", cpus, + "Haswell-noTSX-IBRS shouldn't be versioned") + self.assertNotIn("Haswell-IBRS-v1", cpus, + "Haswell-IBRS shouldn't be versioned") + self.assertNotIn("Broadwell-noTSX-IBRS-v1", cpus, + "Broadwell-noTSX-IBRS shouldn't be versioned") + self.assertNotIn("Broadwell-IBRS-v1", cpus, + "Broadwell-IBRS shouldn't be versioned") + self.assertNotIn("Skylake-Client-IBRS-v1", cpus, + "Skylake-Client-IBRS shouldn't be versioned") + self.assertNotIn("Skylake-Server-IBRS-v1", cpus, + "Skylake-Server-IBRS shouldn't be versioned") + self.assertNotIn("EPYC-IBPB-v1", cpus, + "EPYC-IBPB shouldn't be versioned") + + def test_4_0_alias_compatibility(self): + """ + Check if pc-*-4.0 unversioned CPU model won't be reported as aliases + + :avocado: tags=machine:pc-i440fx-4.0 + """ + # pc-*-4.0 won't expose non-versioned CPU models as aliases + # We do this to help management software to keep compatibility + # with older QEMU versions that didn't have the versioned CPU model + self.vm.add_args('-S') + self.vm.launch() + cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions')) + + self.assertFalse(cpus['Cascadelake-Server']['static'], + 'unversioned Cascadelake-Server CPU model must not be static') + self.assertNotIn('alias-of', cpus['Cascadelake-Server'], + 'Cascadelake-Server must not be an alias') + self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], + 'Cascadelake-Server-v1 must not be an alias') + + self.assertFalse(cpus['qemu64']['static'], + 'unversioned qemu64 CPU model must not be static') + self.assertNotIn('alias-of', cpus['qemu64'], + 'qemu64 must not be an alias') + self.assertNotIn('alias-of', cpus['qemu64-v1'], + 'qemu64-v1 must not be an alias') + + self.validate_variant_aliases(cpus) + + # On pc-*-4.0, no CPU model should be reported as an alias: + for name,c in cpus.items(): + self.assertNotIn('alias-of', c, "%s shouldn't be an alias" % (name)) + + def test_4_1_alias(self): + """ + Check if unversioned CPU model is an alias pointing to right version + + :avocado: tags=machine:pc-i440fx-4.1 + """ + self.vm.add_args('-S') + self.vm.launch() + + cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions')) + + self.assertFalse(cpus['Cascadelake-Server']['static'], + 'unversioned Cascadelake-Server CPU model must not be static') + self.assertEquals(cpus['Cascadelake-Server'].get('alias-of'), 'Cascadelake-Server-v1', + 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') + self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], + 'Cascadelake-Server-v1 must not be an alias') + + self.assertFalse(cpus['qemu64']['static'], + 'unversioned qemu64 CPU model must not be static') + self.assertEquals(cpus['qemu64'].get('alias-of'), 'qemu64-v1', + 'qemu64 must be an alias of qemu64-v1') + self.assertNotIn('alias-of', cpus['qemu64-v1'], + 'qemu64-v1 must not be an alias') + + self.validate_variant_aliases(cpus) + + # On pc-*-4.1, -noTSX and -IBRS models should be aliases: + self.assertEquals(cpus["Haswell"].get('alias-of'), + "Haswell-v1", + "Haswell must be an alias") + self.assertEquals(cpus["Haswell-noTSX"].get('alias-of'), + "Haswell-v2", + "Haswell-noTSX must be an alias") + self.assertEquals(cpus["Haswell-IBRS"].get('alias-of'), + "Haswell-v3", + "Haswell-IBRS must be an alias") + self.assertEquals(cpus["Haswell-noTSX-IBRS"].get('alias-of'), + "Haswell-v4", + "Haswell-noTSX-IBRS must be an alias") + + self.assertEquals(cpus["Broadwell"].get('alias-of'), + "Broadwell-v1", + "Broadwell must be an alias") + self.assertEquals(cpus["Broadwell-noTSX"].get('alias-of'), + "Broadwell-v2", + "Broadwell-noTSX must be an alias") + self.assertEquals(cpus["Broadwell-IBRS"].get('alias-of'), + "Broadwell-v3", + "Broadwell-IBRS must be an alias") + self.assertEquals(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), + "Broadwell-v4", + "Broadwell-noTSX-IBRS must be an alias") + + self.assertEquals(cpus["Nehalem"].get('alias-of'), + "Nehalem-v1", + "Nehalem must be an alias") + self.assertEquals(cpus["Nehalem-IBRS"].get('alias-of'), + "Nehalem-v2", + "Nehalem-IBRS must be an alias") + + self.assertEquals(cpus["Westmere"].get('alias-of'), + "Westmere-v1", + "Westmere must be an alias") + self.assertEquals(cpus["Westmere-IBRS"].get('alias-of'), + "Westmere-v2", + "Westmere-IBRS must be an alias") + + self.assertEquals(cpus["SandyBridge"].get('alias-of'), + "SandyBridge-v1", + "SandyBridge must be an alias") + self.assertEquals(cpus["SandyBridge-IBRS"].get('alias-of'), + "SandyBridge-v2", + "SandyBridge-IBRS must be an alias") + + self.assertEquals(cpus["IvyBridge"].get('alias-of'), + "IvyBridge-v1", + "IvyBridge must be an alias") + self.assertEquals(cpus["IvyBridge-IBRS"].get('alias-of'), + "IvyBridge-v2", + "IvyBridge-IBRS must be an alias") + + self.assertEquals(cpus["Skylake-Client"].get('alias-of'), + "Skylake-Client-v1", + "Skylake-Client must be an alias") + self.assertEquals(cpus["Skylake-Client-IBRS"].get('alias-of'), + "Skylake-Client-v2", + "Skylake-Client-IBRS must be an alias") + + self.assertEquals(cpus["Skylake-Server"].get('alias-of'), + "Skylake-Server-v1", + "Skylake-Server must be an alias") + self.assertEquals(cpus["Skylake-Server-IBRS"].get('alias-of'), + "Skylake-Server-v2", + "Skylake-Server-IBRS must be an alias") + + self.assertEquals(cpus["EPYC"].get('alias-of'), + "EPYC-v1", + "EPYC must be an alias") + self.assertEquals(cpus["EPYC-IBPB"].get('alias-of'), + "EPYC-v2", + "EPYC-IBPB must be an alias") + + self.validate_aliases(cpus) + + def test_none_alias(self): + """ + Check if unversioned CPU model is an alias pointing to some version + + :avocado: tags=machine:none + """ + self.vm.add_args('-S') + self.vm.launch() + + cpus = dict((m['name'], m) for m in self.vm.command('query-cpu-definitions')) + + self.assertFalse(cpus['Cascadelake-Server']['static'], + 'unversioned Cascadelake-Server CPU model must not be static') + self.assertTrue(re.match('Cascadelake-Server-v[0-9]+', cpus['Cascadelake-Server']['alias-of']), + 'Cascadelake-Server must be an alias of versioned CPU model') + self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], + 'Cascadelake-Server-v1 must not be an alias') + + self.assertFalse(cpus['qemu64']['static'], + 'unversioned qemu64 CPU model must not be static') + self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']), + 'qemu64 must be an alias of versioned CPU model') + self.assertNotIn('alias-of', cpus['qemu64-v1'], + 'qemu64-v1 must not be an alias') + + self.validate_aliases(cpus) + + +class CascadelakeArchCapabilities(avocado_qemu.Test): + """ + Validation of Cascadelake arch-capabilities + + :avocado: tags=arch:x86_64 + """ + def get_cpu_prop(self, prop): + cpu_path = self.vm.command('query-cpus-fast')[0].get('qom-path') + return self.vm.command('qom-get', path=cpu_path, property=prop) + + def test_4_1(self): + """ + :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server + """ + # machine-type only: + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off') + self.vm.launch() + self.assertFalse(self.get_cpu_prop('arch-capabilities'), + 'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities') + + def test_4_0(self): + """ + :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server + """ + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off') + self.vm.launch() + self.assertFalse(self.get_cpu_prop('arch-capabilities'), + 'pc-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities') + + def test_set_4_0(self): + """ + :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server + """ + # command line must override machine-type if CPU model is not versioned: + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off,+arch-capabilities') + self.vm.launch() + self.assertTrue(self.get_cpu_prop('arch-capabilities'), + 'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities') + + def test_unset_4_1(self): + """ + :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server + """ + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off,-arch-capabilities') + self.vm.launch() + self.assertFalse(self.get_cpu_prop('arch-capabilities'), + 'pc-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') + + def test_v1_4_0(self): + """ + :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server + """ + # versioned CPU model overrides machine-type: + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v1,x-force-features=on,check=off,' + 'enforce=off') + self.vm.launch() + self.assertFalse(self.get_cpu_prop('arch-capabilities'), + 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not have arch-capabilities') + + def test_v2_4_0(self): + """ + :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server + """ + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v2,x-force-features=on,check=off,' + 'enforce=off') + self.vm.launch() + self.assertTrue(self.get_cpu_prop('arch-capabilities'), + 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have arch-capabilities') + + def test_v1_set_4_0(self): + """ + :avocado: tags=machine:pc-i440fx-4.0 + :avocado: tags=cpu:Cascadelake-Server + """ + # command line must override machine-type and versioned CPU model: + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v1,x-force-features=on,check=off,' + 'enforce=off,+arch-capabilities') + self.vm.launch() + self.assertTrue(self.get_cpu_prop('arch-capabilities'), + 'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities') + + def test_v2_unset_4_1(self): + """ + :avocado: tags=machine:pc-i440fx-4.1 + :avocado: tags=cpu:Cascadelake-Server + """ + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v2,x-force-features=on,check=off,' + 'enforce=off,-arch-capabilities') + self.vm.launch() + self.assertFalse(self.get_cpu_prop('arch-capabilities'), + 'pc-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') -- cgit v1.2.3-55-g7522 From 3982feb476e46bbac8f6affbc58bf715e5ca9a4f Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 14 Feb 2021 18:59:08 +0100 Subject: tests/avocado: Extract QemuBaseTest from Test The Avocado Test::fetch_asset() is handy to download artifacts before running tests. The current class is named Test but only tests system emulation. As we want to test user emulation, refactor the common code as QemuBaseTest. Reviewed-by: Willian Rampazzo Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211105143416.148332-2-f4bug@amsat.org> --- tests/avocado/avocado_qemu/__init__.py | 72 +++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index cd21b59e04..a495e106d0 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -169,7 +169,7 @@ def exec_command_and_wait_for_pattern(test, command, """ _console_interaction(test, success_message, failure_message, command + '\r') -class Test(avocado.Test): +class QemuBaseTest(avocado.Test): def _get_unique_tag_val(self, tag_name): """ Gets a tag value, if unique for a key @@ -179,6 +179,46 @@ class Test(avocado.Test): return vals.pop() return None + def setUp(self): + self.arch = self.params.get('arch', + default=self._get_unique_tag_val('arch')) + + self.cpu = self.params.get('cpu', + default=self._get_unique_tag_val('cpu')) + + default_qemu_bin = pick_default_qemu_bin(arch=self.arch) + self.qemu_bin = self.params.get('qemu_bin', + default=default_qemu_bin) + if self.qemu_bin is None: + self.cancel("No QEMU binary defined or found in the build tree") + + def fetch_asset(self, name, + asset_hash=None, algorithm=None, + locations=None, expire=None, + find_only=False, cancel_on_missing=True): + return super().fetch_asset(name, + asset_hash=asset_hash, + algorithm=algorithm, + locations=locations, + expire=expire, + find_only=find_only, + cancel_on_missing=cancel_on_missing) + + +class Test(QemuBaseTest): + """Facilitates system emulation tests. + + TODO: Rename this class as `QemuSystemTest`. + """ + + def setUp(self): + self._vms = {} + + super().setUp() + + self.machine = self.params.get('machine', + default=self._get_unique_tag_val('machine')) + def require_accelerator(self, accelerator): """ Requires an accelerator to be available for the test to continue @@ -201,24 +241,6 @@ class Test(avocado.Test): self.cancel("%s accelerator does not seem to be " "available" % accelerator) - def setUp(self): - self._vms = {} - - self.arch = self.params.get('arch', - default=self._get_unique_tag_val('arch')) - - self.cpu = self.params.get('cpu', - default=self._get_unique_tag_val('cpu')) - - self.machine = self.params.get('machine', - default=self._get_unique_tag_val('machine')) - - default_qemu_bin = pick_default_qemu_bin(arch=self.arch) - self.qemu_bin = self.params.get('qemu_bin', - default=default_qemu_bin) - if self.qemu_bin is None: - self.cancel("No QEMU binary defined or found in the build tree") - def _new_vm(self, name, *args): self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir, @@ -272,18 +294,6 @@ class Test(avocado.Test): self._sd = None super().tearDown() - def fetch_asset(self, name, - asset_hash=None, algorithm=None, - locations=None, expire=None, - find_only=False, cancel_on_missing=True): - return super().fetch_asset(name, - asset_hash=asset_hash, - algorithm=algorithm, - locations=locations, - expire=expire, - find_only=find_only, - cancel_on_missing=cancel_on_missing) - class LinuxSSHMixIn: """Contains utility methods for interacting with a guest via SSH.""" -- cgit v1.2.3-55-g7522 From 9112d4fd493c14a30ebd5ba9853328137490aab6 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 14 Feb 2021 18:59:09 +0100 Subject: tests/avocado: Make pick_default_qemu_bin() more generic Make pick_default_qemu_bin() generic to find qemu-system or qemu-user binaries. Reviewed-by: Willian Rampazzo Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211105143416.148332-3-f4bug@amsat.org> --- tests/avocado/avocado_qemu/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index a495e106d0..984c554e7d 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -45,7 +45,7 @@ def is_readable_executable_file(path): return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK) -def pick_default_qemu_bin(arch=None): +def pick_default_qemu_bin(bin_prefix='qemu-system-', arch=None): """ Picks the path of a QEMU binary, starting either in the current working directory or in the source tree root directory. @@ -64,7 +64,7 @@ def pick_default_qemu_bin(arch=None): # qemu binary path does not match arch for powerpc, handle it if 'ppc64le' in arch: arch = 'ppc64' - qemu_bin_relative_path = "./qemu-system-%s" % arch + qemu_bin_relative_path = os.path.join(".", bin_prefix + arch) if is_readable_executable_file(qemu_bin_relative_path): return qemu_bin_relative_path @@ -179,14 +179,14 @@ class QemuBaseTest(avocado.Test): return vals.pop() return None - def setUp(self): + def setUp(self, bin_prefix): self.arch = self.params.get('arch', default=self._get_unique_tag_val('arch')) self.cpu = self.params.get('cpu', default=self._get_unique_tag_val('cpu')) - default_qemu_bin = pick_default_qemu_bin(arch=self.arch) + default_qemu_bin = pick_default_qemu_bin(bin_prefix, arch=self.arch) self.qemu_bin = self.params.get('qemu_bin', default=default_qemu_bin) if self.qemu_bin is None: @@ -214,7 +214,7 @@ class Test(QemuBaseTest): def setUp(self): self._vms = {} - super().setUp() + super().setUp('qemu-system-') self.machine = self.params.get('machine', default=self._get_unique_tag_val('machine')) -- cgit v1.2.3-55-g7522 From 5334df48224f494303b4717b57b2b0cd42bd1c1a Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sun, 14 Feb 2021 18:59:10 +0100 Subject: tests/avocado: Introduce QemuUserTest base class Similarly to the 'System' Test base class with methods for testing system emulation, the QemuUserTest class contains methods useful to test user-mode emulation. Reviewed-by: Wainer dos Santos Moschetta Reviewed-by: Willian Rampazzo Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211105143416.148332-4-f4bug@amsat.org> --- tests/avocado/avocado_qemu/__init__.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index 984c554e7d..e46b3ecb89 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -17,7 +17,7 @@ import time import uuid import avocado -from avocado.utils import cloudinit, datadrainer, network, ssh, vmimage +from avocado.utils import cloudinit, datadrainer, network, process, ssh, vmimage from avocado.utils.path import find_command #: The QEMU build root directory. It may also be the source directory @@ -295,6 +295,23 @@ class Test(QemuBaseTest): super().tearDown() +class QemuUserTest(QemuBaseTest): + """Facilitates user-mode emulation tests.""" + + def setUp(self): + self._ldpath = [] + super().setUp('qemu-') + + def add_ldpath(self, ldpath): + self._ldpath.append(os.path.abspath(ldpath)) + + def run(self, bin_path, args=[]): + qemu_args = " ".join(["-L %s" % ldpath for ldpath in self._ldpath]) + bin_args = " ".join(args) + return process.run("%s %s %s %s" % (self.qemu_bin, qemu_args, + bin_path, bin_args)) + + class LinuxSSHMixIn: """Contains utility methods for interacting with a guest via SSH.""" -- cgit v1.2.3-55-g7522 From 0e4b1c9435528c30718a2722d09ff35beaa300ee Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 15 Mar 2021 23:55:43 +0100 Subject: tests/avocado: Share useful helpers from virtiofs_submounts test Move the useful has_cmd()/has_cmds() helpers from the virtiofs test to the avocado_qemu public class. Reviewed-by: Wainer dos Santos Moschetta Reviewed-by: Willian Rampazzo Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211105143416.148332-5-f4bug@amsat.org> --- tests/avocado/avocado_qemu/__init__.py | 57 ++++++++++++++++++++++++++++++++ tests/avocado/virtiofs_submounts.py | 59 ++-------------------------------- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index e46b3ecb89..1efc22dabf 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -11,6 +11,7 @@ import logging import os import shutil +import subprocess import sys import tempfile import time @@ -41,6 +42,62 @@ from qemu.utils import (get_info_usernet_hostfwd_port, kvm_available, tcg_available) +def has_cmd(name, args=None): + """ + This function is for use in a @avocado.skipUnless decorator, e.g.: + + @skipUnless(*has_cmd('sudo -n', ('sudo', '-n', 'true'))) + def test_something_that_needs_sudo(self): + ... + """ + + if args is None: + args = ('which', name) + + try: + _, stderr, exitcode = run_cmd(args) + except Exception as e: + exitcode = -1 + stderr = str(e) + + if exitcode != 0: + cmd_line = ' '.join(args) + err = f'{name} required, but "{cmd_line}" failed: {stderr.strip()}' + return (False, err) + else: + return (True, '') + +def has_cmds(*cmds): + """ + This function is for use in a @avocado.skipUnless decorator and + allows checking for the availability of multiple commands, e.g.: + + @skipUnless(*has_cmds(('cmd1', ('cmd1', '--some-parameter')), + 'cmd2', 'cmd3')) + def test_something_that_needs_cmd1_and_cmd2(self): + ... + """ + + for cmd in cmds: + if isinstance(cmd, str): + cmd = (cmd,) + + ok, errstr = has_cmd(*cmd) + if not ok: + return (False, errstr) + + return (True, '') + +def run_cmd(args): + subp = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + stdout, stderr = subp.communicate() + ret = subp.returncode + + return (stdout, stderr, ret) + def is_readable_executable_file(path): return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK) diff --git a/tests/avocado/virtiofs_submounts.py b/tests/avocado/virtiofs_submounts.py index 21ad7d792e..e6dc32ffd4 100644 --- a/tests/avocado/virtiofs_submounts.py +++ b/tests/avocado/virtiofs_submounts.py @@ -6,67 +6,12 @@ import time from avocado import skipUnless from avocado_qemu import LinuxTest, BUILD_DIR +from avocado_qemu import has_cmds +from avocado_qemu import run_cmd from avocado_qemu import wait_for_console_pattern from avocado.utils import ssh -def run_cmd(args): - subp = subprocess.Popen(args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True) - stdout, stderr = subp.communicate() - ret = subp.returncode - - return (stdout, stderr, ret) - -def has_cmd(name, args=None): - """ - This function is for use in a @avocado.skipUnless decorator, e.g.: - - @skipUnless(*has_cmd('sudo -n', ('sudo', '-n', 'true'))) - def test_something_that_needs_sudo(self): - ... - """ - - if args is None: - args = ('which', name) - - try: - _, stderr, exitcode = run_cmd(args) - except Exception as e: - exitcode = -1 - stderr = str(e) - - if exitcode != 0: - cmd_line = ' '.join(args) - err = f'{name} required, but "{cmd_line}" failed: {stderr.strip()}' - return (False, err) - else: - return (True, '') - -def has_cmds(*cmds): - """ - This function is for use in a @avocado.skipUnless decorator and - allows checking for the availability of multiple commands, e.g.: - - @skipUnless(*has_cmds(('cmd1', ('cmd1', '--some-parameter')), - 'cmd2', 'cmd3')) - def test_something_that_needs_cmd1_and_cmd2(self): - ... - """ - - for cmd in cmds: - if isinstance(cmd, str): - cmd = (cmd,) - - ok, errstr = has_cmd(*cmd) - if not ok: - return (False, errstr) - - return (True, '') - - class VirtiofsSubmountsTest(LinuxTest): """ :avocado: tags=arch:x86_64 -- cgit v1.2.3-55-g7522 From 8011837a019182c61bad0d8f3a603d26dd4b6710 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Fri, 21 Jun 2019 15:26:38 +0200 Subject: tests/avocado: Add bFLT loader linux-user test Add a very quick test that runs a busybox binary in bFLT format: $ AVOCADO_ALLOW_UNTRUSTED_CODE=1 \ avocado --show=app run -t linux_user tests/avocado/load_bflt.py JOB ID : db94d5960ce564c50904d666a7e259148c27e88f JOB LOG : ~/avocado/job-results/job-2019-06-25T10.52-db94d59/job.log (1/1) tests/avocado/load_bflt.py:LoadBFLT.test_stm32: PASS (0.15 s) RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0 JOB TIME : 0.54 s Reviewed-by: Willian Rampazzo Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211105143416.148332-6-f4bug@amsat.org> --- tests/avocado/load_bflt.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/avocado/load_bflt.py diff --git a/tests/avocado/load_bflt.py b/tests/avocado/load_bflt.py new file mode 100644 index 0000000000..bb50cec1ee --- /dev/null +++ b/tests/avocado/load_bflt.py @@ -0,0 +1,54 @@ +# Test the bFLT loader format +# +# Copyright (C) 2019 Philippe Mathieu-Daudé +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import bz2 +import subprocess + +from avocado import skipUnless +from avocado_qemu import QemuUserTest +from avocado_qemu import has_cmd + + +class LoadBFLT(QemuUserTest): + + def extract_cpio(self, cpio_path): + """ + Extracts a cpio archive into the test workdir + + :param cpio_path: path to the cpio archive + """ + cwd = os.getcwd() + os.chdir(self.workdir) + with bz2.open(cpio_path, 'rb') as archive_cpio: + subprocess.run(['cpio', '-i'], input=archive_cpio.read(), + stderr=subprocess.DEVNULL) + os.chdir(cwd) + + @skipUnless(*has_cmd('cpio')) + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_stm32(self): + """ + :avocado: tags=arch:arm + :avocado: tags=linux_user + :avocado: tags=quick + """ + # See https://elinux.org/STM32#User_Space + rootfs_url = ('https://elinux.org/images/5/51/' + 'Stm32_mini_rootfs.cpio.bz2') + rootfs_hash = '9f065e6ba40cce7411ba757f924f30fcc57951e6' + rootfs_path_bz2 = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash) + busybox_path = os.path.join(self.workdir, "/bin/busybox") + + self.extract_cpio(rootfs_path_bz2) + + res = self.run(busybox_path) + ver = 'BusyBox v1.24.0.git (2015-02-03 22:17:13 CET) multi-call binary.' + self.assertIn(ver, res.stdout_text) + + res = self.run(busybox_path, ['uname', '-a']) + unm = 'armv7l GNU/Linux' + self.assertIn(unm, res.stdout_text) -- cgit v1.2.3-55-g7522 From 2283b627bc6ba2bc7f120b4e7af0e43503282bb7 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Mon, 27 Sep 2021 18:14:33 +0200 Subject: tests/avocado: Rename avocado_qemu.Test -> QemuSystemTest To run user-mode emulation tests, we introduced the avocado_qemu.QemuUserTest which inherits from avocado_qemu.QemuBaseTest. System-mode emulation tests are based on the avocado_qemu.Test class, which also inherits avocado_qemu.QemuBaseTest. To avoid confusion, rename it as avocado_qemu.QemuSystemTest. Suggested-by: Wainer dos Santos Moschetta Reviewed-by: Willian Rampazzo Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211105143416.148332-7-f4bug@amsat.org> --- docs/devel/testing.rst | 8 ++++---- tests/avocado/avocado_qemu/__init__.py | 21 +++++++++------------ tests/avocado/boot_linux_console.py | 4 ++-- tests/avocado/cpu_queries.py | 4 ++-- tests/avocado/empty_cpu_model.py | 4 ++-- tests/avocado/info_usernet.py | 4 ++-- tests/avocado/linux_initrd.py | 4 ++-- tests/avocado/linux_ssh_mips_malta.py | 5 +++-- tests/avocado/machine_arm_canona1100.py | 4 ++-- tests/avocado/machine_arm_integratorcp.py | 4 ++-- tests/avocado/machine_arm_n8x0.py | 4 ++-- tests/avocado/machine_avr6.py | 4 ++-- tests/avocado/machine_m68k_nextcube.py | 4 ++-- tests/avocado/machine_microblaze.py | 4 ++-- tests/avocado/machine_mips_fuloong2e.py | 4 ++-- tests/avocado/machine_mips_loongson3v.py | 4 ++-- tests/avocado/machine_mips_malta.py | 4 ++-- tests/avocado/machine_rx_gdbsim.py | 4 ++-- tests/avocado/machine_s390_ccw_virtio.py | 4 ++-- tests/avocado/machine_sparc_leon3.py | 4 ++-- tests/avocado/migration.py | 4 ++-- tests/avocado/multiprocess.py | 4 ++-- tests/avocado/pc_cpu_hotplug_props.py | 4 ++-- tests/avocado/ppc_405.py | 4 ++-- tests/avocado/ppc_bamboo.py | 4 ++-- tests/avocado/ppc_mpc8544ds.py | 4 ++-- tests/avocado/ppc_prep_40p.py | 4 ++-- tests/avocado/ppc_pseries.py | 4 ++-- tests/avocado/ppc_virtex_ml507.py | 4 ++-- tests/avocado/version.py | 4 ++-- tests/avocado/virtio-gpu.py | 4 ++-- tests/avocado/virtio_check_params.py | 4 ++-- tests/avocado/virtio_version.py | 4 ++-- tests/avocado/vnc.py | 4 ++-- tests/avocado/x86_cpu_model_versions.py | 4 ++-- 35 files changed, 80 insertions(+), 82 deletions(-) diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index dc5dbd057d..60c59023e5 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -811,10 +811,10 @@ class. Here's a simple usage example: .. code:: - from avocado_qemu import Test + from avocado_qemu import QemuSystemTest - class Version(Test): + class Version(QemuSystemTest): """ :avocado: tags=quick """ @@ -859,10 +859,10 @@ and hypothetical example follows: .. code:: - from avocado_qemu import Test + from avocado_qemu import QemuSystemTest - class MultipleMachines(Test): + class MultipleMachines(QemuSystemTest): def test_multiple_machines(self): first_machine = self.get_vm() second_machine = self.get_vm() diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index 1efc22dabf..75063c0c30 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -176,7 +176,7 @@ def interrupt_interactive_console_until_pattern(test, success_message, :param test: an Avocado test containing a VM that will have its console read and probed for a success or failure message - :type test: :class:`avocado_qemu.Test` + :type test: :class:`avocado_qemu.QemuSystemTest` :param success_message: if this message appears, test succeeds :param failure_message: if this message appears, test fails :param interrupt_string: a string to send to the console before trying @@ -192,7 +192,7 @@ def wait_for_console_pattern(test, success_message, failure_message=None, :param test: an Avocado test containing a VM that will have its console read and probed for a success or failure message - :type test: :class:`avocado_qemu.Test` + :type test: :class:`avocado_qemu.QemuSystemTest` :param success_message: if this message appears, test succeeds :param failure_message: if this message appears, test fails """ @@ -204,7 +204,7 @@ def exec_command(test, command): the content. :param test: an Avocado test containing a VM. - :type test: :class:`avocado_qemu.Test` + :type test: :class:`avocado_qemu.QemuSystemTest` :param command: the command to send :type command: str """ @@ -219,7 +219,7 @@ def exec_command_and_wait_for_pattern(test, command, :param test: an Avocado test containing a VM that will have its console read and probed for a success or failure message - :type test: :class:`avocado_qemu.Test` + :type test: :class:`avocado_qemu.QemuSystemTest` :param command: the command to send :param success_message: if this message appears, test succeeds :param failure_message: if this message appears, test fails @@ -262,11 +262,8 @@ class QemuBaseTest(avocado.Test): cancel_on_missing=cancel_on_missing) -class Test(QemuBaseTest): - """Facilitates system emulation tests. - - TODO: Rename this class as `QemuSystemTest`. - """ +class QemuSystemTest(QemuBaseTest): + """Facilitates system emulation tests.""" def setUp(self): self._vms = {} @@ -508,11 +505,11 @@ class LinuxDistro: return self._info.get('kernel_params', None) -class LinuxTest(LinuxSSHMixIn, Test): +class LinuxTest(LinuxSSHMixIn, QemuSystemTest): """Facilitates having a cloud-image Linux based available. - For tests that indend to interact with guests, this is a better choice - to start with than the more vanilla `Test` class. + For tests that indent to interact with guests, this is a better choice + to start with than the more vanilla `QemuSystemTest` class. """ timeout = 900 diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py index 06fc967f6c..4ed01ed789 100644 --- a/tests/avocado/boot_linux_console.py +++ b/tests/avocado/boot_linux_console.py @@ -15,7 +15,7 @@ import shutil from avocado import skip from avocado import skipUnless -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import exec_command from avocado_qemu import exec_command_and_wait_for_pattern from avocado_qemu import interrupt_interactive_console_until_pattern @@ -46,7 +46,7 @@ def image_pow2ceil_expand(path): with open(path, 'ab+') as fd: fd.truncate(size_aligned) -class LinuxKernelTest(Test): +class LinuxKernelTest(QemuSystemTest): KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' def wait_for_console_pattern(self, success_message, vm=None): diff --git a/tests/avocado/cpu_queries.py b/tests/avocado/cpu_queries.py index cc9e380cc7..cf69f69b11 100644 --- a/tests/avocado/cpu_queries.py +++ b/tests/avocado/cpu_queries.py @@ -8,9 +8,9 @@ # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest -class QueryCPUModelExpansion(Test): +class QueryCPUModelExpansion(QemuSystemTest): """ Run query-cpu-model-expansion for each CPU model, and validate results """ diff --git a/tests/avocado/empty_cpu_model.py b/tests/avocado/empty_cpu_model.py index a1e59e45e4..22f504418d 100644 --- a/tests/avocado/empty_cpu_model.py +++ b/tests/avocado/empty_cpu_model.py @@ -7,9 +7,9 @@ # # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest -class EmptyCPUModel(Test): +class EmptyCPUModel(QemuSystemTest): def test(self): self.vm.add_args('-S', '-display', 'none', '-machine', 'none', '-cpu', '') self.vm.set_qmp_monitor(enabled=False) diff --git a/tests/avocado/info_usernet.py b/tests/avocado/info_usernet.py index 9c1fd903a0..dc01f74150 100644 --- a/tests/avocado/info_usernet.py +++ b/tests/avocado/info_usernet.py @@ -8,12 +8,12 @@ # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from qemu.utils import get_info_usernet_hostfwd_port -class InfoUsernet(Test): +class InfoUsernet(QemuSystemTest): def test_hostfwd(self): self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22') diff --git a/tests/avocado/linux_initrd.py b/tests/avocado/linux_initrd.py index 9b4880cd8c..ba02e5a563 100644 --- a/tests/avocado/linux_initrd.py +++ b/tests/avocado/linux_initrd.py @@ -12,11 +12,11 @@ import os import logging import tempfile -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado import skipIf -class LinuxInitrd(Test): +class LinuxInitrd(QemuSystemTest): """ Checks QEMU evaluates correctly the initrd file passed as -initrd option. diff --git a/tests/avocado/linux_ssh_mips_malta.py b/tests/avocado/linux_ssh_mips_malta.py index 4de1947418..c0f0be5ade 100644 --- a/tests/avocado/linux_ssh_mips_malta.py +++ b/tests/avocado/linux_ssh_mips_malta.py @@ -12,7 +12,8 @@ import logging import time from avocado import skipUnless -from avocado_qemu import Test, LinuxSSHMixIn +from avocado_qemu import LinuxSSHMixIn +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado.utils import process from avocado.utils import archive @@ -21,7 +22,7 @@ from avocado.utils import ssh @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') @skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available') -class LinuxSSH(Test, LinuxSSHMixIn): +class LinuxSSH(QemuSystemTest, LinuxSSHMixIn): timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg' diff --git a/tests/avocado/machine_arm_canona1100.py b/tests/avocado/machine_arm_canona1100.py index 0e5c43dbcf..182a0b0513 100644 --- a/tests/avocado/machine_arm_canona1100.py +++ b/tests/avocado/machine_arm_canona1100.py @@ -8,11 +8,11 @@ # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado.utils import archive -class CanonA1100Machine(Test): +class CanonA1100Machine(QemuSystemTest): """Boots the barebox firmware and checks that the console is operational""" timeout = 90 diff --git a/tests/avocado/machine_arm_integratorcp.py b/tests/avocado/machine_arm_integratorcp.py index 49c8ebff78..1ffe1073ef 100644 --- a/tests/avocado/machine_arm_integratorcp.py +++ b/tests/avocado/machine_arm_integratorcp.py @@ -12,7 +12,7 @@ import os import logging from avocado import skipUnless -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern @@ -29,7 +29,7 @@ except ImportError: CV2_AVAILABLE = False -class IntegratorMachine(Test): +class IntegratorMachine(QemuSystemTest): timeout = 90 diff --git a/tests/avocado/machine_arm_n8x0.py b/tests/avocado/machine_arm_n8x0.py index e5741f2d8d..12e9a6803b 100644 --- a/tests/avocado/machine_arm_n8x0.py +++ b/tests/avocado/machine_arm_n8x0.py @@ -11,10 +11,10 @@ import os from avocado import skipUnless -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern -class N8x0Machine(Test): +class N8x0Machine(QemuSystemTest): """Boots the Linux kernel and checks that the console is operational""" timeout = 90 diff --git a/tests/avocado/machine_avr6.py b/tests/avocado/machine_avr6.py index 6bab31342a..5485db79c6 100644 --- a/tests/avocado/machine_avr6.py +++ b/tests/avocado/machine_avr6.py @@ -19,9 +19,9 @@ import time -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest -class AVR6Machine(Test): +class AVR6Machine(QemuSystemTest): timeout = 5 def test_freertos(self): diff --git a/tests/avocado/machine_m68k_nextcube.py b/tests/avocado/machine_m68k_nextcube.py index 09e2745cc5..6790e7d9cd 100644 --- a/tests/avocado/machine_m68k_nextcube.py +++ b/tests/avocado/machine_m68k_nextcube.py @@ -8,7 +8,7 @@ import os import time -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado import skipUnless from tesseract_utils import tesseract_available, tesseract_ocr @@ -20,7 +20,7 @@ except ImportError: PIL_AVAILABLE = False -class NextCubeMachine(Test): +class NextCubeMachine(QemuSystemTest): """ :avocado: tags=arch:m68k :avocado: tags=machine:next-cube diff --git a/tests/avocado/machine_microblaze.py b/tests/avocado/machine_microblaze.py index 7f6d18495d..4928920f96 100644 --- a/tests/avocado/machine_microblaze.py +++ b/tests/avocado/machine_microblaze.py @@ -5,11 +5,11 @@ # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado.utils import archive -class MicroblazeMachine(Test): +class MicroblazeMachine(QemuSystemTest): timeout = 90 diff --git a/tests/avocado/machine_mips_fuloong2e.py b/tests/avocado/machine_mips_fuloong2e.py index 0ac285e2af..89291f47b2 100644 --- a/tests/avocado/machine_mips_fuloong2e.py +++ b/tests/avocado/machine_mips_fuloong2e.py @@ -10,10 +10,10 @@ import os from avocado import skipUnless -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern -class MipsFuloong2e(Test): +class MipsFuloong2e(QemuSystemTest): timeout = 60 diff --git a/tests/avocado/machine_mips_loongson3v.py b/tests/avocado/machine_mips_loongson3v.py index 85b131a40f..5194cf18c9 100644 --- a/tests/avocado/machine_mips_loongson3v.py +++ b/tests/avocado/machine_mips_loongson3v.py @@ -11,10 +11,10 @@ import os import time from avocado import skipUnless -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern -class MipsLoongson3v(Test): +class MipsLoongson3v(QemuSystemTest): timeout = 60 @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') diff --git a/tests/avocado/machine_mips_malta.py b/tests/avocado/machine_mips_malta.py index b67d8cb141..f1895d59f3 100644 --- a/tests/avocado/machine_mips_malta.py +++ b/tests/avocado/machine_mips_malta.py @@ -12,7 +12,7 @@ import gzip import logging from avocado import skipUnless -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado.utils import archive from avocado import skipIf @@ -33,7 +33,7 @@ except ImportError: @skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed') @skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed') -class MaltaMachineFramebuffer(Test): +class MaltaMachineFramebuffer(QemuSystemTest): timeout = 30 diff --git a/tests/avocado/machine_rx_gdbsim.py b/tests/avocado/machine_rx_gdbsim.py index 32b737b6d8..6cd8704b01 100644 --- a/tests/avocado/machine_rx_gdbsim.py +++ b/tests/avocado/machine_rx_gdbsim.py @@ -11,13 +11,13 @@ import os from avocado import skipIf -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import exec_command_and_wait_for_pattern from avocado_qemu import wait_for_console_pattern from avocado.utils import archive -class RxGdbSimMachine(Test): +class RxGdbSimMachine(QemuSystemTest): timeout = 30 KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' diff --git a/tests/avocado/machine_s390_ccw_virtio.py b/tests/avocado/machine_s390_ccw_virtio.py index 4028c99afc..bd03d7160b 100644 --- a/tests/avocado/machine_s390_ccw_virtio.py +++ b/tests/avocado/machine_s390_ccw_virtio.py @@ -13,12 +13,12 @@ import os import tempfile from avocado import skipIf -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import exec_command_and_wait_for_pattern from avocado_qemu import wait_for_console_pattern from avocado.utils import archive -class S390CCWVirtioMachine(Test): +class S390CCWVirtioMachine(QemuSystemTest): KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' timeout = 120 diff --git a/tests/avocado/machine_sparc_leon3.py b/tests/avocado/machine_sparc_leon3.py index 2405cd7a0d..e61b223185 100644 --- a/tests/avocado/machine_sparc_leon3.py +++ b/tests/avocado/machine_sparc_leon3.py @@ -5,12 +5,12 @@ # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado import skip -class Leon3Machine(Test): +class Leon3Machine(QemuSystemTest): timeout = 60 diff --git a/tests/avocado/migration.py b/tests/avocado/migration.py index 792639cb69..584d6ef53f 100644 --- a/tests/avocado/migration.py +++ b/tests/avocado/migration.py @@ -11,7 +11,7 @@ import tempfile -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado import skipUnless from avocado.utils import network @@ -19,7 +19,7 @@ from avocado.utils import wait from avocado.utils.path import find_command -class Migration(Test): +class Migration(QemuSystemTest): """ :avocado: tags=migration """ diff --git a/tests/avocado/multiprocess.py b/tests/avocado/multiprocess.py index 96627f022a..80a3b8f442 100644 --- a/tests/avocado/multiprocess.py +++ b/tests/avocado/multiprocess.py @@ -7,12 +7,12 @@ import os import socket -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado_qemu import exec_command from avocado_qemu import exec_command_and_wait_for_pattern -class Multiprocess(Test): +class Multiprocess(QemuSystemTest): """ :avocado: tags=multiprocess """ diff --git a/tests/avocado/pc_cpu_hotplug_props.py b/tests/avocado/pc_cpu_hotplug_props.py index 2e86d5017a..52b878188e 100644 --- a/tests/avocado/pc_cpu_hotplug_props.py +++ b/tests/avocado/pc_cpu_hotplug_props.py @@ -20,9 +20,9 @@ # License along with this library; if not, see . # -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest -class OmittedCPUProps(Test): +class OmittedCPUProps(QemuSystemTest): """ :avocado: tags=arch:x86_64 :avocado: tags=cpu:qemu64 diff --git a/tests/avocado/ppc_405.py b/tests/avocado/ppc_405.py index c534d5d32f..a47f89b934 100644 --- a/tests/avocado/ppc_405.py +++ b/tests/avocado/ppc_405.py @@ -6,11 +6,11 @@ # later. See the COPYING file in the top-level directory. from avocado.utils import archive -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado_qemu import exec_command_and_wait_for_pattern -class Ppc405Machine(Test): +class Ppc405Machine(QemuSystemTest): timeout = 90 diff --git a/tests/avocado/ppc_bamboo.py b/tests/avocado/ppc_bamboo.py index dd33bf66f3..40629e3478 100644 --- a/tests/avocado/ppc_bamboo.py +++ b/tests/avocado/ppc_bamboo.py @@ -6,11 +6,11 @@ # later. See the COPYING file in the top-level directory. from avocado.utils import archive -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado_qemu import exec_command_and_wait_for_pattern -class BambooMachine(Test): +class BambooMachine(QemuSystemTest): timeout = 90 diff --git a/tests/avocado/ppc_mpc8544ds.py b/tests/avocado/ppc_mpc8544ds.py index ce840600c1..886f967b15 100644 --- a/tests/avocado/ppc_mpc8544ds.py +++ b/tests/avocado/ppc_mpc8544ds.py @@ -6,10 +6,10 @@ # later. See the COPYING file in the top-level directory. from avocado.utils import archive -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern -class Mpc8544dsMachine(Test): +class Mpc8544dsMachine(QemuSystemTest): timeout = 90 KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' diff --git a/tests/avocado/ppc_prep_40p.py b/tests/avocado/ppc_prep_40p.py index 5e61e686bd..4bd956584d 100644 --- a/tests/avocado/ppc_prep_40p.py +++ b/tests/avocado/ppc_prep_40p.py @@ -8,11 +8,11 @@ import os from avocado import skipUnless -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern -class IbmPrep40pMachine(Test): +class IbmPrep40pMachine(QemuSystemTest): timeout = 60 diff --git a/tests/avocado/ppc_pseries.py b/tests/avocado/ppc_pseries.py index f14a884ee1..d8b04dc3ea 100644 --- a/tests/avocado/ppc_pseries.py +++ b/tests/avocado/ppc_pseries.py @@ -6,10 +6,10 @@ # later. See the COPYING file in the top-level directory. from avocado.utils import archive -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern -class pseriesMachine(Test): +class pseriesMachine(QemuSystemTest): timeout = 90 KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' diff --git a/tests/avocado/ppc_virtex_ml507.py b/tests/avocado/ppc_virtex_ml507.py index 27f7bf2d49..a6912ee579 100644 --- a/tests/avocado/ppc_virtex_ml507.py +++ b/tests/avocado/ppc_virtex_ml507.py @@ -6,10 +6,10 @@ # later. See the COPYING file in the top-level directory. from avocado.utils import archive -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern -class VirtexMl507Machine(Test): +class VirtexMl507Machine(QemuSystemTest): timeout = 90 KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' diff --git a/tests/avocado/version.py b/tests/avocado/version.py index 79b923d4fc..ded7f039c1 100644 --- a/tests/avocado/version.py +++ b/tests/avocado/version.py @@ -9,10 +9,10 @@ # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest -class Version(Test): +class Version(QemuSystemTest): """ :avocado: tags=quick """ diff --git a/tests/avocado/virtio-gpu.py b/tests/avocado/virtio-gpu.py index 4acc1e6d5f..2a249a3a2c 100644 --- a/tests/avocado/virtio-gpu.py +++ b/tests/avocado/virtio-gpu.py @@ -4,8 +4,8 @@ # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test from avocado_qemu import BUILD_DIR +from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado_qemu import exec_command_and_wait_for_pattern from avocado_qemu import is_readable_executable_file @@ -27,7 +27,7 @@ def pick_default_vug_bin(): return bld_dir_path -class VirtioGPUx86(Test): +class VirtioGPUx86(QemuSystemTest): """ :avocado: tags=virtio-gpu :avocado: tags=arch:x86_64 diff --git a/tests/avocado/virtio_check_params.py b/tests/avocado/virtio_check_params.py index 87e6c839d1..e869690473 100644 --- a/tests/avocado/virtio_check_params.py +++ b/tests/avocado/virtio_check_params.py @@ -24,7 +24,7 @@ import logging sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) from qemu.machine import QEMUMachine -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest from avocado import skip #list of machine types and virtqueue properties to test @@ -41,7 +41,7 @@ VM_DEV_PARAMS = {'virtio-scsi-pci': ['-device', 'virtio-scsi-pci,id=scsi0'], 'driver=null-co,id=drive0,if=none']} -class VirtioMaxSegSettingsCheck(Test): +class VirtioMaxSegSettingsCheck(QemuSystemTest): @staticmethod def make_pattern(props): pattern_items = ['{0} = \w+'.format(prop) for prop in props] diff --git a/tests/avocado/virtio_version.py b/tests/avocado/virtio_version.py index 33593c29dd..208910bb84 100644 --- a/tests/avocado/virtio_version.py +++ b/tests/avocado/virtio_version.py @@ -13,7 +13,7 @@ import os sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) from qemu.machine import QEMUMachine -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest # Virtio Device IDs: VIRTIO_NET = 1 @@ -55,7 +55,7 @@ def get_pci_interfaces(vm, devtype): interfaces = ('pci-express-device', 'conventional-pci-device') return [i for i in interfaces if devtype_implements(vm, devtype, i)] -class VirtioVersionCheck(Test): +class VirtioVersionCheck(QemuSystemTest): """ Check if virtio-version-specific device types result in the same device tree created by `disable-modern` and diff --git a/tests/avocado/vnc.py b/tests/avocado/vnc.py index f301fbb4f5..096432988f 100644 --- a/tests/avocado/vnc.py +++ b/tests/avocado/vnc.py @@ -8,10 +8,10 @@ # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. -from avocado_qemu import Test +from avocado_qemu import QemuSystemTest -class Vnc(Test): +class Vnc(QemuSystemTest): """ :avocado: tags=vnc,quick """ diff --git a/tests/avocado/x86_cpu_model_versions.py b/tests/avocado/x86_cpu_model_versions.py index 0e9feda62d..a6edf74c1c 100644 --- a/tests/avocado/x86_cpu_model_versions.py +++ b/tests/avocado/x86_cpu_model_versions.py @@ -24,7 +24,7 @@ import avocado_qemu import re -class X86CPUModelAliases(avocado_qemu.Test): +class X86CPUModelAliases(avocado_qemu.QemuSystemTest): """ Validation of PC CPU model versions and CPU model aliases @@ -239,7 +239,7 @@ class X86CPUModelAliases(avocado_qemu.Test): self.validate_aliases(cpus) -class CascadelakeArchCapabilities(avocado_qemu.Test): +class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): """ Validation of Cascadelake arch-capabilities -- cgit v1.2.3-55-g7522 From b94d00898a9ee708b4d4b79432c2272905a56b06 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 6 Nov 2021 10:07:18 +0100 Subject: tests/avocado: Remove p7zip binary availability check The single use of the 7z binary has been removed in commit a30e114f3 ("tests/acceptance: remove Armbian 19.11.3 test for orangepi-pc"), we don't need to check for this binary availability anymore. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Joaquin de Andres Reviewed-by: Willian Rampazzo Message-Id: <20211106091059.465109-1-philmd@redhat.com> --- tests/avocado/boot_linux_console.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py index 4ed01ed789..9c618d4809 100644 --- a/tests/avocado/boot_linux_console.py +++ b/tests/avocado/boot_linux_console.py @@ -22,13 +22,6 @@ from avocado_qemu import interrupt_interactive_console_until_pattern from avocado_qemu import wait_for_console_pattern from avocado.utils import process from avocado.utils import archive -from avocado.utils.path import find_command, CmdNotFoundError - -P7ZIP_AVAILABLE = True -try: - find_command('7z') -except CmdNotFoundError: - P7ZIP_AVAILABLE = False """ Round up to next power of 2 -- cgit v1.2.3-55-g7522