tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_locale_collation.js (8035B)


      1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
      2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /**
      8 * Bug 499990 - Locale-aware collation
      9 *
     10 * Tests our custom, locale-aware collating sequences.
     11 */
     12 
     13 // The name of the file containing the strings we'll sort during this test.
     14 // The file's data is taken from intl/locale/tests/sort/us-ascii_base.txt and
     15 // and intl/locale/tests/sort/us-ascii_sort.txt.
     16 const DATA_BASENAME = "locale_collation.txt";
     17 
     18 // The test data from DATA_BASENAME is read into this array.
     19 var gStrings;
     20 
     21 // A connection to our in-memory UTF-16-encoded database.
     22 var gUtf16Conn;
     23 
     24 // Helper Functions
     25 
     26 /**
     27 * Since we create a UTF-16 database we have to clean it up, in addition to
     28 * the normal cleanup of Storage tests.
     29 */
     30 function cleanupLocaleTests() {
     31  print("-- Cleaning up test_locale_collation.js suite.");
     32  gUtf16Conn.close();
     33  cleanup();
     34 }
     35 
     36 /**
     37 * Creates a test database similar to the default one created in
     38 * head_storage.js, except that this one uses UTF-16 encoding.
     39 *
     40 * @return A connection to the database.
     41 */
     42 function createUtf16Database() {
     43  print("Creating the in-memory UTF-16-encoded database.");
     44  let conn = Services.storage.openSpecialDatabase("memory");
     45  conn.executeSimpleSQL("PRAGMA encoding = 'UTF-16'");
     46 
     47  print("Make sure the encoding was set correctly and is now UTF-16.");
     48  let stmt = conn.createStatement("PRAGMA encoding");
     49  Assert.ok(stmt.executeStep());
     50  let enc = stmt.getString(0);
     51  stmt.finalize();
     52 
     53  // The value returned will actually be UTF-16le or UTF-16be.
     54  Assert.ok(enc === "UTF-16le" || enc === "UTF-16be");
     55 
     56  return conn;
     57 }
     58 
     59 /**
     60 * Compares aActual to aExpected, ensuring that the numbers and orderings of
     61 * the two arrays' elements are the same.
     62 *
     63 * @param aActual
     64 *        An array of strings retrieved from the database.
     65 * @param aExpected
     66 *        An array of strings to which aActual should be equivalent.
     67 */
     68 function ensureResultsAreCorrect(aActual, aExpected) {
     69  print("Actual results:   " + aActual);
     70  print("Expected results: " + aExpected);
     71 
     72  Assert.equal(aActual.length, aExpected.length);
     73  for (let i = 0; i < aActual.length; i++) {
     74    Assert.equal(aActual[i], aExpected[i]);
     75  }
     76 }
     77 
     78 /**
     79 * Synchronously SELECTs all rows from the test table of the given database
     80 * using the given collation.
     81 *
     82 * @param  aCollation
     83 *         The name of one of our custom locale collations.  The rows are
     84 *         ordered by this collation.
     85 * @param  aConn
     86 *         A connection to either the UTF-8 database or the UTF-16 database.
     87 * @return The resulting strings in an array.
     88 */
     89 function getResults(aCollation, aConn) {
     90  let results = [];
     91  let stmt = aConn.createStatement(
     92    "SELECT t FROM test ORDER BY t COLLATE " + aCollation + " ASC"
     93  );
     94  while (stmt.executeStep()) {
     95    results.push(stmt.row.t);
     96  }
     97  stmt.finalize();
     98  return results;
     99 }
    100 
    101 /**
    102 * Inserts strings into our test table of the given database in the order given.
    103 *
    104 * @param aStrings
    105 *        An array of strings.
    106 * @param aConn
    107 *        A connection to either the UTF-8 database or the UTF-16 database.
    108 */
    109 function initTableWithStrings(aStrings, aConn) {
    110  print("Initializing test table.");
    111 
    112  aConn.executeSimpleSQL("DROP TABLE IF EXISTS test");
    113  aConn.createTable("test", "t TEXT");
    114  let stmt = aConn.createStatement("INSERT INTO test (t) VALUES (:t)");
    115  aStrings.forEach(function (str) {
    116    stmt.params.t = str;
    117    stmt.execute();
    118    stmt.reset();
    119  });
    120  stmt.finalize();
    121 }
    122 
    123 /**
    124 * Returns a sorting function suitable for passing to Array.prototype.sort().
    125 * The returned function uses the application's locale to compare strings.
    126 *
    127 * @param  aCollation
    128 *         The name of one of our custom locale collations.  The sorting
    129 *         strength is computed from this value.
    130 * @return A function to use as a sorting callback.
    131 */
    132 function localeCompare(aCollation) {
    133  let sensitivity;
    134 
    135  switch (aCollation) {
    136    case "locale":
    137      sensitivity = "base";
    138      break;
    139    case "locale_case_sensitive":
    140      sensitivity = "case";
    141      break;
    142    case "locale_accent_sensitive":
    143      sensitivity = "accent";
    144      break;
    145    case "locale_case_accent_sensitive":
    146      sensitivity = "variant";
    147      break;
    148    default:
    149      do_throw("Error in test: unknown collation '" + aCollation + "'");
    150      break;
    151  }
    152  const collation = new Intl.Collator("en", { sensitivity });
    153  return function (aStr1, aStr2) {
    154    return collation.compare(aStr1, aStr2);
    155  };
    156 }
    157 
    158 /**
    159 * Reads in the test data from the file DATA_BASENAME and returns it as an array
    160 * of strings.
    161 *
    162 * @return The test data as an array of strings.
    163 */
    164 function readTestData() {
    165  print("Reading in test data.");
    166 
    167  let file = do_get_file(DATA_BASENAME);
    168 
    169  let istream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
    170    Ci.nsIFileInputStream
    171  );
    172  istream.init(file, -1, -1, 0);
    173  istream.QueryInterface(Ci.nsILineInputStream);
    174 
    175  let line = {};
    176  let lines = [];
    177  while (istream.readLine(line)) {
    178    lines.push(line.value);
    179  }
    180  istream.close();
    181 
    182  return lines;
    183 }
    184 
    185 /**
    186 * Gets the results from the given database using the given collation and
    187 * ensures that they match gStrings sorted by the same collation.
    188 *
    189 * @param aCollation
    190 *        The name of one of our custom locale collations.  The rows from the
    191 *        database and the expected results are ordered by this collation.
    192 * @param aConn
    193 *        A connection to either the UTF-8 database or the UTF-16 database.
    194 */
    195 function runTest(aCollation, aConn) {
    196  ensureResultsAreCorrect(
    197    getResults(aCollation, aConn),
    198    gStrings.slice(0).sort(localeCompare(aCollation))
    199  );
    200 }
    201 
    202 /**
    203 * Gets the results from the UTF-8 database using the given collation and
    204 * ensures that they match gStrings sorted by the same collation.
    205 *
    206 * @param aCollation
    207 *        The name of one of our custom locale collations.  The rows from the
    208 *        database and the expected results are ordered by this collation.
    209 */
    210 function runUtf8Test(aCollation) {
    211  runTest(aCollation, getOpenedDatabase());
    212 }
    213 
    214 /**
    215 * Gets the results from the UTF-16 database using the given collation and
    216 * ensures that they match gStrings sorted by the same collation.
    217 *
    218 * @param aCollation
    219 *        The name of one of our custom locale collations.  The rows from the
    220 *        database and the expected results are ordered by this collation.
    221 */
    222 function runUtf16Test(aCollation) {
    223  runTest(aCollation, gUtf16Conn);
    224 }
    225 
    226 /**
    227 * Sets up the test suite.
    228 */
    229 function setup() {
    230  print("-- Setting up the test_locale_collation.js suite.");
    231 
    232  gStrings = readTestData();
    233 
    234  initTableWithStrings(gStrings, getOpenedDatabase());
    235 
    236  gUtf16Conn = createUtf16Database();
    237  initTableWithStrings(gStrings, gUtf16Conn);
    238 }
    239 
    240 // Test Runs
    241 
    242 var gTests = [
    243  {
    244    desc: "Case and accent sensitive UTF-8",
    245    run: () => runUtf8Test("locale_case_accent_sensitive"),
    246  },
    247 
    248  {
    249    desc: "Case sensitive, accent insensitive UTF-8",
    250    run: () => runUtf8Test("locale_case_sensitive"),
    251  },
    252 
    253  {
    254    desc: "Case insensitive, accent sensitive UTF-8",
    255    run: () => runUtf8Test("locale_accent_sensitive"),
    256  },
    257 
    258  {
    259    desc: "Case and accent insensitive UTF-8",
    260    run: () => runUtf8Test("locale"),
    261  },
    262 
    263  {
    264    desc: "Case and accent sensitive UTF-16",
    265    run: () => runUtf16Test("locale_case_accent_sensitive"),
    266  },
    267 
    268  {
    269    desc: "Case sensitive, accent insensitive UTF-16",
    270    run: () => runUtf16Test("locale_case_sensitive"),
    271  },
    272 
    273  {
    274    desc: "Case insensitive, accent sensitive UTF-16",
    275    run: () => runUtf16Test("locale_accent_sensitive"),
    276  },
    277 
    278  {
    279    desc: "Case and accent insensitive UTF-16",
    280    run: () => runUtf16Test("locale"),
    281  },
    282 ];
    283 
    284 function run_test() {
    285  setup();
    286  gTests.forEach(function (test) {
    287    print("-- Running test: " + test.desc);
    288    test.run();
    289  });
    290  cleanupLocaleTests();
    291 }