File indexing completed on 2024-05-26 05:28:47

0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
0002 
0003    This file is part of the Trojita Qt IMAP e-mail client,
0004    http://trojita.flaska.net/
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public License as
0008    published by the Free Software Foundation; either version 2 of
0009    the License or (at your option) version 3 or any later version
0010    accepted by the membership of KDE e.V. (or its successor approved
0011    by the membership of KDE e.V.), which shall act as a proxy
0012    defined in Section 14 of version 3 of the license.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017    GNU General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 #include <limits>
0024 #include <QDebug>
0025 #include <QTest>
0026 
0027 #include "test_Imap_LowLevelParser.h"
0028 
0029 #include "Imap/Exceptions.h"
0030 
0031 typedef QPair<QByteArray,Imap::LowLevelParser::ParsedAs> StringWithKind;
0032 
0033 void ImapLowLevelParserTest::testParseList()
0034 {
0035     using namespace Imap::LowLevelParser;
0036 
0037     QByteArray line = "()";
0038     int start = 0;
0039     QVariant res;
0040     QVariantList list;
0041 
0042     res = parseList( '(', ')', line, start );
0043     QCOMPARE( res, QVariant( QVariantList() ) );
0044     QCOMPARE( start, line.size() );
0045 
0046     line = "() 123";
0047     start = 0;
0048     res = parseList( '(', ')', line, start );
0049     QCOMPARE( res, QVariant( QVariantList() ) );
0050     QCOMPARE( line.mid(start), QByteArray(" 123") );
0051 
0052     line = "(smrt)";
0053     start = 0;
0054     res = parseList( '(', ')', line, start );
0055     Q_ASSERT( res.canConvert( QVariant::List ) );
0056     list = res.toList();
0057     QCOMPARE( list.size(), 1 );
0058     QCOMPARE( list, QVariantList() <<  "smrt" );
0059     QCOMPARE( line.size(), start );
0060 
0061     line = "[\\smrt] ahoj";
0062     start = 0;
0063     res = parseList( '[', ']', line, start );
0064     Q_ASSERT( res.canConvert( QVariant::List ) );
0065     list = res.toList();
0066     QCOMPARE( list.size(), 1 );
0067     QCOMPARE( list, QVariantList() <<  "\\smrt" );
0068     QCOMPARE( line.at(start), ' ' );
0069     ++start;
0070     QCOMPARE( line.at(start), 'a' );
0071 
0072     line = "(smrt [666] (999 1337) 3)";
0073     start = 0;
0074     res = parseList( '(', ')', line, start );
0075     Q_ASSERT( res.canConvert( QVariant::List ) );
0076     list = res.toList();
0077     QCOMPARE( list.size(), 4 );
0078     QCOMPARE( list, QVariantList() <<  "smrt" <<
0079             QVariant( QVariantList() << 666) << 
0080             QVariant( QVariantList() << 999 << 1337 ) << 3 );
0081     QCOMPARE( line.size(), start );
0082 
0083     try {
0084         line = "ahoj";
0085         start = 0;
0086         res = parseList( '(', ')', line, start );
0087         QFAIL( "parseList() against a string parameter should have thrown an exception" );
0088     } catch ( Imap::UnexpectedHere& ) {
0089         QVERIFY( true );
0090     }
0091 
0092     line = "(ahoj cau {6}\r\nnazdar 1337 \\* 666 \"aho\\\"oooj\") (bleee \\*)";
0093     start = 0;
0094     res = parseList( '(', ')', line, start );
0095     Q_ASSERT( res.canConvert( QVariant::List ) );
0096     list = res.toList();
0097     QCOMPARE( list.size(), 7 );
0098     QCOMPARE( list, QVariantList() <<  "ahoj" << "cau" << "nazdar" << 1337 << "\\*" << 666 << "aho\"oooj" );
0099     QVERIFY( start < line.size() );
0100     QCOMPARE( line.at( start ), ' ' );
0101     ++start;
0102     QVERIFY( start < line.size() );
0103     res = parseList( '(', ')', line, start );
0104     Q_ASSERT( res.canConvert( QVariant::List ) );
0105     list = res.toList();
0106     QCOMPARE( list.size(), 2 );
0107     QCOMPARE( list, QVariantList() << "bleee" << "\\*" );
0108     QCOMPARE( start, line.size() );
0109 }
0110 
0111 void ImapLowLevelParserTest::testGetString()
0112 {
0113     using namespace Imap::LowLevelParser;
0114 
0115     QByteArray line = "ahOj";
0116     int pos = 0;
0117     StringWithKind res;
0118 
0119     try {
0120         line = ""; pos = 0;
0121         res = getString( line, pos );
0122         QFAIL( "getString() should scream on empty line" );
0123     } catch ( Imap::NoData& ) {
0124         QCOMPARE( pos, 0 );
0125     }
0126 
0127     try {
0128         line = "ah0j 333"; pos = 0;
0129         res = getString( line, pos );
0130         QFAIL( "getString() should ignore atoms" );
0131     } catch ( Imap::UnexpectedHere& ) {
0132         QCOMPARE( pos, 0 );
0133     }
0134 
0135     line = "{0}\r\na"; pos = 0;
0136     res = getString( line, pos );
0137     QCOMPARE( res.first.size(), 0 );
0138     QCOMPARE( res.second, LITERAL );
0139     QCOMPARE( pos, line.size() - 1 );
0140 
0141     line = "{0}\r\n a"; pos = 0;
0142     res = getString( line, pos );
0143     QCOMPARE( res.first.size(), 0 );
0144     QCOMPARE( res.second, LITERAL );
0145     QCOMPARE( pos, line.size() - 2 );
0146 
0147     line = "{3}\r\n666"; pos = 0;
0148     res = getString( line, pos );
0149     QCOMPARE( res.first, QByteArray("666") );
0150     QCOMPARE( res.second, LITERAL );
0151     QCOMPARE( pos, line.size() );
0152     pos = 0;
0153     QCOMPARE(getAnything(line, pos).toByteArray(), QByteArray("666"));
0154     QCOMPARE(pos, line.size());
0155 
0156     line = "~{3}\r\n666"; pos = 0;
0157     res = getString( line, pos );
0158     QCOMPARE( res.first, QByteArray("666") );
0159     QCOMPARE( res.second, LITERAL8 );
0160     QCOMPARE( pos, line.size() );
0161     pos = 0;
0162     QCOMPARE(getAnything(line, pos).toByteArray(), QByteArray("666"));
0163     QCOMPARE(pos, line.size());
0164 
0165     QByteArray myData;
0166     myData.append('\x00');
0167     myData.append("\x01\x02\x03 abcde");
0168     line = QByteArray("{") + QByteArray::number( myData.size() ) + QByteArray("}\r\n");
0169     line.append(myData);
0170     pos = 0;
0171     res = getString( line, pos );
0172     QCOMPARE( res.first, myData );
0173     QCOMPARE( res.second, LITERAL );
0174     QCOMPARE( pos, line.size() );
0175 
0176     line = "\"333\\\\ \\\" 666\"a"; pos = 0;
0177     res = getString( line, pos );
0178     QCOMPARE( res.first, QByteArray("333\\ \" 666") );
0179     QCOMPARE( res.second, QUOTED );
0180     QCOMPARE( line.at(pos), 'a' );
0181 
0182     line = "\"\"x"; pos = 0;
0183     res = getString( line, pos );
0184     QCOMPARE( res.first.size(), 0 );
0185     QCOMPARE( res.second, QUOTED );
0186     QCOMPARE( pos, line.size() - 1 );
0187 
0188 }
0189 
0190 void ImapLowLevelParserTest::testGetUInt()
0191 {
0192     using namespace Imap::LowLevelParser;
0193 
0194     QByteArray line = "123456 789 a666b333";
0195     uint res;
0196     int pos = 0;
0197 
0198     res = getUInt( line, pos );
0199     QCOMPARE( res, 123456u );
0200     ++pos;
0201 
0202     res = getUInt( line, pos );
0203     QCOMPARE( res, 789u );
0204     ++pos;
0205 
0206     try {
0207         getUInt( line, pos );
0208         QFAIL("exception not raised");
0209     } catch (Imap::ParseError& e) {
0210         QCOMPARE( pos, 11 );
0211         ++pos;
0212     }
0213 
0214     res = getUInt( line, pos );
0215     QCOMPARE( res, 666u );
0216 
0217     QCOMPARE( pos, 15 );
0218     ++pos;
0219 
0220     res = getUInt( line, pos );
0221     QCOMPARE( res, 333u );
0222 
0223     Q_ASSERT( pos == line.size() );
0224 
0225     for (int i = 0; i < 20; ++i) {
0226         quint32 num = std::numeric_limits<quint32>::max() - i;
0227         QByteArray line = QByteArray::number(num);
0228         int start = 0;
0229         quint32 res = getUInt(line, start);
0230         QCOMPARE(res, num);
0231         QCOMPARE(start, line.size());
0232     }
0233     for (int i = 0; i < 20; ++i) {
0234         quint64 num = std::numeric_limits<quint64>::max() - i;
0235         QByteArray line = QByteArray::number(num);
0236         int start = 0;
0237         quint64 res = getUInt64(line, start);
0238         QCOMPARE(res, num);
0239         QCOMPARE(start, line.size());
0240     }
0241 
0242     try {
0243         line = "4294967297";
0244         pos = 0;
0245         getUInt(line, pos);
0246         QFAIL("exception not raised");
0247     } catch (Imap::ParseError&) {
0248         QCOMPARE(pos, line.size() - 1);
0249     }
0250 
0251     try {
0252         line = "18446744073709551617";
0253         pos = 0;
0254         getUInt64(line, pos);
0255         QFAIL("exception not raised");
0256     } catch (Imap::ParseError&) {
0257         QCOMPARE(pos, line.size() - 1);
0258     }
0259 }
0260 
0261 void ImapLowLevelParserTest::testGetAtom()
0262 {
0263     using namespace Imap::LowLevelParser;
0264 
0265     QByteArray line = "blesmrt troj1ta s matovou\nomackou";
0266     int pos = 0;
0267 
0268     QCOMPARE( getAtom( line, pos ), QByteArray("blesmrt") );
0269     ++pos;
0270     QCOMPARE( getAtom( line, pos ), QByteArray("troj1ta") );
0271     ++pos;
0272     QCOMPARE( getAtom( line, pos ), QByteArray("s") );
0273     ++pos;
0274     QCOMPARE( getAtom( line, pos ), QByteArray("matovou") );
0275     ++pos;
0276     QCOMPARE( getAtom( line, pos ), QByteArray("omackou") );
0277     Q_ASSERT( pos == line.size() );
0278 }
0279 
0280 void ImapLowLevelParserTest::testGetAString()
0281 {
0282     using namespace Imap::LowLevelParser;
0283 
0284     QByteArray line = "ahOj";
0285     int pos = 0;
0286 
0287     StringWithKind res = getAString( line, pos );
0288     QCOMPARE( res.first, QByteArray("ahOj") );
0289     QCOMPARE( res.second, ATOM );
0290     QCOMPARE( pos, line.size() );
0291 
0292     line = "ah0j 333"; pos = 0;
0293     res = getAString( line, pos );
0294     QCOMPARE( res.first, QByteArray("ah0j") );
0295     QCOMPARE( res.second, ATOM );
0296     ++pos;
0297     res = getAString( line, pos );
0298     QCOMPARE( res.first, QByteArray("333") );
0299     QCOMPARE( pos, line.size() );
0300 
0301     line = "\"ah0j 333\""; pos = 0;
0302     res = getAString( line, pos );
0303     QCOMPARE( res.first, QByteArray("ah0j 333") );
0304     QCOMPARE( res.second, QUOTED );
0305     QCOMPARE( pos, line.size() );
0306 
0307     line = "{8}\r\nah0j 333"; pos = 0;
0308     res = getAString( line, pos );
0309     QCOMPARE( res.first, QByteArray("ah0j 333") );
0310     QCOMPARE( res.second, LITERAL );
0311     QCOMPARE( pos, line.size() );
0312 
0313     line = "~{2}\r\n";
0314     line.append('\x00');
0315     line.append('\xff');
0316     line.append("trms");
0317     QCOMPARE(line.size(), 12);
0318     pos = 0;
0319     res = getAString(line, pos);
0320     QByteArray bdata;
0321     bdata.append('\x00');
0322     bdata.append('\xff');
0323     QCOMPARE(res.first, bdata);
0324     QCOMPARE(res.second, LITERAL8);
0325     QCOMPARE(line.mid(pos), QByteArray("trms"));
0326 
0327     line = "BEST.[Trainers] ";
0328     pos = 0;
0329     res = getAString(line, pos);
0330     QCOMPARE(res.first, QByteArray("BEST.[Trainers]"));
0331     QCOMPARE(res.second, ASTRING);
0332     QCOMPARE(line.mid(pos), QByteArray(" "));
0333 
0334     line = "BEST.[Trainers]666 ";
0335     pos = 0;
0336     res = getAString(line, pos);
0337     QCOMPARE(res.first, QByteArray("BEST.[Trainers]666"));
0338     QCOMPARE(res.second, ASTRING);
0339     QCOMPARE(line.mid(pos), QByteArray(" "));
0340 
0341     line = "][][][ ";
0342     pos = 0;
0343     res = getAString(line, pos);
0344     QCOMPARE(res.first, QByteArray("][][]["));
0345     QCOMPARE(res.second, ASTRING);
0346     QCOMPARE(line.mid(pos), QByteArray(" "));
0347 }
0348 
0349 void ImapLowLevelParserTest::testGetAnything()
0350 {
0351     using namespace Imap::LowLevelParser;
0352     QByteArray line = "ah0j";
0353     int pos = 0;
0354     QVariant res;
0355 
0356     res = getAnything( line, pos );
0357     QCOMPARE( line, res.toByteArray() );
0358     QCOMPARE( pos, line.size() );
0359 
0360     line = "ahoj cau";
0361     pos = 0;
0362     res = getAnything( line, pos );
0363     QCOMPARE( QByteArray("ahoj"), res.toByteArray() );
0364     QCOMPARE( line.at( pos ), ' ' );
0365     ++pos;
0366     res = getAnything( line, pos );
0367     QCOMPARE( QByteArray("cau"), res.toByteArray() );
0368     QCOMPARE( pos, line.size() );
0369 
0370     line = "1337"; pos = 0;
0371     res = getAnything( line, pos );
0372     Q_ASSERT( res.canConvert( QVariant::Int ) );
0373     QCOMPARE( 1337, res.toInt() );
0374     QCOMPARE( pos, line.size() );
0375 
0376     line = "0 666";
0377     pos = 0;
0378     res = getAnything( line, pos );
0379     Q_ASSERT( res.canConvert( QVariant::Int ) );
0380     QCOMPARE( 0, res.toInt() );
0381     QCOMPARE( line.at( pos ), ' ' );
0382     ++pos;
0383     res = getAnything( line, pos );
0384     Q_ASSERT( res.canConvert( QVariant::Int ) );
0385     QCOMPARE( 666, res.toInt() );
0386     QCOMPARE( pos, line.size() );
0387 
0388     line = "Blesmrt[trojita (666 333 1337)]"; pos = 0;
0389     res = getAnything( line, pos );
0390     QCOMPARE( line, res.toByteArray() );
0391     QCOMPARE( pos, line.size() );
0392 
0393     line = "Blesmrt[trojita (666 333 1337)] ahoj"; pos = 0;
0394     res = getAnything( line, pos );
0395     QCOMPARE( QByteArray("Blesmrt[trojita (666 333 1337)]"), res.toByteArray() );
0396     QCOMPARE( line.mid(pos), QByteArray(" ahoj") );
0397 
0398     line = "Blesmrt[trojita (666 333 1337)]<1337> z666"; pos = 0;
0399     res = getAnything( line, pos );
0400     QCOMPARE( QByteArray("Blesmrt[trojita (666 333 1337)]<1337>"), res.toByteArray() );
0401     QCOMPARE( line.mid(pos), QByteArray(" z666") );
0402 
0403     line = "NilAtom"; pos = 0;
0404     res = getAnything(line, pos);
0405     QCOMPARE(res.toByteArray(), line);
0406     QCOMPARE(pos, line.size());
0407 
0408     line = "Ni"; pos = 0;
0409     res = getAnything(line, pos);
0410     QCOMPARE(res.toByteArray(), line);
0411     QCOMPARE(pos, line.size());
0412 
0413     line = "nil"; pos = 0;
0414     res = getAnything(line, pos);
0415     QCOMPARE(res.toByteArray(), QByteArray());
0416     QCOMPARE(pos, line.size());
0417 
0418     line = "Nil Atom"; pos = 0;
0419     res = getAnything(line, pos);
0420     QCOMPARE(res.toByteArray(), QByteArray());
0421     QCOMPARE(pos, 3);
0422 }
0423 
0424 void ImapLowLevelParserTest::testGetRFC2822DateTime()
0425 {
0426     QFETCH( QString, line );
0427     QFETCH( QDateTime, date );
0428     QDateTime d;
0429     try {
0430         d = Imap::LowLevelParser::parseRFC2822DateTime( line.toUtf8() );
0431     } catch ( Imap::ParseError& e ) {
0432         qDebug() << e.what();
0433     }
0434     QCOMPARE( d, date );
0435 }
0436 
0437 void ImapLowLevelParserTest::testGetRFC2822DateTime_data()
0438 {
0439     QTest::addColumn<QString>("line");
0440     QTest::addColumn<QDateTime>("date");
0441 
0442     /*
0443       courier-imap on woodpecker.gentoo.org won't convert the following:
0444     QTest::newRow("date-no-leading-zero")
0445         << QString("Fri Apr  3 00:21:52 UTC 2009")
0446         << QDateTime( QDate( 2009, 4, 3 ), QTime( 0, 21, 52), Qt::UTC );*/
0447 
0448     QTest::newRow("date-manual")
0449         << QStringLiteral("Wed, 09 Apr 2008 20:16:12 +0200")
0450         << QDateTime( QDate( 2008, 4, 9 ), QTime( 18, 16, 12 ), Qt::UTC );
0451 
0452     QTest::newRow("date-wo-weekday")
0453         << QStringLiteral("09 Apr 2008 20:16:12 +0200")
0454         << QDateTime( QDate( 2008, 4, 9 ), QTime( 18, 16, 12 ), Qt::UTC );
0455 
0456     QTest::newRow("date-no-weekday-no-zone")
0457         << QStringLiteral("08 Apr 2009 03:00:19")
0458         << QDateTime( QDate( 2009, 4, 8 ), QTime( 3, 0, 19 ), Qt::UTC );
0459 
0460     QTest::newRow("date-no-zone")
0461         << QStringLiteral("Wed, 08 Apr 2009 03:00:19")
0462         << QDateTime( QDate( 2009, 4, 8 ), QTime( 3, 0, 19 ), Qt::UTC );
0463 
0464     QTest::newRow("date-ut")
0465         << QStringLiteral("Wed, 09 Apr 2008 20:16:12 UT")
0466         << QDateTime( QDate( 2008, 4, 9 ), QTime( 20, 16, 12 ), Qt::UTC );
0467 
0468     QTest::newRow("date-gmt")
0469         << QStringLiteral("Wed, 09 Apr 2008 20:16:12 gMt")
0470         << QDateTime( QDate( 2008, 4, 9 ), QTime( 20, 16, 12 ), Qt::UTC );
0471 
0472     QTest::newRow("date-est")
0473         << QStringLiteral("Wed, 09 Apr 2008 13:16:12 est")
0474         << QDateTime( QDate( 2008, 4, 9 ), QTime( 18, 16, 12 ), Qt::UTC );
0475 
0476     QTest::newRow("date-edt")
0477         << QStringLiteral("Wed, 09 Apr 2008 13:16:12 edt")
0478         << QDateTime( QDate( 2008, 4, 9 ), QTime( 17, 16, 12 ), Qt::UTC );
0479 
0480     QTest::newRow("date-cst")
0481         << QStringLiteral("Wed, 09 Apr 2008 10:17:12 CST")
0482         << QDateTime( QDate( 2008, 4, 9 ), QTime( 16, 17, 12 ), Qt::UTC );
0483 
0484     QTest::newRow("date-cdt")
0485         << QStringLiteral("Wed, 09 Apr 2008 20:16:12 CDT")
0486         << QDateTime( QDate( 2008, 4, 10 ), QTime( 1, 16, 12 ), Qt::UTC );
0487 
0488     QTest::newRow("date-mst")
0489         << QStringLiteral("wEd, 09 APr 2001 20:16:12 mst")
0490         << QDateTime( QDate( 2001, 4, 10 ), QTime( 3, 16, 12 ), Qt::UTC );
0491 
0492     QTest::newRow("date-mdt")
0493         << QStringLiteral("Wed, 09 Apr 2008 20:16:12 mdT")
0494         << QDateTime( QDate( 2008, 4, 10 ), QTime( 2, 16, 12 ), Qt::UTC );
0495 
0496     QTest::newRow("date-pst")
0497         << QStringLiteral("Wed, 09 Apr 2008 20:16:12 pst")
0498         << QDateTime( QDate( 2008, 4, 10 ), QTime( 4, 16, 12 ), Qt::UTC );
0499 
0500     QTest::newRow("date-pdt")
0501         << QStringLiteral("Wed, 09 Apr 2008 20:16:12 pdt")
0502         << QDateTime( QDate( 2008, 4, 10 ), QTime( 3, 16, 12 ), Qt::UTC );
0503 
0504     QTest::newRow("date-a")
0505         << QStringLiteral("Wed, 09 Apr 2008 20:16:12 a")
0506         << QDateTime( QDate( 2008, 4, 9 ), QTime( 20, 16, 12 ), Qt::UTC );
0507 
0508     QTest::newRow("no-seconds")
0509         << QStringLiteral("Sat, 25 Aug 2012 20:12 +0200")
0510         << QDateTime(QDate(2012, 8, 25), QTime(18, 12, 0), Qt::UTC);
0511 
0512     QTest::newRow("single-digit-h-m-s")
0513         << QStringLiteral("Sat, 25 Aug 2012 5:2:1 +0200")
0514         << QDateTime(QDate(2012, 8, 25), QTime(3, 2, 1), Qt::UTC);
0515 
0516     int month = 1;
0517     int day = 1;
0518     QTime time( 0, 0, 0 );
0519     QStringList months = QStringList() << QStringLiteral("Jan") << QStringLiteral("FEb") << QStringLiteral("mar") << QStringLiteral("Apr") <<
0520         QStringLiteral("May") << QStringLiteral("Jun") << QStringLiteral("Jul") << QStringLiteral("AUG") << QStringLiteral("Sep") << QStringLiteral("Oct") << QStringLiteral("nOV") << QStringLiteral("Dec");
0521     QStringList wDays = QStringList() << QStringLiteral("Mon") << QStringLiteral("tue") << QStringLiteral("WED") << QStringLiteral("ThU") <<
0522         QStringLiteral("Fri") << QStringLiteral("Sat") << QStringLiteral("Sun");
0523     int tz = 11*60;
0524     bool plusOrSpace = false;
0525     for ( int year = 1970; year < 2035; year += 1, plusOrSpace = !plusOrSpace ) {
0526         QDateTime date( QDate( year, month, day), time, Qt::UTC );
0527         QString str = date.toString( QStringLiteral("%1, dd %2 yyyy hh:mm:ss %3%4%5") ).arg(
0528                         wDays[ date.date().dayOfWeek() - 1 ],
0529                         months[ month - 1 ],
0530                         ( tz >= 12* 60 ) ? ( plusOrSpace ? "" : "+" ) : "-"
0531                     ).arg(
0532                         qAbs(int( ( tz - 12*60 ) / 60 )), 2, 10, QChar('0')
0533                     ).arg (
0534                         qAbs( ( tz - 12 * 60 ) % 60 ), 2, 10, QChar('0') );
0535         date = date.addSecs( - 60 * tz + 12*3600 );
0536         QTest::newRow(static_cast<QByteArray>("date-generated-" + str.toUtf8()).data()) << str << date;
0537 
0538         month = qMax( ( month + 1 ) % 12, 1 );
0539         day = qMax( ( day + 3 ) % 31, 1 );
0540         time = time.addSecs( 3600 * 13 + 60 * 27 + 17 );
0541         tz = ( tz + 30 ) % ( 24 * 60 );
0542     }
0543     
0544 }
0545 
0546 QTEST_GUILESS_MAIN( ImapLowLevelParserTest )
0547 
0548 namespace QTest {
0549 
0550 template<> char * toString( const QPair<QStringList,QByteArray>& res )
0551 {
0552     QByteArray buf;
0553     QTextStream stream( &buf );
0554     stream << "first: " << res.first.join(QStringLiteral(", ")) << ", second: " << res.second;
0555     stream.flush();
0556     return qstrdup( buf.data() );
0557 }
0558 
0559 }