Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
// Tests alternative pages frecency.
// Note: the order of the tests here matters, since we are emulating subsquent
// starts of the recalculator component with different initial conditions.
const FEATURE_PREF = "places.frecency.pages.alternative.featureGate";
async function restartRecalculator() {
let subject = {};
PlacesFrecencyRecalculator.observe(
subject,
"test-alternative-frecency-init",
""
);
await subject.promise;
}
async function getAllPages() {
let db = await PlacesUtils.promiseDBConnection();
let rows = await db.execute(`SELECT * FROM moz_places`);
Assert.greater(rows.length, 0);
return rows.map(r => ({
url: r.getResultByName("url"),
frecency: r.getResultByName("frecency"),
recalc_frecency: r.getResultByName("recalc_frecency"),
alt_frecency: r.getResultByName("alt_frecency"),
recalc_alt_frecency: r.getResultByName("recalc_alt_frecency"),
}));
}
add_setup(async function () {
await PlacesTestUtils.addVisits([
]);
registerCleanupFunction(PlacesUtils.history.clear);
});
add_task(
{
pref_set: [[FEATURE_PREF, false]],
},
async function test_normal_init() {
// The test starts with the pref enabled, otherwise we'd not have the SQL
// function defined. So here we disable it, then enable again later.
await restartRecalculator();
// Avoid hitting the cache, we want to check the actual database value.
PlacesUtils.metadata.cache.clear();
Assert.ok(
ObjectUtils.isEmpty(
await PlacesUtils.metadata.get(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
Object.create(null)
)
),
"Check there's no variables stored"
);
}
);
add_task(
{
pref_set: [[FEATURE_PREF, true]],
},
async function test_enable_init() {
// Set alt_frecency to NULL and recalc_alt_frecency = 0 for the entries in
// moz_places to verify they are recalculated.
await PlacesTestUtils.updateDatabaseValues("moz_places", {
alt_frecency: null,
recalc_alt_frecency: 0,
});
await restartRecalculator();
// Ensure moz_meta doesn't report anything.
Assert.ok(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.enabled,
"Check the pref is enabled"
);
// Avoid hitting the cache, we want to check the actual database value.
PlacesUtils.metadata.cache.clear();
Assert.equal(
(
await PlacesUtils.metadata.get(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
Object.create(null)
)
).version,
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.variables
.version,
"Check the algorithm version has been stored"
);
// Check all alternative frecencies have been calculated, since we just have
// a few.
let pages = await getAllPages();
Assert.ok(
pages.every(p => p.recalc_alt_frecency == 0),
"All the entries have been recalculated"
);
Assert.ok(
pages.every(p => p.alt_frecency > 0),
"All the entries have been recalculated"
);
Assert.ok(
PlacesFrecencyRecalculator.isRecalculationPending,
"Recalculation should be pending"
);
}
);
add_task(
{
pref_set: [[FEATURE_PREF, true]],
},
async function test_different_version() {
let pages = await getAllPages();
Assert.ok(
pages.every(p => p.recalc_alt_frecency == 0),
"All the entries should not need recalculation"
);
// Set alt_frecency to NULL to verify all the entries are recalculated.
await PlacesTestUtils.updateDatabaseValues("moz_places", {
alt_frecency: null,
});
// It doesn't matter that the version is, it just have to be different.
let variables = await PlacesUtils.metadata.get(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
Object.create(null)
);
variables.version = 999;
await PlacesUtils.metadata.set(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
variables
);
await restartRecalculator();
// Check alternative frecency has been marked for recalculation.
// Note just after init we reculate a chunk, and this test code is expected
// to run before that... though we can't be sure, so if this starts failing
// intermittently we'll have to add more synchronization test code.
pages = await getAllPages();
// Ensure moz_meta has been updated.
Assert.ok(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.enabled,
"Check the pref is enabled"
);
// Avoid hitting the cache, we want to check the actual database value.
PlacesUtils.metadata.cache.clear();
Assert.deepEqual(
(
await PlacesUtils.metadata.get(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
Object.create(null)
)
).version,
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.variables
.version,
"Check the algorithm version has been stored"
);
// Check all alternative frecencies have been calculated, since we just have
// a few.
pages = await getAllPages();
Assert.ok(
pages.every(p => p.recalc_alt_frecency == 0),
"All the entries have been recalculated"
);
Assert.ok(
pages.every(p => p.alt_frecency > 0),
"All the entries have been recalculated"
);
Assert.ok(
PlacesFrecencyRecalculator.isRecalculationPending,
"Recalculation should be pending"
);
}
);
add_task(
{
pref_set: [[FEATURE_PREF, true]],
},
async function test_different_variables() {
let pages = await getAllPages();
Assert.ok(
pages.every(p => p.recalc_alt_frecency == 0),
"All the entries should not need recalculation"
);
// Set alt_frecency to NULL to verify all the entries are recalculated.
await PlacesTestUtils.updateDatabaseValues("moz_places", {
alt_frecency: null,
});
// Change variables.
let variables = await PlacesUtils.metadata.get(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
Object.create(null)
);
Assert.greater(Object.keys(variables).length, 1);
Assert.ok("version" in variables, "At least the version is always present");
await PlacesUtils.metadata.set(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
{
version:
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.variables
.version,
someVar: 1,
}
);
await restartRecalculator();
// Ensure moz_meta has been updated.
Assert.ok(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.enabled,
"Check the pref is enabled"
);
// Avoid hitting the cache, we want to check the actual database value.
PlacesUtils.metadata.cache.clear();
Assert.deepEqual(
await PlacesUtils.metadata.get(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
Object.create(null)
),
variables,
"Check the algorithm variables have been stored"
);
// Check all alternative frecencies have been calculated, since we just have
// a few.
pages = await getAllPages();
Assert.ok(
pages.every(p => p.recalc_alt_frecency == 0),
"All the entries have been recalculated"
);
Assert.ok(
pages.every(p => p.alt_frecency > 0),
"All the entries have been recalculated"
);
Assert.ok(
PlacesFrecencyRecalculator.isRecalculationPending,
"Recalculation should be pending"
);
}
);
add_task(
{
pref_set: [[FEATURE_PREF, false]],
},
async function test_disable() {
let pages = await getAllPages();
Assert.ok(
pages.every(p => p.recalc_alt_frecency == 0),
"All the entries should not need recalculation"
);
// Avoid hitting the cache, we want to check the actual database value.
PlacesUtils.metadata.cache.clear();
Assert.equal(
(
await PlacesUtils.metadata.get(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
Object.create(null)
)
).version,
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.variables
.version,
"Check the algorithm version has been stored"
);
await restartRecalculator();
// Check alternative frecency has not been marked for recalculation.
pages = await getAllPages();
Assert.ok(
pages.every(p => p.recalc_alt_frecency == 0),
"The entries not have been marked for recalc"
);
Assert.ok(
pages.every(p => p.alt_frecency === null),
"All the alt_frecency values should have been nullified"
);
// Ensure moz_meta has been updated.
// Avoid hitting the cache, we want to check the actual database value.
PlacesUtils.metadata.cache.clear();
Assert.ok(
ObjectUtils.isEmpty(
await PlacesUtils.metadata.get(
PlacesFrecencyRecalculator.alternativeFrecencyInfo.pages.metadataKey,
Object.create(null)
)
),
"Check the algorithm variables has been removed"
);
}
);
add_task(
{
pref_set: [[FEATURE_PREF, true]],
},
async function test_score() {
await restartRecalculator();
// This is not intended to cover the algorithm as a whole, but just as a
// sanity check for scores.
// Add before visits to properly set visit source.
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
});
await PlacesTestUtils.addVisits([
{
transition: PlacesUtils.history.TRANSITIONS.FRAMED_LINK,
},
{
transition: PlacesUtils.history.TRANSITIONS.FRAMED_LINK,
},
{
visitDate: (Date.now() - 2 * 86400000) * 1000,
},
{ url: "https://base.moz.org" },
]);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
});
await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies();
let getFrecency = url =>
PlacesTestUtils.getDatabaseValue("moz_places", "alt_frecency", {
url,
});
let low = await getFrecency("https://low.moz.org/");
let old = await getFrecency("https://old.moz.org/");
Assert.greater(old, low);
let base = await getFrecency("https://base.moz.org/");
Assert.greater(base, old);
let unvisitedBm = await getFrecency("https://unvisitedbookmark.moz.org/");
Assert.greater(unvisitedBm, base);
let manyVisits = await getFrecency("https://manyvisits.moz.org/");
Assert.greater(manyVisits, unvisitedBm);
let visitedBm = await getFrecency("https://visitedbookmark.moz.org/");
Assert.greater(visitedBm, base);
}
);