Now that all code has been converted to QObjectInputVisitor's QemuOpts compatibility mode, there is no longer any reason to keep OptsVisitor alive.
Signed-off-by: Daniel P. Berrange <berra...@redhat.com> --- include/qapi/opts-visitor.h | 40 ---- qapi/Makefile.objs | 2 +- qapi/opts-visitor.c | 544 -------------------------------------------- tests/Makefile.include | 5 +- tests/test-opts-visitor.c | 268 ---------------------- vl.c | 1 - 6 files changed, 2 insertions(+), 858 deletions(-) delete mode 100644 include/qapi/opts-visitor.h delete mode 100644 qapi/opts-visitor.c delete mode 100644 tests/test-opts-visitor.c diff --git a/include/qapi/opts-visitor.h b/include/qapi/opts-visitor.h deleted file mode 100644 index 6462c96..0000000 --- a/include/qapi/opts-visitor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Options Visitor - * - * Copyright Red Hat, Inc. 2012 - * - * Author: Laszlo Ersek <ler...@redhat.com> - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ - -#ifndef OPTS_VISITOR_H -#define OPTS_VISITOR_H - -#include "qapi/visitor.h" -#include "qemu/option.h" - -/* Inclusive upper bound on the size of any flattened range. This is a safety - * (= anti-annoyance) measure; wrong ranges should not cause long startup - * delays nor exhaust virtual memory. - */ -#define OPTS_VISITOR_RANGE_MAX 65536 - -typedef struct OptsVisitor OptsVisitor; - -/* Contrarily to qemu-option.c::parse_option_number(), OptsVisitor's "int" - * parser relies on strtoll() instead of strtoull(). Consequences: - * - string representations of negative numbers yield negative values, - * - values below INT64_MIN or LLONG_MIN are rejected, - * - values above INT64_MAX or LLONG_MAX are rejected. - * - * The Opts input visitor does not implement support for visiting QAPI - * alternates, numbers (other than integers), null, or arbitrary - * QTypes. It also requires a non-null list argument to - * visit_start_list(). - */ -Visitor *opts_visitor_new(const QemuOpts *opts); - -#endif diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs index 33906ff..4b820a7 100644 --- a/qapi/Makefile.objs +++ b/qapi/Makefile.objs @@ -1,6 +1,6 @@ util-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qobject-input-visitor.o util-obj-y += qobject-output-visitor.o qmp-registry.o qmp-dispatch.o util-obj-y += string-input-visitor.o string-output-visitor.o -util-obj-y += opts-visitor.o qapi-clone-visitor.o +util-obj-y += qapi-clone-visitor.o util-obj-y += qmp-event.o util-obj-y += qapi-util.o diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c deleted file mode 100644 index 084f7cc..0000000 --- a/qapi/opts-visitor.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Options Visitor - * - * Copyright Red Hat, Inc. 2012-2016 - * - * Author: Laszlo Ersek <ler...@redhat.com> - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu/cutils.h" -#include "qapi/qmp/qerror.h" -#include "qapi/opts-visitor.h" -#include "qemu/queue.h" -#include "qemu/option_int.h" -#include "qapi/visitor-impl.h" - - -enum ListMode -{ - LM_NONE, /* not traversing a list of repeated options */ - - LM_IN_PROGRESS, /* opts_next_list() ready to be called. - * - * Generating the next list link will consume the most - * recently parsed QemuOpt instance of the repeated - * option. - * - * Parsing a value into the list link will examine the - * next QemuOpt instance of the repeated option, and - * possibly enter LM_SIGNED_INTERVAL or - * LM_UNSIGNED_INTERVAL. - */ - - LM_SIGNED_INTERVAL, /* opts_next_list() has been called. - * - * Generating the next list link will consume the most - * recently stored element from the signed interval, - * parsed from the most recent QemuOpt instance of the - * repeated option. This may consume QemuOpt itself - * and return to LM_IN_PROGRESS. - * - * Parsing a value into the list link will store the - * next element of the signed interval. - */ - - LM_UNSIGNED_INTERVAL /* Same as above, only for an unsigned interval. */ -}; - -typedef enum ListMode ListMode; - -struct OptsVisitor -{ - Visitor visitor; - - /* Ownership remains with opts_visitor_new()'s caller. */ - const QemuOpts *opts_root; - - unsigned depth; - - /* Non-null iff depth is positive. Each key is a QemuOpt name. Each value - * is a non-empty GQueue, enumerating all QemuOpt occurrences with that - * name. */ - GHashTable *unprocessed_opts; - - /* The list currently being traversed with opts_start_list() / - * opts_next_list(). The list must have a struct element type in the - * schema, with a single mandatory scalar member. */ - ListMode list_mode; - GQueue *repeated_opts; - - /* When parsing a list of repeating options as integers, values of the form - * "a-b", representing a closed interval, are allowed. Elements in the - * range are generated individually. - */ - union { - int64_t s; - uint64_t u; - } range_next, range_limit; - - /* If "opts_root->id" is set, reinstantiate it as a fake QemuOpt for - * uniformity. Only its "name" and "str" fields are set. "fake_id_opt" does - * not survive or escape the OptsVisitor object. - */ - QemuOpt *fake_id_opt; -}; - - -static OptsVisitor *to_ov(Visitor *v) -{ - return container_of(v, OptsVisitor, visitor); -} - - -static void -destroy_list(gpointer list) -{ - g_queue_free(list); -} - - -static void -opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt) -{ - GQueue *list; - - list = g_hash_table_lookup(unprocessed_opts, opt->name); - if (list == NULL) { - list = g_queue_new(); - - /* GHashTable will never try to free the keys -- we supply NULL as - * "key_destroy_func" in opts_start_struct(). Thus cast away key - * const-ness in order to suppress gcc's warning. - */ - g_hash_table_insert(unprocessed_opts, (gpointer)opt->name, list); - } - - /* Similarly, destroy_list() doesn't call g_queue_free_full(). */ - g_queue_push_tail(list, (gpointer)opt); -} - - -static void -opts_start_struct(Visitor *v, const char *name, void **obj, - size_t size, Error **errp) -{ - OptsVisitor *ov = to_ov(v); - const QemuOpt *opt; - - if (obj) { - *obj = g_malloc0(size); - } - if (ov->depth++ > 0) { - return; - } - - ov->unprocessed_opts = g_hash_table_new_full(&g_str_hash, &g_str_equal, - NULL, &destroy_list); - QTAILQ_FOREACH(opt, &ov->opts_root->head, next) { - /* ensured by qemu-option.c::opts_do_parse() */ - assert(strcmp(opt->name, "id") != 0); - - opts_visitor_insert(ov->unprocessed_opts, opt); - } - - if (ov->opts_root->id != NULL) { - ov->fake_id_opt = g_malloc0(sizeof *ov->fake_id_opt); - - ov->fake_id_opt->name = g_strdup("id"); - ov->fake_id_opt->str = g_strdup(ov->opts_root->id); - opts_visitor_insert(ov->unprocessed_opts, ov->fake_id_opt); - } -} - - -static void -opts_check_struct(Visitor *v, Error **errp) -{ - OptsVisitor *ov = to_ov(v); - GHashTableIter iter; - GQueue *any; - - if (ov->depth > 0) { - return; - } - - /* we should have processed all (distinct) QemuOpt instances */ - g_hash_table_iter_init(&iter, ov->unprocessed_opts); - if (g_hash_table_iter_next(&iter, NULL, (void **)&any)) { - const QemuOpt *first; - - first = g_queue_peek_head(any); - error_setg(errp, QERR_INVALID_PARAMETER, first->name); - } -} - - -static void -opts_end_struct(Visitor *v, void **obj) -{ - OptsVisitor *ov = to_ov(v); - - if (--ov->depth > 0) { - return; - } - - g_hash_table_destroy(ov->unprocessed_opts); - ov->unprocessed_opts = NULL; - if (ov->fake_id_opt) { - g_free(ov->fake_id_opt->name); - g_free(ov->fake_id_opt->str); - g_free(ov->fake_id_opt); - } - ov->fake_id_opt = NULL; -} - - -static GQueue * -lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp) -{ - GQueue *list; - - list = g_hash_table_lookup(ov->unprocessed_opts, name); - if (!list) { - error_setg(errp, QERR_MISSING_PARAMETER, name); - } - return list; -} - - -static void -opts_start_list(Visitor *v, const char *name, GenericList **list, size_t size, - Error **errp) -{ - OptsVisitor *ov = to_ov(v); - - /* we can't traverse a list in a list */ - assert(ov->list_mode == LM_NONE); - /* we don't support visits without a list */ - assert(list); - ov->repeated_opts = lookup_distinct(ov, name, errp); - if (ov->repeated_opts) { - ov->list_mode = LM_IN_PROGRESS; - *list = g_malloc0(size); - } else { - *list = NULL; - } -} - - -static GenericList * -opts_next_list(Visitor *v, GenericList *tail, size_t size) -{ - OptsVisitor *ov = to_ov(v); - - switch (ov->list_mode) { - case LM_SIGNED_INTERVAL: - case LM_UNSIGNED_INTERVAL: - if (ov->list_mode == LM_SIGNED_INTERVAL) { - if (ov->range_next.s < ov->range_limit.s) { - ++ov->range_next.s; - break; - } - } else if (ov->range_next.u < ov->range_limit.u) { - ++ov->range_next.u; - break; - } - ov->list_mode = LM_IN_PROGRESS; - /* range has been completed, fall through in order to pop option */ - - case LM_IN_PROGRESS: { - const QemuOpt *opt; - - opt = g_queue_pop_head(ov->repeated_opts); - if (g_queue_is_empty(ov->repeated_opts)) { - g_hash_table_remove(ov->unprocessed_opts, opt->name); - return NULL; - } - break; - } - - default: - abort(); - } - - tail->next = g_malloc0(size); - return tail->next; -} - - -static void -opts_end_list(Visitor *v, void **obj) -{ - OptsVisitor *ov = to_ov(v); - - assert(ov->list_mode == LM_IN_PROGRESS || - ov->list_mode == LM_SIGNED_INTERVAL || - ov->list_mode == LM_UNSIGNED_INTERVAL); - ov->repeated_opts = NULL; - ov->list_mode = LM_NONE; -} - - -static const QemuOpt * -lookup_scalar(const OptsVisitor *ov, const char *name, Error **errp) -{ - if (ov->list_mode == LM_NONE) { - GQueue *list; - - /* the last occurrence of any QemuOpt takes effect when queried by name - */ - list = lookup_distinct(ov, name, errp); - return list ? g_queue_peek_tail(list) : NULL; - } - assert(ov->list_mode == LM_IN_PROGRESS); - return g_queue_peek_head(ov->repeated_opts); -} - - -static void -processed(OptsVisitor *ov, const char *name) -{ - if (ov->list_mode == LM_NONE) { - g_hash_table_remove(ov->unprocessed_opts, name); - return; - } - assert(ov->list_mode == LM_IN_PROGRESS); - /* do nothing */ -} - - -static void -opts_type_str(Visitor *v, const char *name, char **obj, Error **errp) -{ - OptsVisitor *ov = to_ov(v); - const QemuOpt *opt; - - opt = lookup_scalar(ov, name, errp); - if (!opt) { - *obj = NULL; - return; - } - *obj = g_strdup(opt->str ? opt->str : ""); - /* Note that we consume a string even if this is called as part of - * an enum visit that later fails because the string is not a - * valid enum value; this is harmless because tracking what gets - * consumed only matters to visit_end_struct() as the final error - * check if there were no other failures during the visit. */ - processed(ov, name); -} - - -static void -opts_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) -{ - OptsVisitor *ov = to_ov(v); - const QemuOpt *opt; - - opt = lookup_scalar(ov, name, errp); - if (!opt) { - return; - } - - parse_option_bool(opt->name, opt->str, obj, errp); - - processed(ov, name); -} - - -static void -opts_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) -{ - OptsVisitor *ov = to_ov(v); - const QemuOpt *opt; - const char *str; - long long val; - char *endptr; - - if (ov->list_mode == LM_SIGNED_INTERVAL) { - *obj = ov->range_next.s; - return; - } - - opt = lookup_scalar(ov, name, errp); - if (!opt) { - return; - } - str = opt->str ? opt->str : ""; - - /* we've gotten past lookup_scalar() */ - assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS); - - errno = 0; - val = strtoll(str, &endptr, 0); - if (errno == 0 && endptr > str && INT64_MIN <= val && val <= INT64_MAX) { - if (*endptr == '\0') { - *obj = val; - processed(ov, name); - return; - } - if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) { - long long val2; - - str = endptr + 1; - val2 = strtoll(str, &endptr, 0); - if (errno == 0 && endptr > str && *endptr == '\0' && - INT64_MIN <= val2 && val2 <= INT64_MAX && val <= val2 && - (val > INT64_MAX - OPTS_VISITOR_RANGE_MAX || - val2 < val + OPTS_VISITOR_RANGE_MAX)) { - ov->range_next.s = val; - ov->range_limit.s = val2; - ov->list_mode = LM_SIGNED_INTERVAL; - - /* as if entering on the top */ - *obj = ov->range_next.s; - return; - } - } - } - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, - (ov->list_mode == LM_NONE) ? "an int64 value" : - "an int64 value or range"); -} - - -static void -opts_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp) -{ - OptsVisitor *ov = to_ov(v); - const QemuOpt *opt; - const char *str; - unsigned long long val; - char *endptr; - - if (ov->list_mode == LM_UNSIGNED_INTERVAL) { - *obj = ov->range_next.u; - return; - } - - opt = lookup_scalar(ov, name, errp); - if (!opt) { - return; - } - str = opt->str; - - /* we've gotten past lookup_scalar() */ - assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS); - - if (parse_uint(str, &val, &endptr, 0) == 0 && val <= UINT64_MAX) { - if (*endptr == '\0') { - *obj = val; - processed(ov, name); - return; - } - if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) { - unsigned long long val2; - - str = endptr + 1; - if (parse_uint_full(str, &val2, 0) == 0 && - val2 <= UINT64_MAX && val <= val2 && - val2 - val < OPTS_VISITOR_RANGE_MAX) { - ov->range_next.u = val; - ov->range_limit.u = val2; - ov->list_mode = LM_UNSIGNED_INTERVAL; - - /* as if entering on the top */ - *obj = ov->range_next.u; - return; - } - } - } - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, - (ov->list_mode == LM_NONE) ? "a uint64 value" : - "a uint64 value or range"); -} - - -static void -opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp) -{ - OptsVisitor *ov = to_ov(v); - const QemuOpt *opt; - int64_t val; - char *endptr; - - opt = lookup_scalar(ov, name, errp); - if (!opt) { - return; - } - - val = qemu_strtosz_suffix(opt->str ? opt->str : "", &endptr, - QEMU_STRTOSZ_DEFSUFFIX_B); - if (val < 0 || *endptr) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, - "a size value representible as a non-negative int64"); - return; - } - - *obj = val; - processed(ov, name); -} - - -static void -opts_optional(Visitor *v, const char *name, bool *present) -{ - OptsVisitor *ov = to_ov(v); - - /* we only support a single mandatory scalar field in a list node */ - assert(ov->list_mode == LM_NONE); - *present = (lookup_distinct(ov, name, NULL) != NULL); -} - - -static void -opts_free(Visitor *v) -{ - OptsVisitor *ov = to_ov(v); - - if (ov->unprocessed_opts != NULL) { - g_hash_table_destroy(ov->unprocessed_opts); - } - g_free(ov->fake_id_opt); - g_free(ov); -} - - -Visitor * -opts_visitor_new(const QemuOpts *opts) -{ - OptsVisitor *ov; - - ov = g_malloc0(sizeof *ov); - - ov->visitor.type = VISITOR_INPUT; - - ov->visitor.start_struct = &opts_start_struct; - ov->visitor.check_struct = &opts_check_struct; - ov->visitor.end_struct = &opts_end_struct; - - ov->visitor.start_list = &opts_start_list; - ov->visitor.next_list = &opts_next_list; - ov->visitor.end_list = &opts_end_list; - - ov->visitor.type_int64 = &opts_type_int64; - ov->visitor.type_uint64 = &opts_type_uint64; - ov->visitor.type_size = &opts_type_size; - ov->visitor.type_bool = &opts_type_bool; - ov->visitor.type_str = &opts_type_str; - - /* type_number() is not filled in, but this is not the first visitor to - * skip some mandatory methods... */ - - ov->visitor.optional = &opts_optional; - ov->visitor.free = opts_free; - - ov->opts_root = opts; - - return &ov->visitor; -} diff --git a/tests/Makefile.include b/tests/Makefile.include index 72f71ea..df39976 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -35,8 +35,6 @@ check-unit-y += tests/test-string-output-visitor$(EXESUF) gcov-files-test-string-output-visitor-y = qapi/string-output-visitor.c check-unit-y += tests/test-qmp-event$(EXESUF) gcov-files-test-qmp-event-y += qapi/qmp-event.c -check-unit-y += tests/test-opts-visitor$(EXESUF) -gcov-files-test-opts-visitor-y = qapi/opts-visitor.c check-unit-y += tests/test-coroutine$(EXESUF) gcov-files-test-coroutine-y = coroutine-$(CONFIG_COROUTINE_BACKEND).c check-unit-y += tests/test-visitor-serialization$(EXESUF) @@ -445,7 +443,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \ tests/test-qobject-input-visitor.o tests/test-qobject-input-strict.o \ tests/test-qmp-commands.o tests/test-visitor-serialization.o \ tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \ - tests/test-opts-visitor.o tests/test-qmp-event.o \ + tests/test-qmp-event.o \ tests/rcutorture.o tests/test-rcu-list.o \ tests/test-qdist.o \ tests/test-qht.o tests/qht-bench.o tests/test-qht-par.o @@ -549,7 +547,6 @@ tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $( tests/test-qobject-input-strict$(EXESUF): tests/test-qobject-input-strict.o $(test-qapi-obj-y) tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y) tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y) -tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y) tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y) diff --git a/tests/test-opts-visitor.c b/tests/test-opts-visitor.c deleted file mode 100644 index 0a9e75f..0000000 --- a/tests/test-opts-visitor.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Options Visitor unit-tests. - * - * Copyright (C) 2013 Red Hat, Inc. - * - * Authors: - * Laszlo Ersek <ler...@redhat.com> (based on test-string-output-visitor) - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" - -#include "qemu/config-file.h" /* qemu_add_opts() */ -#include "qemu/option.h" /* qemu_opts_parse() */ -#include "qapi/error.h" -#include "qapi/opts-visitor.h" /* opts_visitor_new() */ -#include "test-qapi-visit.h" /* visit_type_UserDefOptions() */ - -static QemuOptsList userdef_opts = { - .name = "userdef", - .head = QTAILQ_HEAD_INITIALIZER(userdef_opts.head), - .desc = { { 0 } } /* validated with OptsVisitor */ -}; - -/* fixture (= glib test case context) and test case manipulation */ - -typedef struct OptsVisitorFixture { - UserDefOptions *userdef; - Error *err; -} OptsVisitorFixture; - - -static void -setup_fixture(OptsVisitorFixture *f, gconstpointer test_data) -{ - const char *opts_string = test_data; - QemuOpts *opts; - Visitor *v; - - opts = qemu_opts_parse(qemu_find_opts("userdef"), opts_string, false, - NULL); - g_assert(opts != NULL); - - v = opts_visitor_new(opts); - visit_type_UserDefOptions(v, NULL, &f->userdef, &f->err); - visit_free(v); - qemu_opts_del(opts); -} - - -static void -teardown_fixture(OptsVisitorFixture *f, gconstpointer test_data) -{ - qapi_free_UserDefOptions(f->userdef); - error_free(f->err); -} - - -static void -add_test(const char *testpath, - void (*test_func)(OptsVisitorFixture *f, gconstpointer test_data), - gconstpointer test_data) -{ - g_test_add(testpath, OptsVisitorFixture, test_data, setup_fixture, - test_func, teardown_fixture); -} - -/* test output evaluation */ - -static void -expect_ok(OptsVisitorFixture *f, gconstpointer test_data) -{ - g_assert(f->err == NULL); - g_assert(f->userdef != NULL); -} - - -static void -expect_fail(OptsVisitorFixture *f, gconstpointer test_data) -{ - g_assert(f->err != NULL); - - /* The error message is printed when this test utility is invoked directly - * (ie. without gtester) and the --verbose flag is passed: - * - * tests/test-opts-visitor --verbose - */ - g_test_message("'%s': %s", (const char *)test_data, - error_get_pretty(f->err)); -} - - -static void -test_value(OptsVisitorFixture *f, gconstpointer test_data) -{ - uint64_t magic, bitval; - intList *i64; - uint64List *u64; - uint16List *u16; - - expect_ok(f, test_data); - - magic = 0; - for (i64 = f->userdef->i64; i64 != NULL; i64 = i64->next) { - g_assert(-16 <= i64->value && i64->value < 64-16); - bitval = 1ull << (i64->value + 16); - g_assert((magic & bitval) == 0); - magic |= bitval; - } - g_assert(magic == 0xDEADBEEF); - - magic = 0; - for (u64 = f->userdef->u64; u64 != NULL; u64 = u64->next) { - g_assert(u64->value < 64); - bitval = 1ull << u64->value; - g_assert((magic & bitval) == 0); - magic |= bitval; - } - g_assert(magic == 0xBADC0FFEE0DDF00DULL); - - magic = 0; - for (u16 = f->userdef->u16; u16 != NULL; u16 = u16->next) { - g_assert(u16->value < 64); - bitval = 1ull << u16->value; - g_assert((magic & bitval) == 0); - magic |= bitval; - } - g_assert(magic == 0xD15EA5E); -} - - -static void -expect_i64_min(OptsVisitorFixture *f, gconstpointer test_data) -{ - expect_ok(f, test_data); - g_assert(f->userdef->has_i64); - g_assert(f->userdef->i64->next == NULL); - g_assert(f->userdef->i64->value == INT64_MIN); -} - - -static void -expect_i64_max(OptsVisitorFixture *f, gconstpointer test_data) -{ - expect_ok(f, test_data); - g_assert(f->userdef->has_i64); - g_assert(f->userdef->i64->next == NULL); - g_assert(f->userdef->i64->value == INT64_MAX); -} - - -static void -expect_zero(OptsVisitorFixture *f, gconstpointer test_data) -{ - expect_ok(f, test_data); - g_assert(f->userdef->has_u64); - g_assert(f->userdef->u64->next == NULL); - g_assert(f->userdef->u64->value == 0); -} - - -static void -expect_u64_max(OptsVisitorFixture *f, gconstpointer test_data) -{ - expect_ok(f, test_data); - g_assert(f->userdef->has_u64); - g_assert(f->userdef->u64->next == NULL); - g_assert(f->userdef->u64->value == UINT64_MAX); -} - -/* test cases */ - -int -main(int argc, char **argv) -{ - g_test_init(&argc, &argv, NULL); - - qemu_add_opts(&userdef_opts); - - /* Three hexadecimal magic numbers, "dead beef", "bad coffee, odd food" and - * "disease", from - * <http://en.wikipedia.org/wiki/Magic_number_%28programming%29>, were - * converted to binary and dissected into bit ranges. Each magic number is - * going to be recomposed using the lists called "i64", "u64" and "u16", - * respectively. - * - * (Note that these types pertain to the individual bit shift counts, not - * the magic numbers themselves; the intent is to exercise opts_type_int() - * and opts_type_uint64().) - * - * The "i64" shift counts have been decreased by 16 (decimal) in order to - * test negative values as well. Finally, the full list of QemuOpt elements - * has been permuted with "shuf". - * - * Both "i64" and "u64" have some (distinct) single-element ranges - * represented as both "a" and "a-a". "u16" is a special case of "i64" (see - * visit_type_uint16()), so it wouldn't add a separate test in this regard. - */ - - add_test("/visitor/opts/flatten/value", &test_value, - "i64=-1-0,u64=12-16,u64=2-3,i64=-11--9,u64=57,u16=9,i64=5-5," - "u16=1-4,u16=20,u64=63-63,i64=-16--13,u64=50-52,i64=14-15,u16=11," - "i64=7,u16=18,i64=2-3,u16=6,u64=54-55,u64=0,u64=18-20,u64=33-43," - "i64=9-12,u16=26-27,u64=59-61,u16=13-16,u64=29-31,u64=22-23," - "u16=24,i64=-7--3"); - - add_test("/visitor/opts/i64/val1/errno", &expect_fail, - "i64=0x8000000000000000"); - add_test("/visitor/opts/i64/val1/empty", &expect_fail, "i64="); - add_test("/visitor/opts/i64/val1/trailing", &expect_fail, "i64=5z"); - add_test("/visitor/opts/i64/nonlist", &expect_fail, "i64x=5-6"); - add_test("/visitor/opts/i64/val2/errno", &expect_fail, - "i64=0x7fffffffffffffff-0x8000000000000000"); - add_test("/visitor/opts/i64/val2/empty", &expect_fail, "i64=5-"); - add_test("/visitor/opts/i64/val2/trailing", &expect_fail, "i64=5-6z"); - add_test("/visitor/opts/i64/range/empty", &expect_fail, "i64=6-5"); - add_test("/visitor/opts/i64/range/minval", &expect_i64_min, - "i64=-0x8000000000000000--0x8000000000000000"); - add_test("/visitor/opts/i64/range/maxval", &expect_i64_max, - "i64=0x7fffffffffffffff-0x7fffffffffffffff"); - - add_test("/visitor/opts/u64/val1/errno", &expect_fail, "u64=-1"); - add_test("/visitor/opts/u64/val1/empty", &expect_fail, "u64="); - add_test("/visitor/opts/u64/val1/trailing", &expect_fail, "u64=5z"); - add_test("/visitor/opts/u64/nonlist", &expect_fail, "u64x=5-6"); - add_test("/visitor/opts/u64/val2/errno", &expect_fail, - "u64=0xffffffffffffffff-0x10000000000000000"); - add_test("/visitor/opts/u64/val2/empty", &expect_fail, "u64=5-"); - add_test("/visitor/opts/u64/val2/trailing", &expect_fail, "u64=5-6z"); - add_test("/visitor/opts/u64/range/empty", &expect_fail, "u64=6-5"); - add_test("/visitor/opts/u64/range/minval", &expect_zero, "u64=0-0"); - add_test("/visitor/opts/u64/range/maxval", &expect_u64_max, - "u64=0xffffffffffffffff-0xffffffffffffffff"); - - /* Test maximum range sizes. The macro value is open-coded here - * *intentionally*; the test case must use concrete values by design. If - * OPTS_VISITOR_RANGE_MAX is changed, the following values need to be - * recalculated as well. The assert and this comment should help with it. - */ - g_assert(OPTS_VISITOR_RANGE_MAX == 65536); - - /* The unsigned case is simple, a u64-u64 difference can always be - * represented as a u64. - */ - add_test("/visitor/opts/u64/range/max", &expect_ok, "u64=0-65535"); - add_test("/visitor/opts/u64/range/2big", &expect_fail, "u64=0-65536"); - - /* The same cannot be said about an i64-i64 difference. */ - add_test("/visitor/opts/i64/range/max/pos/a", &expect_ok, - "i64=0x7fffffffffff0000-0x7fffffffffffffff"); - add_test("/visitor/opts/i64/range/max/pos/b", &expect_ok, - "i64=0x7ffffffffffeffff-0x7ffffffffffffffe"); - add_test("/visitor/opts/i64/range/2big/pos", &expect_fail, - "i64=0x7ffffffffffeffff-0x7fffffffffffffff"); - add_test("/visitor/opts/i64/range/max/neg/a", &expect_ok, - "i64=-0x8000000000000000--0x7fffffffffff0001"); - add_test("/visitor/opts/i64/range/max/neg/b", &expect_ok, - "i64=-0x7fffffffffffffff--0x7fffffffffff0000"); - add_test("/visitor/opts/i64/range/2big/neg", &expect_fail, - "i64=-0x8000000000000000--0x7fffffffffff0000"); - add_test("/visitor/opts/i64/range/2big/full", &expect_fail, - "i64=-0x8000000000000000-0x7fffffffffffffff"); - - g_test_run(); - return 0; -} diff --git a/vl.c b/vl.c index ab0349b..3a214c1 100644 --- a/vl.c +++ b/vl.c @@ -115,7 +115,6 @@ int main(int argc, char **argv) #include "ui/qemu-spice.h" #include "qapi/string-input-visitor.h" -#include "qapi/opts-visitor.h" #include "qom/object_interfaces.h" #include "qapi-event.h" #include "exec/semihost.h" -- 2.7.4