Peter Xu <[email protected]> writes:
> On Mon, Dec 15, 2025 at 07:00:16PM -0300, Fabiano Rosas wrote:
>> The tests are being refactored to pass migration options to QEMU using
>> the new API of passing a JSON object as argument the migration
>> commands instead of using several calls to the
>> migrate_set_capabilities|parameters commands.
>>
>> Since multiple tests share common infrastructure (framework.c,
>> migration-utils.c, migration-qmp.c), it's cumbersome to convert tests
>> in small chunks, which would require changes to every common function
>> to accept both the new and old ways.
>>
>> After some tinkering, an easier way to do this transition is to allow
>> the tests to set a key in the config dict itself telling whether the
>> config is supported. With this, the common functions can be fully
>> altered to support the config object, as long as they check this
>> temporary key and do the right thing.
>>
>> QEMU doesn't know about this hack, so some code is needed to hide it
>> when issuing QMP commands with the config object.
>>
>> This will all be removed once tests are fully converted.
>>
>> Signed-off-by: Fabiano Rosas <[email protected]>
>> ---
>> tests/qtest/migration/migration-qmp.h | 1 -
>> tests/qtest/migration/migration-util.c | 1 +
>> tests/qtest/migration/migration-util.h | 34 ++++++++++++++++++++++++++
>> 3 files changed, 35 insertions(+), 1 deletion(-)
>>
>> diff --git a/tests/qtest/migration/migration-qmp.h
>> b/tests/qtest/migration/migration-qmp.h
>> index 940ffd5950..9a36a677ba 100644
>> --- a/tests/qtest/migration/migration-qmp.h
>> +++ b/tests/qtest/migration/migration-qmp.h
>> @@ -47,5 +47,4 @@ void migrate_recover(QTestState *who, const char *uri);
>> void migrate_cancel(QTestState *who);
>> void migrate_postcopy_start(QTestState *from, QTestState *to,
>> QTestMigrationState *src_state);
>> -
>> #endif /* MIGRATION_QMP_H */
>> diff --git a/tests/qtest/migration/migration-util.c
>> b/tests/qtest/migration/migration-util.c
>> index 416dd10ef8..e702f00896 100644
>> --- a/tests/qtest/migration/migration-util.c
>> +++ b/tests/qtest/migration/migration-util.c
>> @@ -255,6 +255,7 @@ static void migration_test_wrapper(const void *data)
>>
>> test->data = g_new0(MigrateCommon, 1);
>> test->data->start.config = qdict_new();
>> + qdict_put_bool(test->data->start.config, "use-config", false);
>>
>> g_test_message("Running /%s%s", qtest_get_arch(), test->name);
>> test->func(test->name, test->data);
>> diff --git a/tests/qtest/migration/migration-util.h
>> b/tests/qtest/migration/migration-util.h
>> index e73d69bab0..3c3b5a8777 100644
>> --- a/tests/qtest/migration/migration-util.h
>> +++ b/tests/qtest/migration/migration-util.h
>> @@ -60,4 +60,38 @@ void migration_test_add_suffix(const char *path, const
>> char *suffix,
>> char *migrate_get_connect_uri(QTestState *who);
>> void migrate_set_ports(QTestState *to, QList *channel_list);
>>
>> +/*
>> + * Scaffolding to allow the framework _common functions and _qmp
>> + * functions to use the config object while some tests are still using
>> + * migrate_set_*. Tests that have been converted will set use-config =
>> + * true on the config dict.
>> + */
>> +static bool has_key;
>> +static bool use_config;
>
> Looks like this is temp measure, so no strong opinions.. said that, it
> looks tricky to have the two globals shared between all the tests, and
> having magic keys in the qdict.
>
It is tricky, but it works. The other options all require "passing
something" in, which ends up touching good code and causing a mess with
rebases and the overall clarity of the patches. But let me read about
your suggestions below...
> Can we pass in MigrateStart* for config_load() and config_put()? Then at
> least we can change globals into per-test flags of MigrateStart.
>
> Btw, AFAIU the two helpers should always used in a pair but load() and
> put() do not look like a pair..
>
My mind went to vcpu_load/vcpu_put from kvm code. =D
> If we can have args->use_config as a bool, having tests opt-in config
> setups by setting it, then I wonder if we can do that like:
>
The migrate_qmp commands don't take args. So I'd have to alter their
signature just for this temporary state. That's why I put the flag in
the dict itself.
> if (args->use_config) {
> // do whatever with args->config...
> } else {
> // covered by other migrate-set-parameters QMP commands..
> }
>
> Do we really need config_put()? I'll keep reading, but please evaluate..
>
Because of the migrate_incoming_qmp and -incoming calls, we need to take
the key out of the dict to hide it. Then put it back so the rest of the
code, e.g. migrate_qmp can use it.
>> +static inline QDict *config_load(QDict *config)
>> +{
>> + if (!config) {
>> + return NULL;
>> + }
>> +
>> + has_key = qdict_haskey(config, "use-config");
>> + if (has_key) {
>> + use_config = qdict_get_try_bool(config, "use-config", false);
>> + qdict_del(config, "use-config");
>> + }
>> +
>> + if (use_config) {
>> + return config;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +static inline void config_put(QDict *config)
>> +{
>> + if (config && has_key) {
>> + qdict_put_bool(config, "use-config", use_config);
>> + }
>> +}
>> +
>> #endif /* MIGRATION_UTIL_H */
>> --
>> 2.51.0
>>