From patchwork Fri May 10 22:46:08 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 243087 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9C5EE2C00E0 for ; Sat, 11 May 2013 08:52:13 +1000 (EST) Received: from localhost ([::1]:53127 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UawAd-0000k9-Sg for incoming@patchwork.ozlabs.org; Fri, 10 May 2013 18:52:11 -0400 Received: from eggs.gnu.org ([208.118.235.92]:34605) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uaw6C-0001sX-Ot for qemu-devel@nongnu.org; Fri, 10 May 2013 18:47:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Uaw6B-0001VI-2S for qemu-devel@nongnu.org; Fri, 10 May 2013 18:47:36 -0400 Received: from mail-ie0-x22a.google.com ([2607:f8b0:4001:c03::22a]:61622) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uaw6A-0001VD-SS for qemu-devel@nongnu.org; Fri, 10 May 2013 18:47:35 -0400 Received: by mail-ie0-f170.google.com with SMTP id aq17so9321096iec.29 for ; Fri, 10 May 2013 15:47:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=GE2OGhDd/rjSmVYngTMDSvsdVD8KmjWm1LWShUBDf14=; b=G/SJHycOC1V6gDEGjuar7Kg/p9KOJQsMXfCrV5Mrxyads07r56wvG296+fvXsAYgzF VrKj3WlSeI4mdzr57DK7xPb4dLKEnWkZr8Kd9Ysr7oHEK/v1Ruwd3NSaqUnEZ0iB3qo+ 8R8D+FiR2zBn652E8Ro1b6quhl1sOMvBKWJbuSZAqHM9o0M2pdimMTjxT9FV0jEyHsfy twJ5aphaqbAhQjEfeF0HihXlDuZGVj7sYNEKrXp3zePwfV8kNntDDxkLd80Kp5xHGfQ/ f4bGIqG4cjvcQGD0JZ/HRsy8gWCKFfVziFb0t+JAqp+MXu6zLSU/qww32Mbn8mh11JI4 bgUw== X-Received: by 10.50.83.102 with SMTP id p6mr3524535igy.45.1368226054369; Fri, 10 May 2013 15:47:34 -0700 (PDT) Received: from localhost (cpe-72-177-121-217.austin.res.rr.com. [72.177.121.217]) by mx.google.com with ESMTPSA id lr1sm902954igb.6.2013.05.10.15.47.32 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 10 May 2013 15:47:33 -0700 (PDT) From: Michael Roth To: qemu-devel@nongnu.org Date: Fri, 10 May 2013 17:46:08 -0500 Message-Id: <1368225970-28506-10-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1368225970-28506-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1368225970-28506-1-git-send-email-mdroth@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:4001:c03::22a Cc: akong@redhat.com, lersek@redhat.com, lcapitulino@redhat.com Subject: [Qemu-devel] [PATCH 09/11] qapi: add native list coverage for visitor serialization tests X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Michael Roth --- tests/test-visitor-serialization.c | 451 ++++++++++++++++++++++++++++++++++-- 1 file changed, 433 insertions(+), 18 deletions(-) diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c index fed6810..ee7916b 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -23,6 +23,25 @@ #include "qapi/qmp-output-visitor.h" #include "qapi/string-input-visitor.h" #include "qapi/string-output-visitor.h" +#include "qapi-types.h" +#include "qapi-visit.h" +#include "qapi/dealloc-visitor.h" + +enum PrimitiveTypeKind { + PTYPE_STRING = 0, + PTYPE_BOOLEAN, + PTYPE_NUMBER, + PTYPE_INTEGER, + PTYPE_U8, + PTYPE_U16, + PTYPE_U32, + PTYPE_U64, + PTYPE_S8, + PTYPE_S16, + PTYPE_S32, + PTYPE_S64, + PTYPE_EOL, +}; typedef struct PrimitiveType { union { @@ -40,26 +59,42 @@ typedef struct PrimitiveType { int64_t s64; intmax_t max; } value; - enum { - PTYPE_STRING = 0, - PTYPE_BOOLEAN, - PTYPE_NUMBER, - PTYPE_INTEGER, - PTYPE_U8, - PTYPE_U16, - PTYPE_U32, - PTYPE_U64, - PTYPE_S8, - PTYPE_S16, - PTYPE_S32, - PTYPE_S64, - PTYPE_EOL, - } type; + enum PrimitiveTypeKind type; const char *description; } PrimitiveType; +typedef struct PrimitiveList { + union { + strList *strings; + boolList *booleans; + numberList *numbers; + intList *integers; + int8List *s8_integers; + int16List *s16_integers; + int32List *s32_integers; + int64List *s64_integers; + uint8List *u8_integers; + uint16List *u16_integers; + uint32List *u32_integers; + uint64List *u64_integers; + } value; + enum PrimitiveTypeKind type; + const char *description; +} PrimitiveList; + /* test helpers */ +typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp); + +static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp) +{ + QapiDeallocVisitor *qdv = qapi_dealloc_visitor_new(); + + visit(qapi_dealloc_get_visitor(qdv), &native_in, errp); + + qapi_dealloc_visitor_cleanup(qdv); +} + static void visit_primitive_type(Visitor *v, void **native, Error **errp) { PrimitiveType *pt = *native; @@ -105,6 +140,51 @@ static void visit_primitive_type(Visitor *v, void **native, Error **errp) } } +static void visit_primitive_list(Visitor *v, void **native, Error **errp) +{ + PrimitiveList *pl = *native; + switch (pl->type) { + case PTYPE_STRING: + visit_type_strList(v, &pl->value.strings, NULL, errp); + break; + case PTYPE_BOOLEAN: + visit_type_boolList(v, &pl->value.booleans, NULL, errp); + break; + case PTYPE_NUMBER: + visit_type_numberList(v, &pl->value.numbers, NULL, errp); + break; + case PTYPE_INTEGER: + visit_type_intList(v, &pl->value.integers, NULL, errp); + break; + case PTYPE_S8: + visit_type_int8List(v, &pl->value.s8_integers, NULL, errp); + break; + case PTYPE_S16: + visit_type_int16List(v, &pl->value.s16_integers, NULL, errp); + break; + case PTYPE_S32: + visit_type_int32List(v, &pl->value.s32_integers, NULL, errp); + break; + case PTYPE_S64: + visit_type_int64List(v, &pl->value.s64_integers, NULL, errp); + break; + case PTYPE_U8: + visit_type_uint8List(v, &pl->value.u8_integers, NULL, errp); + break; + case PTYPE_U16: + visit_type_uint16List(v, &pl->value.u16_integers, NULL, errp); + break; + case PTYPE_U32: + visit_type_uint32List(v, &pl->value.u32_integers, NULL, errp); + break; + case PTYPE_U64: + visit_type_uint64List(v, &pl->value.u64_integers, NULL, errp); + break; + default: + g_assert(false); + } +} + typedef struct TestStruct { int64_t integer; @@ -206,12 +286,11 @@ static void visit_nested_struct_list(Visitor *v, void **native, Error **errp) /* test cases */ -typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp); - typedef enum VisitorCapabilities { VCAP_PRIMITIVES = 1, VCAP_STRUCTURES = 2, VCAP_LISTS = 4, + VCAP_PRIMITIVE_LISTS = 8, } VisitorCapabilities; typedef struct SerializeOps { @@ -270,6 +349,328 @@ static void test_primitives(gconstpointer opaque) g_free(pt_copy); } +static void test_primitive_lists(gconstpointer opaque) +{ + TestArgs *args = (TestArgs *) opaque; + const SerializeOps *ops = args->ops; + PrimitiveType *pt = args->test_data; + PrimitiveList pl = { .value = { 0 } }; + PrimitiveList pl_copy = { .value = { 0 } }; + PrimitiveList *pl_copy_ptr = &pl_copy; + Error *err = NULL; + void *serialize_data; + void *cur_head = NULL; + int i; + + pl.type = pl_copy.type = pt->type; + + /* build up our list of primitive types */ + for (i = 0; i < 32; i++) { + switch (pl.type) { + case PTYPE_STRING: { + strList *tmp = g_new0(strList, 1); + tmp->value = g_strdup(pt->value.string); + if (pl.value.strings == NULL) { + pl.value.strings = tmp; + } else { + tmp->next = pl.value.strings; + pl.value.strings = tmp; + } + break; + } + case PTYPE_INTEGER: { + intList *tmp = g_new0(intList, 1); + tmp->value = pt->value.integer; + if (pl.value.integers == NULL) { + pl.value.integers = tmp; + } else { + tmp->next = pl.value.integers; + pl.value.integers = tmp; + } + break; + } + case PTYPE_S8: { + int8List *tmp = g_new0(int8List, 1); + tmp->value = pt->value.s8; + if (pl.value.s8_integers == NULL) { + pl.value.s8_integers = tmp; + } else { + tmp->next = pl.value.s8_integers; + pl.value.s8_integers = tmp; + } + break; + } + case PTYPE_S16: { + int16List *tmp = g_new0(int16List, 1); + tmp->value = pt->value.s16; + if (pl.value.s16_integers == NULL) { + pl.value.s16_integers = tmp; + } else { + tmp->next = pl.value.s16_integers; + pl.value.s16_integers = tmp; + } + break; + } + case PTYPE_S32: { + int32List *tmp = g_new0(int32List, 1); + tmp->value = pt->value.s32; + if (pl.value.s32_integers == NULL) { + pl.value.s32_integers = tmp; + } else { + tmp->next = pl.value.s32_integers; + pl.value.s32_integers = tmp; + } + break; + } + case PTYPE_S64: { + int64List *tmp = g_new0(int64List, 1); + tmp->value = pt->value.s64; + if (pl.value.s64_integers == NULL) { + pl.value.s64_integers = tmp; + } else { + tmp->next = pl.value.s64_integers; + pl.value.s64_integers = tmp; + } + break; + } + case PTYPE_U8: { + uint8List *tmp = g_new0(uint8List, 1); + tmp->value = pt->value.u8; + if (pl.value.u8_integers == NULL) { + pl.value.u8_integers = tmp; + } else { + tmp->next = pl.value.u8_integers; + pl.value.u8_integers = tmp; + } + break; + } + case PTYPE_U16: { + uint16List *tmp = g_new0(uint16List, 1); + tmp->value = pt->value.u16; + if (pl.value.u16_integers == NULL) { + pl.value.u16_integers = tmp; + } else { + tmp->next = pl.value.u16_integers; + pl.value.u16_integers = tmp; + } + break; + } + case PTYPE_U32: { + uint32List *tmp = g_new0(uint32List, 1); + tmp->value = pt->value.u32; + if (pl.value.u32_integers == NULL) { + pl.value.u32_integers = tmp; + } else { + tmp->next = pl.value.u32_integers; + pl.value.u32_integers = tmp; + } + break; + } + case PTYPE_U64: { + uint64List *tmp = g_new0(uint64List, 1); + tmp->value = pt->value.u64; + if (pl.value.u64_integers == NULL) { + pl.value.u64_integers = tmp; + } else { + tmp->next = pl.value.u64_integers; + pl.value.u64_integers = tmp; + } + break; + } + case PTYPE_NUMBER: { + numberList *tmp = g_new0(numberList, 1); + tmp->value = pt->value.number; + if (pl.value.numbers == NULL) { + pl.value.numbers = tmp; + } else { + tmp->next = pl.value.numbers; + pl.value.numbers = tmp; + } + break; + } + case PTYPE_BOOLEAN: { + boolList *tmp = g_new0(boolList, 1); + tmp->value = pt->value.boolean; + if (pl.value.booleans == NULL) { + pl.value.booleans = tmp; + } else { + tmp->next = pl.value.booleans; + pl.value.booleans = tmp; + } + break; + } + default: + g_assert(0); + } + } + + ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err); + ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err); + + g_assert(err == NULL); + i = 0; + + /* compare our deserialized list of primitives to the original */ + do { + switch (pl_copy.type) { + case PTYPE_STRING: { + strList *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.strings; + } + g_assert_cmpstr(pt->value.string, ==, ptr->value); + break; + } + case PTYPE_INTEGER: { + intList *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.integers; + } + g_assert_cmpint(pt->value.integer, ==, ptr->value); + break; + } + case PTYPE_S8: { + int8List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.s8_integers; + } + g_assert_cmpint(pt->value.s8, ==, ptr->value); + break; + } + case PTYPE_S16: { + int16List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.s16_integers; + } + g_assert_cmpint(pt->value.s16, ==, ptr->value); + break; + } + case PTYPE_S32: { + int32List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.s32_integers; + } + g_assert_cmpint(pt->value.s32, ==, ptr->value); + break; + } + case PTYPE_S64: { + int64List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.s64_integers; + } + g_assert_cmpint(pt->value.s64, ==, ptr->value); + break; + } + case PTYPE_U8: { + uint8List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.u8_integers; + } + g_assert_cmpint(pt->value.u8, ==, ptr->value); + break; + } + case PTYPE_U16: { + uint16List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.u16_integers; + } + g_assert_cmpint(pt->value.u16, ==, ptr->value); + break; + } + case PTYPE_U32: { + uint32List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.u32_integers; + } + g_assert_cmpint(pt->value.u32, ==, ptr->value); + break; + } + case PTYPE_U64: { + uint64List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.u64_integers; + } + g_assert_cmpint(pt->value.u64, ==, ptr->value); + break; + } + case PTYPE_NUMBER: { + numberList *ptr; + GString *double_expected = g_string_new(""); + GString *double_actual = g_string_new(""); + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.numbers; + } + /* we serialize with %f for our reference visitors, so rather than + * fuzzy floating math to test "equality", just compare the + * formatted values + */ + g_string_printf(double_expected, "%.6f", pt->value.number); + g_string_printf(double_actual, "%.6f", ptr->value); + g_assert_cmpstr(double_actual->str, ==, double_expected->str); + g_string_free(double_expected, true); + g_string_free(double_actual, true); + break; + } + case PTYPE_BOOLEAN: { + boolList *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.booleans; + } + g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value); + break; + } + default: + g_assert(0); + } + i++; + } while (cur_head); + + g_assert_cmpint(i, ==, 33); + + ops->cleanup(serialize_data); + dealloc_helper(&pl, visit_primitive_list, &err); + g_assert(!err); + dealloc_helper(&pl_copy, visit_primitive_list, &err); + g_assert(!err); + g_free(args); +} + static void test_struct(gconstpointer opaque) { TestArgs *args = (TestArgs *) opaque; @@ -719,7 +1120,8 @@ static const SerializeOps visitors[] = { .serialize = qmp_serialize, .deserialize = qmp_deserialize, .cleanup = qmp_cleanup, - .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS + .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS | + VCAP_PRIMITIVE_LISTS }, { .type = "String", @@ -773,6 +1175,19 @@ static void add_visitor_type(const SerializeOps *ops) args->test_data = NULL; g_test_add_data_func(testname, args, test_nested_struct_list); } + + if (ops->caps & VCAP_PRIMITIVE_LISTS) { + i = 0; + while (pt_values[i].type != PTYPE_EOL) { + sprintf(testname, "%s/primitive_list/%s", testname_prefix, + pt_values[i].description); + args = g_malloc0(sizeof(*args)); + args->ops = ops; + args->test_data = &pt_values[i]; + g_test_add_data_func(testname, args, test_primitive_lists); + i++; + } + } } int main(int argc, char **argv)