1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/test/unit/test_locale_collation.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,304 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/** 1.11 + * Bug 499990 - Locale-aware collation 1.12 + * 1.13 + * Tests our custom, locale-aware collating sequences. 1.14 + */ 1.15 + 1.16 +// The name of the file containing the strings we'll sort during this test. 1.17 +// The file's data is taken from intl/locale/tests/sort/us-ascii_base.txt and 1.18 +// and intl/locale/tests/sort/us-ascii_sort.txt. 1.19 +const DATA_BASENAME = "locale_collation.txt"; 1.20 + 1.21 +// The test data from DATA_BASENAME is read into this array. 1.22 +var gStrings; 1.23 + 1.24 +// A collation created from the application's locale. Used by localeCompare(). 1.25 +var gLocaleCollation; 1.26 + 1.27 +// A connection to our in-memory UTF-16-encoded database. 1.28 +var gUtf16Conn; 1.29 + 1.30 +/////////////////////////////////////////////////////////////////////////////// 1.31 +//// Helper Functions 1.32 + 1.33 +/** 1.34 + * Since we create a UTF-16 database we have to clean it up, in addition to 1.35 + * the normal cleanup of Storage tests. 1.36 + */ 1.37 +function cleanupLocaleTests() 1.38 +{ 1.39 + print("-- Cleaning up test_locale_collation.js suite."); 1.40 + gUtf16Conn.close(); 1.41 + cleanup(); 1.42 +} 1.43 + 1.44 +/** 1.45 + * Creates a test database similar to the default one created in 1.46 + * head_storage.js, except that this one uses UTF-16 encoding. 1.47 + * 1.48 + * @return A connection to the database. 1.49 + */ 1.50 +function createUtf16Database() 1.51 +{ 1.52 + print("Creating the in-memory UTF-16-encoded database."); 1.53 + let conn = getService().openSpecialDatabase("memory"); 1.54 + conn.executeSimpleSQL("PRAGMA encoding = 'UTF-16'"); 1.55 + 1.56 + print("Make sure the encoding was set correctly and is now UTF-16."); 1.57 + let stmt = conn.createStatement("PRAGMA encoding"); 1.58 + do_check_true(stmt.executeStep()); 1.59 + let enc = stmt.getString(0); 1.60 + stmt.finalize(); 1.61 + 1.62 + // The value returned will actually be UTF-16le or UTF-16be. 1.63 + do_check_true(enc === "UTF-16le" || enc === "UTF-16be"); 1.64 + 1.65 + return conn; 1.66 +} 1.67 + 1.68 +/** 1.69 + * Compares aActual to aExpected, ensuring that the numbers and orderings of 1.70 + * the two arrays' elements are the same. 1.71 + * 1.72 + * @param aActual 1.73 + * An array of strings retrieved from the database. 1.74 + * @param aExpected 1.75 + * An array of strings to which aActual should be equivalent. 1.76 + */ 1.77 +function ensureResultsAreCorrect(aActual, aExpected) 1.78 +{ 1.79 + print("Actual results: " + aActual); 1.80 + print("Expected results: " + aExpected); 1.81 + 1.82 + do_check_eq(aActual.length, aExpected.length); 1.83 + for (let i = 0; i < aActual.length; i++) 1.84 + do_check_eq(aActual[i], aExpected[i]); 1.85 +} 1.86 + 1.87 +/** 1.88 + * Synchronously SELECTs all rows from the test table of the given database 1.89 + * using the given collation. 1.90 + * 1.91 + * @param aCollation 1.92 + * The name of one of our custom locale collations. The rows are 1.93 + * ordered by this collation. 1.94 + * @param aConn 1.95 + * A connection to either the UTF-8 database or the UTF-16 database. 1.96 + * @return The resulting strings in an array. 1.97 + */ 1.98 +function getResults(aCollation, aConn) 1.99 +{ 1.100 + let results = []; 1.101 + let stmt = aConn.createStatement("SELECT t FROM test " + 1.102 + "ORDER BY t COLLATE " + aCollation + " ASC"); 1.103 + while (stmt.executeStep()) 1.104 + results.push(stmt.row.t); 1.105 + stmt.finalize(); 1.106 + return results; 1.107 +} 1.108 + 1.109 +/** 1.110 + * Inserts strings into our test table of the given database in the order given. 1.111 + * 1.112 + * @param aStrings 1.113 + * An array of strings. 1.114 + * @param aConn 1.115 + * A connection to either the UTF-8 database or the UTF-16 database. 1.116 + */ 1.117 +function initTableWithStrings(aStrings, aConn) 1.118 +{ 1.119 + print("Initializing test table."); 1.120 + 1.121 + aConn.executeSimpleSQL("DROP TABLE IF EXISTS test"); 1.122 + aConn.createTable("test", "t TEXT"); 1.123 + let stmt = aConn.createStatement("INSERT INTO test (t) VALUES (:t)"); 1.124 + aStrings.forEach(function (str) { 1.125 + stmt.params.t = str; 1.126 + stmt.execute(); 1.127 + stmt.reset(); 1.128 + }); 1.129 + stmt.finalize(); 1.130 +} 1.131 + 1.132 +/** 1.133 + * Returns a sorting function suitable for passing to Array.prototype.sort(). 1.134 + * The returned function uses the application's locale to compare strings. 1.135 + * 1.136 + * @param aCollation 1.137 + * The name of one of our custom locale collations. The sorting 1.138 + * strength is computed from this value. 1.139 + * @return A function to use as a sorting callback. 1.140 + */ 1.141 +function localeCompare(aCollation) 1.142 +{ 1.143 + var strength; 1.144 + 1.145 + switch (aCollation) { 1.146 + case "locale": 1.147 + strength = Ci.nsICollation.kCollationCaseInSensitive; 1.148 + break; 1.149 + case "locale_case_sensitive": 1.150 + strength = Ci.nsICollation.kCollationAccentInsenstive; 1.151 + break; 1.152 + case "locale_accent_sensitive": 1.153 + strength = Ci.nsICollation.kCollationCaseInsensitiveAscii; 1.154 + break; 1.155 + case "locale_case_accent_sensitive": 1.156 + strength = Ci.nsICollation.kCollationCaseSensitive; 1.157 + break; 1.158 + default: 1.159 + do_throw("Error in test: unknown collation '" + aCollation + "'"); 1.160 + break; 1.161 + } 1.162 + return function (aStr1, aStr2) 1.163 + gLocaleCollation.compareString(strength, aStr1, aStr2); 1.164 +} 1.165 + 1.166 +/** 1.167 + * Reads in the test data from the file DATA_BASENAME and returns it as an array 1.168 + * of strings. 1.169 + * 1.170 + * @return The test data as an array of strings. 1.171 + */ 1.172 +function readTestData() 1.173 +{ 1.174 + print("Reading in test data."); 1.175 + 1.176 + let file = do_get_file(DATA_BASENAME); 1.177 + 1.178 + let istream = Cc["@mozilla.org/network/file-input-stream;1"]. 1.179 + createInstance(Ci.nsIFileInputStream); 1.180 + istream.init(file, -1, -1, 0); 1.181 + istream.QueryInterface(Components.interfaces.nsILineInputStream); 1.182 + 1.183 + let line = {}; 1.184 + let lines = []; 1.185 + while (istream.readLine(line)) 1.186 + lines.push(line.value); 1.187 + istream.close(); 1.188 + 1.189 + return lines; 1.190 +} 1.191 + 1.192 +/** 1.193 + * Gets the results from the given database using the given collation and 1.194 + * ensures that they match gStrings sorted by the same collation. 1.195 + * 1.196 + * @param aCollation 1.197 + * The name of one of our custom locale collations. The rows from the 1.198 + * database and the expected results are ordered by this collation. 1.199 + * @param aConn 1.200 + * A connection to either the UTF-8 database or the UTF-16 database. 1.201 + */ 1.202 +function runTest(aCollation, aConn) 1.203 +{ 1.204 + ensureResultsAreCorrect(getResults(aCollation, aConn), 1.205 + gStrings.slice(0).sort(localeCompare(aCollation))); 1.206 +} 1.207 + 1.208 +/** 1.209 + * Gets the results from the UTF-8 database using the given collation and 1.210 + * ensures that they match gStrings sorted by the same collation. 1.211 + * 1.212 + * @param aCollation 1.213 + * The name of one of our custom locale collations. The rows from the 1.214 + * database and the expected results are ordered by this collation. 1.215 + */ 1.216 +function runUtf8Test(aCollation) 1.217 +{ 1.218 + runTest(aCollation, getOpenedDatabase()); 1.219 +} 1.220 + 1.221 +/** 1.222 + * Gets the results from the UTF-16 database using the given collation and 1.223 + * ensures that they match gStrings sorted by the same collation. 1.224 + * 1.225 + * @param aCollation 1.226 + * The name of one of our custom locale collations. The rows from the 1.227 + * database and the expected results are ordered by this collation. 1.228 + */ 1.229 +function runUtf16Test(aCollation) 1.230 +{ 1.231 + runTest(aCollation, gUtf16Conn); 1.232 +} 1.233 + 1.234 +/** 1.235 + * Sets up the test suite. 1.236 + */ 1.237 +function setup() 1.238 +{ 1.239 + print("-- Setting up the test_locale_collation.js suite."); 1.240 + 1.241 + gStrings = readTestData(); 1.242 + 1.243 + initTableWithStrings(gStrings, getOpenedDatabase()); 1.244 + 1.245 + gUtf16Conn = createUtf16Database(); 1.246 + initTableWithStrings(gStrings, gUtf16Conn); 1.247 + 1.248 + let localeSvc = Cc["@mozilla.org/intl/nslocaleservice;1"]. 1.249 + getService(Ci.nsILocaleService); 1.250 + let collFact = Cc["@mozilla.org/intl/collation-factory;1"]. 1.251 + createInstance(Ci.nsICollationFactory); 1.252 + gLocaleCollation = collFact.CreateCollation(localeSvc.getApplicationLocale()); 1.253 +} 1.254 + 1.255 +/////////////////////////////////////////////////////////////////////////////// 1.256 +//// Test Runs 1.257 + 1.258 +let gTests = [ 1.259 + { 1.260 + desc: "Case and accent sensitive UTF-8", 1.261 + run: function () runUtf8Test("locale_case_accent_sensitive") 1.262 + }, 1.263 + 1.264 + { 1.265 + desc: "Case sensitive, accent insensitive UTF-8", 1.266 + run: function () runUtf8Test("locale_case_sensitive") 1.267 + }, 1.268 + 1.269 + { 1.270 + desc: "Case insensitive, accent sensitive UTF-8", 1.271 + run: function () runUtf8Test("locale_accent_sensitive") 1.272 + }, 1.273 + 1.274 + { 1.275 + desc: "Case and accent insensitive UTF-8", 1.276 + run: function () runUtf8Test("locale") 1.277 + }, 1.278 + 1.279 + { 1.280 + desc: "Case and accent sensitive UTF-16", 1.281 + run: function () runUtf16Test("locale_case_accent_sensitive") 1.282 + }, 1.283 + 1.284 + { 1.285 + desc: "Case sensitive, accent insensitive UTF-16", 1.286 + run: function () runUtf16Test("locale_case_sensitive") 1.287 + }, 1.288 + 1.289 + { 1.290 + desc: "Case insensitive, accent sensitive UTF-16", 1.291 + run: function () runUtf16Test("locale_accent_sensitive") 1.292 + }, 1.293 + 1.294 + { 1.295 + desc: "Case and accent insensitive UTF-16", 1.296 + run: function () runUtf16Test("locale") 1.297 + }, 1.298 +]; 1.299 + 1.300 +function run_test() 1.301 +{ 1.302 + setup(); 1.303 + gTests.forEach(function (test) { 1.304 + print("-- Running test: " + test.desc); 1.305 + test.run(); 1.306 + }); 1.307 +}