From nobody Sat Apr 27 16:01:47 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 1507130896703736.8201900514222; Wed, 4 Oct 2017 08:28:16 -0700 (PDT) Received: from localhost ([::1]:35661 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlaV-0005lL-Qd for importer@patchew.org; Wed, 04 Oct 2017 11:27:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60539) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlYn-0004dv-VT for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dzlYm-0000xX-W0 for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51010) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dzlYk-0000tC-7W; Wed, 04 Oct 2017 11:26:06 -0400 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 476C780491; Wed, 4 Oct 2017 15:26:05 +0000 (UTC) Received: from localhost (unknown [10.40.205.149]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 80F7C5D9C0; Wed, 4 Oct 2017 15:26:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 476C780491 Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=mreitz@redhat.com From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 4 Oct 2017 17:25:48 +0200 Message-Id: <20171004152553.30263-2-mreitz@redhat.com> In-Reply-To: <20171004152553.30263-1-mreitz@redhat.com> References: <20171004152553.30263-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.28]); Wed, 04 Oct 2017 15:26:05 +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 v6 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_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: 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 Apr 27 16:01:47 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 1507130923692769.1066180035015; Wed, 4 Oct 2017 08:28:43 -0700 (PDT) Received: from localhost ([::1]:35664 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlaw-0006Be-Uq for importer@patchew.org; Wed, 04 Oct 2017 11:28:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60742) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlZ6-0004sA-Lo for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dzlZ5-0001VH-GN for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56776) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dzlYx-0001HD-80; Wed, 04 Oct 2017 11:26:19 -0400 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 5F0B3780DE; Wed, 4 Oct 2017 15:26:18 +0000 (UTC) Received: from localhost (unknown [10.40.205.149]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 92626619C8; Wed, 4 Oct 2017 15:26:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 5F0B3780DE Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=mreitz@redhat.com From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 4 Oct 2017 17:25:49 +0200 Message-Id: <20171004152553.30263-3-mreitz@redhat.com> In-Reply-To: <20171004152553.30263-1-mreitz@redhat.com> References: <20171004152553.30263-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.27]); Wed, 04 Oct 2017 15:26:18 +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 v6 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: Alberto Garcia Reviewed-by: Eric Blake --- 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 Apr 27 16:01:47 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1507131028200594.4445354776939; Wed, 4 Oct 2017 08:30:28 -0700 (PDT) Received: from localhost ([::1]:35673 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlch-0007hT-3N for importer@patchew.org; Wed, 04 Oct 2017 11:30:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60736) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlZ6-0004rn-55 for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dzlZ4-0001TA-AZ for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:19244) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dzlYz-0001NU-UJ; Wed, 04 Oct 2017 11:26:22 -0400 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 08FD08B11B; Wed, 4 Oct 2017 15:26:21 +0000 (UTC) Received: from localhost (unknown [10.40.205.149]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 57580619CE; Wed, 4 Oct 2017 15:26:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 08FD08B11B Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=mreitz@redhat.com From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 4 Oct 2017 17:25:50 +0200 Message-Id: <20171004152553.30263-4-mreitz@redhat.com> In-Reply-To: <20171004152553.30263-1-mreitz@redhat.com> References: <20171004152553.30263-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.28]); Wed, 04 Oct 2017 15:26:21 +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 v6 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_6 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 Apr 27 16:01:47 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 1507130920768881.1562767407141; Wed, 4 Oct 2017 08:28:40 -0700 (PDT) Received: from localhost ([::1]:35663 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlat-00067p-Qs for importer@patchew.org; Wed, 04 Oct 2017 11:28:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60750) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlZ7-0004sl-60 for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dzlZ5-0001Vm-U8 for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57314) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dzlZ3-0001Rk-E6; Wed, 04 Oct 2017 11:26:25 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 80D5A780DC; Wed, 4 Oct 2017 15:26:24 +0000 (UTC) Received: from localhost (unknown [10.40.205.149]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0C021679C3; Wed, 4 Oct 2017 15:26:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 80D5A780DC Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=mreitz@redhat.com From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 4 Oct 2017 17:25:51 +0200 Message-Id: <20171004152553.30263-5-mreitz@redhat.com> In-Reply-To: <20171004152553.30263-1-mreitz@redhat.com> References: <20171004152553.30263-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 04 Oct 2017 15:26:24 +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 v6 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_6 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 ef5af81f66..68b0655dc5 100644 --- a/block.c +++ b/block.c @@ -3040,19 +3040,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 Apr 27 16:01:47 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1507131031686570.7201948328396; Wed, 4 Oct 2017 08:30:31 -0700 (PDT) Received: from localhost ([::1]:35674 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlcn-0007mW-T1 for importer@patchew.org; Wed, 04 Oct 2017 11:30:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60818) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlZD-0004wm-Sh for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dzlZC-0001ha-VN for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53248) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dzlZA-0001ey-Sk; Wed, 04 Oct 2017 11:26:33 -0400 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 F18378B11B; Wed, 4 Oct 2017 15:26:31 +0000 (UTC) Received: from localhost (unknown [10.40.205.149]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CAE0A6BF7C; Wed, 4 Oct 2017 15:26:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F18378B11B Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=mreitz@redhat.com From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 4 Oct 2017 17:25:52 +0200 Message-Id: <20171004152553.30263-6-mreitz@redhat.com> In-Reply-To: <20171004152553.30263-1-mreitz@redhat.com> References: <20171004152553.30263-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.28]); Wed, 04 Oct 2017 15:26:32 +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 v6 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_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: 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 Apr 27 16:01:47 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 1507131102290914.1733260089835; Wed, 4 Oct 2017 08:31:42 -0700 (PDT) Received: from localhost ([::1]:35685 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzle3-0000JO-Hl for importer@patchew.org; Wed, 04 Oct 2017 11:31:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60879) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dzlZP-00058b-KC for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dzlZN-0001qP-Hu for qemu-devel@nongnu.org; Wed, 04 Oct 2017 11:26:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40350) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dzlZH-0001lF-1e; Wed, 04 Oct 2017 11:26:39 -0400 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 10E305D68A; Wed, 4 Oct 2017 15:26:38 +0000 (UTC) Received: from localhost (unknown [10.40.205.149]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 31E20707A5; Wed, 4 Oct 2017 15:26:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 10E305D68A Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=mreitz@redhat.com From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 4 Oct 2017 17:25:53 +0200 Message-Id: <20171004152553.30263-7-mreitz@redhat.com> In-Reply-To: <20171004152553.30263-1-mreitz@redhat.com> References: <20171004152553.30263-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]); Wed, 04 Oct 2017 15:26:38 +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 v6 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 Reviewed-by: Markus Armbruster --- tests/Makefile.include | 4 +- tests/check-qobject.c | 325 +++++++++++++++++++++++++++++++++++++++++++++= ++++ tests/.gitignore | 1 + 3 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 tests/check-qobject.c diff --git a/tests/Makefile.include b/tests/Makefile.include index abc6707ef2..20622139f8 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) @@ -543,7 +544,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 \ @@ -577,6 +578,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..e6b1556c2b --- /dev/null +++ b/tests/check-qobject.c @@ -0,0 +1,325 @@ +/* + * 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). + */ +static void do_test_equality(bool expected, ...) +{ + va_list ap_count, ap_extract; + QObject **args; + int arg_count =3D 0; + int i, j; + + va_start(ap_count, expected); + 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, __VA_ARGS__, &test_equality_end_of_arguments) +#define check_unequal(...) \ + do_test_equality(false, __VA_ARGS__, &test_equality_end_of_arguments) + +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 cf6d99c91e..36fc912243 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -7,6 +7,7 @@ check-qnum check-qjson check-qlist check-qnull +check-qobject check-qstring check-qom-interface check-qom-proplist --=20 2.13.6