From nobody Fri May 3 03:11:43 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.zoho.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 1496250967946215.053418969243; Wed, 31 May 2017 10:16:07 -0700 (PDT) Received: from localhost ([::1]:33032 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG7E4-0007LF-FA for importer@patchew.org; Wed, 31 May 2017 13:16:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32863) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG77S-0002M5-6Y for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dG77P-0000dU-0Q for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55142) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dG77O-0000d2-Ok for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:10 -0400 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 97A058124B for ; Wed, 31 May 2017 17:09:09 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-98.ams2.redhat.com [10.36.116.98]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6499762923 for ; Wed, 31 May 2017 17:09:09 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D28C11138648; Wed, 31 May 2017 19:09:07 +0200 (CEST) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 97A058124B Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=armbru@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 97A058124B From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 31 May 2017 19:09:04 +0200 Message-Id: <1496250547-20701-2-git-send-email-armbru@redhat.com> In-Reply-To: <1496250547-20701-1-git-send-email-armbru@redhat.com> References: <1496250547-20701-1-git-send-email-armbru@redhat.com> MIME-Version: 1.0 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.25]); Wed, 31 May 2017 17:09:09 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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] [PULL 1/4] qobject-input-visitor: Reject non-finite numbers with keyval 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The QObject input visitor can produce only finite numbers when its input comes out of the JSON parser, because the the JSON parser implements RFC 7159, which provides no syntax for infinity and NaN. However, it can produce infinity and NaN when its input comes out of keyval_parse(), because we parse with strtod() then. The keyval variant should not be able to express things the JSON variant can't. Rejecting non-finite numbers there is the conservative fix. It's also minimally invasive. We could instead extend our JSON dialect to provide for infinity and NaN. Not today. Note that the JSON formatter can emit non-finite numbers (marked FIXME in commit 6e8e5cb). Signed-off-by: Markus Armbruster Message-Id: <1495471335-23707-2-git-send-email-armbru@redhat.com> Reviewed-by: Eric Blake Reviewed-by: Marc-Andr=C3=A9 Lureau --- qapi/qobject-input-visitor.c | 3 ++- tests/test-qobject-input-visitor.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index d0f0002..eac40f6 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -13,6 +13,7 @@ */ =20 #include "qemu/osdep.h" +#include #include "qapi/error.h" #include "qapi/qobject-input-visitor.h" #include "qapi/visitor-impl.h" @@ -568,7 +569,7 @@ static void qobject_input_type_number_keyval(Visitor *v= , const char *name, =20 errno =3D 0; *obj =3D strtod(str, &endp); - if (errno || endp =3D=3D str || *endp) { + if (errno || endp =3D=3D str || *endp || !isfinite(*obj)) { /* TODO report -ERANGE more nicely */ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "number"); diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index f965743..e2aabbe 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -278,11 +278,17 @@ static void test_visitor_in_number_str_keyval(TestInp= utVisitorData *data, { double res =3D 0, value =3D 3.14; Visitor *v; + Error *err =3D NULL; =20 v =3D visitor_input_test_init_full(data, true, "\"3.14\""); =20 visit_type_number(v, NULL, &res, &error_abort); g_assert_cmpfloat(res, =3D=3D, value); + + v =3D visitor_input_test_init_full(data, true, "\"inf\""); + + visit_type_number(v, NULL, &res, &err); + error_free_or_abort(&err); } =20 static void test_visitor_in_number_str_fail(TestInputVisitorData *data, --=20 2.7.4 From nobody Fri May 3 03:11:43 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.zoho.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 1496250815320135.9129737016516; Wed, 31 May 2017 10:13:35 -0700 (PDT) Received: from localhost ([::1]:33014 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG7Be-0005Ul-0g for importer@patchew.org; Wed, 31 May 2017 13:13:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32862) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG77S-0002M4-6S for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dG77O-0000dI-V4 for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49154) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dG77O-0000d0-Od for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:10 -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 9C632C04B316 for ; Wed, 31 May 2017 17:09:09 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-98.ams2.redhat.com [10.36.116.98]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 67E5794D94 for ; Wed, 31 May 2017 17:09:09 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D4E29113864A; Wed, 31 May 2017 19:09:07 +0200 (CEST) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 9C632C04B316 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=armbru@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 9C632C04B316 From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 31 May 2017 19:09:05 +0200 Message-Id: <1496250547-20701-3-git-send-email-armbru@redhat.com> In-Reply-To: <1496250547-20701-1-git-send-email-armbru@redhat.com> References: <1496250547-20701-1-git-send-email-armbru@redhat.com> MIME-Version: 1.0 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.31]); Wed, 31 May 2017 17:09:09 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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] [PULL 2/4] qapi: Document visit_type_any() issues with keyval input 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" It's already documented in keyval.c (commit 0ee9ae7), but visitor.h can use a note, too. Signed-off-by: Markus Armbruster Message-Id: <1495471335-23707-3-git-send-email-armbru@redhat.com> Reviewed-by: Eric Blake Reviewed-by: Marc-Andr=C3=A9 Lureau --- include/qapi/visitor.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index b0e233d..4721c39 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -607,6 +607,10 @@ void visit_type_number(Visitor *v, const char *name, d= ouble *obj, * @obj must be non-NULL. Input visitors set *@obj to the value; * other visitors will leave *@obj unchanged. *@obj must be non-NULL * for output visitors. + * + * Note that some kinds of input can't express arbitrary QObject. + * E.g. the visitor returned by qobject_input_visitor_new_keyval() + * can't create numbers or booleans, only strings. */ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **e= rrp); =20 --=20 2.7.4 From nobody Fri May 3 03:11:43 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.zoho.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 1496251053142123.28262109083198; Wed, 31 May 2017 10:17:33 -0700 (PDT) Received: from localhost ([::1]:33039 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG7FT-00089Z-Nz for importer@patchew.org; Wed, 31 May 2017 13:17:31 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32859) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG77S-0002M1-63 for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dG77P-0000db-42 for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55158) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dG77O-0000d9-Rk for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:11 -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 F339181250 for ; Wed, 31 May 2017 17:09:09 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-98.ams2.redhat.com [10.36.116.98]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6AA9E7C8A1 for ; Wed, 31 May 2017 17:09:09 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id D7BAF113864C; Wed, 31 May 2017 19:09:07 +0200 (CEST) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F339181250 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=armbru@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com F339181250 From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 31 May 2017 19:09:06 +0200 Message-Id: <1496250547-20701-4-git-send-email-armbru@redhat.com> In-Reply-To: <1496250547-20701-1-git-send-email-armbru@redhat.com> References: <1496250547-20701-1-git-send-email-armbru@redhat.com> MIME-Version: 1.0 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.25]); Wed, 31 May 2017 17:09:10 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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] [PULL 3/4] tests/qapi-schema: Avoid 'str' in alternate test cases 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The next commit is going to make alternate members of type 'str' conflict with other scalar types. Would break a few test cases that don't actually require 'str'. Flip them from 'str' to 'bool' or 'EnumOne'. Signed-off-by: Markus Armbruster Message-Id: <1495471335-23707-4-git-send-email-armbru@redhat.com> Reviewed-by: Eric Blake Reviewed-by: Marc-Andr=C3=A9 Lureau --- tests/qapi-schema/alternate-clash.json | 2 +- tests/qapi-schema/alternate-nested.json | 2 +- tests/qapi-schema/args-alternate.json | 2 +- tests/qapi-schema/doc-bad-alternate-member.json | 2 +- tests/qapi-schema/qapi-schema-test.json | 9 ++-- tests/qapi-schema/qapi-schema-test.out | 30 +++++++------ tests/qapi-schema/returns-alternate.json | 2 +- tests/test-clone-visitor.c | 23 +++++----- tests/test-qobject-input-visitor.c | 56 ++++++++++++---------= ---- tests/test-qobject-output-visitor.c | 4 +- 10 files changed, 68 insertions(+), 64 deletions(-) diff --git a/tests/qapi-schema/alternate-clash.json b/tests/qapi-schema/alt= ernate-clash.json index 6d73bc5..9a59b88 100644 --- a/tests/qapi-schema/alternate-clash.json +++ b/tests/qapi-schema/alternate-clash.json @@ -5,4 +5,4 @@ # the implicit Alt1Kind enum, we would still have a collision with the # resulting C union trying to have two members named 'a_b'. { 'alternate': 'Alt1', - 'data': { 'a-b': 'str', 'a_b': 'int' } } + 'data': { 'a-b': 'bool', 'a_b': 'int' } } diff --git a/tests/qapi-schema/alternate-nested.json b/tests/qapi-schema/al= ternate-nested.json index 8e22186..f2b9632 100644 --- a/tests/qapi-schema/alternate-nested.json +++ b/tests/qapi-schema/alternate-nested.json @@ -1,5 +1,5 @@ # we reject a nested alternate branch { 'alternate': 'Alt1', - 'data': { 'name': 'str', 'value': 'int' } } + 'data': { 'name': 'bool', 'value': 'int' } } { 'alternate': 'Alt2', 'data': { 'nested': 'Alt1', 'b': 'bool' } } diff --git a/tests/qapi-schema/args-alternate.json b/tests/qapi-schema/args= -alternate.json index 69e94d4..824d69c 100644 --- a/tests/qapi-schema/args-alternate.json +++ b/tests/qapi-schema/args-alternate.json @@ -1,3 +1,3 @@ # we do not allow alternate arguments -{ 'alternate': 'Alt', 'data': { 'case1': 'int', 'case2': 'str' } } +{ 'alternate': 'Alt', 'data': { 'case1': 'int', 'case2': 'bool' } } { 'command': 'oops', 'data': 'Alt' } diff --git a/tests/qapi-schema/doc-bad-alternate-member.json b/tests/qapi-s= chema/doc-bad-alternate-member.json index 738635c..fa4143d 100644 --- a/tests/qapi-schema/doc-bad-alternate-member.json +++ b/tests/qapi-schema/doc-bad-alternate-member.json @@ -6,4 +6,4 @@ # @bb: b ## { 'alternate': 'AorB', - 'data': { 'a': 'str', 'b': 'int' } } + 'data': { 'a': 'bool', 'b': 'int' } } diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qa= pi-schema-test.json index 842ea3c..303f2b2 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -93,16 +93,17 @@ { 'struct': 'WrapAlternate', 'data': { 'alt': 'UserDefAlternate' } } { 'alternate': 'UserDefAlternate', - 'data': { 'udfu': 'UserDefFlatUnion', 's': 'str', 'i': 'int' } } + 'data': { 'udfu': 'UserDefFlatUnion', 'e': 'EnumOne', 'i': 'int' } } =20 { 'struct': 'UserDefC', 'data': { 'string1': 'str', 'string2': 'str' } } =20 # for testing use of 'number' within alternates -{ 'alternate': 'AltStrBool', 'data': { 's': 'str', 'b': 'bool' } } -{ 'alternate': 'AltStrNum', 'data': { 's': 'str', 'n': 'number' } } +{ 'alternate': 'AltEnumBool', 'data': { 'e': 'EnumOne', 'b': 'bool' } } +{ 'alternate': 'AltEnumNum', 'data': { 'e': 'EnumOne', 'n': 'number' } } { 'alternate': 'AltNumStr', 'data': { 'n': 'number', 's': 'str' } } -{ 'alternate': 'AltStrInt', 'data': { 's': 'str', 'i': 'int' } } +{ 'alternate': 'AltNumEnum', 'data': { 'n': 'number', 'e': 'EnumOne' } } +{ 'alternate': 'AltEnumInt', 'data': { 'e': 'EnumOne', 'i': 'int' } } { 'alternate': 'AltIntNum', 'data': { 'i': 'int', 'n': 'number' } } { 'alternate': 'AltNumInt', 'data': { 'n': 'number', 'i': 'int' } } =20 diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qap= i-schema-test.out index 9d99c4e..3081091 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -1,7 +1,23 @@ +alternate AltEnumBool + tag type + case e: EnumOne + case b: bool +alternate AltEnumInt + tag type + case e: EnumOne + case i: int +alternate AltEnumNum + tag type + case e: EnumOne + case n: number alternate AltIntNum tag type case i: int case n: number +alternate AltNumEnum + tag type + case n: number + case e: EnumOne alternate AltNumInt tag type case n: number @@ -10,18 +26,6 @@ alternate AltNumStr tag type case n: number case s: str -alternate AltStrBool - tag type - case s: str - case b: bool -alternate AltStrInt - tag type - case s: str - case i: int -alternate AltStrNum - tag type - case s: str - case n: number event EVENT_A None boxed=3DFalse event EVENT_B None @@ -66,7 +70,7 @@ object UserDefA alternate UserDefAlternate tag type case udfu: UserDefFlatUnion - case s: str + case e: EnumOne case i: int object UserDefB member intb: int optional=3DFalse diff --git a/tests/qapi-schema/returns-alternate.json b/tests/qapi-schema/r= eturns-alternate.json index 972390c..f873718 100644 --- a/tests/qapi-schema/returns-alternate.json +++ b/tests/qapi-schema/returns-alternate.json @@ -1,3 +1,3 @@ # we reject returns if it is an alternate type -{ 'alternate': 'Alt', 'data': { 'a': 'int', 'b': 'str' } } +{ 'alternate': 'Alt', 'data': { 'a': 'int', 'b': 'bool' } } { 'command': 'oops', 'returns': 'Alt' } diff --git a/tests/test-clone-visitor.c b/tests/test-clone-visitor.c index df0c045..9698216 100644 --- a/tests/test-clone-visitor.c +++ b/tests/test-clone-visitor.c @@ -42,29 +42,28 @@ static void test_clone_struct(void) =20 static void test_clone_alternate(void) { - AltStrBool *b_src, *s_src, *b_dst, *s_dst; + AltEnumBool *b_src, *s_src, *b_dst, *s_dst; =20 - b_src =3D g_new0(AltStrBool, 1); + b_src =3D g_new0(AltEnumBool, 1); b_src->type =3D QTYPE_QBOOL; b_src->u.b =3D true; - s_src =3D g_new0(AltStrBool, 1); + s_src =3D g_new0(AltEnumBool, 1); s_src->type =3D QTYPE_QSTRING; - s_src->u.s =3D g_strdup("World"); + s_src->u.e =3D ENUM_ONE_VALUE1; =20 - b_dst =3D QAPI_CLONE(AltStrBool, b_src); + b_dst =3D QAPI_CLONE(AltEnumBool, b_src); g_assert(b_dst); g_assert_cmpint(b_dst->type, =3D=3D, b_src->type); g_assert_cmpint(b_dst->u.b, =3D=3D, b_src->u.b); - s_dst =3D QAPI_CLONE(AltStrBool, s_src); + s_dst =3D QAPI_CLONE(AltEnumBool, s_src); g_assert(s_dst); g_assert_cmpint(s_dst->type, =3D=3D, s_src->type); - g_assert_cmpstr(s_dst->u.s, =3D=3D, s_src->u.s); - g_assert(s_dst->u.s !=3D s_src->u.s); + g_assert_cmpint(s_dst->u.e, =3D=3D, s_src->u.e); =20 - qapi_free_AltStrBool(b_src); - qapi_free_AltStrBool(s_src); - qapi_free_AltStrBool(b_dst); - qapi_free_AltStrBool(s_dst); + qapi_free_AltEnumBool(b_src); + qapi_free_AltEnumBool(s_src); + qapi_free_AltEnumBool(b_dst); + qapi_free_AltEnumBool(s_dst); } =20 static void test_clone_native_list(void) diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index e2aabbe..6b997a1 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -537,10 +537,10 @@ static void test_visitor_in_alternate(TestInputVisito= rData *data, g_assert_cmpint(tmp->u.i, =3D=3D, 42); qapi_free_UserDefAlternate(tmp); =20 - v =3D visitor_input_test_init(data, "'string'"); + v =3D visitor_input_test_init(data, "'value1'"); visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort); g_assert_cmpint(tmp->type, =3D=3D, QTYPE_QSTRING); - g_assert_cmpstr(tmp->u.s, =3D=3D, "string"); + g_assert_cmpint(tmp->u.e, =3D=3D, ENUM_ONE_VALUE1); qapi_free_UserDefAlternate(tmp); =20 v =3D visitor_input_test_init(data, "{'integer':1, 'string':'str', " @@ -565,10 +565,10 @@ static void test_visitor_in_alternate(TestInputVisito= rData *data, g_assert_cmpint(wrap->alt->u.i, =3D=3D, 42); qapi_free_WrapAlternate(wrap); =20 - v =3D visitor_input_test_init(data, "{ 'alt': 'string' }"); + v =3D visitor_input_test_init(data, "{ 'alt': 'value1' }"); visit_type_WrapAlternate(v, NULL, &wrap, &error_abort); g_assert_cmpint(wrap->alt->type, =3D=3D, QTYPE_QSTRING); - g_assert_cmpstr(wrap->alt->u.s, =3D=3D, "string"); + g_assert_cmpint(wrap->alt->u.e, =3D=3D, ENUM_ONE_VALUE1); qapi_free_WrapAlternate(wrap); =20 v =3D visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'= str', " @@ -588,37 +588,37 @@ static void test_visitor_in_alternate_number(TestInpu= tVisitorData *data, { Visitor *v; Error *err =3D NULL; - AltStrBool *asb; - AltStrNum *asn; - AltNumStr *ans; - AltStrInt *asi; + AltEnumBool *aeb; + AltEnumNum *aen; + AltNumEnum *ans; + AltEnumInt *asi; AltIntNum *ain; AltNumInt *ani; =20 /* Parsing an int */ =20 v =3D visitor_input_test_init(data, "42"); - visit_type_AltStrBool(v, NULL, &asb, &err); + visit_type_AltEnumBool(v, NULL, &aeb, &err); error_free_or_abort(&err); - qapi_free_AltStrBool(asb); + qapi_free_AltEnumBool(aeb); =20 v =3D visitor_input_test_init(data, "42"); - visit_type_AltStrNum(v, NULL, &asn, &error_abort); - g_assert_cmpint(asn->type, =3D=3D, QTYPE_QFLOAT); - g_assert_cmpfloat(asn->u.n, =3D=3D, 42); - qapi_free_AltStrNum(asn); + visit_type_AltEnumNum(v, NULL, &aen, &error_abort); + g_assert_cmpint(aen->type, =3D=3D, QTYPE_QFLOAT); + g_assert_cmpfloat(aen->u.n, =3D=3D, 42); + qapi_free_AltEnumNum(aen); =20 v =3D visitor_input_test_init(data, "42"); - visit_type_AltNumStr(v, NULL, &ans, &error_abort); + visit_type_AltNumEnum(v, NULL, &ans, &error_abort); g_assert_cmpint(ans->type, =3D=3D, QTYPE_QFLOAT); g_assert_cmpfloat(ans->u.n, =3D=3D, 42); - qapi_free_AltNumStr(ans); + qapi_free_AltNumEnum(ans); =20 v =3D visitor_input_test_init(data, "42"); - visit_type_AltStrInt(v, NULL, &asi, &error_abort); + visit_type_AltEnumInt(v, NULL, &asi, &error_abort); g_assert_cmpint(asi->type, =3D=3D, QTYPE_QINT); g_assert_cmpint(asi->u.i, =3D=3D, 42); - qapi_free_AltStrInt(asi); + qapi_free_AltEnumInt(asi); =20 v =3D visitor_input_test_init(data, "42"); visit_type_AltIntNum(v, NULL, &ain, &error_abort); @@ -635,26 +635,26 @@ static void test_visitor_in_alternate_number(TestInpu= tVisitorData *data, /* Parsing a double */ =20 v =3D visitor_input_test_init(data, "42.5"); - visit_type_AltStrBool(v, NULL, &asb, &err); + visit_type_AltEnumBool(v, NULL, &aeb, &err); error_free_or_abort(&err); - qapi_free_AltStrBool(asb); + qapi_free_AltEnumBool(aeb); =20 v =3D visitor_input_test_init(data, "42.5"); - visit_type_AltStrNum(v, NULL, &asn, &error_abort); - g_assert_cmpint(asn->type, =3D=3D, QTYPE_QFLOAT); - g_assert_cmpfloat(asn->u.n, =3D=3D, 42.5); - qapi_free_AltStrNum(asn); + visit_type_AltEnumNum(v, NULL, &aen, &error_abort); + g_assert_cmpint(aen->type, =3D=3D, QTYPE_QFLOAT); + g_assert_cmpfloat(aen->u.n, =3D=3D, 42.5); + qapi_free_AltEnumNum(aen); =20 v =3D visitor_input_test_init(data, "42.5"); - visit_type_AltNumStr(v, NULL, &ans, &error_abort); + visit_type_AltNumEnum(v, NULL, &ans, &error_abort); g_assert_cmpint(ans->type, =3D=3D, QTYPE_QFLOAT); g_assert_cmpfloat(ans->u.n, =3D=3D, 42.5); - qapi_free_AltNumStr(ans); + qapi_free_AltNumEnum(ans); =20 v =3D visitor_input_test_init(data, "42.5"); - visit_type_AltStrInt(v, NULL, &asi, &err); + visit_type_AltEnumInt(v, NULL, &asi, &err); error_free_or_abort(&err); - qapi_free_AltStrInt(asi); + qapi_free_AltEnumInt(asi); =20 v =3D visitor_input_test_init(data, "42.5"); visit_type_AltIntNum(v, NULL, &ain, &error_abort); diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-outpu= t-visitor.c index 94b9518..4e8fdf1 100644 --- a/tests/test-qobject-output-visitor.c +++ b/tests/test-qobject-output-visitor.c @@ -406,12 +406,12 @@ static void test_visitor_out_alternate(TestOutputVisi= torData *data, visitor_reset(data); tmp =3D g_new0(UserDefAlternate, 1); tmp->type =3D QTYPE_QSTRING; - tmp->u.s =3D g_strdup("hello"); + tmp->u.e =3D ENUM_ONE_VALUE1; =20 visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort); qstr =3D qobject_to_qstring(visitor_get(data)); g_assert(qstr); - g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, "hello"); + g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, "value1"); =20 qapi_free_UserDefAlternate(tmp); =20 --=20 2.7.4 From nobody Fri May 3 03:11:43 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.zoho.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 1496250912088729.3804475377864; Wed, 31 May 2017 10:15:12 -0700 (PDT) Received: from localhost ([::1]:33022 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG7DA-0006YY-Et for importer@patchew.org; Wed, 31 May 2017 13:15:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32861) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG77S-0002M3-6M for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dG77P-0000dg-4Z for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49178) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dG77O-0000d6-Rp for qemu-devel@nongnu.org; Wed, 31 May 2017 13:09:11 -0400 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 F2161C04B926 for ; Wed, 31 May 2017 17:09:09 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-98.ams2.redhat.com [10.36.116.98]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6B6F917149 for ; Wed, 31 May 2017 17:09:09 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id DB3FF113864D; Wed, 31 May 2017 19:09:07 +0200 (CEST) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F2161C04B926 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=armbru@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com F2161C04B926 From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 31 May 2017 19:09:07 +0200 Message-Id: <1496250547-20701-5-git-send-email-armbru@redhat.com> In-Reply-To: <1496250547-20701-1-git-send-email-armbru@redhat.com> References: <1496250547-20701-1-git-send-email-armbru@redhat.com> MIME-Version: 1.0 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]); Wed, 31 May 2017 17:09:10 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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] [PULL 4/4] qapi: Reject alternates that can't work with keyval_parse() 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Alternates are sum types like unions, but use the JSON type on the wire / QType in QObject instead of an explicit tag. That's why we require alternate members to have distinct QTypes. The recently introduced keyval_parse() (commit d454dbe) can only produce string scalars. The qobject_input_visitor_new_keyval() input visitor mostly hides the difference, so code using a QObject input visitor doesn't have to care whether its input was parsed from JSON or KEY=3DVALUE,... The difference leaks for alternates, as noted in commit 0ee9ae7: a non-string, non-enum scalar alternate value can't currently be expressed. In part, this is just our insufficiently sophisticated implementation. Consider alternate type 'GuestFileWhence'. It has an integer member and a 'QGASeek' member. The latter is an enumeration with values 'set', 'cur', 'end'. The meaning of b=3Dset, b=3Dcur, b=3Dend, b=3D0, b=3D= 1 and so forth is perfectly obvious. However, our current implementation falls apart at run time for b=3D0, b=3D1, and so forth. Fixable, but not today; add a test case and a TODO comment. Now consider an alternate type with a string and an integer member. What's the meaning of a=3D42? Is it the string "42" or the integer 42? Whichever meaning you pick makes the other inexpressible. This isn't just an implementation problem, it's fundamental. Our current implementation will pick string. So far, we haven't needed such alternates. To make sure we stop and think before we add one that cannot sanely work with keyval_parse(), let's require alternate members to have sufficiently distinct representation in KEY=3DVALUE,... syntax: * A string member clashes with any other scalar member * An enumeration member clashes with bool members when it has value 'on' or 'off'. * An enumeration member clashes with numeric members when it has a value that starts with '-', '+', or a decimal digit. This is a rather lazy approximation of the actual number syntax accepted by the visitor. Note that enumeration values starting with '-' and '+' are rejected elsewhere already, but better safe than sorry. Signed-off-by: Markus Armbruster Message-Id: <1495471335-23707-5-git-send-email-armbru@redhat.com> Reviewed-by: Eric Blake Reviewed-by: Marc-Andr=C3=A9 Lureau --- scripts/qapi.py | 19 +++++++++++++++++= -- tests/Makefile.include | 2 ++ tests/qapi-schema/alternate-conflict-dict.json | 2 +- tests/qapi-schema/alternate-conflict-enum-bool.err | 1 + tests/qapi-schema/alternate-conflict-enum-bool.exit | 1 + tests/qapi-schema/alternate-conflict-enum-bool.json | 6 ++++++ tests/qapi-schema/alternate-conflict-enum-bool.out | 0 tests/qapi-schema/alternate-conflict-enum-int.err | 1 + tests/qapi-schema/alternate-conflict-enum-int.exit | 1 + tests/qapi-schema/alternate-conflict-enum-int.json | 6 ++++++ tests/qapi-schema/alternate-conflict-enum-int.out | 0 tests/qapi-schema/alternate-conflict-string.err | 2 +- tests/qapi-schema/alternate-conflict-string.json | 6 ++---- tests/qapi-schema/qapi-schema-test.json | 4 +++- tests/qapi-schema/qapi-schema-test.out | 4 ++-- tests/test-keyval.c | 18 +++++++++++------- util/keyval.c | 10 +++++----- 17 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 tests/qapi-schema/alternate-conflict-enum-bool.err create mode 100644 tests/qapi-schema/alternate-conflict-enum-bool.exit create mode 100644 tests/qapi-schema/alternate-conflict-enum-bool.json create mode 100644 tests/qapi-schema/alternate-conflict-enum-bool.out create mode 100644 tests/qapi-schema/alternate-conflict-enum-int.err create mode 100644 tests/qapi-schema/alternate-conflict-enum-int.exit create mode 100644 tests/qapi-schema/alternate-conflict-enum-int.json create mode 100644 tests/qapi-schema/alternate-conflict-enum-int.out diff --git a/scripts/qapi.py b/scripts/qapi.py index 6c4d554..b7a25e4 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -812,11 +812,26 @@ def check_alternate(expr, info): if not qtype: raise QAPISemError(info, "Alternate '%s' member '%s' cannot us= e " "type '%s'" % (name, key, value)) - if qtype in types_seen: + conflicting =3D set([qtype]) + if qtype =3D=3D 'QTYPE_QSTRING': + enum_expr =3D enum_types.get(value) + if enum_expr: + for v in enum_expr['data']: + if v in ['on', 'off']: + conflicting.add('QTYPE_QBOOL') + if re.match(r'[-+0-9.]', v): # lazy, could be tightened + conflicting.add('QTYPE_QINT') + conflicting.add('QTYPE_QFLOAT') + else: + conflicting.add('QTYPE_QINT') + conflicting.add('QTYPE_QFLOAT') + conflicting.add('QTYPE_QBOOL') + if conflicting & set(types_seen): raise QAPISemError(info, "Alternate '%s' member '%s' can't " "be distinguished from member '%s'" % (name, key, types_seen[qtype])) - types_seen[qtype] =3D key + for qt in conflicting: + types_seen[qt] =3D key =20 =20 def check_enum(expr, info): diff --git a/tests/Makefile.include b/tests/Makefile.include index 7589383..f42f3df 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -342,6 +342,8 @@ qapi-schema +=3D alternate-array.json qapi-schema +=3D alternate-base.json qapi-schema +=3D alternate-clash.json qapi-schema +=3D alternate-conflict-dict.json +qapi-schema +=3D alternate-conflict-enum-bool.json +qapi-schema +=3D alternate-conflict-enum-int.json qapi-schema +=3D alternate-conflict-string.json qapi-schema +=3D alternate-empty.json qapi-schema +=3D alternate-nested.json diff --git a/tests/qapi-schema/alternate-conflict-dict.json b/tests/qapi-sc= hema/alternate-conflict-dict.json index d566cca..3d78812 100644 --- a/tests/qapi-schema/alternate-conflict-dict.json +++ b/tests/qapi-schema/alternate-conflict-dict.json @@ -1,4 +1,4 @@ -# we reject alternates with multiple object branches +# alternate branches of object type conflict with each other { 'struct': 'One', 'data': { 'name': 'str' } } { 'struct': 'Two', diff --git a/tests/qapi-schema/alternate-conflict-enum-bool.err b/tests/qap= i-schema/alternate-conflict-enum-bool.err new file mode 100644 index 0000000..0dfc002 --- /dev/null +++ b/tests/qapi-schema/alternate-conflict-enum-bool.err @@ -0,0 +1 @@ +tests/qapi-schema/alternate-conflict-enum-bool.json:4: Alternate 'Alt' mem= ber 'two' can't be distinguished from member 'one' diff --git a/tests/qapi-schema/alternate-conflict-enum-bool.exit b/tests/qa= pi-schema/alternate-conflict-enum-bool.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/alternate-conflict-enum-bool.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/alternate-conflict-enum-bool.json b/tests/qa= pi-schema/alternate-conflict-enum-bool.json new file mode 100644 index 0000000..bff25c3 --- /dev/null +++ b/tests/qapi-schema/alternate-conflict-enum-bool.json @@ -0,0 +1,6 @@ +# alternate branch of 'enum' type that conflicts with bool +{ 'enum': 'Enum', + 'data': [ 'aus', 'off' ] } +{ 'alternate': 'Alt', + 'data': { 'one': 'Enum', + 'two': 'bool' } } diff --git a/tests/qapi-schema/alternate-conflict-enum-bool.out b/tests/qap= i-schema/alternate-conflict-enum-bool.out new file mode 100644 index 0000000..e69de29 diff --git a/tests/qapi-schema/alternate-conflict-enum-int.err b/tests/qapi= -schema/alternate-conflict-enum-int.err new file mode 100644 index 0000000..2cc8e7b --- /dev/null +++ b/tests/qapi-schema/alternate-conflict-enum-int.err @@ -0,0 +1 @@ +tests/qapi-schema/alternate-conflict-enum-int.json:4: Alternate 'Alt' memb= er 'two' can't be distinguished from member 'one' diff --git a/tests/qapi-schema/alternate-conflict-enum-int.exit b/tests/qap= i-schema/alternate-conflict-enum-int.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/alternate-conflict-enum-int.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/alternate-conflict-enum-int.json b/tests/qap= i-schema/alternate-conflict-enum-int.json new file mode 100644 index 0000000..beb428c --- /dev/null +++ b/tests/qapi-schema/alternate-conflict-enum-int.json @@ -0,0 +1,6 @@ +# alternate branches of 'enum' type that conflicts with numbers +{ 'enum': 'Enum', + 'data': [ '1', '2', '3' ] } +{ 'alternate': 'Alt', + 'data': { 'one': 'Enum', + 'two': 'int' } } diff --git a/tests/qapi-schema/alternate-conflict-enum-int.out b/tests/qapi= -schema/alternate-conflict-enum-int.out new file mode 100644 index 0000000..e69de29 diff --git a/tests/qapi-schema/alternate-conflict-string.err b/tests/qapi-s= chema/alternate-conflict-string.err index fc523b0..fe2f188 100644 --- a/tests/qapi-schema/alternate-conflict-string.err +++ b/tests/qapi-schema/alternate-conflict-string.err @@ -1 +1 @@ -tests/qapi-schema/alternate-conflict-string.json:4: Alternate 'Alt' member= 'two' can't be distinguished from member 'one' +tests/qapi-schema/alternate-conflict-string.json:2: Alternate 'Alt' member= 'two' can't be distinguished from member 'one' diff --git a/tests/qapi-schema/alternate-conflict-string.json b/tests/qapi-= schema/alternate-conflict-string.json index 72f04a8..85adbd4 100644 --- a/tests/qapi-schema/alternate-conflict-string.json +++ b/tests/qapi-schema/alternate-conflict-string.json @@ -1,6 +1,4 @@ -# we reject alternates with multiple string-like branches -{ 'enum': 'Enum', - 'data': [ 'hello', 'world' ] } +# alternate branches of 'str' type conflict with all scalar types { 'alternate': 'Alt', 'data': { 'one': 'str', - 'two': 'Enum' } } + 'two': 'int' } } diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qa= pi-schema-test.json index 303f2b2..17649c6 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -101,12 +101,14 @@ # for testing use of 'number' within alternates { 'alternate': 'AltEnumBool', 'data': { 'e': 'EnumOne', 'b': 'bool' } } { 'alternate': 'AltEnumNum', 'data': { 'e': 'EnumOne', 'n': 'number' } } -{ 'alternate': 'AltNumStr', 'data': { 'n': 'number', 's': 'str' } } { 'alternate': 'AltNumEnum', 'data': { 'n': 'number', 'e': 'EnumOne' } } { 'alternate': 'AltEnumInt', 'data': { 'e': 'EnumOne', 'i': 'int' } } { 'alternate': 'AltIntNum', 'data': { 'i': 'int', 'n': 'number' } } { 'alternate': 'AltNumInt', 'data': { 'n': 'number', 'i': 'int' } } =20 +# for testing use of 'str' within alternates +{ 'alternate': 'AltStrObj', 'data': { 's': 'str', 'o': 'TestStruct' } } + # for testing native lists { 'union': 'UserDefNativeListUnion', 'data': { 'integer': ['int'], diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qap= i-schema-test.out index 3081091..9f68610 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -22,10 +22,10 @@ alternate AltNumInt tag type case n: number case i: int -alternate AltNumStr +alternate AltStrObj tag type - case n: number case s: str + case o: TestStruct event EVENT_A None boxed=3DFalse event EVENT_B None diff --git a/tests/test-keyval.c b/tests/test-keyval.c index c556b1b..c3be005 100644 --- a/tests/test-keyval.c +++ b/tests/test-keyval.c @@ -614,22 +614,26 @@ static void test_keyval_visit_alternate(void) Error *err =3D NULL; Visitor *v; QDict *qdict; - AltNumStr *ans; + AltStrObj *aso; AltNumInt *ani; + AltEnumBool *aeb; =20 /* * Can't do scalar alternate variants other than string. You get * the string variant if there is one, else an error. + * TODO make it work for unambiguous cases like AltEnumBool below */ - qdict =3D keyval_parse("a=3D1,b=3D2", NULL, &error_abort); + qdict =3D keyval_parse("a=3D1,b=3D2,c=3Don", NULL, &error_abort); v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); QDECREF(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); - visit_type_AltNumStr(v, "a", &ans, &error_abort); - g_assert_cmpint(ans->type, =3D=3D, QTYPE_QSTRING); - g_assert_cmpstr(ans->u.s, =3D=3D, "1"); - qapi_free_AltNumStr(ans); - visit_type_AltNumInt(v, "a", &ani, &err); + visit_type_AltStrObj(v, "a", &aso, &error_abort); + g_assert_cmpint(aso->type, =3D=3D, QTYPE_QSTRING); + g_assert_cmpstr(aso->u.s, =3D=3D, "1"); + qapi_free_AltStrObj(aso); + visit_type_AltNumInt(v, "b", &ani, &err); + error_free_or_abort(&err); + visit_type_AltEnumBool(v, "c", &aeb, &err); error_free_or_abort(&err); visit_end_struct(v, NULL); visit_free(v); diff --git a/util/keyval.c b/util/keyval.c index 93d5db6..7dbda62 100644 --- a/util/keyval.c +++ b/util/keyval.c @@ -65,11 +65,11 @@ * denote numbers, true, false or null. The special QObject input * visitor returned by qobject_input_visitor_new_keyval() mostly hides * this by automatically converting strings to the type the visitor - * expects. Breaks down for alternate types and type 'any', where the - * visitor's expectation isn't clear. Code visiting such types needs - * to do the conversion itself, but only when using this keyval - * visitor. Awkward. Alternate types without a string member don't - * work at all. + * expects. Breaks down for type 'any', where the visitor's + * expectation isn't clear. Code visiting 'any' needs to do the + * conversion itself, but only when using this keyval visitor. + * Awkward. Note that we carefully restrict alternate types to avoid + * similar ambiguity. * * Additional syntax for use with an implied key: * --=20 2.7.4