Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
/**
* This test case verifies that every client receives an engine-termination
* notification and that explicitly closed ports are removed independently.
*/
add_task(async function test_multiple_ports_with_live_process() {
const { cleanup, resolveDownloads } = await loadTestPage({
page: SPANISH_PAGE_URL,
languagePairs: LANGUAGE_PAIRS,
prefs: [["browser.ml.enable", true]],
});
let processKeepAlive = null;
const portStates = [];
let controlState = null;
try {
processKeepAlive =
await TranslationsEngineTestUtils.keepInferenceProcessAlive();
for (let index = 0; index < 3; index++) {
const state = {
engineStatus: "uninitialized",
port: await TranslationsParent.requestTranslationsPort({
sourceLanguage: "es",
targetLanguage: "en",
}),
receivedEngineTerminated: false,
};
state.port.onmessage = ({ data }) => {
switch (data.type) {
case "TranslationsPort:GetEngineStatusResponse":
state.engineStatus = data.status;
break;
case "TranslationsPort:EngineTerminated":
state.receivedEngineTerminated = true;
break;
}
};
state.port.postMessage({
type: "TranslationsPort:GetEngineStatusRequest",
});
portStates.push(state);
}
await resolveDownloads(1);
await waitForCondition(
() => portStates.every(state => state.engineStatus === "ready"),
"Waiting for every client port to become ready."
);
is(
(await processKeepAlive.engineParent.getEngineStateForTests())
.activePortCount,
3,
"The translations engine independently registers every client port."
);
const closedState = portStates.shift();
closedState.port.postMessage({ type: "TranslationsPort:Close" });
closedState.port.close();
await waitForCondition(
async () =>
(await processKeepAlive.engineParent.getEngineStateForTests())
.activePortCount === 2,
"Waiting for the explicitly closed port to be removed."
);
controlState = {
engineStatus: "uninitialized",
port: await TranslationsParent.requestTranslationsPort({
sourceLanguage: "fr",
targetLanguage: "en",
}),
receivedEngineTerminated: false,
};
controlState.port.onmessage = ({ data }) => {
switch (data.type) {
case "TranslationsPort:GetEngineStatusResponse":
controlState.engineStatus = data.status;
break;
case "TranslationsPort:EngineTerminated":
controlState.receivedEngineTerminated = true;
break;
}
};
controlState.port.postMessage({
type: "TranslationsPort:GetEngineStatusRequest",
});
await resolveDownloads(1);
await waitForCondition(
() => controlState.engineStatus === "ready",
"Waiting for the control engine to become ready."
);
await TranslationsEngineTestUtils.waitForIdleTimeoutWithProcessAlive(
processKeepAlive.engineParent,
{ sourceLanguage: "es", targetLanguage: "en" }
);
await waitForCondition(
() => portStates.every(state => state.receivedEngineTerminated),
"Waiting for every remaining client to receive EngineTerminated."
);
ok(
!controlState.receivedEngineTerminated,
"Terminating one engine does not notify a client for another language pair."
);
const { activeEngineCount, activePortCount } =
await processKeepAlive.engineParent.getEngineStateForTests();
is(activeEngineCount, 1, "The control engine remains active.");
is(
activePortCount,
1,
"Engine termination only removes ports for its language pair."
);
} finally {
for (const { port } of portStates) {
port.close();
}
controlState?.port.close();
try {
await processKeepAlive?.release();
} finally {
await cleanup();
}
}
});