Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test runs only with pattern: buildapp == 'browser'
- Manifest: toolkit/components/places/tests/unit/xpcshell.toml
/* 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
"use strict";
/**
* Exercises the three spec scenarios for switching the active embedding model.
* The reconciliation logic is split across PlacesSemanticHistoryManager and
* PlacesSemanticHistoryDatabase; these tests drive the DB-level building
* blocks (getActiveModelConfig + replaceEmbeddingTables) directly, mirroring
* the comparison that the manager performs on startup.
*/
const { PlacesSemanticHistoryDatabase } = ChromeUtils.importESModule(
"resource://gre/modules/PlacesSemanticHistoryDatabase.sys.mjs"
);
const FILE = "places_semantic.sqlite";
// Mirrors the resolved-options shape produced by EmbeddingsGenerator. The DB
// layer compares the three fields modelConfigMatches uses.
const STATIC_CONFIG = dim => ({
featureId: "simple-text-embedder",
modelId: "mozilla/static-embeddings",
embeddingDimension: dim,
});
const ONNX_CONFIG = dim => ({
featureId: "simple-text-embedder",
modelId: null,
embeddingDimension: dim,
});
function eq(x, y) {
return (x ?? null) === (y ?? null);
}
function modelConfigMatches(a, b) {
return (
eq(a.featureId, b.featureId) &&
eq(a.modelId, b.modelId) &&
eq(a.embeddingDimension, b.embeddingDimension)
);
}
async function withDb(initialModelConfig, callback) {
const db = new PlacesSemanticHistoryDatabase({
embeddingSize: initialModelConfig.embeddingDimension,
fileName: FILE,
});
try {
let conn = await db.getConnection();
// Clean install inserts a default static row; align it with the
// desired starting config for the test.
await db.replaceEmbeddingTables(initialModelConfig, conn);
await callback(db);
} finally {
await db.closeConnection();
await db.removeDatabaseFiles();
}
}
async function insertOneTensor(db, dim) {
const conn = await db.getConnection();
await conn.execute(
`INSERT INTO vec_history (rowid, embedding)
VALUES (1, :vector)`,
{ vector: PlacesUtils.tensorToSQLBindable(Array(dim).fill(0.5)) }
);
}
async function countTensors(db) {
const conn = await db.getConnection();
const rows = await conn.execute(`SELECT count(*) FROM vec_history`);
return rows[0].getResultByIndex(0);
}
add_task(async function test_staticToTransformerDropsAndRebuilds() {
const initial = STATIC_CONFIG(128);
const desired = ONNX_CONFIG(384);
await withDb(initial, async db => {
await insertOneTensor(db, 128);
Assert.equal(await countTensors(db), 1, "Inserted starting tensor");
let conn = await db.getConnection();
const onDisk = await db.getActiveModelConfig(conn);
Assert.ok(
!modelConfigMatches(onDisk, desired),
"Initial config should not match desired"
);
await db.replaceEmbeddingTables(desired, conn);
const after = await db.getActiveModelConfig(conn);
Assert.equal(after.modelId, null);
Assert.equal(after.embeddingDimension, 384);
Assert.equal(
await countTensors(db),
0,
"Embeddings should have been dropped"
);
await db.closeConnection();
});
});
add_task(async function test_transformerToStaticDropsAndRebuilds() {
const initial = ONNX_CONFIG(384);
const desired = STATIC_CONFIG(256);
await withDb(initial, async db => {
await insertOneTensor(db, 384);
let conn = await db.getConnection();
const onDisk = await db.getActiveModelConfig(conn);
Assert.ok(
!modelConfigMatches(onDisk, desired),
"Initial config should not match desired"
);
await db.replaceEmbeddingTables(desired, conn);
const after = await db.getActiveModelConfig(conn);
Assert.equal(after.modelId, "mozilla/static-embeddings");
Assert.equal(after.embeddingDimension, 256);
Assert.equal(
await countTensors(db),
0,
"Embeddings should have been dropped"
);
await db.closeConnection();
});
});
add_task(async function test_matchingConfigIsNoOp() {
const config = ONNX_CONFIG(384);
await withDb(config, async db => {
await insertOneTensor(db, 384);
Assert.equal(await countTensors(db), 1);
let conn = await db.getConnection();
const onDisk = await db.getActiveModelConfig(conn);
Assert.ok(
modelConfigMatches(onDisk, config),
"On-disk config matches desired"
);
// Manager would skip replaceEmbeddingTables here; embeddings stay.
Assert.equal(await countTensors(db), 1, "Tensor should still be present");
await db.closeConnection();
});
});