diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/acceptance/boot_linux_console.py | 120 | ||||
-rw-r--r-- | tests/acceptance/boot_xen.py | 118 | ||||
-rw-r--r-- | tests/acceptance/replay_kernel.py | 10 | ||||
-rw-r--r-- | tests/docker/dockerfiles/debian10.docker | 2 | ||||
-rwxr-xr-x | tests/docker/test-tcg | 22 | ||||
-rw-r--r-- | tests/fp/fp-test.c | 8 | ||||
-rw-r--r-- | tests/qemu-iotests/049.out | 14 | ||||
-rw-r--r-- | tests/qemu-iotests/178.out.qcow2 | 3 | ||||
-rw-r--r-- | tests/qemu-iotests/178.out.raw | 3 | ||||
-rw-r--r-- | tests/qemu-iotests/241.out | 4 | ||||
-rw-r--r-- | tests/qtest/fuzz-test.c | 3 | ||||
-rw-r--r-- | tests/qtest/npcm7xx_pwm-test.c | 205 | ||||
-rwxr-xr-x | tests/tcg/configure.sh | 6 | ||||
-rw-r--r-- | tests/tcg/ppc64/Makefile.target | 13 | ||||
-rw-r--r-- | tests/tcg/ppc64le/Makefile.target | 12 | ||||
-rw-r--r-- | tests/tcg/ppc64le/bcdsub.c | 130 | ||||
-rw-r--r-- | tests/unit/test-cutils.c | 168 | ||||
-rw-r--r-- | tests/unit/test-keyval.c | 35 | ||||
-rw-r--r-- | tests/unit/test-qemu-opts.c | 33 |
19 files changed, 755 insertions, 154 deletions
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index eb01286799..1ca32ecf25 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -507,20 +507,18 @@ class BootLinuxConsole(LinuxKernelTest): self.wait_for_console_pattern('Boot successful.') # TODO user command, for now the uart is stuck - @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), - 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_cubieboard_initrd(self): """ :avocado: tags=arch:arm :avocado: tags=machine:cubieboard """ deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') - deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + '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-4.20.7-sunxi') - dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb' + '/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/' @@ -549,20 +547,18 @@ class BootLinuxConsole(LinuxKernelTest): 'system-control@1c00000') # cubieboard's reboot is not functioning; omit reboot test. - @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), - 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_cubieboard_sata(self): """ :avocado: tags=arch:arm :avocado: tags=machine:cubieboard """ deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') - deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + '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-4.20.7-sunxi') - dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb' + '/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/' @@ -678,20 +674,18 @@ class BootLinuxConsole(LinuxKernelTest): self.wait_for_console_pattern( 'Give root password for system maintenance') - @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), - 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_orangepi(self): """ :avocado: tags=arch:arm :avocado: tags=machine:orangepi-pc """ deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') - deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + '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-4.20.7-sunxi') - dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb' + '/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() @@ -705,20 +699,18 @@ class BootLinuxConsole(LinuxKernelTest): console_pattern = 'Kernel command line: %s' % kernel_command_line self.wait_for_console_pattern(console_pattern) - @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), - 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_orangepi_initrd(self): """ :avocado: tags=arch:arm :avocado: tags=machine:orangepi-pc """ deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') - deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + '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-4.20.7-sunxi') - dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb' + '/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/' @@ -749,8 +741,6 @@ class BootLinuxConsole(LinuxKernelTest): # Wait for VM to shut down gracefully self.vm.wait() - @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), - 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_orangepi_sd(self): """ :avocado: tags=arch:arm @@ -758,12 +748,12 @@ class BootLinuxConsole(LinuxKernelTest): :avocado: tags=device:sd """ deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') - deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + '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-4.20.7-sunxi') - dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb' + '/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') @@ -802,7 +792,27 @@ class BootLinuxConsole(LinuxKernelTest): # Wait for VM to shut down gracefully self.vm.wait() - def do_test_arm_orangepi_uboot_armbian(self, image_path): + @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', @@ -828,54 +838,6 @@ class BootLinuxConsole(LinuxKernelTest): 'to <orangepipc>') self.wait_for_console_pattern('Starting Load Kernel Modules...') - @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), - 'Test artifacts fetched from unreliable apt.armbian.com') - @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited') - @skipUnless(P7ZIP_AVAILABLE, '7z not installed') - def test_arm_orangepi_bionic_19_11(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:orangepi-pc - :avocado: tags=device:sd - """ - - # This test download a 196MB compressed image and expand it to 1GB - image_url = ('https://dl.armbian.com/orangepipc/archive/' - 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z') - image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e' - image_path_7z = self.fetch_asset(image_url, asset_hash=image_hash) - image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img' - image_path = os.path.join(self.workdir, image_name) - process.run("7z e -o%s %s" % (self.workdir, image_path_7z)) - image_pow2ceil_expand(image_path) - - self.do_test_arm_orangepi_uboot_armbian(image_path) - - @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), - 'Test artifacts fetched from unreliable apt.armbian.com') - @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://dl.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.do_test_arm_orangepi_uboot_armbian(image_path) - @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited') def test_arm_orangepi_uboot_netbsd9(self): """ diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py new file mode 100644 index 0000000000..75c2d44492 --- /dev/null +++ b/tests/acceptance/boot_xen.py @@ -0,0 +1,118 @@ +# 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 <alex.bennee@linaro.org> +# +# 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 import skipIf +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', + '-cpu', 'cortex-a57', + '-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/replay_kernel.py b/tests/acceptance/replay_kernel.py index c1cb862468..71facdaa75 100644 --- a/tests/acceptance/replay_kernel.py +++ b/tests/acceptance/replay_kernel.py @@ -177,20 +177,18 @@ class ReplayKernelNormal(ReplayKernelBase): self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1) @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'), - 'Test artifacts fetched from unreliable apt.armbian.com') def test_arm_cubieboard_initrd(self): """ :avocado: tags=arch:arm :avocado: tags=machine:cubieboard """ deb_url = ('https://apt.armbian.com/pool/main/l/' - 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb') - deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315' + '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-4.20.7-sunxi') - dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb' + '/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/' diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker index 9d42b5a4b8..d034acbd25 100644 --- a/tests/docker/dockerfiles/debian10.docker +++ b/tests/docker/dockerfiles/debian10.docker @@ -32,6 +32,6 @@ RUN apt update && \ psmisc \ python3 \ python3-sphinx \ - $(apt-get -s build-dep qemu | egrep ^Inst | fgrep '[all]' | cut -d\ -f2) + $(apt-get -s build-dep --arch-only qemu | egrep ^Inst | fgrep '[all]' | cut -d\ -f2) ENV FEATURES docs diff --git a/tests/docker/test-tcg b/tests/docker/test-tcg new file mode 100755 index 0000000000..00993b73ba --- /dev/null +++ b/tests/docker/test-tcg @@ -0,0 +1,22 @@ +#!/bin/bash -e +# +# Build and run the TCG tests +# +# Copyright (c) 2021 Linaro Ltd. +# +# Authors: +# Alex Bennée <alex.bennee@linaro.org> +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +. common.rc + +cd "$BUILD_DIR" + +# although we are not building QEMU itself we still need a configured +# build for the unit tests to be built and run +TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \ +build_qemu +check_qemu check-tcg diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c index 06ffebd6db..5a4cad8c8b 100644 --- a/tests/fp/fp-test.c +++ b/tests/fp/fp-test.c @@ -123,7 +123,7 @@ static void not_implemented(void) fprintf(stderr, "Not implemented.\n"); } -static bool blacklisted(unsigned op, int rmode) +static bool is_allowed(unsigned op, int rmode) { /* odd has not been implemented for any 80-bit ops */ if (rmode == softfloat_round_odd) { @@ -161,10 +161,10 @@ static bool blacklisted(unsigned op, int rmode) case F32_TO_EXTF80: case F64_TO_EXTF80: case F128_TO_EXTF80: - return true; + return false; } } - return false; + return true; } static void do_testfloat(int op, int rmode, bool exact) @@ -194,7 +194,7 @@ static void do_testfloat(int op, int rmode, bool exact) verCases_writeFunctionName(stderr); fputs("\n", stderr); - if (blacklisted(op, rmode)) { + if (!is_allowed(op, rmode)) { not_implemented(); return; } diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out index b1d8fd9107..01f7b1f240 100644 --- a/tests/qemu-iotests/049.out +++ b/tests/qemu-iotests/049.out @@ -92,16 +92,22 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp == 3. Invalid sizes == qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1024 -qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. +qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for +qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2 -qemu-img: TEST_DIR/t.qcow2: Value '-1024' is out of range for parameter 'size' +qemu-img: TEST_DIR/t.qcow2: Parameter 'size' expects a non-negative number below 2^64 +Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta- +and exabytes, respectively. qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k -qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. +qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for +qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2 -qemu-img: TEST_DIR/t.qcow2: Value '-1k' is out of range for parameter 'size' +qemu-img: TEST_DIR/t.qcow2: Parameter 'size' expects a non-negative number below 2^64 +Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta- +and exabytes, respectively. qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 index fe193fd5f4..0d51fe401e 100644 --- a/tests/qemu-iotests/178.out.qcow2 +++ b/tests/qemu-iotests/178.out.qcow2 @@ -13,7 +13,8 @@ qemu-img: Invalid option list: , qemu-img: Invalid parameter 'snapshot.foo' qemu-img: Failed in parsing snapshot param 'snapshot.foo=bar' qemu-img: --output must be used with human or json as argument. -qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. +qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for +qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. qemu-img: Unknown file format 'foo' == Size calculation for a new file (human) == diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw index 445e460fad..116241ddef 100644 --- a/tests/qemu-iotests/178.out.raw +++ b/tests/qemu-iotests/178.out.raw @@ -13,7 +13,8 @@ qemu-img: Invalid option list: , qemu-img: Invalid parameter 'snapshot.foo' qemu-img: Failed in parsing snapshot param 'snapshot.foo=bar' qemu-img: --output must be used with human or json as argument. -qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807. +qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for +qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes. qemu-img: Unknown file format 'foo' == Size calculation for a new file (human) == diff --git a/tests/qemu-iotests/241.out b/tests/qemu-iotests/241.out index 75f9f465e5..3f8c173cc8 100644 --- a/tests/qemu-iotests/241.out +++ b/tests/qemu-iotests/241.out @@ -5,7 +5,7 @@ QA output created by 241 size: 1024 min block: 1 [{ "start": 0, "length": 1000, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 1000, "length": 24, "depth": 0, "zero": true, "data": true, "offset": OFFSET}] +{ "start": 1000, "length": 24, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] 1 KiB (0x400) bytes allocated at offset 0 bytes (0x0) === Exporting unaligned raw image, forced server sector alignment === @@ -23,6 +23,6 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed size: 1024 min block: 1 [{ "start": 0, "length": 1000, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 1000, "length": 24, "depth": 0, "zero": true, "data": true, "offset": OFFSET}] +{ "start": 1000, "length": 24, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] 1 KiB (0x400) bytes allocated at offset 0 bytes (0x0) *** done diff --git a/tests/qtest/fuzz-test.c b/tests/qtest/fuzz-test.c index cdb1100a0b..6f161c93be 100644 --- a/tests/qtest/fuzz-test.c +++ b/tests/qtest/fuzz-test.c @@ -39,8 +39,7 @@ static void test_lp1878642_pci_bus_get_irq_level_assert(void) QTestState *s; s = qtest_init("-M pc-q35-5.0 " - "-nographic -monitor none -serial none " - "-d guest_errors -trace pci*"); + "-nographic -monitor none -serial none"); qtest_outl(s, 0xcf8, 0x8400f841); qtest_outl(s, 0xcfc, 0xebed205d); diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c index 3d82654b81..bd15a1c294 100644 --- a/tests/qtest/npcm7xx_pwm-test.c +++ b/tests/qtest/npcm7xx_pwm-test.c @@ -45,6 +45,7 @@ #define PLL_FBDV(rv) extract32((rv), 16, 12) #define PLL_OTDV1(rv) extract32((rv), 8, 3) #define PLL_OTDV2(rv) extract32((rv), 13, 3) +#define APB4CKDIV(rv) extract32((rv), 30, 2) #define APB3CKDIV(rv) extract32((rv), 28, 2) #define CLK2CKDIV(rv) extract32((rv), 0, 1) #define CLK4CKDIV(rv) extract32((rv), 26, 2) @@ -52,6 +53,49 @@ #define MAX_DUTY 1000000 +/* MFT (PWM fan) related */ +#define MFT_BA(n) (0xf0180000 + ((n) * 0x1000)) +#define MFT_IRQ(n) (96 + (n)) +#define MFT_CNT1 0x00 +#define MFT_CRA 0x02 +#define MFT_CRB 0x04 +#define MFT_CNT2 0x06 +#define MFT_PRSC 0x08 +#define MFT_CKC 0x0a +#define MFT_MCTRL 0x0c +#define MFT_ICTRL 0x0e +#define MFT_ICLR 0x10 +#define MFT_IEN 0x12 +#define MFT_CPA 0x14 +#define MFT_CPB 0x16 +#define MFT_CPCFG 0x18 +#define MFT_INASEL 0x1a +#define MFT_INBSEL 0x1c + +#define MFT_MCTRL_ALL 0x64 +#define MFT_ICLR_ALL 0x3f +#define MFT_IEN_ALL 0x3f +#define MFT_CPCFG_EQ_MODE 0x44 + +#define MFT_CKC_C2CSEL BIT(3) +#define MFT_CKC_C1CSEL BIT(0) + +#define MFT_ICTRL_TFPND BIT(5) +#define MFT_ICTRL_TEPND BIT(4) +#define MFT_ICTRL_TDPND BIT(3) +#define MFT_ICTRL_TCPND BIT(2) +#define MFT_ICTRL_TBPND BIT(1) +#define MFT_ICTRL_TAPND BIT(0) + +#define MFT_MAX_CNT 0xffff +#define MFT_TIMEOUT 0x5000 + +#define DEFAULT_RPM 19800 +#define DEFAULT_PRSC 255 +#define MFT_PULSE_PER_REVOLUTION 2 + +#define MAX_ERROR 1 + typedef struct PWMModule { int irq; uint64_t base_addr; @@ -210,19 +254,36 @@ static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index) return pwm_qom_get(qts, path, name); } +static void mft_qom_set(QTestState *qts, int index, const char *name, + uint32_t value) +{ + QDict *response; + char *path = g_strdup_printf("/machine/soc/mft[%d]", index); + + g_test_message("Setting properties %s of mft[%d] with value %u", + name, index, value); + response = qtest_qmp(qts, "{ 'execute': 'qom-set'," + " 'arguments': { 'path': %s, " + " 'property': %s, 'value': %u}}", + path, name, value); + /* The qom set message returns successfully. */ + g_assert_true(qdict_haskey(response, "return")); +} + static uint32_t get_pll(uint32_t con) { return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con) * PLL_OTDV2(con)); } -static uint64_t read_pclk(QTestState *qts) +static uint64_t read_pclk(QTestState *qts, bool mft) { uint64_t freq = REF_HZ; uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL); uint32_t pllcon; uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1); uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2); + uint32_t apbdiv = mft ? APB4CKDIV(clkdiv2) : APB3CKDIV(clkdiv2); switch (CPUCKSEL(clksel)) { case 0: @@ -241,7 +302,7 @@ static uint64_t read_pclk(QTestState *qts) g_assert_not_reached(); } - freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2)); + freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + apbdiv); return freq; } @@ -267,7 +328,7 @@ static uint32_t pwm_selector(uint32_t csr) static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr, uint32_t cnr) { - return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1)); + return read_pclk(qts, false) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1)); } static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted) @@ -301,6 +362,28 @@ static void pwm_write(QTestState *qts, const TestData *td, unsigned offset, qtest_writel(qts, td->module->base_addr + offset, value); } +static uint8_t mft_readb(QTestState *qts, int index, unsigned offset) +{ + return qtest_readb(qts, MFT_BA(index) + offset); +} + +static uint16_t mft_readw(QTestState *qts, int index, unsigned offset) +{ + return qtest_readw(qts, MFT_BA(index) + offset); +} + +static void mft_writeb(QTestState *qts, int index, unsigned offset, + uint8_t value) +{ + qtest_writeb(qts, MFT_BA(index) + offset, value); +} + +static void mft_writew(QTestState *qts, int index, unsigned offset, + uint16_t value) +{ + return qtest_writew(qts, MFT_BA(index) + offset, value); +} + static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td) { return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8); @@ -351,11 +434,116 @@ static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value) pwm_write(qts, td, td->pwm->cmr_offset, value); } +static int mft_compute_index(const TestData *td) +{ + int index = pwm_module_index(td->module) * ARRAY_SIZE(pwm_list) + + pwm_index(td->pwm); + + g_assert_cmpint(index, <, + ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)); + + return index; +} + +static void mft_reset_counters(QTestState *qts, int index) +{ + mft_writew(qts, index, MFT_CNT1, MFT_MAX_CNT); + mft_writew(qts, index, MFT_CNT2, MFT_MAX_CNT); + mft_writew(qts, index, MFT_CRA, MFT_MAX_CNT); + mft_writew(qts, index, MFT_CRB, MFT_MAX_CNT); + mft_writew(qts, index, MFT_CPA, MFT_MAX_CNT - MFT_TIMEOUT); + mft_writew(qts, index, MFT_CPB, MFT_MAX_CNT - MFT_TIMEOUT); +} + +static void mft_init(QTestState *qts, const TestData *td) +{ + int index = mft_compute_index(td); + + /* Enable everything */ + mft_writeb(qts, index, MFT_CKC, 0); + mft_writeb(qts, index, MFT_ICLR, MFT_ICLR_ALL); + mft_writeb(qts, index, MFT_MCTRL, MFT_MCTRL_ALL); + mft_writeb(qts, index, MFT_IEN, MFT_IEN_ALL); + mft_writeb(qts, index, MFT_INASEL, 0); + mft_writeb(qts, index, MFT_INBSEL, 0); + + /* Set cpcfg to use EQ mode, same as kernel driver */ + mft_writeb(qts, index, MFT_CPCFG, MFT_CPCFG_EQ_MODE); + + /* Write default counters, timeout and prescaler */ + mft_reset_counters(qts, index); + mft_writeb(qts, index, MFT_PRSC, DEFAULT_PRSC); + + /* Write default max rpm via QMP */ + mft_qom_set(qts, index, "max_rpm[0]", DEFAULT_RPM); + mft_qom_set(qts, index, "max_rpm[1]", DEFAULT_RPM); +} + +static int32_t mft_compute_cnt(uint32_t rpm, uint64_t clk) +{ + uint64_t cnt; + + if (rpm == 0) { + return -1; + } + + cnt = clk * 60 / ((DEFAULT_PRSC + 1) * rpm * MFT_PULSE_PER_REVOLUTION); + if (cnt >= MFT_TIMEOUT) { + return -1; + } + return MFT_MAX_CNT - cnt; +} + +static void mft_verify_rpm(QTestState *qts, const TestData *td, uint64_t duty) +{ + int index = mft_compute_index(td); + uint16_t cnt, cr; + uint32_t rpm = DEFAULT_RPM * duty / MAX_DUTY; + uint64_t clk = read_pclk(qts, true); + int32_t expected_cnt = mft_compute_cnt(rpm, clk); + + qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic"); + g_test_message( + "verifying rpm for mft[%d]: clk: %" PRIu64 ", duty: %" PRIu64 ", rpm: %u, cnt: %d", + index, clk, duty, rpm, expected_cnt); + + /* Verify rpm for fan A */ + /* Stop capture */ + mft_writeb(qts, index, MFT_CKC, 0); + mft_writeb(qts, index, MFT_ICLR, MFT_ICLR_ALL); + mft_reset_counters(qts, index); + g_assert_cmphex(mft_readw(qts, index, MFT_CNT1), ==, MFT_MAX_CNT); + g_assert_cmphex(mft_readw(qts, index, MFT_CRA), ==, MFT_MAX_CNT); + g_assert_cmphex(mft_readw(qts, index, MFT_CPA), ==, + MFT_MAX_CNT - MFT_TIMEOUT); + /* Start capture */ + mft_writeb(qts, index, MFT_CKC, MFT_CKC_C1CSEL); + g_assert_true(qtest_get_irq(qts, MFT_IRQ(index))); + if (expected_cnt == -1) { + g_assert_cmphex(mft_readb(qts, index, MFT_ICTRL), ==, MFT_ICTRL_TEPND); + } else { + g_assert_cmphex(mft_readb(qts, index, MFT_ICTRL), ==, MFT_ICTRL_TAPND); + cnt = mft_readw(qts, index, MFT_CNT1); + /* + * Due to error in clock measurement and rounding, we might have a small + * error in measuring RPM. + */ + g_assert_cmphex(cnt + MAX_ERROR, >=, expected_cnt); + g_assert_cmphex(cnt, <=, expected_cnt + MAX_ERROR); + cr = mft_readw(qts, index, MFT_CRA); + g_assert_cmphex(cnt, ==, cr); + } + + /* Verify rpm for fan B */ + + qtest_irq_intercept_out(qts, "/machine/soc/a9mpcore/gic"); +} + /* Check pwm registers can be reset to default value */ static void test_init(gconstpointer test_data) { const TestData *td = test_data; - QTestState *qts = qtest_init("-machine quanta-gsj"); + QTestState *qts = qtest_init("-machine npcm750-evb"); int module = pwm_module_index(td->module); int pwm = pwm_index(td->pwm); @@ -369,7 +557,7 @@ static void test_init(gconstpointer test_data) static void test_oneshot(gconstpointer test_data) { const TestData *td = test_data; - QTestState *qts = qtest_init("-machine quanta-gsj"); + QTestState *qts = qtest_init("-machine npcm750-evb"); int module = pwm_module_index(td->module); int pwm = pwm_index(td->pwm); uint32_t ppr, csr, pcr; @@ -400,13 +588,15 @@ static void test_oneshot(gconstpointer test_data) static void test_toggle(gconstpointer test_data) { const TestData *td = test_data; - QTestState *qts = qtest_init("-machine quanta-gsj"); + QTestState *qts = qtest_init("-machine npcm750-evb"); int module = pwm_module_index(td->module); int pwm = pwm_index(td->pwm); uint32_t ppr, csr, pcr, cnr, cmr; int i, j, k, l; uint64_t expected_freq, expected_duty; + mft_init(qts, td); + pcr = CH_EN | CH_MOD; for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) { ppr = ppr_list[i]; @@ -440,6 +630,9 @@ static void test_toggle(gconstpointer test_data) ==, expected_freq); } + /* Test MFT's RPM is correct. */ + mft_verify_rpm(qts, td, expected_duty); + /* Test inverted mode */ expected_duty = pwm_compute_duty(cnr, cmr, true); pwm_write_pcr(qts, td, pcr | CH_INV); diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh index 36b8a73a54..ce304f4933 100755 --- a/tests/tcg/configure.sh +++ b/tests/tcg/configure.sh @@ -251,6 +251,12 @@ for target in $target_list; do echo "CROSS_CC_HAS_ARMV8_MTE=y" >> $config_target_mak fi ;; + ppc*) + if do_compiler "$target_compiler" $target_compiler_cflags \ + -mpower8-vector -o $TMPE $TMPC; then + echo "CROSS_CC_HAS_POWER8_VECTOR=y" >> $config_target_mak + fi + ;; esac enabled_cross_compilers="$enabled_cross_compilers $target_compiler" diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target new file mode 100644 index 0000000000..0c6a4585fc --- /dev/null +++ b/tests/tcg/ppc64/Makefile.target @@ -0,0 +1,13 @@ +# -*- Mode: makefile -*- +# +# ppc64 specific tweaks + +VPATH += $(SRC_PATH)/tests/tcg/ppc64 +VPATH += $(SRC_PATH)/tests/tcg/ppc64le + +ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER8_VECTOR),) +PPC64_TESTS=bcdsub +endif +bcdsub: CFLAGS += -mpower8-vector + +TESTS += $(PPC64_TESTS) diff --git a/tests/tcg/ppc64le/Makefile.target b/tests/tcg/ppc64le/Makefile.target new file mode 100644 index 0000000000..1acfcff94a --- /dev/null +++ b/tests/tcg/ppc64le/Makefile.target @@ -0,0 +1,12 @@ +# -*- Mode: makefile -*- +# +# ppc64le specific tweaks + +VPATH += $(SRC_PATH)/tests/tcg/ppc64le + +ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER8_VECTOR),) +PPC64LE_TESTS=bcdsub +endif +bcdsub: CFLAGS += -mpower8-vector + +TESTS += $(PPC64LE_TESTS) diff --git a/tests/tcg/ppc64le/bcdsub.c b/tests/tcg/ppc64le/bcdsub.c new file mode 100644 index 0000000000..8c188cae6d --- /dev/null +++ b/tests/tcg/ppc64le/bcdsub.c @@ -0,0 +1,130 @@ +#include <assert.h> +#include <unistd.h> +#include <signal.h> + +#define CRF_LT (1 << 3) +#define CRF_GT (1 << 2) +#define CRF_EQ (1 << 1) +#define CRF_SO (1 << 0) +#define UNDEF 0 + +#define BCDSUB(vra, vrb, ps) \ + asm ("bcdsub. %1,%2,%3,%4;" \ + "mfocrf %0,0b10;" \ + : "=r" (cr), "=v" (vrt) \ + : "v" (vra), "v" (vrb), "i" (ps) \ + : ); + +#define TEST(vra, vrb, ps, exp_res, exp_cr6) \ + do { \ + __int128 vrt = 0; \ + int cr = 0; \ + BCDSUB(vra, vrb, ps); \ + if (exp_res) \ + assert(vrt == exp_res); \ + assert((cr >> 4) == exp_cr6); \ + } while (0) + + +/* + * Unbounded result is equal to zero: + * sign = (PS) ? 0b1111 : 0b1100 + * CR6 = 0b0010 + */ +void test_bcdsub_eq(void) +{ + __int128 a, b; + + /* maximum positive BCD value */ + a = b = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999c); + + TEST(a, b, 0, 0xc, CRF_EQ); + TEST(a, b, 1, 0xf, CRF_EQ); +} + +/* + * Unbounded result is greater than zero: + * sign = (PS) ? 0b1111 : 0b1100 + * CR6 = (overflow) ? 0b0101 : 0b0100 + */ +void test_bcdsub_gt(void) +{ + __int128 a, b, c; + + /* maximum positive BCD value */ + a = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999c); + + /* negative one BCD value */ + b = (__int128) 0x1d; + + TEST(a, b, 0, 0xc, (CRF_GT | CRF_SO)); + TEST(a, b, 1, 0xf, (CRF_GT | CRF_SO)); + + c = (((__int128) 0x9999999999999999) << 64 | 0x999999999999998c); + + TEST(c, b, 0, a, CRF_GT); + TEST(c, b, 1, (a | 0x3), CRF_GT); +} + +/* + * Unbounded result is less than zero: + * sign = 0b1101 + * CR6 = (overflow) ? 0b1001 : 0b1000 + */ +void test_bcdsub_lt(void) +{ + __int128 a, b; + + /* positive zero BCD value */ + a = (__int128) 0xc; + + /* positive one BCD value */ + b = (__int128) 0x1c; + + TEST(a, b, 0, 0x1d, CRF_LT); + TEST(a, b, 1, 0x1d, CRF_LT); + + /* maximum negative BCD value */ + a = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999d); + + /* positive one BCD value */ + b = (__int128) 0x1c; + + TEST(a, b, 0, 0xd, (CRF_LT | CRF_SO)); + TEST(a, b, 1, 0xd, (CRF_LT | CRF_SO)); +} + +void test_bcdsub_invalid(void) +{ + __int128 a, b; + + /* positive one BCD value */ + a = (__int128) 0x1c; + b = 0xf00; + + TEST(a, b, 0, UNDEF, CRF_SO); + TEST(a, b, 1, UNDEF, CRF_SO); + + TEST(b, a, 0, UNDEF, CRF_SO); + TEST(b, a, 1, UNDEF, CRF_SO); + + a = 0xbad; + + TEST(a, b, 0, UNDEF, CRF_SO); + TEST(a, b, 1, UNDEF, CRF_SO); +} + +int main(void) +{ + struct sigaction action; + + action.sa_handler = _exit; + sigaction(SIGABRT, &action, NULL); + + test_bcdsub_eq(); + test_bcdsub_gt(); + test_bcdsub_lt(); + test_bcdsub_invalid(); + + return 0; +} diff --git a/tests/unit/test-cutils.c b/tests/unit/test-cutils.c index 1aa8351520..bad3a60993 100644 --- a/tests/unit/test-cutils.c +++ b/tests/unit/test-cutils.c @@ -1960,18 +1960,24 @@ static void test_qemu_strtosz_simple(void) g_assert_cmpint(res, ==, 0); g_assert(endptr == str + 1); - str = "12345"; + /* Leading 0 gives decimal results, not octal */ + str = "08"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, 8); + g_assert(endptr == str + 2); + + /* Leading space is ignored */ + str = " 12345"; err = qemu_strtosz(str, &endptr, &res); g_assert_cmpint(err, ==, 0); g_assert_cmpint(res, ==, 12345); - g_assert(endptr == str + 5); + g_assert(endptr == str + 6); err = qemu_strtosz(str, NULL, &res); g_assert_cmpint(err, ==, 0); g_assert_cmpint(res, ==, 12345); - /* Note: precision is 53 bits since we're parsing with strtod() */ - str = "9007199254740991"; /* 2^53-1 */ err = qemu_strtosz(str, &endptr, &res); g_assert_cmpint(err, ==, 0); @@ -1987,7 +1993,7 @@ static void test_qemu_strtosz_simple(void) str = "9007199254740993"; /* 2^53+1 */ err = qemu_strtosz(str, &endptr, &res); g_assert_cmpint(err, ==, 0); - g_assert_cmpint(res, ==, 0x20000000000000); /* rounded to 53 bits */ + g_assert_cmpint(res, ==, 0x20000000000001); g_assert(endptr == str + 16); str = "18446744073709549568"; /* 0xfffffffffffff800 (53 msbs set) */ @@ -1999,11 +2005,40 @@ static void test_qemu_strtosz_simple(void) str = "18446744073709550591"; /* 0xfffffffffffffbff */ err = qemu_strtosz(str, &endptr, &res); g_assert_cmpint(err, ==, 0); - g_assert_cmpint(res, ==, 0xfffffffffffff800); /* rounded to 53 bits */ + g_assert_cmpint(res, ==, 0xfffffffffffffbff); g_assert(endptr == str + 20); - /* 0x7ffffffffffffe00..0x7fffffffffffffff get rounded to - * 0x8000000000000000, thus -ERANGE; see test_qemu_strtosz_erange() */ + str = "18446744073709551615"; /* 0xffffffffffffffff */ + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, 0xffffffffffffffff); + g_assert(endptr == str + 20); +} + +static void test_qemu_strtosz_hex(void) +{ + const char *str; + const char *endptr; + int err; + uint64_t res = 0xbaadf00d; + + str = "0x0"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, 0); + g_assert(endptr == str + 3); + + str = "0xab"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, 171); + g_assert(endptr == str + 4); + + str = "0xae"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, 174); + g_assert(endptr == str + 4); } static void test_qemu_strtosz_units(void) @@ -2064,14 +2099,36 @@ static void test_qemu_strtosz_units(void) static void test_qemu_strtosz_float(void) { - const char *str = "12.345M"; + const char *str; int err; const char *endptr; uint64_t res = 0xbaadf00d; + str = "0.5E"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, EiB / 2); + g_assert(endptr == str + 4); + + /* For convenience, a fraction of 0 is tolerated even on bytes */ + str = "1.0B"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, 1); + g_assert(endptr == str + 4); + + /* An empty fraction is tolerated */ + str = "1.k"; err = qemu_strtosz(str, &endptr, &res); g_assert_cmpint(err, ==, 0); - g_assert_cmpint(res, ==, 12.345 * MiB); + g_assert_cmpint(res, ==, 1024); + g_assert(endptr == str + 3); + + /* For convenience, we permit values that are not byte-exact */ + str = "12.345M"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, (uint64_t) (12.345 * MiB)); g_assert(endptr == str + 7); } @@ -2106,6 +2163,45 @@ static void test_qemu_strtosz_invalid(void) err = qemu_strtosz(str, &endptr, &res); g_assert_cmpint(err, ==, -EINVAL); g_assert(endptr == str); + + /* Fractional values require scale larger than bytes */ + str = "1.1B"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, -EINVAL); + g_assert(endptr == str); + + str = "1.1"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, -EINVAL); + g_assert(endptr == str); + + /* No floating point exponents */ + str = "1.5e1k"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, -EINVAL); + g_assert(endptr == str); + + str = "1.5E+0k"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, -EINVAL); + g_assert(endptr == str); + + /* No hex fractions */ + str = "0x1.8k"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, -EINVAL); + g_assert(endptr == str); + + /* No negative values */ + str = "-0"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, -EINVAL); + g_assert(endptr == str); + + str = "-1"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, -EINVAL); + g_assert(endptr == str); } static void test_qemu_strtosz_trailing(void) @@ -2131,6 +2227,30 @@ static void test_qemu_strtosz_trailing(void) err = qemu_strtosz(str, NULL, &res); g_assert_cmpint(err, ==, -EINVAL); + + str = "0x"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(res, ==, 0); + g_assert(endptr == str + 1); + + err = qemu_strtosz(str, NULL, &res); + g_assert_cmpint(err, ==, -EINVAL); + + str = "0.NaN"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert(endptr == str + 2); + + err = qemu_strtosz(str, NULL, &res); + g_assert_cmpint(err, ==, -EINVAL); + + str = "123-45"; + err = qemu_strtosz(str, &endptr, &res); + g_assert_cmpint(res, ==, 123); + g_assert(endptr == str + 3); + + err = qemu_strtosz(str, NULL, &res); + g_assert_cmpint(err, ==, -EINVAL); } static void test_qemu_strtosz_erange(void) @@ -2140,22 +2260,7 @@ static void test_qemu_strtosz_erange(void) int err; uint64_t res = 0xbaadf00d; - str = "-1"; - err = qemu_strtosz(str, &endptr, &res); - g_assert_cmpint(err, ==, -ERANGE); - g_assert(endptr == str + 2); - - str = "18446744073709550592"; /* 0xfffffffffffffc00 */ - err = qemu_strtosz(str, &endptr, &res); - g_assert_cmpint(err, ==, -ERANGE); - g_assert(endptr == str + 20); - - str = "18446744073709551615"; /* 2^64-1 */ - err = qemu_strtosz(str, &endptr, &res); - g_assert_cmpint(err, ==, -ERANGE); - g_assert(endptr == str + 20); - - str = "18446744073709551616"; /* 2^64 */ + str = "18446744073709551616"; /* 2^64; see strtosz_simple for 2^64-1 */ err = qemu_strtosz(str, &endptr, &res); g_assert_cmpint(err, ==, -ERANGE); g_assert(endptr == str + 20); @@ -2168,15 +2273,22 @@ static void test_qemu_strtosz_erange(void) static void test_qemu_strtosz_metric(void) { - const char *str = "12345k"; + const char *str; int err; const char *endptr; uint64_t res = 0xbaadf00d; + str = "12345k"; err = qemu_strtosz_metric(str, &endptr, &res); g_assert_cmpint(err, ==, 0); g_assert_cmpint(res, ==, 12345000); g_assert(endptr == str + 6); + + str = "12.345M"; + err = qemu_strtosz_metric(str, &endptr, &res); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(res, ==, 12345000); + g_assert(endptr == str + 7); } int main(int argc, char **argv) @@ -2443,6 +2555,8 @@ int main(int argc, char **argv) g_test_add_func("/cutils/strtosz/simple", test_qemu_strtosz_simple); + g_test_add_func("/cutils/strtosz/hex", + test_qemu_strtosz_hex); g_test_add_func("/cutils/strtosz/units", test_qemu_strtosz_units); g_test_add_func("/cutils/strtosz/float", diff --git a/tests/unit/test-keyval.c b/tests/unit/test-keyval.c index ee927fe4e4..e20c07cf3e 100644 --- a/tests/unit/test-keyval.c +++ b/tests/unit/test-keyval.c @@ -445,9 +445,9 @@ static void test_keyval_visit_size(void) visit_end_struct(v, NULL); visit_free(v); - /* Note: precision is 53 bits since we're parsing with strtod() */ + /* Note: full 64 bits of precision */ - /* Around limit of precision: 2^53-1, 2^53, 2^53+1 */ + /* Around double limit of precision: 2^53-1, 2^53, 2^53+1 */ qdict = keyval_parse("sz1=9007199254740991," "sz2=9007199254740992," "sz3=9007199254740993", @@ -460,22 +460,25 @@ static void test_keyval_visit_size(void) visit_type_size(v, "sz2", &sz, &error_abort); g_assert_cmphex(sz, ==, 0x20000000000000); visit_type_size(v, "sz3", &sz, &error_abort); - g_assert_cmphex(sz, ==, 0x20000000000000); + g_assert_cmphex(sz, ==, 0x20000000000001); visit_check_struct(v, &error_abort); visit_end_struct(v, NULL); visit_free(v); - /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */ - qdict = keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */ - "sz2=9223372036854775295", /* 7ffffffffffffdff */ + /* Close to signed integer limit 2^63 */ + qdict = keyval_parse("sz1=9223372036854775807," /* 7fffffffffffffff */ + "sz2=9223372036854775808," /* 8000000000000000 */ + "sz3=9223372036854775809", /* 8000000000000001 */ NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); visit_type_size(v, "sz1", &sz, &error_abort); - g_assert_cmphex(sz, ==, 0x7ffffffffffffc00); + g_assert_cmphex(sz, ==, 0x7fffffffffffffff); visit_type_size(v, "sz2", &sz, &error_abort); - g_assert_cmphex(sz, ==, 0x7ffffffffffffc00); + g_assert_cmphex(sz, ==, 0x8000000000000000); + visit_type_size(v, "sz3", &sz, &error_abort); + g_assert_cmphex(sz, ==, 0x8000000000000001); visit_check_struct(v, &error_abort); visit_end_struct(v, NULL); visit_free(v); @@ -490,14 +493,26 @@ static void test_keyval_visit_size(void) visit_type_size(v, "sz1", &sz, &error_abort); g_assert_cmphex(sz, ==, 0xfffffffffffff800); visit_type_size(v, "sz2", &sz, &error_abort); - g_assert_cmphex(sz, ==, 0xfffffffffffff800); + g_assert_cmphex(sz, ==, 0xfffffffffffffbff); + visit_check_struct(v, &error_abort); + visit_end_struct(v, NULL); + visit_free(v); + + /* Actual limit 2^64-1*/ + qdict = keyval_parse("sz1=18446744073709551615", /* ffffffffffffffff */ + NULL, NULL, &error_abort); + v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); + qobject_unref(qdict); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_type_size(v, "sz1", &sz, &error_abort); + g_assert_cmphex(sz, ==, 0xffffffffffffffff); visit_check_struct(v, &error_abort); visit_end_struct(v, NULL); visit_free(v); /* Beyond limits */ qdict = keyval_parse("sz1=-1," - "sz2=18446744073709550592", /* fffffffffffffc00 */ + "sz2=18446744073709551616", /* 2^64 */ NULL, NULL, &error_abort); v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); qobject_unref(qdict); diff --git a/tests/unit/test-qemu-opts.c b/tests/unit/test-qemu-opts.c index 8bbb17b1c7..6568e31a72 100644 --- a/tests/unit/test-qemu-opts.c +++ b/tests/unit/test-qemu-opts.c @@ -654,9 +654,9 @@ static void test_opts_parse_size(void) g_assert_cmpuint(opts_count(opts), ==, 1); g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0); - /* Note: precision is 53 bits since we're parsing with strtod() */ + /* Note: full 64 bits of precision */ - /* Around limit of precision: 2^53-1, 2^53, 2^54 */ + /* Around double limit of precision: 2^53-1, 2^53, 2^53+1 */ opts = qemu_opts_parse(&opts_list_02, "size1=9007199254740991," "size2=9007199254740992," @@ -668,18 +668,21 @@ static void test_opts_parse_size(void) g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), ==, 0x20000000000000); g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1), - ==, 0x20000000000000); + ==, 0x20000000000001); - /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */ + /* Close to signed int limit: 2^63-1, 2^63, 2^63+1 */ opts = qemu_opts_parse(&opts_list_02, - "size1=9223372036854774784," /* 7ffffffffffffc00 */ - "size2=9223372036854775295", /* 7ffffffffffffdff */ + "size1=9223372036854775807," /* 7fffffffffffffff */ + "size2=9223372036854775808," /* 8000000000000000 */ + "size3=9223372036854775809", /* 8000000000000001 */ false, &error_abort); - g_assert_cmpuint(opts_count(opts), ==, 2); + g_assert_cmpuint(opts_count(opts), ==, 3); g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), - ==, 0x7ffffffffffffc00); + ==, 0x7fffffffffffffff); g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), - ==, 0x7ffffffffffffc00); + ==, 0x8000000000000000); + g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1), + ==, 0x8000000000000001); /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ opts = qemu_opts_parse(&opts_list_02, @@ -690,14 +693,22 @@ static void test_opts_parse_size(void) g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), ==, 0xfffffffffffff800); g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), - ==, 0xfffffffffffff800); + ==, 0xfffffffffffffbff); + + /* Actual limit, 2^64-1 */ + opts = qemu_opts_parse(&opts_list_02, + "size1=18446744073709551615", /* ffffffffffffffff */ + false, &error_abort); + g_assert_cmpuint(opts_count(opts), ==, 1); + g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), + ==, 0xffffffffffffffff); /* Beyond limits */ opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err); error_free_or_abort(&err); g_assert(!opts); opts = qemu_opts_parse(&opts_list_02, - "size1=18446744073709550592", /* fffffffffffffc00 */ + "size1=18446744073709551616", /* 2^64 */ false, &err); error_free_or_abort(&err); g_assert(!opts); |