tests/auto/qchar/tst_qchar.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    41 
    41 
    42 
    42 
    43 #include <QtTest/QtTest>
    43 #include <QtTest/QtTest>
    44 #include <qchar.h>
    44 #include <qchar.h>
    45 #include <qfile.h>
    45 #include <qfile.h>
       
    46 #include <qstringlist.h>
    46 #include <private/qunicodetables_p.h>
    47 #include <private/qunicodetables_p.h>
    47 #if defined(Q_OS_WINCE)
    48 #if defined(Q_OS_WINCE)
    48 #include <qcoreapplication.h>
    49 #include <qcoreapplication.h>
    49 #endif
    50 #endif
    50 
    51 
    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 {