xref: /qemu/tests/unit/test-opts-visitor.c (revision da668aa15b99150a8595c491aee00d5d2426aaf9)
13953e3a5SLaszlo Ersek /*
23953e3a5SLaszlo Ersek  * Options Visitor unit-tests.
33953e3a5SLaszlo Ersek  *
43953e3a5SLaszlo Ersek  * Copyright (C) 2013 Red Hat, Inc.
53953e3a5SLaszlo Ersek  *
63953e3a5SLaszlo Ersek  * Authors:
73953e3a5SLaszlo Ersek  *   Laszlo Ersek <lersek@redhat.com> (based on test-string-output-visitor)
83953e3a5SLaszlo Ersek  *
93953e3a5SLaszlo Ersek  * This work is licensed under the terms of the GNU GPL, version 2 or later.
103953e3a5SLaszlo Ersek  * See the COPYING file in the top-level directory.
113953e3a5SLaszlo Ersek  */
123953e3a5SLaszlo Ersek 
13681c28a3SPeter Maydell #include "qemu/osdep.h"
143953e3a5SLaszlo Ersek 
153953e3a5SLaszlo Ersek #include "qemu/config-file.h"     /* qemu_add_opts() */
163953e3a5SLaszlo Ersek #include "qemu/option.h"          /* qemu_opts_parse() */
17da34e65cSMarkus Armbruster #include "qapi/error.h"
183953e3a5SLaszlo Ersek #include "qapi/opts-visitor.h"    /* opts_visitor_new() */
193953e3a5SLaszlo Ersek #include "test-qapi-visit.h"      /* visit_type_UserDefOptions() */
203953e3a5SLaszlo Ersek 
213953e3a5SLaszlo Ersek static QemuOptsList userdef_opts = {
223953e3a5SLaszlo Ersek     .name = "userdef",
233953e3a5SLaszlo Ersek     .head = QTAILQ_HEAD_INITIALIZER(userdef_opts.head),
243953e3a5SLaszlo Ersek     .desc = { { 0 } } /* validated with OptsVisitor */
253953e3a5SLaszlo Ersek };
263953e3a5SLaszlo Ersek 
273953e3a5SLaszlo Ersek /* fixture (= glib test case context) and test case manipulation */
283953e3a5SLaszlo Ersek 
293953e3a5SLaszlo Ersek typedef struct OptsVisitorFixture {
303953e3a5SLaszlo Ersek     UserDefOptions *userdef;
313953e3a5SLaszlo Ersek     Error *err;
323953e3a5SLaszlo Ersek } OptsVisitorFixture;
333953e3a5SLaszlo Ersek 
343953e3a5SLaszlo Ersek 
353953e3a5SLaszlo Ersek static void
setup_fixture(OptsVisitorFixture * f,gconstpointer test_data)363953e3a5SLaszlo Ersek setup_fixture(OptsVisitorFixture *f, gconstpointer test_data)
373953e3a5SLaszlo Ersek {
383953e3a5SLaszlo Ersek     const char *opts_string = test_data;
393953e3a5SLaszlo Ersek     QemuOpts *opts;
4009204eacSEric Blake     Visitor *v;
413953e3a5SLaszlo Ersek 
4270b94331SMarkus Armbruster     opts = qemu_opts_parse(qemu_find_opts("userdef"), opts_string, false,
4370b94331SMarkus Armbruster                            NULL);
443953e3a5SLaszlo Ersek     g_assert(opts != NULL);
453953e3a5SLaszlo Ersek 
4609204eacSEric Blake     v = opts_visitor_new(opts);
4709204eacSEric Blake     visit_type_UserDefOptions(v, NULL, &f->userdef, &f->err);
4809204eacSEric Blake     visit_free(v);
493953e3a5SLaszlo Ersek     qemu_opts_del(opts);
503953e3a5SLaszlo Ersek }
513953e3a5SLaszlo Ersek 
523953e3a5SLaszlo Ersek 
533953e3a5SLaszlo Ersek static void
teardown_fixture(OptsVisitorFixture * f,gconstpointer test_data)543953e3a5SLaszlo Ersek teardown_fixture(OptsVisitorFixture *f, gconstpointer test_data)
553953e3a5SLaszlo Ersek {
5696a1616cSEric Blake     qapi_free_UserDefOptions(f->userdef);
573953e3a5SLaszlo Ersek     error_free(f->err);
583953e3a5SLaszlo Ersek }
593953e3a5SLaszlo Ersek 
603953e3a5SLaszlo Ersek 
613953e3a5SLaszlo Ersek static void
add_test(const char * testpath,void (* test_func)(OptsVisitorFixture * f,gconstpointer test_data),gconstpointer test_data)623953e3a5SLaszlo Ersek add_test(const char *testpath,
633953e3a5SLaszlo Ersek          void (*test_func)(OptsVisitorFixture *f, gconstpointer test_data),
643953e3a5SLaszlo Ersek          gconstpointer test_data)
653953e3a5SLaszlo Ersek {
663953e3a5SLaszlo Ersek     g_test_add(testpath, OptsVisitorFixture, test_data, setup_fixture,
673953e3a5SLaszlo Ersek                test_func, teardown_fixture);
683953e3a5SLaszlo Ersek }
693953e3a5SLaszlo Ersek 
703953e3a5SLaszlo Ersek /* test output evaluation */
713953e3a5SLaszlo Ersek 
723953e3a5SLaszlo Ersek static void
expect_ok(OptsVisitorFixture * f,gconstpointer test_data)733953e3a5SLaszlo Ersek expect_ok(OptsVisitorFixture *f, gconstpointer test_data)
743953e3a5SLaszlo Ersek {
753953e3a5SLaszlo Ersek     g_assert(f->err == NULL);
763953e3a5SLaszlo Ersek     g_assert(f->userdef != NULL);
773953e3a5SLaszlo Ersek }
783953e3a5SLaszlo Ersek 
793953e3a5SLaszlo Ersek 
803953e3a5SLaszlo Ersek static void
expect_fail(OptsVisitorFixture * f,gconstpointer test_data)813953e3a5SLaszlo Ersek expect_fail(OptsVisitorFixture *f, gconstpointer test_data)
823953e3a5SLaszlo Ersek {
833953e3a5SLaszlo Ersek     g_assert(f->err != NULL);
843953e3a5SLaszlo Ersek 
853953e3a5SLaszlo Ersek     /* The error message is printed when this test utility is invoked directly
863953e3a5SLaszlo Ersek      * (ie. without gtester) and the --verbose flag is passed:
873953e3a5SLaszlo Ersek      *
883953e3a5SLaszlo Ersek      * tests/test-opts-visitor --verbose
893953e3a5SLaszlo Ersek      */
903953e3a5SLaszlo Ersek     g_test_message("'%s': %s", (const char *)test_data,
913953e3a5SLaszlo Ersek                    error_get_pretty(f->err));
923953e3a5SLaszlo Ersek }
933953e3a5SLaszlo Ersek 
943953e3a5SLaszlo Ersek 
953953e3a5SLaszlo Ersek static void
test_value(OptsVisitorFixture * f,gconstpointer test_data)963953e3a5SLaszlo Ersek test_value(OptsVisitorFixture *f, gconstpointer test_data)
973953e3a5SLaszlo Ersek {
983953e3a5SLaszlo Ersek     uint64_t magic, bitval;
993953e3a5SLaszlo Ersek     intList *i64;
1003953e3a5SLaszlo Ersek     uint64List *u64;
1013953e3a5SLaszlo Ersek     uint16List *u16;
1023953e3a5SLaszlo Ersek 
1033953e3a5SLaszlo Ersek     expect_ok(f, test_data);
1043953e3a5SLaszlo Ersek 
1053953e3a5SLaszlo Ersek     magic = 0;
1063953e3a5SLaszlo Ersek     for (i64 = f->userdef->i64; i64 != NULL; i64 = i64->next) {
1073953e3a5SLaszlo Ersek         g_assert(-16 <= i64->value && i64->value < 64-16);
1083953e3a5SLaszlo Ersek         bitval = 1ull << (i64->value + 16);
1093953e3a5SLaszlo Ersek         g_assert((magic & bitval) == 0);
1103953e3a5SLaszlo Ersek         magic |= bitval;
1113953e3a5SLaszlo Ersek     }
1123953e3a5SLaszlo Ersek     g_assert(magic == 0xDEADBEEF);
1133953e3a5SLaszlo Ersek 
1143953e3a5SLaszlo Ersek     magic = 0;
1153953e3a5SLaszlo Ersek     for (u64 = f->userdef->u64; u64 != NULL; u64 = u64->next) {
1163953e3a5SLaszlo Ersek         g_assert(u64->value < 64);
1173953e3a5SLaszlo Ersek         bitval = 1ull << u64->value;
1183953e3a5SLaszlo Ersek         g_assert((magic & bitval) == 0);
1193953e3a5SLaszlo Ersek         magic |= bitval;
1203953e3a5SLaszlo Ersek     }
1215cb6be2cSStefan Hajnoczi     g_assert(magic == 0xBADC0FFEE0DDF00DULL);
1223953e3a5SLaszlo Ersek 
1233953e3a5SLaszlo Ersek     magic = 0;
1243953e3a5SLaszlo Ersek     for (u16 = f->userdef->u16; u16 != NULL; u16 = u16->next) {
1253953e3a5SLaszlo Ersek         g_assert(u16->value < 64);
1263953e3a5SLaszlo Ersek         bitval = 1ull << u16->value;
1273953e3a5SLaszlo Ersek         g_assert((magic & bitval) == 0);
1283953e3a5SLaszlo Ersek         magic |= bitval;
1293953e3a5SLaszlo Ersek     }
1303953e3a5SLaszlo Ersek     g_assert(magic == 0xD15EA5E);
1313953e3a5SLaszlo Ersek }
1323953e3a5SLaszlo Ersek 
1333953e3a5SLaszlo Ersek 
1343953e3a5SLaszlo Ersek static void
expect_i64_min(OptsVisitorFixture * f,gconstpointer test_data)1353953e3a5SLaszlo Ersek expect_i64_min(OptsVisitorFixture *f, gconstpointer test_data)
1363953e3a5SLaszlo Ersek {
1373953e3a5SLaszlo Ersek     expect_ok(f, test_data);
1383953e3a5SLaszlo Ersek     g_assert(f->userdef->has_i64);
1393953e3a5SLaszlo Ersek     g_assert(f->userdef->i64->next == NULL);
1403953e3a5SLaszlo Ersek     g_assert(f->userdef->i64->value == INT64_MIN);
1413953e3a5SLaszlo Ersek }
1423953e3a5SLaszlo Ersek 
1433953e3a5SLaszlo Ersek 
1443953e3a5SLaszlo Ersek static void
expect_i64_max(OptsVisitorFixture * f,gconstpointer test_data)1453953e3a5SLaszlo Ersek expect_i64_max(OptsVisitorFixture *f, gconstpointer test_data)
1463953e3a5SLaszlo Ersek {
1473953e3a5SLaszlo Ersek     expect_ok(f, test_data);
1483953e3a5SLaszlo Ersek     g_assert(f->userdef->has_i64);
1493953e3a5SLaszlo Ersek     g_assert(f->userdef->i64->next == NULL);
1503953e3a5SLaszlo Ersek     g_assert(f->userdef->i64->value == INT64_MAX);
1513953e3a5SLaszlo Ersek }
1523953e3a5SLaszlo Ersek 
1533953e3a5SLaszlo Ersek 
1543953e3a5SLaszlo Ersek static void
expect_zero(OptsVisitorFixture * f,gconstpointer test_data)1553953e3a5SLaszlo Ersek expect_zero(OptsVisitorFixture *f, gconstpointer test_data)
1563953e3a5SLaszlo Ersek {
1573953e3a5SLaszlo Ersek     expect_ok(f, test_data);
1583953e3a5SLaszlo Ersek     g_assert(f->userdef->has_u64);
1593953e3a5SLaszlo Ersek     g_assert(f->userdef->u64->next == NULL);
1603953e3a5SLaszlo Ersek     g_assert(f->userdef->u64->value == 0);
1613953e3a5SLaszlo Ersek }
1623953e3a5SLaszlo Ersek 
1633953e3a5SLaszlo Ersek 
1643953e3a5SLaszlo Ersek static void
expect_u64_max(OptsVisitorFixture * f,gconstpointer test_data)1653953e3a5SLaszlo Ersek expect_u64_max(OptsVisitorFixture *f, gconstpointer test_data)
1663953e3a5SLaszlo Ersek {
1673953e3a5SLaszlo Ersek     expect_ok(f, test_data);
1683953e3a5SLaszlo Ersek     g_assert(f->userdef->has_u64);
1693953e3a5SLaszlo Ersek     g_assert(f->userdef->u64->next == NULL);
1703953e3a5SLaszlo Ersek     g_assert(f->userdef->u64->value == UINT64_MAX);
1713953e3a5SLaszlo Ersek }
1723953e3a5SLaszlo Ersek 
1733953e3a5SLaszlo Ersek /* test cases */
1743953e3a5SLaszlo Ersek 
1759cb8ef36SMarkus Armbruster static void
test_opts_range_unvisited(void)1769cb8ef36SMarkus Armbruster test_opts_range_unvisited(void)
1779cb8ef36SMarkus Armbruster {
178*21f88d02SEric Blake     Error *err = NULL;
1799cb8ef36SMarkus Armbruster     intList *list = NULL;
1809cb8ef36SMarkus Armbruster     intList *tail;
1819cb8ef36SMarkus Armbruster     QemuOpts *opts;
1829cb8ef36SMarkus Armbruster     Visitor *v;
1839cb8ef36SMarkus Armbruster 
1849cb8ef36SMarkus Armbruster     opts = qemu_opts_parse(qemu_find_opts("userdef"), "ilist=0-2", false,
1859cb8ef36SMarkus Armbruster                            &error_abort);
1869cb8ef36SMarkus Armbruster 
1879cb8ef36SMarkus Armbruster     v = opts_visitor_new(opts);
1889cb8ef36SMarkus Armbruster 
1899cb8ef36SMarkus Armbruster     visit_start_struct(v, NULL, NULL, 0, &error_abort);
1909cb8ef36SMarkus Armbruster 
1919cb8ef36SMarkus Armbruster     /* Would be simpler if the visitor genuinely supported virtual walks */
1929cb8ef36SMarkus Armbruster     visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list),
1939cb8ef36SMarkus Armbruster                      &error_abort);
1949cb8ef36SMarkus Armbruster     tail = list;
1959cb8ef36SMarkus Armbruster     visit_type_int(v, NULL, &tail->value, &error_abort);
1969cb8ef36SMarkus Armbruster     g_assert_cmpint(tail->value, ==, 0);
1979cb8ef36SMarkus Armbruster     tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));
1989cb8ef36SMarkus Armbruster     g_assert(tail);
1999cb8ef36SMarkus Armbruster     visit_type_int(v, NULL, &tail->value, &error_abort);
2009cb8ef36SMarkus Armbruster     g_assert_cmpint(tail->value, ==, 1);
2019cb8ef36SMarkus Armbruster     tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));
2029cb8ef36SMarkus Armbruster     g_assert(tail);
203*21f88d02SEric Blake     visit_check_list(v, &error_abort); /* unvisited tail ignored until... */
2049cb8ef36SMarkus Armbruster     visit_end_list(v, (void **)&list);
2059cb8ef36SMarkus Armbruster 
206*21f88d02SEric Blake     visit_check_struct(v, &err); /* ...here */
207*21f88d02SEric Blake     error_free_or_abort(&err);
2089cb8ef36SMarkus Armbruster     visit_end_struct(v, NULL);
2099cb8ef36SMarkus Armbruster 
2109cb8ef36SMarkus Armbruster     qapi_free_intList(list);
2119cb8ef36SMarkus Armbruster     visit_free(v);
2129cb8ef36SMarkus Armbruster     qemu_opts_del(opts);
2139cb8ef36SMarkus Armbruster }
2149cb8ef36SMarkus Armbruster 
215a9416dc6SMarkus Armbruster static void
test_opts_range_beyond(void)216a9416dc6SMarkus Armbruster test_opts_range_beyond(void)
217a9416dc6SMarkus Armbruster {
218a9416dc6SMarkus Armbruster     Error *err = NULL;
219a9416dc6SMarkus Armbruster     intList *list = NULL;
220a9416dc6SMarkus Armbruster     intList *tail;
221a9416dc6SMarkus Armbruster     QemuOpts *opts;
222a9416dc6SMarkus Armbruster     Visitor *v;
223a9416dc6SMarkus Armbruster     int64_t val;
224a9416dc6SMarkus Armbruster 
225a9416dc6SMarkus Armbruster     opts = qemu_opts_parse(qemu_find_opts("userdef"), "ilist=0", false,
226a9416dc6SMarkus Armbruster                            &error_abort);
227a9416dc6SMarkus Armbruster 
228a9416dc6SMarkus Armbruster     v = opts_visitor_new(opts);
229a9416dc6SMarkus Armbruster 
230a9416dc6SMarkus Armbruster     visit_start_struct(v, NULL, NULL, 0, &error_abort);
231a9416dc6SMarkus Armbruster 
232a9416dc6SMarkus Armbruster     /* Would be simpler if the visitor genuinely supported virtual walks */
233a9416dc6SMarkus Armbruster     visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list),
234a9416dc6SMarkus Armbruster                      &error_abort);
235a9416dc6SMarkus Armbruster     tail = list;
236a9416dc6SMarkus Armbruster     visit_type_int(v, NULL, &tail->value, &error_abort);
237a9416dc6SMarkus Armbruster     g_assert_cmpint(tail->value, ==, 0);
238a9416dc6SMarkus Armbruster     tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*tail));
239a9416dc6SMarkus Armbruster     g_assert(!tail);
240a9416dc6SMarkus Armbruster     visit_type_int(v, NULL, &val, &err);
241a9416dc6SMarkus Armbruster     error_free_or_abort(&err);
242a9416dc6SMarkus Armbruster     visit_end_list(v, (void **)&list);
243a9416dc6SMarkus Armbruster 
244a9416dc6SMarkus Armbruster     visit_check_struct(v, &error_abort);
245a9416dc6SMarkus Armbruster     visit_end_struct(v, NULL);
246a9416dc6SMarkus Armbruster 
247a9416dc6SMarkus Armbruster     qapi_free_intList(list);
248a9416dc6SMarkus Armbruster     visit_free(v);
249a9416dc6SMarkus Armbruster     qemu_opts_del(opts);
250a9416dc6SMarkus Armbruster }
251a9416dc6SMarkus Armbruster 
25276861f6bSEric Blake static void
test_opts_dict_unvisited(void)25376861f6bSEric Blake test_opts_dict_unvisited(void)
25476861f6bSEric Blake {
255*21f88d02SEric Blake     Error *err = NULL;
25676861f6bSEric Blake     QemuOpts *opts;
25776861f6bSEric Blake     Visitor *v;
25876861f6bSEric Blake     UserDefOptions *userdef;
25976861f6bSEric Blake 
26076861f6bSEric Blake     opts = qemu_opts_parse(qemu_find_opts("userdef"), "i64x=0,bogus=1", false,
26176861f6bSEric Blake                            &error_abort);
26276861f6bSEric Blake 
26376861f6bSEric Blake     v = opts_visitor_new(opts);
264*21f88d02SEric Blake     visit_type_UserDefOptions(v, NULL, &userdef, &err);
265*21f88d02SEric Blake     error_free_or_abort(&err);
26676861f6bSEric Blake     visit_free(v);
26776861f6bSEric Blake     qemu_opts_del(opts);
268*21f88d02SEric Blake     g_assert(!userdef);
26976861f6bSEric Blake }
27076861f6bSEric Blake 
2713953e3a5SLaszlo Ersek int
main(int argc,char ** argv)2723953e3a5SLaszlo Ersek main(int argc, char **argv)
2733953e3a5SLaszlo Ersek {
2743953e3a5SLaszlo Ersek     g_test_init(&argc, &argv, NULL);
2753953e3a5SLaszlo Ersek 
2763953e3a5SLaszlo Ersek     qemu_add_opts(&userdef_opts);
2773953e3a5SLaszlo Ersek 
2783953e3a5SLaszlo Ersek     /* Three hexadecimal magic numbers, "dead beef", "bad coffee, odd food" and
2793953e3a5SLaszlo Ersek      * "disease", from
2803953e3a5SLaszlo Ersek      * <http://en.wikipedia.org/wiki/Magic_number_%28programming%29>, were
2813953e3a5SLaszlo Ersek      * converted to binary and dissected into bit ranges. Each magic number is
2823953e3a5SLaszlo Ersek      * going to be recomposed using the lists called "i64", "u64" and "u16",
2833953e3a5SLaszlo Ersek      * respectively.
2843953e3a5SLaszlo Ersek      *
2853953e3a5SLaszlo Ersek      * (Note that these types pertain to the individual bit shift counts, not
2863953e3a5SLaszlo Ersek      * the magic numbers themselves; the intent is to exercise opts_type_int()
2873953e3a5SLaszlo Ersek      * and opts_type_uint64().)
2883953e3a5SLaszlo Ersek      *
2893953e3a5SLaszlo Ersek      * The "i64" shift counts have been decreased by 16 (decimal) in order to
2903953e3a5SLaszlo Ersek      * test negative values as well. Finally, the full list of QemuOpt elements
2913953e3a5SLaszlo Ersek      * has been permuted with "shuf".
2923953e3a5SLaszlo Ersek      *
2933953e3a5SLaszlo Ersek      * Both "i64" and "u64" have some (distinct) single-element ranges
2943953e3a5SLaszlo Ersek      * represented as both "a" and "a-a". "u16" is a special case of "i64" (see
2953953e3a5SLaszlo Ersek      * visit_type_uint16()), so it wouldn't add a separate test in this regard.
2963953e3a5SLaszlo Ersek      */
2973953e3a5SLaszlo Ersek 
2983953e3a5SLaszlo Ersek     add_test("/visitor/opts/flatten/value", &test_value,
2993953e3a5SLaszlo Ersek              "i64=-1-0,u64=12-16,u64=2-3,i64=-11--9,u64=57,u16=9,i64=5-5,"
3003953e3a5SLaszlo Ersek              "u16=1-4,u16=20,u64=63-63,i64=-16--13,u64=50-52,i64=14-15,u16=11,"
3013953e3a5SLaszlo Ersek              "i64=7,u16=18,i64=2-3,u16=6,u64=54-55,u64=0,u64=18-20,u64=33-43,"
3023953e3a5SLaszlo Ersek              "i64=9-12,u16=26-27,u64=59-61,u16=13-16,u64=29-31,u64=22-23,"
3033953e3a5SLaszlo Ersek              "u16=24,i64=-7--3");
3043953e3a5SLaszlo Ersek 
3053953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val1/errno",    &expect_fail,
3063953e3a5SLaszlo Ersek              "i64=0x8000000000000000");
3073953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val1/empty",    &expect_fail, "i64=");
3083953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val1/trailing", &expect_fail, "i64=5z");
3093953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/nonlist",       &expect_fail, "i64x=5-6");
3103953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val2/errno",    &expect_fail,
3113953e3a5SLaszlo Ersek              "i64=0x7fffffffffffffff-0x8000000000000000");
3123953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val2/empty",    &expect_fail, "i64=5-");
3133953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val2/trailing", &expect_fail, "i64=5-6z");
3143953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/empty",   &expect_fail, "i64=6-5");
3153953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/minval",  &expect_i64_min,
3163953e3a5SLaszlo Ersek              "i64=-0x8000000000000000--0x8000000000000000");
3173953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/maxval",  &expect_i64_max,
3183953e3a5SLaszlo Ersek              "i64=0x7fffffffffffffff-0x7fffffffffffffff");
3193953e3a5SLaszlo Ersek 
3203953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val1/errno",    &expect_fail, "u64=-1");
3213953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val1/empty",    &expect_fail, "u64=");
3223953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val1/trailing", &expect_fail, "u64=5z");
3233953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/nonlist",       &expect_fail, "u64x=5-6");
3243953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val2/errno",    &expect_fail,
3253953e3a5SLaszlo Ersek              "u64=0xffffffffffffffff-0x10000000000000000");
3263953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val2/empty",    &expect_fail, "u64=5-");
3273953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val2/trailing", &expect_fail, "u64=5-6z");
3283953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/empty",   &expect_fail, "u64=6-5");
3293953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/minval",  &expect_zero, "u64=0-0");
3303953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/maxval",  &expect_u64_max,
3313953e3a5SLaszlo Ersek              "u64=0xffffffffffffffff-0xffffffffffffffff");
3323953e3a5SLaszlo Ersek 
3333953e3a5SLaszlo Ersek     /* Test maximum range sizes. The macro value is open-coded here
3343953e3a5SLaszlo Ersek      * *intentionally*; the test case must use concrete values by design. If
3353953e3a5SLaszlo Ersek      * OPTS_VISITOR_RANGE_MAX is changed, the following values need to be
3363953e3a5SLaszlo Ersek      * recalculated as well. The assert and this comment should help with it.
3373953e3a5SLaszlo Ersek      */
3383953e3a5SLaszlo Ersek     g_assert(OPTS_VISITOR_RANGE_MAX == 65536);
3393953e3a5SLaszlo Ersek 
3403953e3a5SLaszlo Ersek     /* The unsigned case is simple, a u64-u64 difference can always be
3413953e3a5SLaszlo Ersek      * represented as a u64.
3423953e3a5SLaszlo Ersek      */
3433953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/max",  &expect_ok,   "u64=0-65535");
3443953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/2big", &expect_fail, "u64=0-65536");
3453953e3a5SLaszlo Ersek 
3463953e3a5SLaszlo Ersek     /* The same cannot be said about an i64-i64 difference. */
3473953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/max/pos/a", &expect_ok,
3483953e3a5SLaszlo Ersek              "i64=0x7fffffffffff0000-0x7fffffffffffffff");
3493953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/max/pos/b", &expect_ok,
3503953e3a5SLaszlo Ersek              "i64=0x7ffffffffffeffff-0x7ffffffffffffffe");
3513953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/2big/pos",  &expect_fail,
3523953e3a5SLaszlo Ersek              "i64=0x7ffffffffffeffff-0x7fffffffffffffff");
3533953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/max/neg/a", &expect_ok,
3543953e3a5SLaszlo Ersek              "i64=-0x8000000000000000--0x7fffffffffff0001");
3553953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/max/neg/b", &expect_ok,
3563953e3a5SLaszlo Ersek              "i64=-0x7fffffffffffffff--0x7fffffffffff0000");
3573953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/2big/neg",  &expect_fail,
3583953e3a5SLaszlo Ersek              "i64=-0x8000000000000000--0x7fffffffffff0000");
3593953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/2big/full", &expect_fail,
3603953e3a5SLaszlo Ersek              "i64=-0x8000000000000000-0x7fffffffffffffff");
3613953e3a5SLaszlo Ersek 
3629cb8ef36SMarkus Armbruster     g_test_add_func("/visitor/opts/range/unvisited",
3639cb8ef36SMarkus Armbruster                     test_opts_range_unvisited);
364a9416dc6SMarkus Armbruster     g_test_add_func("/visitor/opts/range/beyond",
365a9416dc6SMarkus Armbruster                     test_opts_range_beyond);
3669cb8ef36SMarkus Armbruster 
36776861f6bSEric Blake     g_test_add_func("/visitor/opts/dict/unvisited", test_opts_dict_unvisited);
36876861f6bSEric Blake 
3693953e3a5SLaszlo Ersek     g_test_run();
3703953e3a5SLaszlo Ersek     return 0;
3713953e3a5SLaszlo Ersek }
372