273 строки
9.8 KiB
JavaScript
273 строки
9.8 KiB
JavaScript
/* globals require, exports */
|
|
"use strict";
|
|
|
|
const {before, after, waitUntil} = require("sdk/test/utils");
|
|
const {MetadataStore} = require("lib/MetadataStore.js");
|
|
const {metadataFixture} = require("./lib/MetastoreFixture.js");
|
|
const fileIO = require("sdk/io/file");
|
|
|
|
const gMetadataStore = new MetadataStore();
|
|
|
|
/**
|
|
* Description of the metadata fixture
|
|
*
|
|
* The metadata fixture is composed of 3 pages, i.e.
|
|
* 1. https://www.mozilla.org/
|
|
* 2. https://www.mozilla.org/en-US/firefox/new/
|
|
* 3. https://www.mozilla.org/en-GB/firefox/new/
|
|
* where the page #1 consists of 1 favicon and 1 image, whereas both
|
|
* page #2 and #3 share the same 1 favicon and 2 images, respectively
|
|
*/
|
|
|
|
/**
|
|
* This function could be used to ensure the "asyncReset" actually commit
|
|
* the transaction. It appears that the transaction might be still in
|
|
* the uncommitted state despite its promise is resolved in Sqlite.jsm.
|
|
* Hence, it has to poll for the table info periodically to comfirm that
|
|
*/
|
|
function waitForAsyncReset() {
|
|
return waitUntil(function*() {
|
|
if (gMetadataStore.transactionInProgress) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
let nMetadata = yield gMetadataStore.asyncExecuteQuery(
|
|
"SELECT count(*) as count FROM page_metadata",
|
|
{"columns": ["count"]});
|
|
let nImages = yield gMetadataStore.asyncExecuteQuery(
|
|
"SELECT count(*) as count FROM page_images",
|
|
{"columns": ["count"]});
|
|
let nMetadataImages = yield gMetadataStore.asyncExecuteQuery(
|
|
"SELECT count(*) as count FROM page_metadata_images",
|
|
{"columns": ["count"]});
|
|
return !nMetadata[0].count &&
|
|
!nImages[0].count &&
|
|
!nMetadataImages[0].count;
|
|
} catch (e) {
|
|
/* ignore whatever error that makes the query above fail */
|
|
return false;
|
|
}
|
|
}, 10);
|
|
}
|
|
|
|
/**
|
|
* Test insert every single page separately
|
|
*/
|
|
exports.test_insert_single = function*(assert) {
|
|
for (let metadata of metadataFixture) {
|
|
yield gMetadataStore.asyncInsert([metadata]);
|
|
|
|
let items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata");
|
|
assert.equal(items.length, 1);
|
|
items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_images");
|
|
assert.equal(metadata.images.length + 1, items.length);
|
|
items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata_images");
|
|
assert.equal(metadata.images.length + 1, items.length);
|
|
yield gMetadataStore.asyncReset();
|
|
yield waitForAsyncReset();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Test insert a partial record
|
|
*/
|
|
exports.test_insert_partial = function*(assert) {
|
|
yield gMetadataStore.asyncInsert([{
|
|
places_url: "http://foobar.com",
|
|
cache_key: "foobar.com/"
|
|
}]);
|
|
let items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata");
|
|
assert.equal(items.length, 1, "Page is inserted");
|
|
items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_images");
|
|
assert.equal(items.length, 0, "No images were inserted");
|
|
items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata_images");
|
|
assert.equal(items.length, 0, "No metadata_images were inserted");
|
|
};
|
|
|
|
/**
|
|
* Test insert a record with images without colors or sizes
|
|
*/
|
|
exports.test_insert_partial_images = function*(assert) {
|
|
yield gMetadataStore.asyncInsert([{
|
|
places_url: "http://foobar.com",
|
|
cache_key: "foobar.com/",
|
|
images: [
|
|
{url: "http://foobar.com/blah.com"}
|
|
]
|
|
}]);
|
|
let items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata");
|
|
assert.equal(items.length, 1, "Page is inserted");
|
|
items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_images");
|
|
assert.equal(items.length, 1, "1 image was inserted");
|
|
items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata_images");
|
|
assert.equal(items.length, 1, "1 metadata_image was inserted");
|
|
};
|
|
|
|
/**
|
|
* Test missing required fields for insert should throw an error
|
|
*/
|
|
exports.test_insert_required_fields = function*(assert) {
|
|
const correctMessage = "Objects to insert must include a places_url";
|
|
let error;
|
|
try {
|
|
yield gMetadataStore.asyncInsert([{}]);
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
assert.ok(error, "Error was thrown for missing cache_key");
|
|
assert.equal(error.message, correctMessage, "Has the right error message");
|
|
};
|
|
|
|
exports.test_insert_twice = function*(assert) {
|
|
const metadata = metadataFixture[0];
|
|
yield gMetadataStore.asyncInsert([metadata]);
|
|
|
|
let items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata");
|
|
assert.equal(items.length, 1, "Page is inserted");
|
|
let error = false;
|
|
try {
|
|
yield gMetadataStore.asyncInsert([metadata]);
|
|
} catch (e) {
|
|
error = true;
|
|
}
|
|
assert.ok(error, "Re-insert the same page should be rejected!");
|
|
};
|
|
|
|
/**
|
|
* Test insert all the fixture pages, to test that page #2 and #3
|
|
* should share the same favicon and images instead of storing the
|
|
* same image twice
|
|
*/
|
|
exports.test_async_insert_all = function*(assert) {
|
|
yield gMetadataStore.asyncInsert(metadataFixture);
|
|
|
|
let items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata");
|
|
assert.equal(items.length, 3);
|
|
items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_images");
|
|
assert.equal(items.length, 5); // page #1(1 + 1) + page #2(1 + 2)
|
|
items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata_images");
|
|
assert.deepEqual(items.length, 8);
|
|
assert.deepEqual(items[0], [1, 1]);
|
|
assert.deepEqual(items[1], [1, 2]);
|
|
assert.deepEqual(items[2], [2, 3]);
|
|
assert.deepEqual(items[3], [2, 4]);
|
|
assert.deepEqual(items[4], [2, 5]);
|
|
assert.deepEqual(items[5], [3, 3]);
|
|
assert.deepEqual(items[6], [3, 4]);
|
|
assert.deepEqual(items[7], [3, 5]);
|
|
};
|
|
|
|
exports.test_async_get_by_cache_key = function*(assert) {
|
|
yield gMetadataStore.asyncInsert(metadataFixture);
|
|
|
|
for (let fixture of metadataFixture) {
|
|
let metaObjects = yield gMetadataStore.asyncGetMetadataByCacheKey([fixture.cache_key]);
|
|
assert.equal(metaObjects.length, 1, "It should fetch one metadata record");
|
|
let metaObject = metaObjects[0];
|
|
assert.equal(metaObject.favicons.length, 1, "It should fetch one favicon");
|
|
assert.equal(metaObject.images.length, fixture.images.length, "It should fetch one favicon");
|
|
}
|
|
|
|
let cacheKeys = metadataFixture.map(fixture => {return fixture.cache_key;});
|
|
let metaObjects = yield gMetadataStore.asyncGetMetadataByCacheKey(cacheKeys);
|
|
assert.equal(metaObjects.length, metadataFixture.length, "It should fetch all metadata records");
|
|
};
|
|
|
|
exports.test_async_get_by_cache_key_in_special_cases = function*(assert) {
|
|
yield gMetadataStore.asyncInsert(metadataFixture);
|
|
|
|
let cacheKeys = metadataFixture.map(fixture => {return fixture.cache_key;});
|
|
let metaObjects = yield gMetadataStore.asyncGetMetadataByCacheKey(
|
|
cacheKeys.concat("missing-key1", "missing-key2"));
|
|
assert.equal(metaObjects.length, metadataFixture.length,
|
|
"It should fetch all metadata records despite missing keys are presented in the cache keys");
|
|
|
|
// Manually set the image type to invalid values
|
|
yield gMetadataStore.asyncExecuteQuery("UPDATE page_images SET type=-1");
|
|
let error = false;
|
|
try {
|
|
yield gMetadataStore.asyncGetMetadataByCacheKey(cacheKeys);
|
|
} catch (e) {
|
|
error = true;
|
|
}
|
|
assert.ok(error, "It should raise exception on the invalid image type");
|
|
};
|
|
|
|
exports.test_on_an_invalid_connection = function*(assert) {
|
|
yield gMetadataStore.asyncClose();
|
|
|
|
let error = false;
|
|
try {
|
|
yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata");
|
|
} catch (e) {
|
|
error = true;
|
|
}
|
|
assert.ok(error, "It should raise exception if the connection is closed or not established");
|
|
|
|
error = false;
|
|
try {
|
|
yield gMetadataStore.asycnInsert(metadataFixture);
|
|
} catch (e) {
|
|
error = true;
|
|
}
|
|
assert.ok(error, "It should raise exception if the connection is closed or not established");
|
|
|
|
let cacheKeys = metadataFixture.map(fixture => {return fixture.cache_key;});
|
|
let metaObjects = yield gMetadataStore.asyncGetMetadataByCacheKey(cacheKeys);
|
|
assert.equal(metaObjects.length, 0, "It should return an empty array if the connection is closed or not established");
|
|
};
|
|
|
|
exports.test_color_conversions = function(assert) {
|
|
const white = [0, 0, 0];
|
|
const black = [255, 255, 255];
|
|
const randomColor = [111, 122, 133];
|
|
|
|
assert.deepEqual(white,
|
|
gMetadataStore._hexToRgb(gMetadataStore._rgbToHex(white)));
|
|
assert.deepEqual(black,
|
|
gMetadataStore._hexToRgb(gMetadataStore._rgbToHex(black)));
|
|
assert.deepEqual(randomColor,
|
|
gMetadataStore._hexToRgb(gMetadataStore._rgbToHex(randomColor)));
|
|
assert.equal(gMetadataStore._hexToRgb(gMetadataStore._rgbToHex(null)), null);
|
|
};
|
|
|
|
exports.test_data_expiry = function*(assert) {
|
|
let item = Object.assign({}, metadataFixture[0]);
|
|
let expected = 2;
|
|
let ticked = 0;
|
|
|
|
gMetadataStore.enableDataExpiryJob(100);
|
|
item.expired_at = Date.now();
|
|
yield gMetadataStore.asyncInsert([].concat(item, metadataFixture.slice(1, 3)));
|
|
// it waits until the expired item gets deleted or the waitUntil hits the timeout
|
|
yield waitUntil(function*() {
|
|
let items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata");
|
|
if (items.length === expected || ticked++ > 10) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}, 1000);
|
|
let items = yield gMetadataStore.asyncExecuteQuery("SELECT * FROM page_metadata");
|
|
assert.equal(items.length, expected, "It should have deleted the expired page");
|
|
gMetadataStore.disableDataExpiryJob();
|
|
};
|
|
|
|
exports.test_delete = function*(assert) {
|
|
yield gMetadataStore.asyncInsert(metadataFixture);
|
|
yield gMetadataStore.asyncTearDown();
|
|
assert.ok(!fileIO.exists(gMetadataStore._path), "It should remove the SQLite file");
|
|
};
|
|
|
|
before(exports, function*() {
|
|
yield gMetadataStore.asyncConnect();
|
|
});
|
|
|
|
after(exports, function*() {
|
|
yield gMetadataStore.asyncReset();
|
|
yield waitForAsyncReset();
|
|
yield gMetadataStore.asyncClose();
|
|
});
|
|
|
|
require("sdk/test").run(exports);
|