/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(async
function test_metadata() {
await PlacesUtils.metadata.set(
"test/integer", 123);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"test/integer"),
123,
"Should store new integer value"
);
await PlacesUtils.metadata.set(
"test/double", 123.45);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"test/double"),
123.45,
"Should store new double value"
);
await PlacesUtils.metadata.set(
"test/double", 567.89);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"test/double"),
567.89,
"Should update existing double value"
);
await PlacesUtils.metadata.set(
"test/boolean",
false);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"test/boolean"),
false,
"Should store new Boolean value"
);
await PlacesUtils.metadata.set(
"test/boolean",
true);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"test/boolean"),
true,
"Should update existing Boolean value"
);
await PlacesUtils.metadata.set(
"test/string",
"hi");
Assert.equal(
await PlacesUtils.metadata.get(
"test/string"),
"hi",
"Should store new string value"
);
await PlacesUtils.metadata.cache.clear();
Assert.equal(
await PlacesUtils.metadata.get(
"test/string"),
"hi",
"Should return string value after clearing cache"
);
await
Assert.rejects(
PlacesUtils.metadata.get(
"test/nonexistent"),
/No data stored
for key test\/nonexistent/,
"Should reject for a non-existent key and no default value."
);
Assert.equal(
await PlacesUtils.metadata.get(
"test/nonexistent",
"defaultValue"),
"defaultValue",
"Should return the default value for a non-existent key."
);
// Values are untyped; it's OK to store a value of a different type for the
// same key.
await PlacesUtils.metadata.set(
"test/string", 111);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"test/string"),
111,
"Should replace string with integer"
);
await PlacesUtils.metadata.set(
"test/string",
null);
await
Assert.rejects(
PlacesUtils.metadata.get(
"test/string"),
/No data stored
for key test\/string/,
"Should clear value when setting to NULL"
);
await PlacesUtils.metadata.
delete(
"test/string",
"test/boolean");
await
Assert.rejects(
PlacesUtils.metadata.get(
"test/string"),
/No data stored
for key test\/string/,
"Should delete string value"
);
await
Assert.rejects(
PlacesUtils.metadata.get(
"test/boolean"),
/No data stored
for key test\/
boolean/,
"Should delete Boolean value"
);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"test/integer"),
123,
"Should keep undeleted integer value"
);
await PlacesTestUtils.clearMetadata();
await
Assert.rejects(
PlacesUtils.metadata.get(
"test/integer"),
/No data stored
for key test\/integer/,
"Should clear integer value"
);
await
Assert.rejects(
PlacesUtils.metadata.get(
"test/double"),
/No data stored
for key test\/
double/,
"Should clear double value"
);
});
add_task(async
function test_metadata_canonical_keys() {
await PlacesUtils.metadata.set(
"Test/Integer", 123);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"tEsT/integer"),
123,
"New keys should be case-insensitive"
);
await PlacesUtils.metadata.set(
"test/integer", 456);
Assert.strictEqual(
await PlacesUtils.metadata.get(
"TEST/INTEGER"),
456,
"Existing keys should be case-insensitive"
);
await
Assert.rejects(
PlacesUtils.metadata.set(
"", 123),
/Invalid metadata key/,
"Should reject empty keys"
);
await
Assert.rejects(
PlacesUtils.metadata.get(123),
/Invalid metadata key/,
"Should reject numeric keys"
);
await
Assert.rejects(
PlacesUtils.metadata.
delete(
true),
/Invalid metadata key/,
"Should reject Boolean keys"
);
await
Assert.rejects(
PlacesUtils.metadata.set({}),
/Invalid metadata key/,
"Should reject object keys"
);
await
Assert.rejects(
PlacesUtils.metadata.get(
null),
/Invalid metadata key/,
"Should reject null keys"
);
await
Assert.rejects(
PlacesUtils.metadata.
delete(
"!@#$"),
/Invalid metadata key/,
"Should reject keys with invalid characters"
);
});
add_task(async
function test_metadata_blobs() {
let blob =
new Uint8Array([1, 2, 3]);
await PlacesUtils.metadata.set(
"test/blob", blob);
let sameBlob = await PlacesUtils.metadata.get(
"test/blob");
Assert.equal(
ChromeUtils.getClassName(sameBlob),
"Uint8Array",
"Should cache typed array for blob value"
);
Assert.deepEqual(sameBlob, blob,
"Should store new blob value");
info(
"Remove blob from cache");
await PlacesUtils.metadata.cache.clear();
let newBlob = await PlacesUtils.metadata.get(
"test/blob");
Assert.equal(
ChromeUtils.getClassName(newBlob),
"Uint8Array",
"Should inflate blob into typed array"
);
Assert.deepEqual(
newBlob,
blob,
"Should return same blob after clearing cache"
);
await PlacesTestUtils.clearMetadata();
});
add_task(async
function test_metadata_arrays() {
let array = [1, 2, 3,
"\u2713 \u00E0 la mode"];
await PlacesUtils.metadata.set(
"test/array", array);
let sameArray = await PlacesUtils.metadata.get(
"test/array");
Assert.ok(Array.isArray(sameArray),
"Should cache array for array value");
Assert.deepEqual(sameArray, array,
"Should store new array value");
info(
"Remove array from cache");
await PlacesUtils.metadata.cache.clear();
let newArray = await PlacesUtils.metadata.get(
"test/array");
Assert.ok(Array.isArray(newArray),
"Should inflate into array");
Assert.deepEqual(
newArray,
array,
"Should return same array after clearing cache"
);
await PlacesTestUtils.clearMetadata();
});
add_task(async
function test_metadata_objects() {
let object = { foo: 123, bar:
"test", meow:
"\u2713 \u00E0 la mode" };
await PlacesUtils.metadata.set(
"test/object", object);
let sameObject = await PlacesUtils.metadata.get(
"test/object");
Assert.equal(
typeof sameObject,
"object",
"Should cache object for object value"
);
Assert.deepEqual(sameObject, object,
"Should store new object value");
info(
"Remove object from cache");
await PlacesUtils.metadata.cache.clear();
let newObject = await PlacesUtils.metadata.get(
"test/object");
Assert.equal(
typeof newObject,
"object",
"Should inflate into object");
Assert.deepEqual(
newObject,
object,
"Should return same object after clearing cache"
);
await PlacesTestUtils.clearMetadata();
});
add_task(async
function test_metadata_unparsable() {
await PlacesUtils.withConnectionWrapper(
"test_medata", db => {
let data = PlacesUtils.metadata._base64Encode(
"{hjjkhj}");
return db.execute(`
INSERT INTO moz_meta (key, value)
VALUES (
"test/unparsable",
"data:application/json;base64,${data}")
`);
});
await
Assert.rejects(
PlacesUtils.metadata.get(
"test/unparsable"),
/SyntaxError: JSON.parse/,
"Should reject for an unparsable value with no default"
);
Assert.deepEqual(
await PlacesUtils.metadata.get(
"test/unparsable", { foo: 1 }),
{ foo: 1 },
"Should return the default when encountering an unparsable value."
);
await PlacesTestUtils.clearMetadata();
});
add_task(async
function test_metadata_setMany() {
await PlacesUtils.metadata.setMany(
new Map([
[
"test/string",
"hi"],
[
"test/boolean",
true],
])
);
await PlacesUtils.metadata.set(
"test/string",
"hi");
Assert.deepEqual(
await PlacesUtils.metadata.get(
"test/string"),
"hi",
"Should store new string value"
);
Assert.deepEqual(
await PlacesUtils.metadata.get(
"test/boolean"),
true,
"Should store new boolean value"
);
await PlacesUtils.metadata.cache.clear();
Assert.equal(
await PlacesUtils.metadata.get(
"test/string"),
"hi",
"Should return string value after clearing cache"
);
Assert.deepEqual(
await PlacesUtils.metadata.get(
"test/boolean"),
true,
"Should store new boolean value"
);
await PlacesTestUtils.clearMetadata();
});