Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/**
* Any copyright is dedicated to the Public Domain.
*/
/* exported testSteps */
async function testSteps() {
const name = "test_transaction_durability";
const abc = "abcdefghijklmnopqrstuvwxyz";
const durabilities = ["relaxed", "default", "strict"];
// Repeat the measurement 3 times.
const measurementCount = 3;
// The difference between relaxed and default is negligible (especially with
// SSDs).
const relaxedDefaultDiffPercentage = 1;
// The difference between default and strict is notable (even with SSDs).
const defaultStrictDiffPercentage = 20;
// Allow some tolerance (to deal with noise).
const tolerancePercentage = (function () {
if (isInChaosMode()) {
return 50;
}
return 30;
})();
// Adjust the number of transactions, so the test takes roughly same time
// across all platforms (including the chaos mode).
const transactionCount = (function () {
if (isInChaosMode()) {
switch (mozinfo.os) {
case "linux":
return 50;
case "mac":
return 7;
case "win":
return 650;
case "android":
return 1;
default:
return 250;
}
}
switch (mozinfo.os) {
case "linux":
return 275;
case "mac":
return 1150;
case "win":
return 650;
case "android":
return 135;
default:
return 500;
}
})();
// A helper function (could be moved to a common place).
function transposeMatrix(matrix) {
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < i; j++) {
const tmp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = tmp;
}
}
}
// A helper function (could be moved to a common place).
function getMedian(array) {
array.sort((a, b) => a - b);
const middleIndex = Math.floor(array.length / 2);
if (array.length % 2 === 0) {
return (array[middleIndex - 1] + array[middleIndex]) / 2;
}
return array[middleIndex];
}
// Data generation.
async function createDatabase(actualName) {
info(`Creating database ${actualName}`);
const request = indexedDB.open(actualName, 1);
const event = await expectingUpgrade(request);
const database = event.target.result;
database.createObjectStore(name);
await expectingSuccess(request);
return database;
}
async function fillDatabase(database, durability) {
return new Promise(function (resolve) {
const startTime = Cu.now();
info(`Filling database ${database.name} using ${durability} durability`);
let index = 0;
function addData() {
const transaction = database.transaction(name, "readwrite", {
durability,
});
const objectStore = transaction.objectStore(name);
objectStore.add(abc, index++);
transaction.oncomplete = function () {
if (index < transactionCount) {
addData();
} else {
const endTime = Cu.now();
const timeDelta = endTime - startTime;
info(
`Filled database ${database.name} using ${durability} ` +
`durability in ${timeDelta} msec`
);
resolve(timeDelta);
}
};
}
addData();
});
}
const timeDeltaMatrix = await (async function () {
let timeDeltaMatrix = [];
for (
let measurementIndex = 0;
measurementIndex < measurementCount;
measurementIndex++
) {
let databases = [];
for (
let durabilityIndex = 0;
durabilityIndex < durabilities.length;
durabilityIndex++
) {
const actualName =
name + "_" + measurementIndex + "_" + durabilityIndex;
const database = await createDatabase(actualName);
databases.push(database);
}
let promises = [];
for (
let durabilityIndex = 0;
durabilityIndex < durabilities.length;
durabilityIndex++
) {
const promise = fillDatabase(
databases[durabilityIndex],
durabilities[durabilityIndex]
);
promises.push(promise);
}
const timeDeltas = await Promise.all(promises);
timeDeltaMatrix.push(timeDeltas);
}
// Convert rows to columns.
transposeMatrix(timeDeltaMatrix);
return timeDeltaMatrix;
})();
// Data evaluation.
{
let lastTimeDeltaMedian;
for (
let durabilityIndex = 0;
durabilityIndex < durabilities.length;
durabilityIndex++
) {
const timeDeltaMedian = getMedian(timeDeltaMatrix[durabilityIndex]);
info("Time delta median: " + timeDeltaMedian);
if (lastTimeDeltaMedian) {
const durability = durabilities[durabilityIndex];
const actualTolerancePercentage =
tolerancePercentage -
(durability == "default"
? relaxedDefaultDiffPercentage
: defaultStrictDiffPercentage);
const coefficient = actualTolerancePercentage / 100;
const adjustedTimeDeltaMedian =
coefficient >= 0
? timeDeltaMedian * (1 + coefficient)
: timeDeltaMedian / (1 + Math.abs(coefficient));
Assert.greater(
adjustedTimeDeltaMedian,
lastTimeDeltaMedian,
`Database filling using higher (${durability}) durability should ` +
`take more time`
);
}
lastTimeDeltaMedian = timeDeltaMedian;
}
}
}