|  | /* | 
|  | * QemuOpts unit-tests. | 
|  | * | 
|  | * Copyright (C) 2014 Leandro Dorileo <l@dorileo.org> | 
|  | * | 
|  | * 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 "qapi/error.h" | 
|  | #include "qapi/qmp/qstring.h" | 
|  | #include "qemu/config-file.h" | 
|  |  | 
|  | #include <glib.h> | 
|  | #include <string.h> | 
|  |  | 
|  | static QemuOptsList opts_list_01 = { | 
|  | .name = "opts_list_01", | 
|  | .head = QTAILQ_HEAD_INITIALIZER(opts_list_01.head), | 
|  | .desc = { | 
|  | { | 
|  | .name = "str1", | 
|  | .type = QEMU_OPT_STRING, | 
|  | },{ | 
|  | .name = "str2", | 
|  | .type = QEMU_OPT_STRING, | 
|  | },{ | 
|  | .name = "str3", | 
|  | .type = QEMU_OPT_STRING, | 
|  | },{ | 
|  | .name = "number1", | 
|  | .type = QEMU_OPT_NUMBER, | 
|  | }, | 
|  | { /* end of list */ } | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static QemuOptsList opts_list_02 = { | 
|  | .name = "opts_list_02", | 
|  | .head = QTAILQ_HEAD_INITIALIZER(opts_list_02.head), | 
|  | .desc = { | 
|  | { | 
|  | .name = "str1", | 
|  | .type = QEMU_OPT_STRING, | 
|  | },{ | 
|  | .name = "bool1", | 
|  | .type = QEMU_OPT_BOOL, | 
|  | },{ | 
|  | .name = "str2", | 
|  | .type = QEMU_OPT_STRING, | 
|  | },{ | 
|  | .name = "size1", | 
|  | .type = QEMU_OPT_SIZE, | 
|  | }, | 
|  | { /* end of list */ } | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static QemuOptsList opts_list_03 = { | 
|  | .name = "opts_list_03", | 
|  | .head = QTAILQ_HEAD_INITIALIZER(opts_list_03.head), | 
|  | .desc = { | 
|  | /* no elements => accept any params */ | 
|  | { /* end of list */ } | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static void register_opts(void) | 
|  | { | 
|  | qemu_add_opts(&opts_list_01); | 
|  | qemu_add_opts(&opts_list_02); | 
|  | qemu_add_opts(&opts_list_03); | 
|  | } | 
|  |  | 
|  | static void test_find_unknown_opts(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  | Error *err = NULL; | 
|  |  | 
|  | /* should not return anything, we don't have an "unknown" option */ | 
|  | list = qemu_find_opts_err("unknown", &err); | 
|  | g_assert(list == NULL); | 
|  | g_assert(err); | 
|  | error_free(err); | 
|  | } | 
|  |  | 
|  | static void test_qemu_find_opts(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  |  | 
|  | /* we have an "opts_list_01" option, should return it */ | 
|  | list = qemu_find_opts("opts_list_01"); | 
|  | g_assert(list != NULL); | 
|  | g_assert_cmpstr(list->name, ==, "opts_list_01"); | 
|  | } | 
|  |  | 
|  | static void test_qemu_opts_create(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  | QemuOpts *opts; | 
|  |  | 
|  | list = qemu_find_opts("opts_list_01"); | 
|  | g_assert(list != NULL); | 
|  | g_assert(QTAILQ_EMPTY(&list->head)); | 
|  | g_assert_cmpstr(list->name, ==, "opts_list_01"); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  |  | 
|  | /* create the opts */ | 
|  | opts = qemu_opts_create(list, NULL, 0, &error_abort); | 
|  | g_assert(opts != NULL); | 
|  | g_assert(!QTAILQ_EMPTY(&list->head)); | 
|  |  | 
|  | /* now we've create the opts, must find it */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts != NULL); | 
|  |  | 
|  | qemu_opts_del(opts); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  | } | 
|  |  | 
|  | static void test_qemu_opt_get(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  | QemuOpts *opts; | 
|  | const char *opt = NULL; | 
|  |  | 
|  | list = qemu_find_opts("opts_list_01"); | 
|  | g_assert(list != NULL); | 
|  | g_assert(QTAILQ_EMPTY(&list->head)); | 
|  | g_assert_cmpstr(list->name, ==, "opts_list_01"); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  |  | 
|  | /* create the opts */ | 
|  | opts = qemu_opts_create(list, NULL, 0, &error_abort); | 
|  | g_assert(opts != NULL); | 
|  | g_assert(!QTAILQ_EMPTY(&list->head)); | 
|  |  | 
|  | /* haven't set anything to str2 yet */ | 
|  | opt = qemu_opt_get(opts, "str2"); | 
|  | g_assert(opt == NULL); | 
|  |  | 
|  | qemu_opt_set(opts, "str2", "value"); | 
|  |  | 
|  | /* now we have set str2, should know about it */ | 
|  | opt = qemu_opt_get(opts, "str2"); | 
|  | g_assert_cmpstr(opt, ==, "value"); | 
|  |  | 
|  | qemu_opt_set(opts, "str2", "value2"); | 
|  |  | 
|  | /* having reset the value, the returned should be the reset one */ | 
|  | opt = qemu_opt_get(opts, "str2"); | 
|  | g_assert_cmpstr(opt, ==, "value2"); | 
|  |  | 
|  | qemu_opts_del(opts); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  | } | 
|  |  | 
|  | static void test_qemu_opt_get_bool(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  | QemuOpts *opts; | 
|  | bool opt; | 
|  | int ret; | 
|  |  | 
|  | list = qemu_find_opts("opts_list_02"); | 
|  | g_assert(list != NULL); | 
|  | g_assert(QTAILQ_EMPTY(&list->head)); | 
|  | g_assert_cmpstr(list->name, ==, "opts_list_02"); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  |  | 
|  | /* create the opts */ | 
|  | opts = qemu_opts_create(list, NULL, 0, &error_abort); | 
|  | g_assert(opts != NULL); | 
|  | g_assert(!QTAILQ_EMPTY(&list->head)); | 
|  |  | 
|  | /* haven't set anything to bool1 yet, so defval should be returned */ | 
|  | opt = qemu_opt_get_bool(opts, "bool1", false); | 
|  | g_assert(opt == false); | 
|  |  | 
|  | ret = qemu_opt_set_bool(opts, "bool1", true); | 
|  | g_assert(ret == 0); | 
|  |  | 
|  | /* now we have set bool1, should know about it */ | 
|  | opt = qemu_opt_get_bool(opts, "bool1", false); | 
|  | g_assert(opt == true); | 
|  |  | 
|  | /* having reset the value, opt should be the reset one not defval */ | 
|  | ret = qemu_opt_set_bool(opts, "bool1", false); | 
|  | g_assert(ret == 0); | 
|  |  | 
|  | opt = qemu_opt_get_bool(opts, "bool1", true); | 
|  | g_assert(opt == false); | 
|  |  | 
|  | qemu_opts_del(opts); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  | } | 
|  |  | 
|  | static void test_qemu_opt_get_number(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  | QemuOpts *opts; | 
|  | uint64_t opt; | 
|  | int ret; | 
|  |  | 
|  | list = qemu_find_opts("opts_list_01"); | 
|  | g_assert(list != NULL); | 
|  | g_assert(QTAILQ_EMPTY(&list->head)); | 
|  | g_assert_cmpstr(list->name, ==, "opts_list_01"); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  |  | 
|  | /* create the opts */ | 
|  | opts = qemu_opts_create(list, NULL, 0, &error_abort); | 
|  | g_assert(opts != NULL); | 
|  | g_assert(!QTAILQ_EMPTY(&list->head)); | 
|  |  | 
|  | /* haven't set anything to number1 yet, so defval should be returned */ | 
|  | opt = qemu_opt_get_number(opts, "number1", 5); | 
|  | g_assert(opt == 5); | 
|  |  | 
|  | ret = qemu_opt_set_number(opts, "number1", 10); | 
|  | g_assert(ret == 0); | 
|  |  | 
|  | /* now we have set number1, should know about it */ | 
|  | opt = qemu_opt_get_number(opts, "number1", 5); | 
|  | g_assert(opt == 10); | 
|  |  | 
|  | /* having reset it, the returned should be the reset one not defval */ | 
|  | ret = qemu_opt_set_number(opts, "number1", 15); | 
|  | g_assert(ret == 0); | 
|  |  | 
|  | opt = qemu_opt_get_number(opts, "number1", 5); | 
|  | g_assert(opt == 15); | 
|  |  | 
|  | qemu_opts_del(opts); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  | } | 
|  |  | 
|  | static void test_qemu_opt_get_size(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  | QemuOpts *opts; | 
|  | uint64_t opt; | 
|  | QDict *dict; | 
|  |  | 
|  | list = qemu_find_opts("opts_list_02"); | 
|  | g_assert(list != NULL); | 
|  | g_assert(QTAILQ_EMPTY(&list->head)); | 
|  | g_assert_cmpstr(list->name, ==, "opts_list_02"); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  |  | 
|  | /* create the opts */ | 
|  | opts = qemu_opts_create(list, NULL, 0, &error_abort); | 
|  | g_assert(opts != NULL); | 
|  | g_assert(!QTAILQ_EMPTY(&list->head)); | 
|  |  | 
|  | /* haven't set anything to size1 yet, so defval should be returned */ | 
|  | opt = qemu_opt_get_size(opts, "size1", 5); | 
|  | g_assert(opt == 5); | 
|  |  | 
|  | dict = qdict_new(); | 
|  | g_assert(dict != NULL); | 
|  |  | 
|  | qdict_put(dict, "size1", qstring_from_str("10")); | 
|  |  | 
|  | qemu_opts_absorb_qdict(opts, dict, &error_abort); | 
|  | g_assert(error_abort == NULL); | 
|  |  | 
|  | /* now we have set size1, should know about it */ | 
|  | opt = qemu_opt_get_size(opts, "size1", 5); | 
|  | g_assert(opt == 10); | 
|  |  | 
|  | /* reset value */ | 
|  | qdict_put(dict, "size1", qstring_from_str("15")); | 
|  |  | 
|  | qemu_opts_absorb_qdict(opts, dict, &error_abort); | 
|  | g_assert(error_abort == NULL); | 
|  |  | 
|  | /* test the reset value */ | 
|  | opt = qemu_opt_get_size(opts, "size1", 5); | 
|  | g_assert(opt == 15); | 
|  |  | 
|  | qdict_del(dict, "size1"); | 
|  | g_free(dict); | 
|  |  | 
|  | qemu_opts_del(opts); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  | } | 
|  |  | 
|  | static void test_qemu_opt_unset(void) | 
|  | { | 
|  | QemuOpts *opts; | 
|  | const char *value; | 
|  | int ret; | 
|  |  | 
|  | /* dynamically initialized (parsed) opts */ | 
|  | opts = qemu_opts_parse(&opts_list_03, "key=value", 0); | 
|  | g_assert(opts != NULL); | 
|  |  | 
|  | /* check default/parsed value */ | 
|  | value = qemu_opt_get(opts, "key"); | 
|  | g_assert_cmpstr(value, ==, "value"); | 
|  |  | 
|  | /* reset it to value2 */ | 
|  | qemu_opt_set(opts, "key", "value2"); | 
|  |  | 
|  | value = qemu_opt_get(opts, "key"); | 
|  | g_assert_cmpstr(value, ==, "value2"); | 
|  |  | 
|  | /* unset, valid only for "accept any" */ | 
|  | ret = qemu_opt_unset(opts, "key"); | 
|  | g_assert(ret == 0); | 
|  |  | 
|  | /* after reset the value should be the parsed/default one */ | 
|  | value = qemu_opt_get(opts, "key"); | 
|  | g_assert_cmpstr(value, ==, "value"); | 
|  |  | 
|  | qemu_opts_del(opts); | 
|  | } | 
|  |  | 
|  | static void test_qemu_opts_reset(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  | QemuOpts *opts; | 
|  | uint64_t opt; | 
|  | int ret; | 
|  |  | 
|  | list = qemu_find_opts("opts_list_01"); | 
|  | g_assert(list != NULL); | 
|  | g_assert(QTAILQ_EMPTY(&list->head)); | 
|  | g_assert_cmpstr(list->name, ==, "opts_list_01"); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  |  | 
|  | /* create the opts */ | 
|  | opts = qemu_opts_create(list, NULL, 0, &error_abort); | 
|  | g_assert(opts != NULL); | 
|  | g_assert(!QTAILQ_EMPTY(&list->head)); | 
|  |  | 
|  | /* haven't set anything to number1 yet, so defval should be returned */ | 
|  | opt = qemu_opt_get_number(opts, "number1", 5); | 
|  | g_assert(opt == 5); | 
|  |  | 
|  | ret = qemu_opt_set_number(opts, "number1", 10); | 
|  | g_assert(ret == 0); | 
|  |  | 
|  | /* now we have set number1, should know about it */ | 
|  | opt = qemu_opt_get_number(opts, "number1", 5); | 
|  | g_assert(opt == 10); | 
|  |  | 
|  | qemu_opts_reset(list); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  | } | 
|  |  | 
|  | static void test_qemu_opts_set(void) | 
|  | { | 
|  | QemuOptsList *list; | 
|  | QemuOpts *opts; | 
|  | int ret; | 
|  | const char *opt; | 
|  |  | 
|  | list = qemu_find_opts("opts_list_01"); | 
|  | g_assert(list != NULL); | 
|  | g_assert(QTAILQ_EMPTY(&list->head)); | 
|  | g_assert_cmpstr(list->name, ==, "opts_list_01"); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  |  | 
|  | /* implicitly create opts and set str3 value */ | 
|  | ret = qemu_opts_set(list, NULL, "str3", "value"); | 
|  | g_assert(ret == 0); | 
|  | g_assert(!QTAILQ_EMPTY(&list->head)); | 
|  |  | 
|  | /* get the just created opts */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts != NULL); | 
|  |  | 
|  | /* check the str3 value */ | 
|  | opt = qemu_opt_get(opts, "str3"); | 
|  | g_assert_cmpstr(opt, ==, "value"); | 
|  |  | 
|  | qemu_opts_del(opts); | 
|  |  | 
|  | /* should not find anything at this point */ | 
|  | opts = qemu_opts_find(list, NULL); | 
|  | g_assert(opts == NULL); | 
|  | } | 
|  |  | 
|  | int main(int argc, char *argv[]) | 
|  | { | 
|  | register_opts(); | 
|  | g_test_init(&argc, &argv, NULL); | 
|  | g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts); | 
|  | g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts); | 
|  | g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create); | 
|  | g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get); | 
|  | g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool); | 
|  | g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number); | 
|  | g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size); | 
|  | 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_run(); | 
|  | return 0; | 
|  | } |