static void qdict_crumple_test_bad_inputs(void) { QDict *src; Error *error = NULL; src = qdict_new(); /* rule.0 can't be both a string and a dict */ qdict_put(src, "rule.0", qstring_from_str("fred")); qdict_put(src, "rule.0.policy", qstring_from_str("allow")); g_assert(qdict_crumple(src, &error) == NULL); g_assert(error != NULL); error_free(error); error = NULL; QDECREF(src); src = qdict_new(); /* rule can't be both a list and a dict */ qdict_put(src, "rule.0", qstring_from_str("fred")); qdict_put(src, "rule.a", qstring_from_str("allow")); g_assert(qdict_crumple(src, &error) == NULL); g_assert(error != NULL); error_free(error); error = NULL; QDECREF(src); src = qdict_new(); /* The input should be flat, ie no dicts or lists */ qdict_put(src, "rule.a", qdict_new()); qdict_put(src, "rule.b", qstring_from_str("allow")); g_assert(qdict_crumple(src, &error) == NULL); g_assert(error != NULL); error_free(error); error = NULL; QDECREF(src); src = qdict_new(); /* List indexes must not have gaps */ qdict_put(src, "rule.0", qstring_from_str("deny")); qdict_put(src, "rule.3", qstring_from_str("allow")); g_assert(qdict_crumple(src, &error) == NULL); g_assert(error != NULL); error_free(error); error = NULL; QDECREF(src); src = qdict_new(); /* List indexes must be in %zu format */ qdict_put(src, "rule.0", qstring_from_str("deny")); qdict_put(src, "rule.+1", qstring_from_str("allow")); g_assert(qdict_crumple(src, &error) == NULL); g_assert(error != NULL); error_free(error); error = NULL; QDECREF(src); }
static InetSocketAddress *ssh_config(BDRVSSHState *s, QDict *options, Error **errp) { InetSocketAddress *inet = NULL; QDict *addr = NULL; QObject *crumpled_addr = NULL; Visitor *iv = NULL; Error *local_error = NULL; qdict_extract_subqdict(options, &addr, "server."); if (!qdict_size(addr)) { error_setg(errp, "SSH server address missing"); goto out; } crumpled_addr = qdict_crumple(addr, errp); if (!crumpled_addr) { goto out; } iv = qobject_input_visitor_new(crumpled_addr, true); visit_type_InetSocketAddress(iv, NULL, &inet, &local_error); if (local_error) { error_propagate(errp, local_error); goto out; } out: QDECREF(addr); qobject_decref(crumpled_addr); visit_free(iv); return inet; }
static void qdict_crumple_test_recursive(void) { QDict *src, *dst, *rule, *vnc, *acl, *listen; QList *rules; src = qdict_new(); qdict_put(src, "vnc.listen.addr", qstring_from_str("127.0.0.1")); qdict_put(src, "vnc.listen.port", qstring_from_str("5901")); qdict_put(src, "vnc.acl.rules.0.match", qstring_from_str("fred")); qdict_put(src, "vnc.acl.rules.0.policy", qstring_from_str("allow")); qdict_put(src, "vnc.acl.rules.1.match", qstring_from_str("bob")); qdict_put(src, "vnc.acl.rules.1.policy", qstring_from_str("deny")); qdict_put(src, "vnc.acl.default", qstring_from_str("deny")); qdict_put(src, "vnc.acl..name", qstring_from_str("acl0")); qdict_put(src, "vnc.acl.rule..name", qstring_from_str("acl0")); dst = qobject_to_qdict(qdict_crumple(src, &error_abort)); g_assert(dst); g_assert_cmpint(qdict_size(dst), ==, 1); vnc = qdict_get_qdict(dst, "vnc"); g_assert(vnc); g_assert_cmpint(qdict_size(vnc), ==, 3); listen = qdict_get_qdict(vnc, "listen"); g_assert(listen); g_assert_cmpint(qdict_size(listen), ==, 2); g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr")); g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port")); acl = qdict_get_qdict(vnc, "acl"); g_assert(acl); g_assert_cmpint(qdict_size(acl), ==, 3); rules = qdict_get_qlist(acl, "rules"); g_assert(rules); g_assert_cmpint(qlist_size(rules), ==, 2); rule = qobject_to_qdict(qlist_pop(rules)); g_assert(rule); g_assert_cmpint(qdict_size(rule), ==, 2); g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match")); g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy")); QDECREF(rule); rule = qobject_to_qdict(qlist_pop(rules)); g_assert(rule); g_assert_cmpint(qdict_size(rule), ==, 2); g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match")); g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy")); QDECREF(rule); /* With recursive crumpling, we should see all names unescaped */ g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name")); g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name")); QDECREF(src); QDECREF(dst); }
static void qdict_crumple_test_empty(void) { QDict *src, *dst; src = qdict_new(); dst = (QDict *)qdict_crumple(src, &error_abort); g_assert_cmpint(qdict_size(dst), ==, 0); QDECREF(src); QDECREF(dst); }
static void qdict_crumple_test_empty(void) { QDict *src, *dst; src = qdict_new(); dst = qobject_to(QDict, qdict_crumple(src, &error_abort)); g_assert_cmpint(qdict_size(dst), ==, 0); qobject_unref(src); qobject_unref(dst); }
static InetSocketAddress *ssh_config(QDict *options, Error **errp) { InetSocketAddress *inet = NULL; QDict *addr = NULL; QObject *crumpled_addr = NULL; Visitor *iv = NULL; Error *local_error = NULL; qdict_extract_subqdict(options, &addr, "server."); if (!qdict_size(addr)) { error_setg(errp, "SSH server address missing"); goto out; } crumpled_addr = qdict_crumple(addr, errp); if (!crumpled_addr) { goto out; } /* * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive. * .to doesn't matter, it's ignored anyway. * That's because when @options come from -blockdev or * blockdev_add, members are typed according to the QAPI schema, * but when they come from -drive, they're all QString. The * visitor expects the former. */ iv = qobject_input_visitor_new(crumpled_addr); visit_type_InetSocketAddress(iv, NULL, &inet, &local_error); if (local_error) { error_propagate(errp, local_error); goto out; } out: QDECREF(addr); qobject_decref(crumpled_addr); visit_free(iv); return inet; }
static void qobject_is_equal_dict_test(void) { Error *local_err = NULL; QDict *dict_0, *dict_1, *dict_cloned; QDict *dict_different_key, *dict_different_value, *dict_different_null_key; QDict *dict_longer, *dict_shorter, *dict_nested; QDict *dict_crumpled; dict_0 = qdict_new(); dict_1 = qdict_new(); dict_different_key = qdict_new(); dict_different_value = qdict_new(); dict_different_null_key = qdict_new(); dict_longer = qdict_new(); dict_shorter = qdict_new(); dict_nested = qdict_new(); qdict_put_int(dict_0, "f.o", 1); qdict_put_int(dict_0, "bar", 2); qdict_put_int(dict_0, "baz", 3); qdict_put_null(dict_0, "null"); qdict_put_int(dict_1, "f.o", 1); qdict_put_int(dict_1, "bar", 2); qdict_put_int(dict_1, "baz", 3); qdict_put_null(dict_1, "null"); qdict_put_int(dict_different_key, "F.o", 1); qdict_put_int(dict_different_key, "bar", 2); qdict_put_int(dict_different_key, "baz", 3); qdict_put_null(dict_different_key, "null"); qdict_put_int(dict_different_value, "f.o", 42); qdict_put_int(dict_different_value, "bar", 2); qdict_put_int(dict_different_value, "baz", 3); qdict_put_null(dict_different_value, "null"); qdict_put_int(dict_different_null_key, "f.o", 1); qdict_put_int(dict_different_null_key, "bar", 2); qdict_put_int(dict_different_null_key, "baz", 3); qdict_put_null(dict_different_null_key, "none"); qdict_put_int(dict_longer, "f.o", 1); qdict_put_int(dict_longer, "bar", 2); qdict_put_int(dict_longer, "baz", 3); qdict_put_int(dict_longer, "xyz", 4); qdict_put_null(dict_longer, "null"); qdict_put_int(dict_shorter, "f.o", 1); qdict_put_int(dict_shorter, "bar", 2); qdict_put_int(dict_shorter, "baz", 3); qdict_put(dict_nested, "f", qdict_new()); qdict_put_int(qdict_get_qdict(dict_nested, "f"), "o", 1); qdict_put_int(dict_nested, "bar", 2); qdict_put_int(dict_nested, "baz", 3); qdict_put_null(dict_nested, "null"); dict_cloned = qdict_clone_shallow(dict_0); check_equal(dict_0, dict_1, dict_cloned); check_unequal(dict_0, dict_different_key, dict_different_value, dict_different_null_key, dict_longer, dict_shorter, dict_nested); dict_crumpled = qobject_to(QDict, qdict_crumple(dict_1, &local_err)); g_assert(!local_err); check_equal(dict_crumpled, dict_nested); qdict_flatten(dict_nested); check_equal(dict_0, dict_nested); /* Containing an NaN value will make this dict compare unequal to * itself */ qdict_put(dict_0, "NaN", qnum_from_double(NAN)); g_assert(qobject_is_equal(QOBJECT(dict_0), QOBJECT(dict_0)) == false); free_all(dict_0, dict_1, dict_cloned, dict_different_key, dict_different_value, dict_different_null_key, dict_longer, dict_shorter, dict_nested, dict_crumpled); }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; BlockdevOptionsRbd *opts = NULL; Visitor *v; QObject *crumpled = NULL; const QDictEntry *e; Error *local_err = NULL; const char *filename; char *keypairs, *secretid; int r; /* If we are given a filename, parse the filename, with precedence given to * filename encoded options */ filename = qdict_get_try_str(options, "filename"); if (filename) { warn_report("'filename' option specified. " "This is an unsupported option, and may be deprecated " "in the future"); qemu_rbd_parse_filename(filename, options, &local_err); qdict_del(options, "filename"); if (local_err) { error_propagate(errp, local_err); return -EINVAL; } } keypairs = g_strdup(qdict_get_try_str(options, "=keyvalue-pairs")); if (keypairs) { qdict_del(options, "=keyvalue-pairs"); } secretid = g_strdup(qdict_get_try_str(options, "password-secret")); if (secretid) { qdict_del(options, "password-secret"); } /* Convert the remaining options into a QAPI object */ crumpled = qdict_crumple(options, errp); if (crumpled == NULL) { r = -EINVAL; goto out; } v = qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevOptionsRbd(v, NULL, &opts, &local_err); visit_free(v); qobject_unref(crumpled); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto out; } /* Remove the processed options from the QDict (the visitor processes * _all_ options in the QDict) */ while ((e = qdict_first(options))) { qdict_del(options, e->key); } r = qemu_rbd_connect(&s->cluster, &s->io_ctx, opts, !(flags & BDRV_O_NOCACHE), keypairs, secretid, errp); if (r < 0) { goto out; } s->snap = g_strdup(opts->snapshot); s->image_name = g_strdup(opts->image); /* rbd_open is always r/w */ r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap); if (r < 0) { error_setg_errno(errp, -r, "error reading header from %s", s->image_name); goto failed_open; } /* If we are using an rbd snapshot, we must be r/o, otherwise * leave as-is */ if (s->snap != NULL) { if (!bdrv_is_read_only(bs)) { error_report("Opening rbd snapshots without an explicit " "read-only=on option is deprecated. Future versions " "will refuse to open the image instead of " "automatically marking the image read-only."); r = bdrv_set_read_only(bs, true, &local_err); if (r < 0) { error_propagate(errp, local_err); goto failed_open; } } } r = 0; goto out; failed_open: rados_ioctx_destroy(s->io_ctx); g_free(s->snap); g_free(s->image_name); rados_shutdown(s->cluster); out: qapi_free_BlockdevOptionsRbd(opts); g_free(keypairs); g_free(secretid); return r; }
static void qdict_crumple_test_recursive(void) { QDict *src, *dst, *rule, *vnc, *acl, *listen; QDict *empty, *empty_dict, *empty_list_0; QList *rules, *empty_list, *empty_dict_a; src = qdict_new(); qdict_put_str(src, "vnc.listen.addr", "127.0.0.1"); qdict_put_str(src, "vnc.listen.port", "5901"); qdict_put_str(src, "vnc.acl.rules.0.match", "fred"); qdict_put_str(src, "vnc.acl.rules.0.policy", "allow"); qdict_put_str(src, "vnc.acl.rules.1.match", "bob"); qdict_put_str(src, "vnc.acl.rules.1.policy", "deny"); qdict_put_str(src, "vnc.acl.default", "deny"); qdict_put_str(src, "vnc.acl..name", "acl0"); qdict_put_str(src, "vnc.acl.rule..name", "acl0"); qdict_put(src, "empty.dict.a", qlist_new()); qdict_put(src, "empty.list.0", qdict_new()); dst = qobject_to(QDict, qdict_crumple(src, &error_abort)); g_assert(dst); g_assert_cmpint(qdict_size(dst), ==, 2); vnc = qdict_get_qdict(dst, "vnc"); g_assert(vnc); g_assert_cmpint(qdict_size(vnc), ==, 3); listen = qdict_get_qdict(vnc, "listen"); g_assert(listen); g_assert_cmpint(qdict_size(listen), ==, 2); g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr")); g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port")); acl = qdict_get_qdict(vnc, "acl"); g_assert(acl); g_assert_cmpint(qdict_size(acl), ==, 3); rules = qdict_get_qlist(acl, "rules"); g_assert(rules); g_assert_cmpint(qlist_size(rules), ==, 2); rule = qobject_to(QDict, qlist_pop(rules)); g_assert(rule); g_assert_cmpint(qdict_size(rule), ==, 2); g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match")); g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy")); qobject_unref(rule); rule = qobject_to(QDict, qlist_pop(rules)); g_assert(rule); g_assert_cmpint(qdict_size(rule), ==, 2); g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match")); g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy")); qobject_unref(rule); /* With recursive crumpling, we should see all names unescaped */ g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name")); g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name")); empty = qdict_get_qdict(dst, "empty"); g_assert(empty); g_assert_cmpint(qdict_size(empty), ==, 2); empty_dict = qdict_get_qdict(empty, "dict"); g_assert(empty_dict); g_assert_cmpint(qdict_size(empty_dict), ==, 1); empty_dict_a = qdict_get_qlist(empty_dict, "a"); g_assert(empty_dict_a && qlist_empty(empty_dict_a)); empty_list = qdict_get_qlist(empty, "list"); g_assert(empty_list); g_assert_cmpint(qlist_size(empty_list), ==, 1); empty_list_0 = qobject_to(QDict, qlist_pop(empty_list)); g_assert(empty_list_0); g_assert_cmpint(qdict_size(empty_list_0), ==, 0); qobject_unref(src); qobject_unref(dst); }