xref: /qemu/tests/unit/test-opts-visitor.c (revision 9cb8ef36681b9645af1f7bd8fb64656e65de8a03)
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
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
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
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
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
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
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
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
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
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
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 
175*9cb8ef36SMarkus Armbruster static void
176*9cb8ef36SMarkus Armbruster test_opts_range_unvisited(void)
177*9cb8ef36SMarkus Armbruster {
178*9cb8ef36SMarkus Armbruster     intList *list = NULL;
179*9cb8ef36SMarkus Armbruster     intList *tail;
180*9cb8ef36SMarkus Armbruster     QemuOpts *opts;
181*9cb8ef36SMarkus Armbruster     Visitor *v;
182*9cb8ef36SMarkus Armbruster 
183*9cb8ef36SMarkus Armbruster     opts = qemu_opts_parse(qemu_find_opts("userdef"), "ilist=0-2", false,
184*9cb8ef36SMarkus Armbruster                            &error_abort);
185*9cb8ef36SMarkus Armbruster 
186*9cb8ef36SMarkus Armbruster     v = opts_visitor_new(opts);
187*9cb8ef36SMarkus Armbruster 
188*9cb8ef36SMarkus Armbruster     visit_start_struct(v, NULL, NULL, 0, &error_abort);
189*9cb8ef36SMarkus Armbruster 
190*9cb8ef36SMarkus Armbruster     /* Would be simpler if the visitor genuinely supported virtual walks */
191*9cb8ef36SMarkus Armbruster     visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list),
192*9cb8ef36SMarkus Armbruster                      &error_abort);
193*9cb8ef36SMarkus Armbruster     tail = list;
194*9cb8ef36SMarkus Armbruster     visit_type_int(v, NULL, &tail->value, &error_abort);
195*9cb8ef36SMarkus Armbruster     g_assert_cmpint(tail->value, ==, 0);
196*9cb8ef36SMarkus Armbruster     tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));
197*9cb8ef36SMarkus Armbruster     g_assert(tail);
198*9cb8ef36SMarkus Armbruster     visit_type_int(v, NULL, &tail->value, &error_abort);
199*9cb8ef36SMarkus Armbruster     g_assert_cmpint(tail->value, ==, 1);
200*9cb8ef36SMarkus Armbruster     tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));
201*9cb8ef36SMarkus Armbruster     g_assert(tail);
202*9cb8ef36SMarkus Armbruster     visit_end_list(v, (void **)&list);
203*9cb8ef36SMarkus Armbruster     /* BUG: unvisited tail not reported; actually not reportable by design */
204*9cb8ef36SMarkus Armbruster 
205*9cb8ef36SMarkus Armbruster     visit_check_struct(v, &error_abort);
206*9cb8ef36SMarkus Armbruster     visit_end_struct(v, NULL);
207*9cb8ef36SMarkus Armbruster 
208*9cb8ef36SMarkus Armbruster     qapi_free_intList(list);
209*9cb8ef36SMarkus Armbruster     visit_free(v);
210*9cb8ef36SMarkus Armbruster     qemu_opts_del(opts);
211*9cb8ef36SMarkus Armbruster }
212*9cb8ef36SMarkus Armbruster 
2133953e3a5SLaszlo Ersek int
2143953e3a5SLaszlo Ersek main(int argc, char **argv)
2153953e3a5SLaszlo Ersek {
2163953e3a5SLaszlo Ersek     g_test_init(&argc, &argv, NULL);
2173953e3a5SLaszlo Ersek 
2183953e3a5SLaszlo Ersek     qemu_add_opts(&userdef_opts);
2193953e3a5SLaszlo Ersek 
2203953e3a5SLaszlo Ersek     /* Three hexadecimal magic numbers, "dead beef", "bad coffee, odd food" and
2213953e3a5SLaszlo Ersek      * "disease", from
2223953e3a5SLaszlo Ersek      * <http://en.wikipedia.org/wiki/Magic_number_%28programming%29>, were
2233953e3a5SLaszlo Ersek      * converted to binary and dissected into bit ranges. Each magic number is
2243953e3a5SLaszlo Ersek      * going to be recomposed using the lists called "i64", "u64" and "u16",
2253953e3a5SLaszlo Ersek      * respectively.
2263953e3a5SLaszlo Ersek      *
2273953e3a5SLaszlo Ersek      * (Note that these types pertain to the individual bit shift counts, not
2283953e3a5SLaszlo Ersek      * the magic numbers themselves; the intent is to exercise opts_type_int()
2293953e3a5SLaszlo Ersek      * and opts_type_uint64().)
2303953e3a5SLaszlo Ersek      *
2313953e3a5SLaszlo Ersek      * The "i64" shift counts have been decreased by 16 (decimal) in order to
2323953e3a5SLaszlo Ersek      * test negative values as well. Finally, the full list of QemuOpt elements
2333953e3a5SLaszlo Ersek      * has been permuted with "shuf".
2343953e3a5SLaszlo Ersek      *
2353953e3a5SLaszlo Ersek      * Both "i64" and "u64" have some (distinct) single-element ranges
2363953e3a5SLaszlo Ersek      * represented as both "a" and "a-a". "u16" is a special case of "i64" (see
2373953e3a5SLaszlo Ersek      * visit_type_uint16()), so it wouldn't add a separate test in this regard.
2383953e3a5SLaszlo Ersek      */
2393953e3a5SLaszlo Ersek 
2403953e3a5SLaszlo Ersek     add_test("/visitor/opts/flatten/value", &test_value,
2413953e3a5SLaszlo Ersek              "i64=-1-0,u64=12-16,u64=2-3,i64=-11--9,u64=57,u16=9,i64=5-5,"
2423953e3a5SLaszlo Ersek              "u16=1-4,u16=20,u64=63-63,i64=-16--13,u64=50-52,i64=14-15,u16=11,"
2433953e3a5SLaszlo Ersek              "i64=7,u16=18,i64=2-3,u16=6,u64=54-55,u64=0,u64=18-20,u64=33-43,"
2443953e3a5SLaszlo Ersek              "i64=9-12,u16=26-27,u64=59-61,u16=13-16,u64=29-31,u64=22-23,"
2453953e3a5SLaszlo Ersek              "u16=24,i64=-7--3");
2463953e3a5SLaszlo Ersek 
2473953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val1/errno",    &expect_fail,
2483953e3a5SLaszlo Ersek              "i64=0x8000000000000000");
2493953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val1/empty",    &expect_fail, "i64=");
2503953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val1/trailing", &expect_fail, "i64=5z");
2513953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/nonlist",       &expect_fail, "i64x=5-6");
2523953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val2/errno",    &expect_fail,
2533953e3a5SLaszlo Ersek              "i64=0x7fffffffffffffff-0x8000000000000000");
2543953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val2/empty",    &expect_fail, "i64=5-");
2553953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/val2/trailing", &expect_fail, "i64=5-6z");
2563953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/empty",   &expect_fail, "i64=6-5");
2573953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/minval",  &expect_i64_min,
2583953e3a5SLaszlo Ersek              "i64=-0x8000000000000000--0x8000000000000000");
2593953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/maxval",  &expect_i64_max,
2603953e3a5SLaszlo Ersek              "i64=0x7fffffffffffffff-0x7fffffffffffffff");
2613953e3a5SLaszlo Ersek 
2623953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val1/errno",    &expect_fail, "u64=-1");
2633953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val1/empty",    &expect_fail, "u64=");
2643953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val1/trailing", &expect_fail, "u64=5z");
2653953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/nonlist",       &expect_fail, "u64x=5-6");
2663953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val2/errno",    &expect_fail,
2673953e3a5SLaszlo Ersek              "u64=0xffffffffffffffff-0x10000000000000000");
2683953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val2/empty",    &expect_fail, "u64=5-");
2693953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/val2/trailing", &expect_fail, "u64=5-6z");
2703953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/empty",   &expect_fail, "u64=6-5");
2713953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/minval",  &expect_zero, "u64=0-0");
2723953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/maxval",  &expect_u64_max,
2733953e3a5SLaszlo Ersek              "u64=0xffffffffffffffff-0xffffffffffffffff");
2743953e3a5SLaszlo Ersek 
2753953e3a5SLaszlo Ersek     /* Test maximum range sizes. The macro value is open-coded here
2763953e3a5SLaszlo Ersek      * *intentionally*; the test case must use concrete values by design. If
2773953e3a5SLaszlo Ersek      * OPTS_VISITOR_RANGE_MAX is changed, the following values need to be
2783953e3a5SLaszlo Ersek      * recalculated as well. The assert and this comment should help with it.
2793953e3a5SLaszlo Ersek      */
2803953e3a5SLaszlo Ersek     g_assert(OPTS_VISITOR_RANGE_MAX == 65536);
2813953e3a5SLaszlo Ersek 
2823953e3a5SLaszlo Ersek     /* The unsigned case is simple, a u64-u64 difference can always be
2833953e3a5SLaszlo Ersek      * represented as a u64.
2843953e3a5SLaszlo Ersek      */
2853953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/max",  &expect_ok,   "u64=0-65535");
2863953e3a5SLaszlo Ersek     add_test("/visitor/opts/u64/range/2big", &expect_fail, "u64=0-65536");
2873953e3a5SLaszlo Ersek 
2883953e3a5SLaszlo Ersek     /* The same cannot be said about an i64-i64 difference. */
2893953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/max/pos/a", &expect_ok,
2903953e3a5SLaszlo Ersek              "i64=0x7fffffffffff0000-0x7fffffffffffffff");
2913953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/max/pos/b", &expect_ok,
2923953e3a5SLaszlo Ersek              "i64=0x7ffffffffffeffff-0x7ffffffffffffffe");
2933953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/2big/pos",  &expect_fail,
2943953e3a5SLaszlo Ersek              "i64=0x7ffffffffffeffff-0x7fffffffffffffff");
2953953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/max/neg/a", &expect_ok,
2963953e3a5SLaszlo Ersek              "i64=-0x8000000000000000--0x7fffffffffff0001");
2973953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/max/neg/b", &expect_ok,
2983953e3a5SLaszlo Ersek              "i64=-0x7fffffffffffffff--0x7fffffffffff0000");
2993953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/2big/neg",  &expect_fail,
3003953e3a5SLaszlo Ersek              "i64=-0x8000000000000000--0x7fffffffffff0000");
3013953e3a5SLaszlo Ersek     add_test("/visitor/opts/i64/range/2big/full", &expect_fail,
3023953e3a5SLaszlo Ersek              "i64=-0x8000000000000000-0x7fffffffffffffff");
3033953e3a5SLaszlo Ersek 
304*9cb8ef36SMarkus Armbruster     g_test_add_func("/visitor/opts/range/unvisited",
305*9cb8ef36SMarkus Armbruster                     test_opts_range_unvisited);
306*9cb8ef36SMarkus Armbruster 
3073953e3a5SLaszlo Ersek     g_test_run();
3083953e3a5SLaszlo Ersek     return 0;
3093953e3a5SLaszlo Ersek }
310