Merge remote-tracking branch 'luiz/queue/qmp' into staging
# By Michael Roth (10) and others # Via Luiz Capitulino * luiz/queue/qmp: monitor: allow to disable the default monitor ui/input.c: replace magic numbers with macros qapi: add native list coverage for QMP input visitor tests qapi: add native list coverage for QMP output visitor tests qapi: add native list coverage for visitor serialization tests qapi: fix visitor serialization tests for numbers/doubles qapi: add QMP input test for large integers json-parser: fix handling of large whole number values qapi: enable generation of native list code qapi: qapi-visit.py, native list support qapi: qapi-visit.py, fix list handling for union types qapi: qapi-types.py, native list support Message-id: 1369333232-24145-1-git-send-email-lcapitulino@redhat.com Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
commit
64afc2b4d4
6
Makefile
6
Makefile
@ -178,7 +178,7 @@ Makefile: $(version-obj-y) $(version-lobj-y)
|
||||
# Build libraries
|
||||
|
||||
libqemustub.a: $(stub-obj-y)
|
||||
libqemuutil.a: $(util-obj-y)
|
||||
libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
|
||||
|
||||
######################################################################
|
||||
|
||||
@ -215,10 +215,10 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
|
||||
|
||||
qapi-types.c qapi-types.h :\
|
||||
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@")
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." -b < $<, " GEN $@")
|
||||
qapi-visit.c qapi-visit.h :\
|
||||
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@")
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -b < $<, " GEN $@")
|
||||
qmp-commands.h qmp-marshal.c :\
|
||||
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@")
|
||||
|
@ -32,6 +32,21 @@
|
||||
{ 'union': 'UserDefUnion',
|
||||
'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } }
|
||||
|
||||
# for testing native lists
|
||||
{ 'union': 'UserDefNativeListUnion',
|
||||
'data': { 'integer': ['int'],
|
||||
's8': ['int8'],
|
||||
's16': ['int16'],
|
||||
's32': ['int32'],
|
||||
's64': ['int64'],
|
||||
'u8': ['uint8'],
|
||||
'u16': ['uint16'],
|
||||
'u32': ['uint32'],
|
||||
'u64': ['uint64'],
|
||||
'number': ['number'],
|
||||
'boolean': ['bool'],
|
||||
'string': ['str'] } }
|
||||
|
||||
# testing commands
|
||||
{ 'command': 'user_def_cmd', 'data': {} }
|
||||
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
|
||||
|
@ -2528,6 +2528,7 @@ Redirect the monitor to host device @var{dev} (same devices as the
|
||||
serial port).
|
||||
The default device is @code{vc} in graphical mode and @code{stdio} in
|
||||
non graphical mode.
|
||||
Use @code{-monitor none} to disable the default monitor.
|
||||
ETEXI
|
||||
DEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \
|
||||
"-qmp dev like -monitor but opens in 'control' mode\n",
|
||||
|
@ -640,9 +640,29 @@ static QObject *parse_literal(JSONParserContext *ctxt)
|
||||
case JSON_STRING:
|
||||
obj = QOBJECT(qstring_from_escaped_str(ctxt, token));
|
||||
break;
|
||||
case JSON_INTEGER:
|
||||
obj = QOBJECT(qint_from_int(strtoll(token_get_value(token), NULL, 10)));
|
||||
break;
|
||||
case JSON_INTEGER: {
|
||||
/* A possibility exists that this is a whole-valued float where the
|
||||
* fractional part was left out due to being 0 (.0). It's not a big
|
||||
* deal to treat these as ints in the parser, so long as users of the
|
||||
* resulting QObject know to expect a QInt in place of a QFloat in
|
||||
* cases like these.
|
||||
*
|
||||
* However, in some cases these values will overflow/underflow a
|
||||
* QInt/int64 container, thus we should assume these are to be handled
|
||||
* as QFloats/doubles rather than silently changing their values.
|
||||
*
|
||||
* strtoll() indicates these instances by setting errno to ERANGE
|
||||
*/
|
||||
int64_t value;
|
||||
|
||||
errno = 0; /* strtoll doesn't set errno on success */
|
||||
value = strtoll(token_get_value(token), NULL, 10);
|
||||
if (errno != ERANGE) {
|
||||
obj = QOBJECT(qint_from_int(value));
|
||||
break;
|
||||
}
|
||||
/* fall through to JSON_FLOAT */
|
||||
}
|
||||
case JSON_FLOAT:
|
||||
/* FIXME dependent on locale */
|
||||
obj = QOBJECT(qfloat_from_double(strtod(token_get_value(token), NULL)));
|
||||
|
@ -16,8 +16,21 @@ import os
|
||||
import getopt
|
||||
import errno
|
||||
|
||||
def generate_fwd_struct(name, members):
|
||||
def generate_fwd_struct(name, members, builtin_type=False):
|
||||
if builtin_type:
|
||||
return mcgen('''
|
||||
|
||||
typedef struct %(name)sList
|
||||
{
|
||||
%(type)s value;
|
||||
struct %(name)sList *next;
|
||||
} %(name)sList;
|
||||
''',
|
||||
type=c_type(name),
|
||||
name=name)
|
||||
|
||||
return mcgen('''
|
||||
|
||||
typedef struct %(name)s %(name)s;
|
||||
|
||||
typedef struct %(name)sList
|
||||
@ -164,6 +177,7 @@ void qapi_free_%(type)s(%(c_type)s obj);
|
||||
|
||||
def generate_type_cleanup(name):
|
||||
ret = mcgen('''
|
||||
|
||||
void qapi_free_%(type)s(%(c_type)s obj)
|
||||
{
|
||||
QapiDeallocVisitor *md;
|
||||
@ -184,8 +198,9 @@ void qapi_free_%(type)s(%(c_type)s obj)
|
||||
|
||||
|
||||
try:
|
||||
opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
|
||||
["source", "header", "prefix=", "output-dir="])
|
||||
opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
|
||||
["source", "header", "builtins",
|
||||
"prefix=", "output-dir="])
|
||||
except getopt.GetoptError, err:
|
||||
print str(err)
|
||||
sys.exit(1)
|
||||
@ -197,6 +212,7 @@ h_file = 'qapi-types.h'
|
||||
|
||||
do_c = False
|
||||
do_h = False
|
||||
do_builtins = False
|
||||
|
||||
for o, a in opts:
|
||||
if o in ("-p", "--prefix"):
|
||||
@ -207,6 +223,8 @@ for o, a in opts:
|
||||
do_c = True
|
||||
elif o in ("-h", "--header"):
|
||||
do_h = True
|
||||
elif o in ("-b", "--builtins"):
|
||||
do_builtins = True
|
||||
|
||||
if not do_c and not do_h:
|
||||
do_c = True
|
||||
@ -282,6 +300,11 @@ fdecl.write(mcgen('''
|
||||
exprs = parse_schema(sys.stdin)
|
||||
exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
|
||||
|
||||
fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
|
||||
for typename in builtin_types:
|
||||
fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
|
||||
fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
|
||||
|
||||
for expr in exprs:
|
||||
ret = "\n"
|
||||
if expr.has_key('type'):
|
||||
@ -298,6 +321,22 @@ for expr in exprs:
|
||||
continue
|
||||
fdecl.write(ret)
|
||||
|
||||
# to avoid header dependency hell, we always generate declarations
|
||||
# for built-in types in our header files and simply guard them
|
||||
fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
|
||||
for typename in builtin_types:
|
||||
fdecl.write(generate_type_cleanup_decl(typename + "List"))
|
||||
fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
|
||||
|
||||
# ...this doesn't work for cases where we link in multiple objects that
|
||||
# have the functions defined, so we use -b option to provide control
|
||||
# over these cases
|
||||
if do_builtins:
|
||||
fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
|
||||
for typename in builtin_types:
|
||||
fdef.write(generate_type_cleanup(typename + "List"))
|
||||
fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
|
||||
|
||||
for expr in exprs:
|
||||
ret = "\n"
|
||||
if expr.has_key('type'):
|
||||
|
@ -174,7 +174,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
|
||||
''',
|
||||
abbrev = de_camel_case(name).upper(),
|
||||
enum = c_fun(de_camel_case(key),False).upper(),
|
||||
c_type=members[key],
|
||||
c_type=type_name(members[key]),
|
||||
c_name=c_fun(key))
|
||||
|
||||
ret += mcgen('''
|
||||
@ -202,12 +202,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
|
||||
|
||||
return ret
|
||||
|
||||
def generate_declaration(name, members, genlist=True):
|
||||
ret = mcgen('''
|
||||
def generate_declaration(name, members, genlist=True, builtin_type=False):
|
||||
ret = ""
|
||||
if not builtin_type:
|
||||
ret += mcgen('''
|
||||
|
||||
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp);
|
||||
''',
|
||||
name=name)
|
||||
name=name)
|
||||
|
||||
if genlist:
|
||||
ret += mcgen('''
|
||||
@ -235,8 +237,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e
|
||||
name=name)
|
||||
|
||||
try:
|
||||
opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
|
||||
["source", "header", "prefix=", "output-dir="])
|
||||
opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
|
||||
["source", "header", "builtins", "prefix=",
|
||||
"output-dir="])
|
||||
except getopt.GetoptError, err:
|
||||
print str(err)
|
||||
sys.exit(1)
|
||||
@ -248,6 +251,7 @@ h_file = 'qapi-visit.h'
|
||||
|
||||
do_c = False
|
||||
do_h = False
|
||||
do_builtins = False
|
||||
|
||||
for o, a in opts:
|
||||
if o in ("-p", "--prefix"):
|
||||
@ -258,6 +262,8 @@ for o, a in opts:
|
||||
do_c = True
|
||||
elif o in ("-h", "--header"):
|
||||
do_h = True
|
||||
elif o in ("-b", "--builtins"):
|
||||
do_builtins = True
|
||||
|
||||
if not do_c and not do_h:
|
||||
do_c = True
|
||||
@ -324,11 +330,29 @@ fdecl.write(mcgen('''
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
#include "%(prefix)sqapi-types.h"
|
||||
|
||||
''',
|
||||
prefix=prefix, guard=guardname(h_file)))
|
||||
|
||||
exprs = parse_schema(sys.stdin)
|
||||
|
||||
# to avoid header dependency hell, we always generate declarations
|
||||
# for built-in types in our header files and simply guard them
|
||||
fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
|
||||
for typename in builtin_types:
|
||||
fdecl.write(generate_declaration(typename, None, genlist=True,
|
||||
builtin_type=True))
|
||||
fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
|
||||
|
||||
# ...this doesn't work for cases where we link in multiple objects that
|
||||
# have the functions defined, so we use -b option to provide control
|
||||
# over these cases
|
||||
if do_builtins:
|
||||
fdef.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DEF"))
|
||||
for typename in builtin_types:
|
||||
fdef.write(generate_visit_list(typename, None))
|
||||
fdef.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DEF"))
|
||||
|
||||
for expr in exprs:
|
||||
if expr.has_key('type'):
|
||||
ret = generate_visit_struct(expr['type'], expr['data'])
|
||||
|
@ -11,6 +11,12 @@
|
||||
|
||||
from ordereddict import OrderedDict
|
||||
|
||||
builtin_types = [
|
||||
'str', 'int', 'number', 'bool',
|
||||
'int8', 'int16', 'int32', 'int64',
|
||||
'uint8', 'uint16', 'uint32', 'uint64'
|
||||
]
|
||||
|
||||
def tokenize(data):
|
||||
while len(data):
|
||||
ch = data[0]
|
||||
@ -242,3 +248,20 @@ def guardname(filename):
|
||||
for substr in [".", " ", "-"]:
|
||||
guard = guard.replace(substr, "_")
|
||||
return guard.upper() + '_H'
|
||||
|
||||
def guardstart(name):
|
||||
return mcgen('''
|
||||
|
||||
#ifndef %(name)s
|
||||
#define %(name)s
|
||||
|
||||
''',
|
||||
name=guardname(name))
|
||||
|
||||
def guardend(name):
|
||||
return mcgen('''
|
||||
|
||||
#endif /* %(name)s */
|
||||
|
||||
''',
|
||||
name=guardname(name))
|
||||
|
@ -61,6 +61,31 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data,
|
||||
return v;
|
||||
}
|
||||
|
||||
/* similar to visitor_input_test_init(), but does not expect a string
|
||||
* literal/format json_string argument and so can be used for
|
||||
* programatically generated strings (and we can't pass in programatically
|
||||
* generated strings via %s format parameters since qobject_from_jsonv()
|
||||
* will wrap those in double-quotes and treat the entire object as a
|
||||
* string)
|
||||
*/
|
||||
static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
|
||||
const char *json_string)
|
||||
{
|
||||
Visitor *v;
|
||||
|
||||
data->obj = qobject_from_json(json_string);
|
||||
|
||||
g_assert(data->obj != NULL);
|
||||
|
||||
data->qiv = qmp_input_visitor_new(data->obj);
|
||||
g_assert(data->qiv != NULL);
|
||||
|
||||
v = qmp_input_get_visitor(data->qiv);
|
||||
g_assert(v != NULL);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static void test_visitor_in_int(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
@ -75,6 +100,24 @@ static void test_visitor_in_int(TestInputVisitorData *data,
|
||||
g_assert_cmpint(res, ==, value);
|
||||
}
|
||||
|
||||
static void test_visitor_in_int_overflow(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
int64_t res = 0;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
/* this will overflow a Qint/int64, so should be deserialized into
|
||||
* a QFloat/double field instead, leading to an error if we pass it
|
||||
* to visit_type_int. confirm this.
|
||||
*/
|
||||
v = visitor_input_test_init(data, "%f", DBL_MAX);
|
||||
|
||||
visit_type_int(v, &res, NULL, &errp);
|
||||
g_assert(error_is_set(&errp));
|
||||
error_free(errp);
|
||||
}
|
||||
|
||||
static void test_visitor_in_bool(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
@ -259,6 +302,287 @@ static void test_visitor_in_union(TestInputVisitorData *data,
|
||||
qapi_free_UserDefUnion(tmp);
|
||||
}
|
||||
|
||||
static void test_native_list_integer_helper(TestInputVisitorData *data,
|
||||
const void *unused,
|
||||
UserDefNativeListUnionKind kind)
|
||||
{
|
||||
UserDefNativeListUnion *cvalue = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
GString *gstr_list = g_string_new("");
|
||||
GString *gstr_union = g_string_new("");
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
g_string_append_printf(gstr_list, "%d", i);
|
||||
if (i != 31) {
|
||||
g_string_append(gstr_list, ", ");
|
||||
}
|
||||
}
|
||||
g_string_append_printf(gstr_union, "{ 'type': '%s', 'data': [ %s ] }",
|
||||
UserDefNativeListUnionKind_lookup[kind],
|
||||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
g_assert(cvalue != NULL);
|
||||
g_assert_cmpint(cvalue->kind, ==, kind);
|
||||
|
||||
switch (kind) {
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
|
||||
intList *elem = NULL;
|
||||
for (i = 0, elem = cvalue->integer; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
|
||||
int8List *elem = NULL;
|
||||
for (i = 0, elem = cvalue->s8; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
|
||||
int16List *elem = NULL;
|
||||
for (i = 0, elem = cvalue->s16; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
|
||||
int32List *elem = NULL;
|
||||
for (i = 0, elem = cvalue->s32; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
|
||||
int64List *elem = NULL;
|
||||
for (i = 0, elem = cvalue->s64; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
|
||||
uint8List *elem = NULL;
|
||||
for (i = 0, elem = cvalue->u8; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
|
||||
uint16List *elem = NULL;
|
||||
for (i = 0, elem = cvalue->u16; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
|
||||
uint32List *elem = NULL;
|
||||
for (i = 0, elem = cvalue->u32; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
|
||||
uint64List *elem = NULL;
|
||||
for (i = 0, elem = cvalue->u64; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert(false);
|
||||
}
|
||||
|
||||
g_string_free(gstr_union, true);
|
||||
g_string_free(gstr_list, true);
|
||||
qapi_free_UserDefNativeListUnion(cvalue);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_int(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_int8(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_S8);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_int16(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_S16);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_int32(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_S32);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_int64(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_S64);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_uint8(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_U8);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_uint16(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_U16);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_uint32(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_U32);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_uint64(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list_integer_helper(data, unused,
|
||||
USER_DEF_NATIVE_LIST_UNION_KIND_U64);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefNativeListUnion *cvalue = NULL;
|
||||
boolList *elem = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
GString *gstr_list = g_string_new("");
|
||||
GString *gstr_union = g_string_new("");
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
g_string_append_printf(gstr_list, "%s",
|
||||
(i % 3 == 0) ? "true" : "false");
|
||||
if (i != 31) {
|
||||
g_string_append(gstr_list, ", ");
|
||||
}
|
||||
}
|
||||
g_string_append_printf(gstr_union, "{ 'type': 'boolean', 'data': [ %s ] }",
|
||||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
g_assert(cvalue != NULL);
|
||||
g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
|
||||
|
||||
for (i = 0, elem = cvalue->boolean; elem; elem = elem->next, i++) {
|
||||
g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
|
||||
}
|
||||
|
||||
g_string_free(gstr_union, true);
|
||||
g_string_free(gstr_list, true);
|
||||
qapi_free_UserDefNativeListUnion(cvalue);
|
||||
}
|
||||
|
||||
static void test_visitor_in_native_list_string(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefNativeListUnion *cvalue = NULL;
|
||||
strList *elem = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
GString *gstr_list = g_string_new("");
|
||||
GString *gstr_union = g_string_new("");
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
g_string_append_printf(gstr_list, "'%d'", i);
|
||||
if (i != 31) {
|
||||
g_string_append(gstr_list, ", ");
|
||||
}
|
||||
}
|
||||
g_string_append_printf(gstr_union, "{ 'type': 'string', 'data': [ %s ] }",
|
||||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
g_assert(cvalue != NULL);
|
||||
g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
|
||||
|
||||
for (i = 0, elem = cvalue->string; elem; elem = elem->next, i++) {
|
||||
gchar str[8];
|
||||
sprintf(str, "%d", i);
|
||||
g_assert_cmpstr(elem->value, ==, str);
|
||||
}
|
||||
|
||||
g_string_free(gstr_union, true);
|
||||
g_string_free(gstr_list, true);
|
||||
qapi_free_UserDefNativeListUnion(cvalue);
|
||||
}
|
||||
|
||||
#define DOUBLE_STR_MAX 16
|
||||
|
||||
static void test_visitor_in_native_list_number(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefNativeListUnion *cvalue = NULL;
|
||||
numberList *elem = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
GString *gstr_list = g_string_new("");
|
||||
GString *gstr_union = g_string_new("");
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
g_string_append_printf(gstr_list, "%f", (double)i / 3);
|
||||
if (i != 31) {
|
||||
g_string_append(gstr_list, ", ");
|
||||
}
|
||||
}
|
||||
g_string_append_printf(gstr_union, "{ 'type': 'number', 'data': [ %s ] }",
|
||||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
g_assert(cvalue != NULL);
|
||||
g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
|
||||
|
||||
for (i = 0, elem = cvalue->number; elem; elem = elem->next, i++) {
|
||||
GString *double_expected = g_string_new("");
|
||||
GString *double_actual = g_string_new("");
|
||||
|
||||
g_string_printf(double_expected, "%.6f", (double)i / 3);
|
||||
g_string_printf(double_actual, "%.6f", elem->value);
|
||||
g_assert_cmpstr(double_expected->str, ==, double_actual->str);
|
||||
|
||||
g_string_free(double_expected, true);
|
||||
g_string_free(double_actual, true);
|
||||
}
|
||||
|
||||
g_string_free(gstr_union, true);
|
||||
g_string_free(gstr_list, true);
|
||||
qapi_free_UserDefNativeListUnion(cvalue);
|
||||
}
|
||||
|
||||
static void input_visitor_test_add(const char *testpath,
|
||||
TestInputVisitorData *data,
|
||||
void (*test_func)(TestInputVisitorData *data, const void *user_data))
|
||||
@ -292,6 +616,8 @@ int main(int argc, char **argv)
|
||||
|
||||
input_visitor_test_add("/visitor/input/int",
|
||||
&in_visitor_data, test_visitor_in_int);
|
||||
input_visitor_test_add("/visitor/input/int_overflow",
|
||||
&in_visitor_data, test_visitor_in_int_overflow);
|
||||
input_visitor_test_add("/visitor/input/bool",
|
||||
&in_visitor_data, test_visitor_in_bool);
|
||||
input_visitor_test_add("/visitor/input/number",
|
||||
@ -310,6 +636,38 @@ int main(int argc, char **argv)
|
||||
&in_visitor_data, test_visitor_in_union);
|
||||
input_visitor_test_add("/visitor/input/errors",
|
||||
&in_visitor_data, test_visitor_in_errors);
|
||||
input_visitor_test_add("/visitor/input/native_list/int",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int);
|
||||
input_visitor_test_add("/visitor/input/native_list/int8",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int8);
|
||||
input_visitor_test_add("/visitor/input/native_list/int16",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int16);
|
||||
input_visitor_test_add("/visitor/input/native_list/int32",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int32);
|
||||
input_visitor_test_add("/visitor/input/native_list/int64",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_int64);
|
||||
input_visitor_test_add("/visitor/input/native_list/uint8",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_uint8);
|
||||
input_visitor_test_add("/visitor/input/native_list/uint16",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_uint16);
|
||||
input_visitor_test_add("/visitor/input/native_list/uint32",
|
||||
&in_visitor_data,
|
||||
test_visitor_in_native_list_uint32);
|
||||
input_visitor_test_add("/visitor/input/native_list/uint64",
|
||||
&in_visitor_data, test_visitor_in_native_list_uint64);
|
||||
input_visitor_test_add("/visitor/input/native_list/bool",
|
||||
&in_visitor_data, test_visitor_in_native_list_bool);
|
||||
input_visitor_test_add("/visitor/input/native_list/str",
|
||||
&in_visitor_data, test_visitor_in_native_list_string);
|
||||
input_visitor_test_add("/visitor/input/native_list/number",
|
||||
&in_visitor_data, test_visitor_in_native_list_number);
|
||||
|
||||
g_test_run();
|
||||
|
||||
|
@ -431,6 +431,314 @@ static void test_visitor_out_union(TestOutputVisitorData *data,
|
||||
QDECREF(qdict);
|
||||
}
|
||||
|
||||
static void init_native_list(UserDefNativeListUnion *cvalue)
|
||||
{
|
||||
int i;
|
||||
switch (cvalue->kind) {
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
|
||||
intList **list = &cvalue->integer;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(intList, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
|
||||
int8List **list = &cvalue->s8;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(int8List, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
|
||||
int16List **list = &cvalue->s16;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(int16List, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
|
||||
int32List **list = &cvalue->s32;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(int32List, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
|
||||
int64List **list = &cvalue->s64;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(int64List, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
|
||||
uint8List **list = &cvalue->u8;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(uint8List, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
|
||||
uint16List **list = &cvalue->u16;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(uint16List, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
|
||||
uint32List **list = &cvalue->u32;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(uint32List, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
|
||||
uint64List **list = &cvalue->u64;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(uint64List, 1);
|
||||
(*list)->value = i;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN: {
|
||||
boolList **list = &cvalue->boolean;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(boolList, 1);
|
||||
(*list)->value = (i % 3 == 0);
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_STRING: {
|
||||
strList **list = &cvalue->string;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(strList, 1);
|
||||
(*list)->value = g_strdup_printf("%d", i);
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER: {
|
||||
numberList **list = &cvalue->number;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*list = g_new0(numberList, 1);
|
||||
(*list)->value = (double)i / 3;
|
||||
(*list)->next = NULL;
|
||||
list = &(*list)->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_native_list(QObject *qobj,
|
||||
UserDefNativeListUnionKind kind)
|
||||
{
|
||||
QDict *qdict;
|
||||
QList *qlist;
|
||||
int i;
|
||||
|
||||
g_assert(qobj);
|
||||
g_assert(qobject_type(qobj) == QTYPE_QDICT);
|
||||
qdict = qobject_to_qdict(qobj);
|
||||
g_assert(qdict);
|
||||
g_assert(qdict_haskey(qdict, "data"));
|
||||
qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data")));
|
||||
|
||||
switch (kind) {
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
|
||||
/* all integer elements in JSON arrays get stored into QInts when
|
||||
* we convert to QObjects, so we can check them all in the same
|
||||
* fashion, so simply fall through here
|
||||
*/
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER:
|
||||
for (i = 0; i < 32; i++) {
|
||||
QObject *tmp;
|
||||
QInt *qvalue;
|
||||
tmp = qlist_peek(qlist);
|
||||
g_assert(tmp);
|
||||
qvalue = qobject_to_qint(tmp);
|
||||
g_assert_cmpint(qint_get_int(qvalue), ==, i);
|
||||
qobject_decref(qlist_pop(qlist));
|
||||
}
|
||||
break;
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN:
|
||||
for (i = 0; i < 32; i++) {
|
||||
QObject *tmp;
|
||||
QBool *qvalue;
|
||||
tmp = qlist_peek(qlist);
|
||||
g_assert(tmp);
|
||||
qvalue = qobject_to_qbool(tmp);
|
||||
g_assert_cmpint(qbool_get_int(qvalue), ==, (i % 3 == 0) ? 1 : 0);
|
||||
qobject_decref(qlist_pop(qlist));
|
||||
}
|
||||
break;
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_STRING:
|
||||
for (i = 0; i < 32; i++) {
|
||||
QObject *tmp;
|
||||
QString *qvalue;
|
||||
gchar str[8];
|
||||
tmp = qlist_peek(qlist);
|
||||
g_assert(tmp);
|
||||
qvalue = qobject_to_qstring(tmp);
|
||||
sprintf(str, "%d", i);
|
||||
g_assert_cmpstr(qstring_get_str(qvalue), ==, str);
|
||||
qobject_decref(qlist_pop(qlist));
|
||||
}
|
||||
break;
|
||||
case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER:
|
||||
for (i = 0; i < 32; i++) {
|
||||
QObject *tmp;
|
||||
QFloat *qvalue;
|
||||
GString *double_expected = g_string_new("");
|
||||
GString *double_actual = g_string_new("");
|
||||
|
||||
tmp = qlist_peek(qlist);
|
||||
g_assert(tmp);
|
||||
qvalue = qobject_to_qfloat(tmp);
|
||||
g_string_printf(double_expected, "%.6f", (double)i / 3);
|
||||
g_string_printf(double_actual, "%.6f", qfloat_get_double(qvalue));
|
||||
g_assert_cmpstr(double_actual->str, ==, double_expected->str);
|
||||
|
||||
qobject_decref(qlist_pop(qlist));
|
||||
g_string_free(double_expected, true);
|
||||
g_string_free(double_actual, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert(false);
|
||||
}
|
||||
QDECREF(qlist);
|
||||
}
|
||||
|
||||
static void test_native_list(TestOutputVisitorData *data,
|
||||
const void *unused,
|
||||
UserDefNativeListUnionKind kind)
|
||||
{
|
||||
UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1);
|
||||
Error *err = NULL;
|
||||
QObject *obj;
|
||||
|
||||
cvalue->kind = kind;
|
||||
init_native_list(cvalue);
|
||||
|
||||
visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
check_native_list(obj, cvalue->kind);
|
||||
qapi_free_UserDefNativeListUnion(cvalue);
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_int(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_int8(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S8);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_int16(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S16);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_int32(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S32);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_int64(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S64);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_uint8(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U8);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_uint16(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U16);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_uint32(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U32);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_uint64(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U64);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_bool(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_str(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
|
||||
}
|
||||
|
||||
static void test_visitor_out_native_list_number(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
|
||||
}
|
||||
|
||||
static void output_visitor_test_add(const char *testpath,
|
||||
TestOutputVisitorData *data,
|
||||
void (*test_func)(TestOutputVisitorData *data, const void *user_data))
|
||||
@ -471,6 +779,30 @@ int main(int argc, char **argv)
|
||||
&out_visitor_data, test_visitor_out_list_qapi_free);
|
||||
output_visitor_test_add("/visitor/output/union",
|
||||
&out_visitor_data, test_visitor_out_union);
|
||||
output_visitor_test_add("/visitor/output/native_list/int",
|
||||
&out_visitor_data, test_visitor_out_native_list_int);
|
||||
output_visitor_test_add("/visitor/output/native_list/int8",
|
||||
&out_visitor_data, test_visitor_out_native_list_int8);
|
||||
output_visitor_test_add("/visitor/output/native_list/int16",
|
||||
&out_visitor_data, test_visitor_out_native_list_int16);
|
||||
output_visitor_test_add("/visitor/output/native_list/int32",
|
||||
&out_visitor_data, test_visitor_out_native_list_int32);
|
||||
output_visitor_test_add("/visitor/output/native_list/int64",
|
||||
&out_visitor_data, test_visitor_out_native_list_int64);
|
||||
output_visitor_test_add("/visitor/output/native_list/uint8",
|
||||
&out_visitor_data, test_visitor_out_native_list_uint8);
|
||||
output_visitor_test_add("/visitor/output/native_list/uint16",
|
||||
&out_visitor_data, test_visitor_out_native_list_uint16);
|
||||
output_visitor_test_add("/visitor/output/native_list/uint32",
|
||||
&out_visitor_data, test_visitor_out_native_list_uint32);
|
||||
output_visitor_test_add("/visitor/output/native_list/uint64",
|
||||
&out_visitor_data, test_visitor_out_native_list_uint64);
|
||||
output_visitor_test_add("/visitor/output/native_list/bool",
|
||||
&out_visitor_data, test_visitor_out_native_list_bool);
|
||||
output_visitor_test_add("/visitor/output/native_list/string",
|
||||
&out_visitor_data, test_visitor_out_native_list_str);
|
||||
output_visitor_test_add("/visitor/output/native_list/number",
|
||||
&out_visitor_data, test_visitor_out_native_list_number);
|
||||
|
||||
g_test_run();
|
||||
|
||||
|
@ -23,6 +23,25 @@
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi/string-input-visitor.h"
|
||||
#include "qapi/string-output-visitor.h"
|
||||
#include "qapi-types.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/dealloc-visitor.h"
|
||||
|
||||
enum PrimitiveTypeKind {
|
||||
PTYPE_STRING = 0,
|
||||
PTYPE_BOOLEAN,
|
||||
PTYPE_NUMBER,
|
||||
PTYPE_INTEGER,
|
||||
PTYPE_U8,
|
||||
PTYPE_U16,
|
||||
PTYPE_U32,
|
||||
PTYPE_U64,
|
||||
PTYPE_S8,
|
||||
PTYPE_S16,
|
||||
PTYPE_S32,
|
||||
PTYPE_S64,
|
||||
PTYPE_EOL,
|
||||
};
|
||||
|
||||
typedef struct PrimitiveType {
|
||||
union {
|
||||
@ -40,26 +59,42 @@ typedef struct PrimitiveType {
|
||||
int64_t s64;
|
||||
intmax_t max;
|
||||
} value;
|
||||
enum {
|
||||
PTYPE_STRING = 0,
|
||||
PTYPE_BOOLEAN,
|
||||
PTYPE_NUMBER,
|
||||
PTYPE_INTEGER,
|
||||
PTYPE_U8,
|
||||
PTYPE_U16,
|
||||
PTYPE_U32,
|
||||
PTYPE_U64,
|
||||
PTYPE_S8,
|
||||
PTYPE_S16,
|
||||
PTYPE_S32,
|
||||
PTYPE_S64,
|
||||
PTYPE_EOL,
|
||||
} type;
|
||||
enum PrimitiveTypeKind type;
|
||||
const char *description;
|
||||
} PrimitiveType;
|
||||
|
||||
typedef struct PrimitiveList {
|
||||
union {
|
||||
strList *strings;
|
||||
boolList *booleans;
|
||||
numberList *numbers;
|
||||
intList *integers;
|
||||
int8List *s8_integers;
|
||||
int16List *s16_integers;
|
||||
int32List *s32_integers;
|
||||
int64List *s64_integers;
|
||||
uint8List *u8_integers;
|
||||
uint16List *u16_integers;
|
||||
uint32List *u32_integers;
|
||||
uint64List *u64_integers;
|
||||
} value;
|
||||
enum PrimitiveTypeKind type;
|
||||
const char *description;
|
||||
} PrimitiveList;
|
||||
|
||||
/* test helpers */
|
||||
|
||||
typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
|
||||
|
||||
static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
|
||||
{
|
||||
QapiDeallocVisitor *qdv = qapi_dealloc_visitor_new();
|
||||
|
||||
visit(qapi_dealloc_get_visitor(qdv), &native_in, errp);
|
||||
|
||||
qapi_dealloc_visitor_cleanup(qdv);
|
||||
}
|
||||
|
||||
static void visit_primitive_type(Visitor *v, void **native, Error **errp)
|
||||
{
|
||||
PrimitiveType *pt = *native;
|
||||
@ -105,6 +140,51 @@ static void visit_primitive_type(Visitor *v, void **native, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void visit_primitive_list(Visitor *v, void **native, Error **errp)
|
||||
{
|
||||
PrimitiveList *pl = *native;
|
||||
switch (pl->type) {
|
||||
case PTYPE_STRING:
|
||||
visit_type_strList(v, &pl->value.strings, NULL, errp);
|
||||
break;
|
||||
case PTYPE_BOOLEAN:
|
||||
visit_type_boolList(v, &pl->value.booleans, NULL, errp);
|
||||
break;
|
||||
case PTYPE_NUMBER:
|
||||
visit_type_numberList(v, &pl->value.numbers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_INTEGER:
|
||||
visit_type_intList(v, &pl->value.integers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_S8:
|
||||
visit_type_int8List(v, &pl->value.s8_integers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_S16:
|
||||
visit_type_int16List(v, &pl->value.s16_integers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_S32:
|
||||
visit_type_int32List(v, &pl->value.s32_integers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_S64:
|
||||
visit_type_int64List(v, &pl->value.s64_integers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_U8:
|
||||
visit_type_uint8List(v, &pl->value.u8_integers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_U16:
|
||||
visit_type_uint16List(v, &pl->value.u16_integers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_U32:
|
||||
visit_type_uint32List(v, &pl->value.u32_integers, NULL, errp);
|
||||
break;
|
||||
case PTYPE_U64:
|
||||
visit_type_uint64List(v, &pl->value.u64_integers, NULL, errp);
|
||||
break;
|
||||
default:
|
||||
g_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct TestStruct
|
||||
{
|
||||
int64_t integer;
|
||||
@ -206,12 +286,11 @@ static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
|
||||
|
||||
/* test cases */
|
||||
|
||||
typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
|
||||
|
||||
typedef enum VisitorCapabilities {
|
||||
VCAP_PRIMITIVES = 1,
|
||||
VCAP_STRUCTURES = 2,
|
||||
VCAP_LISTS = 4,
|
||||
VCAP_PRIMITIVE_LISTS = 8,
|
||||
} VisitorCapabilities;
|
||||
|
||||
typedef struct SerializeOps {
|
||||
@ -229,17 +308,6 @@ typedef struct TestArgs {
|
||||
void *test_data;
|
||||
} TestArgs;
|
||||
|
||||
#define FLOAT_STRING_PRECISION 6 /* corresponding to n in %.nf formatting */
|
||||
static gsize calc_float_string_storage(double value)
|
||||
{
|
||||
int whole_value = value;
|
||||
gsize i = 0;
|
||||
do {
|
||||
i++;
|
||||
} while (whole_value /= 10);
|
||||
return i + 2 + FLOAT_STRING_PRECISION;
|
||||
}
|
||||
|
||||
static void test_primitives(gconstpointer opaque)
|
||||
{
|
||||
TestArgs *args = (TestArgs *) opaque;
|
||||
@ -248,7 +316,6 @@ static void test_primitives(gconstpointer opaque)
|
||||
PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
|
||||
Error *err = NULL;
|
||||
void *serialize_data;
|
||||
char *double1, *double2;
|
||||
|
||||
pt_copy->type = pt->type;
|
||||
ops->serialize(pt, &serialize_data, visit_primitive_type, &err);
|
||||
@ -260,14 +327,17 @@ static void test_primitives(gconstpointer opaque)
|
||||
g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
|
||||
g_free((char *)pt_copy->value.string);
|
||||
} else if (pt->type == PTYPE_NUMBER) {
|
||||
GString *double_expected = g_string_new("");
|
||||
GString *double_actual = g_string_new("");
|
||||
/* we serialize with %f for our reference visitors, so rather than fuzzy
|
||||
* floating math to test "equality", just compare the formatted values
|
||||
*/
|
||||
double1 = g_malloc0(calc_float_string_storage(pt->value.number));
|
||||
double2 = g_malloc0(calc_float_string_storage(pt_copy->value.number));
|
||||
g_assert_cmpstr(double1, ==, double2);
|
||||
g_free(double1);
|
||||
g_free(double2);
|
||||
g_string_printf(double_expected, "%.6f", pt->value.number);
|
||||
g_string_printf(double_actual, "%.6f", pt_copy->value.number);
|
||||
g_assert_cmpstr(double_actual->str, ==, double_expected->str);
|
||||
|
||||
g_string_free(double_expected, true);
|
||||
g_string_free(double_actual, true);
|
||||
} else if (pt->type == PTYPE_BOOLEAN) {
|
||||
g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
|
||||
} else {
|
||||
@ -279,6 +349,328 @@ static void test_primitives(gconstpointer opaque)
|
||||
g_free(pt_copy);
|
||||
}
|
||||
|
||||
static void test_primitive_lists(gconstpointer opaque)
|
||||
{
|
||||
TestArgs *args = (TestArgs *) opaque;
|
||||
const SerializeOps *ops = args->ops;
|
||||
PrimitiveType *pt = args->test_data;
|
||||
PrimitiveList pl = { .value = { 0 } };
|
||||
PrimitiveList pl_copy = { .value = { 0 } };
|
||||
PrimitiveList *pl_copy_ptr = &pl_copy;
|
||||
Error *err = NULL;
|
||||
void *serialize_data;
|
||||
void *cur_head = NULL;
|
||||
int i;
|
||||
|
||||
pl.type = pl_copy.type = pt->type;
|
||||
|
||||
/* build up our list of primitive types */
|
||||
for (i = 0; i < 32; i++) {
|
||||
switch (pl.type) {
|
||||
case PTYPE_STRING: {
|
||||
strList *tmp = g_new0(strList, 1);
|
||||
tmp->value = g_strdup(pt->value.string);
|
||||
if (pl.value.strings == NULL) {
|
||||
pl.value.strings = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.strings;
|
||||
pl.value.strings = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_INTEGER: {
|
||||
intList *tmp = g_new0(intList, 1);
|
||||
tmp->value = pt->value.integer;
|
||||
if (pl.value.integers == NULL) {
|
||||
pl.value.integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.integers;
|
||||
pl.value.integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_S8: {
|
||||
int8List *tmp = g_new0(int8List, 1);
|
||||
tmp->value = pt->value.s8;
|
||||
if (pl.value.s8_integers == NULL) {
|
||||
pl.value.s8_integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.s8_integers;
|
||||
pl.value.s8_integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_S16: {
|
||||
int16List *tmp = g_new0(int16List, 1);
|
||||
tmp->value = pt->value.s16;
|
||||
if (pl.value.s16_integers == NULL) {
|
||||
pl.value.s16_integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.s16_integers;
|
||||
pl.value.s16_integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_S32: {
|
||||
int32List *tmp = g_new0(int32List, 1);
|
||||
tmp->value = pt->value.s32;
|
||||
if (pl.value.s32_integers == NULL) {
|
||||
pl.value.s32_integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.s32_integers;
|
||||
pl.value.s32_integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_S64: {
|
||||
int64List *tmp = g_new0(int64List, 1);
|
||||
tmp->value = pt->value.s64;
|
||||
if (pl.value.s64_integers == NULL) {
|
||||
pl.value.s64_integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.s64_integers;
|
||||
pl.value.s64_integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_U8: {
|
||||
uint8List *tmp = g_new0(uint8List, 1);
|
||||
tmp->value = pt->value.u8;
|
||||
if (pl.value.u8_integers == NULL) {
|
||||
pl.value.u8_integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.u8_integers;
|
||||
pl.value.u8_integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_U16: {
|
||||
uint16List *tmp = g_new0(uint16List, 1);
|
||||
tmp->value = pt->value.u16;
|
||||
if (pl.value.u16_integers == NULL) {
|
||||
pl.value.u16_integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.u16_integers;
|
||||
pl.value.u16_integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_U32: {
|
||||
uint32List *tmp = g_new0(uint32List, 1);
|
||||
tmp->value = pt->value.u32;
|
||||
if (pl.value.u32_integers == NULL) {
|
||||
pl.value.u32_integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.u32_integers;
|
||||
pl.value.u32_integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_U64: {
|
||||
uint64List *tmp = g_new0(uint64List, 1);
|
||||
tmp->value = pt->value.u64;
|
||||
if (pl.value.u64_integers == NULL) {
|
||||
pl.value.u64_integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.u64_integers;
|
||||
pl.value.u64_integers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_NUMBER: {
|
||||
numberList *tmp = g_new0(numberList, 1);
|
||||
tmp->value = pt->value.number;
|
||||
if (pl.value.numbers == NULL) {
|
||||
pl.value.numbers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.numbers;
|
||||
pl.value.numbers = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTYPE_BOOLEAN: {
|
||||
boolList *tmp = g_new0(boolList, 1);
|
||||
tmp->value = pt->value.boolean;
|
||||
if (pl.value.booleans == NULL) {
|
||||
pl.value.booleans = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.booleans;
|
||||
pl.value.booleans = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err);
|
||||
ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err);
|
||||
|
||||
g_assert(err == NULL);
|
||||
i = 0;
|
||||
|
||||
/* compare our deserialized list of primitives to the original */
|
||||
do {
|
||||
switch (pl_copy.type) {
|
||||
case PTYPE_STRING: {
|
||||
strList *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.strings;
|
||||
}
|
||||
g_assert_cmpstr(pt->value.string, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_INTEGER: {
|
||||
intList *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.integer, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_S8: {
|
||||
int8List *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.s8_integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.s8, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_S16: {
|
||||
int16List *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.s16_integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.s16, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_S32: {
|
||||
int32List *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.s32_integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.s32, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_S64: {
|
||||
int64List *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.s64_integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.s64, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_U8: {
|
||||
uint8List *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.u8_integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.u8, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_U16: {
|
||||
uint16List *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.u16_integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.u16, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_U32: {
|
||||
uint32List *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.u32_integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.u32, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_U64: {
|
||||
uint64List *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.u64_integers;
|
||||
}
|
||||
g_assert_cmpint(pt->value.u64, ==, ptr->value);
|
||||
break;
|
||||
}
|
||||
case PTYPE_NUMBER: {
|
||||
numberList *ptr;
|
||||
GString *double_expected = g_string_new("");
|
||||
GString *double_actual = g_string_new("");
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.numbers;
|
||||
}
|
||||
/* we serialize with %f for our reference visitors, so rather than
|
||||
* fuzzy floating math to test "equality", just compare the
|
||||
* formatted values
|
||||
*/
|
||||
g_string_printf(double_expected, "%.6f", pt->value.number);
|
||||
g_string_printf(double_actual, "%.6f", ptr->value);
|
||||
g_assert_cmpstr(double_actual->str, ==, double_expected->str);
|
||||
g_string_free(double_expected, true);
|
||||
g_string_free(double_actual, true);
|
||||
break;
|
||||
}
|
||||
case PTYPE_BOOLEAN: {
|
||||
boolList *ptr;
|
||||
if (cur_head) {
|
||||
ptr = cur_head;
|
||||
cur_head = ptr->next;
|
||||
} else {
|
||||
cur_head = ptr = pl_copy.value.booleans;
|
||||
}
|
||||
g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert(0);
|
||||
}
|
||||
i++;
|
||||
} while (cur_head);
|
||||
|
||||
g_assert_cmpint(i, ==, 33);
|
||||
|
||||
ops->cleanup(serialize_data);
|
||||
dealloc_helper(&pl, visit_primitive_list, &err);
|
||||
g_assert(!err);
|
||||
dealloc_helper(&pl_copy, visit_primitive_list, &err);
|
||||
g_assert(!err);
|
||||
g_free(args);
|
||||
}
|
||||
|
||||
static void test_struct(gconstpointer opaque)
|
||||
{
|
||||
TestArgs *args = (TestArgs *) opaque;
|
||||
@ -728,7 +1120,8 @@ static const SerializeOps visitors[] = {
|
||||
.serialize = qmp_serialize,
|
||||
.deserialize = qmp_deserialize,
|
||||
.cleanup = qmp_cleanup,
|
||||
.caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS
|
||||
.caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
|
||||
VCAP_PRIMITIVE_LISTS
|
||||
},
|
||||
{
|
||||
.type = "String",
|
||||
@ -782,6 +1175,19 @@ static void add_visitor_type(const SerializeOps *ops)
|
||||
args->test_data = NULL;
|
||||
g_test_add_data_func(testname, args, test_nested_struct_list);
|
||||
}
|
||||
|
||||
if (ops->caps & VCAP_PRIMITIVE_LISTS) {
|
||||
i = 0;
|
||||
while (pt_values[i].type != PTYPE_EOL) {
|
||||
sprintf(testname, "%s/primitive_list/%s", testname_prefix,
|
||||
pt_values[i].description);
|
||||
args = g_malloc0(sizeof(*args));
|
||||
args->ops = ops;
|
||||
args->test_data = &pt_values[i];
|
||||
g_test_add_data_func(testname, args, test_primitive_lists);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
13
ui/input.c
13
ui/input.c
@ -28,6 +28,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "qapi-types.h"
|
||||
#include "ui/keymaps.h"
|
||||
|
||||
struct QEMUPutMouseEntry {
|
||||
QEMUPutMouseEvent *qemu_put_mouse_event;
|
||||
@ -260,10 +261,10 @@ static void free_keycodes(void)
|
||||
static void release_keys(void *opaque)
|
||||
{
|
||||
while (keycodes_size > 0) {
|
||||
if (keycodes[--keycodes_size] & 0x80) {
|
||||
kbd_put_keycode(0xe0);
|
||||
if (keycodes[--keycodes_size] & SCANCODE_GREY) {
|
||||
kbd_put_keycode(SCANCODE_EMUL0);
|
||||
}
|
||||
kbd_put_keycode(keycodes[keycodes_size] | 0x80);
|
||||
kbd_put_keycode(keycodes[keycodes_size] | SCANCODE_UP);
|
||||
}
|
||||
|
||||
free_keycodes();
|
||||
@ -297,10 +298,10 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
|
||||
return;
|
||||
}
|
||||
|
||||
if (keycode & 0x80) {
|
||||
kbd_put_keycode(0xe0);
|
||||
if (keycode & SCANCODE_GREY) {
|
||||
kbd_put_keycode(SCANCODE_EMUL0);
|
||||
}
|
||||
kbd_put_keycode(keycode & 0x7f);
|
||||
kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
|
||||
|
||||
keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1));
|
||||
keycodes[keycodes_size++] = keycode;
|
||||
|
4
vl.c
4
vl.c
@ -3366,8 +3366,10 @@ int main(int argc, char **argv, char **envp)
|
||||
break;
|
||||
}
|
||||
case QEMU_OPTION_monitor:
|
||||
monitor_parse(optarg, "readline");
|
||||
default_monitor = 0;
|
||||
if (strncmp(optarg, "none", 4)) {
|
||||
monitor_parse(optarg, "readline");
|
||||
}
|
||||
break;
|
||||
case QEMU_OPTION_qmp:
|
||||
monitor_parse(optarg, "control");
|
||||
|
Loading…
Reference in New Issue
Block a user