Nothing covered the migration of the register file or the oscillator state, so a dropped field or a wrong version gate would have gone unnoticed.
Signed-off-by: Emmanuel Blot <[email protected]> --- tests/qtest/ds1339-test.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/qtest/ds1339-test.c b/tests/qtest/ds1339-test.c index a1b5afb331..ca2378aa34 100644 --- a/tests/qtest/ds1339-test.c +++ b/tests/qtest/ds1339-test.c @@ -7,9 +7,13 @@ */ #include "qemu/osdep.h" + +#include <glib/gstdio.h> + #include "qemu/bcd.h" #include "libqtest.h" #include "libqtest-single.h" +#include "libqos/qgraph.h" #include "libqos/i2c.h" #include "qobject/qdict.h" @@ -475,6 +479,62 @@ static void test_reset_persists(void *obj, void *data, QGuestAllocator *alloc) check_reset((QI2CDevice *)obj, true); } +/* The register file, the Century bit and a stopped clock all migrate. */ +static void test_migration(void *obj, void *data, QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = (QI2CDevice *)obj; + /* 23:59:59 on the last day of 2099, Century set. */ + const uint8_t tod[7] = { 0x59, 0x59, 0x23, 0x03, 0x31, 0x8c, 0x99 }; + g_autofree char *tmpfs = NULL; + g_autofree char *mig_path = NULL; + g_autofree char *uri = NULL; + GString *dest_cmdline; + GError *err = NULL; + QTestState *from, *to; + uint8_t resp[7]; + QDict *rsp; + + tmpfs = g_dir_make_tmp("ds1339-test-XXXXXX", &err); + g_assert_no_error(err); + g_assert(tmpfs); + + mig_path = g_strdup_printf("%s/socket.mig", tmpfs); + uri = g_strdup_printf("unix:%s", mig_path); + + /* Stop the clock first, so both sides have the same time to compare. */ + i2c_set8(i2cdev, DS1339_CONTROL, 0x18 | 0x80); + i2c_write_block(i2cdev, DS1339_SECONDS, tod, sizeof(tod)); + i2c_set8(i2cdev, DS1339_ALARM1, 0xa5); + + dest_cmdline = g_string_new(qos_get_current_command_line()); + g_string_append_printf(dest_cmdline, " -incoming %s", uri); + to = qtest_init(dest_cmdline->str); + + rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri); + g_assert(qdict_haskey(rsp, "return")); + qobject_unref(rsp); + + qmp_eventwait("STOP"); + qtest_qmp_eventwait(to, "RESUME"); + + from = i2cdev->bus->qts; + i2cdev->bus->qts = to; + + i2c_read_block(i2cdev, DS1339_SECONDS, resp, sizeof(resp)); + g_assert_cmpmem(resp, sizeof(resp), tod, sizeof(tod)); + g_assert_cmphex(i2c_get8(i2cdev, DS1339_ALARM1), ==, 0xa5); + g_assert_cmphex(i2c_get8(i2cdev, DS1339_CONTROL), ==, 0x18 | 0x80); + g_assert_cmphex(i2c_get8(i2cdev, DS1339_STATUS) & DS1339_STATUS_OSF, + ==, DS1339_STATUS_OSF); + + i2cdev->bus->qts = from; + + qtest_quit(to); + g_unlink(mig_path); + g_rmdir(tmpfs); + g_string_free(dest_cmdline, true); +} + static void ds1339_register_nodes(void) { QOSGraphEdgeOptions opts = { @@ -509,6 +569,7 @@ static void ds1339_register_nodes(void) qos_add_test("alarm-registers", "ds1339", test_alarm_registers, NULL); qos_add_test("reset-clears", "ds1339", test_reset_clears, NULL); + qos_add_test("migration", "ds1339", test_migration, NULL); opts.extra_device_opts = "address=0x68,persist-on-reset=on"; qos_node_create_driver_named("ds1339-persist", "ds1339", i2c_device_create); -- 2.50.1
