qemu_fclose(fsave);
}
-static void compare_vmstate(uint8_t *wire, size_t size)
+static void compare_vmstate(const uint8_t *wire, size_t size)
{
QEMUFile *f = open_test_file(false);
uint8_t result[size];
}
static int load_vmstate_one(const VMStateDescription *desc, void *obj,
- int version, uint8_t *wire, size_t size)
+ int version, const uint8_t *wire, size_t size)
{
QEMUFile *f;
int ret;
static int load_vmstate(const VMStateDescription *desc,
void *obj, void *obj_clone,
void (*obj_copy)(void *, void*),
- int version, uint8_t *wire, size_t size)
+ int version, const uint8_t *wire, size_t size)
{
/* We test with zero size */
obj_copy(obj_clone, obj);
FIELD_EQUAL(i64_1);
FIELD_EQUAL(i64_2);
}
-#undef FIELD_EQUAL
typedef struct TestStruct {
uint32_t a, b, c, e;
qemu_fclose(loading);
}
-
typedef struct {
int32_t i;
} TestStructTriv;
qemu_fclose(fload);
}
+typedef struct TmpTestStruct {
+ TestStruct *parent;
+ int64_t diff;
+} TmpTestStruct;
+
+static void tmp_child_pre_save(void *opaque)
+{
+ struct TmpTestStruct *tts = opaque;
+
+ tts->diff = tts->parent->b - tts->parent->a;
+}
+
+static int tmp_child_post_load(void *opaque, int version_id)
+{
+ struct TmpTestStruct *tts = opaque;
+
+ tts->parent->b = tts->parent->a + tts->diff;
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_tmp_back_to_parent = {
+ .name = "test/tmp_child_parent",
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(f, TestStruct),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_tmp_child = {
+ .name = "test/tmp_child",
+ .pre_save = tmp_child_pre_save,
+ .post_load = tmp_child_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT64(diff, TmpTestStruct),
+ VMSTATE_STRUCT_POINTER(parent, TmpTestStruct,
+ vmstate_tmp_back_to_parent, TestStruct),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_with_tmp = {
+ .name = "test/with_tmp",
+ .version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(a, TestStruct),
+ VMSTATE_UINT64(d, TestStruct),
+ VMSTATE_WITH_TMP(TestStruct, TmpTestStruct, vmstate_tmp_child),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void obj_tmp_copy(void *target, void *source)
+{
+ memcpy(target, source, sizeof(TestStruct));
+}
+
+static void test_tmp_struct(void)
+{
+ TestStruct obj, obj_clone;
+
+ uint8_t const wire_with_tmp[] = {
+ /* u32 a */ 0x00, 0x00, 0x00, 0x02,
+ /* u64 d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ /* diff */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ /* u64 f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
+ };
+
+ memset(&obj, 0, sizeof(obj));
+ obj.a = 2;
+ obj.b = 4;
+ obj.d = 1;
+ obj.f = 8;
+ save_vmstate(&vmstate_with_tmp, &obj);
+
+ compare_vmstate(wire_with_tmp, sizeof(wire_with_tmp));
+
+ memset(&obj, 0, sizeof(obj));
+ SUCCESS(load_vmstate(&vmstate_with_tmp, &obj, &obj_clone,
+ obj_tmp_copy, 1, wire_with_tmp,
+ sizeof(wire_with_tmp)));
+ g_assert_cmpint(obj.a, ==, 2); /* From top level vmsd */
+ g_assert_cmpint(obj.b, ==, 4); /* from the post_load */
+ g_assert_cmpint(obj.d, ==, 1); /* From top level vmsd */
+ g_assert_cmpint(obj.f, ==, 8); /* From the child->parent */
+}
+
int main(int argc, char **argv)
{
temp_fd = mkstemp(temp_file);
test_arr_ptr_str_no0_load);
g_test_add_func("/vmstate/qtailq/save/saveq", test_save_q);
g_test_add_func("/vmstate/qtailq/load/loadq", test_load_q);
-
+ g_test_add_func("/vmstate/tmp_struct", test_tmp_struct);
g_test_run();
close(temp_fd);