e72af11fbbd0a1ae10db479f9cb74af576568d53
[profile/ivi/qtbase.git] / tests / auto / corelib / tools / qchar / tst_qchar.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/QtTest>
43 #include <qchar.h>
44 #include <qfile.h>
45 #include <qstringlist.h>
46 #include <private/qunicodetables_p.h>
47 #if defined(Q_OS_WINCE)
48 #include <qcoreapplication.h>
49 #endif
50
51 class tst_QChar : public QObject
52 {
53     Q_OBJECT
54 public slots:
55     void init();
56     void cleanup();
57 private slots:
58     void toUpper();
59     void toLower();
60     void toTitle();
61     void toCaseFolded();
62     void isDigit_data();
63     void isDigit();
64     void isLetter_data();
65     void isLetter();
66     void isLetterOrNumber_data();
67     void isLetterOrNumber();
68     void isPrint();
69     void isUpper();
70     void isLower();
71     void isSpace_data();
72     void isSpace();
73     void isSpaceSpecial();
74     void isTitle();
75     void category();
76     void direction();
77     void joining();
78     void combiningClass();
79     void digitValue();
80     void decomposition();
81     void lineBreakClass();
82     void normalization_data();
83     void normalization();
84     void normalization_manual();
85     void normalizationCorrections();
86     void unicodeVersion();
87 #if defined(Q_OS_WINCE)
88 private:
89     QCoreApplication* app;
90 #endif
91 };
92
93 void tst_QChar::init()
94 {
95 #if defined(Q_OS_WINCE)
96     int argc = 0;
97     app = new QCoreApplication(argc, NULL);
98 #endif
99 }
100
101 void tst_QChar::cleanup()
102 {
103 #if defined(Q_OS_WINCE)
104     delete app;
105 #endif
106 }
107
108 void tst_QChar::toUpper()
109 {
110     QVERIFY(QChar('a').toUpper() == 'A');
111     QVERIFY(QChar('A').toUpper() == 'A');
112     QVERIFY(QChar((ushort)0x1c7).toUpper().unicode() == 0x1c7);
113     QVERIFY(QChar((ushort)0x1c8).toUpper().unicode() == 0x1c7);
114     QVERIFY(QChar((ushort)0x1c9).toUpper().unicode() == 0x1c7);
115
116     QVERIFY(QChar::toUpper((ushort)'a') == 'A');
117     QVERIFY(QChar::toUpper((ushort)'A') == 'A');
118     QVERIFY(QChar::toUpper((ushort)0x1c7) == 0x1c7);
119     QVERIFY(QChar::toUpper((ushort)0x1c8) == 0x1c7);
120     QVERIFY(QChar::toUpper((ushort)0x1c9) == 0x1c7);
121
122     QVERIFY(QChar::toUpper((uint)'a') == 'A');
123     QVERIFY(QChar::toUpper((uint)'A') == 'A');
124     QVERIFY(QChar::toUpper((uint)0x1c7) == 0x1c7);
125     QVERIFY(QChar::toUpper((uint)0x1c8) == 0x1c7);
126     QVERIFY(QChar::toUpper((uint)0x1c9) == 0x1c7);
127
128     QVERIFY(QChar::toUpper((uint)0x10400) == 0x10400);
129     QVERIFY(QChar::toUpper((uint)0x10428) == 0x10400);
130
131 }
132
133 void tst_QChar::toLower()
134 {
135     QVERIFY(QChar('A').toLower() == 'a');
136     QVERIFY(QChar('a').toLower() == 'a');
137     QVERIFY(QChar((ushort)0x1c7).toLower().unicode() == 0x1c9);
138     QVERIFY(QChar((ushort)0x1c8).toLower().unicode() == 0x1c9);
139     QVERIFY(QChar((ushort)0x1c9).toLower().unicode() == 0x1c9);
140
141     QVERIFY(QChar::toLower((ushort)'a') == 'a');
142     QVERIFY(QChar::toLower((ushort)'A') == 'a');
143     QVERIFY(QChar::toLower((ushort)0x1c7) == 0x1c9);
144     QVERIFY(QChar::toLower((ushort)0x1c8) == 0x1c9);
145     QVERIFY(QChar::toLower((ushort)0x1c9) == 0x1c9);
146
147     QVERIFY(QChar::toLower((uint)'a') == 'a');
148     QVERIFY(QChar::toLower((uint)'A') == 'a');
149     QVERIFY(QChar::toLower((uint)0x1c7) == 0x1c9);
150     QVERIFY(QChar::toLower((uint)0x1c8) == 0x1c9);
151     QVERIFY(QChar::toLower((uint)0x1c9) == 0x1c9);
152
153     QVERIFY(QChar::toLower((uint)0x10400) == 0x10428);
154     QVERIFY(QChar::toLower((uint)0x10428) == 0x10428);
155 }
156
157 void tst_QChar::toTitle()
158 {
159     QVERIFY(QChar('a').toTitleCase() == 'A');
160     QVERIFY(QChar('A').toTitleCase() == 'A');
161     QVERIFY(QChar((ushort)0x1c7).toTitleCase().unicode() == 0x1c8);
162     QVERIFY(QChar((ushort)0x1c8).toTitleCase().unicode() == 0x1c8);
163     QVERIFY(QChar((ushort)0x1c9).toTitleCase().unicode() == 0x1c8);
164
165     QVERIFY(QChar::toTitleCase((ushort)'a') == 'A');
166     QVERIFY(QChar::toTitleCase((ushort)'A') == 'A');
167     QVERIFY(QChar::toTitleCase((ushort)0x1c7) == 0x1c8);
168     QVERIFY(QChar::toTitleCase((ushort)0x1c8) == 0x1c8);
169     QVERIFY(QChar::toTitleCase((ushort)0x1c9) == 0x1c8);
170
171     QVERIFY(QChar::toTitleCase((uint)'a') == 'A');
172     QVERIFY(QChar::toTitleCase((uint)'A') == 'A');
173     QVERIFY(QChar::toTitleCase((uint)0x1c7) == 0x1c8);
174     QVERIFY(QChar::toTitleCase((uint)0x1c8) == 0x1c8);
175     QVERIFY(QChar::toTitleCase((uint)0x1c9) == 0x1c8);
176
177     QVERIFY(QChar::toTitleCase((uint)0x10400) == 0x10400);
178     QVERIFY(QChar::toTitleCase((uint)0x10428) == 0x10400);
179
180 }
181
182 void tst_QChar::toCaseFolded()
183 {
184     QVERIFY(QChar('a').toCaseFolded() == 'a');
185     QVERIFY(QChar('A').toCaseFolded() == 'a');
186     QVERIFY(QChar((ushort)0x1c7).toCaseFolded().unicode() == 0x1c9);
187     QVERIFY(QChar((ushort)0x1c8).toCaseFolded().unicode() == 0x1c9);
188     QVERIFY(QChar((ushort)0x1c9).toCaseFolded().unicode() == 0x1c9);
189
190     QVERIFY(QChar::toCaseFolded((ushort)'a') == 'a');
191     QVERIFY(QChar::toCaseFolded((ushort)'A') == 'a');
192     QVERIFY(QChar::toCaseFolded((ushort)0x1c7) == 0x1c9);
193     QVERIFY(QChar::toCaseFolded((ushort)0x1c8) == 0x1c9);
194     QVERIFY(QChar::toCaseFolded((ushort)0x1c9) == 0x1c9);
195
196     QVERIFY(QChar::toCaseFolded((uint)'a') == 'a');
197     QVERIFY(QChar::toCaseFolded((uint)'A') == 'a');
198     QVERIFY(QChar::toCaseFolded((uint)0x1c7) == 0x1c9);
199     QVERIFY(QChar::toCaseFolded((uint)0x1c8) == 0x1c9);
200     QVERIFY(QChar::toCaseFolded((uint)0x1c9) == 0x1c9);
201
202     QVERIFY(QChar::toCaseFolded((uint)0x10400) == 0x10428);
203     QVERIFY(QChar::toCaseFolded((uint)0x10428) == 0x10428);
204
205     QVERIFY(QChar::toCaseFolded((ushort)0xb5) == 0x3bc);
206 }
207
208 void tst_QChar::isDigit_data()
209 {
210     QTest::addColumn<ushort>("ucs");
211     QTest::addColumn<bool>("expected");
212
213     for (ushort ucs = 0; ucs < 256; ++ucs) {
214         bool isDigit = (ucs <= '9' && ucs >= '0');
215         QString tag = QString::fromLatin1("0x%0").arg(QString::number(ucs, 16));
216         QTest::newRow(tag.toLatin1()) << ucs << isDigit;
217     }
218 }
219
220 void tst_QChar::isDigit()
221 {
222     QFETCH(ushort, ucs);
223     QFETCH(bool, expected);
224     QCOMPARE(QChar(ucs).isDigit(), expected);
225 }
226
227 static bool isExpectedLetter(ushort ucs)
228 {
229     return (ucs >= 'a' && ucs <= 'z') || (ucs >= 'A' && ucs <= 'Z')
230             || ucs == 0xAA || ucs == 0xB5 || ucs == 0xBA
231             || (ucs >= 0xC0 && ucs <= 0xD6)
232             || (ucs >= 0xD8 && ucs <= 0xF6)
233             || (ucs >= 0xF8 && ucs <= 0xFF);
234 }
235
236 void tst_QChar::isLetter_data()
237 {
238     QTest::addColumn<ushort>("ucs");
239     QTest::addColumn<bool>("expected");
240
241     for (ushort ucs = 0; ucs < 256; ++ucs) {
242         QString tag = QString::fromLatin1("0x%0").arg(QString::number(ucs, 16));
243         QTest::newRow(tag.toLatin1()) << ucs << isExpectedLetter(ucs);
244     }
245 }
246
247 void tst_QChar::isLetter()
248 {
249     QFETCH(ushort, ucs);
250     QFETCH(bool, expected);
251     QCOMPARE(QChar(ucs).isLetter(), expected);
252 }
253
254 void tst_QChar::isLetterOrNumber_data()
255 {
256     QTest::addColumn<ushort>("ucs");
257     QTest::addColumn<bool>("expected");
258
259     for (ushort ucs = 0; ucs < 256; ++ucs) {
260         bool isLetterOrNumber = isExpectedLetter(ucs)
261                 || (ucs >= '0' && ucs <= '9')
262                 || ucs == 0xB2 || ucs == 0xB3 || ucs == 0xB9
263                 || (ucs >= 0xBC && ucs <= 0xBE);
264         QString tag = QString::fromLatin1("0x%0").arg(QString::number(ucs, 16));
265         QTest::newRow(tag.toLatin1()) << ucs << isLetterOrNumber;
266     }
267 }
268
269 void tst_QChar::isLetterOrNumber()
270 {
271     QFETCH(ushort, ucs);
272     QFETCH(bool, expected);
273     QCOMPARE(QChar(ucs).isLetterOrNumber(), expected);
274 }
275
276 void tst_QChar::isPrint()
277 {
278     QVERIFY(QChar('A').isPrint());
279     QVERIFY(!QChar(0x1aff).isPrint()); // General_Gategory =Cn
280 }
281
282 void tst_QChar::isUpper()
283 {
284     QVERIFY(QChar('A').isUpper());
285     QVERIFY(QChar('Z').isUpper());
286     QVERIFY(!QChar('a').isUpper());
287     QVERIFY(!QChar('z').isUpper());
288     QVERIFY(!QChar('?').isUpper());
289     QVERIFY(QChar(0xC2).isUpper());   // A with ^
290     QVERIFY(!QChar(0xE2).isUpper());  // a with ^
291
292     for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) {
293         if (QChar::category(codepoint) == QChar::Letter_Uppercase)
294             QVERIFY(codepoint == QChar::toUpper(codepoint));
295     }
296 }
297
298 void tst_QChar::isLower()
299 {
300     QVERIFY(!QChar('A').isLower());
301     QVERIFY(!QChar('Z').isLower());
302     QVERIFY(QChar('a').isLower());
303     QVERIFY(QChar('z').isLower());
304     QVERIFY(!QChar('?').isLower());
305     QVERIFY(!QChar(0xC2).isLower());   // A with ^
306     QVERIFY(QChar(0xE2).isLower());  // a with ^
307
308     for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) {
309         if (QChar::category(codepoint) == QChar::Letter_Lowercase)
310             QVERIFY(codepoint == QChar::toLower(codepoint));
311     }
312 }
313
314 void tst_QChar::isSpace_data()
315 {
316     QTest::addColumn<ushort>("ucs");
317     QTest::addColumn<bool>("expected");
318
319     for (ushort ucs = 0; ucs < 256; ++ucs) {
320         bool isSpace = (ucs <= 0x0D && ucs >= 0x09) || ucs == 0x20 || ucs == 0xA0 || ucs == 0x85;
321         QString tag = QString::fromLatin1("0x%0").arg(QString::number(ucs, 16));
322         QTest::newRow(tag.toLatin1()) << ucs << isSpace;
323     }
324 }
325
326 void tst_QChar::isSpace()
327 {
328     QFETCH(ushort, ucs);
329     QFETCH(bool, expected);
330     QCOMPARE(QChar(ucs).isSpace(), expected);
331 }
332
333 void tst_QChar::isSpaceSpecial()
334 {
335     QVERIFY(!QChar(QChar::Null).isSpace());
336     QVERIFY(QChar(QChar::Nbsp).isSpace());
337     QVERIFY(QChar(QChar::ParagraphSeparator).isSpace());
338     QVERIFY(QChar(QChar::LineSeparator).isSpace());
339     QVERIFY(QChar(0x1680).isSpace());
340 }
341
342 void tst_QChar::isTitle()
343 {
344     for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) {
345         if (QChar::category(codepoint) == QChar::Letter_Titlecase)
346             QVERIFY(codepoint == QChar::toTitleCase(codepoint));
347     }
348 }
349
350 void tst_QChar::category()
351 {
352     QVERIFY(QChar('a').category() == QChar::Letter_Lowercase);
353     QVERIFY(QChar('A').category() == QChar::Letter_Uppercase);
354
355     QVERIFY(QChar::category((ushort)'a') == QChar::Letter_Lowercase);
356     QVERIFY(QChar::category((ushort)'A') == QChar::Letter_Uppercase);
357
358     QVERIFY(QChar::category((uint)'a') == QChar::Letter_Lowercase);
359     QVERIFY(QChar::category((uint)'A') == QChar::Letter_Uppercase);
360
361     QVERIFY(QChar::category(0xe0100u) == QChar::Mark_NonSpacing);
362     QVERIFY(QChar::category(0xeffffu) != QChar::Other_PrivateUse);
363     QVERIFY(QChar::category(0xf0000u) == QChar::Other_PrivateUse);
364     QVERIFY(QChar::category(0xf0001u) == QChar::Other_PrivateUse);
365
366     QVERIFY(QChar::category(0xd900u) == QChar::Other_Surrogate);
367     QVERIFY(QChar::category(0xdc00u) == QChar::Other_Surrogate);
368     QVERIFY(QChar::category(0xdc01u) == QChar::Other_Surrogate);
369
370     QVERIFY(QChar::category((uint)0x1aff) == QChar::Other_NotAssigned);
371     QVERIFY(QChar::category((uint)0x10fffdu) == QChar::Other_PrivateUse);
372     QVERIFY(QChar::category((uint)0x10ffffu) == QChar::Other_NotAssigned);
373     QVERIFY(QChar::category((uint)0x110000u) == QChar::Other_NotAssigned);
374 }
375
376 void tst_QChar::direction()
377 {
378     QVERIFY(QChar('a').direction() == QChar::DirL);
379     QVERIFY(QChar('0').direction() == QChar::DirEN);
380     QVERIFY(QChar((ushort)0x627).direction() == QChar::DirAL);
381     QVERIFY(QChar((ushort)0x5d0).direction() == QChar::DirR);
382
383     QVERIFY(QChar::direction((ushort)'a') == QChar::DirL);
384     QVERIFY(QChar::direction((ushort)'0') == QChar::DirEN);
385     QVERIFY(QChar::direction((ushort)0x627) == QChar::DirAL);
386     QVERIFY(QChar::direction((ushort)0x5d0) == QChar::DirR);
387
388     QVERIFY(QChar::direction((uint)'a') == QChar::DirL);
389     QVERIFY(QChar::direction((uint)'0') == QChar::DirEN);
390     QVERIFY(QChar::direction((uint)0x627) == QChar::DirAL);
391     QVERIFY(QChar::direction((uint)0x5d0) == QChar::DirR);
392
393     QVERIFY(QChar::direction(0xE01DAu) == QChar::DirNSM);
394     QVERIFY(QChar::direction(0xf0000u) == QChar::DirL);
395     QVERIFY(QChar::direction(0xE0030u) == QChar::DirBN);
396     QVERIFY(QChar::direction(0x2FA17u) == QChar::DirL);
397 }
398
399 void tst_QChar::joining()
400 {
401     QVERIFY(QChar('a').joining() == QChar::OtherJoining);
402     QVERIFY(QChar('0').joining() == QChar::OtherJoining);
403     QVERIFY(QChar((ushort)0x627).joining() == QChar::Right);
404     QVERIFY(QChar((ushort)0x5d0).joining() == QChar::OtherJoining);
405
406     QVERIFY(QChar::joining((ushort)'a') == QChar::OtherJoining);
407     QVERIFY(QChar::joining((ushort)'0') == QChar::OtherJoining);
408     QVERIFY(QChar::joining((ushort)0x627) == QChar::Right);
409     QVERIFY(QChar::joining((ushort)0x5d0) == QChar::OtherJoining);
410
411     QVERIFY(QChar::joining((uint)'a') == QChar::OtherJoining);
412     QVERIFY(QChar::joining((uint)'0') == QChar::OtherJoining);
413     QVERIFY(QChar::joining((uint)0x627) == QChar::Right);
414     QVERIFY(QChar::joining((uint)0x5d0) == QChar::OtherJoining);
415
416     QVERIFY(QChar::joining(0xE01DAu) == QChar::OtherJoining);
417     QVERIFY(QChar::joining(0xf0000u) == QChar::OtherJoining);
418     QVERIFY(QChar::joining(0xE0030u) == QChar::OtherJoining);
419     QVERIFY(QChar::joining(0x2FA17u) == QChar::OtherJoining);
420 }
421
422 void tst_QChar::combiningClass()
423 {
424     QVERIFY(QChar('a').combiningClass() == 0);
425     QVERIFY(QChar('0').combiningClass() == 0);
426     QVERIFY(QChar((ushort)0x627).combiningClass() == 0);
427     QVERIFY(QChar((ushort)0x5d0).combiningClass() == 0);
428
429     QVERIFY(QChar::combiningClass((ushort)'a') == 0);
430     QVERIFY(QChar::combiningClass((ushort)'0') == 0);
431     QVERIFY(QChar::combiningClass((ushort)0x627) == 0);
432     QVERIFY(QChar::combiningClass((ushort)0x5d0) == 0);
433
434     QVERIFY(QChar::combiningClass((uint)'a') == 0);
435     QVERIFY(QChar::combiningClass((uint)'0') == 0);
436     QVERIFY(QChar::combiningClass((uint)0x627) == 0);
437     QVERIFY(QChar::combiningClass((uint)0x5d0) == 0);
438
439     QVERIFY(QChar::combiningClass(0xE01DAu) == 0);
440     QVERIFY(QChar::combiningClass(0xf0000u) == 0);
441     QVERIFY(QChar::combiningClass(0xE0030u) == 0);
442     QVERIFY(QChar::combiningClass(0x2FA17u) == 0);
443
444     QVERIFY(QChar::combiningClass((ushort)0x300) == 230);
445     QVERIFY(QChar::combiningClass((uint)0x300) == 230);
446
447     QVERIFY(QChar::combiningClass((uint)0x1d244) == 230);
448
449 }
450
451 void tst_QChar::unicodeVersion()
452 {
453     QVERIFY(QChar('a').unicodeVersion() == QChar::Unicode_1_1);
454     QVERIFY(QChar('0').unicodeVersion() == QChar::Unicode_1_1);
455     QVERIFY(QChar((ushort)0x627).unicodeVersion() == QChar::Unicode_1_1);
456     QVERIFY(QChar((ushort)0x5d0).unicodeVersion() == QChar::Unicode_1_1);
457
458     QVERIFY(QChar::unicodeVersion((ushort)'a') == QChar::Unicode_1_1);
459     QVERIFY(QChar::unicodeVersion((ushort)'0') == QChar::Unicode_1_1);
460     QVERIFY(QChar::unicodeVersion((ushort)0x627) == QChar::Unicode_1_1);
461     QVERIFY(QChar::unicodeVersion((ushort)0x5d0) == QChar::Unicode_1_1);
462
463     QVERIFY(QChar::unicodeVersion((uint)'a') == QChar::Unicode_1_1);
464     QVERIFY(QChar::unicodeVersion((uint)'0') == QChar::Unicode_1_1);
465     QVERIFY(QChar::unicodeVersion((uint)0x627) == QChar::Unicode_1_1);
466     QVERIFY(QChar::unicodeVersion((uint)0x5d0) == QChar::Unicode_1_1);
467
468     QVERIFY(QChar(0x0591).unicodeVersion() == QChar::Unicode_2_0);
469     QVERIFY(QChar::unicodeVersion((ushort)0x0591) == QChar::Unicode_2_0);
470     QVERIFY(QChar::unicodeVersion((uint)0x0591) == QChar::Unicode_2_0);
471
472     QVERIFY(QChar(0x20AC).unicodeVersion() == QChar::Unicode_2_1_2);
473     QVERIFY(QChar::unicodeVersion((ushort)0x020AC) == QChar::Unicode_2_1_2);
474     QVERIFY(QChar::unicodeVersion((uint)0x20AC) == QChar::Unicode_2_1_2);
475     QVERIFY(QChar(0xfffc).unicodeVersion() == QChar::Unicode_2_1_2);
476     QVERIFY(QChar::unicodeVersion((ushort)0x0fffc) == QChar::Unicode_2_1_2);
477     QVERIFY(QChar::unicodeVersion((uint)0xfffc) == QChar::Unicode_2_1_2);
478
479     QVERIFY(QChar(0x01f6).unicodeVersion() == QChar::Unicode_3_0);
480     QVERIFY(QChar::unicodeVersion((ushort)0x01f6) == QChar::Unicode_3_0);
481     QVERIFY(QChar::unicodeVersion((uint)0x01f6) == QChar::Unicode_3_0);
482
483     QVERIFY(QChar(0x03F4).unicodeVersion() == QChar::Unicode_3_1);
484     QVERIFY(QChar::unicodeVersion((ushort)0x03F4) == QChar::Unicode_3_1);
485     QVERIFY(QChar::unicodeVersion((uint)0x03F4) == QChar::Unicode_3_1);
486     QVERIFY(QChar::unicodeVersion((uint)0x10300) == QChar::Unicode_3_1);
487
488     QVERIFY(QChar(0x0220).unicodeVersion() == QChar::Unicode_3_2);
489     QVERIFY(QChar::unicodeVersion((ushort)0x0220) == QChar::Unicode_3_2);
490     QVERIFY(QChar::unicodeVersion((uint)0x0220) == QChar::Unicode_3_2);
491     QVERIFY(QChar::unicodeVersion((uint)0xFF5F) == QChar::Unicode_3_2);
492
493     QVERIFY(QChar(0x0221).unicodeVersion() == QChar::Unicode_4_0);
494     QVERIFY(QChar::unicodeVersion((ushort)0x0221) == QChar::Unicode_4_0);
495     QVERIFY(QChar::unicodeVersion((uint)0x0221) == QChar::Unicode_4_0);
496     QVERIFY(QChar::unicodeVersion((uint)0x10000) == QChar::Unicode_4_0);
497
498     QVERIFY(QChar(0x0237).unicodeVersion() == QChar::Unicode_4_1);
499     QVERIFY(QChar::unicodeVersion((ushort)0x0237) == QChar::Unicode_4_1);
500     QVERIFY(QChar::unicodeVersion((uint)0x0237) == QChar::Unicode_4_1);
501     QVERIFY(QChar::unicodeVersion((uint)0x10140) == QChar::Unicode_4_1);
502
503     QVERIFY(QChar(0x0242).unicodeVersion() == QChar::Unicode_5_0);
504     QVERIFY(QChar::unicodeVersion((ushort)0x0242) == QChar::Unicode_5_0);
505     QVERIFY(QChar::unicodeVersion((uint)0x0242) == QChar::Unicode_5_0);
506     QVERIFY(QChar::unicodeVersion((uint)0x12000) == QChar::Unicode_5_0);
507
508 }
509
510
511 void tst_QChar::digitValue()
512 {
513     QVERIFY(QChar('9').digitValue() == 9);
514     QVERIFY(QChar('0').digitValue() == 0);
515     QVERIFY(QChar('a').digitValue() == -1);
516
517     QVERIFY(QChar::digitValue((ushort)'9') == 9);
518     QVERIFY(QChar::digitValue((ushort)'0') == 0);
519     QVERIFY(QChar::digitValue((uint)'9') == 9);
520     QVERIFY(QChar::digitValue((uint)'0') == 0);
521
522     QVERIFY(QChar::digitValue((ushort)0x1049) == 9);
523     QVERIFY(QChar::digitValue((ushort)0x1040) == 0);
524     QVERIFY(QChar::digitValue((uint)0x1049) == 9);
525     QVERIFY(QChar::digitValue((uint)0x1040) == 0);
526 }
527
528 void tst_QChar::decomposition()
529 {
530     QVERIFY(QChar((ushort)0xa0).decompositionTag() == QChar::NoBreak);
531     QVERIFY(QChar((ushort)0xa8).decompositionTag() == QChar::Compat);
532     QVERIFY(QChar((ushort)0x41).decompositionTag() == QChar::NoDecomposition);
533
534     QVERIFY(QChar::decompositionTag(0xa0) == QChar::NoBreak);
535     QVERIFY(QChar::decompositionTag(0xa8) == QChar::Compat);
536     QVERIFY(QChar::decompositionTag(0x41) == QChar::NoDecomposition);
537
538     QVERIFY(QChar::decomposition(0xa0) == QString(QChar(0x20)));
539     QVERIFY(QChar::decomposition(0xc0) == (QString(QChar(0x41)) + QString(QChar(0x300))));
540
541     {
542         QString str;
543         str += QChar( (0x1D157 - 0x10000) / 0x400 + 0xd800 );
544         str += QChar( ((0x1D157 - 0x10000) % 0x400) + 0xdc00 );
545         str += QChar( (0x1D165 - 0x10000) / 0x400 + 0xd800 );
546         str += QChar( ((0x1D165 - 0x10000) % 0x400) + 0xdc00 );
547         QVERIFY(QChar::decomposition(0x1D15e) == str);
548     }
549
550     {
551         QString str;
552         str += QChar(0x1100);
553         str += QChar(0x1161);
554         QVERIFY(QChar::decomposition(0xac00) == str);
555     }
556     {
557         QString str;
558         str += QChar(0x110c);
559         str += QChar(0x1165);
560         str += QChar(0x11b7);
561         QVERIFY(QChar::decomposition(0xc810) == str);
562     }
563 }
564
565 void tst_QChar::lineBreakClass()
566 {
567     QVERIFY(QUnicodeTables::lineBreakClass(0x0041u) == QUnicodeTables::LineBreak_AL);
568     QVERIFY(QUnicodeTables::lineBreakClass(0x0033u) == QUnicodeTables::LineBreak_NU);
569     QVERIFY(QUnicodeTables::lineBreakClass(0xe0164u) == QUnicodeTables::LineBreak_CM);
570     QVERIFY(QUnicodeTables::lineBreakClass(0x2f9a4u) == QUnicodeTables::LineBreak_ID);
571     QVERIFY(QUnicodeTables::lineBreakClass(0x10000u) == QUnicodeTables::LineBreak_AL);
572     QVERIFY(QUnicodeTables::lineBreakClass(0x0fffdu) == QUnicodeTables::LineBreak_AL);
573 }
574
575 void tst_QChar::normalization_data()
576 {
577     QTest::addColumn<QStringList>("columns");
578     QTest::addColumn<int>("part");
579
580     int linenum = 0;
581     int part = 0;
582
583     QString testFile = QFINDTESTDATA("NormalizationTest.txt");
584     QVERIFY2(!testFile.isEmpty(), "NormalizationTest.txt not found!");
585     QFile f(testFile);
586     QVERIFY(f.exists());
587
588     f.open(QIODevice::ReadOnly);
589
590     while (!f.atEnd()) {
591         linenum++;
592
593         QByteArray line;
594         line.resize(1024);
595         int len = f.readLine(line.data(), 1024);
596         line.resize(len-1);
597
598         int comment = line.indexOf('#');
599         if (comment >= 0)
600             line = line.left(comment);
601
602         if (line.startsWith("@")) {
603             if (line.startsWith("@Part") && line.size() > 5 && QChar(line.at(5)).isDigit())
604                 part = QChar(line.at(5)).digitValue();
605             continue;
606         }
607
608         if (line.isEmpty())
609             continue;
610
611         line = line.trimmed();
612         if (line.endsWith(';'))
613             line.truncate(line.length()-1);
614
615         QList<QByteArray> l = line.split(';');
616
617         QCOMPARE(l.size(), 5);
618
619         QStringList columns;
620         for (int i = 0; i < 5; ++i) {
621             columns.append(QString());
622
623             QList<QByteArray> c = l.at(i).split(' ');
624             QVERIFY(!c.isEmpty());
625
626             for (int j = 0; j < c.size(); ++j) {
627                 bool ok;
628                 uint uc = c.at(j).toInt(&ok, 16);
629                 if (uc < 0x10000)
630                     columns[i].append(QChar(uc));
631                 else {
632                     // convert to utf16
633                     ushort high = QChar::highSurrogate(uc);
634                     ushort low = QChar::lowSurrogate(uc);
635                     columns[i].append(QChar(high));
636                     columns[i].append(QChar(low));
637                 }
638             }
639         }
640
641         QString nm = QString("line #%1:").arg(linenum);
642         QTest::newRow(nm.toLatin1()) << columns << part;
643     }
644 }
645
646 void tst_QChar::normalization()
647 {
648     QFETCH(QStringList, columns);
649     QFETCH(int, part);
650
651     Q_UNUSED(part)
652
653         // CONFORMANCE:
654         // 1. The following invariants must be true for all conformant implementations
655         //
656         //    NFC
657         //      c2 ==  NFC(c1) ==  NFC(c2) ==  NFC(c3)
658         //      c4 ==  NFC(c4) ==  NFC(c5)
659
660         QVERIFY(columns[1] == columns[0].normalized(QString::NormalizationForm_C));
661         QVERIFY(columns[1] == columns[1].normalized(QString::NormalizationForm_C));
662         QVERIFY(columns[1] == columns[2].normalized(QString::NormalizationForm_C));
663         QVERIFY(columns[3] == columns[3].normalized(QString::NormalizationForm_C));
664         QVERIFY(columns[3] == columns[4].normalized(QString::NormalizationForm_C));
665
666         //    NFD
667         //      c3 ==  NFD(c1) ==  NFD(c2) ==  NFD(c3)
668         //      c5 ==  NFD(c4) ==  NFD(c5)
669
670         QVERIFY(columns[2] == columns[0].normalized(QString::NormalizationForm_D));
671         QVERIFY(columns[2] == columns[1].normalized(QString::NormalizationForm_D));
672         QVERIFY(columns[2] == columns[2].normalized(QString::NormalizationForm_D));
673         QVERIFY(columns[4] == columns[3].normalized(QString::NormalizationForm_D));
674         QVERIFY(columns[4] == columns[4].normalized(QString::NormalizationForm_D));
675
676         //    NFKC
677         //      c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
678
679         QVERIFY(columns[3] == columns[0].normalized(QString::NormalizationForm_KC));
680         QVERIFY(columns[3] == columns[1].normalized(QString::NormalizationForm_KC));
681         QVERIFY(columns[3] == columns[2].normalized(QString::NormalizationForm_KC));
682         QVERIFY(columns[3] == columns[3].normalized(QString::NormalizationForm_KC));
683         QVERIFY(columns[3] == columns[4].normalized(QString::NormalizationForm_KC));
684
685         //    NFKD
686         //      c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
687
688         QVERIFY(columns[4] == columns[0].normalized(QString::NormalizationForm_KD));
689         QVERIFY(columns[4] == columns[1].normalized(QString::NormalizationForm_KD));
690         QVERIFY(columns[4] == columns[2].normalized(QString::NormalizationForm_KD));
691         QVERIFY(columns[4] == columns[3].normalized(QString::NormalizationForm_KD));
692         QVERIFY(columns[4] == columns[4].normalized(QString::NormalizationForm_KD));
693
694         // 2. For every code point X assigned in this version of Unicode that is not specifically
695         //    listed in Part 1, the following invariants must be true for all conformant
696         //    implementations:
697         //
698         //      X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X)
699
700         // #################
701
702 }
703
704 void tst_QChar::normalization_manual()
705 {
706     {
707         QString composed;
708         composed += QChar(0xc0);
709         QString decomposed;
710         decomposed += QChar(0x41);
711         decomposed += QChar(0x300);
712
713         QVERIFY(composed.normalized(QString::NormalizationForm_D) == decomposed);
714         QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
715         QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
716         QVERIFY(composed.normalized(QString::NormalizationForm_KC) == composed);
717     }
718     {
719         QString composed;
720         composed += QChar(0xa0);
721         QString decomposed;
722         decomposed += QChar(0x20);
723
724         QVERIFY(composed.normalized(QString::NormalizationForm_D) == composed);
725         QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed);
726         QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed);
727         QVERIFY(composed.normalized(QString::NormalizationForm_KC) == decomposed);
728     }
729 }
730
731 void tst_QChar::normalizationCorrections()
732 {
733     QString s;
734     s.append(QChar(0xf951));
735
736     QString n = s.normalized(QString::NormalizationForm_D);
737     QString res;
738     res.append(QChar(0x964b));
739     QCOMPARE(n, res);
740
741     n = s.normalized(QString::NormalizationForm_D, QChar::Unicode_3_1);
742     res.clear();
743     res.append(QChar(0x96fb));
744     QCOMPARE(n, res);
745
746     s.clear();
747     s += QChar(QChar::highSurrogate(0x2f868));
748     s += QChar(QChar::lowSurrogate(0x2f868));
749
750     n = s.normalized(QString::NormalizationForm_C);
751     res.clear();
752     res += QChar(0x36fc);
753     QCOMPARE(n, res);
754
755     n = s.normalized(QString::NormalizationForm_C, QChar::Unicode_3_1);
756     res.clear();
757     res += QChar(0xd844);
758     res += QChar(0xdf6a);
759     QCOMPARE(n, res);
760
761     n = s.normalized(QString::NormalizationForm_C, QChar::Unicode_3_2);
762     QCOMPARE(n, res);
763 }
764
765
766 QTEST_APPLESS_MAIN(tst_QChar)
767 #include "tst_qchar.moc"