diff --git a/tests/mimeobjecttest.cpp b/tests/mimeobjecttest.cpp index 7d2d931..8165fe3 100644 --- a/tests/mimeobjecttest.cpp +++ b/tests/mimeobjecttest.cpp @@ -1,145 +1,186 @@ /* * Copyright (C) 2012 Sofia Balicka + * Copyright (C) 2014 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include "mimeobjecttest.h" -#include "kolabformat/kolabobject.h" #include "testutils.h" #include "kolabformat/mimeobject.h" +#include "conversion/commonconversion.h" #include #include #include -void MIMEObjectTest::initTestCase() +static std::string readFile(const QString &path) { -} - -void MIMEObjectTest::testEvent(){ - - Kolab::MIMEObject mimeobject; - - std::ifstream t((TESTFILEDIR.toStdString()+"v3/event/simple.ics.mime").c_str()); + std::ifstream t(path.toStdString().c_str()); std::stringstream buffer; buffer << t.rdbuf(); - - Kolab::Event event = mimeobject.readEvent(buffer.str()); - - std::string message = mimeobject.writeEvent(event, Kolab::KolabV3); - - QString qMessage = QString::fromStdString(message); - QString input = QString::fromStdString(buffer.str()); - - normalizeMimemessage(qMessage); - normalizeMimemessage(input); - - QCOMPARE(input.simplified(), qMessage.simplified()); + return buffer.str(); } -/* -void MIMEObjectTest::testTodo(){ +static QString normalizeMimemessage(const std::string &path) +{ + QString qString = Kolab::Conversion::fromStdString(path); + normalizeMimemessage(qString); + return qString; } -*/ - -void MIMEObjectTest::testJournal(){ +template +void testFunction(const QString &filename, Kolab::Version version, Kolab::ObjectType type, T (Kolab::MIMEObject::* readFunction) (const std::string&), std::string (Kolab::MIMEObject::* writeFunction) (const T &, Kolab::Version, const std::string &)) +{ + const std::string input = readFile(filename); Kolab::MIMEObject mimeobject; - - std::ifstream t((TESTFILEDIR.toStdString()+"v3/journal/simple.ics.mime").c_str()); - std::stringstream buffer; - buffer << t.rdbuf(); - - Kolab::Journal journal = mimeobject.readJournal(buffer.str()); - - std::string message = mimeobject.writeJournal(journal, Kolab::KolabV3); - - QString qMessage = QString::fromStdString(message); - QString input = QString::fromStdString(buffer.str()); - - normalizeMimemessage(qMessage); - normalizeMimemessage(input); - - QCOMPARE(input.simplified(), qMessage.simplified()); - + const T object = (mimeobject.*readFunction)(input); + QCOMPARE(mimeobject.getType(), type); + const std::string message = (mimeobject.*writeFunction)(object, version, std::string()); + DIFFCOMPARE(normalizeMimemessage(message), normalizeMimemessage(input)); } -void MIMEObjectTest::testNote(){ - - Kolab::MIMEObject mimeobject; - - std::ifstream t((TESTFILEDIR.toStdString()+"v3/note/note.mime.mime").c_str()); - std::stringstream buffer; - buffer << t.rdbuf(); +template +void testFunction(T (Kolab::MIMEObject::* readFunction) (const std::string&), std::string (Kolab::MIMEObject::* writeFunction) (const T &, Kolab::Version, const std::string &)) +{ + testFunction(TESTVALUE(QString, mimeFileName), TESTVALUE(Kolab::Version, version), TESTVALUE(Kolab::ObjectType, type), readFunction, writeFunction); +} - Kolab::Note note = mimeobject.readNote(buffer.str()); - - std::string message = mimeobject.writeNote(note, Kolab::KolabV3); +void MIMEObjectTest::testEvent_data() +{ + QTest::addColumn("version"); + QTest::addColumn("type"); + QTest::addColumn("mimeFileName"); + + QTest::newRow("v2eventSimple") << Kolab::KolabV2 << Kolab::EventObject << getPath("v2/event/simple.ics.mime"); + QTest::newRow("v2eventComplex") << Kolab::KolabV2 << Kolab::EventObject << getPath("v2/event/complex.ics.mime"); + QTest::newRow("v2eventAttachment") << Kolab::KolabV2 << Kolab::EventObject << getPath("v2/event/attachment.ics.mime"); + QTest::newRow("v2eventAllday") << Kolab::KolabV2 << Kolab::EventObject << getPath("v2/event/allday.ics.mime"); + QTest::newRow("v2eventUtf8Attachment") << Kolab::KolabV2 << Kolab::EventObject << getPath("v2/event/attachmentUtf8.ics.mime"); + QTest::newRow("v3eventSimple") << Kolab::KolabV3 << Kolab::EventObject << getPath("v3/event/simple.ics.mime"); + QTest::newRow("v3eventComplex") << Kolab::KolabV3 << Kolab::EventObject << getPath("v3/event/complex.ics.mime"); + QTest::newRow("v3utf8quotedPrintable") << Kolab::KolabV3 << Kolab::EventObject << getPath("v3/event/utf8quotedPrintable.ics.mime"); + //TODO move to read-only + // QTest::newRow("v2eventHorde") << Kolab::KolabV2 << Kolab::EventObject << getPath("v2/event/horde.ics") << getPath("v2/event/horde.ics.mime"); + //TODO read-only test, we never write base64 + // QTest::newRow("v3utf8base64") << Kolab::KolabV3 << Kolab::EventObject << getPath("v3/event/utf8base64.ics.mime"); + //TODO read-only test, we never write 8-bit + // QTest::newRow("v3utf88bit") << Kolab::KolabV3 << Kolab::EventObject << getPath("v3/event/utf88bit.ics.mime"); +} - QString qMessage = QString::fromStdString(message); - QString input = QString::fromStdString(buffer.str()); - - normalizeMimemessage(qMessage); - normalizeMimemessage(input); - - QCOMPARE(input.simplified(), qMessage.simplified()); +void MIMEObjectTest::testEvent() +{ + testFunction(&Kolab::MIMEObject::readEvent, &Kolab::MIMEObject::writeEvent); } -void MIMEObjectTest::testContact(){ +void MIMEObjectTest::testTodo_data() +{ + QTest::addColumn("version"); + QTest::addColumn("type"); + QTest::addColumn("mimeFileName"); + + QTest::newRow("v2todoSimple") << Kolab::KolabV2 << Kolab::TodoObject << getPath("v2/task/simple.ics.mime"); + QTest::newRow("v2todoComplex") << Kolab::KolabV2 << Kolab::TodoObject << getPath("v2/task/complex.ics.mime"); + QTest::newRow("v2todoPrio1") << Kolab::KolabV2 << Kolab::TodoObject << getPath("v2/task/prioritytest1.ics.mime"); + QTest::newRow("v2todoPrio2") << Kolab::KolabV2 << Kolab::TodoObject << getPath("v2/task/prioritytest2.ics.mime"); + QTest::newRow("v3todoSimple") << Kolab::KolabV3 << Kolab::TodoObject << getPath("v3/task/simple.ics.mime"); + QTest::newRow("v3todoComplex") << Kolab::KolabV3 << Kolab::TodoObject << getPath("v3/task/complex.ics.mime"); +} - Kolab::MIMEObject mimeobject; +void MIMEObjectTest::testTodo() +{ + testFunction(&Kolab::MIMEObject::readTodo, &Kolab::MIMEObject::writeTodo); +} - std::ifstream t((TESTFILEDIR.toStdString()+"v3/contacts/simple.vcf.mime").c_str()); - std::stringstream buffer; - buffer << t.rdbuf(); +void MIMEObjectTest::testJournal_data() +{ + QTest::addColumn("version"); + QTest::addColumn("type"); + QTest::addColumn("mimeFileName"); + + QTest::newRow("v2journalSimple") << Kolab::KolabV2 << Kolab::JournalObject << getPath("v2/journal/simple.ics.mime"); + QTest::newRow("v2journalComplex") << Kolab::KolabV2 << Kolab::JournalObject << getPath("v2/journal/complex.ics.mime"); + QTest::newRow("v3journalSimple") << Kolab::KolabV3 << Kolab::JournalObject << getPath("v3/journal/simple.ics.mime"); + QTest::newRow("v3journalComplex") << Kolab::KolabV3 << Kolab::JournalObject << getPath("v3/journal/complex.ics.mime"); +} - Kolab::Contact contact = mimeobject.readContact(buffer.str()); - - std::string message = mimeobject.writeContact(contact, Kolab::KolabV3); +void MIMEObjectTest::testJournal() +{ + testFunction(&Kolab::MIMEObject::readJournal, &Kolab::MIMEObject::writeJournal); +} - QString qMessage = QString::fromStdString(message); - QString input = QString::fromStdString(buffer.str()); - - normalizeMimemessage(qMessage); - normalizeMimemessage(input); - - QCOMPARE(input.simplified(), qMessage.simplified()); +void MIMEObjectTest::testNote_data() +{ + QTest::addColumn("version"); + QTest::addColumn("type"); + QTest::addColumn("mimeFileName"); + QTest::newRow("v3noteSimple") << Kolab::KolabV3 << Kolab::NoteObject << getPath("v3/note/note.mime.mime"); } -void MIMEObjectTest::testDistlist(){ +void MIMEObjectTest::testNote() +{ + testFunction(&Kolab::MIMEObject::readNote, &Kolab::MIMEObject::writeNote); +} - Kolab::MIMEObject mimeobject; +void MIMEObjectTest::testContact_data() +{ + QTest::addColumn("version"); + QTest::addColumn("type"); + QTest::addColumn("mimeFileName"); + + QTest::newRow("v2contactSimple") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/simple.vcf.mime"); + QTest::newRow("v2contactAddress") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/address.vcf.mime"); + //FIXME Figure out why this is broken + // QTest::newRow("v2contactBug238996") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/bug238996.vcf.mime"); + QTest::newRow("v2contactDisplayname") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/displayname.vcf.mime"); + QTest::newRow("v2contactEmails") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/emails.vcf.mime"); + QTest::newRow("v2contactPhonenumbers") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/phonenumbers.vcf.mime"); + QTest::newRow("v3contactSimple") << Kolab::KolabV3 << Kolab::ContactObject << getPath("v3/contacts/simple.vcf.mime"); + QTest::newRow("v3contactComplex") << Kolab::KolabV3 << Kolab::ContactObject << getPath("v3/contacts/complex.vcf.mime"); + + //FIXME Tested in read-only mode in formattest, perhaps move to read-only test that compares with ical? + // QTest::newRow("v3contactPng") << Kolab::KolabV3 << Kolab::ContactObject << getPath("v3/readonly/png.vcf.mime"); + + //FIXME Reference files needs to be adjusted due to fix in how pictures are stored + // QTest::newRow("v2contactComplex") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/complex.vcf.mime"); + // FIXME Reference files needs to be adjusted due to fix in how pictures are stored + // QTest::newRow("v2contactPicture") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/picture.vcf.mime"); + //FIXME the following test fails because the vcard implementation always writes jpeg (which is lossy). + //The reference vcf file is therefore probably also not really useful + // QTest::newRow("v2pictureJPGHorde") << Kolab::KolabV2 << Kolab::ContactObject << getPath("v2/contacts/pictureJPGHorde.vcf.mime"); +} - std::ifstream t((TESTFILEDIR.toStdString()+"v3/contacts/distlist.vcf.mime").c_str()); - std::stringstream buffer; - buffer << t.rdbuf(); +void MIMEObjectTest::testContact() +{ + testFunction(&Kolab::MIMEObject::readContact, &Kolab::MIMEObject::writeContact); +} - Kolab::DistList distlist = mimeobject.readDistlist(buffer.str()); - - std::string message = mimeobject.writeDistlist(distlist, Kolab::KolabV3); +void MIMEObjectTest::testDistlist_data() +{ + QTest::addColumn("version"); + QTest::addColumn("type"); + QTest::addColumn("mimeFileName"); - QString qMessage = QString::fromStdString(message); - QString input = QString::fromStdString(buffer.str()); - - normalizeMimemessage(qMessage); - normalizeMimemessage(input); - - QCOMPARE(input.simplified(), qMessage.simplified()); + QTest::newRow("v3distlistSimple") << Kolab::KolabV3 << Kolab::DistlistObject << getPath("v3/contacts/distlist.vcf.mime"); +} +void MIMEObjectTest::testDistlist() +{ + testFunction(&Kolab::MIMEObject::readDistlist, &Kolab::MIMEObject::writeDistlist); } -QTEST_MAIN( MIMEObjectTest ) + +QTEST_MAIN(MIMEObjectTest) #include "mimeobjecttest.moc" diff --git a/tests/mimeobjecttest.h b/tests/mimeobjecttest.h index a060d40..00dc9ab 100644 --- a/tests/mimeobjecttest.h +++ b/tests/mimeobjecttest.h @@ -1,35 +1,47 @@ /* * Copyright (C) 2012 Sofia Balicka + * Copyright (C) 2014 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef MIMEOBJECTTEST_H #define MIMEOBJECTTEST_H #include +/** + * Read-Write roundtrip test. + * + * Ensures we can read a mime message, serialize it again, and contents are still the same. + */ class MIMEObjectTest: public QObject { Q_OBJECT private slots: - void initTestCase(); + void testEvent_data(); void testEvent(); - void testJournal(); + void testTodo_data(); + void testTodo(); + void testJournal_data(); + void testJournal(); + void testNote_data(); void testNote(); + void testContact_data(); void testContact(); + void testDistlist_data(); void testDistlist(); }; #endif // MIMEOBJECTTEST_H diff --git a/tests/testutils.h b/tests/testutils.h index d11ced2..8a8f25c 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -1,233 +1,250 @@ /* * Copyright (C) 2012 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef TESTUTILS_H #define TESTUTILS_H #include #include #include #include #include #include "kolabformat/kolabobject.h" Q_DECLARE_METATYPE(Kolab::ObjectType); Q_DECLARE_METATYPE(Kolab::Version); #define KCOMPARE(actual, expected) \ do {\ if ( !(actual == expected) ) { \ - qDebug() << __FILE__ << ':' << __LINE__ << "Actual: " #actual ": " << actual << "\nExpceted: " #expected ": " << expected; \ + qDebug() << __FILE__ << ':' << __LINE__ << "Actual: " #actual ": " << actual << "\nExpected: " #expected ": " << expected; \ return false; \ } \ } while (0) #endif +#define DIFFCOMPARE(actual, expected) \ +do {\ + if ( !(actual.simplified() == expected.simplified()) ) { \ + qDebug() << "Content not the same."; \ + showDiff(expected, actual); \ + QTest::qFail("Compared versions differ.", __FILE__, __LINE__); \ + return; \ + } \ +} while (0) + +#define TESTVALUE(type, name)\ + *static_cast(QTest::qData(#name, ::qMetaTypeId())) + const QString TESTFILEDIR = QString::fromLatin1(TEST_DATA_PATH "/testfiles/"); QString getPath(const char *file) { return TESTFILEDIR+QString::fromLatin1(file); } void showDiff(const QString &expected, const QString &converted) { if (expected.isEmpty() || converted.isEmpty()) { qWarning() << "files are emtpy"; return; } if (expected == converted) { qWarning() << "contents are the same"; return; } - // QTemporaryFile expectedFile("expectedFile"); - // QTemporaryFile convertedFile("convertedFile"); - // if (expectedFile.open() && convertedFile.open()) { - // expectedFile.write(expected.toLatin1()); - // convertedFile.write(converted.toLatin1()); - // expectedFile.close(); - // convertedFile.close(); - // QProcess::execute("kompare", QStringList() << "-c" << expectedFile.fileName() << convertedFile.fileName()); - // } else { - // qWarning() << "files are not open"; - // } - - qDebug() << "EXPECTED: " << expected; - qDebug() << "CONVERTED: " << converted; + + bool showDiff = true; + if (showDiff) { + QTemporaryFile expectedFile("expectedFile"); + QTemporaryFile convertedFile("convertedFile"); + if (expectedFile.open() && convertedFile.open()) { + expectedFile.write(expected.toLatin1()); + convertedFile.write(converted.toLatin1()); + expectedFile.close(); + convertedFile.close(); + QProcess::execute("kdiff3", QStringList() << expectedFile.fileName() << convertedFile.fileName()); + } else { + qWarning() << "files are not open"; + } + } else { + qDebug() << "EXPECTED: " << expected; + qDebug() << "CONVERTED: " << converted; + } } KMime::Message::Ptr readMimeFile( const QString &fileName, bool &ok) { // qDebug() << fileName; QFile file( fileName ); ok = file.open( QFile::ReadOnly ); if (!ok) { qWarning() << "failed to open file: " << fileName; return KMime::Message::Ptr(); } const QByteArray data = file.readAll(); KMime::Message::Ptr msg = KMime::Message::Ptr(new KMime::Message); msg->setContent( data ); msg->parse(); return msg; } void normalizeMimemessage(QString &content) { content.replace(QRegExp("\\bLibkolab-\\d.\\d.\\d\\b", Qt::CaseSensitive), "Libkolab-x.x.x"); content.replace(QRegExp("\\bLibkolabxml-\\d.\\d.\\d\\b", Qt::CaseSensitive), "Libkolabxml-x.x.x"); content.replace(QRegExp("\\bLibkolab-\\d.\\d\\b", Qt::CaseSensitive), "Libkolab-x.x.x"); content.replace(QRegExp("\\bLibkolabxml-\\d.\\d\\b", Qt::CaseSensitive), "Libkolabxml-x.x.x"); content.replace(QRegExp("cid:*@kolab.resource.akonadi", Qt::CaseSensitive, QRegExp::Wildcard), "cid:id@kolab.resource.akonadi"); content.replace(QRegExp("Content-ID: <*@kolab.resource.akonadi>", Qt::CaseSensitive, QRegExp::Wildcard), "Content-ID: "); content.replace(QRegExp("mailto:*", Qt::CaseSensitive, QRegExp::Wildcard), "mailto:"); content.replace(QRegExp("mailto:*", Qt::CaseSensitive, QRegExp::Wildcard), "mailto:"); content.replace(QRegExp("data:*", Qt::CaseSensitive, QRegExp::Wildcard), "data:"); content.replace(QRegExp("*", Qt::CaseSensitive, QRegExp::Wildcard), ""); content.replace(QRegExp("*", Qt::CaseSensitive, QRegExp::Wildcard), ""); content.replace(QRegExp("*", Qt::CaseSensitive, QRegExp::Wildcard), ""); content.replace(QRegExp("--nextPart\\S*", Qt::CaseSensitive), "--part"); content.replace(QRegExp("\\bboundary=\"nextPart[^\\n]*", Qt::CaseSensitive), "boundary"); content.replace(QRegExp("Date[^\\n]*", Qt::CaseSensitive), "Date"); //The sort order of the attributes in kolabV2 is unpredictable content.replace(QRegExp("", Qt::CaseSensitive, QRegExp::Wildcard), ""); //quoted-printable encoding changes where the linebreaks are every now and then (an all are valid), so we remove the linebreaks content.replace(QRegExp("=\\n", Qt::CaseSensitive), ""); } QString normalizeVCardMessage(QString content) { //The encoding changes every now and then content.replace(QRegExp("ENCODING=b;TYPE=png:*", Qt::CaseSensitive, QRegExp::Wildcard), "ENCODING=b;TYPE=png:picturedata"); return content; } //Normalize incidences for comparison void normalizeIncidence( KCalCore::Incidence::Ptr incidence) { //The UID is not persistent (it's just the internal pointer), therefore we clear it //TODO make sure that the UID does really not need to be persistent foreach(KCalCore::Attendee::Ptr attendee, incidence->attendees()) { attendee->setUid(QString()); } //FIXME even if hasDueDate can differ, it shouldn't because it breaks equality. Check why they differ in the first place. if ( incidence->type() == KCalCore::IncidenceBase::TypeTodo ) { KCalCore::Todo::Ptr todo = incidence.dynamicCast(); Q_ASSERT(todo.data()); if ( !todo->hasDueDate() && !todo->hasStartDate() ) todo->setAllDay( false ); // all day has no meaning if there are no start and due dates but may differ nevertheless } } template