summaryrefslogtreecommitdiffstats
path: root/storage/test/unit/test_locale_collation.js
diff options
context:
space:
mode:
Diffstat (limited to 'storage/test/unit/test_locale_collation.js')
-rw-r--r--storage/test/unit/test_locale_collation.js291
1 files changed, 291 insertions, 0 deletions
diff --git a/storage/test/unit/test_locale_collation.js b/storage/test/unit/test_locale_collation.js
new file mode 100644
index 0000000000..96f2415451
--- /dev/null
+++ b/storage/test/unit/test_locale_collation.js
@@ -0,0 +1,291 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * 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/. */
+
+/**
+ * Bug 499990 - Locale-aware collation
+ *
+ * Tests our custom, locale-aware collating sequences.
+ */
+
+// The name of the file containing the strings we'll sort during this test.
+// The file's data is taken from intl/locale/tests/sort/us-ascii_base.txt and
+// and intl/locale/tests/sort/us-ascii_sort.txt.
+const DATA_BASENAME = "locale_collation.txt";
+
+// The test data from DATA_BASENAME is read into this array.
+var gStrings;
+
+// A connection to our in-memory UTF-16-encoded database.
+var gUtf16Conn;
+
+// Helper Functions
+
+/**
+ * Since we create a UTF-16 database we have to clean it up, in addition to
+ * the normal cleanup of Storage tests.
+ */
+function cleanupLocaleTests() {
+ print("-- Cleaning up test_locale_collation.js suite.");
+ gUtf16Conn.close();
+ cleanup();
+}
+
+/**
+ * Creates a test database similar to the default one created in
+ * head_storage.js, except that this one uses UTF-16 encoding.
+ *
+ * @return A connection to the database.
+ */
+function createUtf16Database() {
+ print("Creating the in-memory UTF-16-encoded database.");
+ let conn = Services.storage.openSpecialDatabase("memory");
+ conn.executeSimpleSQL("PRAGMA encoding = 'UTF-16'");
+
+ print("Make sure the encoding was set correctly and is now UTF-16.");
+ let stmt = conn.createStatement("PRAGMA encoding");
+ Assert.ok(stmt.executeStep());
+ let enc = stmt.getString(0);
+ stmt.finalize();
+
+ // The value returned will actually be UTF-16le or UTF-16be.
+ Assert.ok(enc === "UTF-16le" || enc === "UTF-16be");
+
+ return conn;
+}
+
+/**
+ * Compares aActual to aExpected, ensuring that the numbers and orderings of
+ * the two arrays' elements are the same.
+ *
+ * @param aActual
+ * An array of strings retrieved from the database.
+ * @param aExpected
+ * An array of strings to which aActual should be equivalent.
+ */
+function ensureResultsAreCorrect(aActual, aExpected) {
+ print("Actual results: " + aActual);
+ print("Expected results: " + aExpected);
+
+ Assert.equal(aActual.length, aExpected.length);
+ for (let i = 0; i < aActual.length; i++) {
+ Assert.equal(aActual[i], aExpected[i]);
+ }
+}
+
+/**
+ * Synchronously SELECTs all rows from the test table of the given database
+ * using the given collation.
+ *
+ * @param aCollation
+ * The name of one of our custom locale collations. The rows are
+ * ordered by this collation.
+ * @param aConn
+ * A connection to either the UTF-8 database or the UTF-16 database.
+ * @return The resulting strings in an array.
+ */
+function getResults(aCollation, aConn) {
+ let results = [];
+ let stmt = aConn.createStatement(
+ "SELECT t FROM test ORDER BY t COLLATE " + aCollation + " ASC"
+ );
+ while (stmt.executeStep()) {
+ results.push(stmt.row.t);
+ }
+ stmt.finalize();
+ return results;
+}
+
+/**
+ * Inserts strings into our test table of the given database in the order given.
+ *
+ * @param aStrings
+ * An array of strings.
+ * @param aConn
+ * A connection to either the UTF-8 database or the UTF-16 database.
+ */
+function initTableWithStrings(aStrings, aConn) {
+ print("Initializing test table.");
+
+ aConn.executeSimpleSQL("DROP TABLE IF EXISTS test");
+ aConn.createTable("test", "t TEXT");
+ let stmt = aConn.createStatement("INSERT INTO test (t) VALUES (:t)");
+ aStrings.forEach(function (str) {
+ stmt.params.t = str;
+ stmt.execute();
+ stmt.reset();
+ });
+ stmt.finalize();
+}
+
+/**
+ * Returns a sorting function suitable for passing to Array.prototype.sort().
+ * The returned function uses the application's locale to compare strings.
+ *
+ * @param aCollation
+ * The name of one of our custom locale collations. The sorting
+ * strength is computed from this value.
+ * @return A function to use as a sorting callback.
+ */
+function localeCompare(aCollation) {
+ let sensitivity;
+
+ switch (aCollation) {
+ case "locale":
+ sensitivity = "base";
+ break;
+ case "locale_case_sensitive":
+ sensitivity = "case";
+ break;
+ case "locale_accent_sensitive":
+ sensitivity = "accent";
+ break;
+ case "locale_case_accent_sensitive":
+ sensitivity = "variant";
+ break;
+ default:
+ do_throw("Error in test: unknown collation '" + aCollation + "'");
+ break;
+ }
+ const collation = new Intl.Collator("en", { sensitivity });
+ return function (aStr1, aStr2) {
+ return collation.compare(aStr1, aStr2);
+ };
+}
+
+/**
+ * Reads in the test data from the file DATA_BASENAME and returns it as an array
+ * of strings.
+ *
+ * @return The test data as an array of strings.
+ */
+function readTestData() {
+ print("Reading in test data.");
+
+ let file = do_get_file(DATA_BASENAME);
+
+ let istream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
+ Ci.nsIFileInputStream
+ );
+ istream.init(file, -1, -1, 0);
+ istream.QueryInterface(Ci.nsILineInputStream);
+
+ let line = {};
+ let lines = [];
+ while (istream.readLine(line)) {
+ lines.push(line.value);
+ }
+ istream.close();
+
+ return lines;
+}
+
+/**
+ * Gets the results from the given database using the given collation and
+ * ensures that they match gStrings sorted by the same collation.
+ *
+ * @param aCollation
+ * The name of one of our custom locale collations. The rows from the
+ * database and the expected results are ordered by this collation.
+ * @param aConn
+ * A connection to either the UTF-8 database or the UTF-16 database.
+ */
+function runTest(aCollation, aConn) {
+ ensureResultsAreCorrect(
+ getResults(aCollation, aConn),
+ gStrings.slice(0).sort(localeCompare(aCollation))
+ );
+}
+
+/**
+ * Gets the results from the UTF-8 database using the given collation and
+ * ensures that they match gStrings sorted by the same collation.
+ *
+ * @param aCollation
+ * The name of one of our custom locale collations. The rows from the
+ * database and the expected results are ordered by this collation.
+ */
+function runUtf8Test(aCollation) {
+ runTest(aCollation, getOpenedDatabase());
+}
+
+/**
+ * Gets the results from the UTF-16 database using the given collation and
+ * ensures that they match gStrings sorted by the same collation.
+ *
+ * @param aCollation
+ * The name of one of our custom locale collations. The rows from the
+ * database and the expected results are ordered by this collation.
+ */
+function runUtf16Test(aCollation) {
+ runTest(aCollation, gUtf16Conn);
+}
+
+/**
+ * Sets up the test suite.
+ */
+function setup() {
+ print("-- Setting up the test_locale_collation.js suite.");
+
+ gStrings = readTestData();
+
+ initTableWithStrings(gStrings, getOpenedDatabase());
+
+ gUtf16Conn = createUtf16Database();
+ initTableWithStrings(gStrings, gUtf16Conn);
+}
+
+// Test Runs
+
+var gTests = [
+ {
+ desc: "Case and accent sensitive UTF-8",
+ run: () => runUtf8Test("locale_case_accent_sensitive"),
+ },
+
+ {
+ desc: "Case sensitive, accent insensitive UTF-8",
+ run: () => runUtf8Test("locale_case_sensitive"),
+ },
+
+ {
+ desc: "Case insensitive, accent sensitive UTF-8",
+ run: () => runUtf8Test("locale_accent_sensitive"),
+ },
+
+ {
+ desc: "Case and accent insensitive UTF-8",
+ run: () => runUtf8Test("locale"),
+ },
+
+ {
+ desc: "Case and accent sensitive UTF-16",
+ run: () => runUtf16Test("locale_case_accent_sensitive"),
+ },
+
+ {
+ desc: "Case sensitive, accent insensitive UTF-16",
+ run: () => runUtf16Test("locale_case_sensitive"),
+ },
+
+ {
+ desc: "Case insensitive, accent sensitive UTF-16",
+ run: () => runUtf16Test("locale_accent_sensitive"),
+ },
+
+ {
+ desc: "Case and accent insensitive UTF-16",
+ run: () => runUtf16Test("locale"),
+ },
+];
+
+function run_test() {
+ setup();
+ gTests.forEach(function (test) {
+ print("-- Running test: " + test.desc);
+ test.run();
+ });
+ cleanupLocaleTests();
+}