Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Tests for ML Suggest backend.
"use strict";
ChromeUtils.defineESModuleGetters(this, {
MLSuggest: "resource:///modules/urlbar/private/MLSuggest.sys.mjs",
setTimeout: "resource://gre/modules/Timer.sys.mjs",
});
const ML_PREFS = ["browser.ml.enable", "quicksuggest.mlEnabled"];
let gSandbox;
let gInitializeStub;
let gShutdownStub;
add_setup(async function init() {
// Stub `MLSuggest`.
gSandbox = sinon.createSandbox();
gInitializeStub = gSandbox.stub(MLSuggest, "initialize");
gShutdownStub = gSandbox.stub(MLSuggest, "shutdown");
// Enable Suggest but not the ML backend yet.
await QuickSuggestTestUtils.ensureQuickSuggestInit({
prefs: [
["suggest.quicksuggest.nonsponsored", true],
["suggest.quicksuggest.sponsored", true],
],
});
});
function enableMl(enable) {
if (enable) {
for (let p of ML_PREFS) {
UrlbarPrefs.set(p, true);
}
} else {
// This assumes the prefs are false by default, i.e., the ML backend is
// disabled by default.
for (let p of ML_PREFS) {
UrlbarPrefs.clear(p);
}
}
}
// Init shouldn't be delayed by default.
add_task(async function zeroDelay() {
// The init timer is always used, its timeout is just set to zero when init
// shouldn't be delayed. To test that there's no large delay, get the current
// time, enable ML, wait for `initialize()` to be called, and then make sure
// the elapsed time is small. Some CI machines are really slow, so this might
// take longer than you think. Use a generous expected upper bound of 1s
// (1000ms).
let startMs = Cu.now();
enableMl(true);
await TestUtils.waitForCondition(
() => gInitializeStub.callCount > 0,
"Waiting for initialize to be called"
);
let elapsedMs = Cu.now() - startMs;
Assert.less(
elapsedMs,
1000,
"initialize should have been called quickly after enabling the backend"
);
enableMl(false);
gInitializeStub.resetHistory();
gShutdownStub.resetHistory();
});
// Delaying init should work properly.
add_task(async function delay() {
// Delay by 4s. We use a large timeout because some CI machines are slow.
let cleanUpNimbus = await UrlbarTestUtils.initNimbusFeature({
quickSuggestMlInitDelaySeconds: 4,
});
enableMl(true);
Assert.equal(
gInitializeStub.callCount,
0,
"initialize should not have been called immediately after enabling ML"
);
await waitSeconds(2);
Assert.equal(
gInitializeStub.callCount,
0,
"initialize should not have been called after waiting 2s"
);
// Wait a generous 4 more seconds for a total of 6s.
await waitSeconds(4);
Assert.equal(
gInitializeStub.callCount,
1,
"initialize should have been called after waiting a total of 6s"
);
enableMl(false);
Assert.equal(
gShutdownStub.callCount,
1,
"shutdown should have been called after disabling ML"
);
gInitializeStub.resetHistory();
gShutdownStub.resetHistory();
await cleanUpNimbus();
});
// `initialize` should not be called if the backend is disabled before the init
// timer fires.
add_task(async function disabledBeforeTimerFires() {
let cleanUpNimbus = await UrlbarTestUtils.initNimbusFeature({
quickSuggestMlInitDelaySeconds: 3,
});
enableMl(true);
// Wait a little for better realism.
await waitSeconds(1);
enableMl(false);
Assert.equal(
gShutdownStub.callCount,
1,
"shutdown should have been called after disabling ML"
);
// Wait a generous 3 more seconds for a total of 4s.
await waitSeconds(3);
Assert.equal(
gInitializeStub.callCount,
0,
"initialize should not have been called after waiting 2s"
);
gInitializeStub.resetHistory();
gShutdownStub.resetHistory();
await cleanUpNimbus();
});
async function waitSeconds(s) {
info(`Waiting ${s} seconds...`);
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(r => setTimeout(r, s * 1000));
}