qtmobility/tests/auto/qversitreader/tst_qversitreader.cpp
changeset 8 71781823f776
parent 5 453da2cfceef
child 11 06b8e2af4411
equal deleted inserted replaced
5:453da2cfceef 8:71781823f776
    39 **
    39 **
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 
    41 
    42 #include "tst_qversitreader.h"
    42 #include "tst_qversitreader.h"
    43 #include "qversitreader.h"
    43 #include "qversitreader.h"
       
    44 #include "qversitproperty.h"
       
    45 #ifdef QT_BUILD_INTERNAL
    44 #include "qversitreader_p.h"
    46 #include "qversitreader_p.h"
    45 #include "versitutils_p.h"
    47 #include "versitutils_p.h"
       
    48 #endif
    46 #include <QtTest/QtTest>
    49 #include <QtTest/QtTest>
    47 #include <QSignalSpy>
    50 #include <QSignalSpy>
    48 
    51 
    49 // Copied from tst_qcontactmanager.cpp
    52 // Copied from tst_qcontactmanager.cpp
    50 // Waits until __expr is true and fails if it doesn't happen within 5s.
    53 // Waits until __expr is true and fails if it doesn't happen within 5s.
    64 #endif
    67 #endif
    65 
    68 
    66 // This says "NOKIA" in Katakana encoded with UTF-8
    69 // This says "NOKIA" in Katakana encoded with UTF-8
    67 const QByteArray KATAKANA_NOKIA("\xe3\x83\x8e\xe3\x82\xad\xe3\x82\xa2");
    70 const QByteArray KATAKANA_NOKIA("\xe3\x83\x8e\xe3\x82\xad\xe3\x82\xa2");
    68 
    71 
       
    72 Q_DECLARE_METATYPE(QVersitDocument::VersitType);
       
    73 Q_DECLARE_METATYPE(QVersitProperty);
       
    74 
    69 QTM_USE_NAMESPACE
    75 QTM_USE_NAMESPACE
    70 
    76 
    71 void tst_QVersitReader::init()
    77 void tst_QVersitReader::init()
    72 {
    78 {
    73     mInputDevice = new QBuffer;
    79     mInputDevice = new QBuffer;
    74     mInputDevice->open(QBuffer::ReadWrite);
    80     mInputDevice->open(QBuffer::ReadWrite);
    75     mReader = new QVersitReader;
    81     mReader = new QVersitReader;
       
    82 #ifdef QT_BUILD_INTERNAL    
    76     mReaderPrivate = new QVersitReaderPrivate;
    83     mReaderPrivate = new QVersitReaderPrivate;
       
    84 #endif
    77     mSignalCatcher = new SignalCatcher;
    85     mSignalCatcher = new SignalCatcher;
    78     connect(mReader, SIGNAL(stateChanged(QVersitReader::State)),
    86     connect(mReader, SIGNAL(stateChanged(QVersitReader::State)),
    79             mSignalCatcher, SLOT(stateChanged(QVersitReader::State)));
    87             mSignalCatcher, SLOT(stateChanged(QVersitReader::State)));
    80     connect(mReader, SIGNAL(resultsAvailable()),
    88     connect(mReader, SIGNAL(resultsAvailable()),
    81             mSignalCatcher, SLOT(resultsAvailable()));
    89             mSignalCatcher, SLOT(resultsAvailable()));
    82     mAsciiCodec = QTextCodec::codecForName("ISO 8859-1");
    90     mAsciiCodec = QTextCodec::codecForName("ISO 8859-1");
    83 }
    91 }
    84 
    92 
    85 void tst_QVersitReader::cleanup()
    93 void tst_QVersitReader::cleanup()
    86 {
    94 {
       
    95 #ifdef QT_BUILD_INTERNAL
    87     delete mReaderPrivate;
    96     delete mReaderPrivate;
       
    97 #endif
    88     delete mReader;
    98     delete mReader;
    89     delete mInputDevice;
    99     delete mInputDevice;
    90     delete mSignalCatcher;
   100     delete mSignalCatcher;
    91 }
   101 }
    92 
   102 
   114 {
   124 {
   115     QVERIFY(mReader->defaultCodec() == QTextCodec::codecForName("UTF-8"));
   125     QVERIFY(mReader->defaultCodec() == QTextCodec::codecForName("UTF-8"));
   116     mReader->setDefaultCodec(QTextCodec::codecForName("UTF-16BE"));
   126     mReader->setDefaultCodec(QTextCodec::codecForName("UTF-16BE"));
   117     QVERIFY(mReader->defaultCodec() == QTextCodec::codecForName("UTF-16BE"));
   127     QVERIFY(mReader->defaultCodec() == QTextCodec::codecForName("UTF-16BE"));
   118 }
   128 }
       
   129 
   119 
   130 
   120 void tst_QVersitReader::testReading()
   131 void tst_QVersitReader::testReading()
   121 {
   132 {
   122     // No I/O device set
   133     // No I/O device set
   123     QVERIFY(!mReader->startReading());
   134     QVERIFY(!mReader->startReading());
   147     QCOMPARE(mReader->error(), QVersitReader::NoError);
   158     QCOMPARE(mReader->error(), QVersitReader::NoError);
   148     QCOMPARE(results.count(),1);
   159     QCOMPARE(results.count(),1);
   149 
   160 
   150     // Wide charset with no byte-order mark
   161     // Wide charset with no byte-order mark
   151     QTextCodec* codec = QTextCodec::codecForName("UTF-16BE");
   162     QTextCodec* codec = QTextCodec::codecForName("UTF-16BE");
       
   163     QTextCodec::ConverterState converterState(QTextCodec::IgnoreHeader);
       
   164     QString document = QString::fromAscii("BEGIN:VCARD\r\nVERSION:2.1\r\nFN:John\r\nEND:VCARD\r\n");
   152     const QByteArray& wideDocument =
   165     const QByteArray& wideDocument =
   153             VersitUtils::encode("BEGIN:VCARD\r\nVERSION:2.1\r\nFN:John\r\nEND:VCARD\r\n", codec);
   166         codec->fromUnicode(document.data(), document.length(), &converterState);
   154     mInputDevice->close();
   167     mInputDevice->close();
   155     mInputDevice->setData(wideDocument);
   168     mInputDevice->setData(wideDocument);
   156     mInputDevice->open(QBuffer::ReadOnly);
   169     mInputDevice->open(QBuffer::ReadOnly);
   157     mInputDevice->seek(0);
   170     mInputDevice->seek(0);
   158     mReader->setDefaultCodec(codec);
   171     mReader->setDefaultCodec(codec);
   278     QCOMPARE(mReader->results().count(),0);
   291     QCOMPARE(mReader->results().count(),0);
   279 }
   292 }
   280 
   293 
   281 void tst_QVersitReader::testSetVersionFromProperty()
   294 void tst_QVersitReader::testSetVersionFromProperty()
   282 {
   295 {
       
   296 #ifndef QT_BUILD_INTERNAL
       
   297     QSKIP("Testing private API", SkipSingle);
       
   298 #else
   283     QVersitDocument document;
   299     QVersitDocument document;
   284 
   300 
   285     // Some other property than VERSION
   301     // Some other property than VERSION
   286     QVersitProperty property;
   302     QVersitProperty property;
   287     property.setName(QString::fromAscii("N"));
   303     property.setName(QString::fromAscii("N"));
   309     QVERIFY(document.type() == QVersitDocument::VCard21Type);
   325     QVERIFY(document.type() == QVersitDocument::VCard21Type);
   310 
   326 
   311     // VERSION property with BASE64 encoded not supported value
   327     // VERSION property with BASE64 encoded not supported value
   312     property.setValue(QString::fromAscii(QByteArray("4.0").toBase64()));
   328     property.setValue(QString::fromAscii(QByteArray("4.0").toBase64()));
   313     QVERIFY(!mReaderPrivate->setVersionFromProperty(document,property));
   329     QVERIFY(!mReaderPrivate->setVersionFromProperty(document,property));
   314 }
   330 #endif
   315 
   331 }
   316 void tst_QVersitReader::testParseNextVersitPropertyVCard21()
   332 
   317 {
   333 void tst_QVersitReader::testParseNextVersitProperty()
   318     QVersitDocument::VersitType type = QVersitDocument::VCard21Type;
   334 {
   319 
   335 #ifndef QT_BUILD_INTERNAL
   320     // Test a valid vCard 2.1 with properties having separate handling:
   336     QSKIP("Testing private API", SkipSingle);
   321     // AGENT property, ENCODING parameters (BASE64 and QUOTED-PRINTABLE) and CHARSET parameter
   337 #else
   322     QTextCodec* codec = QTextCodec::codecForName("UTF-16BE");
   338     QFETCH(QVersitDocument::VersitType, documentType);
   323     QByteArray vCard("Begin:vcard\r\n");
   339     QFETCH(QByteArray, input);
   324     vCard.append("VERSION:2.1\r\n");
   340     QFETCH(QVersitProperty, expectedProperty);
   325     vCard.append("FN:John\r\n");
   341 
   326     // "NOTE:\;\,\:\\"
   342     QBuffer buffer(&input);
   327     vCard.append("NOTE:\\;\\,\\:\\\\\r\n");
       
   328     // "N:foo\;bar;foo\,bar;foo\:bar;foo\\bar;foo\\\;bar"
       
   329     vCard.append("N:foo\\;bar;foo\\,bar;foo\\:bar;foo\\\\bar;foo\\\\\\;bar\r\n");
       
   330     // missing structured value
       
   331     vCard.append("ADR:\r\n");
       
   332     // "NICKNAME:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar"
       
   333     vCard.append("NICKNAME:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n");
       
   334     // "CATEGORIES:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar"
       
   335     vCard.append("CATEGORIES:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n");
       
   336     vCard.append("ORG;CHARSET=UTF-8:");
       
   337     vCard.append(KATAKANA_NOKIA);
       
   338     vCard.append("\r\n");
       
   339     // "NOKIA" in Katakana, UTF-8 encoded, then base-64 encoded:
       
   340     vCard.append("NOTE;ENCODING=BASE64;CHARSET=UTF-8:");
       
   341     vCard.append(KATAKANA_NOKIA.toBase64());
       
   342     vCard.append("\r\n");
       
   343     // The value here is "UXQgaXMgZ3JlYXQh", which is the base64 encoding of "Qt is great!".
       
   344     vCard.append("PHOTO;ENCODING=BASE64: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n");
       
   345     // Again, but without the explicit "ENCODING" parameter
       
   346     vCard.append("PHOTO;BASE64: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n");
       
   347     vCard.append("HOME.Springfield.EMAIL;Encoding=Quoted-Printable:john.citizen=40exam=\r\nple.com\r\n");
       
   348     vCard.append("EMAIL;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-16BE:");
       
   349     vCard.append(codec->fromUnicode(QLatin1String("john.citizen=40exam=\r\nple.com")));
       
   350     vCard.append("\r\n");
       
   351     vCard.append("AGENT:\r\nBEGIN:VCARD\r\nFN:Jenny\r\nEND:VCARD\r\n\r\n");
       
   352     vCard.append("End:VCARD\r\n");
       
   353     QBuffer buffer(&vCard);
       
   354     buffer.open(QIODevice::ReadOnly);
   343     buffer.open(QIODevice::ReadOnly);
   355     LineReader lineReader(&buffer, mAsciiCodec);
   344     LineReader lineReader(&buffer, mAsciiCodec);
   356 
   345     QVersitProperty property = mReaderPrivate->parseNextVersitProperty(documentType, lineReader);
   357     QVersitProperty property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   346     if (property != expectedProperty) {
   358     QCOMPARE(property.name(),QString::fromAscii("BEGIN"));
   347         // compare each part of the property separately for easier debugging
   359     QCOMPARE(property.value(),QString::fromAscii("vcard"));
   348         QCOMPARE(property.groups(), expectedProperty.groups());
   360 
   349         QCOMPARE(property.name(), expectedProperty.name());
   361     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   350         QCOMPARE(property.valueType(), expectedProperty.valueType());
   362     QCOMPARE(property.name(),QString::fromAscii("VERSION"));
   351 
   363     QCOMPARE(property.value(),QString::fromAscii("2.1"));
   352         // QVariant doesn't support == on QVersitDocuments - do it manually
   364 
   353         if (property.variantValue().userType() == qMetaTypeId<QVersitDocument>()) {
   365     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   354             QVERIFY(expectedProperty.variantValue().userType() == qMetaTypeId<QVersitDocument>());
   366     QCOMPARE(property.name(),QString::fromAscii("FN"));
   355             QCOMPARE(property.value<QVersitDocument>(), expectedProperty.value<QVersitDocument>());
   367     QCOMPARE(property.value(),QString::fromAscii("John"));
   356         }
   368 
   357         else
   369     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   358             QCOMPARE(property.variantValue(), expectedProperty.variantValue());
   370     QCOMPARE(property.name(),QString::fromAscii("NOTE"));
   359 
   371     // Do not Unescape semicolons, commas, colons and backlashes
   360         // Don't check parameters because the reader can add random parameters of its own (like CHARSET)
   372     // "\;\,\:\\"
   361         // QCOMPARE(property.parameters(), expectedProperty.parameters());
   373     QCOMPARE(property.value(),QString::fromAscii("\\;\\,\\:\\\\"));
   362     }
   374 
   363 #endif
   375     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   364 }
   376     QCOMPARE(property.name(),QString::fromAscii("N"));
   365 
   377     QCOMPARE(property.valueType(), QVersitProperty::CompoundType);
   366 void tst_QVersitReader::testParseNextVersitProperty_data()
   378     QCOMPARE(property.variantValue().type(), QVariant::StringList);
   367 {
   379     QStringList components = property.value<QStringList>();
   368 #ifdef QT_BUILD_INTERNAL
   380     QCOMPARE(components.size(), 5);
   369     QTest::addColumn<QVersitDocument::VersitType>("documentType");
   381     QCOMPARE(components.at(0), QLatin1String("foo;bar"));
   370     QTest::addColumn<QByteArray>("input");
   382     QCOMPARE(components.at(1), QLatin1String("foo\\,bar"));
   371     QTest::addColumn<QVersitProperty>("expectedProperty");
   383     QCOMPARE(components.at(2), QLatin1String("foo\\:bar"));
   372 
   384     QCOMPARE(components.at(3), QLatin1String("foo\\\\bar"));
   373     {
   385     QCOMPARE(components.at(4), QLatin1String("foo\\\\;bar"));
   374         QVersitProperty expectedProperty;
   386 
   375         expectedProperty.setName(QLatin1String("BEGIN"));
   387     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   376         expectedProperty.setValue(QLatin1String("vcard"));
   388     QCOMPARE(property.name(),QString::fromAscii("ADR"));
   377         QTest::newRow("begin")
   389     QCOMPARE(property.valueType(), QVersitProperty::CompoundType);
   378             << QVersitDocument::VCard21Type
   390     QCOMPARE(property.variantValue().type(), QVariant::StringList);
   379             << QByteArray("Begin:vcard\r\n")
   391     components = property.value<QStringList>();
   380             << expectedProperty;
   392     QCOMPARE(components.size(), 1);
   381     }
   393     QVERIFY(components.at(0).isEmpty());
   382 
   394 
   383     {
   395     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   384         QVersitProperty expectedProperty;
   396     QCOMPARE(property.name(),QString::fromAscii("NICKNAME"));
   385         expectedProperty.setName(QLatin1String("VERSION"));
   397     QCOMPARE(property.valueType(), QVersitProperty::ListType);
   386         expectedProperty.setValue(QLatin1String("2.1"));
   398     QCOMPARE(property.variantValue().type(), QVariant::StringList);
   387         expectedProperty.setValueType(QVersitProperty::PlainType);
   399     components = property.value<QStringList>();
   388         QTest::newRow("version")
   400     QCOMPARE(components.size(), 5);
   389             << QVersitDocument::VCard21Type
   401     QCOMPARE(components.at(0), QLatin1String("foo\\;bar"));
   390             << QByteArray("VERSION:2.1\r\n")
   402     QCOMPARE(components.at(1), QLatin1String("foo,bar"));
   391             << expectedProperty;
   403     QCOMPARE(components.at(2), QLatin1String("foo\\:bar"));
   392     }
   404     QCOMPARE(components.at(3), QLatin1String("foo\\\\bar"));
   393 
   405     QCOMPARE(components.at(4), QLatin1String("foo\\\\,bar"));
   394     {
   406 
   395         QVersitProperty expectedProperty;
   407     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   396         expectedProperty.setName(QLatin1String("FN"));
   408     QCOMPARE(property.name(),QString::fromAscii("CATEGORIES"));
   397         expectedProperty.setValue(QLatin1String("John"));
   409     QCOMPARE(property.valueType(), QVersitProperty::ListType);
   398         expectedProperty.setValueType(QVersitProperty::PlainType);
   410     QCOMPARE(property.variantValue().type(), QVariant::StringList);
   399         QTest::newRow("fn")
   411     components = property.value<QStringList>();
   400             << QVersitDocument::VCard21Type
   412     QCOMPARE(components.size(), 5);
   401             << QByteArray("FN:John\r\n")
   413     QCOMPARE(components.at(0), QLatin1String("foo\\;bar"));
   402             << expectedProperty;
   414     QCOMPARE(components.at(1), QLatin1String("foo,bar"));
   403     }
   415     QCOMPARE(components.at(2), QLatin1String("foo\\:bar"));
   404 
   416     QCOMPARE(components.at(3), QLatin1String("foo\\\\bar"));
   405     {
   417     QCOMPARE(components.at(4), QLatin1String("foo\\\\,bar"));
   406         // "NOTE:\;\,\:\\"
   418 
   407         QVersitProperty expectedProperty;
   419     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   408         expectedProperty.setName(QLatin1String("NOTE"));
   420     QCOMPARE(property.name(),QString::fromAscii("ORG"));
   409         expectedProperty.setValue(QLatin1String("\\;\\,\\:\\\\"));
   421     QCOMPARE(property.value(),QString::fromUtf8(KATAKANA_NOKIA));
   410         expectedProperty.setValueType(QVersitProperty::PlainType);
   422 
   411         QTest::newRow("vcard21 note")
   423     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   412             << QVersitDocument::VCard21Type
   424     QCOMPARE(property.name(),QString::fromAscii("NOTE"));
   413             << QByteArray("NOTE:\\;\\,\\:\\\\\r\n")
   425     QCOMPARE(property.value(),QString::fromUtf8(KATAKANA_NOKIA));
   414             << expectedProperty;
   426 
   415 
   427     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   416         expectedProperty.setValue(QLatin1String(";,:\\"));
   428     QCOMPARE(property.name(),QString::fromAscii("PHOTO"));
   417         QTest::newRow("vcard30 note")
   429     // Linear whitespaces (SPACEs and TABs) removed from the value and base64 decoded:
   418             << QVersitDocument::VCard30Type
   430     QCOMPARE(property.variantValue().type(), QVariant::ByteArray);
   419             << QByteArray("NOTE:\\;\\,\\:\\\\\r\n")
   431     QCOMPARE(property.value<QByteArray>(), QByteArray("Qt is great!"));
   420             << expectedProperty;
   432     // Ensure that base-64 encoded strings can be retrieved as strings.
   421     }
   433     QCOMPARE(property.value(), QLatin1String("Qt is great!"));
   422 
   434 
   423     {
   435     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   424         // "N:foo\;bar;foo\,bar;foo\:bar;foo\\bar;foo\\\;bar"
   436     QCOMPARE(property.name(),QString::fromAscii("PHOTO"));
   425         QVersitProperty expectedProperty;
   437     QCOMPARE(property.variantValue().type(), QVariant::ByteArray);
   426         expectedProperty.setName(QLatin1String("N"));
   438     QCOMPARE(property.value<QByteArray>(), QByteArray("Qt is great!"));
   427         QStringList components;
   439     QCOMPARE(property.value(), QLatin1String("Qt is great!"));
   428         components << QLatin1String("foo;bar")
   440 
   429             << QLatin1String("foo\\,bar")
   441     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   430             << QLatin1String("foo\\:bar")
   442     QStringList propertyGroup(QString::fromAscii("HOME"));
   431             << QLatin1String("foo\\\\bar")
   443     propertyGroup.append(QString::fromAscii("Springfield"));
   432             << QLatin1String("foo\\\\;bar");
   444     QCOMPARE(property.groups(),propertyGroup);
   433         expectedProperty.setValue(components);
   445     QCOMPARE(property.name(),QString::fromAscii("EMAIL"));
   434         expectedProperty.setValueType(QVersitProperty::CompoundType);
   446     QCOMPARE(0,property.parameters().count());
   435         QTest::newRow("vcard21 n")
   447     QCOMPARE(property.value(),QString::fromAscii("john.citizen@example.com"));
   436             << QVersitDocument::VCard21Type
   448 
   437             << QByteArray("N:foo\\;bar;foo\\,bar;foo\\:bar;foo\\\\bar;foo\\\\\\;bar\r\n")
   449     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   438             << expectedProperty;
   450     QCOMPARE(property.name(),QString::fromAscii("EMAIL"));
   439 
   451     // The encoding and charset parameters should be stripped by the reader.
   440         components.clear();
   452     QCOMPARE(property.parameters().count(), 0);
   441         components << QLatin1String("foo;bar")
   453     QCOMPARE(property.value(),QString::fromAscii("john.citizen@example.com"));
   442             << QLatin1String("foo,bar")
   454 
   443             << QLatin1String("foo:bar")
   455     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   444             << QLatin1String("foo\\bar")
   456     QCOMPARE(property.name(),QString::fromAscii("AGENT"));
   445             << QLatin1String("foo\\;bar");
   457     QCOMPARE(property.value(),QString());
   446         expectedProperty.setValue(components);
   458     QVERIFY(property.variantValue().userType() == qMetaTypeId<QVersitDocument>());
   447         QTest::newRow("vcard30 n")
   459     QCOMPARE(property.value<QVersitDocument>().properties().count(), 1);
   448             << QVersitDocument::VCard30Type
   460 
   449             << QByteArray("N:foo\\;bar;foo\\,bar;foo\\:bar;foo\\\\bar;foo\\\\\\;bar\r\n")
   461     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   450             << expectedProperty;
   462     QCOMPARE(property.name(),QString::fromAscii("END"));
   451     }
   463     QCOMPARE(property.value(),QString::fromAscii("VCARD"));
   452 
   464 
   453     {
   465     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   454         QVersitProperty expectedProperty;
   466     QCOMPARE(property.name(),QString());
   455         expectedProperty.setName(QLatin1String("ADR"));
   467     QCOMPARE(property.value(),QString());
   456         expectedProperty.setValue(QStringList(QString()));
   468 
   457         expectedProperty.setValueType(QVersitProperty::CompoundType);
   469     // Simulate a situation where the document nesting level is exceeded
   458         QTest::newRow("empty structured")
   470     // In practice this would mean a big number of nested AGENT properties
   459             << QVersitDocument::VCard21Type
   471     mReaderPrivate->mDocumentNestingLevel = 20;
   460             << QByteArray("ADR:\r\n")
   472     QByteArray agentProperty("AGENT:BEGIN:VCARD\r\nN:Jenny\r\nEND:VCARD\r\n\r\n");
   461             << expectedProperty;
   473     buffer.close();
   462     }
   474     buffer.setData(agentProperty);
   463 
   475     buffer.open(QIODevice::ReadOnly);
   464     {
   476     LineReader agentLineReader(&buffer, mAsciiCodec);
   465         QVersitProperty expectedProperty;
   477 
   466         expectedProperty.setName(QLatin1String("X-CHILDREN"));
   478     property = mReaderPrivate->parseNextVersitProperty(type, agentLineReader);
   467         expectedProperty.setValue(QStringList() << QLatin1String("Child1") << QLatin1String("Child2"));
   479     QVERIFY(property.isEmpty());
   468         expectedProperty.setValueType(QVersitProperty::ListType);
   480 }
   469         QTest::newRow("children")
   481 
   470             << QVersitDocument::VCard21Type
   482 void tst_QVersitReader::testParseNextVersitPropertyVCard30()
   471             << QByteArray("X-CHILDREN:Child1,Child2\r\n")
   483 {
   472             << expectedProperty;
   484     QVersitDocument::VersitType type = QVersitDocument::VCard30Type;
   473     }
   485 
   474 
   486     // Test a valid vCard 3.0 with properties having separate handling:
   475     {
   487     // AGENT property and some other property
   476         // "NICKNAME:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar"
   488     QByteArray vCard("Begin:vcard\r\n");
   477         QVersitProperty expectedProperty;
   489     vCard.append("VERSION:3.0\r\n");
   478         expectedProperty.setName(QLatin1String("NICKNAME"));
   490     vCard.append("FN:John\r\n");
   479         QStringList components;
   491     // "NOTE:\;\,\:\\"
   480         components << QLatin1String("foo\\;bar")
   492     vCard.append("NOTE:\\;\\,\\:\\\\\r\n");
   481             << QLatin1String("foo,bar")
   493     // "N:foo\;bar;foo\,bar;foo\:bar;foo\\bar;foo\\\;bar"
   482             << QLatin1String("foo\\:bar")
   494     vCard.append("N:foo\\;bar;foo\\,bar;foo\\:bar;foo\\\\bar;foo\\\\\\;bar\r\n");
   483             << QLatin1String("foo\\\\bar")
   495     // "NICKNAME:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar"
   484             << QLatin1String("foo\\\\,bar");
   496     vCard.append("NICKNAME:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n");
   485         expectedProperty.setValue(components);
   497     // "CATEGORIES:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar"
   486         expectedProperty.setValueType(QVersitProperty::ListType);
   498     vCard.append("CATEGORIES:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n");
   487         QTest::newRow("vcard21 nickname")
   499     // "CATEGORIES:foobar\\,foobar\\\\,foo\\\\\,bar"
   488             << QVersitDocument::VCard21Type
   500     vCard.append("CATEGORIES:foobar\\\\,foobar\\\\\\\\,foo\\\\\\\\\\,bar\r\n");
   489             << QByteArray("NICKNAME:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n")
   501     vCard.append("ORG;CHARSET=UTF-8:");
   490             << expectedProperty;
   502     vCard.append(KATAKANA_NOKIA);
   491 
   503     vCard.append("\r\n");
   492         components.clear();
   504     // "NOKIA" in Katakana, UTF-8 encoded, then base-64 encoded:
   493         components << QLatin1String("foo;bar")
   505     vCard.append("NOTE;ENCODING=B;CHARSET=UTF-8:");
   494             << QLatin1String("foo,bar")
   506     vCard.append(KATAKANA_NOKIA.toBase64());
   495             << QLatin1String("foo:bar")
   507     vCard.append("\r\n");
   496             << QLatin1String("foo\\bar")
   508     vCard.append("TEL;TYPE=PREF;HOME:123\r\n");
   497             << QLatin1String("foo\\,bar");
   509     // The value here is "UXQgaXMgZ3JlYXQh", which is the base64 encoding of "Qt is great!".
   498         expectedProperty.setValue(components);
   510     vCard.append("PHOTO;ENCODING=B:UXQgaXMgZ3JlYXQh\r\n");
   499         QTest::newRow("vcard30 nickname")
   511     // Again, but without the explicity "ENCODING" parameter
   500             << QVersitDocument::VCard30Type
   512     vCard.append("PHOTO;B:UXQgaXMgZ3JlYXQh\r\n");
   501             << QByteArray("NICKNAME:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n")
   513     vCard.append("EMAIL:john.citizen@example.com\r\n");
   502             << expectedProperty;
   514     vCard.append("AGENT:BEGIN:VCARD\\nFN:Jenny\\nEND:VCARD\\n\r\n");
   503     }
   515     vCard.append("End:VCARD\r\n");
   504 
   516     QBuffer buffer(&vCard);
   505     {
   517     buffer.open(QIODevice::ReadOnly);
   506         // "CATEGORIES:foo\;bar,foo\,bar,foo\:bar,foo\\bar,foo\\\,bar"
   518     LineReader lineReader(&buffer, mAsciiCodec);
   507         QVersitProperty expectedProperty;
   519 
   508         expectedProperty.setName(QLatin1String("CATEGORIES"));
   520     QVersitProperty property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   509         QStringList components;
   521     QCOMPARE(property.name(),QString::fromAscii("BEGIN"));
   510         components << QLatin1String("foo\\;bar")
   522     QCOMPARE(property.value(),QString::fromAscii("vcard"));
   511             << QLatin1String("foo,bar")
   523 
   512             << QLatin1String("foo\\:bar")
   524     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   513             << QLatin1String("foo\\\\bar")
   525     QCOMPARE(property.name(),QString::fromAscii("VERSION"));
   514             << QLatin1String("foo\\\\,bar");
   526     QCOMPARE(property.value(),QString::fromAscii("3.0"));
   515         expectedProperty.setValue(components);
   527 
   516         expectedProperty.setValueType(QVersitProperty::ListType);
   528     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   517         QTest::newRow("vcard21 categories")
   529     QCOMPARE(property.name(),QString::fromAscii("FN"));
   518             << QVersitDocument::VCard21Type
   530     QCOMPARE(property.value(),QString::fromAscii("John"));
   519             << QByteArray("CATEGORIES:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n")
   531 
   520             << expectedProperty;
   532     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   521 
   533     QCOMPARE(property.name(),QString::fromAscii("NOTE"));
   522         components.clear();
   534     QCOMPARE(property.valueType(), QVersitProperty::PlainType);
   523         components << QLatin1String("foo;bar")
   535     QCOMPARE(property.variantValue().type(), QVariant::String);
   524             << QLatin1String("foo,bar")
   536     // Unescape semicolons, commas, colons and backlashes
   525             << QLatin1String("foo:bar")
   537     QCOMPARE(property.value(), QString::fromAscii(";,:\\"));
   526             << QLatin1String("foo\\bar")
   538 
   527             << QLatin1String("foo\\,bar");
   539     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   528         expectedProperty.setValue(components);
   540     QCOMPARE(property.name(),QString::fromAscii("N"));
   529         QTest::newRow("vcard30 categories")
   541     QCOMPARE(property.valueType(), QVersitProperty::CompoundType);
   530             << QVersitDocument::VCard30Type
   542     QCOMPARE(property.variantValue().type(), QVariant::StringList);
   531             << QByteArray("CATEGORIES:foo\\;bar,foo\\,bar,foo\\:bar,foo\\\\bar,foo\\\\\\,bar\r\n")
   543     QStringList components = property.value<QStringList>();
   532             << expectedProperty;
   544     QCOMPARE(components.size(), 5);
   533 
   545     QCOMPARE(components.at(0), QLatin1String("foo;bar"));
   534         // "CATEGORIES:foobar\\,foobar\\\\,foo\\\\\,bar"
   546     QCOMPARE(components.at(1), QLatin1String("foo,bar"));
   535         components.clear();
   547     QCOMPARE(components.at(2), QLatin1String("foo:bar"));
   536         components << QLatin1String("foobar\\")
   548     QCOMPARE(components.at(3), QLatin1String("foo\\bar"));
   537             << QLatin1String("foobar\\\\")
   549     QCOMPARE(components.at(4), QLatin1String("foo\\;bar"));
   538             << QLatin1String("foo\\\\,bar");
   550 
   539         expectedProperty.setValue(components);
   551     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   540         QTest::newRow("vcard30 unescaping")
   552     QCOMPARE(property.name(),QString::fromAscii("NICKNAME"));
   541             << QVersitDocument::VCard30Type
   553     QCOMPARE(property.valueType(), QVersitProperty::ListType);
   542             << QByteArray("CATEGORIES:foobar\\\\,foobar\\\\\\\\,foo\\\\\\\\\\,bar")
   554     QCOMPARE(property.variantValue().type(), QVariant::StringList);
   543             << expectedProperty;
   555     components = property.value<QStringList>();
   544     }
   556     QCOMPARE(components.size(), 5);
   545 
   557     QCOMPARE(components.at(0), QLatin1String("foo;bar"));
   546     {
   558     QCOMPARE(components.at(1), QLatin1String("foo,bar"));
   547         QVersitProperty expectedProperty;
   559     QCOMPARE(components.at(2), QLatin1String("foo:bar"));
   548         expectedProperty.setName(QLatin1String("ORG"));
   560     QCOMPARE(components.at(3), QLatin1String("foo\\bar"));
   549         expectedProperty.setValue(QString::fromUtf8(KATAKANA_NOKIA));
   561     QCOMPARE(components.at(4), QLatin1String("foo\\,bar"));
   550         expectedProperty.setValueType(QVersitProperty::CompoundType);
   562 
   551         QTest::newRow("org utf8")
   563     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   552             << QVersitDocument::VCard21Type
   564     QCOMPARE(property.name(),QString::fromAscii("CATEGORIES"));
   553             << QByteArray("ORG;CHARSET=UTF-8:" + KATAKANA_NOKIA + "\r\n")
   565     QCOMPARE(property.valueType(), QVersitProperty::ListType);
   554             << expectedProperty;
   566     QCOMPARE(property.variantValue().type(), QVariant::StringList);
   555     }
   567     components = property.value<QStringList>();
   556 
   568     QCOMPARE(components.size(), 5);
   557     {
   569     QCOMPARE(components.at(0), QLatin1String("foo;bar"));
   558         QVersitProperty expectedProperty;
   570     QCOMPARE(components.at(1), QLatin1String("foo,bar"));
   559         expectedProperty.setName(QLatin1String("PHOTO"));
   571     QCOMPARE(components.at(2), QLatin1String("foo:bar"));
   560         expectedProperty.setValue(QLatin1String("Qt is great!"));
   572     QCOMPARE(components.at(3), QLatin1String("foo\\bar"));
   561         expectedProperty.setValueType(QVersitProperty::BinaryType);
   573     QCOMPARE(components.at(4), QLatin1String("foo\\,bar"));
   562         QTest::newRow("vcard21 photo1")
   574 
   563             << QVersitDocument::VCard21Type
   575     // "CATEGORIES:foobar\\,foobar\\\\,foo\\\\\,bar"
   564             << QByteArray("PHOTO;ENCODING=BASE64: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n")
   576     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   565             << expectedProperty;
   577     QCOMPARE(property.name(),QString::fromAscii("CATEGORIES"));
   566 
   578     QCOMPARE(property.valueType(), QVersitProperty::ListType);
   567         QTest::newRow("vcard30 photo1")
   579     QCOMPARE(property.variantValue().type(), QVariant::StringList);
   568             << QVersitDocument::VCard30Type
   580     components = property.value<QStringList>();
   569             << QByteArray("PHOTO;ENCODING=B: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n")
   581     QCOMPARE(components.size(), 3);
   570             << expectedProperty;
   582     QCOMPARE(components.at(0), QLatin1String("foobar\\"));
   571     }
   583     QCOMPARE(components.at(1), QLatin1String("foobar\\\\"));
   572 
   584     QCOMPARE(components.at(2), QLatin1String("foo\\\\,bar"));
   573     // Again, but without the explicit "ENCODING" parameter
   585 
   574     {
   586     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   575         QVersitProperty expectedProperty;
   587     QCOMPARE(property.name(),QString::fromAscii("ORG"));
   576         expectedProperty.setName(QLatin1String("PHOTO"));
   588     QCOMPARE(property.value(),QString::fromUtf8(KATAKANA_NOKIA));
   577         expectedProperty.setValue(QLatin1String("Qt is great!"));
   589 
   578         expectedProperty.setValueType(QVersitProperty::BinaryType);
   590     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   579         QTest::newRow("photo2")
   591     QCOMPARE(property.name(),QString::fromAscii("NOTE"));
   580             << QVersitDocument::VCard21Type
   592     QCOMPARE(property.value(),QString::fromUtf8(KATAKANA_NOKIA));
   581             << QByteArray("PHOTO;BASE64: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n")
   593 
   582             << expectedProperty;
   594     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   583 
   595     QCOMPARE(property.name(),QString::fromAscii("TEL"));
   584         QTest::newRow("photo2")
   596     QCOMPARE(property.value(),QString::fromAscii("123"));
   585             << QVersitDocument::VCard30Type
   597     QCOMPARE(property.parameters().count(), 2);
   586             << QByteArray("PHOTO;B: U\t XQgaX MgZ\t3Jl YXQh\r\n\r\n")
   598 
   587             << expectedProperty;
   599     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   588     }
   600     QCOMPARE(property.name(),QString::fromAscii("PHOTO"));
   589 
   601     QCOMPARE(property.variantValue().type(), QVariant::ByteArray);
   590     {
   602     QCOMPARE(property.value<QByteArray>(), QByteArray("Qt is great!"));
   591         QVersitProperty expectedProperty;
   603     // Ensure that base-64 encoded strings can be retrieved as strings.
   592         expectedProperty.setGroups(QStringList() << QLatin1String("HOME") << QLatin1String("Springfield"));
   604     QCOMPARE(property.value(), QLatin1String("Qt is great!"));
   593         expectedProperty.setName(QLatin1String("EMAIL"));
   605 
   594         expectedProperty.setValue(QLatin1String("john.citizen@example.com"));
   606     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   595         expectedProperty.setValueType(QVersitProperty::PlainType);
   607     QCOMPARE(property.name(),QString::fromAscii("PHOTO"));
   596         QTest::newRow("email qp")
   608     QCOMPARE(property.variantValue().type(), QVariant::ByteArray);
   597             << QVersitDocument::VCard21Type
   609     QCOMPARE(property.value<QByteArray>(), QByteArray("Qt is great!"));
   598             << QByteArray("HOME.Springfield.EMAIL;Encoding=Quoted-Printable:john.citizen=40exam=\r\nple.com\r\n")
   610     QCOMPARE(property.value(), QLatin1String("Qt is great!"));
   599             << expectedProperty;
   611 
   600     }
   612     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   601 
   613     QCOMPARE(property.name(),QString::fromAscii("EMAIL"));
   602     {
   614     QCOMPARE(0,property.parameters().count());
   603         QVersitProperty expectedProperty;
   615     QCOMPARE(property.value(),QString::fromAscii("john.citizen@example.com"));
   604         expectedProperty.setName(QLatin1String("EMAIL"));
   616 
   605         expectedProperty.setValue(QLatin1String("john.citizen@example.com"));
   617     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   606         expectedProperty.setValueType(QVersitProperty::PlainType);
   618     QCOMPARE(property.name(),QString::fromAscii("AGENT"));
   607         QTest::newRow("email qp utf16")
   619     QVERIFY(property.variantValue().userType() == qMetaTypeId<QVersitDocument>());
   608             << QVersitDocument::VCard21Type
   620     QCOMPARE(property.value<QVersitDocument>().properties().count(), 1);
   609             << QByteArray("EMAIL;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-16BE:" + QTextCodec::codecForName("UTF-16BE")->fromUnicode(QLatin1String("john.citizen=40exam=\r\nple.com")) + "\r\n")
   621 
   610             << expectedProperty;
   622     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   611     }
   623     QCOMPARE(property.name(),QString::fromAscii("END"));
   612 
   624     QCOMPARE(property.value(),QString::fromAscii("VCARD"));
   613     {
   625 
   614         QVersitDocument subDocument;
   626     property = mReaderPrivate->parseNextVersitProperty(type, lineReader);
   615         subDocument.setType(QVersitDocument::VCard30Type);
   627     QCOMPARE(property.name(),QString());
   616         QVersitProperty subProperty;
   628     QCOMPARE(property.value(),QString());
   617         subProperty.setName(QLatin1String("FN"));
   629 
   618         subProperty.setValue(QLatin1String("Jenny"));
   630     // Simulate a situation where the document nesting level is exceeded
   619         subDocument.addProperty(subProperty);
   631     // In practice this would mean a big number of nested AGENT properties
   620 
   632     mReaderPrivate->mDocumentNestingLevel = 20;
   621         QVersitProperty expectedProperty;
   633     QByteArray agentProperty("AGENT:BEGIN\\:VCARD\\nFN\\:Jenny\\nEND\\:VCARD\\n\r\n");
   622         expectedProperty.setName(QLatin1String("AGENT"));
   634     buffer.close();
   623         expectedProperty.setValue(QVariant::fromValue(subDocument));
   635     buffer.setData(agentProperty);
   624         expectedProperty.setValueType(QVersitProperty::VersitDocumentType);
   636     buffer.open(QIODevice::ReadOnly);
   625         QTest::newRow("agent")
   637     LineReader agentLineReader(&buffer, mAsciiCodec);
   626             << QVersitDocument::VCard21Type
   638 
   627             << QByteArray("AGENT:\r\nBEGIN:VCARD\r\nFN:Jenny\r\nEND:VCARD\r\n\r\n")
   639     property = mReaderPrivate->parseNextVersitProperty(type, agentLineReader);
   628             << expectedProperty;
   640     QVERIFY(property.isEmpty());
   629     }
       
   630 #endif
   641 }
   631 }
   642 
   632 
   643 void tst_QVersitReader::testParseVersitDocument()
   633 void tst_QVersitReader::testParseVersitDocument()
   644 {
   634 {
       
   635 #ifndef QT_BUILD_INTERNAL
       
   636     QSKIP("Testing private API", SkipSingle);
       
   637 #else
   645     QFETCH(QByteArray, vCard);
   638     QFETCH(QByteArray, vCard);
   646     QFETCH(bool, expectedSuccess);
   639     QFETCH(bool, expectedSuccess);
   647     QFETCH(int, expectedProperties);
   640     QFETCH(int, expectedProperties);
   648 
   641 
   649     QBuffer buffer(&vCard);
   642     QBuffer buffer(&vCard);
   652 
   645 
   653     QVersitDocument document;
   646     QVersitDocument document;
   654     QCOMPARE(mReaderPrivate->parseVersitDocument(lineReader, document), expectedSuccess);
   647     QCOMPARE(mReaderPrivate->parseVersitDocument(lineReader, document), expectedSuccess);
   655     QCOMPARE(document.properties().count(), expectedProperties);
   648     QCOMPARE(document.properties().count(), expectedProperties);
   656     QCOMPARE(mReaderPrivate->mDocumentNestingLevel, 0);
   649     QCOMPARE(mReaderPrivate->mDocumentNestingLevel, 0);
       
   650 #endif
   657 }
   651 }
   658 
   652 
   659 void tst_QVersitReader::testParseVersitDocument_data()
   653 void tst_QVersitReader::testParseVersitDocument_data()
   660 {
   654 {
       
   655 #ifdef QT_BUILD_INTERNAL
   661     QTest::addColumn<QByteArray>("vCard");
   656     QTest::addColumn<QByteArray>("vCard");
   662     QTest::addColumn<bool>("expectedSuccess");
   657     QTest::addColumn<bool>("expectedSuccess");
   663     QTest::addColumn<int>("expectedProperties");
   658     QTest::addColumn<int>("expectedProperties");
   664 
   659 
   665     QTest::newRow("Basic vCard 2.1")
   660     QTest::newRow("Basic vCard 2.1")
   752                     "TEL;CELL:7777\r\n"
   747                     "TEL;CELL:7777\r\n"
   753                     "END:VCARD\r\n"
   748                     "END:VCARD\r\n"
   754                     "END:VCARD")
   749                     "END:VCARD")
   755             << false
   750             << false
   756             << 0;
   751             << 0;
       
   752 #endif
   757 }
   753 }
   758 
   754 
   759 void tst_QVersitReader::testDecodeQuotedPrintable()
   755 void tst_QVersitReader::testDecodeQuotedPrintable()
   760 {
   756 {
       
   757 #ifndef QT_BUILD_INTERNAL
       
   758     QSKIP("Testing private API", SkipSingle);
       
   759 #else
   761     QFETCH(QString, encoded);
   760     QFETCH(QString, encoded);
   762 
   761 
   763     QFETCH(QString, decoded);
   762     QFETCH(QString, decoded);
   764     mReaderPrivate->decodeQuotedPrintable(encoded);
   763     mReaderPrivate->decodeQuotedPrintable(encoded);
   765     QCOMPARE(encoded, decoded);
   764     QCOMPARE(encoded, decoded);
       
   765 #endif
   766 }
   766 }
   767 
   767 
   768 void tst_QVersitReader::testDecodeQuotedPrintable_data()
   768 void tst_QVersitReader::testDecodeQuotedPrintable_data()
   769 {
   769 {
       
   770 #ifdef QT_BUILD_INTERNAL
   770     QTest::addColumn<QString>("encoded");
   771     QTest::addColumn<QString>("encoded");
   771     QTest::addColumn<QString>("decoded");
   772     QTest::addColumn<QString>("decoded");
   772 
   773 
   773 
   774 
   774     QTest::newRow("Soft line breaks")
   775     QTest::newRow("Soft line breaks")
   808             << QString::fromLatin1("\n\r");
   809             << QString::fromLatin1("\n\r");
   809 
   810 
   810     QTest::newRow("White spaces")
   811     QTest::newRow("White spaces")
   811             << QString::fromLatin1("=09=20")
   812             << QString::fromLatin1("=09=20")
   812             << QString::fromLatin1("\t ");
   813             << QString::fromLatin1("\t ");
   813 
   814 #endif
   814 
       
   815 }
   815 }
   816 void tst_QVersitReader::testParamName()
   816 void tst_QVersitReader::testParamName()
   817 {
   817 {
       
   818 #ifndef QT_BUILD_INTERNAL
       
   819     QSKIP("Testing private API", SkipSingle);
       
   820 #else
   818     // Empty value
   821     // Empty value
   819     QByteArray param;
   822     QByteArray param;
   820     QCOMPARE(mReaderPrivate->paramName(param, mAsciiCodec),QString());
   823     QCOMPARE(mReaderPrivate->paramName(param, mAsciiCodec),QString());
   821 
   824 
   822     // Only value present
   825     // Only value present
   839     // Test wide character support.
   842     // Test wide character support.
   840     QTextCodec* codec = QTextCodec::codecForName("UTF-16BE");
   843     QTextCodec* codec = QTextCodec::codecForName("UTF-16BE");
   841     param = codec->fromUnicode(QString::fromAscii("TIPE=WORK"));
   844     param = codec->fromUnicode(QString::fromAscii("TIPE=WORK"));
   842     QCOMPARE(mReaderPrivate->paramName(param, codec),
   845     QCOMPARE(mReaderPrivate->paramName(param, codec),
   843              QString::fromAscii("TIPE"));
   846              QString::fromAscii("TIPE"));
   844 
   847 #endif
   845 }
   848 }
   846 
   849 
   847 void tst_QVersitReader::testParamValue()
   850 void tst_QVersitReader::testParamValue()
   848 {
   851 {
       
   852 #ifndef QT_BUILD_INTERNAL
       
   853     QSKIP("Testing private API", SkipSingle);
       
   854 #else
   849     // Empty value
   855     // Empty value
   850     QByteArray param;
   856     QByteArray param;
   851     QCOMPARE(mReaderPrivate->paramValue(param, mAsciiCodec),QString());
   857     QCOMPARE(mReaderPrivate->paramValue(param, mAsciiCodec),QString());
   852 
   858 
   853     // Only value present
   859     // Only value present
   876     // Test wide character support.
   882     // Test wide character support.
   877     QTextCodec* codec = QTextCodec::codecForName("UTF-16BE");
   883     QTextCodec* codec = QTextCodec::codecForName("UTF-16BE");
   878     param = codec->fromUnicode(QString::fromAscii("TYPE=WORK"));
   884     param = codec->fromUnicode(QString::fromAscii("TYPE=WORK"));
   879     QCOMPARE(mReaderPrivate->paramValue(param, codec),
   885     QCOMPARE(mReaderPrivate->paramValue(param, codec),
   880              QString::fromAscii("WORK"));
   886              QString::fromAscii("WORK"));
       
   887 #endif
   881 }
   888 }
   882 
   889 
   883 void tst_QVersitReader::testExtractPart()
   890 void tst_QVersitReader::testExtractPart()
   884 {
   891 {
       
   892 #ifndef QT_BUILD_INTERNAL
       
   893     QSKIP("Testing private API", SkipSingle);
       
   894 #else
   885     QByteArray originalStr;
   895     QByteArray originalStr;
   886 
   896 
   887     // Negative starting position
   897     // Negative starting position
   888     QCOMPARE(mReaderPrivate->extractPart(originalStr,-1,1), QByteArray());
   898     QCOMPARE(mReaderPrivate->extractPart(originalStr,-1,1), QByteArray());
   889 
   899 
   908              QByteArray("X-PARAM=X-VALUE"));
   918              QByteArray("X-PARAM=X-VALUE"));
   909 
   919 
   910     // Non-empty substring, from the middle to the end
   920     // Non-empty substring, from the middle to the end
   911     QCOMPARE(mReaderPrivate->extractPart(originalStr,29),
   921     QCOMPARE(mReaderPrivate->extractPart(originalStr,29),
   912              QByteArray("ENCODING=8BIT"));
   922              QByteArray("ENCODING=8BIT"));
       
   923 #endif
   913 }
   924 }
   914 
   925 
   915 void tst_QVersitReader::testExtractParts()
   926 void tst_QVersitReader::testExtractParts()
   916 {
   927 {
       
   928 #ifndef QT_BUILD_INTERNAL
       
   929     QSKIP("Testing private API", SkipSingle);
       
   930 #else
   917     QList<QByteArray> parts;
   931     QList<QByteArray> parts;
   918 
   932 
   919     // Empty value
   933     // Empty value
   920     QByteArray text;
   934     QByteArray text;
   921     parts = mReaderPrivate->extractParts(text,";", mAsciiCodec);
   935     parts = mReaderPrivate->extractParts(text,";", mAsciiCodec);
   969     text = codec->fromUnicode(QString::fromAscii("part1;part2"));
   983     text = codec->fromUnicode(QString::fromAscii("part1;part2"));
   970     parts = mReaderPrivate->extractParts(text,";", codec);
   984     parts = mReaderPrivate->extractParts(text,";", codec);
   971     QCOMPARE(parts.count(),2);
   985     QCOMPARE(parts.count(),2);
   972     QCOMPARE(codec->toUnicode(parts[0]),QString::fromAscii("part1"));
   986     QCOMPARE(codec->toUnicode(parts[0]),QString::fromAscii("part1"));
   973     QCOMPARE(codec->toUnicode(parts[1]),QString::fromAscii("part2"));
   987     QCOMPARE(codec->toUnicode(parts[1]),QString::fromAscii("part2"));
       
   988 #endif
   974 }
   989 }
   975 
   990 
   976 void tst_QVersitReader::testExtractPropertyGroupsAndName()
   991 void tst_QVersitReader::testExtractPropertyGroupsAndName()
   977 {
   992 {
       
   993 #ifndef QT_BUILD_INTERNAL
       
   994     QSKIP("Testing private API", SkipSingle);
       
   995 #else
   978     QPair<QStringList,QString> groupsAndName;
   996     QPair<QStringList,QString> groupsAndName;
   979 
   997 
   980     // Empty string
   998     // Empty string
   981     VersitCursor cursor(QByteArray(" "));
   999     VersitCursor cursor(QByteArray(" "));
   982     groupsAndName = mReaderPrivate->extractPropertyGroupsAndName(cursor, mAsciiCodec);
  1000     groupsAndName = mReaderPrivate->extractPropertyGroupsAndName(cursor, mAsciiCodec);
  1068     QCOMPARE(groupsAndName.first.count(),2);
  1086     QCOMPARE(groupsAndName.first.count(),2);
  1069     QCOMPARE(groupsAndName.first.takeFirst(),QString::fromAscii("group1"));
  1087     QCOMPARE(groupsAndName.first.takeFirst(),QString::fromAscii("group1"));
  1070     QCOMPARE(groupsAndName.first.takeFirst(),QString::fromAscii("group2"));
  1088     QCOMPARE(groupsAndName.first.takeFirst(),QString::fromAscii("group2"));
  1071     QCOMPARE(groupsAndName.second,QString::fromAscii("TEL"));
  1089     QCOMPARE(groupsAndName.second,QString::fromAscii("TEL"));
  1072     QCOMPARE(cursor.position, 36); // 2 bytes * 17 characters + 2 byte BOM.
  1090     QCOMPARE(cursor.position, 36); // 2 bytes * 17 characters + 2 byte BOM.
  1073 
  1091 #endif
  1074 }
  1092 }
  1075 
  1093 
  1076 void tst_QVersitReader::testExtractVCard21PropertyParams()
  1094 void tst_QVersitReader::testExtractVCard21PropertyParams()
  1077 {
  1095 {
       
  1096 #ifndef QT_BUILD_INTERNAL
       
  1097     QSKIP("Testing private API", SkipSingle);
       
  1098 #else
  1078     // No parameters
  1099     // No parameters
  1079     VersitCursor cursor(QByteArray(":123"));
  1100     VersitCursor cursor(QByteArray(":123"));
  1080     cursor.setSelection(cursor.data.size());
  1101     cursor.setSelection(cursor.data.size());
  1081     QCOMPARE(mReaderPrivate->extractVCard21PropertyParams(cursor, mAsciiCodec).count(), 0);
  1102     QCOMPARE(mReaderPrivate->extractVCard21PropertyParams(cursor, mAsciiCodec).count(), 0);
  1082 
  1103 
  1151     QCOMPARE(1, typeParams.count());
  1172     QCOMPARE(1, typeParams.count());
  1152     QCOMPARE(typeParams[0],QString::fromAscii("HOME"));
  1173     QCOMPARE(typeParams[0],QString::fromAscii("HOME"));
  1153     encodingParams = params.values(QString::fromAscii("CHARSET"));
  1174     encodingParams = params.values(QString::fromAscii("CHARSET"));
  1154     QCOMPARE(1, encodingParams.count());
  1175     QCOMPARE(1, encodingParams.count());
  1155     QCOMPARE(encodingParams[0],QString::fromAscii("UTF-16"));
  1176     QCOMPARE(encodingParams[0],QString::fromAscii("UTF-16"));
       
  1177 #endif
  1156 }
  1178 }
  1157 
  1179 
  1158 void tst_QVersitReader::testExtractVCard30PropertyParams()
  1180 void tst_QVersitReader::testExtractVCard30PropertyParams()
  1159 {
  1181 {
       
  1182 #ifndef QT_BUILD_INTERNAL
       
  1183     QSKIP("Testing private API", SkipSingle);
       
  1184 #else
  1160     // No parameters
  1185     // No parameters
  1161     VersitCursor cursor(QByteArray(":123"));
  1186     VersitCursor cursor(QByteArray(":123"));
  1162     cursor.setSelection(cursor.data.size());
  1187     cursor.setSelection(cursor.data.size());
  1163     QCOMPARE(mReaderPrivate->extractVCard30PropertyParams(cursor, mAsciiCodec).count(), 0);
  1188     QCOMPARE(mReaderPrivate->extractVCard30PropertyParams(cursor, mAsciiCodec).count(), 0);
  1164 
  1189 
  1240     QVERIFY(params.values(QString::fromAscii("TIPE")).contains(QString::fromAscii("HOME")));
  1265     QVERIFY(params.values(QString::fromAscii("TIPE")).contains(QString::fromAscii("HOME")));
  1241     QVERIFY(params.values(QString::fromAscii("TIPE")).contains(QString::fromAscii("VOICE")));
  1266     QVERIFY(params.values(QString::fromAscii("TIPE")).contains(QString::fromAscii("VOICE")));
  1242     encodingParams = params.values(QString::fromAscii("CHARSET"));
  1267     encodingParams = params.values(QString::fromAscii("CHARSET"));
  1243     QCOMPARE(1, encodingParams.count());
  1268     QCOMPARE(1, encodingParams.count());
  1244     QCOMPARE(encodingParams[0],QString::fromAscii("UTF-16"));
  1269     QCOMPARE(encodingParams[0],QString::fromAscii("UTF-16"));
       
  1270 #endif
  1245 }
  1271 }
  1246 
  1272 
  1247 void tst_QVersitReader::testExtractParams()
  1273 void tst_QVersitReader::testExtractParams()
  1248 {
  1274 {
       
  1275 #ifndef QT_BUILD_INTERNAL
       
  1276     QSKIP("Testing private API", SkipSingle);
       
  1277 #else
  1249     VersitCursor cursor;
  1278     VersitCursor cursor;
  1250     QByteArray data = ":123";
  1279     QByteArray data = ":123";
  1251     cursor.setData(data);
  1280     cursor.setData(data);
  1252     cursor.setPosition(0);
  1281     cursor.setPosition(0);
  1253     cursor.setSelection(cursor.data.size());
  1282     cursor.setSelection(cursor.data.size());
  1279     cursor.setPosition(0);
  1308     cursor.setPosition(0);
  1280     cursor.setSelection(cursor.data.size());
  1309     cursor.setSelection(cursor.data.size());
  1281     params = mReaderPrivate->extractParams(cursor, codec);
  1310     params = mReaderPrivate->extractParams(cursor, codec);
  1282     QCOMPARE(params.size(), 2);
  1311     QCOMPARE(params.size(), 2);
  1283     QCOMPARE(cursor.position, 8);
  1312     QCOMPARE(cursor.position, 8);
  1284 
  1313 #endif
  1285 }
  1314 }
  1286 
  1315 
  1287 Q_DECLARE_METATYPE(QList<QString>)
  1316 Q_DECLARE_METATYPE(QList<QString>)
  1288 
  1317 
  1289 void tst_QVersitReader::testReadLine()
  1318 void tst_QVersitReader::testReadLine()
  1290 {
  1319 {
       
  1320 #ifndef QT_BUILD_INTERNAL
       
  1321     QSKIP("Testing private API", SkipSingle);
       
  1322 #else
  1291     QFETCH(QByteArray, codecName);
  1323     QFETCH(QByteArray, codecName);
  1292     QFETCH(QString, data);
  1324     QFETCH(QString, data);
  1293     QFETCH(QList<QString>, expectedLines);
  1325     QFETCH(QList<QString>, expectedLines);
  1294 
  1326 
  1295     QTextCodec* codec = QTextCodec::codecForName(codecName);
  1327     QTextCodec* codec = QTextCodec::codecForName(codecName);
  1316     VersitCursor line = lineReader.readLine();
  1348     VersitCursor line = lineReader.readLine();
  1317     QCOMPARE(line.selection, line.position);
  1349     QCOMPARE(line.selection, line.position);
  1318     QVERIFY(lineReader.atEnd());
  1350     QVERIFY(lineReader.atEnd());
  1319 
  1351 
  1320     delete encoder;
  1352     delete encoder;
       
  1353 #endif
  1321 }
  1354 }
  1322 
  1355 
  1323 void tst_QVersitReader::testReadLine_data()
  1356 void tst_QVersitReader::testReadLine_data()
  1324 {
  1357 {
       
  1358 #ifdef QT_BUILD_INTERNAL
  1325     // Note: for this test, we set mLineReader to read 10 bytes at a time.  Lines of multiples of
  1359     // Note: for this test, we set mLineReader to read 10 bytes at a time.  Lines of multiples of
  1326     // 10 bytes are hence border cases.
  1360     // 10 bytes are hence border cases.
  1327     QTest::addColumn<QByteArray>("codecName");
  1361     QTest::addColumn<QByteArray>("codecName");
  1328     QTest::addColumn<QString>("data");
  1362     QTest::addColumn<QString>("data");
  1329     QTest::addColumn<QList<QString> >("expectedLines");
  1363     QTest::addColumn<QList<QString> >("expectedLines");
  1405         QTest::newRow("three mac lines " + codecName)
  1439         QTest::newRow("three mac lines " + codecName)
  1406                 << codecName
  1440                 << codecName
  1407                 << "one\rtwo\rthree\r"
  1441                 << "one\rtwo\rthree\r"
  1408                 << (QList<QString>() << QLatin1String("one") << QLatin1String("two") << QLatin1String("three"));
  1442                 << (QList<QString>() << QLatin1String("one") << QLatin1String("two") << QLatin1String("three"));
  1409     }
  1443     }
       
  1444 #endif
  1410 }
  1445 }
  1411 
  1446 
  1412 void tst_QVersitReader::testByteArrayInput()
  1447 void tst_QVersitReader::testByteArrayInput()
  1413 {
  1448 {
  1414     delete mReader;
  1449     delete mReader;
  1431     QCOMPARE(properties.first().value(), QLatin1String("John"));
  1466     QCOMPARE(properties.first().value(), QLatin1String("John"));
  1432 }
  1467 }
  1433 
  1468 
  1434 void tst_QVersitReader::testRemoveBackSlashEscaping()
  1469 void tst_QVersitReader::testRemoveBackSlashEscaping()
  1435 {
  1470 {
       
  1471 #ifndef QT_BUILD_INTERNAL
       
  1472     QSKIP("Testing private API", SkipSingle);
       
  1473 #else
  1436     // Empty string
  1474     // Empty string
  1437     QString input;
  1475     QString input;
  1438     QVersitReaderPrivate::removeBackSlashEscaping(input);
  1476     QVersitReaderPrivate::removeBackSlashEscaping(input);
  1439     QCOMPARE(input,QString());
  1477     QCOMPARE(input,QString());
  1440 
  1478 
  1450 
  1488 
  1451     // Don't remove escaping within quotes
  1489     // Don't remove escaping within quotes
  1452     input = QString::fromAscii("\"Quoted \\n \\N \\; \\,\"");
  1490     input = QString::fromAscii("\"Quoted \\n \\N \\; \\,\"");
  1453     QVersitReaderPrivate::removeBackSlashEscaping(input);
  1491     QVersitReaderPrivate::removeBackSlashEscaping(input);
  1454     QCOMPARE(input, QString::fromAscii("\"Quoted \\n \\N \\; \\,\""));
  1492     QCOMPARE(input, QString::fromAscii("\"Quoted \\n \\N \\; \\,\""));
       
  1493 #endif
  1455 }
  1494 }
  1456 
  1495 
  1457 QTEST_MAIN(tst_QVersitReader)
  1496 QTEST_MAIN(tst_QVersitReader)
  1458 
  1497