/* This function is hooked as final emit function, which can verify the correctness. */ static void event_test_emit(test_QAPIEvent event, QDict *d, Error **errp) { QObject *obj; QDict *t; int64_t s, ms; /* Verify that we have timestamp, then remove it to compare other fields */ obj = qdict_get(d, "timestamp"); g_assert(obj); t = qobject_to_qdict(obj); g_assert(t); obj = qdict_get(t, "seconds"); g_assert(obj && qobject_type(obj) == QTYPE_QINT); s = qint_get_int(qobject_to_qint(obj)); obj = qdict_get(t, "microseconds"); g_assert(obj && qobject_type(obj) == QTYPE_QINT); ms = qint_get_int(qobject_to_qint(obj)); if (s == -1) { g_assert(ms == -1); } else { g_assert(ms >= 0 && ms <= 999999); } g_assert(qdict_size(t) == 2); qdict_del(d, "timestamp"); g_assert(qdict_cmp_simple(d, test_event_data->expect)); }
static void qerror_set_data(QError *qerr, const char *fmt, va_list *va) { QObject *obj; obj = qobject_from_jsonv(fmt, va); if (!obj) { qerror_abort(qerr, "invalid format '%s'", fmt); } if (qobject_type(obj) != QTYPE_QDICT) { qerror_abort(qerr, "error format is not a QDict '%s'", fmt); } qerr->error = qobject_to_qdict(obj); obj = qdict_get(qerr->error, "class"); if (!obj) { qerror_abort(qerr, "missing 'class' key in '%s'", fmt); } if (qobject_type(obj) != QTYPE_QSTRING) { qerror_abort(qerr, "'class' key value should be a QString"); } obj = qdict_get(qerr->error, "data"); if (!obj) { qerror_abort(qerr, "missing 'data' key in '%s'", fmt); } if (qobject_type(obj) != QTYPE_QDICT) { qerror_abort(qerr, "'data' key value should be a QDICT"); } }
static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob, Error **errp) { const char *exec_key = NULL; const QDictEntry *ent; const char *arg_name; const QObject *arg_obj; QDict *dict; dict = qobject_to(QDict, request); if (!dict) { error_setg(errp, "QMP input must be a JSON object"); return NULL; } for (ent = qdict_first(dict); ent; ent = qdict_next(dict, ent)) { arg_name = qdict_entry_key(ent); arg_obj = qdict_entry_value(ent); if (!strcmp(arg_name, "execute") || (!strcmp(arg_name, "exec-oob") && allow_oob)) { if (qobject_type(arg_obj) != QTYPE_QSTRING) { error_setg(errp, "QMP input member '%s' must be a string", arg_name); return NULL; } if (exec_key) { error_setg(errp, "QMP input member '%s' clashes with '%s'", arg_name, exec_key); return NULL; } exec_key = arg_name; } else if (!strcmp(arg_name, "arguments")) { if (qobject_type(arg_obj) != QTYPE_QDICT) { error_setg(errp, "QMP input member 'arguments' must be an object"); return NULL; } } else if (!strcmp(arg_name, "id")) { continue; } else { error_setg(errp, "QMP input member '%s' is unexpected", arg_name); return NULL; } } if (!exec_key) { error_setg(errp, "QMP input lacks member 'execute'"); return NULL; } return dict; }
/** * qdict_get_try_bool_or_int(): Try to get a bool or int mapped by 'key' * * Return bool or int mapped by 'key', if it is not present in the * dictionary or if the stored object is not of QBool or QInt type * 'def_value' will be returned. */ int qdict_get_try_bool_or_int(const QDict *qdict, const char *key, int def_value) { QObject *obj; obj = qdict_get(qdict, key); if (obj && qobject_type(obj) == QTYPE_QBOOL) { return qbool_get_int(qobject_to_qbool(obj)); } else if (obj && qobject_type(obj) == QTYPE_QINT) { return qint_get_int(qobject_to_qint(obj)); } return def_value; }
/** * qobject_to_qstring(): Convert a QObject to a QString */ QString *qobject_to_qstring(const QObject *obj) { if (!obj || qobject_type(obj) != QTYPE_QSTRING) { return NULL; } return container_of(obj, QString, base); }
/* Add @value to the current QObject being built. * If the stack is visiting a dictionary or list, @value is now owned * by that container. Otherwise, @value is now the root. */ static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name, QObject *value) { QStackEntry *e = QSLIST_FIRST(&qov->stack); QObject *cur = e ? e->value : NULL; if (!cur) { /* Don't allow reuse of visitor on more than one root */ assert(!qov->root); qov->root = value; } else { switch (qobject_type(cur)) { case QTYPE_QDICT: assert(name); qdict_put_obj(qobject_to(QDict, cur), name, value); break; case QTYPE_QLIST: assert(!name); qlist_append_obj(qobject_to(QList, cur), value); break; default: g_assert_not_reached(); } } }
QDict *qobject_to_qdict(const QObject *obj) { if (qobject_type(obj) != QTYPE_QDICT) return NULL; return container_of(obj, QDict, base); }
/** * qobject_to_qerror(): Convert a QObject into a QError */ QError *qobject_to_qerror(const QObject *obj) { if (qobject_type(obj) != QTYPE_QERROR) { return NULL; } return container_of(obj, QError, base); }
/* Only compares bool, int, string */ static void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque) { QObject *obj2; QDictCmpData d_new, *d = opaque; if (!d->result) { return; } obj2 = qdict_get(d->expect, key); if (!obj2) { d->result = false; return; } if (qobject_type(obj1) != qobject_type(obj2)) { d->result = false; return; } switch (qobject_type(obj1)) { case QTYPE_QBOOL: d->result = (qbool_get_bool(qobject_to_qbool(obj1)) == qbool_get_bool(qobject_to_qbool(obj2))); return; case QTYPE_QINT: d->result = (qint_get_int(qobject_to_qint(obj1)) == qint_get_int(qobject_to_qint(obj2))); return; case QTYPE_QSTRING: d->result = g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)), qstring_get_str(qobject_to_qstring(obj2))) == 0; return; case QTYPE_QDICT: d_new.expect = qobject_to_qdict(obj2); d_new.result = true; qdict_iter(qobject_to_qdict(obj1), qdict_cmp_do_simple, &d_new); d->result = d_new.result; return; default: abort(); } }
/** * qdict_get_try_bool(): Try to get a bool mapped by 'key' * * Return bool mapped by 'key', if it is not present in the * dictionary or if the stored object is not of QBool type * 'def_value' will be returned. */ int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value) { QObject *obj; obj = qdict_get(qdict, key); if (!obj || qobject_type(obj) != QTYPE_QBOOL) return def_value; return qbool_get_int(qobject_to_qbool(obj)); }
static const QObject *qmp_input_get_object(QmpInputVisitor *qiv, const char *name) { const QObject *qobj; if (qiv->nb_stack == 0) { qobj = qiv->obj; } else { qobj = qiv->stack[qiv->nb_stack - 1].obj; } if (name && qobject_type(qobj) == QTYPE_QDICT) { return qdict_get(qobject_to_qdict(qobj), name); } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) { return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry); } return qobj; }
const char *qdict_get_try_str(const QDict *qdict, const char *key) { QObject *obj; obj = qdict_get(qdict, key); if (!obj || qobject_type(obj) != QTYPE_QSTRING) return NULL; return qstring_get_str(qobject_to_qstring(obj)); }
static void qmp_input_type_number(Visitor *v, double *obj, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, true); if (!qobj || (qobject_type(qobj) != QTYPE_QFLOAT && qobject_type(qobj) != QTYPE_QINT)) { error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "number"); return; } if (qobject_type(qobj) == QTYPE_QINT) { *obj = qint_get_int(qobject_to_qint(qobj)); } else { *obj = qfloat_get_double(qobject_to_qfloat(qobj)); } }
static const char *append_field(QString *outstr, const QError *qerror, const char *start) { QObject *obj; QDict *qdict; QString *key_qs; const char *end, *key; if (*start != '%') parse_error(qerror, '%'); start++; if (*start != '(') parse_error(qerror, '('); start++; end = strchr(start, ')'); if (!end) parse_error(qerror, ')'); key_qs = qstring_from_substr(start, 0, end - start - 1); key = qstring_get_str(key_qs); qdict = qobject_to_qdict(qdict_get(qerror->error, "data")); obj = qdict_get(qdict, key); if (!obj) { qerror_abort(qerror, "key '%s' not found in QDict", key); } switch (qobject_type(obj)) { case QTYPE_QSTRING: qstring_append(outstr, qdict_get_str(qdict, key)); break; case QTYPE_QINT: qstring_append_int(outstr, qdict_get_int(qdict, key)); break; default: qerror_abort(qerror, "invalid type '%c'", qobject_type(obj)); } QDECREF(key_qs); return ++end; }
static QObject *qdict_get_obj(const QDict *qdict, const char *key, qtype_code type) { QObject *obj; obj = qdict_get(qdict, key); assert(obj != NULL); assert(qobject_type(obj) == type); return obj; }
int64_t qdict_get_try_int(const QDict *qdict, const char *key, int64_t err_value) { QObject *obj; obj = qdict_get(qdict, key); if (!obj || qobject_type(obj) != QTYPE_QINT) return err_value; return qint_get_int(qobject_to_qint(obj)); }
static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) { const QDictEntry *ent; const char *arg_name; const QObject *arg_obj; bool has_exec_key = false; QDict *dict = NULL; if (qobject_type(request) != QTYPE_QDICT) { error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "request is not a dictionary"); return NULL; } dict = qobject_to_qdict(request); for (ent = qdict_first(dict); ent; ent = qdict_next(dict, ent)) { arg_name = qdict_entry_key(ent); arg_obj = qdict_entry_value(ent); if (!strcmp(arg_name, "execute")) { if (qobject_type(arg_obj) != QTYPE_QSTRING) { error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute", "string"); return NULL; } has_exec_key = true; } else if (strcmp(arg_name, "arguments")) { error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name); return NULL; } } if (!has_exec_key) { error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute"); return NULL; } return dict; }
static void test_visitor_out_int(TestOutputVisitorData *data, const void *unused) { int64_t value = -42; QObject *obj; visit_type_int(data->ov, NULL, &value, &error_abort); obj = visitor_get(data); g_assert(qobject_type(obj) == QTYPE_QINT); g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value); }
static void qlist_new_test(void) { QList *qlist; qlist = qlist_new(); g_assert(qlist != NULL); g_assert(qlist->base.refcnt == 1); g_assert(qobject_type(QOBJECT(qlist)) == QTYPE_QLIST); // destroy doesn't exist yet g_free(qlist); }
static void qmp_input_get_next_type(Visitor *v, int *kind, const int *qobjects, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, false); if (!qobj) { error_set(errp, QERR_MISSING_PARAMETER, name ? name : "null"); return; } *kind = qobjects[qobject_type(qobj)]; }
static void test_visitor_out_bool(TestOutputVisitorData *data, const void *unused) { bool value = true; QObject *obj; visit_type_bool(data->ov, NULL, &value, &error_abort); obj = visitor_get(data); g_assert(qobject_type(obj) == QTYPE_QBOOL); g_assert(qbool_get_bool(qobject_to_qbool(obj)) == value); }
static void test_visitor_out_number(TestOutputVisitorData *data, const void *unused) { double value = 3.14; QObject *obj; visit_type_number(data->ov, NULL, &value, &error_abort); obj = visitor_get(data); g_assert(qobject_type(obj) == QTYPE_QFLOAT); g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value); }
static void test_visitor_out_string(TestOutputVisitorData *data, const void *unused) { char *string = (char *) "Q E M U"; QObject *obj; visit_type_str(data->ov, NULL, &string, &error_abort); obj = visitor_get(data); g_assert(qobject_type(obj) == QTYPE_QSTRING); g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string); }
static void qmp_input_start_list(Visitor *v, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, true); if (!qobj || qobject_type(qobj) != QTYPE_QLIST) { error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "list"); return; } qmp_input_push(qiv, qobj, errp); }
static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp) { qiv->stack[qiv->nb_stack].obj = obj; if (qobject_type(obj) == QTYPE_QLIST) { qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj)); } qiv->nb_stack++; if (qiv->nb_stack >= QIV_STACK_SIZE) { error_set(errp, QERR_BUFFER_OVERRUN); return; } }
static void qnull_ref_test(void) { QObject *obj; g_assert(qnull_.base.refcnt == 1); obj = QOBJECT(qnull()); g_assert(obj); g_assert(obj == QOBJECT(&qnull_)); g_assert(qnull_.base.refcnt == 2); g_assert(qobject_type(obj) == QTYPE_QNULL); qobject_decref(obj); g_assert(qnull_.base.refcnt == 1); }
static void qdict_new_test(void) { QDict *qdict; qdict = qdict_new(); g_assert(qdict != NULL); g_assert(qdict_size(qdict) == 0); g_assert(qdict->base.refcnt == 1); g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT); // destroy doesn't exit yet g_free(qdict); }
static void test_visitor_out_no_string(TestOutputVisitorData *data, const void *unused) { char *string = NULL; QObject *obj; /* A null string should return "" */ visit_type_str(data->ov, NULL, &string, &error_abort); obj = visitor_get(data); g_assert(qobject_type(obj) == QTYPE_QSTRING); g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, ""); }
static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, true); if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) { error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "boolean"); return; } *obj = qbool_get_int(qobject_to_qbool(qobj)); }
static void qmp_input_type_str(Visitor *v, char **obj, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, true); if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) { error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "string"); return; } *obj = g_strdup(qstring_get_str(qobject_to_qstring(qobj))); }