mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-01 23:03:54 -06:00
test makefile overhaul
This introduces new test reporting infrastructure based on gtester and gtester-report. Also, all existing tests are moved to tests/, and tests/Makefile is reorganized to factor out the commonalities in the rules. Signed-off-by: Anthony Liguori <aliguori@linux.vnet.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
040b66f3f9
commit
b93b63f574
16 changed files with 119 additions and 41 deletions
132
tests/Makefile
132
tests/Makefile
|
@ -1,61 +1,113 @@
|
|||
export SRC_PATH
|
||||
|
||||
CHECKS = check-qdict check-qfloat check-qint check-qstring check-qlist
|
||||
CHECKS += check-qjson test-qmp-output-visitor test-qmp-input-visitor
|
||||
CHECKS += test-string-input-visitor test-string-output-visitor test-coroutine
|
||||
CHECKS += test-qmp-commands
|
||||
CHECKS += $(SRC_PATH)/tests/qemu-iotests-quick.sh
|
||||
check-unit-y = tests/check-qdict$(EXESUF)
|
||||
check-unit-y += tests/check-qfloat$(EXESUF)
|
||||
check-unit-y += tests/check-qint$(EXESUF)
|
||||
check-unit-y += tests/check-qstring$(EXESUF)
|
||||
check-unit-y += tests/check-qlist$(EXESUF)
|
||||
check-unit-y += tests/check-qjson$(EXESUF)
|
||||
check-unit-y += tests/test-qmp-output-visitor$(EXESUF)
|
||||
check-unit-y += tests/test-qmp-input-visitor$(EXESUF)
|
||||
check-unit-y += tests/test-qmp-input-strict$(EXESUF)
|
||||
check-unit-y += tests/test-qmp-commands$(EXESUF)
|
||||
check-unit-y += tests/test-string-input-visitor$(EXESUF)
|
||||
check-unit-y += tests/test-string-output-visitor$(EXESUF)
|
||||
check-unit-y += tests/test-coroutine$(EXESUF)
|
||||
|
||||
check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
|
||||
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
|
||||
|
||||
check-qint: check-qint.o qint.o $(tools-obj-y)
|
||||
check-qstring: check-qstring.o qstring.o $(tools-obj-y)
|
||||
check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y)
|
||||
check-qlist: check-qlist.o qlist.o qint.o $(tools-obj-y)
|
||||
check-qfloat: check-qfloat.o qfloat.o $(tools-obj-y)
|
||||
check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
|
||||
test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
|
||||
GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
|
||||
|
||||
test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-input-strict.o \
|
||||
test-string-input-visitor.o test-string-output-visitor.o \
|
||||
test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
|
||||
test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
|
||||
tests/check-qlist.o tests/check-qfloat.o tests/check-qjson.o \
|
||||
tests/test-coroutine.o tests/test-string-output-visitor.o \
|
||||
tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
|
||||
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
|
||||
tests/test-qmp-commands.o
|
||||
|
||||
$(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
|
||||
test-qapi-obj-y = $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y)
|
||||
test-qapi-obj-y += tests/test-qapi-visit.o tests/test-qapi-types.o
|
||||
test-qapi-obj-y += module.o
|
||||
|
||||
$(test-obj-y): $(GENERATED_HEADERS)
|
||||
$(test-obj-y): QEMU_INCLUDES += -Itests
|
||||
|
||||
tests/check-qint$(EXESUF): tests/check-qint.o qint.o $(tools-obj-y)
|
||||
tests/check-qstring$(EXESUF): tests/check-qstring.o qstring.o $(tools-obj-y)
|
||||
tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y)
|
||||
tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o $(tools-obj-y)
|
||||
tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o $(tools-obj-y)
|
||||
tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y)
|
||||
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y)
|
||||
|
||||
tests/test-qapi-types.c tests/test-qapi-types.h :\
|
||||
$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
|
||||
$(qapi-dir)/test-qapi-visit.c $(qapi-dir)/test-qapi-visit.h :\
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
|
||||
tests/test-qapi-visit.c tests/test-qapi-visit.h :\
|
||||
$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
|
||||
$(qapi-dir)/test-qmp-commands.h $(qapi-dir)/test-qmp-marshal.c :\
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
|
||||
tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
|
||||
$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
|
||||
|
||||
|
||||
test-string-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
|
||||
test-string-output-visitor: test-string-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
|
||||
tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
|
||||
tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
|
||||
|
||||
test-string-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
|
||||
test-string-input-visitor: test-string-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
|
||||
.PHONY: check-help
|
||||
check-help:
|
||||
@echo "Regression testing targets:"
|
||||
@echo
|
||||
@echo " make check Run all tests"
|
||||
@echo " make check-unit Run qobject tests"
|
||||
@echo " make check-block Run block tests"
|
||||
@echo " make check-report.html Generates an HTML test report"
|
||||
@echo
|
||||
@echo "Please note that HTML reports do not regenerate if the unit tests"
|
||||
@echo "has not changed."
|
||||
@echo
|
||||
@echo "The variable SPEED can be set to control the gtester speed setting."
|
||||
@echo "Default options are -k and (for make V=1) --verbose; they can be"
|
||||
@echo "changed with variable GTESTER_OPTIONS."
|
||||
|
||||
test-qmp-input-strict.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
|
||||
test-qmp-input-strict: test-qmp-input-strict.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
|
||||
.SECONDARY:
|
||||
|
||||
test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
|
||||
test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
|
||||
SPEED = quick
|
||||
GTESTER_OPTIONS = -k $(if $(V),--verbose,-q)
|
||||
|
||||
test-qmp-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
|
||||
test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
|
||||
# gtester tests, possibly with verbose output
|
||||
|
||||
test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
|
||||
test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
|
||||
.PHONY: $(patsubst %, check-%, $(check-unit-y))
|
||||
$(patsubst %, check-%, $(check-unit-y)): check-%: %
|
||||
$(call quiet-command,gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
|
||||
|
||||
$(SRC_PATH)/tests/qemu-iotests-quick.sh: qemu-img qemu-io
|
||||
# gtester tests with XML output
|
||||
|
||||
check-report-unit.xml: $(check-unit-y)
|
||||
$(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^, "GTESTER $@")
|
||||
|
||||
# Reports and overall runs
|
||||
|
||||
check-report.xml: check-report-unit.xml
|
||||
$(call quiet-command,$(SRC_PATH)/scripts/gtester-cat $^ > $@, " GEN $@")
|
||||
|
||||
check-report.html: check-report.xml
|
||||
$(call quiet-command,gtester-report $< > $@, " GEN $@")
|
||||
|
||||
|
||||
.PHONY: check check-block
|
||||
# Other tests
|
||||
|
||||
check: $(CHECKS)
|
||||
$(call quiet-command, gtester $(CHECKS), " CHECK")
|
||||
.PHONY: check-tests/qemu-iotests-quick.sh
|
||||
check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF)
|
||||
$<
|
||||
|
||||
check-block:
|
||||
$(call quiet-command, $(SHELL) $(SRC_PATH)/tests/check-block.sh , " CHECK")
|
||||
# Consolidated targets
|
||||
|
||||
.PHONY: check-unit check
|
||||
check-unit: $(patsubst %,check-%, $(check-unit-y))
|
||||
check-block: $(patsubst %,check-%, $(check-block-y))
|
||||
check: check-unit
|
||||
|
|
378
tests/check-qdict.c
Normal file
378
tests/check-qdict.c
Normal file
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* QDict unit-tests.
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
#include <glib.h>
|
||||
|
||||
#include "qint.h"
|
||||
#include "qdict.h"
|
||||
#include "qstring.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
/*
|
||||
* Public Interface test-cases
|
||||
*
|
||||
* (with some violations to access 'private' data)
|
||||
*/
|
||||
|
||||
static void qdict_new_test(void)
|
||||
{
|
||||
QDict *qdict;
|
||||
|
||||
qdict = qdict_new();
|
||||
g_assert(qdict != NULL);
|
||||
g_assert(qdict_size(qdict) == 0);
|
||||
g_assert(qdict->base.refcnt == 1);
|
||||
g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
|
||||
|
||||
// destroy doesn't exit yet
|
||||
g_free(qdict);
|
||||
}
|
||||
|
||||
static void qdict_put_obj_test(void)
|
||||
{
|
||||
QInt *qi;
|
||||
QDict *qdict;
|
||||
QDictEntry *ent;
|
||||
const int num = 42;
|
||||
|
||||
qdict = qdict_new();
|
||||
|
||||
// key "" will have tdb hash 12345
|
||||
qdict_put_obj(qdict, "", QOBJECT(qint_from_int(num)));
|
||||
|
||||
g_assert(qdict_size(qdict) == 1);
|
||||
ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
|
||||
qi = qobject_to_qint(ent->value);
|
||||
g_assert(qint_get_int(qi) == num);
|
||||
|
||||
// destroy doesn't exit yet
|
||||
QDECREF(qi);
|
||||
g_free(ent->key);
|
||||
g_free(ent);
|
||||
g_free(qdict);
|
||||
}
|
||||
|
||||
static void qdict_destroy_simple_test(void)
|
||||
{
|
||||
QDict *qdict;
|
||||
|
||||
qdict = qdict_new();
|
||||
qdict_put_obj(qdict, "num", QOBJECT(qint_from_int(0)));
|
||||
qdict_put_obj(qdict, "str", QOBJECT(qstring_from_str("foo")));
|
||||
|
||||
QDECREF(qdict);
|
||||
}
|
||||
|
||||
static void qdict_get_test(void)
|
||||
{
|
||||
QInt *qi;
|
||||
QObject *obj;
|
||||
const int value = -42;
|
||||
const char *key = "test";
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
qdict_put(tests_dict, key, qint_from_int(value));
|
||||
|
||||
obj = qdict_get(tests_dict, key);
|
||||
g_assert(obj != NULL);
|
||||
|
||||
qi = qobject_to_qint(obj);
|
||||
g_assert(qint_get_int(qi) == value);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_get_int_test(void)
|
||||
{
|
||||
int ret;
|
||||
const int value = 100;
|
||||
const char *key = "int";
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
qdict_put(tests_dict, key, qint_from_int(value));
|
||||
|
||||
ret = qdict_get_int(tests_dict, key);
|
||||
g_assert(ret == value);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_get_try_int_test(void)
|
||||
{
|
||||
int ret;
|
||||
const int value = 100;
|
||||
const char *key = "int";
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
qdict_put(tests_dict, key, qint_from_int(value));
|
||||
|
||||
ret = qdict_get_try_int(tests_dict, key, 0);
|
||||
g_assert(ret == value);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_get_str_test(void)
|
||||
{
|
||||
const char *p;
|
||||
const char *key = "key";
|
||||
const char *str = "string";
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
qdict_put(tests_dict, key, qstring_from_str(str));
|
||||
|
||||
p = qdict_get_str(tests_dict, key);
|
||||
g_assert(p != NULL);
|
||||
g_assert(strcmp(p, str) == 0);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_get_try_str_test(void)
|
||||
{
|
||||
const char *p;
|
||||
const char *key = "key";
|
||||
const char *str = "string";
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
qdict_put(tests_dict, key, qstring_from_str(str));
|
||||
|
||||
p = qdict_get_try_str(tests_dict, key);
|
||||
g_assert(p != NULL);
|
||||
g_assert(strcmp(p, str) == 0);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_haskey_not_test(void)
|
||||
{
|
||||
QDict *tests_dict = qdict_new();
|
||||
g_assert(qdict_haskey(tests_dict, "test") == 0);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_haskey_test(void)
|
||||
{
|
||||
const char *key = "test";
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
qdict_put(tests_dict, key, qint_from_int(0));
|
||||
g_assert(qdict_haskey(tests_dict, key) == 1);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_del_test(void)
|
||||
{
|
||||
const char *key = "key test";
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
qdict_put(tests_dict, key, qstring_from_str("foo"));
|
||||
g_assert(qdict_size(tests_dict) == 1);
|
||||
|
||||
qdict_del(tests_dict, key);
|
||||
|
||||
g_assert(qdict_size(tests_dict) == 0);
|
||||
g_assert(qdict_haskey(tests_dict, key) == 0);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qobject_to_qdict_test(void)
|
||||
{
|
||||
QDict *tests_dict = qdict_new();
|
||||
g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_iterapi_test(void)
|
||||
{
|
||||
int count;
|
||||
const QDictEntry *ent;
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
g_assert(qdict_first(tests_dict) == NULL);
|
||||
|
||||
qdict_put(tests_dict, "key1", qint_from_int(1));
|
||||
qdict_put(tests_dict, "key2", qint_from_int(2));
|
||||
qdict_put(tests_dict, "key3", qint_from_int(3));
|
||||
|
||||
count = 0;
|
||||
for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
|
||||
g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
|
||||
count++;
|
||||
}
|
||||
|
||||
g_assert(count == qdict_size(tests_dict));
|
||||
|
||||
/* Do it again to test restarting */
|
||||
count = 0;
|
||||
for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
|
||||
g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
|
||||
count++;
|
||||
}
|
||||
|
||||
g_assert(count == qdict_size(tests_dict));
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors test-cases
|
||||
*/
|
||||
|
||||
static void qdict_put_exists_test(void)
|
||||
{
|
||||
int value;
|
||||
const char *key = "exists";
|
||||
QDict *tests_dict = qdict_new();
|
||||
|
||||
qdict_put(tests_dict, key, qint_from_int(1));
|
||||
qdict_put(tests_dict, key, qint_from_int(2));
|
||||
|
||||
value = qdict_get_int(tests_dict, key);
|
||||
g_assert(value == 2);
|
||||
|
||||
g_assert(qdict_size(tests_dict) == 1);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
static void qdict_get_not_exists_test(void)
|
||||
{
|
||||
QDict *tests_dict = qdict_new();
|
||||
g_assert(qdict_get(tests_dict, "foo") == NULL);
|
||||
|
||||
QDECREF(tests_dict);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stress test-case
|
||||
*
|
||||
* This is a lot big for a unit-test, but there is no other place
|
||||
* to have it.
|
||||
*/
|
||||
|
||||
static void remove_dots(char *string)
|
||||
{
|
||||
char *p = strchr(string, ':');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
static QString *read_line(FILE *file, char *key)
|
||||
{
|
||||
char value[128];
|
||||
|
||||
if (fscanf(file, "%127s%127s", key, value) == EOF) {
|
||||
return NULL;
|
||||
}
|
||||
remove_dots(key);
|
||||
return qstring_from_str(value);
|
||||
}
|
||||
|
||||
#define reset_file(file) fseek(file, 0L, SEEK_SET)
|
||||
|
||||
static void qdict_stress_test(void)
|
||||
{
|
||||
size_t lines;
|
||||
char key[128];
|
||||
FILE *test_file;
|
||||
QDict *qdict;
|
||||
QString *value;
|
||||
const char *test_file_path = "qdict-test-data.txt";
|
||||
|
||||
test_file = fopen(test_file_path, "r");
|
||||
g_assert(test_file != NULL);
|
||||
|
||||
// Create the dict
|
||||
qdict = qdict_new();
|
||||
g_assert(qdict != NULL);
|
||||
|
||||
// Add everything from the test file
|
||||
for (lines = 0;; lines++) {
|
||||
value = read_line(test_file, key);
|
||||
if (!value)
|
||||
break;
|
||||
|
||||
qdict_put(qdict, key, value);
|
||||
}
|
||||
g_assert(qdict_size(qdict) == lines);
|
||||
|
||||
// Check if everything is really in there
|
||||
reset_file(test_file);
|
||||
for (;;) {
|
||||
const char *str1, *str2;
|
||||
|
||||
value = read_line(test_file, key);
|
||||
if (!value)
|
||||
break;
|
||||
|
||||
str1 = qstring_get_str(value);
|
||||
|
||||
str2 = qdict_get_str(qdict, key);
|
||||
g_assert(str2 != NULL);
|
||||
|
||||
g_assert(strcmp(str1, str2) == 0);
|
||||
|
||||
QDECREF(value);
|
||||
}
|
||||
|
||||
// Delete everything
|
||||
reset_file(test_file);
|
||||
for (;;) {
|
||||
value = read_line(test_file, key);
|
||||
if (!value)
|
||||
break;
|
||||
|
||||
qdict_del(qdict, key);
|
||||
QDECREF(value);
|
||||
|
||||
g_assert(qdict_haskey(qdict, key) == 0);
|
||||
}
|
||||
fclose(test_file);
|
||||
|
||||
g_assert(qdict_size(qdict) == 0);
|
||||
QDECREF(qdict);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/public/new", qdict_new_test);
|
||||
g_test_add_func("/public/put_obj", qdict_put_obj_test);
|
||||
g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
|
||||
|
||||
/* Continue, but now with fixtures */
|
||||
g_test_add_func("/public/get", qdict_get_test);
|
||||
g_test_add_func("/public/get_int", qdict_get_int_test);
|
||||
g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
|
||||
g_test_add_func("/public/get_str", qdict_get_str_test);
|
||||
g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
|
||||
g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
|
||||
g_test_add_func("/public/haskey", qdict_haskey_test);
|
||||
g_test_add_func("/public/del", qdict_del_test);
|
||||
g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
|
||||
g_test_add_func("/public/iterapi", qdict_iterapi_test);
|
||||
|
||||
g_test_add_func("/errors/put_exists", qdict_put_exists_test);
|
||||
g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
|
||||
|
||||
/* The Big one */
|
||||
if (g_test_slow()) {
|
||||
g_test_add_func("/stress/test", qdict_stress_test);
|
||||
}
|
||||
|
||||
return g_test_run();
|
||||
}
|
53
tests/check-qfloat.c
Normal file
53
tests/check-qfloat.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* QFloat unit-tests.
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
#include <glib.h>
|
||||
|
||||
#include "qfloat.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
/*
|
||||
* Public Interface test-cases
|
||||
*
|
||||
* (with some violations to access 'private' data)
|
||||
*/
|
||||
|
||||
static void qfloat_from_double_test(void)
|
||||
{
|
||||
QFloat *qf;
|
||||
const double value = -42.23423;
|
||||
|
||||
qf = qfloat_from_double(value);
|
||||
g_assert(qf != NULL);
|
||||
g_assert(qf->value == value);
|
||||
g_assert(qf->base.refcnt == 1);
|
||||
g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
|
||||
|
||||
// destroy doesn't exit yet
|
||||
g_free(qf);
|
||||
}
|
||||
|
||||
static void qfloat_destroy_test(void)
|
||||
{
|
||||
QFloat *qf = qfloat_from_double(0.0);
|
||||
QDECREF(qf);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/public/from_double", qfloat_from_double_test);
|
||||
g_test_add_func("/public/destroy", qfloat_destroy_test);
|
||||
|
||||
return g_test_run();
|
||||
}
|
87
tests/check-qint.c
Normal file
87
tests/check-qint.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* QInt unit-tests.
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
#include <glib.h>
|
||||
|
||||
#include "qint.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
/*
|
||||
* Public Interface test-cases
|
||||
*
|
||||
* (with some violations to access 'private' data)
|
||||
*/
|
||||
|
||||
static void qint_from_int_test(void)
|
||||
{
|
||||
QInt *qi;
|
||||
const int value = -42;
|
||||
|
||||
qi = qint_from_int(value);
|
||||
g_assert(qi != NULL);
|
||||
g_assert(qi->value == value);
|
||||
g_assert(qi->base.refcnt == 1);
|
||||
g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
|
||||
|
||||
// destroy doesn't exit yet
|
||||
g_free(qi);
|
||||
}
|
||||
|
||||
static void qint_destroy_test(void)
|
||||
{
|
||||
QInt *qi = qint_from_int(0);
|
||||
QDECREF(qi);
|
||||
}
|
||||
|
||||
static void qint_from_int64_test(void)
|
||||
{
|
||||
QInt *qi;
|
||||
const int64_t value = 0x1234567890abcdefLL;
|
||||
|
||||
qi = qint_from_int(value);
|
||||
g_assert((int64_t) qi->value == value);
|
||||
|
||||
QDECREF(qi);
|
||||
}
|
||||
|
||||
static void qint_get_int_test(void)
|
||||
{
|
||||
QInt *qi;
|
||||
const int value = 123456;
|
||||
|
||||
qi = qint_from_int(value);
|
||||
g_assert(qint_get_int(qi) == value);
|
||||
|
||||
QDECREF(qi);
|
||||
}
|
||||
|
||||
static void qobject_to_qint_test(void)
|
||||
{
|
||||
QInt *qi;
|
||||
|
||||
qi = qint_from_int(0);
|
||||
g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
|
||||
|
||||
QDECREF(qi);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/public/from_int", qint_from_int_test);
|
||||
g_test_add_func("/public/destroy", qint_destroy_test);
|
||||
g_test_add_func("/public/from_int64", qint_from_int64_test);
|
||||
g_test_add_func("/public/get_int", qint_get_int_test);
|
||||
g_test_add_func("/public/to_qint", qobject_to_qint_test);
|
||||
|
||||
return g_test_run();
|
||||
}
|
728
tests/check-qjson.c
Normal file
728
tests/check-qjson.c
Normal file
|
@ -0,0 +1,728 @@
|
|||
/*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
#include <glib.h>
|
||||
|
||||
#include "qstring.h"
|
||||
#include "qint.h"
|
||||
#include "qdict.h"
|
||||
#include "qlist.h"
|
||||
#include "qfloat.h"
|
||||
#include "qbool.h"
|
||||
#include "qjson.h"
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void escaped_string(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
const char *decoded;
|
||||
int skip;
|
||||
} test_cases[] = {
|
||||
{ "\"\\b\"", "\b" },
|
||||
{ "\"\\f\"", "\f" },
|
||||
{ "\"\\n\"", "\n" },
|
||||
{ "\"\\r\"", "\r" },
|
||||
{ "\"\\t\"", "\t" },
|
||||
{ "\"/\"", "/" },
|
||||
{ "\"\\/\"", "/", .skip = 1 },
|
||||
{ "\"\\\\\"", "\\" },
|
||||
{ "\"\\\"\"", "\"" },
|
||||
{ "\"hello world \\\"embedded string\\\"\"",
|
||||
"hello world \"embedded string\"" },
|
||||
{ "\"hello world\\nwith new line\"", "hello world\nwith new line" },
|
||||
{ "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
|
||||
{ "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
|
||||
{ "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
|
||||
{}
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded);
|
||||
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QSTRING);
|
||||
|
||||
str = qobject_to_qstring(obj);
|
||||
g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
|
||||
|
||||
if (test_cases[i].skip == 0) {
|
||||
str = qobject_to_json(obj);
|
||||
g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
QDECREF(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void simple_string(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
const char *decoded;
|
||||
} test_cases[] = {
|
||||
{ "\"hello world\"", "hello world" },
|
||||
{ "\"the quick brown fox jumped over the fence\"",
|
||||
"the quick brown fox jumped over the fence" },
|
||||
{}
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded);
|
||||
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QSTRING);
|
||||
|
||||
str = qobject_to_qstring(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
|
||||
|
||||
qobject_decref(obj);
|
||||
|
||||
QDECREF(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void single_quote_string(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
const char *decoded;
|
||||
} test_cases[] = {
|
||||
{ "'hello world'", "hello world" },
|
||||
{ "'the quick brown fox \\' jumped over the fence'",
|
||||
"the quick brown fox ' jumped over the fence" },
|
||||
{}
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded);
|
||||
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QSTRING);
|
||||
|
||||
str = qobject_to_qstring(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
|
||||
|
||||
QDECREF(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void vararg_string(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *decoded;
|
||||
} test_cases[] = {
|
||||
{ "hello world" },
|
||||
{ "the quick brown fox jumped over the fence" },
|
||||
{}
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].decoded; i++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_jsonf("%s", test_cases[i].decoded);
|
||||
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QSTRING);
|
||||
|
||||
str = qobject_to_qstring(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
|
||||
|
||||
QDECREF(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void simple_number(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
int64_t decoded;
|
||||
int skip;
|
||||
} test_cases[] = {
|
||||
{ "0", 0 },
|
||||
{ "1234", 1234 },
|
||||
{ "1", 1 },
|
||||
{ "-32", -32 },
|
||||
{ "-0", 0, .skip = 1 },
|
||||
{ },
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QInt *qint;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QINT);
|
||||
|
||||
qint = qobject_to_qint(obj);
|
||||
g_assert(qint_get_int(qint) == test_cases[i].decoded);
|
||||
if (test_cases[i].skip == 0) {
|
||||
QString *str;
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
|
||||
QDECREF(str);
|
||||
}
|
||||
|
||||
QDECREF(qint);
|
||||
}
|
||||
}
|
||||
|
||||
static void float_number(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
double decoded;
|
||||
int skip;
|
||||
} test_cases[] = {
|
||||
{ "32.43", 32.43 },
|
||||
{ "0.222", 0.222 },
|
||||
{ "-32.12313", -32.12313 },
|
||||
{ "-32.20e-10", -32.20e-10, .skip = 1 },
|
||||
{ },
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QFloat *qfloat;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QFLOAT);
|
||||
|
||||
qfloat = qobject_to_qfloat(obj);
|
||||
g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
|
||||
|
||||
if (test_cases[i].skip == 0) {
|
||||
QString *str;
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
|
||||
QDECREF(str);
|
||||
}
|
||||
|
||||
QDECREF(qfloat);
|
||||
}
|
||||
}
|
||||
|
||||
static void vararg_number(void)
|
||||
{
|
||||
QObject *obj;
|
||||
QInt *qint;
|
||||
QFloat *qfloat;
|
||||
int value = 0x2342;
|
||||
int64_t value64 = 0x2342342343LL;
|
||||
double valuef = 2.323423423;
|
||||
|
||||
obj = qobject_from_jsonf("%d", value);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QINT);
|
||||
|
||||
qint = qobject_to_qint(obj);
|
||||
g_assert(qint_get_int(qint) == value);
|
||||
|
||||
QDECREF(qint);
|
||||
|
||||
obj = qobject_from_jsonf("%" PRId64, value64);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QINT);
|
||||
|
||||
qint = qobject_to_qint(obj);
|
||||
g_assert(qint_get_int(qint) == value64);
|
||||
|
||||
QDECREF(qint);
|
||||
|
||||
obj = qobject_from_jsonf("%f", valuef);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QFLOAT);
|
||||
|
||||
qfloat = qobject_to_qfloat(obj);
|
||||
g_assert(qfloat_get_double(qfloat) == valuef);
|
||||
|
||||
QDECREF(qfloat);
|
||||
}
|
||||
|
||||
static void keyword_literal(void)
|
||||
{
|
||||
QObject *obj;
|
||||
QBool *qbool;
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json("true");
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QBOOL);
|
||||
|
||||
qbool = qobject_to_qbool(obj);
|
||||
g_assert(qbool_get_int(qbool) != 0);
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), "true") == 0);
|
||||
QDECREF(str);
|
||||
|
||||
QDECREF(qbool);
|
||||
|
||||
obj = qobject_from_json("false");
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QBOOL);
|
||||
|
||||
qbool = qobject_to_qbool(obj);
|
||||
g_assert(qbool_get_int(qbool) == 0);
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), "false") == 0);
|
||||
QDECREF(str);
|
||||
|
||||
QDECREF(qbool);
|
||||
|
||||
obj = qobject_from_jsonf("%i", false);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QBOOL);
|
||||
|
||||
qbool = qobject_to_qbool(obj);
|
||||
g_assert(qbool_get_int(qbool) == 0);
|
||||
|
||||
QDECREF(qbool);
|
||||
|
||||
obj = qobject_from_jsonf("%i", true);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QBOOL);
|
||||
|
||||
qbool = qobject_to_qbool(obj);
|
||||
g_assert(qbool_get_int(qbool) != 0);
|
||||
|
||||
QDECREF(qbool);
|
||||
}
|
||||
|
||||
typedef struct LiteralQDictEntry LiteralQDictEntry;
|
||||
typedef struct LiteralQObject LiteralQObject;
|
||||
|
||||
struct LiteralQObject
|
||||
{
|
||||
int type;
|
||||
union {
|
||||
int64_t qint;
|
||||
const char *qstr;
|
||||
LiteralQDictEntry *qdict;
|
||||
LiteralQObject *qlist;
|
||||
} value;
|
||||
};
|
||||
|
||||
struct LiteralQDictEntry
|
||||
{
|
||||
const char *key;
|
||||
LiteralQObject value;
|
||||
};
|
||||
|
||||
#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
|
||||
#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
|
||||
#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
|
||||
#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
|
||||
|
||||
typedef struct QListCompareHelper
|
||||
{
|
||||
int index;
|
||||
LiteralQObject *objs;
|
||||
int result;
|
||||
} QListCompareHelper;
|
||||
|
||||
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
|
||||
|
||||
static void compare_helper(QObject *obj, void *opaque)
|
||||
{
|
||||
QListCompareHelper *helper = opaque;
|
||||
|
||||
if (helper->result == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper->objs[helper->index].type == QTYPE_NONE) {
|
||||
helper->result = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
|
||||
}
|
||||
|
||||
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
|
||||
{
|
||||
if (lhs->type != qobject_type(rhs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (lhs->type) {
|
||||
case QTYPE_QINT:
|
||||
return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
|
||||
case QTYPE_QSTRING:
|
||||
return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
|
||||
case QTYPE_QDICT: {
|
||||
int i;
|
||||
|
||||
for (i = 0; lhs->value.qdict[i].key; i++) {
|
||||
QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
|
||||
|
||||
if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
case QTYPE_QLIST: {
|
||||
QListCompareHelper helper;
|
||||
|
||||
helper.index = 0;
|
||||
helper.objs = lhs->value.qlist;
|
||||
helper.result = 1;
|
||||
|
||||
qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
|
||||
|
||||
return helper.result;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void simple_dict(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
LiteralQObject decoded;
|
||||
} test_cases[] = {
|
||||
{
|
||||
.encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
|
||||
.decoded = QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
{ "foo", QLIT_QINT(42) },
|
||||
{ "bar", QLIT_QSTR("hello world") },
|
||||
{ }
|
||||
})),
|
||||
}, {
|
||||
.encoded = "{}",
|
||||
.decoded = QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
{ }
|
||||
})),
|
||||
}, {
|
||||
.encoded = "{\"foo\": 43}",
|
||||
.decoded = QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
{ "foo", QLIT_QINT(43) },
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QDICT);
|
||||
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
qobject_decref(obj);
|
||||
|
||||
obj = qobject_from_json(qstring_get_str(str));
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QDICT);
|
||||
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
qobject_decref(obj);
|
||||
QDECREF(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void simple_list(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
LiteralQObject decoded;
|
||||
} test_cases[] = {
|
||||
{
|
||||
.encoded = "[43,42]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QINT(43),
|
||||
QLIT_QINT(42),
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{
|
||||
.encoded = "[43]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QINT(43),
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{
|
||||
.encoded = "[]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{
|
||||
.encoded = "[{}]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
{},
|
||||
})),
|
||||
{},
|
||||
})),
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QLIST);
|
||||
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
qobject_decref(obj);
|
||||
|
||||
obj = qobject_from_json(qstring_get_str(str));
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QLIST);
|
||||
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
qobject_decref(obj);
|
||||
QDECREF(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void simple_whitespace(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
LiteralQObject decoded;
|
||||
} test_cases[] = {
|
||||
{
|
||||
.encoded = " [ 43 , 42 ]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QINT(43),
|
||||
QLIT_QINT(42),
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{
|
||||
.encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QINT(43),
|
||||
QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
{ "h", QLIT_QSTR("b") },
|
||||
{ }})),
|
||||
QLIT_QLIST(((LiteralQObject[]){
|
||||
{ }})),
|
||||
QLIT_QINT(42),
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{
|
||||
.encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
|
||||
.decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QINT(43),
|
||||
QLIT_QDICT(((LiteralQDictEntry[]){
|
||||
{ "h", QLIT_QSTR("b") },
|
||||
{ "a", QLIT_QINT(32) },
|
||||
{ }})),
|
||||
QLIT_QLIST(((LiteralQObject[]){
|
||||
{ }})),
|
||||
QLIT_QINT(42),
|
||||
{ }
|
||||
})),
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QLIST);
|
||||
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
qobject_decref(obj);
|
||||
|
||||
obj = qobject_from_json(qstring_get_str(str));
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QLIST);
|
||||
|
||||
g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
|
||||
|
||||
qobject_decref(obj);
|
||||
QDECREF(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void simple_varargs(void)
|
||||
{
|
||||
QObject *embedded_obj;
|
||||
QObject *obj;
|
||||
LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QINT(1),
|
||||
QLIT_QINT(2),
|
||||
QLIT_QLIST(((LiteralQObject[]){
|
||||
QLIT_QINT(32),
|
||||
QLIT_QINT(42),
|
||||
{}})),
|
||||
{}}));
|
||||
|
||||
embedded_obj = qobject_from_json("[32, 42]");
|
||||
g_assert(embedded_obj != NULL);
|
||||
|
||||
obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
|
||||
g_assert(obj != NULL);
|
||||
|
||||
g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
|
||||
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
static void empty_input(void)
|
||||
{
|
||||
const char *empty = "";
|
||||
|
||||
QObject *obj = qobject_from_json(empty);
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void unterminated_string(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("\"abc");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void unterminated_sq_string(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("'abc");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void unterminated_escape(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("\"abc\\\"");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void unterminated_array(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("[32");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void unterminated_array_comma(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("[32,");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void invalid_array_comma(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("[32,}");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void unterminated_dict(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("{'abc':32");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void unterminated_dict_comma(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("{'abc':32,");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void invalid_dict_comma(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("{'abc':32,}");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
static void unterminated_literal(void)
|
||||
{
|
||||
QObject *obj = qobject_from_json("nul");
|
||||
g_assert(obj == NULL);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/literals/string/simple", simple_string);
|
||||
g_test_add_func("/literals/string/escaped", escaped_string);
|
||||
g_test_add_func("/literals/string/single_quote", single_quote_string);
|
||||
g_test_add_func("/literals/string/vararg", vararg_string);
|
||||
|
||||
g_test_add_func("/literals/number/simple", simple_number);
|
||||
g_test_add_func("/literals/number/float", float_number);
|
||||
g_test_add_func("/literals/number/vararg", vararg_number);
|
||||
|
||||
g_test_add_func("/literals/keyword", keyword_literal);
|
||||
|
||||
g_test_add_func("/dicts/simple_dict", simple_dict);
|
||||
g_test_add_func("/lists/simple_list", simple_list);
|
||||
|
||||
g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
|
||||
|
||||
g_test_add_func("/varargs/simple_varargs", simple_varargs);
|
||||
|
||||
g_test_add_func("/errors/empty_input", empty_input);
|
||||
g_test_add_func("/errors/unterminated/string", unterminated_string);
|
||||
g_test_add_func("/errors/unterminated/escape", unterminated_escape);
|
||||
g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
|
||||
g_test_add_func("/errors/unterminated/array", unterminated_array);
|
||||
g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
|
||||
g_test_add_func("/errors/unterminated/dict", unterminated_dict);
|
||||
g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
|
||||
g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
|
||||
g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
|
||||
g_test_add_func("/errors/unterminated/literal", unterminated_literal);
|
||||
|
||||
return g_test_run();
|
||||
}
|
127
tests/check-qlist.c
Normal file
127
tests/check-qlist.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* QList unit-tests.
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
#include <glib.h>
|
||||
|
||||
#include "qint.h"
|
||||
#include "qlist.h"
|
||||
|
||||
/*
|
||||
* Public Interface test-cases
|
||||
*
|
||||
* (with some violations to access 'private' data)
|
||||
*/
|
||||
|
||||
static void qlist_new_test(void)
|
||||
{
|
||||
QList *qlist;
|
||||
|
||||
qlist = qlist_new();
|
||||
g_assert(qlist != NULL);
|
||||
g_assert(qlist->base.refcnt == 1);
|
||||
g_assert(qobject_type(QOBJECT(qlist)) == QTYPE_QLIST);
|
||||
|
||||
// destroy doesn't exist yet
|
||||
g_free(qlist);
|
||||
}
|
||||
|
||||
static void qlist_append_test(void)
|
||||
{
|
||||
QInt *qi;
|
||||
QList *qlist;
|
||||
QListEntry *entry;
|
||||
|
||||
qi = qint_from_int(42);
|
||||
|
||||
qlist = qlist_new();
|
||||
qlist_append(qlist, qi);
|
||||
|
||||
entry = QTAILQ_FIRST(&qlist->head);
|
||||
g_assert(entry != NULL);
|
||||
g_assert(entry->value == QOBJECT(qi));
|
||||
|
||||
// destroy doesn't exist yet
|
||||
QDECREF(qi);
|
||||
g_free(entry);
|
||||
g_free(qlist);
|
||||
}
|
||||
|
||||
static void qobject_to_qlist_test(void)
|
||||
{
|
||||
QList *qlist;
|
||||
|
||||
qlist = qlist_new();
|
||||
|
||||
g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist);
|
||||
|
||||
// destroy doesn't exist yet
|
||||
g_free(qlist);
|
||||
}
|
||||
|
||||
static void qlist_destroy_test(void)
|
||||
{
|
||||
int i;
|
||||
QList *qlist;
|
||||
|
||||
qlist = qlist_new();
|
||||
|
||||
for (i = 0; i < 42; i++)
|
||||
qlist_append(qlist, qint_from_int(i));
|
||||
|
||||
QDECREF(qlist);
|
||||
}
|
||||
|
||||
static int iter_called;
|
||||
static const int iter_max = 42;
|
||||
|
||||
static void iter_func(QObject *obj, void *opaque)
|
||||
{
|
||||
QInt *qi;
|
||||
|
||||
g_assert(opaque == NULL);
|
||||
|
||||
qi = qobject_to_qint(obj);
|
||||
g_assert(qi != NULL);
|
||||
g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
|
||||
|
||||
iter_called++;
|
||||
}
|
||||
|
||||
static void qlist_iter_test(void)
|
||||
{
|
||||
int i;
|
||||
QList *qlist;
|
||||
|
||||
qlist = qlist_new();
|
||||
|
||||
for (i = 0; i < iter_max; i++)
|
||||
qlist_append(qlist, qint_from_int(i));
|
||||
|
||||
iter_called = 0;
|
||||
qlist_iter(qlist, iter_func, NULL);
|
||||
|
||||
g_assert(iter_called == iter_max);
|
||||
|
||||
QDECREF(qlist);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/public/new", qlist_new_test);
|
||||
g_test_add_func("/public/append", qlist_append_test);
|
||||
g_test_add_func("/public/to_qlist", qobject_to_qlist_test);
|
||||
g_test_add_func("/public/destroy", qlist_destroy_test);
|
||||
g_test_add_func("/public/iter", qlist_iter_test);
|
||||
|
||||
return g_test_run();
|
||||
}
|
107
tests/check-qstring.c
Normal file
107
tests/check-qstring.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* QString unit-tests.
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
#include <glib.h>
|
||||
|
||||
#include "qstring.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
/*
|
||||
* Public Interface test-cases
|
||||
*
|
||||
* (with some violations to access 'private' data)
|
||||
*/
|
||||
|
||||
static void qstring_from_str_test(void)
|
||||
{
|
||||
QString *qstring;
|
||||
const char *str = "QEMU";
|
||||
|
||||
qstring = qstring_from_str(str);
|
||||
g_assert(qstring != NULL);
|
||||
g_assert(qstring->base.refcnt == 1);
|
||||
g_assert(strcmp(str, qstring->string) == 0);
|
||||
g_assert(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
|
||||
|
||||
// destroy doesn't exit yet
|
||||
g_free(qstring->string);
|
||||
g_free(qstring);
|
||||
}
|
||||
|
||||
static void qstring_destroy_test(void)
|
||||
{
|
||||
QString *qstring = qstring_from_str("destroy test");
|
||||
QDECREF(qstring);
|
||||
}
|
||||
|
||||
static void qstring_get_str_test(void)
|
||||
{
|
||||
QString *qstring;
|
||||
const char *ret_str;
|
||||
const char *str = "QEMU/KVM";
|
||||
|
||||
qstring = qstring_from_str(str);
|
||||
ret_str = qstring_get_str(qstring);
|
||||
g_assert(strcmp(ret_str, str) == 0);
|
||||
|
||||
QDECREF(qstring);
|
||||
}
|
||||
|
||||
static void qstring_append_chr_test(void)
|
||||
{
|
||||
int i;
|
||||
QString *qstring;
|
||||
const char *str = "qstring append char unit-test";
|
||||
|
||||
qstring = qstring_new();
|
||||
|
||||
for (i = 0; str[i]; i++)
|
||||
qstring_append_chr(qstring, str[i]);
|
||||
|
||||
g_assert(strcmp(str, qstring_get_str(qstring)) == 0);
|
||||
QDECREF(qstring);
|
||||
}
|
||||
|
||||
static void qstring_from_substr_test(void)
|
||||
{
|
||||
QString *qs;
|
||||
|
||||
qs = qstring_from_substr("virtualization", 3, 9);
|
||||
g_assert(qs != NULL);
|
||||
g_assert(strcmp(qstring_get_str(qs), "tualiza") == 0);
|
||||
|
||||
QDECREF(qs);
|
||||
}
|
||||
|
||||
|
||||
static void qobject_to_qstring_test(void)
|
||||
{
|
||||
QString *qstring;
|
||||
|
||||
qstring = qstring_from_str("foo");
|
||||
g_assert(qobject_to_qstring(QOBJECT(qstring)) == qstring);
|
||||
|
||||
QDECREF(qstring);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/public/from_str", qstring_from_str_test);
|
||||
g_test_add_func("/public/destroy", qstring_destroy_test);
|
||||
g_test_add_func("/public/get_str", qstring_get_str_test);
|
||||
g_test_add_func("/public/append_chr", qstring_append_chr_test);
|
||||
g_test_add_func("/public/from_substr", qstring_from_substr_test);
|
||||
g_test_add_func("/public/to_qstring", qobject_to_qstring_test);
|
||||
|
||||
return g_test_run();
|
||||
}
|
219
tests/test-coroutine.c
Normal file
219
tests/test-coroutine.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Coroutine tests
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include "qemu-coroutine.h"
|
||||
|
||||
/*
|
||||
* Check that qemu_in_coroutine() works
|
||||
*/
|
||||
|
||||
static void coroutine_fn verify_in_coroutine(void *opaque)
|
||||
{
|
||||
g_assert(qemu_in_coroutine());
|
||||
}
|
||||
|
||||
static void test_in_coroutine(void)
|
||||
{
|
||||
Coroutine *coroutine;
|
||||
|
||||
g_assert(!qemu_in_coroutine());
|
||||
|
||||
coroutine = qemu_coroutine_create(verify_in_coroutine);
|
||||
qemu_coroutine_enter(coroutine, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that qemu_coroutine_self() works
|
||||
*/
|
||||
|
||||
static void coroutine_fn verify_self(void *opaque)
|
||||
{
|
||||
g_assert(qemu_coroutine_self() == opaque);
|
||||
}
|
||||
|
||||
static void test_self(void)
|
||||
{
|
||||
Coroutine *coroutine;
|
||||
|
||||
coroutine = qemu_coroutine_create(verify_self);
|
||||
qemu_coroutine_enter(coroutine, coroutine);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that coroutines may nest multiple levels
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
unsigned int n_enter; /* num coroutines entered */
|
||||
unsigned int n_return; /* num coroutines returned */
|
||||
unsigned int max; /* maximum level of nesting */
|
||||
} NestData;
|
||||
|
||||
static void coroutine_fn nest(void *opaque)
|
||||
{
|
||||
NestData *nd = opaque;
|
||||
|
||||
nd->n_enter++;
|
||||
|
||||
if (nd->n_enter < nd->max) {
|
||||
Coroutine *child;
|
||||
|
||||
child = qemu_coroutine_create(nest);
|
||||
qemu_coroutine_enter(child, nd);
|
||||
}
|
||||
|
||||
nd->n_return++;
|
||||
}
|
||||
|
||||
static void test_nesting(void)
|
||||
{
|
||||
Coroutine *root;
|
||||
NestData nd = {
|
||||
.n_enter = 0,
|
||||
.n_return = 0,
|
||||
.max = 128,
|
||||
};
|
||||
|
||||
root = qemu_coroutine_create(nest);
|
||||
qemu_coroutine_enter(root, &nd);
|
||||
|
||||
/* Must enter and return from max nesting level */
|
||||
g_assert_cmpint(nd.n_enter, ==, nd.max);
|
||||
g_assert_cmpint(nd.n_return, ==, nd.max);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that yield/enter transfer control correctly
|
||||
*/
|
||||
|
||||
static void coroutine_fn yield_5_times(void *opaque)
|
||||
{
|
||||
bool *done = opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
*done = true;
|
||||
}
|
||||
|
||||
static void test_yield(void)
|
||||
{
|
||||
Coroutine *coroutine;
|
||||
bool done = false;
|
||||
int i = -1; /* one extra time to return from coroutine */
|
||||
|
||||
coroutine = qemu_coroutine_create(yield_5_times);
|
||||
while (!done) {
|
||||
qemu_coroutine_enter(coroutine, &done);
|
||||
i++;
|
||||
}
|
||||
g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that creation, enter, and return work
|
||||
*/
|
||||
|
||||
static void coroutine_fn set_and_exit(void *opaque)
|
||||
{
|
||||
bool *done = opaque;
|
||||
|
||||
*done = true;
|
||||
}
|
||||
|
||||
static void test_lifecycle(void)
|
||||
{
|
||||
Coroutine *coroutine;
|
||||
bool done = false;
|
||||
|
||||
/* Create, enter, and return from coroutine */
|
||||
coroutine = qemu_coroutine_create(set_and_exit);
|
||||
qemu_coroutine_enter(coroutine, &done);
|
||||
g_assert(done); /* expect done to be true (first time) */
|
||||
|
||||
/* Repeat to check that no state affects this test */
|
||||
done = false;
|
||||
coroutine = qemu_coroutine_create(set_and_exit);
|
||||
qemu_coroutine_enter(coroutine, &done);
|
||||
g_assert(done); /* expect done to be true (second time) */
|
||||
}
|
||||
|
||||
/*
|
||||
* Lifecycle benchmark
|
||||
*/
|
||||
|
||||
static void coroutine_fn empty_coroutine(void *opaque)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static void perf_lifecycle(void)
|
||||
{
|
||||
Coroutine *coroutine;
|
||||
unsigned int i, max;
|
||||
double duration;
|
||||
|
||||
max = 1000000;
|
||||
|
||||
g_test_timer_start();
|
||||
for (i = 0; i < max; i++) {
|
||||
coroutine = qemu_coroutine_create(empty_coroutine);
|
||||
qemu_coroutine_enter(coroutine, NULL);
|
||||
}
|
||||
duration = g_test_timer_elapsed();
|
||||
|
||||
g_test_message("Lifecycle %u iterations: %f s\n", max, duration);
|
||||
}
|
||||
|
||||
static void perf_nesting(void)
|
||||
{
|
||||
unsigned int i, maxcycles, maxnesting;
|
||||
double duration;
|
||||
|
||||
maxcycles = 100000000;
|
||||
maxnesting = 20000;
|
||||
Coroutine *root;
|
||||
NestData nd = {
|
||||
.n_enter = 0,
|
||||
.n_return = 0,
|
||||
.max = maxnesting,
|
||||
};
|
||||
|
||||
g_test_timer_start();
|
||||
for (i = 0; i < maxcycles; i++) {
|
||||
root = qemu_coroutine_create(nest);
|
||||
qemu_coroutine_enter(root, &nd);
|
||||
}
|
||||
duration = g_test_timer_elapsed();
|
||||
|
||||
g_test_message("Nesting %u iterations of %u depth each: %f s\n",
|
||||
maxcycles, maxnesting, duration);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func("/basic/lifecycle", test_lifecycle);
|
||||
g_test_add_func("/basic/yield", test_yield);
|
||||
g_test_add_func("/basic/nesting", test_nesting);
|
||||
g_test_add_func("/basic/self", test_self);
|
||||
g_test_add_func("/basic/in_coroutine", test_in_coroutine);
|
||||
if (g_test_perf()) {
|
||||
g_test_add_func("/perf/lifecycle", perf_lifecycle);
|
||||
g_test_add_func("/perf/nesting", perf_nesting);
|
||||
}
|
||||
return g_test_run();
|
||||
}
|
139
tests/test-qmp-commands.c
Normal file
139
tests/test-qmp-commands.c
Normal file
|
@ -0,0 +1,139 @@
|
|||
#include <glib.h>
|
||||
#include "qemu-objects.h"
|
||||
#include "test-qmp-commands.h"
|
||||
#include "qapi/qmp-core.h"
|
||||
#include "module.h"
|
||||
|
||||
void qmp_user_def_cmd(Error **errp)
|
||||
{
|
||||
}
|
||||
|
||||
void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
|
||||
{
|
||||
}
|
||||
|
||||
UserDefTwo * qmp_user_def_cmd2(UserDefOne * ud1a, UserDefOne * ud1b, Error **errp)
|
||||
{
|
||||
UserDefTwo *ret;
|
||||
UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
|
||||
UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
|
||||
|
||||
ud1c->string = strdup(ud1a->string);
|
||||
ud1c->integer = ud1a->integer;
|
||||
ud1d->string = strdup(ud1b->string);
|
||||
ud1d->integer = ud1b->integer;
|
||||
|
||||
ret = g_malloc0(sizeof(UserDefTwo));
|
||||
ret->string = strdup("blah1");
|
||||
ret->dict.string = strdup("blah2");
|
||||
ret->dict.dict.userdef = ud1c;
|
||||
ret->dict.dict.string = strdup("blah3");
|
||||
ret->dict.has_dict2 = true;
|
||||
ret->dict.dict2.userdef = ud1d;
|
||||
ret->dict.dict2.string = strdup("blah4");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* test commands with no input and no return value */
|
||||
static void test_dispatch_cmd(void)
|
||||
{
|
||||
QDict *req = qdict_new();
|
||||
QObject *resp;
|
||||
|
||||
qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
|
||||
|
||||
resp = qmp_dispatch(QOBJECT(req));
|
||||
assert(resp != NULL);
|
||||
assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
|
||||
|
||||
qobject_decref(resp);
|
||||
QDECREF(req);
|
||||
}
|
||||
|
||||
/* test commands that return an error due to invalid parameters */
|
||||
static void test_dispatch_cmd_error(void)
|
||||
{
|
||||
QDict *req = qdict_new();
|
||||
QObject *resp;
|
||||
|
||||
qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
|
||||
|
||||
resp = qmp_dispatch(QOBJECT(req));
|
||||
assert(resp != NULL);
|
||||
assert(qdict_haskey(qobject_to_qdict(resp), "error"));
|
||||
|
||||
qobject_decref(resp);
|
||||
QDECREF(req);
|
||||
}
|
||||
|
||||
/* test commands that involve both input parameters and return values */
|
||||
static void test_dispatch_cmd_io(void)
|
||||
{
|
||||
QDict *req = qdict_new();
|
||||
QDict *args = qdict_new();
|
||||
QDict *ud1a = qdict_new();
|
||||
QDict *ud1b = qdict_new();
|
||||
QObject *resp;
|
||||
|
||||
qdict_put_obj(ud1a, "integer", QOBJECT(qint_from_int(42)));
|
||||
qdict_put_obj(ud1a, "string", QOBJECT(qstring_from_str("hello")));
|
||||
qdict_put_obj(ud1b, "integer", QOBJECT(qint_from_int(422)));
|
||||
qdict_put_obj(ud1b, "string", QOBJECT(qstring_from_str("hello2")));
|
||||
qdict_put_obj(args, "ud1a", QOBJECT(ud1a));
|
||||
qdict_put_obj(args, "ud1b", QOBJECT(ud1b));
|
||||
qdict_put_obj(req, "arguments", QOBJECT(args));
|
||||
|
||||
qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
|
||||
|
||||
/* TODO: put in full payload and check for errors */
|
||||
resp = qmp_dispatch(QOBJECT(req));
|
||||
assert(resp != NULL);
|
||||
assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
|
||||
|
||||
qobject_decref(resp);
|
||||
QDECREF(req);
|
||||
}
|
||||
|
||||
/* test generated dealloc functions for generated types */
|
||||
static void test_dealloc_types(void)
|
||||
{
|
||||
UserDefOne *ud1test, *ud1a, *ud1b;
|
||||
UserDefOneList *ud1list;
|
||||
|
||||
ud1test = g_malloc0(sizeof(UserDefOne));
|
||||
ud1test->integer = 42;
|
||||
ud1test->string = g_strdup("hi there 42");
|
||||
|
||||
qapi_free_UserDefOne(ud1test);
|
||||
|
||||
ud1a = g_malloc0(sizeof(UserDefOne));
|
||||
ud1a->integer = 43;
|
||||
ud1a->string = g_strdup("hi there 43");
|
||||
|
||||
ud1b = g_malloc0(sizeof(UserDefOne));
|
||||
ud1b->integer = 44;
|
||||
ud1b->string = g_strdup("hi there 44");
|
||||
|
||||
ud1list = g_malloc0(sizeof(UserDefOneList));
|
||||
ud1list->value = ud1a;
|
||||
ud1list->next = g_malloc0(sizeof(UserDefOneList));
|
||||
ud1list->next->value = ud1b;
|
||||
|
||||
qapi_free_UserDefOneList(ud1list);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
|
||||
g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
|
||||
g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
|
||||
g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
|
||||
|
||||
module_call_init(MODULE_INIT_QAPI);
|
||||
g_test_run();
|
||||
|
||||
return 0;
|
||||
}
|
234
tests/test-qmp-input-strict.c
Normal file
234
tests/test-qmp-input-strict.c
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* QMP Input Visitor unit-tests (strict mode).
|
||||
*
|
||||
* Copyright (C) 2011-2012 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
* Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "test-qapi-types.h"
|
||||
#include "test-qapi-visit.h"
|
||||
#include "qemu-objects.h"
|
||||
|
||||
typedef struct TestInputVisitorData {
|
||||
QObject *obj;
|
||||
QmpInputVisitor *qiv;
|
||||
} TestInputVisitorData;
|
||||
|
||||
static void validate_teardown(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
qobject_decref(data->obj);
|
||||
data->obj = NULL;
|
||||
|
||||
if (data->qiv) {
|
||||
qmp_input_visitor_cleanup(data->qiv);
|
||||
data->qiv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is provided instead of a test setup function so that the JSON
|
||||
string used by the tests are kept in the test functions (and not
|
||||
int main()) */
|
||||
static GCC_FMT_ATTR(2, 3)
|
||||
Visitor *validate_test_init(TestInputVisitorData *data,
|
||||
const char *json_string, ...)
|
||||
{
|
||||
Visitor *v;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, json_string);
|
||||
data->obj = qobject_from_jsonv(json_string, &ap);
|
||||
va_end(ap);
|
||||
|
||||
g_assert(data->obj != NULL);
|
||||
|
||||
data->qiv = qmp_input_visitor_new_strict(data->obj);
|
||||
g_assert(data->qiv != NULL);
|
||||
|
||||
v = qmp_input_get_visitor(data->qiv);
|
||||
g_assert(v != NULL);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
typedef struct TestStruct
|
||||
{
|
||||
int64_t integer;
|
||||
bool boolean;
|
||||
char *string;
|
||||
} TestStruct;
|
||||
|
||||
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
||||
errp);
|
||||
|
||||
visit_type_int(v, &(*obj)->integer, "integer", errp);
|
||||
visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
|
||||
visit_type_str(v, &(*obj)->string, "string", errp);
|
||||
|
||||
visit_end_struct(v, errp);
|
||||
}
|
||||
|
||||
static void test_validate_struct(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
TestStruct *p = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
|
||||
|
||||
visit_type_TestStruct(v, &p, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_free(p->string);
|
||||
g_free(p);
|
||||
}
|
||||
|
||||
static void test_validate_struct_nested(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefNested *udp = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
|
||||
|
||||
visit_type_UserDefNested(v, &udp, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
qapi_free_UserDefNested(udp);
|
||||
}
|
||||
|
||||
static void test_validate_list(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefOneList *head = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
|
||||
|
||||
visit_type_UserDefOneList(v, &head, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
qapi_free_UserDefOneList(head);
|
||||
}
|
||||
|
||||
static void test_validate_union(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefUnion *tmp = NULL;
|
||||
Visitor *v;
|
||||
Error *errp = NULL;
|
||||
|
||||
v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
|
||||
|
||||
visit_type_UserDefUnion(v, &tmp, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
qapi_free_UserDefUnion(tmp);
|
||||
}
|
||||
|
||||
static void test_validate_fail_struct(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
TestStruct *p = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
|
||||
|
||||
visit_type_TestStruct(v, &p, NULL, &errp);
|
||||
g_assert(error_is_set(&errp));
|
||||
if (p) {
|
||||
g_free(p->string);
|
||||
}
|
||||
g_free(p);
|
||||
}
|
||||
|
||||
static void test_validate_fail_struct_nested(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefNested *udp = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
|
||||
|
||||
visit_type_UserDefNested(v, &udp, NULL, &errp);
|
||||
g_assert(error_is_set(&errp));
|
||||
qapi_free_UserDefNested(udp);
|
||||
}
|
||||
|
||||
static void test_validate_fail_list(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefOneList *head = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
|
||||
|
||||
visit_type_UserDefOneList(v, &head, NULL, &errp);
|
||||
g_assert(error_is_set(&errp));
|
||||
qapi_free_UserDefOneList(head);
|
||||
}
|
||||
|
||||
static void test_validate_fail_union(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefUnion *tmp = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
|
||||
|
||||
visit_type_UserDefUnion(v, &tmp, NULL, &errp);
|
||||
g_assert(error_is_set(&errp));
|
||||
qapi_free_UserDefUnion(tmp);
|
||||
}
|
||||
|
||||
static void validate_test_add(const char *testpath,
|
||||
TestInputVisitorData *data,
|
||||
void (*test_func)(TestInputVisitorData *data, const void *user_data))
|
||||
{
|
||||
g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
|
||||
validate_teardown);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestInputVisitorData testdata;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
validate_test_add("/visitor/input-strict/pass/struct",
|
||||
&testdata, test_validate_struct);
|
||||
validate_test_add("/visitor/input-strict/pass/struct-nested",
|
||||
&testdata, test_validate_struct_nested);
|
||||
validate_test_add("/visitor/input-strict/pass/list",
|
||||
&testdata, test_validate_list);
|
||||
validate_test_add("/visitor/input-strict/pass/union",
|
||||
&testdata, test_validate_union);
|
||||
validate_test_add("/visitor/input-strict/fail/struct",
|
||||
&testdata, test_validate_fail_struct);
|
||||
validate_test_add("/visitor/input-strict/fail/struct-nested",
|
||||
&testdata, test_validate_fail_struct_nested);
|
||||
validate_test_add("/visitor/input-strict/fail/list",
|
||||
&testdata, test_validate_fail_list);
|
||||
validate_test_add("/visitor/input-strict/fail/union",
|
||||
&testdata, test_validate_fail_union);
|
||||
|
||||
g_test_run();
|
||||
|
||||
return 0;
|
||||
}
|
308
tests/test-qmp-input-visitor.c
Normal file
308
tests/test-qmp-input-visitor.c
Normal file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* QMP Input Visitor unit-tests.
|
||||
*
|
||||
* Copyright (C) 2011 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "test-qapi-types.h"
|
||||
#include "test-qapi-visit.h"
|
||||
#include "qemu-objects.h"
|
||||
|
||||
typedef struct TestInputVisitorData {
|
||||
QObject *obj;
|
||||
QmpInputVisitor *qiv;
|
||||
} TestInputVisitorData;
|
||||
|
||||
static void visitor_input_teardown(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
qobject_decref(data->obj);
|
||||
data->obj = NULL;
|
||||
|
||||
if (data->qiv) {
|
||||
qmp_input_visitor_cleanup(data->qiv);
|
||||
data->qiv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is provided instead of a test setup function so that the JSON
|
||||
string used by the tests are kept in the test functions (and not
|
||||
int main()) */
|
||||
static GCC_FMT_ATTR(2, 3)
|
||||
Visitor *visitor_input_test_init(TestInputVisitorData *data,
|
||||
const char *json_string, ...)
|
||||
{
|
||||
Visitor *v;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, json_string);
|
||||
data->obj = qobject_from_jsonv(json_string, &ap);
|
||||
va_end(ap);
|
||||
|
||||
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)
|
||||
{
|
||||
int64_t res = 0, value = -42;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "%" PRId64, value);
|
||||
|
||||
visit_type_int(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, value);
|
||||
}
|
||||
|
||||
static void test_visitor_in_bool(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
bool res = false;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "true");
|
||||
|
||||
visit_type_bool(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, true);
|
||||
}
|
||||
|
||||
static void test_visitor_in_number(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
double res = 0, value = 3.14;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "%f", value);
|
||||
|
||||
visit_type_number(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpfloat(res, ==, value);
|
||||
}
|
||||
|
||||
static void test_visitor_in_string(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
char *res = NULL, *value = (char *) "Q E M U";
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "%s", value);
|
||||
|
||||
visit_type_str(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpstr(res, ==, value);
|
||||
|
||||
g_free(res);
|
||||
}
|
||||
|
||||
static void test_visitor_in_enum(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
EnumOne i;
|
||||
|
||||
for (i = 0; EnumOne_lookup[i]; i++) {
|
||||
EnumOne res = -1;
|
||||
|
||||
v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
|
||||
|
||||
visit_type_EnumOne(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(i, ==, res);
|
||||
|
||||
visitor_input_teardown(data, NULL);
|
||||
}
|
||||
|
||||
data->obj = NULL;
|
||||
data->qiv = NULL;
|
||||
}
|
||||
|
||||
typedef struct TestStruct
|
||||
{
|
||||
int64_t integer;
|
||||
bool boolean;
|
||||
char *string;
|
||||
} TestStruct;
|
||||
|
||||
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
||||
errp);
|
||||
|
||||
visit_type_int(v, &(*obj)->integer, "integer", errp);
|
||||
visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
|
||||
visit_type_str(v, &(*obj)->string, "string", errp);
|
||||
|
||||
visit_end_struct(v, errp);
|
||||
}
|
||||
|
||||
static void test_visitor_in_struct(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
TestStruct *p = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
|
||||
|
||||
visit_type_TestStruct(v, &p, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(p->integer, ==, -42);
|
||||
g_assert(p->boolean == true);
|
||||
g_assert_cmpstr(p->string, ==, "foo");
|
||||
|
||||
g_free(p->string);
|
||||
g_free(p);
|
||||
}
|
||||
|
||||
static void check_and_free_str(char *str, const char *cmp)
|
||||
{
|
||||
g_assert_cmpstr(str, ==, cmp);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void test_visitor_in_struct_nested(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefNested *udp = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
|
||||
|
||||
visit_type_UserDefNested(v, &udp, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
|
||||
check_and_free_str(udp->string0, "string0");
|
||||
check_and_free_str(udp->dict1.string1, "string1");
|
||||
g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
|
||||
check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
|
||||
check_and_free_str(udp->dict1.dict2.string2, "string2");
|
||||
g_assert(udp->dict1.has_dict3 == false);
|
||||
|
||||
g_free(udp->dict1.dict2.userdef1);
|
||||
g_free(udp);
|
||||
}
|
||||
|
||||
static void test_visitor_in_list(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefOneList *item, *head = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
int i;
|
||||
|
||||
v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
|
||||
|
||||
visit_type_UserDefOneList(v, &head, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert(head != NULL);
|
||||
|
||||
for (i = 0, item = head; item; item = item->next, i++) {
|
||||
char string[12];
|
||||
|
||||
snprintf(string, sizeof(string), "string%d", i);
|
||||
g_assert_cmpstr(item->value->string, ==, string);
|
||||
g_assert_cmpint(item->value->integer, ==, 42 + i);
|
||||
}
|
||||
|
||||
qapi_free_UserDefOneList(head);
|
||||
}
|
||||
|
||||
static void test_visitor_in_union(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Visitor *v;
|
||||
Error *err = NULL;
|
||||
UserDefUnion *tmp;
|
||||
|
||||
v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
|
||||
|
||||
visit_type_UserDefUnion(v, &tmp, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
|
||||
g_assert_cmpint(tmp->b->integer, ==, 42);
|
||||
qapi_free_UserDefUnion(tmp);
|
||||
}
|
||||
|
||||
static void input_visitor_test_add(const char *testpath,
|
||||
TestInputVisitorData *data,
|
||||
void (*test_func)(TestInputVisitorData *data, const void *user_data))
|
||||
{
|
||||
g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
|
||||
visitor_input_teardown);
|
||||
}
|
||||
|
||||
static void test_visitor_in_errors(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
TestStruct *p = NULL;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
|
||||
|
||||
visit_type_TestStruct(v, &p, NULL, &errp);
|
||||
g_assert(error_is_set(&errp));
|
||||
g_assert(p->string == NULL);
|
||||
|
||||
g_free(p->string);
|
||||
g_free(p);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestInputVisitorData in_visitor_data;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
input_visitor_test_add("/visitor/input/int",
|
||||
&in_visitor_data, test_visitor_in_int);
|
||||
input_visitor_test_add("/visitor/input/bool",
|
||||
&in_visitor_data, test_visitor_in_bool);
|
||||
input_visitor_test_add("/visitor/input/number",
|
||||
&in_visitor_data, test_visitor_in_number);
|
||||
input_visitor_test_add("/visitor/input/string",
|
||||
&in_visitor_data, test_visitor_in_string);
|
||||
input_visitor_test_add("/visitor/input/enum",
|
||||
&in_visitor_data, test_visitor_in_enum);
|
||||
input_visitor_test_add("/visitor/input/struct",
|
||||
&in_visitor_data, test_visitor_in_struct);
|
||||
input_visitor_test_add("/visitor/input/struct-nested",
|
||||
&in_visitor_data, test_visitor_in_struct_nested);
|
||||
input_visitor_test_add("/visitor/input/list",
|
||||
&in_visitor_data, test_visitor_in_list);
|
||||
input_visitor_test_add("/visitor/input/union",
|
||||
&in_visitor_data, test_visitor_in_union);
|
||||
input_visitor_test_add("/visitor/input/errors",
|
||||
&in_visitor_data, test_visitor_in_errors);
|
||||
|
||||
g_test_run();
|
||||
|
||||
return 0;
|
||||
}
|
477
tests/test-qmp-output-visitor.c
Normal file
477
tests/test-qmp-output-visitor.c
Normal file
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
* QMP Output Visitor unit-tests.
|
||||
*
|
||||
* Copyright (C) 2011 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "test-qapi-types.h"
|
||||
#include "test-qapi-visit.h"
|
||||
#include "qemu-objects.h"
|
||||
|
||||
typedef struct TestOutputVisitorData {
|
||||
QmpOutputVisitor *qov;
|
||||
Visitor *ov;
|
||||
} TestOutputVisitorData;
|
||||
|
||||
static void visitor_output_setup(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
data->qov = qmp_output_visitor_new();
|
||||
g_assert(data->qov != NULL);
|
||||
|
||||
data->ov = qmp_output_get_visitor(data->qov);
|
||||
g_assert(data->ov != NULL);
|
||||
}
|
||||
|
||||
static void visitor_output_teardown(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
qmp_output_visitor_cleanup(data->qov);
|
||||
data->qov = NULL;
|
||||
data->ov = NULL;
|
||||
}
|
||||
|
||||
static void test_visitor_out_int(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
int64_t value = -42;
|
||||
Error *errp = NULL;
|
||||
QObject *obj;
|
||||
|
||||
visit_type_int(data->ov, &value, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QINT);
|
||||
g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
|
||||
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
static void test_visitor_out_bool(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
bool value = true;
|
||||
QObject *obj;
|
||||
|
||||
visit_type_bool(data->ov, &value, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QBOOL);
|
||||
g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
|
||||
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
static void test_visitor_out_number(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
double value = 3.14;
|
||||
Error *errp = NULL;
|
||||
QObject *obj;
|
||||
|
||||
visit_type_number(data->ov, &value, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QFLOAT);
|
||||
g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
|
||||
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
static void test_visitor_out_string(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
char *string = (char *) "Q E M U";
|
||||
Error *errp = NULL;
|
||||
QObject *obj;
|
||||
|
||||
visit_type_str(data->ov, &string, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QSTRING);
|
||||
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
|
||||
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
static void test_visitor_out_no_string(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
char *string = NULL;
|
||||
Error *errp = NULL;
|
||||
QObject *obj;
|
||||
|
||||
/* A null string should return "" */
|
||||
visit_type_str(data->ov, &string, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QSTRING);
|
||||
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
|
||||
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
static void test_visitor_out_enum(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
QObject *obj;
|
||||
EnumOne i;
|
||||
|
||||
for (i = 0; i < ENUM_ONE_MAX; i++) {
|
||||
visit_type_EnumOne(data->ov, &i, "unused", &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QSTRING);
|
||||
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
|
||||
EnumOne_lookup[i]);
|
||||
qobject_decref(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
|
||||
Error *errp;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
|
||||
errp = NULL;
|
||||
visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
|
||||
g_assert(error_is_set(&errp) == true);
|
||||
error_free(errp);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct TestStruct
|
||||
{
|
||||
int64_t integer;
|
||||
bool boolean;
|
||||
char *string;
|
||||
} TestStruct;
|
||||
|
||||
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
|
||||
errp);
|
||||
|
||||
visit_type_int(v, &(*obj)->integer, "integer", errp);
|
||||
visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
|
||||
visit_type_str(v, &(*obj)->string, "string", errp);
|
||||
|
||||
visit_end_struct(v, errp);
|
||||
}
|
||||
|
||||
static void test_visitor_out_struct(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
TestStruct test_struct = { .integer = 42,
|
||||
.boolean = false,
|
||||
.string = (char *) "foo"};
|
||||
TestStruct *p = &test_struct;
|
||||
Error *errp = NULL;
|
||||
QObject *obj;
|
||||
QDict *qdict;
|
||||
|
||||
visit_type_TestStruct(data->ov, &p, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QDICT);
|
||||
|
||||
qdict = qobject_to_qdict(obj);
|
||||
g_assert_cmpint(qdict_size(qdict), ==, 3);
|
||||
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
|
||||
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
|
||||
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
|
||||
|
||||
QDECREF(qdict);
|
||||
}
|
||||
|
||||
static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
int64_t value = 42;
|
||||
Error *errp = NULL;
|
||||
UserDefNested *ud2;
|
||||
QObject *obj;
|
||||
QDict *qdict, *dict1, *dict2, *dict3, *userdef;
|
||||
const char *string = "user def string";
|
||||
const char *strings[] = { "forty two", "forty three", "forty four",
|
||||
"forty five" };
|
||||
|
||||
ud2 = g_malloc0(sizeof(*ud2));
|
||||
ud2->string0 = g_strdup(strings[0]);
|
||||
|
||||
ud2->dict1.string1 = g_strdup(strings[1]);
|
||||
ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
|
||||
ud2->dict1.dict2.userdef1->string = g_strdup(string);
|
||||
ud2->dict1.dict2.userdef1->integer = value;
|
||||
ud2->dict1.dict2.string2 = g_strdup(strings[2]);
|
||||
|
||||
ud2->dict1.has_dict3 = true;
|
||||
ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
|
||||
ud2->dict1.dict3.userdef2->string = g_strdup(string);
|
||||
ud2->dict1.dict3.userdef2->integer = value;
|
||||
ud2->dict1.dict3.string3 = g_strdup(strings[3]);
|
||||
|
||||
visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QDICT);
|
||||
|
||||
qdict = qobject_to_qdict(obj);
|
||||
g_assert_cmpint(qdict_size(qdict), ==, 2);
|
||||
g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
|
||||
|
||||
dict1 = qdict_get_qdict(qdict, "dict1");
|
||||
g_assert_cmpint(qdict_size(dict1), ==, 3);
|
||||
g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
|
||||
|
||||
dict2 = qdict_get_qdict(dict1, "dict2");
|
||||
g_assert_cmpint(qdict_size(dict2), ==, 2);
|
||||
g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
|
||||
userdef = qdict_get_qdict(dict2, "userdef1");
|
||||
g_assert_cmpint(qdict_size(userdef), ==, 2);
|
||||
g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
|
||||
g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
|
||||
|
||||
dict3 = qdict_get_qdict(dict1, "dict3");
|
||||
g_assert_cmpint(qdict_size(dict3), ==, 2);
|
||||
g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
|
||||
userdef = qdict_get_qdict(dict3, "userdef2");
|
||||
g_assert_cmpint(qdict_size(userdef), ==, 2);
|
||||
g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
|
||||
g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
|
||||
|
||||
QDECREF(qdict);
|
||||
qapi_free_UserDefNested(ud2);
|
||||
}
|
||||
|
||||
static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
|
||||
UserDefOne u = { 0 }, *pu = &u;
|
||||
Error *errp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
|
||||
errp = NULL;
|
||||
u.has_enum1 = true;
|
||||
u.enum1 = bad_values[i];
|
||||
visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
|
||||
g_assert(error_is_set(&errp) == true);
|
||||
error_free(errp);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct TestStructList
|
||||
{
|
||||
TestStruct *value;
|
||||
struct TestStructList *next;
|
||||
} TestStructList;
|
||||
|
||||
static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
GenericList *i, **head = (GenericList **)obj;
|
||||
|
||||
visit_start_list(v, name, errp);
|
||||
|
||||
for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
|
||||
TestStructList *native_i = (TestStructList *)i;
|
||||
visit_type_TestStruct(v, &native_i->value, NULL, errp);
|
||||
}
|
||||
|
||||
visit_end_list(v, errp);
|
||||
}
|
||||
|
||||
static void test_visitor_out_list(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
char *value_str = (char *) "list value";
|
||||
TestStructList *p, *head = NULL;
|
||||
const int max_items = 10;
|
||||
bool value_bool = true;
|
||||
int value_int = 10;
|
||||
Error *errp = NULL;
|
||||
QListEntry *entry;
|
||||
QObject *obj;
|
||||
QList *qlist;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max_items; i++) {
|
||||
p = g_malloc0(sizeof(*p));
|
||||
p->value = g_malloc0(sizeof(*p->value));
|
||||
p->value->integer = value_int;
|
||||
p->value->boolean = value_bool;
|
||||
p->value->string = value_str;
|
||||
|
||||
p->next = head;
|
||||
head = p;
|
||||
}
|
||||
|
||||
visit_type_TestStructList(data->ov, &head, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QLIST);
|
||||
|
||||
qlist = qobject_to_qlist(obj);
|
||||
g_assert(!qlist_empty(qlist));
|
||||
|
||||
i = 0;
|
||||
QLIST_FOREACH_ENTRY(qlist, entry) {
|
||||
QDict *qdict;
|
||||
|
||||
g_assert(qobject_type(entry->value) == QTYPE_QDICT);
|
||||
qdict = qobject_to_qdict(entry->value);
|
||||
g_assert_cmpint(qdict_size(qdict), ==, 3);
|
||||
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
|
||||
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
|
||||
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
|
||||
i++;
|
||||
}
|
||||
g_assert_cmpint(i, ==, max_items);
|
||||
|
||||
QDECREF(qlist);
|
||||
|
||||
for (p = head; p;) {
|
||||
TestStructList *tmp = p->next;
|
||||
g_free(p->value);
|
||||
g_free(p);
|
||||
p = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefNestedList *p, *head = NULL;
|
||||
const char string[] = "foo bar";
|
||||
int i, max_count = 1024;
|
||||
|
||||
for (i = 0; i < max_count; i++) {
|
||||
p = g_malloc0(sizeof(*p));
|
||||
p->value = g_malloc0(sizeof(*p->value));
|
||||
|
||||
p->value->string0 = g_strdup(string);
|
||||
p->value->dict1.string1 = g_strdup(string);
|
||||
p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
|
||||
p->value->dict1.dict2.userdef1->string = g_strdup(string);
|
||||
p->value->dict1.dict2.userdef1->integer = 42;
|
||||
p->value->dict1.dict2.string2 = g_strdup(string);
|
||||
p->value->dict1.has_dict3 = false;
|
||||
|
||||
p->next = head;
|
||||
head = p;
|
||||
}
|
||||
|
||||
qapi_free_UserDefNestedList(head);
|
||||
}
|
||||
|
||||
static void test_visitor_out_union(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
QObject *arg, *qvalue;
|
||||
QDict *qdict, *value;
|
||||
|
||||
Error *err = NULL;
|
||||
|
||||
UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
|
||||
tmp->kind = USER_DEF_UNION_KIND_A;
|
||||
tmp->a = g_malloc0(sizeof(UserDefA));
|
||||
tmp->a->boolean = true;
|
||||
|
||||
visit_type_UserDefUnion(data->ov, &tmp, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
arg = qmp_output_get_qobject(data->qov);
|
||||
|
||||
g_assert(qobject_type(arg) == QTYPE_QDICT);
|
||||
qdict = qobject_to_qdict(arg);
|
||||
|
||||
g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
|
||||
|
||||
qvalue = qdict_get(qdict, "data");
|
||||
g_assert(data != NULL);
|
||||
g_assert(qobject_type(qvalue) == QTYPE_QDICT);
|
||||
value = qobject_to_qdict(qvalue);
|
||||
g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true);
|
||||
|
||||
qapi_free_UserDefUnion(tmp);
|
||||
QDECREF(qdict);
|
||||
}
|
||||
|
||||
static void output_visitor_test_add(const char *testpath,
|
||||
TestOutputVisitorData *data,
|
||||
void (*test_func)(TestOutputVisitorData *data, const void *user_data))
|
||||
{
|
||||
g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
|
||||
test_func, visitor_output_teardown);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestOutputVisitorData out_visitor_data;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
output_visitor_test_add("/visitor/output/int",
|
||||
&out_visitor_data, test_visitor_out_int);
|
||||
output_visitor_test_add("/visitor/output/bool",
|
||||
&out_visitor_data, test_visitor_out_bool);
|
||||
output_visitor_test_add("/visitor/output/number",
|
||||
&out_visitor_data, test_visitor_out_number);
|
||||
output_visitor_test_add("/visitor/output/string",
|
||||
&out_visitor_data, test_visitor_out_string);
|
||||
output_visitor_test_add("/visitor/output/no-string",
|
||||
&out_visitor_data, test_visitor_out_no_string);
|
||||
output_visitor_test_add("/visitor/output/enum",
|
||||
&out_visitor_data, test_visitor_out_enum);
|
||||
output_visitor_test_add("/visitor/output/enum-errors",
|
||||
&out_visitor_data, test_visitor_out_enum_errors);
|
||||
output_visitor_test_add("/visitor/output/struct",
|
||||
&out_visitor_data, test_visitor_out_struct);
|
||||
output_visitor_test_add("/visitor/output/struct-nested",
|
||||
&out_visitor_data, test_visitor_out_struct_nested);
|
||||
output_visitor_test_add("/visitor/output/struct-errors",
|
||||
&out_visitor_data, test_visitor_out_struct_errors);
|
||||
output_visitor_test_add("/visitor/output/list",
|
||||
&out_visitor_data, test_visitor_out_list);
|
||||
output_visitor_test_add("/visitor/output/list-qapi-free",
|
||||
&out_visitor_data, test_visitor_out_list_qapi_free);
|
||||
output_visitor_test_add("/visitor/output/union",
|
||||
&out_visitor_data, test_visitor_out_union);
|
||||
|
||||
g_test_run();
|
||||
|
||||
return 0;
|
||||
}
|
195
tests/test-string-input-visitor.c
Normal file
195
tests/test-string-input-visitor.c
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* String Input Visitor unit-tests.
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-input-visitor)
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "qapi/string-input-visitor.h"
|
||||
#include "test-qapi-types.h"
|
||||
#include "test-qapi-visit.h"
|
||||
#include "qemu-objects.h"
|
||||
|
||||
typedef struct TestInputVisitorData {
|
||||
StringInputVisitor *siv;
|
||||
} TestInputVisitorData;
|
||||
|
||||
static void visitor_input_teardown(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
if (data->siv) {
|
||||
string_input_visitor_cleanup(data->siv);
|
||||
data->siv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is provided instead of a test setup function so that the JSON
|
||||
string used by the tests are kept in the test functions (and not
|
||||
int main()) */
|
||||
static
|
||||
Visitor *visitor_input_test_init(TestInputVisitorData *data,
|
||||
const char *string)
|
||||
{
|
||||
Visitor *v;
|
||||
|
||||
data->siv = string_input_visitor_new(string);
|
||||
g_assert(data->siv != NULL);
|
||||
|
||||
v = string_input_get_visitor(data->siv);
|
||||
g_assert(v != NULL);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static void test_visitor_in_int(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
int64_t res = 0, value = -42;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "-42");
|
||||
|
||||
visit_type_int(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, value);
|
||||
}
|
||||
|
||||
static void test_visitor_in_bool(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
bool res = false;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "true");
|
||||
|
||||
visit_type_bool(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, true);
|
||||
visitor_input_teardown(data, unused);
|
||||
|
||||
v = visitor_input_test_init(data, "yes");
|
||||
|
||||
visit_type_bool(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, true);
|
||||
visitor_input_teardown(data, unused);
|
||||
|
||||
v = visitor_input_test_init(data, "on");
|
||||
|
||||
visit_type_bool(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, true);
|
||||
visitor_input_teardown(data, unused);
|
||||
|
||||
v = visitor_input_test_init(data, "false");
|
||||
|
||||
visit_type_bool(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, false);
|
||||
visitor_input_teardown(data, unused);
|
||||
|
||||
v = visitor_input_test_init(data, "no");
|
||||
|
||||
visit_type_bool(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, false);
|
||||
visitor_input_teardown(data, unused);
|
||||
|
||||
v = visitor_input_test_init(data, "off");
|
||||
|
||||
visit_type_bool(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(res, ==, false);
|
||||
}
|
||||
|
||||
static void test_visitor_in_number(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
double res = 0, value = 3.14;
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "3.14");
|
||||
|
||||
visit_type_number(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpfloat(res, ==, value);
|
||||
}
|
||||
|
||||
static void test_visitor_in_string(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
char *res = NULL, *value = (char *) "Q E M U";
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, value);
|
||||
|
||||
visit_type_str(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpstr(res, ==, value);
|
||||
|
||||
g_free(res);
|
||||
}
|
||||
|
||||
static void test_visitor_in_enum(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
Visitor *v;
|
||||
EnumOne i;
|
||||
|
||||
for (i = 0; EnumOne_lookup[i]; i++) {
|
||||
EnumOne res = -1;
|
||||
|
||||
v = visitor_input_test_init(data, EnumOne_lookup[i]);
|
||||
|
||||
visit_type_EnumOne(v, &res, NULL, &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
g_assert_cmpint(i, ==, res);
|
||||
|
||||
visitor_input_teardown(data, NULL);
|
||||
}
|
||||
|
||||
data->siv = NULL;
|
||||
}
|
||||
|
||||
static void input_visitor_test_add(const char *testpath,
|
||||
TestInputVisitorData *data,
|
||||
void (*test_func)(TestInputVisitorData *data, const void *user_data))
|
||||
{
|
||||
g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
|
||||
visitor_input_teardown);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestInputVisitorData in_visitor_data;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
input_visitor_test_add("/string-visitor/input/int",
|
||||
&in_visitor_data, test_visitor_in_int);
|
||||
input_visitor_test_add("/string-visitor/input/bool",
|
||||
&in_visitor_data, test_visitor_in_bool);
|
||||
input_visitor_test_add("/string-visitor/input/number",
|
||||
&in_visitor_data, test_visitor_in_number);
|
||||
input_visitor_test_add("/string-visitor/input/string",
|
||||
&in_visitor_data, test_visitor_in_string);
|
||||
input_visitor_test_add("/string-visitor/input/enum",
|
||||
&in_visitor_data, test_visitor_in_enum);
|
||||
|
||||
g_test_run();
|
||||
|
||||
return 0;
|
||||
}
|
188
tests/test-string-output-visitor.c
Normal file
188
tests/test-string-output-visitor.c
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* String Output Visitor unit-tests.
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-output-visitor)
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "qapi/string-output-visitor.h"
|
||||
#include "test-qapi-types.h"
|
||||
#include "test-qapi-visit.h"
|
||||
#include "qemu-objects.h"
|
||||
|
||||
typedef struct TestOutputVisitorData {
|
||||
StringOutputVisitor *sov;
|
||||
Visitor *ov;
|
||||
} TestOutputVisitorData;
|
||||
|
||||
static void visitor_output_setup(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
data->sov = string_output_visitor_new();
|
||||
g_assert(data->sov != NULL);
|
||||
|
||||
data->ov = string_output_get_visitor(data->sov);
|
||||
g_assert(data->ov != NULL);
|
||||
}
|
||||
|
||||
static void visitor_output_teardown(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
string_output_visitor_cleanup(data->sov);
|
||||
data->sov = NULL;
|
||||
data->ov = NULL;
|
||||
}
|
||||
|
||||
static void test_visitor_out_int(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
int64_t value = -42;
|
||||
Error *errp = NULL;
|
||||
char *str;
|
||||
|
||||
visit_type_int(data->ov, &value, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
str = string_output_get_string(data->sov);
|
||||
g_assert(str != NULL);
|
||||
g_assert_cmpstr(str, ==, "-42");
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void test_visitor_out_bool(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
bool value = true;
|
||||
char *str;
|
||||
|
||||
visit_type_bool(data->ov, &value, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
str = string_output_get_string(data->sov);
|
||||
g_assert(str != NULL);
|
||||
g_assert_cmpstr(str, ==, "true");
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void test_visitor_out_number(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
double value = 3.14;
|
||||
Error *errp = NULL;
|
||||
char *str;
|
||||
|
||||
visit_type_number(data->ov, &value, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
str = string_output_get_string(data->sov);
|
||||
g_assert(str != NULL);
|
||||
g_assert_cmpstr(str, ==, "3.14");
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void test_visitor_out_string(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
char *string = (char *) "Q E M U";
|
||||
Error *errp = NULL;
|
||||
char *str;
|
||||
|
||||
visit_type_str(data->ov, &string, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
str = string_output_get_string(data->sov);
|
||||
g_assert(str != NULL);
|
||||
g_assert_cmpstr(str, ==, string);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void test_visitor_out_no_string(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
char *string = NULL;
|
||||
Error *errp = NULL;
|
||||
char *str;
|
||||
|
||||
/* A null string should return "" */
|
||||
visit_type_str(data->ov, &string, NULL, &errp);
|
||||
g_assert(error_is_set(&errp) == 0);
|
||||
|
||||
str = string_output_get_string(data->sov);
|
||||
g_assert(str != NULL);
|
||||
g_assert_cmpstr(str, ==, "");
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void test_visitor_out_enum(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
char *str;
|
||||
EnumOne i;
|
||||
|
||||
for (i = 0; i < ENUM_ONE_MAX; i++) {
|
||||
visit_type_EnumOne(data->ov, &i, "unused", &errp);
|
||||
g_assert(!error_is_set(&errp));
|
||||
|
||||
str = string_output_get_string(data->sov);
|
||||
g_assert(str != NULL);
|
||||
g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
|
||||
g_free(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
|
||||
Error *errp;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
|
||||
errp = NULL;
|
||||
visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
|
||||
g_assert(error_is_set(&errp) == true);
|
||||
error_free(errp);
|
||||
}
|
||||
}
|
||||
|
||||
static void output_visitor_test_add(const char *testpath,
|
||||
TestOutputVisitorData *data,
|
||||
void (*test_func)(TestOutputVisitorData *data, const void *user_data))
|
||||
{
|
||||
g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
|
||||
test_func, visitor_output_teardown);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
TestOutputVisitorData out_visitor_data;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
output_visitor_test_add("/string-visitor/output/int",
|
||||
&out_visitor_data, test_visitor_out_int);
|
||||
output_visitor_test_add("/string-visitor/output/bool",
|
||||
&out_visitor_data, test_visitor_out_bool);
|
||||
output_visitor_test_add("/string-visitor/output/number",
|
||||
&out_visitor_data, test_visitor_out_number);
|
||||
output_visitor_test_add("/string-visitor/output/string",
|
||||
&out_visitor_data, test_visitor_out_string);
|
||||
output_visitor_test_add("/string-visitor/output/no-string",
|
||||
&out_visitor_data, test_visitor_out_no_string);
|
||||
output_visitor_test_add("/string-visitor/output/enum",
|
||||
&out_visitor_data, test_visitor_out_enum);
|
||||
output_visitor_test_add("/string-visitor/output/enum-errors",
|
||||
&out_visitor_data, test_visitor_out_enum_errors);
|
||||
|
||||
g_test_run();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue