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