mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-10 05:08:36 +02:00
I suspect that the root cause of bug 1502182 is that we try open a database connection before the old one is fully closed. Instead of dealing with complicatedasync bookkeeping to make sure this doesn't happen, this patch simply never closes the database connection. I don't think any of the benefits of closing IndexedDB databases apply to Normandy, and it isn't a significant cost to simply keep them open. Additionally, the patch distinguishes between readonly and readwrite transactions with the database. This was originally done to try and fix the bug. When it didn't help, I decided to leave the change in because it is a beneficial change anyways. Differential Revision: https://phabricator.services.mozilla.com/D10629 --HG-- extra : moz-landing-system : lando
189 lines
6.5 KiB
JavaScript
189 lines
6.5 KiB
JavaScript
"use strict";
|
|
|
|
ChromeUtils.import("resource://gre/modules/IndexedDB.jsm", this);
|
|
ChromeUtils.import("resource://gre/modules/TelemetryEnvironment.jsm", this);
|
|
ChromeUtils.import("resource://normandy/lib/PreferenceRollouts.jsm", this);
|
|
ChromeUtils.import("resource://normandy/lib/TelemetryEvents.jsm", this);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testGetMissing() {
|
|
is(
|
|
await PreferenceRollouts.get("does-not-exist"),
|
|
null,
|
|
"get should return null when the requested rollout does not exist"
|
|
);
|
|
}
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testAddUpdateAndGet() {
|
|
const rollout = {slug: "test-rollout", state: PreferenceRollouts.STATE_ACTIVE, preferences: []};
|
|
await PreferenceRollouts.add(rollout);
|
|
let storedRollout = await PreferenceRollouts.get(rollout.slug);
|
|
Assert.deepEqual(rollout, storedRollout, "get should retrieve a rollout from storage.");
|
|
|
|
rollout.state = PreferenceRollouts.STATE_GRADUATED;
|
|
await PreferenceRollouts.update(rollout);
|
|
storedRollout = await PreferenceRollouts.get(rollout.slug);
|
|
Assert.deepEqual(rollout, storedRollout, "get should retrieve a rollout from storage.");
|
|
},
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testCantUpdateNonexistent() {
|
|
const rollout = {slug: "test-rollout", state: PreferenceRollouts.STATE_ACTIVE, preferences: []};
|
|
await Assert.rejects(
|
|
PreferenceRollouts.update(rollout),
|
|
/doesn't already exist/,
|
|
"Update should fail if the rollout doesn't exist",
|
|
);
|
|
ok(!await PreferenceRollouts.has("test-rollout"), "rollout should not have been added");
|
|
},
|
|
);
|
|
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testGetAll() {
|
|
const rollout1 = {slug: "test-rollout-1", preference: []};
|
|
const rollout2 = {slug: "test-rollout-2", preference: []};
|
|
await PreferenceRollouts.add(rollout1);
|
|
await PreferenceRollouts.add(rollout2);
|
|
|
|
const storedRollouts = await PreferenceRollouts.getAll();
|
|
Assert.deepEqual(
|
|
storedRollouts.sort((a, b) => a.id - b.id),
|
|
[rollout1, rollout2],
|
|
"getAll should return every stored rollout.",
|
|
);
|
|
}
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testGetAllActive() {
|
|
const rollout1 = {slug: "test-rollout-1", state: PreferenceRollouts.STATE_ACTIVE};
|
|
const rollout2 = {slug: "test-rollout-2", state: PreferenceRollouts.STATE_GRADUATED};
|
|
const rollout3 = {slug: "test-rollout-3", state: PreferenceRollouts.STATE_ROLLED_BACK};
|
|
await PreferenceRollouts.add(rollout1);
|
|
await PreferenceRollouts.add(rollout2);
|
|
await PreferenceRollouts.add(rollout3);
|
|
|
|
const activeRollouts = await PreferenceRollouts.getAllActive();
|
|
Assert.deepEqual(activeRollouts, [rollout1], "getAllActive should return only active rollouts");
|
|
}
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testHas() {
|
|
const rollout = {slug: "test-rollout", preferences: []};
|
|
await PreferenceRollouts.add(rollout);
|
|
ok(await PreferenceRollouts.has(rollout.slug), "has should return true for an existing rollout");
|
|
ok(!await PreferenceRollouts.has("does not exist"), "has should return false for a missing rollout");
|
|
}
|
|
);
|
|
|
|
// recordOriginalValue should update storage to note the original values
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testRecordOriginalValuesUpdatesPreviousValues() {
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
preferences: [{preferenceName: "test.pref", value: 2, previousValue: null}],
|
|
});
|
|
|
|
await PreferenceRollouts.recordOriginalValues({"test.pref": 1});
|
|
|
|
Assert.deepEqual(
|
|
await PreferenceRollouts.getAll(),
|
|
[{
|
|
slug: "test-rollout",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
preferences: [{preferenceName: "test.pref", value: 2, previousValue: 1}],
|
|
}],
|
|
"rollout in database should be updated",
|
|
);
|
|
},
|
|
);
|
|
|
|
// recordOriginalValue should graduate a study when it is no longer relevant.
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
withSendEventStub,
|
|
async function testRecordOriginalValuesUpdatesPreviousValues(sendEventStub) {
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
preferences: [
|
|
{preferenceName: "test.pref1", value: 2, previousValue: null},
|
|
{preferenceName: "test.pref2", value: 2, previousValue: null},
|
|
],
|
|
});
|
|
|
|
// one pref being the same isn't enough to graduate
|
|
await PreferenceRollouts.recordOriginalValues({"test.pref1": 1, "test.pref2": 2});
|
|
let rollout = await PreferenceRollouts.get("test-rollout");
|
|
is(
|
|
rollout.state,
|
|
PreferenceRollouts.STATE_ACTIVE,
|
|
"rollouts should remain active when only one pref matches the built-in default",
|
|
);
|
|
|
|
Assert.deepEqual(sendEventStub.args, [], "no events should be sent yet");
|
|
|
|
// both prefs is enough
|
|
await PreferenceRollouts.recordOriginalValues({"test.pref1": 2, "test.pref2": 2});
|
|
rollout = await PreferenceRollouts.get("test-rollout");
|
|
is(
|
|
rollout.state,
|
|
PreferenceRollouts.STATE_GRADUATED,
|
|
"rollouts should graduate when all prefs matches the built-in defaults",
|
|
);
|
|
|
|
Assert.deepEqual(
|
|
sendEventStub.args,
|
|
[["graduate", "preference_rollout", "test-rollout", {}]],
|
|
"a graduation event should be sent",
|
|
);
|
|
},
|
|
);
|
|
|
|
// init should mark active rollouts in telemetry
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
withStub(TelemetryEnvironment, "setExperimentActive"),
|
|
async function testInitTelemetry(setExperimentActiveStub) {
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout-active-1",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
});
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout-active-2",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
});
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout-rolled-back",
|
|
state: PreferenceRollouts.STATE_ROLLED_BACK,
|
|
});
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout-graduated",
|
|
state: PreferenceRollouts.STATE_GRADUATED,
|
|
});
|
|
|
|
await PreferenceRollouts.init();
|
|
|
|
Assert.deepEqual(
|
|
setExperimentActiveStub.args,
|
|
[
|
|
["test-rollout-active-1", "active", {type: "normandy-prefrollout"}],
|
|
["test-rollout-active-2", "active", {type: "normandy-prefrollout"}],
|
|
],
|
|
"init should set activate a telemetry experiment for active preferences"
|
|
);
|
|
},
|
|
);
|