aboutsummaryrefslogtreecommitdiff
path: root/tests/test-vmstate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test-vmstate.c')
-rw-r--r--tests/test-vmstate.c170
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();