tests/qtest: migration-test: Add tests for file-based migration
Add basic tests for file-based migration. Signed-off-by: Fabiano Rosas <farosas@suse.de>
This commit is contained in:
		@@ -66,6 +66,10 @@ static bool got_dst_resume;
 | 
			
		||||
 */
 | 
			
		||||
#define DIRTYLIMIT_TOLERANCE_RANGE  25  /* MB/s */
 | 
			
		||||
 | 
			
		||||
#define QEMU_VM_FILE_MAGIC 0x5145564d
 | 
			
		||||
#define FILE_TEST_FILENAME "migfile"
 | 
			
		||||
#define FILE_TEST_OFFSET 0x1000
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__)
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <sys/vfs.h>
 | 
			
		||||
@@ -858,6 +862,7 @@ static void test_migrate_end(QTestState *from, QTestState *to, bool test_dest)
 | 
			
		||||
    cleanup("migsocket");
 | 
			
		||||
    cleanup("src_serial");
 | 
			
		||||
    cleanup("dest_serial");
 | 
			
		||||
    cleanup(FILE_TEST_FILENAME);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_GNUTLS
 | 
			
		||||
@@ -1586,6 +1591,70 @@ finish:
 | 
			
		||||
    test_migrate_end(from, to, args->result == MIG_TEST_SUCCEED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_file_common(MigrateCommon *args, bool stop_src)
 | 
			
		||||
{
 | 
			
		||||
    QTestState *from, *to;
 | 
			
		||||
    void *data_hook = NULL;
 | 
			
		||||
    g_autofree char *connect_uri = g_strdup(args->connect_uri);
 | 
			
		||||
 | 
			
		||||
    if (test_migrate_start(&from, &to, args->listen_uri, &args->start)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * File migration is never live. We can stop the source before
 | 
			
		||||
     * migrating, but the destination will not be running
 | 
			
		||||
     * concurrently.
 | 
			
		||||
     */
 | 
			
		||||
    g_assert_false(args->live);
 | 
			
		||||
 | 
			
		||||
    if (args->start_hook) {
 | 
			
		||||
        data_hook = args->start_hook(from, to);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    migrate_ensure_converge(from);
 | 
			
		||||
    wait_for_serial("src_serial");
 | 
			
		||||
 | 
			
		||||
    if (stop_src) {
 | 
			
		||||
        qtest_qmp_assert_success(from, "{ 'execute' : 'stop'}");
 | 
			
		||||
        if (!got_src_stop) {
 | 
			
		||||
            qtest_qmp_eventwait(from, "STOP");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (args->result == MIG_TEST_QMP_ERROR) {
 | 
			
		||||
        migrate_qmp_fail(from, connect_uri, "{}");
 | 
			
		||||
        goto finish;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    migrate_qmp(from, connect_uri, "{}");
 | 
			
		||||
    wait_for_migration_complete(from);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * We need to wait for the source to finish before starting the
 | 
			
		||||
     * destination.
 | 
			
		||||
     */
 | 
			
		||||
    migrate_incoming_qmp(to, connect_uri, "{}");
 | 
			
		||||
    wait_for_migration_complete(to);
 | 
			
		||||
 | 
			
		||||
    if (stop_src) {
 | 
			
		||||
        qtest_qmp_assert_success(to, "{ 'execute' : 'cont'}");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!got_dst_resume) {
 | 
			
		||||
        qtest_qmp_eventwait(to, "RESUME");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wait_for_serial("dest_serial");
 | 
			
		||||
 | 
			
		||||
finish:
 | 
			
		||||
    if (args->finish_hook) {
 | 
			
		||||
        args->finish_hook(from, to, data_hook);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    test_migrate_end(from, to, args->result == MIG_TEST_SUCCEED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_precopy_unix_plain(void)
 | 
			
		||||
{
 | 
			
		||||
    g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 | 
			
		||||
@@ -1781,6 +1850,75 @@ static void test_precopy_unix_compress_nowait(void)
 | 
			
		||||
    test_precopy_common(&args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_precopy_file(void)
 | 
			
		||||
{
 | 
			
		||||
    g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
 | 
			
		||||
                                           FILE_TEST_FILENAME);
 | 
			
		||||
    MigrateCommon args = {
 | 
			
		||||
        .connect_uri = uri,
 | 
			
		||||
        .listen_uri = "defer",
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    test_file_common(&args, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void file_offset_finish_hook(QTestState *from, QTestState *to, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
#if defined(__linux__)
 | 
			
		||||
    g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
 | 
			
		||||
    size_t size = FILE_TEST_OFFSET + sizeof(QEMU_VM_FILE_MAGIC);
 | 
			
		||||
    uintptr_t *addr, *p;
 | 
			
		||||
    int fd;
 | 
			
		||||
 | 
			
		||||
    fd = open(path, O_RDONLY);
 | 
			
		||||
    g_assert(fd != -1);
 | 
			
		||||
    addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
 | 
			
		||||
    g_assert(addr != MAP_FAILED);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Ensure the skipped offset contains zeros and the migration
 | 
			
		||||
     * stream starts at the right place.
 | 
			
		||||
     */
 | 
			
		||||
    p = addr;
 | 
			
		||||
    while (p < addr + FILE_TEST_OFFSET / sizeof(uintptr_t)) {
 | 
			
		||||
        g_assert(*p == 0);
 | 
			
		||||
        p++;
 | 
			
		||||
    }
 | 
			
		||||
    g_assert_cmpint(cpu_to_be32(*p), ==, QEMU_VM_FILE_MAGIC);
 | 
			
		||||
 | 
			
		||||
    munmap(addr, size);
 | 
			
		||||
    close(fd);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_precopy_file_offset(void)
 | 
			
		||||
{
 | 
			
		||||
    g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=%d", tmpfs,
 | 
			
		||||
                                           FILE_TEST_FILENAME,
 | 
			
		||||
                                           FILE_TEST_OFFSET);
 | 
			
		||||
    MigrateCommon args = {
 | 
			
		||||
        .connect_uri = uri,
 | 
			
		||||
        .listen_uri = "defer",
 | 
			
		||||
        .finish_hook = file_offset_finish_hook,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    test_file_common(&args, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_precopy_file_offset_bad(void)
 | 
			
		||||
{
 | 
			
		||||
    /* using a value not supported by qemu_strtosz() */
 | 
			
		||||
    g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=0x20M",
 | 
			
		||||
                                           tmpfs, FILE_TEST_FILENAME);
 | 
			
		||||
    MigrateCommon args = {
 | 
			
		||||
        .connect_uri = uri,
 | 
			
		||||
        .listen_uri = "defer",
 | 
			
		||||
        .result = MIG_TEST_QMP_ERROR,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    test_file_common(&args, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_precopy_tcp_plain(void)
 | 
			
		||||
{
 | 
			
		||||
    MigrateCommon args = {
 | 
			
		||||
@@ -2833,6 +2971,14 @@ int main(int argc, char **argv)
 | 
			
		||||
        qtest_add_func("/migration/precopy/unix/compress/nowait",
 | 
			
		||||
                       test_precopy_unix_compress_nowait);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qtest_add_func("/migration/precopy/file",
 | 
			
		||||
                   test_precopy_file);
 | 
			
		||||
    qtest_add_func("/migration/precopy/file/offset",
 | 
			
		||||
                   test_precopy_file_offset);
 | 
			
		||||
    qtest_add_func("/migration/precopy/file/offset/bad",
 | 
			
		||||
                   test_precopy_file_offset_bad);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_GNUTLS
 | 
			
		||||
    qtest_add_func("/migration/precopy/unix/tls/psk",
 | 
			
		||||
                   test_precopy_unix_tls_psk);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user