Signed-off-by: Juan Quintela <quint...@redhat.com> --- tests/test-vmstate.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c index 3d8ba20..f4ff93d 100644 --- a/tests/test-vmstate.c +++ b/tests/test-vmstate.c @@ -1649,6 +1649,123 @@ static void test_struct_test(void) STRUCT_NOT_EQUAL((&obj.b[i]), (&obj_struct.b[i])); } } + +typedef struct TestStruct2 { + uint8_t size; + SubStruct a[3]; +} TestStruct2; + +/* + * size: needs to be the 1st field + * a: needs to be the last field + * We use that fact to load with different sizes + */ + +static const VMStateDescription vmstate_struct_varray = { + .name = "struct/varray", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_EQUAL(size, TestStruct2), + VMSTATE_STRUCT_VARRAY_UINT8(a, TestStruct2, size, + vmstate_sub_struct, SubStruct), + VMSTATE_END_OF_LIST() + } +}; + +/* This is the binary representation on the wire of that struct */ +/* We need to change the first byte for load to work */ +uint8_t wire_struct_varray[] = { + /* size */ 0x03, + /* a[0] */ + /* i32 */ 0x00, 0x00, 0x00, 0x15, + /* i64 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + /* buffer */ 0x62, 0x79, 0x65, 0x30, 0x20, 0x20, 0x77, 0x6f, + 0x72, 0x6c, 0x64, 0x21, 0x00, + /* a[1] */ + /* i32 */ 0x00, 0x00, 0x00, 0x16, + /* i64 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + /* buffer */ 0x62, 0x79, 0x65, 0x31, 0x20, 0x20, 0x77, 0x6f, + 0x72, 0x6c, 0x64, 0x21, 0x00, + /* a[2] */ + /* i32 */ 0x00, 0x00, 0x00, 0x17, + /* i64 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, + /* buffer */ 0x62, 0x79, 0x65, 0x32, 0x20, 0x20, 0x77, 0x6f, + 0x72, 0x6c, 0x64, 0x21, 0x00, + QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */ +}; + +static void obj_struct2_copy(void *arg1, void *arg2) +{ + TestStruct2 *target = arg1; + TestStruct2 *source = arg2; + int i; + + target->size = source->size; + for (i = 0; i < 3; i++) { + target->a[i].i32 = source->a[i].i32; + target->a[i].i64 = source->a[i].i64; + memcpy(target->a[i].buffer, source->a[i].buffer, 13); + } +} + +static TestStruct2 *create_struct2(void) +{ + TestStruct2 *obj = g_malloc0(sizeof(*obj)); + obj->size = 3; + + return obj; +} + +static TestStruct2 *create_struct2_init(void) +{ + TestStruct2 *obj = create_struct2(); + int i; + + for (i = 0; i < 3; i++) { + obj->a[i].i32 = i + 21; + obj->a[i].i64 = i + 31; + snprintf((char *)obj->a[i].buffer, 13, "bye%d world!", i); + } + + return obj; +} + +static void test_struct_varray(void) +{ + TestStruct2 *obj, *obj_clone, *obj_struct2; + int i, j; + + obj_struct2 = create_struct2_init(); + obj = create_struct2(); + obj_clone = create_struct2(); + + save_vmstate(&vmstate_struct_varray, obj_struct2); + + compare_vmstate(wire_struct_varray, sizeof(wire_struct_varray)); + + for (j = 3; j >= 0; j--) { + size_t sub_struct_size; + + sub_struct_size = sizeof(uint32_t) + sizeof(uint64_t) + 13; + memset(obj->a, 0, sizeof(obj->a)); + obj->size = j; + obj_struct2->size = j; + wire_struct_varray[0] = j; + SUCCESS(load_vmstate(&vmstate_struct_varray, obj, obj_clone, + obj_struct2_copy, 1, wire_struct_varray, + sizeof(wire_struct_varray) + - sub_struct_size * (3 - j))); + + for (i = 0; i < j; i++) { + STRUCT_EQUAL((&obj->a[i]), (&obj_struct2->a[i])); + } + for (i = j; i < 3; i++) { + STRUCT_NOT_EQUAL((&obj->a[i]), (&obj_struct2->a[i])); + } + } +} #undef STRUCT_EQUAL #undef STRUCT_NOT_EQUAL @@ -1896,6 +2013,7 @@ int main(int argc, char **argv) g_test_add_func("/vmstate/varray/test", test_varray_test); g_test_add_func("/vmstate/struct/simple", test_struct_simple); g_test_add_func("/vmstate/struct/test", test_struct_test); + g_test_add_func("/vmstate/struct/varray", test_struct_varray); g_test_run(); close(temp_fd); -- 1.9.0