]> git.proxmox.com Git - mirror_qemu.git/blame - tests/test-keyval.c
keyval: New keyval_parse()
[mirror_qemu.git] / tests / test-keyval.c
CommitLineData
d454dbe0
MA
1/*
2 * Unit tests for parsing of KEY=VALUE,... strings
3 *
4 * Copyright (C) 2017 Red Hat Inc.
5 *
6 * Authors:
7 * Markus Armbruster <armbru@redhat.com>,
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
13#include "qemu/osdep.h"
14#include "qapi/error.h"
15#include "qemu/option.h"
16
17static void test_keyval_parse(void)
18{
19 Error *err = NULL;
20 QDict *qdict, *sub_qdict;
21 char long_key[129];
22 char *params;
23
24 /* Nothing */
25 qdict = keyval_parse("", NULL, &error_abort);
26 g_assert_cmpuint(qdict_size(qdict), ==, 0);
27 QDECREF(qdict);
28
29 /* Empty key (qemu_opts_parse() accepts this) */
30 qdict = keyval_parse("=val", NULL, &err);
31 error_free_or_abort(&err);
32 g_assert(!qdict);
33
34 /* Empty key fragment */
35 qdict = keyval_parse(".", NULL, &err);
36 error_free_or_abort(&err);
37 g_assert(!qdict);
38 qdict = keyval_parse("key.", NULL, &err);
39 error_free_or_abort(&err);
40 g_assert(!qdict);
41
42 /* Overlong key */
43 memset(long_key, 'a', 127);
44 long_key[127] = 'z';
45 long_key[128] = 0;
46 params = g_strdup_printf("k.%s=v", long_key);
47 qdict = keyval_parse(params + 2, NULL, &err);
48 error_free_or_abort(&err);
49 g_assert(!qdict);
50
51 /* Overlong key fragment */
52 qdict = keyval_parse(params, NULL, &err);
53 error_free_or_abort(&err);
54 g_assert(!qdict);
55 g_free(params);
56
57 /* Long key (qemu_opts_parse() accepts and truncates silently) */
58 params = g_strdup_printf("k.%s=v", long_key + 1);
59 qdict = keyval_parse(params + 2, NULL, &error_abort);
60 g_assert_cmpuint(qdict_size(qdict), ==, 1);
61 g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), ==, "v");
62 QDECREF(qdict);
63
64 /* Long key fragment */
65 qdict = keyval_parse(params, NULL, &error_abort);
66 g_assert_cmpuint(qdict_size(qdict), ==, 1);
67 sub_qdict = qdict_get_qdict(qdict, "k");
68 g_assert(sub_qdict);
69 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
70 g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), ==, "v");
71 QDECREF(qdict);
72 g_free(params);
73
74 /* Multiple keys, last one wins */
75 qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, &error_abort);
76 g_assert_cmpuint(qdict_size(qdict), ==, 2);
77 g_assert_cmpstr(qdict_get_try_str(qdict, "a"), ==, "3");
78 g_assert_cmpstr(qdict_get_try_str(qdict, "b"), ==, "2,x");
79 QDECREF(qdict);
80
81 /* Even when it doesn't in qemu_opts_parse() */
82 qdict = keyval_parse("id=foo,id=bar", NULL, &error_abort);
83 g_assert_cmpuint(qdict_size(qdict), ==, 1);
84 g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "bar");
85 QDECREF(qdict);
86
87 /* Dotted keys */
88 qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort);
89 g_assert_cmpuint(qdict_size(qdict), ==, 2);
90 sub_qdict = qdict_get_qdict(qdict, "a");
91 g_assert(sub_qdict);
92 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
93 sub_qdict = qdict_get_qdict(sub_qdict, "b");
94 g_assert(sub_qdict);
95 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
96 g_assert_cmpstr(qdict_get_try_str(sub_qdict, "c"), ==, "2");
97 g_assert_cmpstr(qdict_get_try_str(qdict, "d"), ==, "3");
98 QDECREF(qdict);
99
100 /* Inconsistent dotted keys */
101 qdict = keyval_parse("a.b=1,a=2", NULL, &err);
102 error_free_or_abort(&err);
103 g_assert(!qdict);
104 qdict = keyval_parse("a.b=1,a.b.c=2", NULL, &err);
105 error_free_or_abort(&err);
106 g_assert(!qdict);
107
108 /* Trailing comma is ignored */
109 qdict = keyval_parse("x=y,", NULL, &error_abort);
110 g_assert_cmpuint(qdict_size(qdict), ==, 1);
111 g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, "y");
112 QDECREF(qdict);
113
114 /* Except when it isn't */
115 qdict = keyval_parse(",", NULL, &err);
116 error_free_or_abort(&err);
117 g_assert(!qdict);
118
119 /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */
120 qdict = keyval_parse("x=,,id=bar", NULL, &error_abort);
121 g_assert_cmpuint(qdict_size(qdict), ==, 1);
122 g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, ",id=bar");
123 QDECREF(qdict);
124
125 /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */
126 qdict = keyval_parse("id=666", NULL, &error_abort);
127 g_assert_cmpuint(qdict_size(qdict), ==, 1);
128 g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "666");
129 QDECREF(qdict);
130
131 /* Implied value not supported (unlike qemu_opts_parse()) */
132 qdict = keyval_parse("an,noaus,noaus=", NULL, &err);
133 error_free_or_abort(&err);
134 g_assert(!qdict);
135
136 /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */
137 qdict = keyval_parse("no", NULL, &err);
138 error_free_or_abort(&err);
139 g_assert(!qdict);
140
141 /* Implied key */
142 qdict = keyval_parse("an,aus=off,noaus=", "implied", &error_abort);
143 g_assert_cmpuint(qdict_size(qdict), ==, 3);
144 g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "an");
145 g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), ==, "off");
146 g_assert_cmpstr(qdict_get_try_str(qdict, "noaus"), ==, "");
147 QDECREF(qdict);
148
149 /* Implied dotted key */
150 qdict = keyval_parse("val", "eins.zwei", &error_abort);
151 g_assert_cmpuint(qdict_size(qdict), ==, 1);
152 sub_qdict = qdict_get_qdict(qdict, "eins");
153 g_assert(sub_qdict);
154 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
155 g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), ==, "val");
156 QDECREF(qdict);
157
158 /* Implied key with empty value (qemu_opts_parse() accepts this) */
159 qdict = keyval_parse(",", "implied", &err);
160 error_free_or_abort(&err);
161 g_assert(!qdict);
162
163 /* Likewise (qemu_opts_parse(): implied key with comma value) */
164 qdict = keyval_parse(",,,a=1", "implied", &err);
165 error_free_or_abort(&err);
166 g_assert(!qdict);
167
168 /* Empty key is not an implied key */
169 qdict = keyval_parse("=val", "implied", &err);
170 error_free_or_abort(&err);
171 g_assert(!qdict);
172}
173
174int main(int argc, char *argv[])
175{
176 g_test_init(&argc, &argv, NULL);
177 g_test_add_func("/keyval/keyval_parse", test_keyval_parse);
178 g_test_run();
179 return 0;
180}