From nobody Sat May 4 22:46:45 2024 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=temperror (zoho.com: Error in retrieving data from DNS) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510682618235196.56436332908686; Tue, 14 Nov 2017 10:03:38 -0800 (PST) Received: from localhost ([::1]:32969 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfYP-0001Pc-IN for importer@patchew.org; Tue, 14 Nov 2017 13:03:21 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41946) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfWq-0000KP-EX for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eEfWn-0003AF-Uw for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:44 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49646) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eEfWg-00035V-Bp; Tue, 14 Nov 2017 13:01:34 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 71A0561D07; Tue, 14 Nov 2017 18:01:33 +0000 (UTC) Received: from localhost (unknown [10.40.205.72]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0395A953AA; Tue, 14 Nov 2017 18:01:32 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Tue, 14 Nov 2017 19:01:23 +0100 Message-Id: <20171114180128.17076-2-mreitz@redhat.com> In-Reply-To: <20171114180128.17076-1-mreitz@redhat.com> References: <20171114180128.17076-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 14 Nov 2017 18:01:33 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-2.11? v7 1/6] qapi/qnull: Add own header X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_6 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Max Reitz Reviewed-by: Eric Blake Reviewed-by: Alberto Garcia Reviewed-by: Markus Armbruster --- include/qapi/qmp/qdict.h | 1 + include/qapi/qmp/qnull.h | 30 ++++++++++++++++++++++++++++++ include/qapi/qmp/qobject.h | 12 ------------ include/qapi/qmp/types.h | 1 + qapi/qapi-clone-visitor.c | 1 + qapi/string-input-visitor.c | 1 + qobject/qnull.c | 2 +- tests/check-qnull.c | 2 +- 8 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 include/qapi/qmp/qnull.h diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h index 6588c7f0c8..7ea5120c4a 100644 --- a/include/qapi/qmp/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -15,6 +15,7 @@ =20 #include "qapi/qmp/qobject.h" #include "qapi/qmp/qlist.h" +#include "qapi/qmp/qnull.h" #include "qapi/qmp/qnum.h" #include "qemu/queue.h" =20 diff --git a/include/qapi/qmp/qnull.h b/include/qapi/qmp/qnull.h new file mode 100644 index 0000000000..d075549283 --- /dev/null +++ b/include/qapi/qmp/qnull.h @@ -0,0 +1,30 @@ +/* + * QNull + * + * Copyright (C) 2015 Red Hat, Inc. + * + * Authors: + * Markus Armbruster + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 + * or later. See the COPYING.LIB file in the top-level directory. + */ + +#ifndef QNULL_H +#define QNULL_H + +#include "qapi/qmp/qobject.h" + +struct QNull { + QObject base; +}; + +extern QNull qnull_; + +static inline QNull *qnull(void) +{ + QINCREF(&qnull_); + return &qnull_; +} + +#endif /* QNULL_H */ diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index eab29edd12..ef1d1a9237 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -93,16 +93,4 @@ static inline QType qobject_type(const QObject *obj) return obj->type; } =20 -struct QNull { - QObject base; -}; - -extern QNull qnull_; - -static inline QNull *qnull(void) -{ - QINCREF(&qnull_); - return &qnull_; -} - #endif /* QOBJECT_H */ diff --git a/include/qapi/qmp/types.h b/include/qapi/qmp/types.h index a4bc662bfb..749ac44dcb 100644 --- a/include/qapi/qmp/types.h +++ b/include/qapi/qmp/types.h @@ -19,5 +19,6 @@ #include "qapi/qmp/qstring.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" +#include "qapi/qmp/qnull.h" =20 #endif /* QAPI_QMP_TYPES_H */ diff --git a/qapi/qapi-clone-visitor.c b/qapi/qapi-clone-visitor.c index d8b62792bc..daab6819b4 100644 --- a/qapi/qapi-clone-visitor.c +++ b/qapi/qapi-clone-visitor.c @@ -12,6 +12,7 @@ #include "qapi/clone-visitor.h" #include "qapi/visitor-impl.h" #include "qapi/error.h" +#include "qapi/qmp/qnull.h" =20 struct QapiCloneVisitor { Visitor visitor; diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index 67a0a4a58b..b3fdd0827d 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -16,6 +16,7 @@ #include "qapi/string-input-visitor.h" #include "qapi/visitor-impl.h" #include "qapi/qmp/qerror.h" +#include "qapi/qmp/qnull.h" #include "qemu/option.h" #include "qemu/queue.h" #include "qemu/range.h" diff --git a/qobject/qnull.c b/qobject/qnull.c index 69a21d1059..bc9fd31626 100644 --- a/qobject/qnull.c +++ b/qobject/qnull.c @@ -12,7 +12,7 @@ =20 #include "qemu/osdep.h" #include "qemu-common.h" -#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qnull.h" =20 QNull qnull_ =3D { .base =3D { diff --git a/tests/check-qnull.c b/tests/check-qnull.c index 5c6eb0adc8..afa4400da1 100644 --- a/tests/check-qnull.c +++ b/tests/check-qnull.c @@ -8,7 +8,7 @@ */ #include "qemu/osdep.h" =20 -#include "qapi/qmp/qobject.h" +#include "qapi/qmp/qnull.h" #include "qemu-common.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qobject-output-visitor.h" --=20 2.13.6 From nobody Sat May 4 22:46:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510682627175854.9723584926812; Tue, 14 Nov 2017 10:03:47 -0800 (PST) Received: from localhost ([::1]:32972 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfYZ-0001Wh-P5 for importer@patchew.org; Tue, 14 Nov 2017 13:03:31 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41974) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfWs-0000Lt-IB for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eEfWq-0003C0-Jf for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:46 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46610) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eEfWj-00038A-Cz; Tue, 14 Nov 2017 13:01:37 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 78EBBC05689C; Tue, 14 Nov 2017 18:01:36 +0000 (UTC) Received: from localhost (unknown [10.40.205.72]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C2FE38A9D0; Tue, 14 Nov 2017 18:01:35 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Tue, 14 Nov 2017 19:01:24 +0100 Message-Id: <20171114180128.17076-3-mreitz@redhat.com> In-Reply-To: <20171114180128.17076-1-mreitz@redhat.com> References: <20171114180128.17076-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Tue, 14 Nov 2017 18:01:36 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-2.11? v7 2/6] qapi/qlist: Add qlist_append_null() macro X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Besides the macro itself, this patch also adds a corresponding Coccinelle rule. Signed-off-by: Max Reitz Reviewed-by: Eric Blake Reviewed-by: Alberto Garcia --- include/qapi/qmp/qlist.h | 3 +++ scripts/coccinelle/qobject.cocci | 3 +++ 2 files changed, 6 insertions(+) diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h index c4b5fdad9b..59d209bbae 100644 --- a/include/qapi/qmp/qlist.h +++ b/include/qapi/qmp/qlist.h @@ -15,6 +15,7 @@ =20 #include "qapi/qmp/qobject.h" #include "qapi/qmp/qnum.h" +#include "qapi/qmp/qnull.h" #include "qemu/queue.h" =20 typedef struct QListEntry { @@ -37,6 +38,8 @@ typedef struct QList { qlist_append(qlist, qbool_from_bool(value)) #define qlist_append_str(qlist, value) \ qlist_append(qlist, qstring_from_str(value)) +#define qlist_append_null(qlist) \ + qlist_append(qlist, qnull()) =20 #define QLIST_FOREACH_ENTRY(qlist, var) \ for ((var) =3D ((qlist)->head.tqh_first); \ diff --git a/scripts/coccinelle/qobject.cocci b/scripts/coccinelle/qobject.= cocci index 1120eb1a42..47bcafe9a9 100644 --- a/scripts/coccinelle/qobject.cocci +++ b/scripts/coccinelle/qobject.cocci @@ -41,4 +41,7 @@ expression Obj, E; | - qlist_append(Obj, qstring_from_str(E)); + qlist_append_str(Obj, E); +| +- qlist_append(Obj, qnull()); ++ qlist_append_null(Obj); ) --=20 2.13.6 From nobody Sat May 4 22:46:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510682760506262.5699229994842; Tue, 14 Nov 2017 10:06:00 -0800 (PST) Received: from localhost ([::1]:32989 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfak-0003FY-Ej for importer@patchew.org; Tue, 14 Nov 2017 13:05:46 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42061) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfX0-0000QE-1Q for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:02:00 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eEfWw-0003Eo-T6 for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:54 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52032) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eEfWm-00039R-Hc; Tue, 14 Nov 2017 13:01:40 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 91BE2C04AC53; Tue, 14 Nov 2017 18:01:39 +0000 (UTC) Received: from localhost (unknown [10.40.205.72]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 81821953A8; Tue, 14 Nov 2017 18:01:38 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Tue, 14 Nov 2017 19:01:25 +0100 Message-Id: <20171114180128.17076-4-mreitz@redhat.com> In-Reply-To: <20171114180128.17076-1-mreitz@redhat.com> References: <20171114180128.17076-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Tue, 14 Nov 2017 18:01:39 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-2.11? v7 3/6] qapi: Add qobject_is_equal() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This generic function (along with its implementations for different types) determines whether two QObjects are equal. Signed-off-by: Max Reitz Reviewed-by: Eric Blake Reviewed-by: Alberto Garcia Reviewed-by: Markus Armbruster --- include/qapi/qmp/qbool.h | 1 + include/qapi/qmp/qdict.h | 1 + include/qapi/qmp/qlist.h | 1 + include/qapi/qmp/qnull.h | 2 ++ include/qapi/qmp/qnum.h | 1 + include/qapi/qmp/qobject.h | 9 ++++++++ include/qapi/qmp/qstring.h | 1 + qobject/qbool.c | 8 +++++++ qobject/qdict.c | 29 +++++++++++++++++++++++++ qobject/qlist.c | 32 +++++++++++++++++++++++++++ qobject/qnull.c | 9 ++++++++ qobject/qnum.c | 54 ++++++++++++++++++++++++++++++++++++++++++= ++++ qobject/qobject.c | 29 +++++++++++++++++++++++++ qobject/qstring.c | 9 ++++++++ 14 files changed, 186 insertions(+) diff --git a/include/qapi/qmp/qbool.h b/include/qapi/qmp/qbool.h index a41111c309..f77ea86c4e 100644 --- a/include/qapi/qmp/qbool.h +++ b/include/qapi/qmp/qbool.h @@ -24,6 +24,7 @@ typedef struct QBool { QBool *qbool_from_bool(bool value); bool qbool_get_bool(const QBool *qb); QBool *qobject_to_qbool(const QObject *obj); +bool qbool_is_equal(const QObject *x, const QObject *y); void qbool_destroy_obj(QObject *obj); =20 #endif /* QBOOL_H */ diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h index 7ea5120c4a..fc218e7be6 100644 --- a/include/qapi/qmp/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -43,6 +43,7 @@ void qdict_del(QDict *qdict, const char *key); int qdict_haskey(const QDict *qdict, const char *key); QObject *qdict_get(const QDict *qdict, const char *key); QDict *qobject_to_qdict(const QObject *obj); +bool qdict_is_equal(const QObject *x, const QObject *y); void qdict_iter(const QDict *qdict, void (*iter)(const char *key, QObject *obj, void *opaque), void *opaque); diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h index 59d209bbae..ec3fcc1a4c 100644 --- a/include/qapi/qmp/qlist.h +++ b/include/qapi/qmp/qlist.h @@ -61,6 +61,7 @@ QObject *qlist_peek(QList *qlist); int qlist_empty(const QList *qlist); size_t qlist_size(const QList *qlist); QList *qobject_to_qlist(const QObject *obj); +bool qlist_is_equal(const QObject *x, const QObject *y); void qlist_destroy_obj(QObject *obj); =20 static inline const QListEntry *qlist_first(const QList *qlist) diff --git a/include/qapi/qmp/qnull.h b/include/qapi/qmp/qnull.h index d075549283..c992ee2ae1 100644 --- a/include/qapi/qmp/qnull.h +++ b/include/qapi/qmp/qnull.h @@ -27,4 +27,6 @@ static inline QNull *qnull(void) return &qnull_; } =20 +bool qnull_is_equal(const QObject *x, const QObject *y); + #endif /* QNULL_H */ diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h index d6b0791139..c3d86794bb 100644 --- a/include/qapi/qmp/qnum.h +++ b/include/qapi/qmp/qnum.h @@ -69,6 +69,7 @@ double qnum_get_double(QNum *qn); char *qnum_to_string(QNum *qn); =20 QNum *qobject_to_qnum(const QObject *obj); +bool qnum_is_equal(const QObject *x, const QObject *y); void qnum_destroy_obj(QObject *obj); =20 #endif /* QNUM_H */ diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index ef1d1a9237..38ac68845c 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -68,6 +68,15 @@ static inline void qobject_incref(QObject *obj) } =20 /** + * qobject_is_equal(): Return whether the two objects are equal. + * + * Any of the pointers may be NULL; return true if both are. Always + * return false if only one is (therefore a QNull object is not + * considered equal to a NULL pointer). + */ +bool qobject_is_equal(const QObject *x, const QObject *y); + +/** * qobject_destroy(): Free resources used by the object */ void qobject_destroy(QObject *obj); diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h index 10076b7c8c..65c05a9be5 100644 --- a/include/qapi/qmp/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -31,6 +31,7 @@ void qstring_append_int(QString *qstring, int64_t value); void qstring_append(QString *qstring, const char *str); void qstring_append_chr(QString *qstring, int c); QString *qobject_to_qstring(const QObject *obj); +bool qstring_is_equal(const QObject *x, const QObject *y); void qstring_destroy_obj(QObject *obj); =20 #endif /* QSTRING_H */ diff --git a/qobject/qbool.c b/qobject/qbool.c index 0606bbd2a3..ac825fc5a2 100644 --- a/qobject/qbool.c +++ b/qobject/qbool.c @@ -52,6 +52,14 @@ QBool *qobject_to_qbool(const QObject *obj) } =20 /** + * qbool_is_equal(): Test whether the two QBools are equal + */ +bool qbool_is_equal(const QObject *x, const QObject *y) +{ + return qobject_to_qbool(x)->value =3D=3D qobject_to_qbool(y)->value; +} + +/** * qbool_destroy_obj(): Free all memory allocated by a * QBool object */ diff --git a/qobject/qdict.c b/qobject/qdict.c index 576018e531..e8f15f1132 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -403,6 +403,35 @@ void qdict_del(QDict *qdict, const char *key) } =20 /** + * qdict_is_equal(): Test whether the two QDicts are equal + * + * Here, equality means whether they contain the same keys and whether + * the respective values are in turn equal (i.e. invoking + * qobject_is_equal() on them yields true). + */ +bool qdict_is_equal(const QObject *x, const QObject *y) +{ + const QDict *dict_x =3D qobject_to_qdict(x); + const QDict *dict_y =3D qobject_to_qdict(y); + const QDictEntry *e; + + if (qdict_size(dict_x) !=3D qdict_size(dict_y)) { + return false; + } + + for (e =3D qdict_first(dict_x); e; e =3D qdict_next(dict_x, e)) { + const QObject *obj_x =3D qdict_entry_value(e); + const QObject *obj_y =3D qdict_get(dict_y, qdict_entry_key(e)); + + if (!qobject_is_equal(obj_x, obj_y)) { + return false; + } + } + + return true; +} + +/** * qdict_destroy_obj(): Free all the memory allocated by a QDict */ void qdict_destroy_obj(QObject *obj) diff --git a/qobject/qlist.c b/qobject/qlist.c index 86b60cb88c..3ef57d31d1 100644 --- a/qobject/qlist.c +++ b/qobject/qlist.c @@ -140,6 +140,38 @@ QList *qobject_to_qlist(const QObject *obj) } =20 /** + * qlist_is_equal(): Test whether the two QLists are equal + * + * In order to be considered equal, the respective two objects at each + * index of the two lists have to compare equal (regarding + * qobject_is_equal()), and both lists have to have the same number of + * elements. + * That means both lists have to contain equal objects in equal order. + */ +bool qlist_is_equal(const QObject *x, const QObject *y) +{ + const QList *list_x =3D qobject_to_qlist(x); + const QList *list_y =3D qobject_to_qlist(y); + const QListEntry *entry_x, *entry_y; + + entry_x =3D qlist_first(list_x); + entry_y =3D qlist_first(list_y); + + while (entry_x && entry_y) { + if (!qobject_is_equal(qlist_entry_obj(entry_x), + qlist_entry_obj(entry_y))) + { + return false; + } + + entry_x =3D qlist_next(entry_x); + entry_y =3D qlist_next(entry_y); + } + + return !entry_x && !entry_y; +} + +/** * qlist_destroy_obj(): Free all the memory allocated by a QList */ void qlist_destroy_obj(QObject *obj) diff --git a/qobject/qnull.c b/qobject/qnull.c index bc9fd31626..f6f55f11ea 100644 --- a/qobject/qnull.c +++ b/qobject/qnull.c @@ -20,3 +20,12 @@ QNull qnull_ =3D { .refcnt =3D 1, }, }; + +/** + * qnull_is_equal(): Always return true because any two QNull objects + * are equal. + */ +bool qnull_is_equal(const QObject *x, const QObject *y) +{ + return true; +} diff --git a/qobject/qnum.c b/qobject/qnum.c index 476e81c93b..410686a611 100644 --- a/qobject/qnum.c +++ b/qobject/qnum.c @@ -213,6 +213,60 @@ QNum *qobject_to_qnum(const QObject *obj) } =20 /** + * qnum_is_equal(): Test whether the two QNums are equal + * + * Negative integers are never considered equal to unsigned integers, + * but positive integers in the range [0, INT64_MAX] are considered + * equal independently of whether the QNum's kind is i64 or u64. + * + * Doubles are never considered equal to integers. + */ +bool qnum_is_equal(const QObject *x, const QObject *y) +{ + QNum *num_x =3D qobject_to_qnum(x); + QNum *num_y =3D qobject_to_qnum(y); + + switch (num_x->kind) { + case QNUM_I64: + switch (num_y->kind) { + case QNUM_I64: + /* Comparison in native int64_t type */ + return num_x->u.i64 =3D=3D num_y->u.i64; + case QNUM_U64: + /* Implicit conversion of x to uin64_t, so we have to + * check its sign before */ + return num_x->u.i64 >=3D 0 && num_x->u.i64 =3D=3D num_y->u.u64; + case QNUM_DOUBLE: + return false; + } + abort(); + case QNUM_U64: + switch (num_y->kind) { + case QNUM_I64: + return qnum_is_equal(y, x); + case QNUM_U64: + /* Comparison in native uint64_t type */ + return num_x->u.u64 =3D=3D num_y->u.u64; + case QNUM_DOUBLE: + return false; + } + abort(); + case QNUM_DOUBLE: + switch (num_y->kind) { + case QNUM_I64: + case QNUM_U64: + return false; + case QNUM_DOUBLE: + /* Comparison in native double type */ + return num_x->u.dbl =3D=3D num_y->u.dbl; + } + abort(); + } + + abort(); +} + +/** * qnum_destroy_obj(): Free all memory allocated by a * QNum object */ diff --git a/qobject/qobject.c b/qobject/qobject.c index b0cafb66f1..b2a536041d 100644 --- a/qobject/qobject.c +++ b/qobject/qobject.c @@ -27,3 +27,32 @@ void qobject_destroy(QObject *obj) assert(QTYPE_QNULL < obj->type && obj->type < QTYPE__MAX); qdestroy[obj->type](obj); } + + +static bool (*qis_equal[QTYPE__MAX])(const QObject *, const QObject *) =3D= { + [QTYPE_NONE] =3D NULL, /* No such object exists */ + [QTYPE_QNULL] =3D qnull_is_equal, + [QTYPE_QNUM] =3D qnum_is_equal, + [QTYPE_QSTRING] =3D qstring_is_equal, + [QTYPE_QDICT] =3D qdict_is_equal, + [QTYPE_QLIST] =3D qlist_is_equal, + [QTYPE_QBOOL] =3D qbool_is_equal, +}; + +bool qobject_is_equal(const QObject *x, const QObject *y) +{ + /* We cannot test x =3D=3D y because an object does not need to be + * equal to itself (e.g. NaN floats are not). */ + + if (!x && !y) { + return true; + } + + if (!x || !y || x->type !=3D y->type) { + return false; + } + + assert(QTYPE_NONE < x->type && x->type < QTYPE__MAX); + + return qis_equal[x->type](x, y); +} diff --git a/qobject/qstring.c b/qobject/qstring.c index 5da7b5f37c..74182a1c02 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -129,6 +129,15 @@ const char *qstring_get_str(const QString *qstring) } =20 /** + * qstring_is_equal(): Test whether the two QStrings are equal + */ +bool qstring_is_equal(const QObject *x, const QObject *y) +{ + return !strcmp(qobject_to_qstring(x)->string, + qobject_to_qstring(y)->string); +} + +/** * qstring_destroy_obj(): Free all memory allocated by a QString * object */ --=20 2.13.6 From nobody Sat May 4 22:46:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510682763296530.7492356709226; Tue, 14 Nov 2017 10:06:03 -0800 (PST) Received: from localhost ([::1]:32990 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfas-0003Mi-Mb for importer@patchew.org; Tue, 14 Nov 2017 13:05:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42063) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfX0-0000QF-22 for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eEfWw-0003Et-TB for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:54 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49778) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eEfWp-0003AO-22; Tue, 14 Nov 2017 13:01:43 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2A08F61D1A; Tue, 14 Nov 2017 18:01:42 +0000 (UTC) Received: from localhost (unknown [10.40.205.72]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 888FB87100; Tue, 14 Nov 2017 18:01:41 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Tue, 14 Nov 2017 19:01:26 +0100 Message-Id: <20171114180128.17076-5-mreitz@redhat.com> In-Reply-To: <20171114180128.17076-1-mreitz@redhat.com> References: <20171114180128.17076-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 14 Nov 2017 18:01:42 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-2.11? v7 4/6] block: qobject_is_equal() in bdrv_reopen_prepare() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Currently, bdrv_reopen_prepare() assumes that all BDS options are strings. However, this is not the case if the BDS has been created through the json: pseudo-protocol or blockdev-add. Note that the user-invokable reopen command is an HMP command, so you can only specify strings there. Therefore, specifying a non-string option with the "same" value as it was when originally created will now return an error because the values are supposedly similar (and there is no way for the user to circumvent this but to just not specify the option again -- however, this is still strictly better than just crashing). Signed-off-by: Max Reitz Reviewed-by: Eric Blake --- block.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/block.c b/block.c index 684cb018da..28889a2690 100644 --- a/block.c +++ b/block.c @@ -3069,19 +3069,26 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_sta= te, BlockReopenQueue *queue, const QDictEntry *entry =3D qdict_first(reopen_state->options); =20 do { - QString *new_obj =3D qobject_to_qstring(entry->value); - const char *new =3D qstring_get_str(new_obj); + QObject *new =3D entry->value; + QObject *old =3D qdict_get(reopen_state->bs->options, entry->k= ey); + /* - * Caution: while qdict_get_try_str() is fine, getting - * non-string types would require more care. When - * bs->options come from -blockdev or blockdev_add, its - * members are typed according to the QAPI schema, but - * when they come from -drive, they're all QString. + * TODO: When using -drive to specify blockdev options, all va= lues + * will be strings; however, when using -blockdev, blockdev-ad= d or + * filenames using the json:{} pseudo-protocol, they will be + * correctly typed. + * In contrast, reopening options are (currently) always strin= gs + * (because you can only specify them through qemu-io; all oth= er + * callers do not specify any options). + * Therefore, when using anything other than -drive to create = a BDS, + * this cannot detect non-string options as unchanged, because + * qobject_is_equal() always returns false for objects of diff= erent + * type. In the future, this should be remedied by correctly = typing + * all options. For now, this is not too big of an issue beca= use + * the user can simply omit options which cannot be changed an= yway, + * so they will stay unchanged. */ - const char *old =3D qdict_get_try_str(reopen_state->bs->option= s, - entry->key); - - if (!old || strcmp(new, old)) { + if (!qobject_is_equal(new, old)) { error_setg(errp, "Cannot change the option '%s'", entry->k= ey); ret =3D -EINVAL; goto error; --=20 2.13.6 From nobody Sat May 4 22:46:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510682772633613.3331942726071; Tue, 14 Nov 2017 10:06:12 -0800 (PST) Received: from localhost ([::1]:32991 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfb2-0003UZ-IN for importer@patchew.org; Tue, 14 Nov 2017 13:06:04 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42077) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfX0-0000Qz-NV for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eEfWw-0003Ey-UA for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:54 -0500 Received: from mx1.redhat.com ([209.132.183.28]:47274) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eEfWr-0003CL-Mv; Tue, 14 Nov 2017 13:01:45 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C11F36A7CC; Tue, 14 Nov 2017 18:01:44 +0000 (UTC) Received: from localhost (unknown [10.40.205.72]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 31BDC87110; Tue, 14 Nov 2017 18:01:44 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Tue, 14 Nov 2017 19:01:27 +0100 Message-Id: <20171114180128.17076-6-mreitz@redhat.com> In-Reply-To: <20171114180128.17076-1-mreitz@redhat.com> References: <20171114180128.17076-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 14 Nov 2017 18:01:44 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-2.11? v7 5/6] iotests: Add test for non-string option reopening X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Max Reitz Reviewed-by: Kevin Wolf Reviewed-by: Eric Blake --- tests/qemu-iotests/133 | 9 +++++++++ tests/qemu-iotests/133.out | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/tests/qemu-iotests/133 b/tests/qemu-iotests/133 index 9d35a6a1ca..af6b3e1dd4 100755 --- a/tests/qemu-iotests/133 +++ b/tests/qemu-iotests/133 @@ -83,6 +83,15 @@ $QEMU_IO -c 'reopen -o driver=3Dqcow2' $TEST_IMG $QEMU_IO -c 'reopen -o file.driver=3Dfile' $TEST_IMG $QEMU_IO -c 'reopen -o backing.driver=3Dqcow2' $TEST_IMG =20 +echo +echo "=3D=3D=3D Check that reopening works with non-string options =3D=3D= =3D" +echo + +# Using the json: pseudo-protocol we can create non-string options +# (Invoke 'info' just so we get some output afterwards) +IMGOPTSSYNTAX=3Dfalse $QEMU_IO -f null-co -c 'reopen' -c 'info' \ + "json:{'driver': 'null-co', 'size': 65536}" + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/133.out b/tests/qemu-iotests/133.out index cc86b94880..f4a85aeb63 100644 --- a/tests/qemu-iotests/133.out +++ b/tests/qemu-iotests/133.out @@ -19,4 +19,9 @@ Cannot change the option 'driver' =20 =3D=3D=3D Check that unchanged driver is okay =3D=3D=3D =20 + +=3D=3D=3D Check that reopening works with non-string options =3D=3D=3D + +format name: null-co +format name: null-co *** done --=20 2.13.6 From nobody Sat May 4 22:46:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510682885243145.02815376905903; Tue, 14 Nov 2017 10:08:05 -0800 (PST) Received: from localhost ([::1]:32996 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfco-0004q8-BC for importer@patchew.org; Tue, 14 Nov 2017 13:07:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42120) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEfX3-0000cq-OL for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eEfX2-0003IW-0A for qemu-devel@nongnu.org; Tue, 14 Nov 2017 13:01:57 -0500 Received: from mx1.redhat.com ([209.132.183.28]:47328) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eEfWv-0003Dk-0x; Tue, 14 Nov 2017 13:01:49 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 24ACF6A7CA; Tue, 14 Nov 2017 18:01:48 +0000 (UTC) Received: from localhost (unknown [10.40.205.72]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2D51C8B16A; Tue, 14 Nov 2017 18:01:46 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Tue, 14 Nov 2017 19:01:28 +0100 Message-Id: <20171114180128.17076-7-mreitz@redhat.com> In-Reply-To: <20171114180128.17076-1-mreitz@redhat.com> References: <20171114180128.17076-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 14 Nov 2017 18:01:48 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-2.11? v7 6/6] tests: Add check-qobject for equality tests X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a new test file (check-qobject.c) for unit tests that concern QObjects as a whole. Its only purpose for now is to test the qobject_is_equal() function. Signed-off-by: Max Reitz Reviewed-by: Eric Blake --- tests/Makefile.include | 4 +- tests/check-qobject.c | 328 +++++++++++++++++++++++++++++++++++++++++++++= ++++ tests/.gitignore | 1 + 3 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 tests/check-qobject.c diff --git a/tests/Makefile.include b/tests/Makefile.include index 434a2ce868..c002352134 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -41,6 +41,7 @@ check-unit-y +=3D tests/check-qlist$(EXESUF) gcov-files-check-qlist-y =3D qobject/qlist.c check-unit-y +=3D tests/check-qnull$(EXESUF) gcov-files-check-qnull-y =3D qobject/qnull.c +check-unit-y +=3D tests/check-qobject$(EXESUF) check-unit-y +=3D tests/check-qjson$(EXESUF) gcov-files-check-qjson-y =3D qobject/qjson.c check-unit-y +=3D tests/check-qlit$(EXESUF) @@ -546,7 +547,7 @@ GENERATED_FILES +=3D tests/test-qapi-types.h tests/test= -qapi-visit.h \ tests/test-qmp-introspect.h =20 test-obj-y =3D tests/check-qnum.o tests/check-qstring.o tests/check-qdict.= o \ - tests/check-qlist.o tests/check-qnull.o \ + tests/check-qlist.o tests/check-qnull.o tests/check-qobject.o \ tests/check-qjson.o tests/check-qlit.o \ tests/test-coroutine.o tests/test-string-output-visitor.o \ tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \ @@ -580,6 +581,7 @@ tests/check-qstring$(EXESUF): tests/check-qstring.o $(t= est-util-obj-y) tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y) tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y) tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y) +tests/check-qobject$(EXESUF): tests/check-qobject.o $(test-util-obj-y) tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y) tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y) tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom= -obj-y) diff --git a/tests/check-qobject.c b/tests/check-qobject.c new file mode 100644 index 0000000000..03e9175113 --- /dev/null +++ b/tests/check-qobject.c @@ -0,0 +1,328 @@ +/* + * Generic QObject unit-tests. + * + * Copyright (C) 2017 Red Hat Inc. + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or l= ater. + * See the COPYING.LIB file in the top-level directory. + */ +#include "qemu/osdep.h" + +#include "qapi/qmp/types.h" +#include "qemu-common.h" + +#include + +/* Marks the end of the test_equality() argument list. + * We cannot use NULL there because that is a valid argument. */ +static QObject test_equality_end_of_arguments; + +/** + * Test whether all variadic QObject *arguments are equal (@expected + * is true) or whether they are all not equal (@expected is false). + * Every QObject is tested to be equal to itself (to test + * reflexivity), all tests are done both ways (to test symmetry), and + * transitivity is not assumed but checked (each object is compared to + * every other one). + * + * Note that qobject_is_equal() is not really an equivalence relation, + * so this function may not be used for all objects (reflexivity is + * not guaranteed, e.g. in the case of a QNum containing NaN). + * + * The @_ argument is required because a boolean may not be the last + * argument before a variadic argument list (C11 7.16.1.4 para. 4). + */ +static void do_test_equality(bool expected, int _, ...) +{ + va_list ap_count, ap_extract; + QObject **args; + int arg_count =3D 0; + int i, j; + + va_start(ap_count, _); + va_copy(ap_extract, ap_count); + while (va_arg(ap_count, QObject *) !=3D &test_equality_end_of_argument= s) { + arg_count++; + } + va_end(ap_count); + + args =3D g_new(QObject *, arg_count); + for (i =3D 0; i < arg_count; i++) { + args[i] =3D va_arg(ap_extract, QObject *); + } + va_end(ap_extract); + + for (i =3D 0; i < arg_count; i++) { + g_assert(qobject_is_equal(args[i], args[i]) =3D=3D true); + + for (j =3D i + 1; j < arg_count; j++) { + g_assert(qobject_is_equal(args[i], args[j]) =3D=3D expected); + } + } +} + +#define check_equal(...) \ + do_test_equality(true, 0, __VA_ARGS__, &test_equality_end_of_arguments) +#define check_unequal(...) \ + do_test_equality(false, 0, __VA_ARGS__, &test_equality_end_of_argument= s) + +static void do_free_all(int _, ...) +{ + va_list ap; + QObject *obj; + + va_start(ap, _); + while ((obj =3D va_arg(ap, QObject *)) !=3D NULL) { + qobject_decref(obj); + } + va_end(ap); +} + +#define free_all(...) \ + do_free_all(0, __VA_ARGS__, NULL) + +static void qobject_is_equal_null_test(void) +{ + check_unequal(qnull(), NULL); +} + +static void qobject_is_equal_num_test(void) +{ + QNum *u0, *i0, *d0, *dnan, *um42, *im42, *dm42; + + u0 =3D qnum_from_uint(0u); + i0 =3D qnum_from_int(0); + d0 =3D qnum_from_double(0.0); + dnan =3D qnum_from_double(NAN); + um42 =3D qnum_from_uint((uint64_t)-42); + im42 =3D qnum_from_int(-42); + dm42 =3D qnum_from_double(-42.0); + + /* Integers representing a mathematically equal number should + * compare equal */ + check_equal(u0, i0); + /* Doubles, however, are always unequal to integers */ + check_unequal(u0, d0); + check_unequal(i0, d0); + + /* Do not assume any object is equal to itself -- note however + * that NaN cannot occur in a JSON object anyway. */ + g_assert(qobject_is_equal(QOBJECT(dnan), QOBJECT(dnan)) =3D=3D false); + + /* No unsigned overflow */ + check_unequal(um42, im42); + check_unequal(um42, dm42); + check_unequal(im42, dm42); + + free_all(u0, i0, d0, dnan, um42, im42, dm42); +} + +static void qobject_is_equal_bool_test(void) +{ + QBool *btrue_0, *btrue_1, *bfalse_0, *bfalse_1; + + btrue_0 =3D qbool_from_bool(true); + btrue_1 =3D qbool_from_bool(true); + bfalse_0 =3D qbool_from_bool(false); + bfalse_1 =3D qbool_from_bool(false); + + check_equal(btrue_0, btrue_1); + check_equal(bfalse_0, bfalse_1); + check_unequal(btrue_0, bfalse_0); + + free_all(btrue_0, btrue_1, bfalse_0, bfalse_1); +} + +static void qobject_is_equal_string_test(void) +{ + QString *str_base, *str_whitespace_0, *str_whitespace_1, *str_whitespa= ce_2; + QString *str_whitespace_3, *str_case, *str_built; + + str_base =3D qstring_from_str("foo"); + str_whitespace_0 =3D qstring_from_str(" foo"); + str_whitespace_1 =3D qstring_from_str("foo "); + str_whitespace_2 =3D qstring_from_str("foo\b"); + str_whitespace_3 =3D qstring_from_str("fooo\b"); + str_case =3D qstring_from_str("Foo"); + + /* Should yield "foo" */ + str_built =3D qstring_from_substr("form", 0, 1); + qstring_append_chr(str_built, 'o'); + + check_unequal(str_base, str_whitespace_0, str_whitespace_1, + str_whitespace_2, str_whitespace_3, str_case); + + check_equal(str_base, str_built); + + free_all(str_base, str_whitespace_0, str_whitespace_1, str_whitespace_= 2, + str_whitespace_3, str_case, str_built); +} + +static void qobject_is_equal_list_test(void) +{ + QList *list_0, *list_1, *list_cloned; + QList *list_reordered, *list_longer, *list_shorter; + + list_0 =3D qlist_new(); + list_1 =3D qlist_new(); + list_reordered =3D qlist_new(); + list_longer =3D qlist_new(); + list_shorter =3D qlist_new(); + + qlist_append_int(list_0, 1); + qlist_append_int(list_0, 2); + qlist_append_int(list_0, 3); + + qlist_append_int(list_1, 1); + qlist_append_int(list_1, 2); + qlist_append_int(list_1, 3); + + qlist_append_int(list_reordered, 1); + qlist_append_int(list_reordered, 3); + qlist_append_int(list_reordered, 2); + + qlist_append_int(list_longer, 1); + qlist_append_int(list_longer, 2); + qlist_append_int(list_longer, 3); + qlist_append_null(list_longer); + + qlist_append_int(list_shorter, 1); + qlist_append_int(list_shorter, 2); + + list_cloned =3D qlist_copy(list_0); + + check_equal(list_0, list_1, list_cloned); + check_unequal(list_0, list_reordered, list_longer, list_shorter); + + /* With a NaN in it, the list should no longer compare equal to + * itself */ + qlist_append(list_0, qnum_from_double(NAN)); + g_assert(qobject_is_equal(QOBJECT(list_0), QOBJECT(list_0)) =3D=3D fal= se); + + free_all(list_0, list_1, list_cloned, list_reordered, list_longer, + list_shorter); +} + +static void qobject_is_equal_dict_test(void) +{ + Error *local_err =3D NULL; + QDict *dict_0, *dict_1, *dict_cloned; + QDict *dict_different_key, *dict_different_value, *dict_different_null= _key; + QDict *dict_longer, *dict_shorter, *dict_nested; + QDict *dict_crumpled; + + dict_0 =3D qdict_new(); + dict_1 =3D qdict_new(); + dict_different_key =3D qdict_new(); + dict_different_value =3D qdict_new(); + dict_different_null_key =3D qdict_new(); + dict_longer =3D qdict_new(); + dict_shorter =3D qdict_new(); + dict_nested =3D qdict_new(); + + qdict_put_int(dict_0, "f.o", 1); + qdict_put_int(dict_0, "bar", 2); + qdict_put_int(dict_0, "baz", 3); + qdict_put_null(dict_0, "null"); + + qdict_put_int(dict_1, "f.o", 1); + qdict_put_int(dict_1, "bar", 2); + qdict_put_int(dict_1, "baz", 3); + qdict_put_null(dict_1, "null"); + + qdict_put_int(dict_different_key, "F.o", 1); + qdict_put_int(dict_different_key, "bar", 2); + qdict_put_int(dict_different_key, "baz", 3); + qdict_put_null(dict_different_key, "null"); + + qdict_put_int(dict_different_value, "f.o", 42); + qdict_put_int(dict_different_value, "bar", 2); + qdict_put_int(dict_different_value, "baz", 3); + qdict_put_null(dict_different_value, "null"); + + qdict_put_int(dict_different_null_key, "f.o", 1); + qdict_put_int(dict_different_null_key, "bar", 2); + qdict_put_int(dict_different_null_key, "baz", 3); + qdict_put_null(dict_different_null_key, "none"); + + qdict_put_int(dict_longer, "f.o", 1); + qdict_put_int(dict_longer, "bar", 2); + qdict_put_int(dict_longer, "baz", 3); + qdict_put_int(dict_longer, "xyz", 4); + qdict_put_null(dict_longer, "null"); + + qdict_put_int(dict_shorter, "f.o", 1); + qdict_put_int(dict_shorter, "bar", 2); + qdict_put_int(dict_shorter, "baz", 3); + + qdict_put(dict_nested, "f", qdict_new()); + qdict_put_int(qdict_get_qdict(dict_nested, "f"), "o", 1); + qdict_put_int(dict_nested, "bar", 2); + qdict_put_int(dict_nested, "baz", 3); + qdict_put_null(dict_nested, "null"); + + dict_cloned =3D qdict_clone_shallow(dict_0); + + check_equal(dict_0, dict_1, dict_cloned); + check_unequal(dict_0, dict_different_key, dict_different_value, + dict_different_null_key, dict_longer, dict_shorter, + dict_nested); + + dict_crumpled =3D qobject_to_qdict(qdict_crumple(dict_1, &local_err)); + g_assert(!local_err); + check_equal(dict_crumpled, dict_nested); + + qdict_flatten(dict_nested); + check_equal(dict_0, dict_nested); + + /* Containing an NaN value will make this dict compare unequal to + * itself */ + qdict_put(dict_0, "NaN", qnum_from_double(NAN)); + g_assert(qobject_is_equal(QOBJECT(dict_0), QOBJECT(dict_0)) =3D=3D fal= se); + + free_all(dict_0, dict_1, dict_cloned, dict_different_key, + dict_different_value, dict_different_null_key, dict_longer, + dict_shorter, dict_nested, dict_crumpled); +} + +static void qobject_is_equal_conversion_test(void) +{ + QNum *u0, *i0, *d0; + QString *s0, *s_empty; + QBool *bfalse; + + u0 =3D qnum_from_uint(0u); + i0 =3D qnum_from_int(0); + d0 =3D qnum_from_double(0.0); + s0 =3D qstring_from_str("0"); + s_empty =3D qstring_new(); + bfalse =3D qbool_from_bool(false); + + /* No automatic type conversion */ + check_unequal(u0, s0, s_empty, bfalse, qnull(), NULL); + check_unequal(i0, s0, s_empty, bfalse, qnull(), NULL); + check_unequal(d0, s0, s_empty, bfalse, qnull(), NULL); + + free_all(u0, i0, d0, s0, s_empty, bfalse); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/public/qobject_is_equal_null", + qobject_is_equal_null_test); + g_test_add_func("/public/qobject_is_equal_num", qobject_is_equal_num_t= est); + g_test_add_func("/public/qobject_is_equal_bool", + qobject_is_equal_bool_test); + g_test_add_func("/public/qobject_is_equal_string", + qobject_is_equal_string_test); + g_test_add_func("/public/qobject_is_equal_list", + qobject_is_equal_list_test); + g_test_add_func("/public/qobject_is_equal_dict", + qobject_is_equal_dict_test); + g_test_add_func("/public/qobject_is_equal_conversion", + qobject_is_equal_conversion_test); + + return g_test_run(); +} diff --git a/tests/.gitignore b/tests/.gitignore index 53cb2efaee..74e55d7264 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -8,6 +8,7 @@ check-qjson check-qlist check-qlit check-qnull +check-qobject check-qstring check-qom-interface check-qom-proplist --=20 2.13.6