[FIX] bus: fix non-deterministic channel managment test
This commit fixes a non-deterministic error in the bus module. Testing the bus service is difficult because it relies heavily on async code. Until now, `nextTick` was used but there is no guarantee that this is enough. This commit introduces the `waitForChannels` method that awaits the channel subscriptions to be done before resolving. fixes runbot-21942,54467 closes odoo/odoo#147616 X-original-commit: 429a0668a4bed52eff1c7b8cd0c5c66261678699 Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
This commit is contained in:
@@ -60,38 +60,43 @@ export function waitUntilSubscribe(...requiredChannels) {
|
||||
*
|
||||
* @returns {import("@web/core/utils/concurrency").Deferred} */
|
||||
export function waitForChannels(channels, { operation = "add" } = {}) {
|
||||
const successDeferred = makeDeferred();
|
||||
const failTimeout = setTimeout(() => {
|
||||
const failMessage = `Waited ${TIMEOUT}ms for ${channels.join(", ")} to be ${
|
||||
operation === "add" ? "added" : "deleted"
|
||||
}`;
|
||||
const missingChannels = new Set(channels);
|
||||
const deferred = makeDeferred();
|
||||
function check({ crashOnFail = false } = {}) {
|
||||
const success = missingChannels.size === 0;
|
||||
if (!success && !crashOnFail) {
|
||||
return;
|
||||
}
|
||||
unpatch();
|
||||
QUnit.assert.ok(false, failMessage);
|
||||
successDeferred.resolve();
|
||||
}, TIMEOUT);
|
||||
const channelsSeen = new Set();
|
||||
clearTimeout(failTimeout);
|
||||
const msg = success
|
||||
? `Channel(s) [${channels.join(", ")}] ${operation === "add" ? "added" : "deleted"}.`
|
||||
: `Waited ${TIMEOUT}ms for [${channels.join(", ")}] to be ${
|
||||
operation === "add" ? "added" : "deleted"
|
||||
}`;
|
||||
QUnit.assert.ok(success, msg);
|
||||
if (success) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
deferred.reject(new Error(msg));
|
||||
}
|
||||
}
|
||||
const failTimeout = setTimeout(() => check({ crashOnFail: true }), TIMEOUT);
|
||||
registerCleanup(() => {
|
||||
if (missingChannels.length > 0) {
|
||||
check({ crashOnFail: true });
|
||||
}
|
||||
});
|
||||
const worker = patchWebsocketWorkerWithCleanup();
|
||||
const workerMethod = operation === "add" ? "_addChannel" : "_deleteChannel";
|
||||
const unpatch = patch(worker, {
|
||||
async [operation === "add" ? "_addChannel" : "_deleteChannel"](client, channel) {
|
||||
await super[operation === "add" ? "_addChannel" : "_deleteChannel"](client, channel);
|
||||
if (channels.includes(channel)) {
|
||||
channelsSeen.add(channel);
|
||||
}
|
||||
if (channelsSeen.size === channels.length) {
|
||||
unpatch();
|
||||
QUnit.assert.ok(
|
||||
true,
|
||||
`Channel(s) ${channels.join(", ")} ${
|
||||
operation === "add" ? "added" : "deleted"
|
||||
}.`
|
||||
);
|
||||
successDeferred.resolve();
|
||||
clearTimeout(failTimeout);
|
||||
}
|
||||
async [workerMethod](client, channel) {
|
||||
await super[workerMethod](client, channel);
|
||||
missingChannels.delete(channel);
|
||||
check();
|
||||
},
|
||||
});
|
||||
registerCleanup(unpatch);
|
||||
return successDeferred;
|
||||
return deferred;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user