File indexing completed on 2024-04-21 05:18:10

0001 /*
0002     SPDX-FileCopyrightText: 2006 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #undef QT_USE_FAST_CONCATENATION
0008 #undef QT_USE_FAST_OPERATOR_PLUS
0009 
0010 #include <QTest>
0011 
0012 #include "utiltest.h"
0013 
0014 #include <kmime_charfreq.cpp>
0015 #include <kmime_util_p.cpp>
0016 #include "kmime_message.h"
0017 
0018 using namespace KMime;
0019 
0020 QTEST_MAIN(UtilTest)
0021 
0022 void UtilTest::testUnfoldHeader()
0023 {
0024     // empty header
0025     QCOMPARE(KMime::unfoldHeader(""), QByteArray());
0026     // identity
0027     QCOMPARE(KMime::unfoldHeader("bla"), QByteArray("bla"));
0028     // single folding
0029     QCOMPARE(KMime::unfoldHeader("bla\nblub"), QByteArray("bla blub"));
0030     QCOMPARE(KMime::unfoldHeader("bla\n \t blub"), QByteArray("bla blub"));
0031     QCOMPARE(KMime::unfoldHeader("bla   \r\nblub"), QByteArray("bla blub"));
0032     // multiple folding
0033     QCOMPARE(KMime::unfoldHeader("bla\nbla\nblub"), QByteArray("bla bla blub"));
0034     QCOMPARE(KMime::unfoldHeader("bla  \r\n   bla  \r\n  blub"), QByteArray("bla bla blub"));
0035     QCOMPARE(KMime::unfoldHeader("bla\n"), QByteArray("bla"));
0036     // bug #86302 - malformed header continuation
0037     QCOMPARE(KMime::unfoldHeader("bla\n=20bla"), QByteArray("bla bla"));
0038     QCOMPARE(KMime::unfoldHeader("bla\n=09bla"), QByteArray("bla bla"));
0039     QCOMPARE(KMime::unfoldHeader("bla\r\n=20bla"), QByteArray("bla bla"));
0040     QCOMPARE(KMime::unfoldHeader("bla\r\n=09bla"), QByteArray("bla bla"));
0041     QCOMPARE(KMime::unfoldHeader("bla \n=20 bla"), QByteArray("bla bla"));
0042     QCOMPARE(KMime::unfoldHeader("bla \n=09 bla"), QByteArray("bla bla"));
0043     QCOMPARE(KMime::unfoldHeader("bla \n =20 bla"), QByteArray("bla =20 bla"));
0044     QCOMPARE(KMime::unfoldHeader("bla \n =09 bla"), QByteArray("bla =09 bla"));
0045     // malformed input resulting in leading linebreaks
0046     QCOMPARE(KMime::unfoldHeader("\n bla"), QByteArray("bla"));
0047     QCOMPARE(KMime::unfoldHeader("\r\n bla"), QByteArray("bla"));
0048 }
0049 
0050 void UtilTest::testFoldHeader()
0051 {
0052     // no folding required
0053     // -------------------
0054 
0055     // <78 characters
0056     QCOMPARE(KMime::foldHeader("To: foo@bar"), QByteArray("To: foo@bar"));
0057     // exactly 78 characters
0058     QCOMPARE(KMime::foldHeader("To: fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaar"),
0059                     QByteArray("To: fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaar"));
0060 
0061     // folding required
0062     // ----------------
0063 
0064     // exactly 79 characters
0065     QCOMPARE(KMime::foldHeader("To: fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"),
0066                     QByteArray("To:\n fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"));
0067 
0068     // >78 characters
0069     QCOMPARE(KMime::foldHeader("To: some@where, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"),
0070                     QByteArray("To: some@where,\n fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"));
0071 
0072     QCOMPARE(KMime::foldHeader("To: some@where, some@else, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"),
0073                     QByteArray("To: some@where, some@else,\n fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"));
0074 
0075     QCOMPARE(KMime::foldHeader("To: Some Body <some@where>, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"),
0076                     QByteArray("To: Some Body <some@where>,\n fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"));
0077 
0078     QCOMPARE(KMime::foldHeader("To: \"Some Body\" <some@where>, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"),
0079                     QByteArray("To: \"Some Body\" <some@where>,\n fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"));
0080 
0081     QCOMPARE(KMime::foldHeader("To: Some Body <some@where>, John Doe <some@else>, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"),
0082                     QByteArray("To: Some Body <some@where>, John Doe <some@else>,\n fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"));
0083 
0084     QCOMPARE(KMime::foldHeader("To: \"Some Body\" <some@where>, \"John Doe\" <some@else>, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"),
0085                     QByteArray("To: \"Some Body\" <some@where>, \"John Doe\" <some@else>,\n fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaaaaaaaaaar"));
0086 
0087     QCOMPARE(KMime::foldHeader("To: Some Body <some@where>, Aaaa Bbb <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"),
0088                     QByteArray("To: Some Body <some@where>,\n Aaaa Bbb <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"));
0089 
0090     QCOMPARE(KMime::foldHeader("To: \"Some Body\" <some@where>, \"Aaaa Bbb\" <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"),
0091                     QByteArray("To: \"Some Body\" <some@where>,\n \"Aaaa Bbb\" <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"));
0092 
0093     QCOMPARE(KMime::foldHeader("To: Some Body <some@where>, John Doe <some@else>, Aaaa Bbb <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"),
0094                     QByteArray("To: Some Body <some@where>, John Doe <some@else>,\n Aaaa Bbb <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"));
0095 
0096     QCOMPARE(KMime::foldHeader("To: \"Some Body\" <some@where>, \"John Doe\" <some@else>, \"Aaaa Bbb\" <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"),
0097                     QByteArray("To: \"Some Body\" <some@where>, \"John Doe\" <some@else>,\n \"Aaaa Bbb\" <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"));
0098 
0099     // avoid splitting at comma within quoted string (allowed but discouraged)
0100     QCOMPARE(KMime::foldHeader("To: \"Body, Some\" <some@where>, \"Doe, John\" <some@else>, \"Bbb, Aaaa\" <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"),
0101                     QByteArray("To: \"Body, Some\" <some@where>, \"Doe, John\" <some@else>,\n \"Bbb, Aaaa\" <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"));
0102 
0103     // ignore escaped double quote within quoted string
0104     QCOMPARE(KMime::foldHeader("To: \"\\\"Body, Some\" <some@where>, \"\\\"Doe, John\" <some@else>, \"\\\"Bbb, Aaaa\" <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"),
0105                     QByteArray("To: \"\\\"Body, Some\" <some@where>, \"\\\"Doe, John\" <some@else>,\n \"\\\"Bbb, Aaaa\" <aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb>"));
0106 
0107     // escaped backslashes, followed by escaped double quote within quoted string
0108     QCOMPARE(KMime::foldHeader("To: \"Body\\\\\\\\\\\", Some\\\\\\\\\" <some@where>, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb"),
0109                     QByteArray("To: \"Body\\\\\\\\\\\", Some\\\\\\\\\" <some@where>,\n aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbb"));
0110 
0111     // don't remove already inserted folding
0112     QCOMPARE(KMime::foldHeader("To: some@where,\n some@else"),
0113                     QByteArray("To: some@where,\n some@else"));
0114 
0115     // honor already inserted folding: no additional folding required
0116     QCOMPARE(KMime::foldHeader("To: some@where,\n some@else, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaar"),
0117                     QByteArray("To: some@where,\n some@else, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaar"));
0118 
0119     // honor already inserted folding: fold at correct position
0120     QCOMPARE(KMime::foldHeader("To: some@where,\n some@else, fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaar"),
0121                     QByteArray("To: some@where,\n some@else,\n fooooooooooooooooooooooooooooooooooooooooooooooooooooooooo@baaaaaar"));
0122 }
0123 
0124 void UtilTest::testExtractHeader()
0125 {
0126     QByteArray header("To: <foo@bla.org>\n"
0127                       "Subject: =?UTF-8?Q?_Notification_for_appointment:?=\n"
0128                       " =?UTF-8?Q?_Test?=\n"
0129                       "Continuation: =?UTF-8?Q?_TEST\n"
0130                       "=20CONT1?= =?UTF-8?Q?_TEST\n"
0131                       "=09CONT2?=\n"
0132                       "MIME-Version: 1.0");
0133 
0134     // basic tests
0135     QVERIFY(extractHeader(header, "Foo").isEmpty());
0136     QCOMPARE(extractHeader(header, "To"), QByteArray("<foo@bla.org>"));
0137 
0138     // case insensitive matching
0139     QCOMPARE(extractHeader(header, "mime-version"), QByteArray("1.0"));
0140 
0141     // extraction of multi-line headers
0142     QCOMPARE(extractHeader(header, "Subject"),
0143              QByteArray("=?UTF-8?Q?_Notification_for_appointment:?= =?UTF-8?Q?_Test?="));
0144 
0145     // bug #86302 - malformed header continuation
0146     QCOMPARE(extractHeader(header, "Continuation"),
0147              QByteArray("=?UTF-8?Q?_TEST CONT1?= =?UTF-8?Q?_TEST CONT2?="));
0148 
0149     // missing space after ':'
0150     QCOMPARE(extractHeader("From:<toma@kovoks.nl>", "From"), QByteArray("<toma@kovoks.nl>"));
0151 }
0152 
0153 void UtilTest::testBalanceBidiState()
0154 {
0155     QFETCH(QString, input);
0156     QFETCH(QString, expResult);
0157 
0158     QCOMPARE(balanceBidiState(input), expResult);
0159 }
0160 
0161 void UtilTest::testBalanceBidiState_data()
0162 {
0163     QTest::addColumn<QString>("input");
0164     QTest::addColumn<QString>("expResult");
0165 
0166     const QString LRO(QChar(0x202D));
0167     const QString RLO(QChar(0x202E));
0168     const QString LRE(QChar(0x202A));
0169     const QString RLE(QChar(0x202B));
0170     const QString PDF(QChar(0x202C));
0171 
0172     QTest::newRow("") << QString::fromLatin1("Normal") << QString::fromLatin1("Normal");
0173     QTest::newRow("") << RLO + QString::fromLatin1("Balanced") + PDF << RLO + QString::fromLatin1("Balanced") + PDF;
0174     QTest::newRow("") << RLO + QString::fromLatin1("MissingPDF1") << RLO + QString::fromLatin1("MissingPDF1") + PDF;
0175     QTest::newRow("") << QString::fromLatin1("\"") + RLO + QString::fromLatin1("Quote\"") << QString::fromLatin1("\"") + RLO + QString::fromLatin1("Quote") + PDF + QString::fromLatin1("\"");
0176     QTest::newRow("") << QString::fromLatin1("MissingPDF2") + RLO << QString::fromLatin1("MissingPDF2") + RLO + PDF;
0177     QTest::newRow("") << RLO + QString::fromLatin1("MultipleRLO") + RLO << RLO + QString::fromLatin1("MultipleRLO") + RLO + PDF + PDF;
0178     QTest::newRow("") << LRO + QString::fromLatin1("Mixed") + LRE + RLE + RLO + QString::fromLatin1("Bla")
0179                       << LRO + QString::fromLatin1("Mixed") + LRE + RLE + RLO + QString::fromLatin1("Bla") + PDF.repeated(4);
0180     QTest::newRow("") << RLO + QString::fromLatin1("TooManyPDF") + PDF + RLO + PDF + PDF
0181                       << RLO + QString::fromLatin1("TooManyPDF") + PDF + RLO + PDF;
0182     QTest::newRow("") << PDF + QString::fromLatin1("WrongOrder") + RLO
0183                       << QString::fromLatin1("WrongOrder") + RLO + PDF;
0184     QTest::newRow("") << QString::fromLatin1("ComplexOrder") + RLO + PDF + PDF + RLO
0185                       << QString::fromLatin1("ComplexOrder") + RLO + PDF + RLO + PDF;
0186     QTest::newRow("") << QString::fromLatin1("ComplexOrder2") + RLO + PDF + PDF + PDF + RLO + PDF + PDF + PDF
0187                       << QString::fromLatin1("ComplexOrder2") + RLO + PDF + RLO + PDF;
0188     QTest::newRow("") << PDF + PDF + PDF + QString::fromLatin1("ComplexOrder3") + PDF + PDF + RLO + PDF + PDF + PDF
0189                       << QString::fromLatin1("ComplexOrder3") + RLO + PDF;
0190 }
0191 
0192 void UtilTest::testAddQuotes()
0193 {
0194     QFETCH(QByteArray, input);
0195     QFETCH(QByteArray, expResult);
0196     QFETCH(bool, forceQuotes);
0197 
0198     addQuotes(input, forceQuotes);
0199     QCOMPARE(input.data(), expResult.data());
0200 }
0201 
0202 void UtilTest::testAddQuotes_data()
0203 {
0204     QTest::addColumn<QByteArray>("input");
0205     QTest::addColumn<QByteArray>("expResult");
0206     QTest::addColumn<bool>("forceQuotes");
0207 
0208     QTest::newRow("") << QByteArray("Test") << QByteArray("Test") << false;
0209     QTest::newRow("") << QByteArray("Test") << QByteArray("\"Test\"") << true;
0210     QTest::newRow("") << QByteArray("Lastname, Firstname")
0211                       << QByteArray("\"Lastname, Firstname\"") << false;
0212     QTest::newRow("") << QByteArray("John \"the hacker\" Smith")
0213                       << QByteArray(R"("John \"the hacker\" Smith")") << false;
0214 
0215     // Test the whole thing on strings as well, for one example
0216     QString string(QLatin1StringView("John \"the hacker\" Smith"));
0217     addQuotes(string, false);
0218     QCOMPARE(string, QString::fromLatin1("\"John \\\"the hacker\\\" Smith\""));
0219 }
0220 
0221 void UtilTest::testIsSigned_data()
0222 {
0223     QTest::addColumn<QByteArray>("input");
0224     QTest::addColumn<bool>("hasSignature");
0225 
0226     QTest::newRow("pgp") << QByteArray(
0227                              "From: xxx xxx <xxx@xxx.xxx>\n"
0228                              "To: xxx xxx <xxx@xxx.xxx>\n"
0229                              "Subject: Re: xxx\n"
0230                              "Date: Mon, 13 Dec 2010 12:22:03 +0100\n"
0231                              "MIME-Version: 1.0\n"
0232                              "Content-Type: multipart/signed;\n"
0233                              "  boundary=\"nextPart1571960.gHxU0aGA9V\";\n"
0234                              "  protocol=\"application/pgp-signature\";\n"
0235                              "  micalg=pgp-sha1\n"
0236                              "Content-Transfer-Encoding: 7bit\n\n"
0237                              "--nextPart1571960.gHxU0aGA9V\n"
0238                              "Content-Type: text/plain;\n"
0239                              "  charset=\"iso-8859-15\"\n"
0240                              "Content-Transfer-Encoding: quoted-printable\n"
0241                              "Content-Disposition: inline\n\n"
0242                              "Hi there...\n\n"
0243                              "--nextPart1571960.gHxU0aGA9V\n"
0244                              "Content-Type: application/pgp-signature; name=signature.asc\n"
0245                              "Content-Description: This is a digitally signed message part.\n\n"
0246                              "-----BEGIN PGP SIGNATURE-----\n"
0247                              "Version: GnuPG v2.0.15 (GNU/Linux)\n"
0248                              "...\n"
0249                              "-----END PGP SIGNATURE-----\n\n"
0250                              "--nextPart1571960.gHxU0aGA9V--\n"
0251                          ) << true;
0252 }
0253 
0254 void UtilTest::testIsSigned()
0255 {
0256     QFETCH(QByteArray, input);
0257     QFETCH(bool, hasSignature);
0258 
0259     KMime::Message::Ptr msg(new KMime::Message);
0260     msg->setContent(input);
0261     msg->parse();
0262     QCOMPARE(isSigned(msg.data()), hasSignature);
0263 }
0264 
0265 void UtilTest::testIsCryptoPart_data()
0266 {
0267     QTest::addColumn<QByteArray>("mimeType");
0268     QTest::addColumn<QString>("fileName");
0269     QTest::addColumn<bool>("isCrypto");
0270 
0271     QTest::newRow("pgp-encrypted") << QByteArray("application/pgp-encrypted") << QString() << true;
0272     QTest::newRow("pgp-encrypted upper case") << QByteArray("APPLICATION/PGP-ENCRYPTED") << QString() << true;
0273     QTest::newRow("pgp-signature") << QByteArray("application/pgp-signature") << QString() << true;
0274     QTest::newRow("pkcs7-mime") << QByteArray("application/pkcs7-mime") << QString() << true;
0275     QTest::newRow("pkcs7-signature") << QByteArray("application/pkcs7-signature") << QString() << true;
0276     QTest::newRow("x-pkcs7-signature") << QByteArray("application/x-pkcs7-signature") << QString() << true;
0277     QTest::newRow("msg.asc") << QByteArray("application/octet-stream") << QStringLiteral("msg.asc") << true;
0278     QTest::newRow("msg.asc upper case") << QByteArray("application/octet-stream") << QStringLiteral("MSG.ASC") << true;
0279     QTest::newRow("encrypted.asc") << QByteArray("application/octet-stream") << QStringLiteral("encrypted.asc") << true;
0280     QTest::newRow("octet-stream") << QByteArray("application/octet-stream") << QStringLiteral("bla.foo") << false;
0281     QTest::newRow("wrong mimetype") << QByteArray("application/foo") << QString() << false;
0282     QTest::newRow("text") << QByteArray("text/plain") << QString() << false;
0283     QTest::newRow("encrypted.asc wrong type") << QByteArray("application/foo") << QStringLiteral("encrypted.asc") << false;
0284     QTest::newRow("msc.asc wrong type") << QByteArray("application/foo") << QStringLiteral("msc.asc") << false;
0285 }
0286 
0287 void UtilTest::testIsCryptoPart()
0288 {
0289     QFETCH(QByteArray, mimeType);
0290     QFETCH(QString, fileName);
0291     QFETCH(bool, isCrypto);
0292 
0293     KMime::Content c;
0294     c.contentType()->setMimeType(mimeType);
0295     c.contentDisposition()->setFilename(fileName);
0296 
0297     QCOMPARE(KMime::isCryptoPart(&c), isCrypto);
0298 }
0299 
0300 void UtilTest::testLFCRLF_data()
0301 {
0302     QTest::addColumn<QByteArray>("input");
0303     QTest::addColumn<QByteArray>("expected");
0304     QTest::addColumn<QByteArray>("convertedBack");
0305 
0306     const QByteArray noNewline("no newline character");
0307     QTest::newRow("none") << noNewline << noNewline << noNewline;
0308     QTest::newRow("alone") << QByteArray("\n") << QByteArray("\r\n") << QByteArray("\n");
0309     QTest::newRow("CRLF") << QByteArray("\r\n") << QByteArray("\r\n") << QByteArray("\n");
0310     QTest::newRow("single_first") << QByteArray("\nfoo") << QByteArray("\r\nfoo") << QByteArray("\nfoo");
0311     QTest::newRow("single_last") << QByteArray("foo\n") << QByteArray("foo\r\n") << QByteArray("foo\n");
0312     QTest::newRow("single_two_lines") << QByteArray("foo\nbar") << QByteArray("foo\r\nbar") << QByteArray("foo\nbar");
0313     QTest::newRow("two_lines") << QByteArray("foo\nbar\n") << QByteArray("foo\r\nbar\r\n") << QByteArray("foo\nbar\n");
0314     QTest::newRow("already_CRLF") << QByteArray("foo\r\nbar\r\n") << QByteArray("foo\r\nbar\r\n") << QByteArray("foo\nbar\n");
0315     QTest::newRow("mixed_CRLF_LF_unchanged") << QByteArray("foo\r\nbar\n") << QByteArray("foo\r\nbar\n") << QByteArray("foo\nbar\n");
0316     // out of scope QTest::newRow("mixed_LF_CRLF_unchanged") << QByteArray("foo\nbar\r\n") << QByteArray("foo\nbar\r\n") << QByteArray("foo\nbar\n");
0317 }
0318 
0319 void UtilTest::testLFCRLF()
0320 {
0321     QFETCH(QByteArray, input);
0322     QFETCH(QByteArray, expected);
0323     QFETCH(QByteArray, convertedBack);
0324 
0325     const QByteArray output = KMime::LFtoCRLF(input);
0326     QCOMPARE(output, expected);
0327     const QByteArray output2 = KMime::LFtoCRLF(input.constData()); // test the const char* overload
0328     QCOMPARE(output2, expected);
0329 
0330     const QByteArray back = KMime::CRLFtoLF(output);
0331     QCOMPARE(back, convertedBack);
0332 }
0333 
0334 void UtilTest::testLFCRLF_performance()
0335 {
0336     const QByteArray line = "This is one line\n";
0337     const int count = 1000;
0338     QByteArray input;
0339     input.reserve(line.size() * count);
0340     for (int i = 0 ; i < count; ++i) {
0341         input += line;
0342     }
0343 
0344     QByteArray output;
0345     QBENCHMARK {
0346         output = KMime::LFtoCRLF(input);
0347     }
0348     QByteArray expected = input;
0349     expected.replace('\n', "\r\n");
0350     QCOMPARE(output, expected);
0351 }
0352 
0353 #include "moc_utiltest.cpp"