File indexing completed on 2024-11-10 04:40:17
0001 /* 0002 SPDX-FileCopyrightText: 2006 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "imapparsertest.h" 0008 #include "private/imapparser_p.h" 0009 #include <QTest> 0010 0011 #include <QBuffer> 0012 0013 Q_DECLARE_METATYPE(QList<QByteArray>) 0014 Q_DECLARE_METATYPE(QList<int>) 0015 0016 using namespace Akonadi; 0017 0018 QTEST_MAIN(ImapParserTest) 0019 0020 void ImapParserTest::testStripLeadingSpaces() 0021 { 0022 QByteArray input = " a "; 0023 int result; 0024 0025 // simple leading spaces at the beginning 0026 result = ImapParser::stripLeadingSpaces(input, 0); 0027 QCOMPARE(result, 2); 0028 0029 // simple leading spaces in the middle 0030 result = ImapParser::stripLeadingSpaces(input, 1); 0031 QCOMPARE(result, 2); 0032 0033 // no leading spaces 0034 result = ImapParser::stripLeadingSpaces(input, 2); 0035 QCOMPARE(result, 2); 0036 0037 // trailing spaces 0038 result = ImapParser::stripLeadingSpaces(input, 3); 0039 QCOMPARE(result, 5); 0040 0041 // out of bounds access 0042 result = ImapParser::stripLeadingSpaces(input, input.length()); 0043 QCOMPARE(result, input.length()); 0044 } 0045 0046 void ImapParserTest::testParseQuotedString() 0047 { 0048 QByteArray input = R"("quoted \"NIL\" string inside")"; 0049 QByteArray result; 0050 int consumed; 0051 0052 // the whole thing 0053 consumed = ImapParser::parseQuotedString(input, result, 0); 0054 QCOMPARE(result, QByteArray("quoted \"NIL\" string inside")); 0055 QCOMPARE(consumed, 32); 0056 0057 // unquoted string 0058 consumed = ImapParser::parseQuotedString(input, result, 1); 0059 QCOMPARE(result, QByteArray("quoted")); 0060 QCOMPARE(consumed, 7); 0061 0062 // whitespaces in quoted string 0063 consumed = ImapParser::parseQuotedString(input, result, 14); 0064 QCOMPARE(result, QByteArray(" string inside")); 0065 QCOMPARE(consumed, 32); 0066 0067 // whitespaces before unquoted string 0068 consumed = ImapParser::parseQuotedString(input, result, 15); 0069 QCOMPARE(result, QByteArray("string")); 0070 QCOMPARE(consumed, 24); 0071 0072 // NIL and emptiness tests 0073 input = R"(NIL "NIL" "")"; 0074 0075 // unquoted NIL 0076 consumed = ImapParser::parseQuotedString(input, result, 0); 0077 QVERIFY(result.isNull()); 0078 QCOMPARE(consumed, 3); 0079 0080 // quoted NIL 0081 consumed = ImapParser::parseQuotedString(input, result, 3); 0082 QCOMPARE(result, QByteArray("NIL")); 0083 QCOMPARE(consumed, 9); 0084 0085 // quoted empty string 0086 consumed = ImapParser::parseQuotedString(input, result, 9); 0087 QCOMPARE(result, QByteArray("")); 0088 QCOMPARE(consumed, 12); 0089 0090 // unquoted string at input end 0091 input = "some string"; 0092 consumed = ImapParser::parseQuotedString(input, result, 4); 0093 QCOMPARE(result, QByteArray("string")); 0094 QCOMPARE(consumed, 11); 0095 0096 // out of bounds access 0097 consumed = ImapParser::parseQuotedString(input, result, input.length()); 0098 QVERIFY(result.isEmpty()); 0099 QCOMPARE(consumed, input.length()); 0100 0101 // de-quoting 0102 input = R"("\"some \\ quoted stuff\"")"; 0103 consumed = ImapParser::parseQuotedString(input, result, 0); 0104 QCOMPARE(result, QByteArray("\"some \\ quoted stuff\"")); 0105 QCOMPARE(consumed, input.length()); 0106 0107 // linebreak as separator 0108 input = "LOGOUT\nFOO"; 0109 consumed = ImapParser::parseQuotedString(input, result, 0); 0110 QCOMPARE(result, QByteArray("LOGOUT")); 0111 QCOMPARE(consumed, 6); 0112 } 0113 0114 void ImapParserTest::testParseString() 0115 { 0116 QByteArray input = "\"quoted\" unquoted {7}\nliteral {0}\n empty literal"; 0117 QByteArray result; 0118 int consumed; 0119 0120 // quoted strings 0121 consumed = ImapParser::parseString(input, result, 0); 0122 QCOMPARE(result, QByteArray("quoted")); 0123 QCOMPARE(consumed, 8); 0124 0125 // unquoted string 0126 consumed = ImapParser::parseString(input, result, 8); 0127 QCOMPARE(result, QByteArray("unquoted")); 0128 QCOMPARE(consumed, 17); 0129 0130 // literal string 0131 consumed = ImapParser::parseString(input, result, 17); 0132 QCOMPARE(result, QByteArray("literal")); 0133 QCOMPARE(consumed, 29); 0134 0135 // empty literal string 0136 consumed = ImapParser::parseString(input, result, 29); 0137 QCOMPARE(result, QByteArray("")); 0138 QCOMPARE(consumed, 34); 0139 0140 // out of bounds access 0141 consumed = ImapParser::parseString(input, result, input.length()); 0142 QCOMPARE(result, QByteArray()); 0143 QCOMPARE(consumed, input.length()); 0144 } 0145 0146 void ImapParserTest::testParseParenthesizedList_data() 0147 { 0148 QTest::addColumn<QByteArray>("input"); 0149 QTest::addColumn<QList<QByteArray>>("result"); 0150 QTest::addColumn<int>("consumed"); 0151 0152 QList<QByteArray> reference; 0153 0154 QTest::newRow("null") << QByteArray() << reference << 0; 0155 QTest::newRow("empty") << QByteArray("()") << reference << 2; 0156 QTest::newRow("empty with space") << QByteArray(" ( )") << reference << 4; 0157 QTest::newRow("no list") << QByteArray("some list-less text") << reference << 0; 0158 QTest::newRow("\n") << QByteArray() << reference << 0; 0159 0160 reference << "entry1"; 0161 reference << "entry2()"; 0162 reference << "(sub list)"; 0163 reference << ")))"; 0164 reference << "entry3"; 0165 QTest::newRow("complex") << QByteArray("(entry1 \"entry2()\" (sub list) \")))\" {6}\nentry3) end") << reference << 47; 0166 0167 reference.clear(); 0168 reference << "foo"; 0169 reference << "\n\nbar\n"; 0170 reference << "bla"; 0171 QTest::newRow("newline literal") << QByteArray("(foo {6}\n\n\nbar\n bla)") << reference << 20; 0172 0173 reference.clear(); 0174 reference << "partid"; 0175 reference << "body"; 0176 QTest::newRow("CRLF literal separator") << QByteArray("(partid {4}\r\nbody)") << reference << 18; 0177 0178 reference.clear(); 0179 reference << "partid"; 0180 reference << "\n\rbody\n\r"; 0181 QTest::newRow("CRLF literal separator 2") << QByteArray("(partid {8}\r\n\n\rbody\n\r)") << reference << 22; 0182 0183 reference.clear(); 0184 reference << "NAME"; 0185 reference << "net)"; 0186 QTest::newRow("spurious newline") << QByteArray("(NAME \"net)\"\n)") << reference << 14; 0187 0188 reference.clear(); 0189 reference << "(42 \"net)\")"; 0190 reference << "(0 \"\")"; 0191 QTest::newRow("list of lists") << QByteArray("((42 \"net)\") (0 \"\"))") << reference << 20; 0192 } 0193 0194 void ImapParserTest::testParseParenthesizedList() 0195 { 0196 QFETCH(QByteArray, input); 0197 QFETCH(QList<QByteArray>, result); 0198 QFETCH(int, consumed); 0199 0200 QList<QByteArray> realResult; 0201 0202 int reallyConsumed = ImapParser::parseParenthesizedList(input, realResult, 0); 0203 QCOMPARE(realResult, result); 0204 QCOMPARE(reallyConsumed, consumed); 0205 0206 // briefly also test the other overload 0207 QVarLengthArray<QByteArray, 16> realVLAResult; 0208 reallyConsumed = ImapParser::parseParenthesizedList(input, realVLAResult, 0); 0209 QCOMPARE(reallyConsumed, consumed); 0210 0211 // newline literal (based on itemappendtest bug) 0212 input = "(foo {6}\n\n\nbar\n bla)"; 0213 ImapParser::parseParenthesizedList(input, result); 0214 } 0215 0216 void ImapParserTest::testParseNumber() 0217 { 0218 QByteArray input = " 1a23.4"; 0219 qint64 result; 0220 int pos; 0221 bool ok; 0222 0223 // empty string 0224 pos = ImapParser::parseNumber(QByteArray(), result, &ok); 0225 QCOMPARE(ok, false); 0226 QCOMPARE(pos, 0); 0227 0228 // leading spaces at the beginning 0229 pos = ImapParser::parseNumber(input, result, &ok, 0); 0230 QCOMPARE(ok, true); 0231 QCOMPARE(pos, 2); 0232 QCOMPARE(result, 1LL); 0233 0234 // multiple digits 0235 pos = ImapParser::parseNumber(input, result, &ok, 3); 0236 QCOMPARE(ok, true); 0237 QCOMPARE(pos, 5); 0238 QCOMPARE(result, 23LL); 0239 0240 // number at input end 0241 pos = ImapParser::parseNumber(input, result, &ok, 6); 0242 QCOMPARE(ok, true); 0243 QCOMPARE(pos, 7); 0244 QCOMPARE(result, 4LL); 0245 0246 // out of bounds access 0247 pos = ImapParser::parseNumber(input, result, &ok, input.length()); 0248 QCOMPARE(ok, false); 0249 QCOMPARE(pos, input.length()); 0250 } 0251 0252 void ImapParserTest::testQuote_data() 0253 { 0254 QTest::addColumn<QByteArray>("unquoted"); 0255 QTest::addColumn<QByteArray>("quoted"); 0256 0257 QTest::newRow("empty") << QByteArray("") << QByteArray("\"\""); 0258 QTest::newRow("simple") << QByteArray("bla") << QByteArray("\"bla\""); 0259 QTest::newRow("double-quotes") << QByteArray(R"("test"test")") << QByteArray(R"("\"test\"test\"")"); 0260 QTest::newRow("backslash") << QByteArray("\\") << QByteArray(R"("\\")"); 0261 QByteArray binaryNonEncoded; 0262 binaryNonEncoded += '\000'; 0263 QByteArray binaryEncoded("\""); 0264 binaryEncoded += '\000'; 0265 binaryEncoded += '"'; 0266 QTest::newRow("binary") << binaryNonEncoded << binaryEncoded; 0267 0268 QTest::newRow("LF") << QByteArray("\n") << QByteArray(R"("\n")"); 0269 QTest::newRow("CR") << QByteArray("\r") << QByteArray(R"("\r")"); 0270 QTest::newRow("double quote") << QByteArray("\"") << QByteArray(R"("\"")"); 0271 QTest::newRow("mixed 1") << QByteArray("a\nb\\c") << QByteArray(R"("a\nb\\c")"); 0272 QTest::newRow("mixed 2") << QByteArray("\"a\rb\"") << QByteArray(R"("\"a\rb\"")"); 0273 } 0274 0275 void ImapParserTest::testQuote() 0276 { 0277 QFETCH(QByteArray, unquoted); 0278 QFETCH(QByteArray, quoted); 0279 QCOMPARE(ImapParser::quote(unquoted), quoted); 0280 } 0281 0282 void ImapParserTest::testMessageParser_data() 0283 { 0284 QTest::addColumn<QList<QByteArray>>("input"); 0285 QTest::addColumn<QByteArray>("tag"); 0286 QTest::addColumn<QByteArray>("data"); 0287 QTest::addColumn<bool>("complete"); 0288 QTest::addColumn<QList<int>>("continuations"); 0289 0290 QList<QByteArray> input; 0291 QList<int> continuations; 0292 QTest::newRow("empty") << input << QByteArray() << QByteArray() << false << continuations; 0293 0294 input << "*"; 0295 QTest::newRow("tag-only") << input << QByteArray("*") << QByteArray() << true << continuations; 0296 0297 input.clear(); 0298 input << "20 UID FETCH (foo)"; 0299 QTest::newRow("simple") << input << QByteArray("20") << QByteArray("UID FETCH (foo)") << true << continuations; 0300 0301 input.clear(); 0302 input << "1 (bla (" 0303 << ") blub)"; 0304 QTest::newRow("parenthesis") << input << QByteArray("1") << QByteArray("(bla () blub)") << true << continuations; 0305 0306 input.clear(); 0307 input << "1 {3}" 0308 << "bla"; 0309 continuations << 0; 0310 QTest::newRow("literal") << input << QByteArray("1") << QByteArray("{3}bla") << true << continuations; 0311 0312 input.clear(); 0313 input << "1 FETCH (UID 5 DATA {3}" 0314 << "bla" 0315 << " RID 5)"; 0316 QTest::newRow("parenthesisEnclosedLiteral") << input << QByteArray("1") << QByteArray("FETCH (UID 5 DATA {3}bla RID 5)") << true << continuations; 0317 0318 input.clear(); 0319 input << "1 {3}" 0320 << "bla {4}" 0321 << "blub"; 0322 continuations.clear(); 0323 continuations << 0 << 1; 0324 QTest::newRow("2literal") << input << QByteArray("1") << QByteArray("{3}bla {4}blub") << true << continuations; 0325 0326 input.clear(); 0327 input << "1 {4}" 0328 << "A{9}"; 0329 continuations.clear(); 0330 continuations << 0; 0331 QTest::newRow("literal in literal") << input << QByteArray("1") << QByteArray("{4}A{9}") << true << continuations; 0332 0333 input.clear(); 0334 input << "* FETCH (UID 1 DATA {3}" 0335 << "bla" 0336 << " ENVELOPE {4}" 0337 << "blub" 0338 << " RID 5)"; 0339 continuations.clear(); 0340 continuations << 0 << 2; 0341 QTest::newRow("enclosed2literal") << input << QByteArray("*") << QByteArray("FETCH (UID 1 DATA {3}bla ENVELOPE {4}blub RID 5)") << true << continuations; 0342 0343 input.clear(); 0344 input << "1 DATA {0}"; 0345 continuations.clear(); 0346 QTest::newRow("empty literal") << input << QByteArray("1") << QByteArray("DATA {0}") << true << continuations; 0347 } 0348 0349 void ImapParserTest::testMessageParser() 0350 { 0351 QFETCH(QList<QByteArray>, input); 0352 QFETCH(QByteArray, tag); 0353 QFETCH(QByteArray, data); 0354 QFETCH(bool, complete); 0355 QFETCH(QList<int>, continuations); 0356 QList<int> cont = continuations; 0357 0358 auto parser = new ImapParser(); 0359 QVERIFY(parser->tag().isEmpty()); 0360 QVERIFY(parser->data().isEmpty()); 0361 0362 for (int i = 0; i < input.count(); ++i) { 0363 bool res = parser->parseNextLine(input.at(i)); 0364 if (i != input.count() - 1) { 0365 QVERIFY(!res); 0366 } else { 0367 QCOMPARE(res, complete); 0368 } 0369 if (parser->continuationStarted()) { 0370 QVERIFY(cont.contains(i)); 0371 cont.removeAll(i); 0372 } 0373 } 0374 0375 QCOMPARE(parser->tag(), tag); 0376 QCOMPARE(parser->data(), data); 0377 QVERIFY(cont.isEmpty()); 0378 0379 // try again, this time with a not fresh parser 0380 parser->reset(); 0381 QVERIFY(parser->tag().isEmpty()); 0382 QVERIFY(parser->data().isEmpty()); 0383 cont = continuations; 0384 0385 for (int i = 0; i < input.count(); ++i) { 0386 bool res = parser->parseNextLine(input.at(i)); 0387 if (i != input.count() - 1) { 0388 QVERIFY(!res); 0389 } else { 0390 QCOMPARE(res, complete); 0391 } 0392 if (parser->continuationStarted()) { 0393 QVERIFY(cont.contains(i)); 0394 cont.removeAll(i); 0395 } 0396 } 0397 0398 QCOMPARE(parser->tag(), tag); 0399 QCOMPARE(parser->data(), data); 0400 QVERIFY(cont.isEmpty()); 0401 0402 delete parser; 0403 } 0404 0405 void ImapParserTest::testParseSequenceSet_data() 0406 { 0407 QTest::addColumn<QByteArray>("data"); 0408 QTest::addColumn<int>("begin"); 0409 QTest::addColumn<ImapInterval::List>("result"); 0410 QTest::addColumn<int>("end"); 0411 0412 QByteArray data(" 1 0:* 3:4,8:* *:5,1"); 0413 0414 QTest::newRow("empty") << QByteArray() << 0 << ImapInterval::List() << 0; 0415 QTest::newRow("input end") << data << 20 << ImapInterval::List() << 20; 0416 0417 ImapInterval::List result; 0418 result << ImapInterval(1, 1); 0419 QTest::newRow("single value 1") << data << 0 << result << 2; 0420 QTest::newRow("single value 2") << data << 1 << result << 2; 0421 QTest::newRow("single value 3") << data << 19 << result << 20; 0422 0423 result.clear(); 0424 result << ImapInterval(); 0425 QTest::newRow("full interval") << data << 2 << result << 6; 0426 0427 result.clear(); 0428 result << ImapInterval(3, 4) << ImapInterval(8); 0429 QTest::newRow("complex 1") << data << 7 << result << 14; 0430 0431 result.clear(); 0432 result << ImapInterval(0, 5) << ImapInterval(1, 1); 0433 QTest::newRow("complex 2") << data << 14 << result << 20; 0434 } 0435 0436 void ImapParserTest::testParseSequenceSet() 0437 { 0438 QFETCH(QByteArray, data); 0439 QFETCH(int, begin); 0440 QFETCH(ImapInterval::List, result); 0441 QFETCH(int, end); 0442 0443 ImapSet res; 0444 int pos = ImapParser::parseSequenceSet(data, res, begin); 0445 QCOMPARE(res.intervals(), result); 0446 QCOMPARE(pos, end); 0447 } 0448 0449 void ImapParserTest::testParseDateTime_data() 0450 { 0451 QTest::addColumn<QByteArray>("data"); 0452 QTest::addColumn<int>("begin"); 0453 QTest::addColumn<QDateTime>("result"); 0454 QTest::addColumn<int>("end"); 0455 0456 QTest::newRow("empty") << QByteArray() << 0 << QDateTime() << 0; 0457 0458 QByteArray data(" \"28-May-2006 01:03:35 +0200\""); 0459 QByteArray data2("22-Jul-2008 16:31:48 +0000"); 0460 0461 QDateTime dt(QDate(2006, 5, 27), QTime(23, 3, 35), QTimeZone::UTC); 0462 QDateTime dt2(QDate(2008, 7, 22), QTime(16, 31, 48), QTimeZone::UTC); 0463 0464 QTest::newRow("quoted 1") << data << 0 << dt << 29; 0465 QTest::newRow("quoted 2") << data << 1 << dt << 29; 0466 QTest::newRow("unquoted") << data << 2 << dt << 28; 0467 QTest::newRow("unquoted2") << data2 << 0 << dt2 << 26; 0468 QTest::newRow("invalid") << data << 4 << QDateTime() << 4; 0469 } 0470 0471 void ImapParserTest::testParseDateTime() 0472 { 0473 QFETCH(QByteArray, data); 0474 QFETCH(int, begin); 0475 QFETCH(QDateTime, result); 0476 QFETCH(int, end); 0477 0478 QDateTime actualResult; 0479 int actualEnd = ImapParser::parseDateTime(data, actualResult, begin); 0480 QCOMPARE(actualResult, result); 0481 QCOMPARE(actualEnd, end); 0482 } 0483 0484 void ImapParserTest::testBulkParser_data() 0485 { 0486 QTest::addColumn<QByteArray>("input"); 0487 QTest::addColumn<QByteArray>("data"); 0488 0489 QTest::newRow("empty") << QByteArray("* PRE {0} POST\n") << QByteArray("PRE {0} POST\n"); 0490 QTest::newRow("small block") << QByteArray("* PRE {2}\nXX POST\n") << QByteArray("PRE {2}\nXX POST\n"); 0491 QTest::newRow("small block 2") << QByteArray("* (PRE {2}\nXX\n POST)\n") << QByteArray("(PRE {2}\nXX\n POST)\n"); 0492 QTest::newRow("large block") << QByteArray("* PRE {10}\n0123456789\n") << QByteArray("PRE {10}\n0123456789\n"); 0493 QTest::newRow("store failure") << QByteArray("3 UID STORE (FOO bar ENV {3}\n(a) HEAD {3}\na\n\n BODY {3}\nabc)\n") 0494 << QByteArray("UID STORE (FOO bar ENV {3}\n(a) HEAD {3}\na\n\n BODY {3}\nabc)\n"); 0495 } 0496 0497 void ImapParserTest::testBulkParser() 0498 { 0499 QFETCH(QByteArray, input); 0500 QFETCH(QByteArray, data); 0501 0502 auto parser = new ImapParser(); 0503 QBuffer buffer; 0504 buffer.setData(input); 0505 QVERIFY(buffer.open(QBuffer::ReadOnly)); 0506 0507 // reading continuation as a single block 0508 for (;;) { 0509 if (buffer.atEnd()) { 0510 break; 0511 } 0512 if (parser->continuationSize() > 0) { 0513 parser->parseBlock(buffer.read(parser->continuationSize())); 0514 } else if (buffer.canReadLine()) { 0515 const QByteArray line = buffer.readLine(); 0516 bool res = parser->parseNextLine(line); 0517 QCOMPARE(res, buffer.atEnd()); 0518 } 0519 } 0520 QCOMPARE(parser->data(), data); 0521 0522 // reading continuations as smaller blocks 0523 buffer.reset(); 0524 parser->reset(); 0525 for (;;) { 0526 if (buffer.atEnd()) { 0527 break; 0528 } 0529 if (parser->continuationSize() > 4) { 0530 parser->parseBlock(buffer.read(4)); 0531 } else if (parser->continuationSize() > 0) { 0532 parser->parseBlock(buffer.read(parser->continuationSize())); 0533 } else if (buffer.canReadLine()) { 0534 bool res = parser->parseNextLine(buffer.readLine()); 0535 QCOMPARE(res, buffer.atEnd()); 0536 } 0537 } 0538 0539 delete parser; 0540 } 0541 0542 void ImapParserTest::testJoin_data() 0543 { 0544 QTest::addColumn<QList<QByteArray>>("list"); 0545 QTest::addColumn<QByteArray>("joined"); 0546 QTest::newRow("empty") << QList<QByteArray>() << QByteArray(); 0547 QTest::newRow("one") << (QList<QByteArray>() << "abab") << QByteArray("abab"); 0548 QTest::newRow("two") << (QList<QByteArray>() << "abab" 0549 << "cdcd") 0550 << QByteArray("abab cdcd"); 0551 QTest::newRow("three") << (QList<QByteArray>() << "abab" 0552 << "cdcd" 0553 << "efef") 0554 << QByteArray("abab cdcd efef"); 0555 } 0556 0557 void ImapParserTest::testJoin() 0558 { 0559 QFETCH(QList<QByteArray>, list); 0560 QFETCH(QByteArray, joined); 0561 QCOMPARE(ImapParser::join(list, " "), joined); 0562 } 0563 0564 void ImapParserTest::benchParseQuotedString_data() 0565 { 0566 QTest::addColumn<QByteArray>("data"); 0567 QTest::addColumn<QByteArray>("expectedResult"); 0568 QTest::addColumn<int>("expectedConsumed"); 0569 0570 QTest::newRow("quoted") << QByteArray("\"foo bar asdf\"") << QByteArray("foo bar asdf") << 14; 0571 QTest::newRow("unquoted") << QByteArray("foo bar asdf") << QByteArray("foo") << 3; 0572 } 0573 0574 void ImapParserTest::benchParseQuotedString() 0575 { 0576 QFETCH(QByteArray, data); 0577 QFETCH(QByteArray, expectedResult); 0578 QFETCH(int, expectedConsumed); 0579 0580 QByteArray result; 0581 QBENCHMARK { 0582 int consumed = ImapParser::parseQuotedString(data, result, 0); 0583 // use data, to prevent it from getting optimized away 0584 if (consumed != expectedConsumed || result != expectedResult) { 0585 // NOTE: don't use QCOMPARE in the outer hot loop, it's quite slow 0586 // just do it when something fails 0587 QCOMPARE(result, expectedResult); 0588 QCOMPARE(consumed, expectedConsumed); 0589 } 0590 } 0591 } 0592 0593 #include "moc_imapparsertest.cpp"