From nobody Mon Feb 9 00:42:40 2026 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 1487709534233325.66358912765713; Tue, 21 Feb 2017 12:38:54 -0800 (PST) Received: from localhost ([::1]:48400 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cgHD3-0004uV-0O for importer@patchew.org; Tue, 21 Feb 2017 15:38:53 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55021) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cgGpC-0007Pk-H7 for qemu-devel@nongnu.org; Tue, 21 Feb 2017 15:14:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cgGp9-0008TH-LG for qemu-devel@nongnu.org; Tue, 21 Feb 2017 15:14:14 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40078) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cgGp9-0008Sk-CS for qemu-devel@nongnu.org; Tue, 21 Feb 2017 15:14:11 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 99F9A4E02B for ; Tue, 21 Feb 2017 20:14:11 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1LKE9Uo030778 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 21 Feb 2017 15:14:10 -0500 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 25FC5113864A; Tue, 21 Feb 2017 21:14:08 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 21 Feb 2017 21:13:45 +0100 Message-Id: <1487708048-2131-2-git-send-email-armbru@redhat.com> In-Reply-To: <1487708048-2131-1-git-send-email-armbru@redhat.com> References: <1487708048-2131-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 21 Feb 2017 20:14:11 +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 v2 01/24] test-qemu-opts: Cover qemu_opts_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-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The new tests demonstrate a few bugs, all clearly marked. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Signed-off-by: Markus Armbruster --- tests/test-qemu-opts.c | 312 +++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 310 insertions(+), 2 deletions(-) diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c index a505a3e..d5dab12 100644 --- a/tests/test-qemu-opts.c +++ b/tests/test-qemu-opts.c @@ -8,6 +8,7 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qapi/error.h" #include "qapi/qmp/qstring.h" #include "qemu/config-file.h" @@ -29,6 +30,9 @@ static QemuOptsList opts_list_01 =3D { },{ .name =3D "number1", .type =3D QEMU_OPT_NUMBER, + },{ + .name =3D "number2", + .type =3D QEMU_OPT_NUMBER, }, { /* end of list */ } }, @@ -42,14 +46,23 @@ static QemuOptsList opts_list_02 =3D { .name =3D "str1", .type =3D QEMU_OPT_STRING, },{ + .name =3D "str2", + .type =3D QEMU_OPT_STRING, + },{ .name =3D "bool1", .type =3D QEMU_OPT_BOOL, },{ - .name =3D "str2", - .type =3D QEMU_OPT_STRING, + .name =3D "bool2", + .type =3D QEMU_OPT_BOOL, },{ .name =3D "size1", .type =3D QEMU_OPT_SIZE, + },{ + .name =3D "size2", + .type =3D QEMU_OPT_SIZE, + },{ + .name =3D "size3", + .type =3D QEMU_OPT_SIZE, }, { /* end of list */ } }, @@ -57,6 +70,7 @@ static QemuOptsList opts_list_02 =3D { =20 static QemuOptsList opts_list_03 =3D { .name =3D "opts_list_03", + .implied_opt_name =3D "implied", .head =3D QTAILQ_HEAD_INITIALIZER(opts_list_03.head), .desc =3D { /* no elements =3D> accept any params */ @@ -421,6 +435,296 @@ static void test_qemu_opts_set(void) g_assert(opts =3D=3D NULL); } =20 +static int opts_count_iter(void *opaque, const char *name, const char *val= ue, + Error **errp) +{ + (*(size_t *)opaque)++; + return 0; +} + +static size_t opts_count(QemuOpts *opts) +{ + size_t n =3D 0; + + qemu_opt_foreach(opts, opts_count_iter, &n, NULL); + return n; +} + +static void test_opts_parse(void) +{ + Error *err =3D NULL; + QemuOpts *opts; + char long_key[129]; + char *params; + + /* Nothing */ + opts =3D qemu_opts_parse(&opts_list_03, "", false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 0); + + /* Empty key */ + opts =3D qemu_opts_parse(&opts_list_03, "=3Dval", false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpstr(qemu_opt_get(opts, ""), =3D=3D, "val"); + + /* Long key */ + memset(long_key, 'a', 127); + long_key[127] =3D 'z'; + long_key[128] =3D 0; + params =3D g_strdup_printf("%s=3Dv", long_key); + opts =3D qemu_opts_parse(&opts_list_03, params + 1, NULL, &error_abort= ); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpstr(qemu_opt_get(opts, long_key + 1), =3D=3D, "v"); + + /* Overlong key gets truncated */ + opts =3D qemu_opts_parse(&opts_list_03, params, NULL, &error_abort); + g_assert(opts_count(opts) =3D=3D 1); + long_key[127] =3D 0; + g_assert_cmpstr(qemu_opt_get(opts, long_key), =3D=3D, "v"); + g_free(params); + + /* Multiple keys, last one wins */ + opts =3D qemu_opts_parse(&opts_list_03, "a=3D1,b=3D2,,x,a=3D3", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 3); + g_assert_cmpstr(qemu_opt_get(opts, "a"), =3D=3D, "3"); + g_assert_cmpstr(qemu_opt_get(opts, "b"), =3D=3D, "2,x"); + + /* Except when it doesn't */ + opts =3D qemu_opts_parse(&opts_list_03, "id=3Dfoo,id=3Dbar", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 0); + g_assert_cmpstr(qemu_opts_id(opts), =3D=3D, "foo"); + + /* Implied value */ + opts =3D qemu_opts_parse(&opts_list_03, "an,noaus,noaus=3D", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 3); + g_assert_cmpstr(qemu_opt_get(opts, "an"), =3D=3D, "on"); + g_assert_cmpstr(qemu_opt_get(opts, "aus"), =3D=3D, "off"); + g_assert_cmpstr(qemu_opt_get(opts, "noaus"), =3D=3D, ""); + + /* Implied key */ + opts =3D qemu_opts_parse(&opts_list_03, "an,noaus,noaus=3D", true, + &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 3); + g_assert_cmpstr(qemu_opt_get(opts, "implied"), =3D=3D, "an"); + g_assert_cmpstr(qemu_opt_get(opts, "aus"), =3D=3D, "off"); + g_assert_cmpstr(qemu_opt_get(opts, "noaus"), =3D=3D, ""); + + /* Trailing comma is ignored */ + opts =3D qemu_opts_parse(&opts_list_03, "x=3Dy,", false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpstr(qemu_opt_get(opts, "x"), =3D=3D, "y"); + + /* Except when it isn't */ + opts =3D qemu_opts_parse(&opts_list_03, ",", false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpstr(qemu_opt_get(opts, ""), =3D=3D, "on"); + + /* Duplicate ID */ + opts =3D qemu_opts_parse(&opts_list_03, "x=3Dy,id=3Dfoo", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + /* TODO Cover .merge_lists =3D true */ + + /* Buggy ID recognition */ + opts =3D qemu_opts_parse(&opts_list_03, "x=3D,,id=3Dbar", false, &erro= r_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpstr(qemu_opts_id(opts), =3D=3D, "bar"); /* BUG */ + g_assert_cmpstr(qemu_opt_get(opts, "x"), =3D=3D, ",id=3Dbar"); + + /* Anti-social ID */ + opts =3D qemu_opts_parse(&opts_list_01, "id=3D666", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + + /* Unknown key */ + opts =3D qemu_opts_parse(&opts_list_01, "nonexistent=3D", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + + qemu_opts_reset(&opts_list_01); + qemu_opts_reset(&opts_list_03); +} + +static void test_opts_parse_bool(void) +{ + Error *err =3D NULL; + QemuOpts *opts; + + opts =3D qemu_opts_parse(&opts_list_02, "bool1=3Don,bool2=3Doff", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 2); + g_assert(qemu_opt_get_bool(opts, "bool1", false)); + g_assert(!qemu_opt_get_bool(opts, "bool2", true)); + + opts =3D qemu_opts_parse(&opts_list_02, "bool1=3Doffer", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + + qemu_opts_reset(&opts_list_02); +} + +static void test_opts_parse_number(void) +{ + Error *err =3D NULL; + QemuOpts *opts; + + /* Lower limit zero */ + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D0", false, &error_a= bort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), =3D=3D, 0); + + /* Upper limit 2^64-1 */ + opts =3D qemu_opts_parse(&opts_list_01, + "number1=3D18446744073709551615,number2=3D-1", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 2); + g_assert_cmphex(qemu_opt_get_number(opts, "number1", 1), =3D=3D, UINT6= 4_MAX); + g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), =3D=3D, UINT6= 4_MAX); + + /* Above upper limit */ + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D1844674407370955161= 6", + false, &error_abort); + /* BUG: should reject */ + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), =3D=3D, UINT= 64_MAX); + + /* Below lower limit */ + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D-184467440737095516= 16", + false, &error_abort); + /* BUG: should reject */ + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), =3D=3D, UINT= 64_MAX); + + /* Hex and octal */ + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D0x2a,number2=3D052", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 2); + g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), =3D=3D, 42); + g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), =3D=3D, 42); + + /* Invalid */ + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D", false, &err); + /* BUG: should reject */ + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), =3D=3D, 0); + opts =3D qemu_opts_parse(&opts_list_01, "number1=3Deins", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + + /* Leading whitespace */ + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D \t42", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), =3D=3D, 42); + + /* Trailing crap */ + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D3.14", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D08", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + opts =3D qemu_opts_parse(&opts_list_01, "number1=3D0 ", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + + qemu_opts_reset(&opts_list_01); +} + +static void test_opts_parse_size(void) +{ + Error *err =3D NULL; + QemuOpts *opts; + + /* Lower limit zero */ + opts =3D qemu_opts_parse(&opts_list_02, "size1=3D0", false, &error_abo= rt); + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), =3D=3D, 0); + + /* Note: precision is 53 bits since we're parsing with strtod() */ + + /* Around limit of precision: 2^53-1, 2^53, 2^54 */ + opts =3D qemu_opts_parse(&opts_list_02, + "size1=3D9007199254740991," + "size2=3D9007199254740992," + "size3=3D9007199254740993", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 3); + g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), + =3D=3D, 0x1fffffffffffff); + g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), + =3D=3D, 0x20000000000000); + g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1), + =3D=3D, 0x20000000000000); + + /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */ + opts =3D qemu_opts_parse(&opts_list_02, + "size1=3D9223372036854774784," /* 7ffffffffffff= c00 */ + "size2=3D9223372036854775295", /* 7ffffffffffff= dff */ + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 2); + g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), + =3D=3D, 0x7ffffffffffffc00); + g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), + =3D=3D, 0x7ffffffffffffc00); + + /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ + opts =3D qemu_opts_parse(&opts_list_02, + "size1=3D18446744073709549568," /* ffffffffffff= f800 */ + "size2=3D18446744073709550591", /* ffffffffffff= fbff */ + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 2); + g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), + =3D=3D, 0xfffffffffffff800); + g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), + =3D=3D, 0xfffffffffffff800); + + /* Beyond limits */ + opts =3D qemu_opts_parse(&opts_list_02, "size1=3D-1", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + opts =3D qemu_opts_parse(&opts_list_02, + "size1=3D18446744073709550592", /* ffffffffffff= fc00 */ + false, &error_abort); + /* BUG: should reject */ + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), =3D=3D, 0); + + /* Suffixes */ + opts =3D qemu_opts_parse(&opts_list_02, "size1=3D8b,size2=3D1.5k,size3= =3D2M", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 3); + g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), =3D=3D, 8); + g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), =3D=3D, 1536); + g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), =3D=3D, 2 * M_BYT= E); + opts =3D qemu_opts_parse(&opts_list_02, "size1=3D0.1G,size2=3D16777215= T", + false, &error_abort); + g_assert_cmpuint(opts_count(opts), =3D=3D, 2); + g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), =3D=3D, G_BYTE / = 10); + g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), + =3D=3D, 16777215 * T_BYTE); + + /* Beyond limit with suffix */ + opts =3D qemu_opts_parse(&opts_list_02, "size1=3D16777216T", + false, &error_abort); + /* BUG: should reject */ + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), =3D=3D, 0); + + /* Trailing crap */ + opts =3D qemu_opts_parse(&opts_list_02, "size1=3D16E", false, &err); + error_free_or_abort(&err); + g_assert(!opts); + opts =3D qemu_opts_parse(&opts_list_02, "size1=3D16Gi", false, &error_= abort); + /* BUG: should reject */ + g_assert_cmpuint(opts_count(opts), =3D=3D, 1); + g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), =3D=3D, 16 * G_B= YTE); + + qemu_opts_reset(&opts_list_02); +} + int main(int argc, char *argv[]) { register_opts(); @@ -435,6 +739,10 @@ int main(int argc, char *argv[]) g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset); g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset); g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set); + g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse); + g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool); + g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number= ); + g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size); g_test_run(); return 0; } --=20 2.7.4