diff options
author | Eric Auger <eric.auger@redhat.com> | 2020-01-13 14:48:23 +0100 |
---|---|---|
committer | Juan Quintela <quintela@redhat.com> | 2020-01-20 09:10:23 +0100 |
commit | 4746dbf8a98d560e20dbd22d0e8405b38478b409 (patch) | |
tree | 3bc9f98a1ccb539c72fa1f6efb81ca998224e077 /tests/test-vmstate.c | |
parent | 0ab994867c365db21e15f9503922c79234d8e40e (diff) | |
download | qemu-4746dbf8a98d560e20dbd22d0e8405b38478b409.zip qemu-4746dbf8a98d560e20dbd22d0e8405b38478b409.tar.gz qemu-4746dbf8a98d560e20dbd22d0e8405b38478b409.tar.bz2 |
migration: Support QLIST migration
Support QLIST migration using the same principle as QTAILQ:
94869d5c52 ("migration: migrate QTAILQ").
The VMSTATE_QLIST_V macro has the same proto as VMSTATE_QTAILQ_V.
The change mainly resides in QLIST RAW macros: QLIST_RAW_INSERT_HEAD
and QLIST_RAW_REVERSE.
Tests also are provided.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
Diffstat (limited to 'tests/test-vmstate.c')
-rw-r--r-- | tests/test-vmstate.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c index 8f184f3..cea363d 100644 --- a/tests/test-vmstate.c +++ b/tests/test-vmstate.c @@ -926,6 +926,28 @@ static const VMStateDescription vmstate_domain = { } }; +/* test QLIST Migration */ + +typedef struct TestQListElement { + uint32_t id; + QLIST_ENTRY(TestQListElement) next; +} TestQListElement; + +typedef struct TestQListContainer { + uint32_t id; + QLIST_HEAD(, TestQListElement) list; +} TestQListContainer; + +static const VMStateDescription vmstate_qlist_element = { + .name = "test/queue list", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(id, TestQListElement), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_iommu = { .name = "iommu", .version_id = 1, @@ -939,6 +961,18 @@ static const VMStateDescription vmstate_iommu = { } }; +static const VMStateDescription vmstate_container = { + .name = "test/container/qlist", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(id, TestQListContainer), + VMSTATE_QLIST_V(list, TestQListContainer, 1, vmstate_qlist_element, + TestQListElement, next), + VMSTATE_END_OF_LIST() + } +}; + uint8_t first_domain_dump[] = { /* id */ 0x00, 0x0, 0x0, 0x6, @@ -1229,6 +1263,140 @@ static void test_gtree_load_iommu(void) qemu_fclose(fload); } +static uint8_t qlist_dump[] = { + 0x00, 0x00, 0x00, 0x01, /* container id */ + 0x1, /* start of a */ + 0x00, 0x00, 0x00, 0x0a, + 0x1, /* start of b */ + 0x00, 0x00, 0x0b, 0x00, + 0x1, /* start of c */ + 0x00, 0x0c, 0x00, 0x00, + 0x1, /* start of d */ + 0x0d, 0x00, 0x00, 0x00, + 0x0, /* end of list */ + QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */ +}; + +static TestQListContainer *alloc_container(void) +{ + TestQListElement *a = g_malloc(sizeof(TestQListElement)); + TestQListElement *b = g_malloc(sizeof(TestQListElement)); + TestQListElement *c = g_malloc(sizeof(TestQListElement)); + TestQListElement *d = g_malloc(sizeof(TestQListElement)); + TestQListContainer *container = g_malloc(sizeof(TestQListContainer)); + + a->id = 0x0a; + b->id = 0x0b00; + c->id = 0xc0000; + d->id = 0xd000000; + container->id = 1; + + QLIST_INIT(&container->list); + QLIST_INSERT_HEAD(&container->list, d, next); + QLIST_INSERT_HEAD(&container->list, c, next); + QLIST_INSERT_HEAD(&container->list, b, next); + QLIST_INSERT_HEAD(&container->list, a, next); + return container; +} + +static void free_container(TestQListContainer *container) +{ + TestQListElement *iter, *tmp; + + QLIST_FOREACH_SAFE(iter, &container->list, next, tmp) { + QLIST_REMOVE(iter, next); + g_free(iter); + } + g_free(container); +} + +static void compare_containers(TestQListContainer *c1, TestQListContainer *c2) +{ + TestQListElement *first_item_c1, *first_item_c2; + + while (!QLIST_EMPTY(&c1->list)) { + first_item_c1 = QLIST_FIRST(&c1->list); + first_item_c2 = QLIST_FIRST(&c2->list); + assert(first_item_c2); + assert(first_item_c1->id == first_item_c2->id); + QLIST_REMOVE(first_item_c1, next); + QLIST_REMOVE(first_item_c2, next); + g_free(first_item_c1); + g_free(first_item_c2); + } + assert(QLIST_EMPTY(&c2->list)); +} + +/* + * Check the prev & next fields are correct by doing list + * manipulations on the container. We will do that for both + * the source and the destination containers + */ +static void manipulate_container(TestQListContainer *c) +{ + TestQListElement *prev = NULL, *iter = QLIST_FIRST(&c->list); + TestQListElement *elem; + + elem = g_malloc(sizeof(TestQListElement)); + elem->id = 0x12; + QLIST_INSERT_AFTER(iter, elem, next); + + elem = g_malloc(sizeof(TestQListElement)); + elem->id = 0x13; + QLIST_INSERT_HEAD(&c->list, elem, next); + + while (iter) { + prev = iter; + iter = QLIST_NEXT(iter, next); + } + + elem = g_malloc(sizeof(TestQListElement)); + elem->id = 0x14; + QLIST_INSERT_BEFORE(prev, elem, next); + + elem = g_malloc(sizeof(TestQListElement)); + elem->id = 0x15; + QLIST_INSERT_AFTER(prev, elem, next); + + QLIST_REMOVE(prev, next); + g_free(prev); +} + +static void test_save_qlist(void) +{ + TestQListContainer *container = alloc_container(); + + save_vmstate(&vmstate_container, container); + compare_vmstate(qlist_dump, sizeof(qlist_dump)); + free_container(container); +} + +static void test_load_qlist(void) +{ + QEMUFile *fsave, *fload; + TestQListContainer *orig_container = alloc_container(); + TestQListContainer *dest_container = g_malloc0(sizeof(TestQListContainer)); + char eof; + + QLIST_INIT(&dest_container->list); + + fsave = open_test_file(true); + qemu_put_buffer(fsave, qlist_dump, sizeof(qlist_dump)); + g_assert(!qemu_file_get_error(fsave)); + qemu_fclose(fsave); + + fload = open_test_file(false); + vmstate_load_state(fload, &vmstate_container, dest_container, 1); + eof = qemu_get_byte(fload); + g_assert(!qemu_file_get_error(fload)); + g_assert_cmpint(eof, ==, QEMU_VM_EOF); + manipulate_container(orig_container); + manipulate_container(dest_container); + compare_containers(orig_container, dest_container); + free_container(orig_container); + free_container(dest_container); +} + typedef struct TmpTestStruct { TestStruct *parent; int64_t diff; @@ -1353,6 +1521,8 @@ int main(int argc, char **argv) g_test_add_func("/vmstate/gtree/load/loaddomain", test_gtree_load_domain); g_test_add_func("/vmstate/gtree/save/saveiommu", test_gtree_save_iommu); g_test_add_func("/vmstate/gtree/load/loadiommu", test_gtree_load_iommu); + g_test_add_func("/vmstate/qlist/save/saveqlist", test_save_qlist); + g_test_add_func("/vmstate/qlist/load/loadqlist", test_load_qlist); g_test_add_func("/vmstate/tmp_struct", test_tmp_struct); g_test_run(); |