These patches implement asn1 ber visitors for encoding and decoding data. References: <20130226230354.982917...@linux.vnet.ibm.com> Content-Disposition: inline; filename=asn1_tests.diff
Signed-off-by: Stefan Berger <stef...@linux.vnet.ibm.com> Signed-off-by: Joel Schopp <jsch...@linux.vnet.ibm.com> --- tests/Makefile | 12 + tests/test-ber-visitor.c | 518 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 530 insertions(+) Index: b/tests/test-ber-visitor.c =================================================================== --- /dev/null +++ b/tests/test-ber-visitor.c @@ -0,0 +1,518 @@ +/* + * BER Output Visitor unit-tests. + * + * Copyright (C) 2011 Red Hat Inc. + * Copyright (C) 2011 IBM Corporation + * + * Authors: + * Luiz Capitulino <lcapitul...@redhat.com> + * Stefan Berger <stef...@linux.vnet.ibm.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 "qemu-common.h" +#include "ber/ber-output-visitor.h" +#include "ber/ber-input-visitor.h" +#include "hw/hw.h" +#include "include/qapi/visitor.h" + + +typedef struct TestInputOutputVisitorData { + QEMUFile *qoutfile; + BEROutputVisitor *bov; + Visitor *ov; + + QEMUFile *qinfile; + BERInputVisitor *biv; + Visitor *iv; +} TestInputOutputVisitor; + +static void visitor_output_setup(TestInputOutputVisitor *data, + BERTypePC ber_type_pc) +{ + data->qoutfile = qemu_bufopen("w", NULL); + + data->bov = ber_output_visitor_new(data->qoutfile, ber_type_pc); + g_assert(data->bov != NULL); + + data->ov = ber_output_get_visitor(data->bov); + g_assert(data->ov != NULL); +} + +static void visitor_output_setup_primitive(TestInputOutputVisitor *data, + const void *unused) +{ + visitor_output_setup(data, BER_TYPE_PRIMITIVE); +} + +static void visitor_output_setup_constructed(TestInputOutputVisitor *data, + const void *unused) +{ + visitor_output_setup(data, BER_TYPE_CONSTRUCTED); +} + +static void visitor_input_setup(TestInputOutputVisitor *data) +{ + const QEMUSizedBuffer *qsb = qemu_buf_get(data->qoutfile); + QEMUSizedBuffer *new_qsb = qsb_clone(qsb); + g_assert(new_qsb != NULL); + + data->qinfile = qemu_bufopen("r", new_qsb); + g_assert(data->qinfile != NULL); + + data->biv = ber_input_visitor_new(data->qinfile, ~0); + g_assert(data->biv != NULL); + + data->iv = ber_input_get_visitor(data->biv); + g_assert(data->iv != NULL); +} + +static void visitor_output_teardown(TestInputOutputVisitor *data, + const void *unused) +{ + ber_output_visitor_cleanup(data->bov); + data->bov = NULL; + data->ov = NULL; + + ber_input_visitor_cleanup(data->biv); + data->biv = NULL; + data->iv = NULL; + + if (data->qinfile) { + qemu_fclose(data->qinfile); + } + if (data->qoutfile) { + qemu_fclose(data->qoutfile); + } +} + +static void test_visitor_out_int(TestInputOutputVisitor *data, + const void *unused) +{ + int64_t value_in = -42, value_out = 0; + Error *errp = NULL; + + visit_type_int(data->ov, &value_in, NULL, &errp); + g_assert(error_is_set(&errp) == 0); + + visitor_input_setup(data); + + visit_type_int(data->iv, &value_out, NULL, &errp); + g_assert_cmpint(value_out, ==, -42); +} + +static void test_visitor_out_bool(TestInputOutputVisitor *data, + const void *unused) +{ + Error *errp = NULL; + bool value_in = true, value_out = false; + + visit_type_bool(data->ov, &value_in, NULL, &errp); + g_assert(error_is_set(&errp) == 0); + + visitor_input_setup(data); + + visit_type_bool(data->iv, &value_out, NULL, &errp); + g_assert_cmpint(value_out, ==, true); + +} + +static void test_visitor_out_string(TestInputOutputVisitor *data, + const void *unused) +{ + char *string_in = (char *) "Q E M U", *string_out = NULL; + Error *errp = NULL; + + visit_type_str(data->ov, &string_in, NULL, &errp); + g_assert(error_is_set(&errp) == 0); + + visitor_input_setup(data); + + visit_type_str(data->iv, &string_out, NULL, &errp); + + g_assert_cmpstr(string_out, ==, string_in); + g_free(string_out); +} + +static void test_visitor_out_no_string(TestInputOutputVisitor *data, + const void *unused) +{ + char *string_in = NULL, *string_out = NULL; + Error *errp = NULL; + + /* A null string should return "" */ + visit_type_str(data->ov, &string_in, NULL, &errp); + g_assert(error_is_set(&errp) == 0); + g_assert(qsb_get_length(qemu_buf_get(data->qoutfile)) == 2); + + visitor_input_setup(data); + + visit_type_str(data->iv, &string_out, NULL, &errp); + g_assert_cmpstr(string_out, ==, ""); + + g_free(string_out); +} + +typedef struct SimpleStruct { + int64_t integer; + bool boolean; + char *string; +} SimpleStruct; + +static void visit_type_SimpleStruct(Visitor *v, SimpleStruct **obj, + const char *name, Error **errp) +{ + visit_start_struct(v, (void **)obj, "SimpleStruct", name, + sizeof(SimpleStruct), 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(TestInputOutputVisitor *data, + const void *unused) +{ + SimpleStruct test_struct = { + .integer = 42, + .boolean = false, + .string = (char *)"foo" + }; + SimpleStruct *p_in = &test_struct, *p_out = NULL; + Error *errp = NULL; + + visit_type_SimpleStruct(data->ov, &p_in, NULL, &errp); + g_assert(!error_is_set(&errp)); + + visitor_input_setup(data); + + visit_type_SimpleStruct(data->iv, &p_out, NULL, &errp); + + g_assert_cmpint(p_out->integer, ==, 42); + g_assert_cmpint(p_out->boolean, ==, 0); + g_assert_cmpstr(p_out->string, ==, "foo"); + + g_free(p_out->string); + g_free(p_out); +} + +static void visit_type_SimpleStructArray(Visitor *v, SimpleStruct **obj, + const char *name, + size_t elem_count, size_t elem_size, + Error **errp) +{ + size_t i; + + visit_start_array(v, (void **)obj, name, elem_count, elem_size, errp); + + for (i = 0; i < elem_count; i++) { + SimpleStruct *s = &((*obj)[i]); + visit_type_SimpleStruct(v, &s, "SimpleStruct", errp); + visit_next_array(v, errp); + } + + visit_end_array(v, errp); +} + +static void test_visitor_out_array(TestInputOutputVisitor *data, + const void *unused) +{ + SimpleStruct test_struct[] = { + { + .integer = 42, + .boolean = false, + .string = (char *)"foo" + }, { + .integer = 1000, + .boolean = true, + .string = (char *)"bar" + } + }; + SimpleStruct *p_in = test_struct, *p_out = NULL; + Error *errp = NULL; + + visit_type_SimpleStructArray(data->ov, &p_in, NULL, + ARRAY_SIZE(test_struct), + sizeof(test_struct[0]), &errp); + g_assert(!error_is_set(&errp)); + + visitor_input_setup(data); + + visit_type_SimpleStructArray(data->iv, &p_out, NULL, + ARRAY_SIZE(test_struct), + sizeof(test_struct[0]), &errp); + + g_assert_cmpint(p_out[0].integer, ==, 42); + g_assert_cmpint(p_out[0].boolean, ==, 0); + g_assert_cmpstr(p_out[0].string, ==, "foo"); + + g_assert_cmpint(p_out[1].integer, ==, 1000); + g_assert_cmpint(p_out[1].boolean, ==, 1); + g_assert_cmpstr(p_out[1].string, ==, "bar"); + + g_free(p_out[0].string); + g_free(p_out[1].string); + g_free(p_out); +} + +typedef struct NestedStruct { + int64_t integer; + bool boolean; + SimpleStruct simpleStruct[2]; + char *string; +} NestedStruct; + +static void visit_type_NestedStruct(Visitor *v, NestedStruct **obj, + const char *name, Error **errp) +{ + unsigned int i; + + visit_start_struct(v, (void **)obj, "NestedStruct", name, + sizeof(NestedStruct), errp); + + visit_type_int(v, &(*obj)->integer, "integer", errp); + visit_type_bool(v, &(*obj)->boolean, "boolean", errp); + + for (i = 0; i < ARRAY_SIZE((*obj)->simpleStruct); i++) { + SimpleStruct *simple = &(*obj)->simpleStruct[i]; + visit_type_SimpleStruct(v, &simple, "SimpleStruct", errp); + } + + visit_type_str(v, &(*obj)->string, "string", errp); + + visit_end_struct(v, errp); +} + +static void test_visitor_out_nested_struct(TestInputOutputVisitor *data, + const void *unused) +{ + NestedStruct nested_struct = { + .integer = 42, + .boolean = true, + .simpleStruct = { + { + .integer = 1000, + .boolean = false, + .string = (char *)"Hello", + }, { + .integer = 2000, + .boolean = false, + .string = (char *)"world!", + }, + }, + .string = (char *)"bar", + }; + NestedStruct *p_in = &nested_struct, *p_out = NULL; + Error *errp = NULL; + unsigned int i; + + visit_type_NestedStruct(data->ov, &p_in, NULL, &errp); + g_assert(!error_is_set(&errp)); + + visitor_input_setup(data); + + visit_type_NestedStruct(data->iv, &p_out, NULL, &errp); + + g_assert_cmpint(p_out->integer, ==, 42); + g_assert_cmpint(p_out->boolean, ==, true); + + g_assert_cmpint(p_out->simpleStruct[0].integer, ==, 1000); + g_assert_cmpint(p_out->simpleStruct[0].boolean, ==, 0); + g_assert_cmpstr(p_out->simpleStruct[0].string , ==, "Hello"); + + g_assert_cmpint(p_out->simpleStruct[1].integer, ==, 2000); + g_assert_cmpint(p_out->simpleStruct[1].boolean, ==, 0); + g_assert_cmpstr(p_out->simpleStruct[1].string , ==, "world!"); + + g_assert_cmpstr(p_out->string, ==, "bar"); + + g_free(p_out->string); + for (i = 0; i < ARRAY_SIZE(p_out->simpleStruct); i++) { + g_free(p_out->simpleStruct[i].string); + } + g_free(p_out); +} + +typedef struct SimpleStringList { + char *value; + struct SimpleStringList *next; +} SimpleStringList; + +static void visit_type_SimpleStringList(Visitor *m, SimpleStringList ** obj, + const char *name, Error **errp) +{ + GenericList *i, **head = (GenericList **)obj; + + visit_start_list(m, name, errp); + + for (*head = i = visit_next_list(m, head, errp); + i; + i = visit_next_list(m, &i, errp)) { + SimpleStringList *native_i = (SimpleStringList *)i; + visit_type_str(m, &native_i->value, NULL, errp); + } + + visit_end_list(m, errp); +} + +static void test_visitor_out_list(TestInputOutputVisitor *data, + const void *unused) +{ + SimpleStringList test_list = { + .value = (char *)"hello", + .next = &(SimpleStringList) { + .value = (char *)"world", + .next = NULL, + }, + }; + SimpleStringList *p_in = &test_list, *p_out = NULL, *iter = NULL, *_iter; + Error *errp = NULL; + + visit_type_SimpleStringList(data->ov, &p_in, "SimpleStringList", &errp); + g_assert(!error_is_set(&errp)); + + visitor_input_setup(data); + + visit_type_SimpleStringList(data->iv, &p_out, "SimpleStringList", &errp); + g_assert(!error_is_set(&errp)); + + iter = p_out; + g_assert_cmpstr(iter->value, ==, "hello"); + iter = iter->next; + g_assert_cmpstr(iter->value, ==, "world"); + + for (iter = p_out; iter; iter = _iter) { + _iter = iter->next; + g_free(iter->value); + g_free(iter); + } +} + +typedef struct SimpleStructList { + SimpleStruct *value; + struct SimpleStructList *next; +} SimpleStructList; + +static void visit_type_SimpleStructList(Visitor *m, SimpleStructList ** obj, + const char *name, Error **errp) +{ + GenericList *i, **head = (GenericList **)obj; + + visit_start_list(m, name, errp); + + for (*head = i = visit_next_list(m, head, errp); + i; + i = visit_next_list(m, &i, errp)) { + SimpleStructList *native_i = (SimpleStructList *)i; + visit_type_SimpleStruct(m, &native_i->value, NULL, errp); + } + + visit_end_list(m, errp); +} + +static void test_visitor_out_simplestruct_list(TestInputOutputVisitor *data, + const void *unused) +{ + SimpleStructList test_list = { + .value = &(SimpleStruct) { + .string = (char *)"hello", + .integer = 1000, + .boolean = false, + }, + .next = &(SimpleStructList) { + .value = &(SimpleStruct) { + .string = (char *)"world", + .integer = 2000, + .boolean = true, + }, + .next = NULL, + }, + }; + SimpleStructList *p_in = &test_list, *p_out = NULL, *iter = NULL, *_iter; + Error *errp = NULL; + + visit_type_SimpleStructList(data->ov, &p_in, "SimpleStructList", &errp); + g_assert(!error_is_set(&errp)); + + visitor_input_setup(data); + + visit_type_SimpleStructList(data->iv, &p_out, "SimpleStructList", &errp); + g_assert(!error_is_set(&errp)); + + iter = p_out; + g_assert_cmpstr(iter->value->string, ==, "hello"); + iter = iter->next; + g_assert_cmpstr(iter->value->string, ==, "world"); + + for (iter = p_out; iter; iter = _iter) { + _iter = iter->next; + g_free(iter->value->string); + g_free(iter->value); + g_free(iter); + } +} + +static void test_visitor_test_add(const char *testpath, + BERTypePC ber_type, + TestInputOutputVisitor *data, + void (*test_func)(TestInputOutputVisitor *data, const void *user_data)) +{ + char path[64]; + void (*setup)(TestInputOutputVisitor *data, const void *unused); + + switch (ber_type) { + case BER_TYPE_PRIMITIVE: + snprintf(path, sizeof(path), "/primitive%s", testpath); + setup = visitor_output_setup_primitive; + break; + default: + snprintf(path, sizeof(path), "/constructed%s", testpath); + setup = visitor_output_setup_constructed; + break; + } + + g_test_add(path, TestInputOutputVisitor, data, setup, + test_func, visitor_output_teardown); +} + +int main(int argc, char **argv) +{ + TestInputOutputVisitor out_visitor_data; + BERTypePC types[] = {BER_TYPE_CONSTRUCTED, BER_TYPE_PRIMITIVE}; + int i; + + g_test_init(&argc, &argv, NULL); + + for (i = 0; i < ARRAY_SIZE(types); i++) { + test_visitor_test_add("/visitor/output/int", types[i], + &out_visitor_data, test_visitor_out_int); + test_visitor_test_add("/visitor/output/bool", types[i], + &out_visitor_data, test_visitor_out_bool); + test_visitor_test_add("/visitor/output/string", types[i], + &out_visitor_data, test_visitor_out_string); + test_visitor_test_add("/visitor/output/no-string", types[i], + &out_visitor_data, test_visitor_out_no_string); + test_visitor_test_add("/visitor/output/struct", types[i], + &out_visitor_data, test_visitor_out_struct); + test_visitor_test_add("/visitor/output/array", types[i], + &out_visitor_data, test_visitor_out_array); + test_visitor_test_add("/visitor/output/nested-struct", types[i], + &out_visitor_data, + test_visitor_out_nested_struct); + test_visitor_test_add("/visitor/output/list", types[i], + &out_visitor_data, test_visitor_out_list); + test_visitor_test_add("/visitor/output/simplestruct_list", types[i], + &out_visitor_data, + test_visitor_out_simplestruct_list); + } + + g_test_run(); + + return 0; +} Index: b/tests/Makefile =================================================================== --- a/tests/Makefile +++ b/tests/Makefile @@ -23,6 +23,10 @@ check-unit-y += tests/test-string-input- gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c check-unit-y += tests/test-string-output-visitor$(EXESUF) gcov-files-test-string-output-visitor-y = qapi/string-output-visitor.c +check-unit-y += tests/test-ber-visitor$(EXESUF) +gcov-files-test-vistor-y = ber/ + + check-unit-y += tests/test-coroutine$(EXESUF) ifeq ($(CONFIG_WIN32),y) gcov-files-test-coroutine-y = coroutine-win32.c @@ -134,6 +138,14 @@ tests/fdc-test$(EXESUF): tests/fdc-test. tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o tests/tmp105-test$(EXESUF): tests/tmp105-test.o +ber-dir = ber + +tests/test-ber-visitor.o : QEMU_CFLAGS += -I $(ber-dir) + +tests/test-ber-visitor.o: $(addprefix $(ber-dir)/, ber-common.c ber.h ber-input-visitor.c ber-input-visitor.h ber-output-visitor.c ber-output-visitor.h) $(ber-obj-y) +#tests/test-ber-visitor$(EXESUF): tests/test-ber-visitor.o $(tools-obj-y) $(ber-dir)/ber-output-visitor.o $(ber-dir)/ber-input-visitor.o $(ber-dir)/ber-common.o $(block-obj-y) qemu-file.o libqemustub.a $(qobject-obj-y) $(qapi-obj-y) +tests/test-ber-visitor$(EXESUF): tests/test-ber-visitor.o $(tools-obj-y) $(ber-dir)/ber-output-visitor.o $(ber-dir)/ber-input-visitor.o $(ber-dir)/ber-common.o $(block-obj-y) qemu-file.o libqemuutil.a libqemustub.a + # QTest rules TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))