diff mbox

[v5,02/13] qtest: Don't perform side effects inside assertion

Message ID 20170818211542.5380-3-eblake@redhat.com
State New
Headers show

Commit Message

Eric Blake Aug. 18, 2017, 9:15 p.m. UTC
Assertions should be separate from the side effects, since in
theory, g_assert() can be disabled (in practice, we can't really
ever do that).

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 qtest.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 23 deletions(-)

Comments

Philippe Mathieu-Daudé Aug. 18, 2017, 9:33 p.m. UTC | #1
Hi Eric,

On 08/18/2017 06:15 PM, Eric Blake wrote:
> Assertions should be separate from the side effects, since in
> theory, g_assert() can be disabled (in practice, we can't really
> ever do that).

What about the suggestion on your "Hacks for building on gcc 7 / Fedora 
26" series about avoid building without assertions?

The obvious win is a more readable code.

http://lists.nongnu.org/archive/html/qemu-devel/2017-07/msg06084.html

> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
>   qtest.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++-------------------
>   1 file changed, 57 insertions(+), 23 deletions(-)
> 
> diff --git a/qtest.c b/qtest.c
> index 88a09e9afc..cbbfb71114 100644
> --- a/qtest.c
> +++ b/qtest.c
> @@ -332,10 +332,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>                  strcmp(words[0], "outl") == 0) {
>           unsigned long addr;
>           unsigned long value;
> +        int ret;
> 
>           g_assert(words[1] && words[2]);
> -        g_assert(qemu_strtoul(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtoul(words[2], NULL, 0, &value) == 0);
> +        ret = qemu_strtoul(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
> +        ret = qemu_strtoul(words[2], NULL, 0, &value);
> +        g_assert(ret == 0);
>           g_assert(addr <= 0xffff);
> 
>           if (words[0][3] == 'b') {
> @@ -352,9 +355,11 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>           strcmp(words[0], "inl") == 0) {
>           unsigned long addr;
>           uint32_t value = -1U;
> +        int ret;
> 
>           g_assert(words[1]);
> -        g_assert(qemu_strtoul(words[1], NULL, 0, &addr) == 0);
> +        ret = qemu_strtoul(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
>           g_assert(addr <= 0xffff);
> 
>           if (words[0][2] == 'b') {
> @@ -372,10 +377,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>                  strcmp(words[0], "writeq") == 0) {
>           uint64_t addr;
>           uint64_t value;
> +        int ret;
> 
>           g_assert(words[1] && words[2]);
> -        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtou64(words[2], NULL, 0, &value) == 0);
> +        ret = qemu_strtou64(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
> +        ret = qemu_strtou64(words[2], NULL, 0, &value);
> +        g_assert(ret == 0);
> 
>           if (words[0][5] == 'b') {
>               uint8_t data = value;
> @@ -401,9 +409,11 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>                  strcmp(words[0], "readq") == 0) {
>           uint64_t addr;
>           uint64_t value = UINT64_C(-1);
> +        int ret;
> 
>           g_assert(words[1]);
> -        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> +        ret = qemu_strtou64(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
> 
>           if (words[0][4] == 'b') {
>               uint8_t data;
> @@ -427,10 +437,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>           uint64_t addr, len, i;
>           uint8_t *data;
>           char *enc;
> +        int ret;
> 
>           g_assert(words[1] && words[2]);
> -        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
> +        ret = qemu_strtou64(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
> +        ret = qemu_strtou64(words[2], NULL, 0, &len);
> +        g_assert(ret == 0);
>           /* We'd send garbage to libqtest if len is 0 */
>           g_assert(len);
> 
> @@ -451,10 +464,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>           uint64_t addr, len;
>           uint8_t *data;
>           gchar *b64_data;
> +        int ret;
> 
>           g_assert(words[1] && words[2]);
> -        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
> +        ret = qemu_strtou64(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
> +        ret = qemu_strtou64(words[2], NULL, 0, &len);
> +        g_assert(ret == 0);
> 
>           data = g_malloc(len);
>           cpu_physical_memory_read(addr, data, len);
> @@ -468,10 +484,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>           uint64_t addr, len, i;
>           uint8_t *data;
>           size_t data_len;
> +        int ret;
> 
>           g_assert(words[1] && words[2] && words[3]);
> -        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
> +        ret = qemu_strtou64(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
> +        ret = qemu_strtou64(words[2], NULL, 0, &len);
> +        g_assert(ret == 0);
> 
>           data_len = strlen(words[3]);
>           if (data_len < 3) {
> @@ -497,11 +516,15 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>           uint64_t addr, len;
>           uint8_t *data;
>           unsigned long pattern;
> +        int ret;
> 
>           g_assert(words[1] && words[2] && words[3]);
> -        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
> -        g_assert(qemu_strtoul(words[3], NULL, 0, &pattern) == 0);
> +        ret = qemu_strtou64(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
> +        ret = qemu_strtou64(words[2], NULL, 0, &len);
> +        g_assert(ret == 0);
> +        ret = qemu_strtoul(words[3], NULL, 0, &pattern);
> +        g_assert(ret == 0);
> 
>           if (len) {
>               data = g_malloc(len);
> @@ -517,10 +540,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>           uint8_t *data;
>           size_t data_len;
>           gsize out_len;
> +        int ret;
> 
>           g_assert(words[1] && words[2] && words[3]);
> -        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
> +        ret = qemu_strtou64(words[1], NULL, 0, &addr);
> +        g_assert(ret == 0);
> +        ret = qemu_strtou64(words[2], NULL, 0, &len);
> +        g_assert(ret == 0);
> 
>           data_len = strlen(words[3]);
>           if (data_len < 3) {
> @@ -551,11 +577,16 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>       } else if (strcmp(words[0], "rtas") == 0) {
>           uint64_t res, args, ret;
>           unsigned long nargs, nret;
> +        int rc;
> 
> -        g_assert(qemu_strtoul(words[2], NULL, 0, &nargs) == 0);
> -        g_assert(qemu_strtou64(words[3], NULL, 0, &args) == 0);
> -        g_assert(qemu_strtoul(words[4], NULL, 0, &nret) == 0);
> -        g_assert(qemu_strtou64(words[5], NULL, 0, &ret) == 0);
> +        rc = qemu_strtoul(words[2], NULL, 0, &nargs);
> +        g_assert(rc == 0);
> +        rc = qemu_strtou64(words[3], NULL, 0, &args);
> +        g_assert(rc == 0);
> +        rc = qemu_strtoul(words[4], NULL, 0, &nret);
> +        g_assert(rc == 0);
> +        rc = qemu_strtou64(words[5], NULL, 0, &ret);
> +        g_assert(rc == 0);
>           res = qtest_rtas_call(words[1], nargs, args, nret, ret);
> 
>           qtest_send_prefix(chr);
> @@ -565,7 +596,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>           int64_t ns;
> 
>           if (words[1]) {
> -            g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
> +            int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
> +            g_assert(ret == 0);
>           } else {
>               ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
>           }
> @@ -575,9 +607,11 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>                       (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
>       } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
>           int64_t ns;
> +        int ret;
> 
>           g_assert(words[1]);
> -        g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
> +        ret = qemu_strtoi64(words[1], NULL, 0, &ns);
> +        g_assert(ret == 0);
>           qtest_clock_warp(ns);
>           qtest_send_prefix(chr);
>           qtest_sendf(chr, "OK %"PRIi64"\n",
>
Eric Blake Aug. 18, 2017, 9:39 p.m. UTC | #2
On 08/18/2017 04:33 PM, Philippe Mathieu-Daudé wrote:
> Hi Eric,
> 
> On 08/18/2017 06:15 PM, Eric Blake wrote:
>> Assertions should be separate from the side effects, since in
>> theory, g_assert() can be disabled (in practice, we can't really
>> ever do that).
> 
> What about the suggestion on your "Hacks for building on gcc 7 / Fedora
> 26" series about avoid building without assertions?

NDEBUG doesn't affect g_assert() (only assert(), but that wasn't in use
here) - I have to double-check glib documentation to see whether
g_assert() can be crippled in a manner similar to how I know assert()
can be crippled.  Ideally, we have a form that always performs side
effects exactly once, whether or not abort-on-error is enabled (assert()
does not have that, but I don't know whether glib does).

> 
> The obvious win is a more readable code.
> 
> http://lists.nongnu.org/archive/html/qemu-devel/2017-07/msg06084.html

Indeed, that's a patch proposal that I still haven't written, but it can
be done independently of this series.

Still, even if we guarantee that assertions will never be crippled for
qemu, it is bad practice to code side-effects in an assert(), because it
makes the code harder to copy-and-paste into projects that DO work with
assertions disabled, and it raises red flags in reviewers' minds of
whether it was intentional.

[And truth be told, this particular patch is not really about libqtest,
so much as something that horrified me when I was grepping for
qemu_strtoul() in order to fix the checkpatch warning I got on
libqtest's raw use of strtol() in patch 6, and which necessitated me to
write patch 5 - even though the name of the file in question is 'qtest.c']
Philippe Mathieu-Daudé Aug. 18, 2017, 9:52 p.m. UTC | #3
On 08/18/2017 06:39 PM, Eric Blake wrote:
> On 08/18/2017 04:33 PM, Philippe Mathieu-Daudé wrote:
>> Hi Eric,
>>
>> On 08/18/2017 06:15 PM, Eric Blake wrote:
>>> Assertions should be separate from the side effects, since in
>>> theory, g_assert() can be disabled (in practice, we can't really
>>> ever do that).
>>
>> What about the suggestion on your "Hacks for building on gcc 7 / Fedora
>> 26" series about avoid building without assertions?
> 
> NDEBUG doesn't affect g_assert() (only assert(), but that wasn't in use
> here) - I have to double-check glib documentation to see whether
> g_assert() can be crippled in a manner similar to how I know assert()
> can be crippled.  Ideally, we have a form that always performs side
> effects exactly once, whether or not abort-on-error is enabled (assert()
> does not have that, but I don't know whether glib does).

Yes it does:

https://developer.gnome.org/glib/stable/glib-Testing.html#g-assert

"The macro can be turned off in final releases of code by defining 
G_DISABLE_ASSERT when compiling the application, so code must not depend 
on any side effects from expr ."

> 
>>
>> The obvious win is a more readable code.
>>
>> http://lists.nongnu.org/archive/html/qemu-devel/2017-07/msg06084.html
> 
> Indeed, that's a patch proposal that I still haven't written, but it can
> be done independently of this series.
> 
> Still, even if we guarantee that assertions will never be crippled for
> qemu, it is bad practice to code side-effects in an assert(), because it
> makes the code harder to copy-and-paste into projects that DO work with
> assertions disabled, and it raises red flags in reviewers' minds of
> whether it was intentional.

This is a good point.

> [And truth be told, this particular patch is not really about libqtest,
> so much as something that horrified me when I was grepping for
> qemu_strtoul() in order to fix the checkpatch warning I got on
> libqtest's raw use of strtol() in patch 6, and which necessitated me to
> write patch 5 - even though the name of the file in question is 'qtest.c']
>
Eric Blake Aug. 18, 2017, 9:58 p.m. UTC | #4
On 08/18/2017 04:39 PM, Eric Blake wrote:
> On 08/18/2017 04:33 PM, Philippe Mathieu-Daudé wrote:
>> Hi Eric,
>>
>> On 08/18/2017 06:15 PM, Eric Blake wrote:
>>> Assertions should be separate from the side effects, since in
>>> theory, g_assert() can be disabled (in practice, we can't really
>>> ever do that).
>>
>> What about the suggestion on your "Hacks for building on gcc 7 / Fedora
>> 26" series about avoid building without assertions?
> 
> NDEBUG doesn't affect g_assert() (only assert(), but that wasn't in use
> here) - I have to double-check glib documentation to see whether
> g_assert() can be crippled in a manner similar to how I know assert()
> can be crippled.  Ideally, we have a form that always performs side
> effects exactly once, whether or not abort-on-error is enabled (assert()
> does not have that, but I don't know whether glib does).

Per https://developer.gnome.org/glib/stable/glib-Testing.html#g-assert,
G_DISABLE_ASSERT has the same compile-time effect on g_assert() as
NDEBUG on assert().  Even worse, g_assert_not_reached() has the same
problem.

Then there is the runtime switch g_test_set_nonfatal_assertions() which
affects the REST of the g_assert_*() family (such as g_assert_cmpint(),
g_assert_true(), g_assert_null()) - but NOT g_assert() proper.  And I
recall Markus has posted in the past about complaining that
g_assert_cmpint() should not be used outside of tests/.
Eric Blake Aug. 18, 2017, 10:03 p.m. UTC | #5
On 08/18/2017 04:58 PM, Eric Blake wrote:
>> NDEBUG doesn't affect g_assert() (only assert(), but that wasn't in use
>> here) - I have to double-check glib documentation to see whether
>> g_assert() can be crippled in a manner similar to how I know assert()
>> can be crippled.  Ideally, we have a form that always performs side
>> effects exactly once, whether or not abort-on-error is enabled (assert()
>> does not have that, but I don't know whether glib does).
> 
> Per https://developer.gnome.org/glib/stable/glib-Testing.html#g-assert,
> G_DISABLE_ASSERT has the same compile-time effect on g_assert() as
> NDEBUG on assert().  Even worse, g_assert_not_reached() has the same
> problem.

Oh, and I failed to mention:

g_assert() has the same problem as assert() - when disabled at
compile-time, 'expr' is not evaluated.  If you want legible code (by
including side-effects within your macro that has optional
abort-on-error behavior), then you need some OTHER macro that always
performs the evaluation.  But if you create such a macro, don't use
'assert' in its name.  And I still fail to see why anyone would actually
want to disable abort-on-error behavior - once an assertion has gone
wrong, continuing execution is liable to hit follow-on problems that are
much harder to diagnose than it would have been just quitting at the
assertion failure.
diff mbox

Patch

diff --git a/qtest.c b/qtest.c
index 88a09e9afc..cbbfb71114 100644
--- a/qtest.c
+++ b/qtest.c
@@ -332,10 +332,13 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
                strcmp(words[0], "outl") == 0) {
         unsigned long addr;
         unsigned long value;
+        int ret;

         g_assert(words[1] && words[2]);
-        g_assert(qemu_strtoul(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtoul(words[2], NULL, 0, &value) == 0);
+        ret = qemu_strtoul(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);
+        ret = qemu_strtoul(words[2], NULL, 0, &value);
+        g_assert(ret == 0);
         g_assert(addr <= 0xffff);

         if (words[0][3] == 'b') {
@@ -352,9 +355,11 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
         strcmp(words[0], "inl") == 0) {
         unsigned long addr;
         uint32_t value = -1U;
+        int ret;

         g_assert(words[1]);
-        g_assert(qemu_strtoul(words[1], NULL, 0, &addr) == 0);
+        ret = qemu_strtoul(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);
         g_assert(addr <= 0xffff);

         if (words[0][2] == 'b') {
@@ -372,10 +377,13 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
                strcmp(words[0], "writeq") == 0) {
         uint64_t addr;
         uint64_t value;
+        int ret;

         g_assert(words[1] && words[2]);
-        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtou64(words[2], NULL, 0, &value) == 0);
+        ret = qemu_strtou64(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);
+        ret = qemu_strtou64(words[2], NULL, 0, &value);
+        g_assert(ret == 0);

         if (words[0][5] == 'b') {
             uint8_t data = value;
@@ -401,9 +409,11 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
                strcmp(words[0], "readq") == 0) {
         uint64_t addr;
         uint64_t value = UINT64_C(-1);
+        int ret;

         g_assert(words[1]);
-        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
+        ret = qemu_strtou64(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);

         if (words[0][4] == 'b') {
             uint8_t data;
@@ -427,10 +437,13 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
         uint64_t addr, len, i;
         uint8_t *data;
         char *enc;
+        int ret;

         g_assert(words[1] && words[2]);
-        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
+        ret = qemu_strtou64(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);
+        ret = qemu_strtou64(words[2], NULL, 0, &len);
+        g_assert(ret == 0);
         /* We'd send garbage to libqtest if len is 0 */
         g_assert(len);

@@ -451,10 +464,13 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
         uint64_t addr, len;
         uint8_t *data;
         gchar *b64_data;
+        int ret;

         g_assert(words[1] && words[2]);
-        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
+        ret = qemu_strtou64(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);
+        ret = qemu_strtou64(words[2], NULL, 0, &len);
+        g_assert(ret == 0);

         data = g_malloc(len);
         cpu_physical_memory_read(addr, data, len);
@@ -468,10 +484,13 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
         uint64_t addr, len, i;
         uint8_t *data;
         size_t data_len;
+        int ret;

         g_assert(words[1] && words[2] && words[3]);
-        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
+        ret = qemu_strtou64(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);
+        ret = qemu_strtou64(words[2], NULL, 0, &len);
+        g_assert(ret == 0);

         data_len = strlen(words[3]);
         if (data_len < 3) {
@@ -497,11 +516,15 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
         uint64_t addr, len;
         uint8_t *data;
         unsigned long pattern;
+        int ret;

         g_assert(words[1] && words[2] && words[3]);
-        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
-        g_assert(qemu_strtoul(words[3], NULL, 0, &pattern) == 0);
+        ret = qemu_strtou64(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);
+        ret = qemu_strtou64(words[2], NULL, 0, &len);
+        g_assert(ret == 0);
+        ret = qemu_strtoul(words[3], NULL, 0, &pattern);
+        g_assert(ret == 0);

         if (len) {
             data = g_malloc(len);
@@ -517,10 +540,13 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
         uint8_t *data;
         size_t data_len;
         gsize out_len;
+        int ret;

         g_assert(words[1] && words[2] && words[3]);
-        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
+        ret = qemu_strtou64(words[1], NULL, 0, &addr);
+        g_assert(ret == 0);
+        ret = qemu_strtou64(words[2], NULL, 0, &len);
+        g_assert(ret == 0);

         data_len = strlen(words[3]);
         if (data_len < 3) {
@@ -551,11 +577,16 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
     } else if (strcmp(words[0], "rtas") == 0) {
         uint64_t res, args, ret;
         unsigned long nargs, nret;
+        int rc;

-        g_assert(qemu_strtoul(words[2], NULL, 0, &nargs) == 0);
-        g_assert(qemu_strtou64(words[3], NULL, 0, &args) == 0);
-        g_assert(qemu_strtoul(words[4], NULL, 0, &nret) == 0);
-        g_assert(qemu_strtou64(words[5], NULL, 0, &ret) == 0);
+        rc = qemu_strtoul(words[2], NULL, 0, &nargs);
+        g_assert(rc == 0);
+        rc = qemu_strtou64(words[3], NULL, 0, &args);
+        g_assert(rc == 0);
+        rc = qemu_strtoul(words[4], NULL, 0, &nret);
+        g_assert(rc == 0);
+        rc = qemu_strtou64(words[5], NULL, 0, &ret);
+        g_assert(rc == 0);
         res = qtest_rtas_call(words[1], nargs, args, nret, ret);

         qtest_send_prefix(chr);
@@ -565,7 +596,8 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
         int64_t ns;

         if (words[1]) {
-            g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
+            int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
+            g_assert(ret == 0);
         } else {
             ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
         }
@@ -575,9 +607,11 @@  static void qtest_process_command(CharBackend *chr, gchar **words)
                     (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
     } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
         int64_t ns;
+        int ret;

         g_assert(words[1]);
-        g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
+        ret = qemu_strtoi64(words[1], NULL, 0, &ns);
+        g_assert(ret == 0);
         qtest_clock_warp(ns);
         qtest_send_prefix(chr);
         qtest_sendf(chr, "OK %"PRIi64"\n",