diff options
Diffstat (limited to 'toolkit/components/xulstore/tests')
12 files changed, 664 insertions, 0 deletions
diff --git a/toolkit/components/xulstore/tests/chrome/chrome.ini b/toolkit/components/xulstore/tests/chrome/chrome.ini new file mode 100644 index 0000000000..c8f4ddf073 --- /dev/null +++ b/toolkit/components/xulstore/tests/chrome/chrome.ini @@ -0,0 +1,5 @@ +[DEFAULT] +support-files = + window_persistence.xhtml + +[test_persistence.xhtml] diff --git a/toolkit/components/xulstore/tests/chrome/test_persistence.xhtml b/toolkit/components/xulstore/tests/chrome/test_persistence.xhtml new file mode 100644 index 0000000000..b3e65fb050 --- /dev/null +++ b/toolkit/components/xulstore/tests/chrome/test_persistence.xhtml @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> + +<window title="Persistence Tests" + onload="runTest()" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <script> + SimpleTest.waitForExplicitFinish(); + function runTest() { + window.openDialog("window_persistence.xhtml", "_blank", "chrome,noopener", true, window); + } + + function windowOpened() { + window.openDialog("window_persistence.xhtml", "_blank", "chrome,noopener", false, window); + } + + function testDone() { + SimpleTest.finish(); + } + </script> + +<body xmlns="http://www.w3.org/1999/xhtml"> + <p id="display"/> +</body> + +</window> diff --git a/toolkit/components/xulstore/tests/chrome/window_persistence.xhtml b/toolkit/components/xulstore/tests/chrome/window_persistence.xhtml new file mode 100644 index 0000000000..d474891cfc --- /dev/null +++ b/toolkit/components/xulstore/tests/chrome/window_persistence.xhtml @@ -0,0 +1,67 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> + +<window title="Persistence Tests" + onload="opened()" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + persist="screenX screenY width height"> + +<button id="button1" label="Button1" persist="value"/> +<button id="button2" label="Button2" value="Normal" persist="value"/> +<button id="button3" label="Button3" value="Normal" persist="hidden" hidden="true"/> + +<script> +<![CDATA[ + +const XULStore = Services.xulStore; +let URI = "chrome://mochitests/content/chrome/toolkit/components/xulstore/tests/chrome/window_persistence.xhtml"; + +function opened() +{ + runTest(); +} + +function runTest() +{ + var firstRun = window.arguments[0]; + var button1 = document.getElementById("button1"); + var button2 = document.getElementById("button2"); + var button3 = document.getElementById("button3"); + if (firstRun) { + button1.setAttribute("value", "Pressed"); + button2.removeAttribute("value"); + + button2.setAttribute("foo", "bar"); + XULStore.persist(button2, "foo"); + is(XULStore.getValue(URI, "button2", "foo"), "bar", "attribute persisted"); + button2.removeAttribute("foo"); + XULStore.persist(button2, "foo"); + is(XULStore.hasValue(URI, "button2", "foo"), false, "attribute removed"); + + button3.removeAttribute("hidden"); + + window.close(); + window.arguments[1].windowOpened(); + } + else { + is(button1.getAttribute("value"), "Pressed", + "Attribute set"); + is(button2.hasAttribute("value"), false, + "Attribute cleared"); + is(button2.hasAttribute("foo"), false, + "Attribute cleared"); + + is(button3.hasAttribute("hidden"), false, + "Attribute cleared"); + + window.close(); + window.arguments[1].testDone(); + } +} + +function is(l, r, n) { window.arguments[1].SimpleTest.is(l,r,n); } + +]]></script> + +</window> diff --git a/toolkit/components/xulstore/tests/gtest/Cargo.toml b/toolkit/components/xulstore/tests/gtest/Cargo.toml new file mode 100644 index 0000000000..53c75a2100 --- /dev/null +++ b/toolkit/components/xulstore/tests/gtest/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "xulstore-gtest" +version = "0.1.0" +authors = ["The Mozilla Project Developers"] + +[lib] +path = "test.rs" diff --git a/toolkit/components/xulstore/tests/gtest/TestXULStore.cpp b/toolkit/components/xulstore/tests/gtest/TestXULStore.cpp new file mode 100644 index 0000000000..50d7f54b80 --- /dev/null +++ b/toolkit/components/xulstore/tests/gtest/TestXULStore.cpp @@ -0,0 +1,141 @@ +#include <stdint.h> +#include "gtest/gtest.h" +#include "mozilla/XULStore.h" +#include "nsCOMPtr.h" +#include "nsString.h" + +using mozilla::XULStoreIterator; +using mozilla::XULStore::GetAttrs; +using mozilla::XULStore::GetIDs; +using mozilla::XULStore::GetValue; +using mozilla::XULStore::HasValue; +using mozilla::XULStore::RemoveValue; +using mozilla::XULStore::SetValue; + +TEST(XULStore, SetGetValue) +{ + nsAutoString doc(u"SetGetValue"_ns); + nsAutoString id(u"foo"_ns); + nsAutoString attr(u"bar"_ns); + nsAutoString value; + + EXPECT_EQ(GetValue(doc, id, attr, value), NS_OK); + EXPECT_TRUE(value.EqualsASCII("")); + + { + nsAutoString value(u"baz"_ns); + EXPECT_EQ(SetValue(doc, id, attr, value), NS_OK); + } + + EXPECT_EQ(GetValue(doc, id, attr, value), NS_OK); + EXPECT_TRUE(value.EqualsASCII("baz")); +} + +TEST(XULStore, HasValue) +{ + nsAutoString doc(u"HasValue"_ns); + nsAutoString id(u"foo"_ns); + nsAutoString attr(u"bar"_ns); + bool hasValue = true; + EXPECT_EQ(HasValue(doc, id, attr, hasValue), NS_OK); + EXPECT_FALSE(hasValue); + nsAutoString value(u"baz"_ns); + EXPECT_EQ(SetValue(doc, id, attr, value), NS_OK); + EXPECT_EQ(HasValue(doc, id, attr, hasValue), NS_OK); + EXPECT_TRUE(hasValue); +} + +TEST(XULStore, RemoveValue) +{ + nsAutoString doc(u"RemoveValue"_ns); + nsAutoString id(u"foo"_ns); + nsAutoString attr(u"bar"_ns); + nsAutoString value(u"baz"_ns); + EXPECT_EQ(SetValue(doc, id, attr, value), NS_OK); + EXPECT_EQ(GetValue(doc, id, attr, value), NS_OK); + EXPECT_TRUE(value.EqualsASCII("baz")); + EXPECT_EQ(RemoveValue(doc, id, attr), NS_OK); + EXPECT_EQ(GetValue(doc, id, attr, value), NS_OK); + EXPECT_TRUE(value.EqualsASCII("")); +} + +TEST(XULStore, GetIDsIterator) +{ + nsAutoString doc(u"idIterDoc"_ns); + nsAutoString id1(u"id1"_ns); + nsAutoString id2(u"id2"_ns); + nsAutoString id3(u"id3"_ns); + nsAutoString attr(u"attr"_ns); + nsAutoString value(u"value"_ns); + nsAutoString id; + + // Confirm that the store doesn't have any IDs yet. + mozilla::UniquePtr<XULStoreIterator> iter; + EXPECT_EQ(GetIDs(doc, iter), NS_OK); + EXPECT_FALSE(iter->HasMore()); + // EXPECT_EQ(iter->GetNext(&id), NS_ERROR_FAILURE); + + // Insert with IDs in non-alphanumeric order to confirm + // that store will order them when iterating them. + EXPECT_EQ(SetValue(doc, id3, attr, value), NS_OK); + EXPECT_EQ(SetValue(doc, id1, attr, value), NS_OK); + EXPECT_EQ(SetValue(doc, id2, attr, value), NS_OK); + + // Insert different ID for another doc to confirm that store + // won't return it when iterating IDs for our doc. + nsAutoString otherDoc(u"otherDoc"_ns); + nsAutoString otherID(u"otherID"_ns); + EXPECT_EQ(SetValue(otherDoc, otherID, attr, value), NS_OK); + + EXPECT_EQ(GetIDs(doc, iter), NS_OK); + EXPECT_TRUE(iter->HasMore()); + EXPECT_EQ(iter->GetNext(&id), NS_OK); + EXPECT_TRUE(id.EqualsASCII("id1")); + EXPECT_TRUE(iter->HasMore()); + EXPECT_EQ(iter->GetNext(&id), NS_OK); + EXPECT_TRUE(id.EqualsASCII("id2")); + EXPECT_TRUE(iter->HasMore()); + EXPECT_EQ(iter->GetNext(&id), NS_OK); + EXPECT_TRUE(id.EqualsASCII("id3")); + EXPECT_FALSE(iter->HasMore()); +} + +TEST(XULStore, GetAttributeIterator) +{ + nsAutoString doc(u"attrIterDoc"_ns); + nsAutoString id(u"id"_ns); + nsAutoString attr1(u"attr1"_ns); + nsAutoString attr2(u"attr2"_ns); + nsAutoString attr3(u"attr3"_ns); + nsAutoString value(u"value"_ns); + nsAutoString attr; + + mozilla::UniquePtr<XULStoreIterator> iter; + EXPECT_EQ(GetAttrs(doc, id, iter), NS_OK); + EXPECT_FALSE(iter->HasMore()); + // EXPECT_EQ(iter->GetNext(&attr), NS_ERROR_FAILURE); + + // Insert with attributes in non-alphanumeric order to confirm + // that store will order them when iterating them. + EXPECT_EQ(SetValue(doc, id, attr3, value), NS_OK); + EXPECT_EQ(SetValue(doc, id, attr1, value), NS_OK); + EXPECT_EQ(SetValue(doc, id, attr2, value), NS_OK); + + // Insert different attribute for another ID to confirm that store + // won't return it when iterating attributes for our ID. + nsAutoString otherID(u"otherID"_ns); + nsAutoString otherAttr(u"otherAttr"_ns); + EXPECT_EQ(SetValue(doc, otherID, otherAttr, value), NS_OK); + + EXPECT_EQ(GetAttrs(doc, id, iter), NS_OK); + EXPECT_TRUE(iter->HasMore()); + EXPECT_EQ(iter->GetNext(&attr), NS_OK); + EXPECT_TRUE(attr.EqualsASCII("attr1")); + EXPECT_TRUE(iter->HasMore()); + EXPECT_EQ(iter->GetNext(&attr), NS_OK); + EXPECT_TRUE(attr.EqualsASCII("attr2")); + EXPECT_TRUE(iter->HasMore()); + EXPECT_EQ(iter->GetNext(&attr), NS_OK); + EXPECT_TRUE(attr.EqualsASCII("attr3")); + EXPECT_FALSE(iter->HasMore()); +} diff --git a/toolkit/components/xulstore/tests/gtest/moz.build b/toolkit/components/xulstore/tests/gtest/moz.build new file mode 100644 index 0000000000..81fd27a7e7 --- /dev/null +++ b/toolkit/components/xulstore/tests/gtest/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +UNIFIED_SOURCES += [ + "TestXULStore.cpp", +] + +FINAL_LIBRARY = "xul-gtest" diff --git a/toolkit/components/xulstore/tests/xpcshell/test_XULStore.js b/toolkit/components/xulstore/tests/xpcshell/test_XULStore.js new file mode 100644 index 0000000000..d100592e81 --- /dev/null +++ b/toolkit/components/xulstore/tests/xpcshell/test_XULStore.js @@ -0,0 +1,150 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/◦ +*/ + +"use strict"; + +var XULStore = null; +var browserURI = "chrome://browser/content/browser.xhtml"; +var aboutURI = "about:config"; + +function run_test() { + do_get_profile(); + run_next_test(); +} + +function checkValue(uri, id, attr, reference) { + let value = XULStore.getValue(uri, id, attr); + Assert.equal(value, reference); +} + +function checkValueExists(uri, id, attr, exists) { + Assert.equal(XULStore.hasValue(uri, id, attr), exists); +} + +function getIDs(uri) { + return Array.from(XULStore.getIDsEnumerator(uri)).sort(); +} + +function getAttributes(uri, id) { + return Array.from(XULStore.getAttributeEnumerator(uri, id)).sort(); +} + +function checkArrays(a, b) { + a.sort(); + b.sort(); + Assert.equal(a.toString(), b.toString()); +} + +add_task(async function setup() { + // Set a value that a future test depends on manually + XULStore = Services.xulStore; + XULStore.setValue(browserURI, "main-window", "width", "994"); +}); + +add_task(async function testTruncation() { + let dos = Array(8192).join("~"); + // Long id names should trigger an exception + Assert.throws( + () => XULStore.setValue(browserURI, dos, "foo", "foo"), + /NS_ERROR_ILLEGAL_VALUE/ + ); + + // Long attr names should trigger an exception + Assert.throws( + () => XULStore.setValue(browserURI, "foo", dos, "foo"), + /NS_ERROR_ILLEGAL_VALUE/ + ); + + // Long values should be truncated + XULStore.setValue(browserURI, "dos", "dos", dos); + dos = XULStore.getValue(browserURI, "dos", "dos"); + Assert.ok(dos.length == 4096); + XULStore.removeValue(browserURI, "dos", "dos"); +}); + +add_task(async function testGetValue() { + // Get non-existing property + checkValue(browserURI, "side-window", "height", ""); + + // Get existing property + checkValue(browserURI, "main-window", "width", "994"); +}); + +add_task(async function testHasValue() { + // Check non-existing property + checkValueExists(browserURI, "side-window", "height", false); + + // Check existing property + checkValueExists(browserURI, "main-window", "width", true); +}); + +add_task(async function testSetValue() { + // Set new attribute + checkValue(browserURI, "side-bar", "width", ""); + XULStore.setValue(browserURI, "side-bar", "width", "1000"); + checkValue(browserURI, "side-bar", "width", "1000"); + checkArrays(["main-window", "side-bar"], getIDs(browserURI)); + checkArrays(["width"], getAttributes(browserURI, "side-bar")); + + // Modify existing property + checkValue(browserURI, "side-bar", "width", "1000"); + XULStore.setValue(browserURI, "side-bar", "width", "1024"); + checkValue(browserURI, "side-bar", "width", "1024"); + checkArrays(["main-window", "side-bar"], getIDs(browserURI)); + checkArrays(["width"], getAttributes(browserURI, "side-bar")); + + // Add another attribute + checkValue(browserURI, "side-bar", "height", ""); + XULStore.setValue(browserURI, "side-bar", "height", "1000"); + checkValue(browserURI, "side-bar", "height", "1000"); + checkArrays(["main-window", "side-bar"], getIDs(browserURI)); + checkArrays(["width", "height"], getAttributes(browserURI, "side-bar")); +}); + +add_task(async function testRemoveValue() { + // Remove first attribute + checkValue(browserURI, "side-bar", "width", "1024"); + XULStore.removeValue(browserURI, "side-bar", "width"); + checkValue(browserURI, "side-bar", "width", ""); + checkValueExists(browserURI, "side-bar", "width", false); + checkArrays(["main-window", "side-bar"], getIDs(browserURI)); + checkArrays(["height"], getAttributes(browserURI, "side-bar")); + + // Remove second attribute + checkValue(browserURI, "side-bar", "height", "1000"); + XULStore.removeValue(browserURI, "side-bar", "height"); + checkValue(browserURI, "side-bar", "height", ""); + checkArrays(["main-window"], getIDs(browserURI)); + + // Removing an attribute that doesn't exists shouldn't fail + XULStore.removeValue(browserURI, "main-window", "bar"); + + // Removing from an id that doesn't exists shouldn't fail + XULStore.removeValue(browserURI, "foo", "bar"); + + // Removing from a document that doesn't exists shouldn't fail + let nonDocURI = "chrome://example/content/other.xul"; + XULStore.removeValue(nonDocURI, "foo", "bar"); + + // Remove all attributes in browserURI + XULStore.removeValue(browserURI, "addon-bar", "collapsed"); + checkArrays([], getAttributes(browserURI, "addon-bar")); + XULStore.removeValue(browserURI, "main-window", "width"); + XULStore.removeValue(browserURI, "main-window", "height"); + XULStore.removeValue(browserURI, "main-window", "screenX"); + XULStore.removeValue(browserURI, "main-window", "screenY"); + XULStore.removeValue(browserURI, "main-window", "sizemode"); + checkArrays([], getAttributes(browserURI, "main-window")); + XULStore.removeValue(browserURI, "sidebar-title", "value"); + checkArrays([], getAttributes(browserURI, "sidebar-title")); + checkArrays([], getIDs(browserURI)); + + // Remove all attributes in aboutURI + XULStore.removeValue(aboutURI, "prefCol", "ordinal"); + XULStore.removeValue(aboutURI, "prefCol", "sortDirection"); + checkArrays([], getAttributes(aboutURI, "prefCol")); + XULStore.removeValue(aboutURI, "lockCol", "ordinal"); + checkArrays([], getAttributes(aboutURI, "lockCol")); + checkArrays([], getIDs(aboutURI)); +}); diff --git a/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration.js b/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration.js new file mode 100644 index 0000000000..f054a45288 --- /dev/null +++ b/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration.js @@ -0,0 +1,85 @@ +"use strict"; + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +function run_test() { + do_get_profile(); + run_next_test(); +} + +add_task( + { + skip_if: () => !AppConstants.MOZ_NEW_XULSTORE, + }, + async function test_create_old_datastore() { + const path = PathUtils.join(PathUtils.profileDir, "xulstore.json"); + + const xulstoreJSON = { + doc1: { + id1: { + attr1: "value1", + }, + }, + doc2: { + id1: { + attr2: "value2", + }, + id2: { + attr1: "value1", + attr2: "value2", + attr3: "value3", + }, + id3: {}, + }, + doc3: {}, + }; + + await IOUtils.writeJSON(path, xulstoreJSON); + } +); + +add_task( + { + skip_if: () => !AppConstants.MOZ_NEW_XULSTORE, + }, + async function test_get_values() { + // We wait until now to import XULStore to ensure we've created + // the old datastore, as importing that module will initiate the attempt + // to migrate the old datastore to the new one. + const { XULStore } = ChromeUtils.import( + "resource://gre/modules/XULStore.jsm" + ); + + Assert.equal(await XULStore.getValue("doc1", "id1", "attr1"), "value1"); + Assert.equal(await XULStore.getValue("doc1", "id1", "attr2"), ""); + Assert.equal(await XULStore.getValue("doc1", "id1", "attr3"), ""); + Assert.equal(await XULStore.getValue("doc1", "id2", "attr1"), ""); + Assert.equal(await XULStore.getValue("doc1", "id2", "attr2"), ""); + Assert.equal(await XULStore.getValue("doc1", "id2", "attr3"), ""); + Assert.equal(await XULStore.getValue("doc1", "id3", "attr1"), ""); + Assert.equal(await XULStore.getValue("doc1", "id3", "attr2"), ""); + Assert.equal(await XULStore.getValue("doc1", "id3", "attr3"), ""); + + Assert.equal(await XULStore.getValue("doc2", "id1", "attr1"), ""); + Assert.equal(await XULStore.getValue("doc2", "id1", "attr2"), "value2"); + Assert.equal(await XULStore.getValue("doc2", "id1", "attr3"), ""); + Assert.equal(await XULStore.getValue("doc2", "id2", "attr1"), "value1"); + Assert.equal(await XULStore.getValue("doc2", "id2", "attr2"), "value2"); + Assert.equal(await XULStore.getValue("doc2", "id2", "attr3"), "value3"); + Assert.equal(await XULStore.getValue("doc2", "id3", "attr1"), ""); + Assert.equal(await XULStore.getValue("doc2", "id3", "attr2"), ""); + Assert.equal(await XULStore.getValue("doc2", "id3", "attr3"), ""); + + Assert.equal(await XULStore.getValue("doc3", "id1", "attr1"), ""); + Assert.equal(await XULStore.getValue("doc3", "id1", "attr2"), ""); + Assert.equal(await XULStore.getValue("doc3", "id1", "attr3"), ""); + Assert.equal(await XULStore.getValue("doc3", "id2", "attr1"), ""); + Assert.equal(await XULStore.getValue("doc3", "id2", "attr2"), ""); + Assert.equal(await XULStore.getValue("doc3", "id2", "attr3"), ""); + Assert.equal(await XULStore.getValue("doc3", "id3", "attr1"), ""); + Assert.equal(await XULStore.getValue("doc3", "id3", "attr2"), ""); + Assert.equal(await XULStore.getValue("doc3", "id3", "attr3"), ""); + } +); diff --git a/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_fail_invalid_data.js b/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_fail_invalid_data.js new file mode 100644 index 0000000000..b7b06bac2f --- /dev/null +++ b/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_fail_invalid_data.js @@ -0,0 +1,57 @@ +"use strict"; + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +function run_test() { + do_get_profile(); + run_next_test(); +} + +add_task( + { + skip_if: () => !AppConstants.MOZ_NEW_XULSTORE, + }, + async function test_create_old_datastore() { + const path = PathUtils.join(PathUtils.profileDir, "xulstore.json"); + + // Valid JSON, but invalid data: attr1's value is a number, not a string. + const xulstoreJSON = { + doc1: { + id1: { + attr1: 1, + }, + }, + doc2: { + id2: { + attr2: "value2", + }, + }, + }; + + await IOUtils.writeJSON(path, xulstoreJSON); + } +); + +add_task( + { + skip_if: () => !AppConstants.MOZ_NEW_XULSTORE, + }, + async function test_get_values() { + // We wait until now to import XULStore to ensure we've created + // the old store, as importing that module will initiate the attempt + // to migrate the old store to the new one. + const { XULStore } = ChromeUtils.import( + "resource://gre/modules/XULStore.jsm" + ); + + // XULStore should *not* have migrated the values from the old store, + // so it should return empty strings when we try to retrieve them. + // That's true for both values, even though one of them is valid, + // because the migrator uses a typed parser that requires the entire + // JSON file to conform to the XULStore format. + Assert.equal(await XULStore.getValue("doc1", "id1", "attr1"), ""); + Assert.equal(await XULStore.getValue("doc2", "id2", "attr2"), ""); + } +); diff --git a/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_fail_invalid_json.js b/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_fail_invalid_json.js new file mode 100644 index 0000000000..057e00c680 --- /dev/null +++ b/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_fail_invalid_json.js @@ -0,0 +1,42 @@ +"use strict"; + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +function run_test() { + do_get_profile(); + run_next_test(); +} + +add_task( + { + skip_if: () => !AppConstants.MOZ_NEW_XULSTORE, + }, + async function test_create_old_datastore() { + const path = PathUtils.join(PathUtils.profileDir, "xulstore.json"); + + // Invalid JSON: it's missing the final closing brace. + const xulstoreJSON = '{ doc: { id: { attr: "value" } }'; + + await IOUtils.writeUTF8(path, xulstoreJSON); + } +); + +add_task( + { + skip_if: () => !AppConstants.MOZ_NEW_XULSTORE, + }, + async function test_get_value() { + // We wait until now to import XULStore to ensure we've created + // the old store, as importing that module will initiate the attempt + // to migrate the old store to the new one. + const { XULStore } = ChromeUtils.import( + "resource://gre/modules/XULStore.jsm" + ); + + // XULStore should *not* have migrated the value from the old store, + // so it should return an empty string when we try to retrieve it. + Assert.equal(await XULStore.getValue("doc", "id", "attr"), ""); + } +); diff --git a/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_profile_change.js b/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_profile_change.js new file mode 100644 index 0000000000..d3db2af4f3 --- /dev/null +++ b/toolkit/components/xulstore/tests/xpcshell/test_XULStore_migration_profile_change.js @@ -0,0 +1,56 @@ +"use strict"; + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); +const { FileUtils } = ChromeUtils.importESModule( + "resource://gre/modules/FileUtils.sys.mjs" +); + +add_task( + { + skip_if: () => !AppConstants.MOZ_NEW_XULSTORE, + }, + async function test_get_values() { + // Import XULStore before getting the profile to ensure that the new store + // is initialized, as the purpose of this test is to confirm that the old + // store data gets migrated if the profile change happens post-initialization. + const { XULStore } = ChromeUtils.import( + "resource://gre/modules/XULStore.jsm" + ); + + // We haven't migrated any data yet (nor even changed to a profile), so there + // shouldn't be a value in the store. + Assert.equal(XULStore.getValue("doc1", "id1", "attr1"), ""); + + // Register an observer before the XULStore service registers its observer, + // so we can observe the profile-after-change notification first and create + // an old store for it to migrate. We need to write synchronously to avoid + // racing XULStore, so we use FileUtils instead of IOUtils. + Services.obs.addObserver( + { + observe() { + const file = FileUtils.getFile("ProfD", ["xulstore.json"]); + const xulstoreJSON = JSON.stringify({ + doc1: { + id1: { + attr1: "value1", + }, + }, + }); + let stream = FileUtils.openAtomicFileOutputStream(file); + stream.write(xulstoreJSON, xulstoreJSON.length); + FileUtils.closeAtomicFileOutputStream(stream); + }, + }, + "profile-after-change" + ); + + // This creates a profile and changes to it, triggering first our + // profile-after-change observer above and then XULStore's equivalent. + do_get_profile(true); + + // XULStore should now have migrated the value from the old store. + Assert.equal(XULStore.getValue("doc1", "id1", "attr1"), "value1"); + } +); diff --git a/toolkit/components/xulstore/tests/xpcshell/xpcshell.ini b/toolkit/components/xulstore/tests/xpcshell/xpcshell.ini new file mode 100644 index 0000000000..04c579dab5 --- /dev/null +++ b/toolkit/components/xulstore/tests/xpcshell/xpcshell.ini @@ -0,0 +1,13 @@ +[DEFAULT] +skip-if = toolkit == 'android' + +[test_XULStore.js] + +# These tests only run on the new implementation of XULStore, since they +# test migration of data from the old implementation to the new one. +# But there isn't a skip-if condition we can add here to disable them, +# so we disable them within each test file using add_task() properties. +[test_XULStore_migration.js] +[test_XULStore_migration_fail_invalid_json.js] +[test_XULStore_migration_fail_invalid_data.js] +[test_XULStore_migration_profile_change.js] |