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
|
# Build libraries
|
||||||
|
|
||||||
libqemustub.a: $(stub-obj-y)
|
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 :\
|
qapi-types.c qapi-types.h :\
|
||||||
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
|
$(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 :\
|
qapi-visit.c qapi-visit.h :\
|
||||||
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
|
$(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 :\
|
qmp-commands.h qmp-marshal.c :\
|
||||||
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
|
$(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 $@")
|
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@")
|
||||||
|
@ -32,6 +32,21 @@
|
|||||||
{ 'union': 'UserDefUnion',
|
{ 'union': 'UserDefUnion',
|
||||||
'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } }
|
'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
|
# testing commands
|
||||||
{ 'command': 'user_def_cmd', 'data': {} }
|
{ 'command': 'user_def_cmd', 'data': {} }
|
||||||
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
|
{ '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).
|
serial port).
|
||||||
The default device is @code{vc} in graphical mode and @code{stdio} in
|
The default device is @code{vc} in graphical mode and @code{stdio} in
|
||||||
non graphical mode.
|
non graphical mode.
|
||||||
|
Use @code{-monitor none} to disable the default monitor.
|
||||||
ETEXI
|
ETEXI
|
||||||
DEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \
|
DEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \
|
||||||
"-qmp dev like -monitor but opens in 'control' mode\n",
|
"-qmp dev like -monitor but opens in 'control' mode\n",
|
||||||
|
@ -640,9 +640,29 @@ static QObject *parse_literal(JSONParserContext *ctxt)
|
|||||||
case JSON_STRING:
|
case JSON_STRING:
|
||||||
obj = QOBJECT(qstring_from_escaped_str(ctxt, token));
|
obj = QOBJECT(qstring_from_escaped_str(ctxt, token));
|
||||||
break;
|
break;
|
||||||
case JSON_INTEGER:
|
case JSON_INTEGER: {
|
||||||
obj = QOBJECT(qint_from_int(strtoll(token_get_value(token), NULL, 10)));
|
/* A possibility exists that this is a whole-valued float where the
|
||||||
break;
|
* 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:
|
case JSON_FLOAT:
|
||||||
/* FIXME dependent on locale */
|
/* FIXME dependent on locale */
|
||||||
obj = QOBJECT(qfloat_from_double(strtod(token_get_value(token), NULL)));
|
obj = QOBJECT(qfloat_from_double(strtod(token_get_value(token), NULL)));
|
||||||
|
@ -16,8 +16,21 @@ import os
|
|||||||
import getopt
|
import getopt
|
||||||
import errno
|
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('''
|
return mcgen('''
|
||||||
|
|
||||||
typedef struct %(name)s %(name)s;
|
typedef struct %(name)s %(name)s;
|
||||||
|
|
||||||
typedef struct %(name)sList
|
typedef struct %(name)sList
|
||||||
@ -164,6 +177,7 @@ void qapi_free_%(type)s(%(c_type)s obj);
|
|||||||
|
|
||||||
def generate_type_cleanup(name):
|
def generate_type_cleanup(name):
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
|
|
||||||
void qapi_free_%(type)s(%(c_type)s obj)
|
void qapi_free_%(type)s(%(c_type)s obj)
|
||||||
{
|
{
|
||||||
QapiDeallocVisitor *md;
|
QapiDeallocVisitor *md;
|
||||||
@ -184,8 +198,9 @@ void qapi_free_%(type)s(%(c_type)s obj)
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
|
opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
|
||||||
["source", "header", "prefix=", "output-dir="])
|
["source", "header", "builtins",
|
||||||
|
"prefix=", "output-dir="])
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
print str(err)
|
print str(err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -197,6 +212,7 @@ h_file = 'qapi-types.h'
|
|||||||
|
|
||||||
do_c = False
|
do_c = False
|
||||||
do_h = False
|
do_h = False
|
||||||
|
do_builtins = False
|
||||||
|
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
if o in ("-p", "--prefix"):
|
if o in ("-p", "--prefix"):
|
||||||
@ -207,6 +223,8 @@ for o, a in opts:
|
|||||||
do_c = True
|
do_c = True
|
||||||
elif o in ("-h", "--header"):
|
elif o in ("-h", "--header"):
|
||||||
do_h = True
|
do_h = True
|
||||||
|
elif o in ("-b", "--builtins"):
|
||||||
|
do_builtins = True
|
||||||
|
|
||||||
if not do_c and not do_h:
|
if not do_c and not do_h:
|
||||||
do_c = True
|
do_c = True
|
||||||
@ -282,6 +300,11 @@ fdecl.write(mcgen('''
|
|||||||
exprs = parse_schema(sys.stdin)
|
exprs = parse_schema(sys.stdin)
|
||||||
exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
|
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:
|
for expr in exprs:
|
||||||
ret = "\n"
|
ret = "\n"
|
||||||
if expr.has_key('type'):
|
if expr.has_key('type'):
|
||||||
@ -298,6 +321,22 @@ for expr in exprs:
|
|||||||
continue
|
continue
|
||||||
fdecl.write(ret)
|
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:
|
for expr in exprs:
|
||||||
ret = "\n"
|
ret = "\n"
|
||||||
if expr.has_key('type'):
|
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(),
|
abbrev = de_camel_case(name).upper(),
|
||||||
enum = c_fun(de_camel_case(key),False).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))
|
c_name=c_fun(key))
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
@ -202,12 +202,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def generate_declaration(name, members, genlist=True):
|
def generate_declaration(name, members, genlist=True, builtin_type=False):
|
||||||
ret = mcgen('''
|
ret = ""
|
||||||
|
if not builtin_type:
|
||||||
|
ret += mcgen('''
|
||||||
|
|
||||||
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp);
|
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp);
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
if genlist:
|
if genlist:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
@ -235,8 +237,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e
|
|||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
|
opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
|
||||||
["source", "header", "prefix=", "output-dir="])
|
["source", "header", "builtins", "prefix=",
|
||||||
|
"output-dir="])
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
print str(err)
|
print str(err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -248,6 +251,7 @@ h_file = 'qapi-visit.h'
|
|||||||
|
|
||||||
do_c = False
|
do_c = False
|
||||||
do_h = False
|
do_h = False
|
||||||
|
do_builtins = False
|
||||||
|
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
if o in ("-p", "--prefix"):
|
if o in ("-p", "--prefix"):
|
||||||
@ -258,6 +262,8 @@ for o, a in opts:
|
|||||||
do_c = True
|
do_c = True
|
||||||
elif o in ("-h", "--header"):
|
elif o in ("-h", "--header"):
|
||||||
do_h = True
|
do_h = True
|
||||||
|
elif o in ("-b", "--builtins"):
|
||||||
|
do_builtins = True
|
||||||
|
|
||||||
if not do_c and not do_h:
|
if not do_c and not do_h:
|
||||||
do_c = True
|
do_c = True
|
||||||
@ -324,11 +330,29 @@ fdecl.write(mcgen('''
|
|||||||
|
|
||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
#include "%(prefix)sqapi-types.h"
|
#include "%(prefix)sqapi-types.h"
|
||||||
|
|
||||||
''',
|
''',
|
||||||
prefix=prefix, guard=guardname(h_file)))
|
prefix=prefix, guard=guardname(h_file)))
|
||||||
|
|
||||||
exprs = parse_schema(sys.stdin)
|
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:
|
for expr in exprs:
|
||||||
if expr.has_key('type'):
|
if expr.has_key('type'):
|
||||||
ret = generate_visit_struct(expr['type'], expr['data'])
|
ret = generate_visit_struct(expr['type'], expr['data'])
|
||||||
|
@ -11,6 +11,12 @@
|
|||||||
|
|
||||||
from ordereddict import OrderedDict
|
from ordereddict import OrderedDict
|
||||||
|
|
||||||
|
builtin_types = [
|
||||||
|
'str', 'int', 'number', 'bool',
|
||||||
|
'int8', 'int16', 'int32', 'int64',
|
||||||
|
'uint8', 'uint16', 'uint32', 'uint64'
|
||||||
|
]
|
||||||
|
|
||||||
def tokenize(data):
|
def tokenize(data):
|
||||||
while len(data):
|
while len(data):
|
||||||
ch = data[0]
|
ch = data[0]
|
||||||
@ -242,3 +248,20 @@ def guardname(filename):
|
|||||||
for substr in [".", " ", "-"]:
|
for substr in [".", " ", "-"]:
|
||||||
guard = guard.replace(substr, "_")
|
guard = guard.replace(substr, "_")
|
||||||
return guard.upper() + '_H'
|
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;
|
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,
|
static void test_visitor_in_int(TestInputVisitorData *data,
|
||||||
const void *unused)
|
const void *unused)
|
||||||
{
|
{
|
||||||
@ -75,6 +100,24 @@ static void test_visitor_in_int(TestInputVisitorData *data,
|
|||||||
g_assert_cmpint(res, ==, value);
|
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,
|
static void test_visitor_in_bool(TestInputVisitorData *data,
|
||||||
const void *unused)
|
const void *unused)
|
||||||
{
|
{
|
||||||
@ -259,6 +302,287 @@ static void test_visitor_in_union(TestInputVisitorData *data,
|
|||||||
qapi_free_UserDefUnion(tmp);
|
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,
|
static void input_visitor_test_add(const char *testpath,
|
||||||
TestInputVisitorData *data,
|
TestInputVisitorData *data,
|
||||||
void (*test_func)(TestInputVisitorData *data, const void *user_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",
|
input_visitor_test_add("/visitor/input/int",
|
||||||
&in_visitor_data, test_visitor_in_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",
|
input_visitor_test_add("/visitor/input/bool",
|
||||||
&in_visitor_data, test_visitor_in_bool);
|
&in_visitor_data, test_visitor_in_bool);
|
||||||
input_visitor_test_add("/visitor/input/number",
|
input_visitor_test_add("/visitor/input/number",
|
||||||
@ -310,6 +636,38 @@ int main(int argc, char **argv)
|
|||||||
&in_visitor_data, test_visitor_in_union);
|
&in_visitor_data, test_visitor_in_union);
|
||||||
input_visitor_test_add("/visitor/input/errors",
|
input_visitor_test_add("/visitor/input/errors",
|
||||||
&in_visitor_data, test_visitor_in_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();
|
g_test_run();
|
||||||
|
|
||||||
|
@ -431,6 +431,314 @@ static void test_visitor_out_union(TestOutputVisitorData *data,
|
|||||||
QDECREF(qdict);
|
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,
|
static void output_visitor_test_add(const char *testpath,
|
||||||
TestOutputVisitorData *data,
|
TestOutputVisitorData *data,
|
||||||
void (*test_func)(TestOutputVisitorData *data, const void *user_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);
|
&out_visitor_data, test_visitor_out_list_qapi_free);
|
||||||
output_visitor_test_add("/visitor/output/union",
|
output_visitor_test_add("/visitor/output/union",
|
||||||
&out_visitor_data, test_visitor_out_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();
|
g_test_run();
|
||||||
|
|
||||||
|
@ -23,6 +23,25 @@
|
|||||||
#include "qapi/qmp-output-visitor.h"
|
#include "qapi/qmp-output-visitor.h"
|
||||||
#include "qapi/string-input-visitor.h"
|
#include "qapi/string-input-visitor.h"
|
||||||
#include "qapi/string-output-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 {
|
typedef struct PrimitiveType {
|
||||||
union {
|
union {
|
||||||
@ -40,26 +59,42 @@ typedef struct PrimitiveType {
|
|||||||
int64_t s64;
|
int64_t s64;
|
||||||
intmax_t max;
|
intmax_t max;
|
||||||
} value;
|
} value;
|
||||||
enum {
|
enum PrimitiveTypeKind type;
|
||||||
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;
|
|
||||||
const char *description;
|
const char *description;
|
||||||
} PrimitiveType;
|
} 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 */
|
/* 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)
|
static void visit_primitive_type(Visitor *v, void **native, Error **errp)
|
||||||
{
|
{
|
||||||
PrimitiveType *pt = *native;
|
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
|
typedef struct TestStruct
|
||||||
{
|
{
|
||||||
int64_t integer;
|
int64_t integer;
|
||||||
@ -206,12 +286,11 @@ static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
|
|||||||
|
|
||||||
/* test cases */
|
/* test cases */
|
||||||
|
|
||||||
typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
|
|
||||||
|
|
||||||
typedef enum VisitorCapabilities {
|
typedef enum VisitorCapabilities {
|
||||||
VCAP_PRIMITIVES = 1,
|
VCAP_PRIMITIVES = 1,
|
||||||
VCAP_STRUCTURES = 2,
|
VCAP_STRUCTURES = 2,
|
||||||
VCAP_LISTS = 4,
|
VCAP_LISTS = 4,
|
||||||
|
VCAP_PRIMITIVE_LISTS = 8,
|
||||||
} VisitorCapabilities;
|
} VisitorCapabilities;
|
||||||
|
|
||||||
typedef struct SerializeOps {
|
typedef struct SerializeOps {
|
||||||
@ -229,17 +308,6 @@ typedef struct TestArgs {
|
|||||||
void *test_data;
|
void *test_data;
|
||||||
} TestArgs;
|
} 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)
|
static void test_primitives(gconstpointer opaque)
|
||||||
{
|
{
|
||||||
TestArgs *args = (TestArgs *) opaque;
|
TestArgs *args = (TestArgs *) opaque;
|
||||||
@ -248,7 +316,6 @@ static void test_primitives(gconstpointer opaque)
|
|||||||
PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
|
PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
void *serialize_data;
|
void *serialize_data;
|
||||||
char *double1, *double2;
|
|
||||||
|
|
||||||
pt_copy->type = pt->type;
|
pt_copy->type = pt->type;
|
||||||
ops->serialize(pt, &serialize_data, visit_primitive_type, &err);
|
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_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
|
||||||
g_free((char *)pt_copy->value.string);
|
g_free((char *)pt_copy->value.string);
|
||||||
} else if (pt->type == PTYPE_NUMBER) {
|
} 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
|
/* we serialize with %f for our reference visitors, so rather than fuzzy
|
||||||
* floating math to test "equality", just compare the formatted values
|
* floating math to test "equality", just compare the formatted values
|
||||||
*/
|
*/
|
||||||
double1 = g_malloc0(calc_float_string_storage(pt->value.number));
|
g_string_printf(double_expected, "%.6f", pt->value.number);
|
||||||
double2 = g_malloc0(calc_float_string_storage(pt_copy->value.number));
|
g_string_printf(double_actual, "%.6f", pt_copy->value.number);
|
||||||
g_assert_cmpstr(double1, ==, double2);
|
g_assert_cmpstr(double_actual->str, ==, double_expected->str);
|
||||||
g_free(double1);
|
|
||||||
g_free(double2);
|
g_string_free(double_expected, true);
|
||||||
|
g_string_free(double_actual, true);
|
||||||
} else if (pt->type == PTYPE_BOOLEAN) {
|
} else if (pt->type == PTYPE_BOOLEAN) {
|
||||||
g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
|
g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
|
||||||
} else {
|
} else {
|
||||||
@ -279,6 +349,328 @@ static void test_primitives(gconstpointer opaque)
|
|||||||
g_free(pt_copy);
|
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)
|
static void test_struct(gconstpointer opaque)
|
||||||
{
|
{
|
||||||
TestArgs *args = (TestArgs *) opaque;
|
TestArgs *args = (TestArgs *) opaque;
|
||||||
@ -728,7 +1120,8 @@ static const SerializeOps visitors[] = {
|
|||||||
.serialize = qmp_serialize,
|
.serialize = qmp_serialize,
|
||||||
.deserialize = qmp_deserialize,
|
.deserialize = qmp_deserialize,
|
||||||
.cleanup = qmp_cleanup,
|
.cleanup = qmp_cleanup,
|
||||||
.caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS
|
.caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
|
||||||
|
VCAP_PRIMITIVE_LISTS
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.type = "String",
|
.type = "String",
|
||||||
@ -782,6 +1175,19 @@ static void add_visitor_type(const SerializeOps *ops)
|
|||||||
args->test_data = NULL;
|
args->test_data = NULL;
|
||||||
g_test_add_data_func(testname, args, test_nested_struct_list);
|
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)
|
int main(int argc, char **argv)
|
||||||
|
13
ui/input.c
13
ui/input.c
@ -28,6 +28,7 @@
|
|||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qmp-commands.h"
|
#include "qmp-commands.h"
|
||||||
#include "qapi-types.h"
|
#include "qapi-types.h"
|
||||||
|
#include "ui/keymaps.h"
|
||||||
|
|
||||||
struct QEMUPutMouseEntry {
|
struct QEMUPutMouseEntry {
|
||||||
QEMUPutMouseEvent *qemu_put_mouse_event;
|
QEMUPutMouseEvent *qemu_put_mouse_event;
|
||||||
@ -260,10 +261,10 @@ static void free_keycodes(void)
|
|||||||
static void release_keys(void *opaque)
|
static void release_keys(void *opaque)
|
||||||
{
|
{
|
||||||
while (keycodes_size > 0) {
|
while (keycodes_size > 0) {
|
||||||
if (keycodes[--keycodes_size] & 0x80) {
|
if (keycodes[--keycodes_size] & SCANCODE_GREY) {
|
||||||
kbd_put_keycode(0xe0);
|
kbd_put_keycode(SCANCODE_EMUL0);
|
||||||
}
|
}
|
||||||
kbd_put_keycode(keycodes[keycodes_size] | 0x80);
|
kbd_put_keycode(keycodes[keycodes_size] | SCANCODE_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_keycodes();
|
free_keycodes();
|
||||||
@ -297,10 +298,10 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keycode & 0x80) {
|
if (keycode & SCANCODE_GREY) {
|
||||||
kbd_put_keycode(0xe0);
|
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 = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1));
|
||||||
keycodes[keycodes_size++] = keycode;
|
keycodes[keycodes_size++] = keycode;
|
||||||
|
4
vl.c
4
vl.c
@ -3366,8 +3366,10 @@ int main(int argc, char **argv, char **envp)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QEMU_OPTION_monitor:
|
case QEMU_OPTION_monitor:
|
||||||
monitor_parse(optarg, "readline");
|
|
||||||
default_monitor = 0;
|
default_monitor = 0;
|
||||||
|
if (strncmp(optarg, "none", 4)) {
|
||||||
|
monitor_parse(optarg, "readline");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_qmp:
|
case QEMU_OPTION_qmp:
|
||||||
monitor_parse(optarg, "control");
|
monitor_parse(optarg, "control");
|
||||||
|
Loading…
Reference in New Issue
Block a user