70 private slots: |
71 private slots: |
71 void toUpper(); |
72 void toUpper(); |
72 void toLower(); |
73 void toLower(); |
73 void toTitle(); |
74 void toTitle(); |
74 void toCaseFolded(); |
75 void toCaseFolded(); |
|
76 void isPrint(); |
75 void isUpper(); |
77 void isUpper(); |
76 void isLower(); |
78 void isLower(); |
|
79 void isTitle(); |
77 void category(); |
80 void category(); |
78 void direction(); |
81 void direction(); |
79 void joining(); |
82 void joining(); |
80 void combiningClass(); |
83 void combiningClass(); |
81 void digitValue(); |
84 void digitValue(); |
82 void decomposition(); |
85 void decomposition(); |
83 // void ligature(); |
86 // void ligature(); |
84 void lineBreakClass(); |
87 void lineBreakClass(); |
|
88 void normalization_data(); |
85 void normalization(); |
89 void normalization(); |
|
90 void normalization_manual(); |
86 void normalizationCorrections(); |
91 void normalizationCorrections(); |
87 void unicodeVersion(); |
92 void unicodeVersion(); |
88 #if defined(Q_OS_WINCE) |
93 #if defined(Q_OS_WINCE) |
89 private: |
94 private: |
90 QCoreApplication* app; |
95 QCoreApplication* app; |
216 QVERIFY(QChar::toCaseFolded((uint)0x10428) == 0x10428); |
221 QVERIFY(QChar::toCaseFolded((uint)0x10428) == 0x10428); |
217 |
222 |
218 QVERIFY(QChar::toCaseFolded((ushort)0xb5) == 0x3bc); |
223 QVERIFY(QChar::toCaseFolded((ushort)0xb5) == 0x3bc); |
219 } |
224 } |
220 |
225 |
|
226 void tst_QChar::isPrint() |
|
227 { |
|
228 QVERIFY(QChar('A').isPrint()); |
|
229 QVERIFY(!QChar(0x1aff).isPrint()); // General_Gategory =Cn |
|
230 } |
|
231 |
221 void tst_QChar::isUpper() |
232 void tst_QChar::isUpper() |
222 { |
233 { |
223 QVERIFY(QChar('A').isUpper()); |
234 QVERIFY(QChar('A').isUpper()); |
224 QVERIFY(QChar('Z').isUpper()); |
235 QVERIFY(QChar('Z').isUpper()); |
225 QVERIFY(!QChar('a').isUpper()); |
236 QVERIFY(!QChar('a').isUpper()); |
226 QVERIFY(!QChar('z').isUpper()); |
237 QVERIFY(!QChar('z').isUpper()); |
227 QVERIFY(!QChar('?').isUpper()); |
238 QVERIFY(!QChar('?').isUpper()); |
228 QVERIFY(QChar(0xC2).isUpper()); // A with ^ |
239 QVERIFY(QChar(0xC2).isUpper()); // A with ^ |
229 QVERIFY(!QChar(0xE2).isUpper()); // a with ^ |
240 QVERIFY(!QChar(0xE2).isUpper()); // a with ^ |
|
241 |
|
242 for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) { |
|
243 if (QChar::category(codepoint) == QChar::Letter_Uppercase) |
|
244 QVERIFY(codepoint == QChar::toUpper(codepoint)); |
|
245 } |
230 } |
246 } |
231 |
247 |
232 void tst_QChar::isLower() |
248 void tst_QChar::isLower() |
233 { |
249 { |
234 QVERIFY(!QChar('A').isLower()); |
250 QVERIFY(!QChar('A').isLower()); |
236 QVERIFY(QChar('a').isLower()); |
252 QVERIFY(QChar('a').isLower()); |
237 QVERIFY(QChar('z').isLower()); |
253 QVERIFY(QChar('z').isLower()); |
238 QVERIFY(!QChar('?').isLower()); |
254 QVERIFY(!QChar('?').isLower()); |
239 QVERIFY(!QChar(0xC2).isLower()); // A with ^ |
255 QVERIFY(!QChar(0xC2).isLower()); // A with ^ |
240 QVERIFY(QChar(0xE2).isLower()); // a with ^ |
256 QVERIFY(QChar(0xE2).isLower()); // a with ^ |
|
257 |
|
258 for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) { |
|
259 if (QChar::category(codepoint) == QChar::Letter_Lowercase) |
|
260 QVERIFY(codepoint == QChar::toLower(codepoint)); |
|
261 } |
|
262 } |
|
263 |
|
264 void tst_QChar::isTitle() |
|
265 { |
|
266 for (uint codepoint = 0; codepoint <= UNICODE_LAST_CODEPOINT; ++codepoint) { |
|
267 if (QChar::category(codepoint) == QChar::Letter_Titlecase) |
|
268 QVERIFY(codepoint == QChar::toTitleCase(codepoint)); |
|
269 } |
241 } |
270 } |
242 |
271 |
243 void tst_QChar::category() |
272 void tst_QChar::category() |
244 { |
273 { |
245 QVERIFY(QChar('a').category() == QChar::Letter_Lowercase); |
274 QVERIFY(QChar('a').category() == QChar::Letter_Lowercase); |
257 QVERIFY(QChar::category(0xf0001u) == QChar::Other_PrivateUse); |
286 QVERIFY(QChar::category(0xf0001u) == QChar::Other_PrivateUse); |
258 |
287 |
259 QVERIFY(QChar::category(0xd900u) == QChar::Other_Surrogate); |
288 QVERIFY(QChar::category(0xd900u) == QChar::Other_Surrogate); |
260 QVERIFY(QChar::category(0xdc00u) == QChar::Other_Surrogate); |
289 QVERIFY(QChar::category(0xdc00u) == QChar::Other_Surrogate); |
261 QVERIFY(QChar::category(0xdc01u) == QChar::Other_Surrogate); |
290 QVERIFY(QChar::category(0xdc01u) == QChar::Other_Surrogate); |
|
291 |
|
292 QVERIFY(QChar::category((uint)0x10fffdu) == QChar::Other_PrivateUse); |
|
293 QVERIFY(QChar::category((uint)0x110000u) == QChar::NoCategory); |
|
294 |
|
295 QVERIFY(QChar::category((uint)0x1aff) == QChar::Other_NotAssigned); |
|
296 QVERIFY(QChar::category((uint)0x10ffffu) == QChar::Other_NotAssigned); |
262 } |
297 } |
263 |
298 |
264 void tst_QChar::direction() |
299 void tst_QChar::direction() |
265 { |
300 { |
266 QVERIFY(QChar('a').direction() == QChar::DirL); |
301 QVERIFY(QChar('a').direction() == QChar::DirL); |
471 QVERIFY(QUnicodeTables::lineBreakClass(0x2f9a4u) == QUnicodeTables::LineBreak_ID); |
506 QVERIFY(QUnicodeTables::lineBreakClass(0x2f9a4u) == QUnicodeTables::LineBreak_ID); |
472 QVERIFY(QUnicodeTables::lineBreakClass(0x10000u) == QUnicodeTables::LineBreak_AL); |
507 QVERIFY(QUnicodeTables::lineBreakClass(0x10000u) == QUnicodeTables::LineBreak_AL); |
473 QVERIFY(QUnicodeTables::lineBreakClass(0x0fffdu) == QUnicodeTables::LineBreak_AL); |
508 QVERIFY(QUnicodeTables::lineBreakClass(0x0fffdu) == QUnicodeTables::LineBreak_AL); |
474 } |
509 } |
475 |
510 |
476 void tst_QChar::normalization() |
511 void tst_QChar::normalization_data() |
477 { |
512 { |
478 { |
513 QTest::addColumn<QStringList>("columns"); |
479 QString composed; |
514 QTest::addColumn<int>("part"); |
480 composed += QChar(0xc0); |
515 |
481 QString decomposed; |
516 int linenum = 0; |
482 decomposed += QChar(0x41); |
517 int part = 0; |
483 decomposed += QChar(0x300); |
518 |
484 |
519 QFile f(SRCDIR "NormalizationTest.txt"); |
485 QVERIFY(composed.normalized(QString::NormalizationForm_D) == decomposed); |
520 QVERIFY(f.exists()); |
486 QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed); |
|
487 QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed); |
|
488 QVERIFY(composed.normalized(QString::NormalizationForm_KC) == composed); |
|
489 } |
|
490 { |
|
491 QString composed; |
|
492 composed += QChar(0xa0); |
|
493 QString decomposed; |
|
494 decomposed += QChar(0x20); |
|
495 |
|
496 QVERIFY(composed.normalized(QString::NormalizationForm_D) == composed); |
|
497 QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed); |
|
498 QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed); |
|
499 QVERIFY(composed.normalized(QString::NormalizationForm_KC) == decomposed); |
|
500 } |
|
501 |
|
502 QFile f("NormalizationTest.txt"); |
|
503 // Windows - current directory is the debug/release subdirectory where the executable is located |
|
504 if (!f.exists()) |
|
505 f.setFileName("../NormalizationTest.txt");; |
|
506 if (!f.exists()) { |
|
507 QFAIL("Couldn't find NormalizationTest.txt"); |
|
508 return; |
|
509 } |
|
510 |
521 |
511 f.open(QIODevice::ReadOnly); |
522 f.open(QIODevice::ReadOnly); |
512 |
523 |
513 while (!f.atEnd()) { |
524 while (!f.atEnd()) { |
|
525 linenum++; |
|
526 |
514 QByteArray line; |
527 QByteArray line; |
515 line.resize(1024); |
528 line.resize(1024); |
516 int len = f.readLine(line.data(), 1024); |
529 int len = f.readLine(line.data(), 1024); |
517 line.resize(len-1); |
530 line.resize(len-1); |
518 |
531 |
519 int comment = line.indexOf('#'); |
532 int comment = line.indexOf('#'); |
520 if (comment >= 0) |
533 if (comment >= 0) |
521 line = line.left(comment); |
534 line = line.left(comment); |
522 |
535 |
523 if (line.startsWith("@")) |
536 if (line.startsWith("@")) { |
|
537 if (line.startsWith("@Part") && line.size() > 5 && QChar(line.at(5)).isDigit()) |
|
538 part = QChar(line.at(5)).digitValue(); |
524 continue; |
539 continue; |
|
540 } |
525 |
541 |
526 if (line.isEmpty()) |
542 if (line.isEmpty()) |
527 continue; |
543 continue; |
528 |
544 |
529 line = line.trimmed(); |
545 line = line.trimmed(); |
532 |
548 |
533 QList<QByteArray> l = line.split(';'); |
549 QList<QByteArray> l = line.split(';'); |
534 |
550 |
535 Q_ASSERT(l.size() == 5); |
551 Q_ASSERT(l.size() == 5); |
536 |
552 |
537 QString columns[5]; |
553 QStringList columns; |
538 for (int i = 0; i < 5; ++i) { |
554 for (int i = 0; i < 5; ++i) { |
|
555 columns.append(QString()); |
|
556 |
539 QList<QByteArray> c = l.at(i).split(' '); |
557 QList<QByteArray> c = l.at(i).split(' '); |
540 Q_ASSERT(!c.isEmpty()); |
558 Q_ASSERT(!c.isEmpty()); |
541 |
559 |
542 for (int j = 0; j < c.size(); ++j) { |
560 for (int j = 0; j < c.size(); ++j) { |
543 bool ok; |
561 bool ok; |
544 uint uc = c.at(j).toInt(&ok, 16); |
562 uint uc = c.at(j).toInt(&ok, 16); |
545 if (uc < 0x10000) |
563 if (uc < 0x10000) |
546 columns[i].append(QChar(uc)); |
564 columns[i].append(QChar(uc)); |
547 else { |
565 else { |
548 // convert to utf16 |
566 // convert to utf16 |
549 uc -= 0x10000; |
567 ushort high = QChar::highSurrogate(uc); |
550 ushort high = uc/0x400 + 0xd800; |
568 ushort low = QChar::lowSurrogate(uc); |
551 ushort low = uc%0x400 + 0xdc00; |
|
552 columns[i].append(QChar(high)); |
569 columns[i].append(QChar(high)); |
553 columns[i].append(QChar(low)); |
570 columns[i].append(QChar(low)); |
554 } |
571 } |
555 } |
572 } |
556 } |
573 } |
|
574 |
|
575 QString nm = QString("line #%1:").arg(linenum); |
|
576 QTest::newRow(nm.toLatin1()) << columns << part; |
|
577 } |
|
578 } |
|
579 |
|
580 void tst_QChar::normalization() |
|
581 { |
|
582 QFETCH(QStringList, columns); |
|
583 QFETCH(int, part); |
|
584 |
|
585 Q_UNUSED(part) |
557 |
586 |
558 // CONFORMANCE: |
587 // CONFORMANCE: |
559 // 1. The following invariants must be true for all conformant implementations |
588 // 1. The following invariants must be true for all conformant implementations |
560 // |
589 // |
561 // NFC |
590 // NFC |
602 // |
631 // |
603 // X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X) |
632 // X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X) |
604 |
633 |
605 // ################# |
634 // ################# |
606 |
635 |
|
636 } |
|
637 |
|
638 void tst_QChar::normalization_manual() |
|
639 { |
|
640 { |
|
641 QString composed; |
|
642 composed += QChar(0xc0); |
|
643 QString decomposed; |
|
644 decomposed += QChar(0x41); |
|
645 decomposed += QChar(0x300); |
|
646 |
|
647 QVERIFY(composed.normalized(QString::NormalizationForm_D) == decomposed); |
|
648 QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed); |
|
649 QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed); |
|
650 QVERIFY(composed.normalized(QString::NormalizationForm_KC) == composed); |
|
651 } |
|
652 { |
|
653 QString composed; |
|
654 composed += QChar(0xa0); |
|
655 QString decomposed; |
|
656 decomposed += QChar(0x20); |
|
657 |
|
658 QVERIFY(composed.normalized(QString::NormalizationForm_D) == composed); |
|
659 QVERIFY(composed.normalized(QString::NormalizationForm_C) == composed); |
|
660 QVERIFY(composed.normalized(QString::NormalizationForm_KD) == decomposed); |
|
661 QVERIFY(composed.normalized(QString::NormalizationForm_KC) == decomposed); |
607 } |
662 } |
608 } |
663 } |
609 |
664 |
610 void tst_QChar::normalizationCorrections() |
665 void tst_QChar::normalizationCorrections() |
611 { |
666 { |