qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Beraldo Leal <bleal@redhat.com>,
	qemu-block@nongnu.org, John Snow <jsnow@redhat.com>,
	Hanna Reitz <hreitz@redhat.com>, Cleber Rosa <crosa@redhat.com>,
	Eric Blake <eblake@redhat.com>
Subject: [PATCH v5 04/18] iotests: make qemu_img raise on non-zero rc by default
Date: Mon, 21 Mar 2022 16:16:04 -0400	[thread overview]
Message-ID: <20220321201618.903471-5-jsnow@redhat.com> (raw)
In-Reply-To: <20220321201618.903471-1-jsnow@redhat.com>

re-write qemu_img() as a function that will by default raise a
VerboseProcessException (extended from CalledProcessException) on
non-zero return codes. This will produce a stack trace that will show
the command line arguments and return code from the failed process run.

Users that want something more flexible (there appears to be only one)
can use check=False and manage the return themselves. However, when the
return code is negative, the Exception will be raised no matter what.
This is done under the belief that there's no legitimate reason, even in
negative tests, to see a crash from qemu-img.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
---
 tests/qemu-iotests/257        |  8 +++--
 tests/qemu-iotests/iotests.py | 57 ++++++++++++++++++++++++++++++-----
 2 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257
index fb5359c581..e7e7a2317e 100755
--- a/tests/qemu-iotests/257
+++ b/tests/qemu-iotests/257
@@ -241,11 +241,13 @@ def compare_images(image, reference, baseimg=None, expected_match=True):
     expected_ret = 0 if expected_match else 1
     if baseimg:
         qemu_img("rebase", "-u", "-b", baseimg, '-F', iotests.imgfmt, image)
-    ret = qemu_img("compare", image, reference)
+
+    sub = qemu_img("compare", image, reference, check=False)
+
     log('qemu_img compare "{:s}" "{:s}" ==> {:s}, {:s}'.format(
         image, reference,
-        "Identical" if ret == 0 else "Mismatch",
-        "OK!" if ret == expected_ret else "ERROR!"),
+        "Identical" if sub.returncode == 0 else "Mismatch",
+        "OK!" if sub.returncode == expected_ret else "ERROR!"),
         filters=[iotests.filter_testfiles])
 
 def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 508adade9e..4afe63df07 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -37,9 +37,10 @@
 
 from contextlib import contextmanager
 
+from qemu.aqmp.legacy import QEMUMonitorProtocol
 from qemu.machine import qtest
 from qemu.qmp import QMPMessage
-from qemu.aqmp.legacy import QEMUMonitorProtocol
+from qemu.utils import VerboseProcessError
 
 # Use this logger for logging messages directly from the iotests module
 logger = logging.getLogger('qemu.iotests')
@@ -215,9 +216,50 @@ def qemu_img_pipe_and_status(*args: str) -> Tuple[str, int]:
     return qemu_tool_pipe_and_status('qemu-img', full_args,
                                      drop_successful_output=is_create)
 
-def qemu_img(*args: str) -> int:
-    '''Run qemu-img and return the exit code'''
-    return qemu_img_pipe_and_status(*args)[1]
+def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
+             ) -> 'subprocess.CompletedProcess[str]':
+    """
+    Run qemu_img and return the status code and console output.
+
+    This function always prepends QEMU_IMG_OPTIONS and may further alter
+    the args for 'create' commands.
+
+    :param args: command-line arguments to qemu-img.
+    :param check: Enforce a return code of zero.
+    :param combine_stdio: set to False to keep stdout/stderr separated.
+
+    :raise VerboseProcessError:
+        When the return code is negative, or on any non-zero exit code
+        when 'check=True' was provided (the default). This exception has
+        'stdout', 'stderr', and 'returncode' properties that may be
+        inspected to show greater detail. If this exception is not
+        handled, the command-line, return code, and all console output
+        will be included at the bottom of the stack trace.
+
+    :return:
+        a CompletedProcess. This object has args, returncode, and stdout
+        properties. If streams are not combined, it will also have a
+        stderr property.
+    """
+    full_args = qemu_img_args + qemu_img_create_prepare_args(list(args))
+
+    subp = subprocess.run(
+        full_args,
+        stdout=subprocess.PIPE,
+        stderr=subprocess.STDOUT if combine_stdio else subprocess.PIPE,
+        universal_newlines=True,
+        check=False
+    )
+
+    if check and subp.returncode or (subp.returncode < 0):
+        raise VerboseProcessError(
+            subp.returncode, full_args,
+            output=subp.stdout,
+            stderr=subp.stderr,
+        )
+
+    return subp
+
 
 def ordered_qmp(qmsg, conv_keys=True):
     # Dictionaries are not ordered prior to 3.6, therefore:
@@ -232,7 +274,7 @@ def ordered_qmp(qmsg, conv_keys=True):
         return od
     return qmsg
 
-def qemu_img_create(*args):
+def qemu_img_create(*args: str) -> 'subprocess.CompletedProcess[str]':
     return qemu_img('create', *args)
 
 def qemu_img_measure(*args):
@@ -467,8 +509,9 @@ def qemu_nbd_popen(*args):
 
 def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
     '''Return True if two image files are identical'''
-    return qemu_img('compare', '-f', fmt1,
-                    '-F', fmt2, img1, img2) == 0
+    res = qemu_img('compare', '-f', fmt1,
+                   '-F', fmt2, img1, img2, check=False)
+    return res.returncode == 0
 
 def create_image(name, size):
     '''Create a fully-allocated raw image with sector markers'''
-- 
2.34.1



  parent reply	other threads:[~2022-03-21 20:18 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-21 20:16 [PATCH v5 00/18] iotests: add enhanced debugging info to qemu-img failures John Snow
2022-03-21 20:16 ` [PATCH v5 01/18] python/utils: add add_visual_margin() text decoration utility John Snow
2022-03-21 20:16 ` [PATCH v5 02/18] python/utils: add VerboseProcessError John Snow
2022-03-21 20:16 ` [PATCH v5 03/18] iotests: Remove explicit checks for qemu_img() == 0 John Snow
2022-03-21 20:16 ` John Snow [this message]
2022-03-21 20:16 ` [PATCH v5 05/18] iotests: fortify compare_images() against crashes John Snow
2022-03-21 20:16 ` [PATCH v5 06/18] iotests: add qemu_img_json() John Snow
2022-03-21 20:16 ` [PATCH v5 07/18] iotests: use qemu_img_json() when applicable John Snow
2022-03-21 20:16 ` [PATCH v5 08/18] iotests: add qemu_img_info() John Snow
2022-03-21 20:16 ` [PATCH v5 09/18] iotests/remove-bitmap-from-backing: use qemu_img_info() John Snow
2022-03-21 20:16 ` [PATCH v5 10/18] iotests: add qemu_img_map() function John Snow
2022-03-21 20:16 ` [PATCH v5 11/18] iotests: change supports_quorum to use qemu_img John Snow
2022-03-21 20:16 ` [PATCH v5 12/18] iotests: replace unchecked calls to qemu_img_pipe() John Snow
2022-03-21 20:16 ` [PATCH v5 13/18] iotests/149: Remove qemu_img_pipe() call John Snow
2022-03-21 20:16 ` [PATCH v5 14/18] iotests: remove remaining calls to qemu_img_pipe() John Snow
2022-03-21 20:16 ` [PATCH v5 15/18] iotests: use qemu_img() in has_working_luks() John Snow
2022-03-21 20:16 ` [PATCH v5 16/18] iotests: replace qemu_img_log('create', ...) calls John Snow
2022-03-21 20:16 ` [PATCH v5 17/18] iotests: remove qemu_img_pipe_and_status() John Snow
2022-03-21 21:31   ` Eric Blake
2022-03-21 20:16 ` [PATCH v5 18/18] iotests: make qemu_img_log and img_info_log raise on error John Snow
2022-03-21 21:33   ` Eric Blake
2022-03-22  9:42 ` [PATCH v5 00/18] iotests: add enhanced debugging info to qemu-img failures Hanna Reitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220321201618.903471-5-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=bleal@redhat.com \
    --cc=crosa@redhat.com \
    --cc=eblake@redhat.com \
    --cc=hreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).