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