diff --git a/outboxinterface/CMakeLists.txt b/outboxinterface/CMakeLists.txt index 0f143cda3..033bdfd1e 100644 --- a/outboxinterface/CMakeLists.txt +++ b/outboxinterface/CMakeLists.txt @@ -1,51 +1,44 @@ #include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES} ${KDEPIMLIBS_INCLUDE_DIRS}) # TODO: 5324 is mailtransport. we need one of our own! add_definitions( -DKDE_DEFAULT_DEBUG_AREA=5324 ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" ) add_subdirectory( tests ) set(outboxinterface_lib_srcs dispatcherinterface.cpp - localfolders.cpp outboxactions.cpp messagequeuejob.cpp addressattribute.cpp dispatchmodeattribute.cpp errorattribute.cpp sentbehaviourattribute.cpp transportattribute.cpp - - resourcetester/resourcesynchronizationjob.cpp ) # qt4_add_dbus_interface( outboxinterface_lib_srcs interfaces/org.kde.Akonadi.MailDispatcher.xml mdainterface ) # install( FILES interfaces/org.kde.Akonadi.MailDispatcher.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR} ) -kde4_add_kcfg_files(outboxinterface_lib_srcs settings.kcfgc) -install(FILES outboxinterface.kcfg DESTINATION ${KCFG_INSTALL_DIR}) - kde4_add_library(outboxinterface SHARED ${outboxinterface_lib_srcs}) -target_link_libraries(outboxinterface ${KDE4_KIO_LIBS} akonadi-kde kmime mailtransport ) +target_link_libraries( outboxinterface ${KDE4_KIO_LIBS} akonadi-kde akonadi-kmime kmime mailtransport ) set_target_properties(outboxinterface PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) install(TARGETS outboxinterface ${INSTALL_TARGETS_DEFAULT_ARGS}) install( FILES outboxinterface_export.h dispatcherinterface.h - localfolders.h messagequeuejob.h addressattribute.h dispatchmodeattribute.h errorattribute.h sentbehaviourattribute.h transportattribute.h DESTINATION ${INCLUDE_INSTALL_DIR}/outboxinterface COMPONENT Devel) diff --git a/outboxinterface/TODO b/outboxinterface/TODO index 3f77b221d..be69631b6 100644 --- a/outboxinterface/TODO +++ b/outboxinterface/TODO @@ -1,14 +1,16 @@ * figure out a better name (than outboxinterface), and decide where to merge (in mailtransport?) * better name for MessageQueuer? * Figure out a better way to configure the resource via D-Bus. * Krazy wants me to use private d-pointers in the attributes -- probably a good idea since this is a library?... * if stuff like dispatchManually (stuff that modifies the outbox in general) stays in DispatcherInterface, then it should really be called OutboxInterface (too bad that's a conflict). * provide a dispatcherReady() signal in DispatcherInterface, and think of what should happen if it is not ready... * provide a job to modify items in the outbox such as - remove error attribute and re-queue - change Never dispatch mode to Immediately +* Currently apps have to call DispatcherInterface::self() for the attributes to + be registered. Find a way to do this automatically. diff --git a/outboxinterface/dispatcherinterface.cpp b/outboxinterface/dispatcherinterface.cpp index 802c64fa5..b886b8f7c 100644 --- a/outboxinterface/dispatcherinterface.cpp +++ b/outboxinterface/dispatcherinterface.cpp @@ -1,124 +1,136 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "dispatcherinterface.h" -#include "localfolders.h" +#include "addressattribute.h" +#include "dispatchmodeattribute.h" +#include "errorattribute.h" #include "outboxactions.h" +#include "sentbehaviourattribute.h" +#include "transportattribute.h" #include #include #include #include #include +#include #include #include +#include using namespace Akonadi; using namespace OutboxInterface; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class OutboxInterface::DispatcherInterfacePrivate { public: DispatcherInterfacePrivate(); ~DispatcherInterfacePrivate(); DispatcherInterface *instance; // slots void massModifyResult( KJob *job ); }; K_GLOBAL_STATIC( DispatcherInterfacePrivate, sInstance ) DispatcherInterfacePrivate::DispatcherInterfacePrivate() : instance( new DispatcherInterface( this ) ) { } DispatcherInterfacePrivate::~DispatcherInterfacePrivate() { delete instance; } void DispatcherInterfacePrivate::massModifyResult( KJob *job ) { // Nothing to do here, really. If the job fails, the user can retry it. if( job->error() ) { kDebug() << "failed" << job->errorString(); } else { kDebug() << "succeeded."; } } DispatcherInterface::DispatcherInterface( DispatcherInterfacePrivate *dd ) : QObject() , d( dd ) { + // register attributes + AttributeFactory::registerAttribute(); + AttributeFactory::registerAttribute(); + AttributeFactory::registerAttribute(); + AttributeFactory::registerAttribute(); + AttributeFactory::registerAttribute(); } DispatcherInterface *DispatcherInterface::self() { return sInstance->instance; } AgentInstance DispatcherInterface::dispatcherInstance() const { AgentInstance a = AgentManager::self()->instance( QLatin1String( "akonadi_maildispatcher_agent" ) ); if( !a.isValid() ) { kWarning() << "Could not get MDA instance."; } return a; } void DispatcherInterface::dispatchManually() { if( !LocalFolders::self()->isReady() ) { kWarning() << "LocalFolders not ready."; return; } FilterActionJob *mjob = new FilterActionJob( LocalFolders::self()->outbox(), new SendQueuedAction, this ); connect( mjob, SIGNAL(result(KJob*)), this, SLOT(massModifyResult(KJob*)) ); } void DispatcherInterface::retryDispatching() { if( !LocalFolders::self()->isReady() ) { kWarning() << "LocalFolders not ready."; return; } FilterActionJob *mjob = new FilterActionJob( LocalFolders::self()->outbox(), new ClearErrorAction, this ); connect( mjob, SIGNAL(result(KJob*)), this, SLOT(massModifyResult(KJob*)) ); } #include "dispatcherinterface.moc" diff --git a/outboxinterface/localfolders.cpp b/outboxinterface/localfolders.cpp deleted file mode 100644 index ab4449724..000000000 --- a/outboxinterface/localfolders.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/* - Copyright (c) 2009 Constantin Berzan - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "localfolders.h" - -#include "settings.h" -#include "addressattribute.h" -#include "dispatchmodeattribute.h" -#include "errorattribute.h" -#include "sentbehaviourattribute.h" -#include "transportattribute.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include // svn:external from playground/pim/akonaditest - -#define DBUS_SERVICE_NAME QLatin1String( "org.kde.pim.LocalFolders" ) - - -using namespace Akonadi; -using namespace OutboxInterface; - - -/** - * Private class that helps to provide binary compatibility between releases. - * @internal - */ -class OutboxInterface::LocalFoldersPrivate -{ - public: - LocalFoldersPrivate(); - ~LocalFoldersPrivate(); - - LocalFolders *instance; - bool ready; - bool preparing; - bool scheduled; - bool isMainInstance; - Collection outbox; - Collection sentMail; - Collection rootMaildir; - KJob *outboxJob; - KJob *sentMailJob; - Monitor *monitor; - - /** - If this is the main instance, attempts to create the resource and collections - if necessary, then fetches them. - If this is not the main instance, waits for them to be created by the main - instance, and then fetches them. - - Will emit foldersReady() when done - */ - void prepare(); - - /** - Schedules a prepare() in 1 second. - Called when this is not the main instance and we need to wait, or when - something disappeared and needs to be recreated. - */ - void schedulePrepare(); // slot - - /** - Creates the maildir resource, if it is not found. - */ - void createResourceIfNeeded(); - - /** - Creates the outbox and sent-mail collections, if they are not present. - */ - void createCollectionsIfNeeded(); - - /** - Creates a Monitor to watch the resource and connects to its signals. - This is used to watch for evil users deleting the resource / outbox / etc. - */ - void connectMonitor(); - - /** - Fetches the collections of the maildir resource. - There is one root collection, which contains the outbox and sent-mail - collections. - */ - void fetchCollections(); - - void resourceCreateResult( KJob *job ); - void resourceSyncResult( KJob *job ); - void collectionCreateResult( KJob *job ); - void collectionFetchResult( KJob *job ); - -}; - - -K_GLOBAL_STATIC( LocalFoldersPrivate, sInstance ) - - -LocalFolders::LocalFolders( LocalFoldersPrivate *dd ) - : QObject() - , d( dd ) -{ - // register attributes - AttributeFactory::registerAttribute(); - AttributeFactory::registerAttribute(); - AttributeFactory::registerAttribute(); - AttributeFactory::registerAttribute(); - AttributeFactory::registerAttribute(); -} - -LocalFolders *LocalFolders::self() -{ - return sInstance->instance; -} - -void LocalFolders::fetch() -{ - d->prepare(); -} - -bool LocalFolders::isReady() const -{ - return d->ready; -} - -Collection LocalFolders::outbox() const -{ - Q_ASSERT( d->ready ); - return d->outbox; -} - -Collection LocalFolders::sentMail() const -{ - Q_ASSERT( d->ready ); - return d->sentMail; -} - - - -LocalFoldersPrivate::LocalFoldersPrivate() - : instance( new LocalFolders(this) ) -{ - isMainInstance = QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); - - ready = false; - // prepare() expects these - preparing = false; - outboxJob = 0; - sentMailJob = 0; - monitor = 0; - prepare(); -} - -LocalFoldersPrivate::~LocalFoldersPrivate() -{ - delete instance; -} - -void LocalFoldersPrivate::prepare() -{ - if( ready ) { - //kDebug() << "Already ready. Emitting foldersReady()."; - emit instance->foldersReady(); - return; - } - if( preparing ) { - kDebug() << "Already preparing."; - return; - } - kDebug() << "Preparing. isMainInstance" << isMainInstance; - preparing = true; - scheduled = false; - - Q_ASSERT( outboxJob == 0 ); - Q_ASSERT( sentMailJob == 0 ); - Q_ASSERT( monitor == 0); - - rootMaildir = Collection( -1 ); - outbox = Collection( -1 ); - sentMail = Collection( -1 ); - - createResourceIfNeeded(); -} - -void LocalFoldersPrivate::schedulePrepare() -{ - if( scheduled ) { - kDebug() << "Prepare already scheduled."; - return; - } - - kDebug() << "Scheduling prepare."; - - if( monitor ) { - monitor->disconnect( instance ); - monitor->deleteLater(); - monitor = 0; - } - - ready = false; - preparing = false; - scheduled = true; - QTimer::singleShot( 1000, instance, SLOT( prepare() ) ); -} - -void LocalFoldersPrivate::createResourceIfNeeded() -{ - Q_ASSERT( preparing ); - - // Another instance might have created the resource and updated the config. - Settings::self()->readConfig(); - kDebug() << "Resource from config:" << Settings::resourceId(); - - // check that the maildir resource exists - AgentInstance resource = AgentManager::self()->instance( Settings::resourceId() ); - if( !resource.isValid() ) { - // Try to grab main instance status (if previous main instance quit). - if( !isMainInstance ) { - isMainInstance = QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); - if( isMainInstance ) { - kDebug() << "I have become the main instance."; - } - } - - // Create resource if main instance. - if( !isMainInstance ) { - kDebug() << "Waiting for the main instance to create the resource."; - schedulePrepare(); - } else { - kDebug() << "Creating maildir resource."; - AgentType type = AgentManager::self()->type( "akonadi_maildir_resource" ); - AgentInstanceCreateJob *job = new AgentInstanceCreateJob( type ); - QObject::connect( job, SIGNAL( result( KJob * ) ), - instance, SLOT( resourceCreateResult( KJob * ) ) ); - // this is not an Akonadi::Job, so we must start it ourselves - job->start(); - } - } else { - connectMonitor(); - } -} - -void LocalFoldersPrivate::createCollectionsIfNeeded() -{ - Q_ASSERT( preparing ); // but I may not be the main instance - Q_ASSERT( rootMaildir.isValid() ); - - if( !outbox.isValid() ) { - kDebug() << "Creating outbox collection."; - Collection col; - col.setParent( rootMaildir ); - col.setName( "outbox" ); - col.setContentMimeTypes( QStringList( "message/rfc822" ) ); - Q_ASSERT( outboxJob == 0 ); - outboxJob = new CollectionCreateJob( col ); - QObject::connect( outboxJob, SIGNAL( result( KJob * ) ), - instance, SLOT( collectionCreateResult( KJob * ) ) ); - } - - if( !sentMail.isValid() ) { - kDebug() << "Creating sent-mail collection."; - Collection col; - col.setParent( rootMaildir ); - col.setName( "sent-mail" ); - col.setContentMimeTypes( QStringList( "message/rfc822" ) ); - Q_ASSERT( sentMailJob == 0 ); - sentMailJob = new CollectionCreateJob( col ); - QObject::connect( sentMailJob, SIGNAL( result( KJob * ) ), - instance, SLOT( collectionCreateResult( KJob * ) ) ); - } - - if( outboxJob == 0 && sentMailJob == 0 ) { - // Everything is ready (created and fetched). - kDebug() << "Local folders ready. resourceId" << Settings::resourceId() - << "outbox id" << outbox.id() << "sentMail id" << sentMail.id(); - - Q_ASSERT( !ready ); - ready = true; - preparing = false; - Settings::self()->writeConfig(); - emit instance->foldersReady(); - } -} - -void LocalFoldersPrivate::connectMonitor() -{ - Q_ASSERT( preparing ); // but I may not be the main instance - Q_ASSERT( monitor == 0 ); - monitor = new Monitor( instance ); - monitor->setResourceMonitored( Settings::resourceId().toAscii() ); - QObject::connect( monitor, SIGNAL( collectionRemoved( Akonadi::Collection ) ), - instance, SLOT( schedulePrepare() ) ); - kDebug() << "Connected monitor."; - fetchCollections(); -} - -void LocalFoldersPrivate::fetchCollections() -{ - Q_ASSERT( preparing ); // but I may not be the main instance - kDebug() << "Fetching collections in maildir resource."; - - CollectionFetchJob *job = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive ); - job->setResource( Settings::resourceId() ); // limit search - QObject::connect( job, SIGNAL( result( KJob * ) ), - instance, SLOT( collectionFetchResult( KJob * ) ) ); -} - -void LocalFoldersPrivate::resourceCreateResult( KJob *job ) -{ - Q_ASSERT( isMainInstance ); - Q_ASSERT( preparing ); - if( job->error() ) { - kFatal() << "AgentInstanceCreateJob failed to make a maildir resource for us."; - } - - AgentInstanceCreateJob *createJob = static_cast( job ); - AgentInstance agent = createJob->instance(); - Settings::setResourceId( agent.identifier() ); - kDebug() << "Created maildir resource with id" << Settings::resourceId(); - - // configure the resource - agent.setName( i18n( "Local Mail Folders" ) ); - QDBusInterface conf( "org.freedesktop.Akonadi.Resource." + Settings::resourceId(), - "/Settings", "org.kde.Akonadi.Maildir.Settings" ); - QDBusReply reply = conf.call( "setPath", KGlobal::dirs()->localxdgdatadir() + "mail" ); - if( !reply.isValid() ) { - kFatal() << "Failed to set the root maildir."; - } - agent.reconfigure(); - - // sync the resource - ResourceSynchronizationJob *sjob = new ResourceSynchronizationJob( agent ); - QObject::connect( sjob, SIGNAL( result( KJob* ) ), - instance, SLOT( resourceSyncResult( KJob* ) ) ); - sjob->start(); // non-Akonadi -} - -void LocalFoldersPrivate::resourceSyncResult( KJob *job ) -{ - Q_ASSERT( isMainInstance ); - Q_ASSERT( preparing ); - if( job->error() ) { - kFatal() << "ResourceSynchronizationJob failed."; - } - - connectMonitor(); -} - -void LocalFoldersPrivate::collectionCreateResult( KJob *job ) -{ - Q_ASSERT( isMainInstance ); - if( job->error() ) { - kFatal() << "CollectionCreateJob failed to make a collection for us."; - } - - CollectionCreateJob *createJob = static_cast( job ); - if( job == outboxJob ) { - outboxJob = 0; - outbox = createJob->collection(); - kDebug() << "Created outbox collection with id" << outbox.id(); - } else if( job == sentMailJob ) { - sentMailJob = 0; - sentMail = createJob->collection(); - kDebug() << "Created sent-mail collection with id" << sentMail.id(); - } else { - kFatal() << "Got a result for a job I don't know about."; - } - - if( outboxJob == 0 && sentMailJob == 0 ) { - // Done creating. Refetch everything. - fetchCollections(); - } -} - -void LocalFoldersPrivate::collectionFetchResult( KJob *job ) -{ - Q_ASSERT( preparing ); // but I may not be the main instance - CollectionFetchJob *fetchJob = static_cast( job ); - Collection::List cols = fetchJob->collections(); - - kDebug() << "CollectionFetchJob fetched" << cols.count() << "collections."; - - outbox = Collection( -1 ); - sentMail = Collection( -1 ); - Q_FOREACH( const Collection &col, cols ) { - if( col.parent() == Collection::root().id() ) { - rootMaildir = col; - kDebug() << "Fetched root maildir collection."; - } else if( col.name() == "outbox" ) { - Q_ASSERT( outbox.id() == -1 ); - outbox = col; - kDebug() << "Fetched outbox collection."; - } else if( col.name() == "sent-mail" ) { - Q_ASSERT( sentMail.id() == -1 ); - sentMail = col; - kDebug() << "Fetched sent-mail collection."; - } else { - kWarning() << "Extraneous collection" << col.name() << "with id" - << col.id() << "found."; - } - } - - if( !rootMaildir.isValid() ) { - kFatal() << "Failed to fetch root maildir collection."; - } - - createCollectionsIfNeeded(); -} - - -#include "localfolders.moc" diff --git a/outboxinterface/localfolders.h b/outboxinterface/localfolders.h deleted file mode 100644 index 80b5eb4ec..000000000 --- a/outboxinterface/localfolders.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright (c) 2009 Constantin Berzan - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#ifndef OUTBOXINTERFACE_LOCALFOLDERS_H -#define OUTBOXINTERFACE_LOCALFOLDERS_H - -#include - -#include - -class KJob; - -namespace Akonadi { - class Collection; -} - - -namespace OutboxInterface { - - -class LocalFoldersPrivate; - - -/** - Creates and monitors the Outbox and Sent-Mail collections for the mail - dispatcher agent. - - The first time it is used, or when you call fetch(), this class checks for - the following: - * a maildir resource with name 'Local Mail Folders' - * 'outbox' and 'sent-mail' collections under that resource - If they do not exist, this class creates them, and then emits foldersReady(). - - Do not store the collections returned by outbox() and sentMail(). They can - become invalid if e.g. the user deletes them and LocalFolders creates them - again, so you should always use LocalFolders::outbox() instead of storing - its return value. - -*/ -class OUTBOXINTERFACE_EXPORT LocalFolders : public QObject -{ - Q_OBJECT - - public: - /** - Returns the LocalFolders instance. - Does a fetch() when first called. - */ - static LocalFolders *self(); - - /** - Begins creating / fetching the resource and collections. - Emits foldersReady() when done. - */ - void fetch(); - - /** - Returns whether the outbox and sent-mail collections have been - fetched and are ready to be used via outbox() and sentMail(). - */ - bool isReady() const; - - public Q_SLOTS: - /** - Returns the outbox collection. - */ - Akonadi::Collection outbox() const; - - /** - Returns the sent-mail collection. - */ - Akonadi::Collection sentMail() const; - - Q_SIGNALS: - /** - Emitted when the outbox and sent-mail collections have been fetched and - are ready to be used via outbox() and sentMail(). - */ - void foldersReady(); - - private: - friend class LocalFoldersPrivate; - - // singleton class; the only instance resides in sInstance->instance - LocalFolders( LocalFoldersPrivate *dd ); - - LocalFoldersPrivate *const d; - - Q_PRIVATE_SLOT( d, void prepare() ) - Q_PRIVATE_SLOT( d, void schedulePrepare() ) - Q_PRIVATE_SLOT( d, void resourceCreateResult( KJob * ) ) - Q_PRIVATE_SLOT( d, void resourceSyncResult( KJob * ) ) - Q_PRIVATE_SLOT( d, void collectionCreateResult( KJob * ) ) - Q_PRIVATE_SLOT( d, void collectionFetchResult( KJob * ) ) - -}; - - -} - - -#endif diff --git a/outboxinterface/messagequeuejob.cpp b/outboxinterface/messagequeuejob.cpp index 5fa194e1c..15becac8e 100644 --- a/outboxinterface/messagequeuejob.cpp +++ b/outboxinterface/messagequeuejob.cpp @@ -1,320 +1,320 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "messagequeuejob.h" -#include "localfolders.h" #include "addressattribute.h" #include "transportattribute.h" #include #include #include #include #include #include +#include #include #include using namespace Akonadi; using namespace KMime; using namespace MailTransport; using namespace OutboxInterface; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class OutboxInterface::MessageQueueJob::Private { public: Private( MessageQueueJob *qq ) : q( qq ) { transport = -1; dispatchMode = DispatchModeAttribute::Immediately; sentBehaviour = SentBehaviourAttribute::MoveToDefaultSentCollection; moveToCollection = -1; started = false; } MessageQueueJob *const q; Message::Ptr message; int transport; DispatchModeAttribute::DispatchMode dispatchMode; QDateTime dueDate; SentBehaviourAttribute::SentBehaviour sentBehaviour; Collection::Id moveToCollection; QString from; QStringList to; QStringList cc; QStringList bcc; bool started; void readAddressesFromMime(); /** Checks that this message has everything it needs and is ready to be sent. */ bool validate(); // slot void doStart(); }; void MessageQueueJob::Private::readAddressesFromMime() { kDebug() << "implement me"; // big TODO } bool MessageQueueJob::Private::validate() { if( !message ) { q->setError( UserDefinedError ); q->setErrorText( i18n( "Empty message." ) ); q->emitResult(); return false; // NOTE: the MDA also asserts that msg->encodedContent(true) is non-empty. } if( to.count() + cc.count() + bcc.count() == 0 ) { q->setError( UserDefinedError ); q->setErrorText( i18n( "Message has no recipients." ) ); q->emitResult(); return false; } if( dispatchMode == DispatchModeAttribute::AfterDueDate && !dueDate.isValid() ) { q->setError( UserDefinedError ); q->setErrorText( i18n( "Message has invalid due date." ) ); q->emitResult(); return false; } if( TransportManager::self()->transportById( transport, false ) == 0 ) { q->setError( UserDefinedError ); q->setErrorText( i18n( "Message has invalid transport." ) ); q->emitResult(); return false; } if( sentBehaviour == SentBehaviourAttribute::MoveToCollection && moveToCollection < 0 ) { q->setError( UserDefinedError ); q->setErrorText( i18n( "Message has invalid sent-mail folder." ) ); q->emitResult(); return false; } else if( sentBehaviour == SentBehaviourAttribute::MoveToDefaultSentCollection ) { Q_ASSERT( LocalFolders::self()->isReady() ); Q_ASSERT( LocalFolders::self()->sentMail().isValid() ); } return true; // all ok } void MessageQueueJob::Private::doStart() { LocalFolders::self()->disconnect( q ); //kDebug() << q << "starting"; Q_ASSERT( !started ); started = true; if( !validate() ) { // The error has been set; the result has been emitted. return; } // create item Item item; item.setMimeType( "message/rfc822" ); item.setPayload( message ); //kDebug() << "message:" << message->encodedContent( true ); // set attributes AddressAttribute *addrA = new AddressAttribute( from, to, cc, bcc ); DispatchModeAttribute *dmA = new DispatchModeAttribute( dispatchMode, dueDate ); SentBehaviourAttribute *sA = new SentBehaviourAttribute( sentBehaviour, moveToCollection ); TransportAttribute *tA = new TransportAttribute( transport ); item.addAttribute( addrA ); item.addAttribute( dmA ); item.addAttribute( sA ); item.addAttribute( tA ); // set flags item.setFlag( "queued" ); // put item in Akonadi storage Q_ASSERT( LocalFolders::self()->isReady() ); Collection col = LocalFolders::self()->outbox(); ItemCreateJob *job = new ItemCreateJob( item, col ); // job autostarts q->addSubjob( job ); } MessageQueueJob::MessageQueueJob( QObject *parent ) : KCompositeJob( parent ) , d( new Private( this ) ) { //kDebug() << this << "created"; } MessageQueueJob::~MessageQueueJob() { //kDebug() << this << "destroyed"; delete d; } Message::Ptr MessageQueueJob::message() const { return d->message; } int MessageQueueJob::transportId() const { return d->transport; } DispatchModeAttribute::DispatchMode MessageQueueJob::dispatchMode() const { return d->dispatchMode; } QDateTime MessageQueueJob::sendDueDate() const { if( d->dispatchMode != DispatchModeAttribute::AfterDueDate ) { kWarning() << "Called when dispatchMode is not AfterDueDate."; } return d->dueDate; } Collection::Id MessageQueueJob::moveToCollection() const { if( d->sentBehaviour != SentBehaviourAttribute::MoveToCollection ) { kWarning() << "Called when sentBehaviour is not MoveToCollection."; } return d->moveToCollection; } QString MessageQueueJob::from() const { return d->from; } QStringList MessageQueueJob::to() const { return d->to; } QStringList MessageQueueJob::cc() const { return d->cc; } QStringList MessageQueueJob::bcc() const { return d->bcc; } void MessageQueueJob::setMessage( Message::Ptr message ) { d->message = message; } void MessageQueueJob::setTransportId( int id ) { d->transport = id; } void MessageQueueJob::setDispatchMode( DispatchModeAttribute::DispatchMode mode ) { d->dispatchMode = mode; } void MessageQueueJob::setDueDate( const QDateTime &date ) { d->dueDate = date; } void MessageQueueJob::setSentBehaviour( SentBehaviourAttribute::SentBehaviour beh ) { d->sentBehaviour = beh; } void MessageQueueJob::setMoveToCollection( Collection::Id cid ) { d->moveToCollection = cid; } void MessageQueueJob::setFrom( const QString &from ) { d->from = from; } void MessageQueueJob::setTo( const QStringList &to ) { d->to = to; } void MessageQueueJob::setCc( const QStringList &cc ) { d->cc = cc; } void MessageQueueJob::setBcc( const QStringList &bcc ) { d->bcc = bcc; } void MessageQueueJob::readAddressesFromMime() { d->readAddressesFromMime(); } void MessageQueueJob::start() { LocalFolders *folders = LocalFolders::self(); connect( folders, SIGNAL( foldersReady() ), this, SLOT( doStart() ) ); folders->fetch(); // will emit foldersReady() } void MessageQueueJob::slotResult( KJob *job ) { // error handling KCompositeJob::slotResult( job ); if( !error() ) { //kDebug() << "item created ok. emitting result."; emitResult(); } } #include "messagequeuejob.moc" diff --git a/outboxinterface/outboxinterface.kcfg b/outboxinterface/outboxinterface.kcfg deleted file mode 100644 index 281118bc4..000000000 --- a/outboxinterface/outboxinterface.kcfg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Id of the maildir resource containing the outbox and sent-mail collections. - "" - - - - -1 - - - - -1 - - - diff --git a/outboxinterface/settings.kcfgc b/outboxinterface/settings.kcfgc deleted file mode 100644 index e7a2caddd..000000000 --- a/outboxinterface/settings.kcfgc +++ /dev/null @@ -1,7 +0,0 @@ -File=outboxinterface.kcfg -ClassName=Settings -NameSpace=OutboxInterface -Singleton=true -ItemAccessors=true -Mutators=true -SetUserTextx=true diff --git a/outboxinterface/tests/CMakeLists.txt b/outboxinterface/tests/CMakeLists.txt index 53594e1e4..13deeb25d 100644 --- a/outboxinterface/tests/CMakeLists.txt +++ b/outboxinterface/tests/CMakeLists.txt @@ -1,68 +1,61 @@ set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) set(queuer_srcs queuer.cpp) kde4_add_executable(queuer TEST ${queuer_srcs}) target_link_libraries(queuer ${KDE4_KDEUI_LIBS} ${KDE4_MAILTRANSPORT_LIBS} ${KDE4_KMIME_LIBS} outboxinterface) -set( requester_srcs foldersrequester.cpp ) -kde4_add_executable( requester TEST ${requester_srcs} ) -target_link_libraries( requester outboxinterface ) -# for racetest -add_definitions( -DREQUESTER_EXE=\\"${CMAKE_CURRENT_BINARY_DIR}/requester\\" ) - set( sendqueued_srcs sendqueued.cpp ) kde4_add_executable( sendqueued TEST ${sendqueued_srcs} ) target_link_libraries( sendqueued outboxinterface ) set( clearerror_srcs clearerror.cpp ) kde4_add_executable( clearerror TEST ${clearerror_srcs} ) target_link_libraries( clearerror outboxinterface ) set( abort_srcs abort.cpp ) kde4_add_executable( abort TEST ${abort_srcs} ) target_link_libraries( abort outboxinterface ) # Stolen from kdepimlibs/akonadi/tests macro(add_akonadi_isolated_test _source) get_filename_component(_targetName ${_source} NAME_WE) set(_srcList ${_source} ) kde4_add_executable(${_targetName} TEST ${_srcList}) target_link_libraries(${_targetName} ${QT_QTTEST_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_AKONADI_LIBS} ${KDE4_KDECORE_LIBS} ${KDE4_MAILTRANSPORT_LIBS} ${KDE4_KMIME_LIBS} ${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY} outboxinterface ) # based on kde4_add_unit_test if (WIN32) get_target_property( _loc ${_targetName} LOCATION ) set(_executable ${_loc}.bat) else (WIN32) set(_executable ${EXECUTABLE_OUTPUT_PATH}/${_targetName}) endif (WIN32) if (UNIX) set(_executable ${_executable}.shell) endif (UNIX) find_program(_testrunner akonaditest) add_test( outboxinterface-${_targetName} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config.xml ${_executable} ) endmacro(add_akonadi_isolated_test) add_akonadi_isolated_test( messagequeuejobtest.cpp ) -add_akonadi_isolated_test( racetest.cpp ) diff --git a/outboxinterface/tests/TODO b/outboxinterface/tests/TODO index 03dc5a0f3..04bb421ba 100644 --- a/outboxinterface/tests/TODO +++ b/outboxinterface/tests/TODO @@ -1,12 +1,6 @@ -LocalFolders: -* LocalFolders should be able to recover from any of the following situations: -- maildir resource and collection were removed -- maildir resource was removed, but collections are still there -- one or both collections have been removed - MessageQueueJob: - see source Attributes: - add test for serialization and common mistakes such as forgetting to setDueDate diff --git a/outboxinterface/tests/clearerror.cpp b/outboxinterface/tests/clearerror.cpp index ce59ed669..7f81a57f1 100644 --- a/outboxinterface/tests/clearerror.cpp +++ b/outboxinterface/tests/clearerror.cpp @@ -1,82 +1,82 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "clearerror.h" #include #include #include #include #include #include #include +#include -#include #include using namespace Akonadi; using namespace OutboxInterface; Runner::Runner() { Control::start(); connect( LocalFolders::self(), SIGNAL( foldersReady() ), this, SLOT( checkFolders() ) ); LocalFolders::self()->fetch(); } void Runner::checkFolders() { Collection outbox = LocalFolders::self()->outbox(); kDebug() << "Got outbox" << outbox.id(); if( !outbox.isValid() ) { KApplication::exit( 1 ); } FilterActionJob *fjob = new FilterActionJob( outbox, new ClearErrorAction, this ); connect( fjob, SIGNAL(result(KJob*)), this, SLOT(jobResult(KJob*)) ); } void Runner::jobResult( KJob *job ) { if( job->error() ) { kDebug() << "Job error:" << job->errorString(); KApplication::exit( 2 ); } else { kDebug() << "Job success."; KApplication::exit( 0 ); } } int main( int argc, char **argv ) { KCmdLineArgs::init( argc, argv, "clearerror", 0, ki18n( "clearerror" ), "0", ki18n( "An app that re-queues failed items from the outbox" ) ); KApplication app; new Runner(); return app.exec(); } #include "clearerror.moc" diff --git a/outboxinterface/tests/foldersrequester.cpp b/outboxinterface/tests/foldersrequester.cpp deleted file mode 100644 index 39f67ad19..000000000 --- a/outboxinterface/tests/foldersrequester.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (c) 2009 Constantin Berzan - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "foldersrequester.h" - -#include -#include -#include - -#include -#include - -#include - -using namespace Akonadi; -using namespace OutboxInterface; - - -Requester::Requester() -{ - Control::start(); - - connect( LocalFolders::self(), SIGNAL( foldersReady() ), - this, SLOT( checkFolders() ) ); - LocalFolders::self()->fetch(); -} - -void Requester::checkFolders() -{ - Collection outbox = LocalFolders::self()->outbox(); - Collection sentMail = LocalFolders::self()->sentMail(); - - kDebug() << "Got outbox" << outbox.id() << "sent-mail" << sentMail.id(); - - if( !outbox.isValid() || !sentMail.isValid() ) { - KApplication::exit( 1 ); - } else { - KApplication::exit( 2 ); - } -} - -int main( int argc, char **argv ) -{ - KCmdLineArgs::init( argc, argv, "foldersrequester", 0, - ki18n( "foldersrequester" ), "0", - ki18n( "An app that requests LocalFolders" ) ); - KApplication app; - new Requester(); - return app.exec(); -} - - -#include "foldersrequester.moc" diff --git a/outboxinterface/tests/foldersrequester.h b/outboxinterface/tests/foldersrequester.h deleted file mode 100644 index cee1c7bc2..000000000 --- a/outboxinterface/tests/foldersrequester.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (c) 2009 Constantin Berzan - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#ifndef FOLDERSREQUESTER_H -#define FOLDERSREQUESTER_H - -#include - -/** - This class requests the LocalFolders, then exits the app with a status of 2 - if they were delivered OK, or 1 if they were not. - - NOTE: The non-standard exit status 2 in case of success is to make feel more - comfortable than checking for zero (I actually had a bug causing it to always - return zero). -*/ -class Requester : public QObject -{ - Q_OBJECT - - public: - Requester(); - - private slots: - void checkFolders(); - -}; - - -#endif diff --git a/outboxinterface/tests/messagequeuejobtest.cpp b/outboxinterface/tests/messagequeuejobtest.cpp index c2d50cd18..6be922df8 100644 --- a/outboxinterface/tests/messagequeuejobtest.cpp +++ b/outboxinterface/tests/messagequeuejobtest.cpp @@ -1,198 +1,202 @@ /* Copyright 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "messagequeuejobtest.h" #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include -#include -#include #include +#include #include #include +#include #include #include #define SPAM_ADDRESS ( QStringList() << "idanoka@gmail.com" ) using namespace Akonadi; using namespace KMime; using namespace MailTransport; using namespace OutboxInterface; void MessageQueueJobTest::initTestCase() { Control::start(); // HACK: Otherwise the MDA is not switched offline soon enough apparently... QTest::qWait( 1000 ); + // HACK: Register attributes. + DispatcherInterface::self(); + // Switch MDA offline to avoid spam. AgentInstance mda = AgentManager::self()->instance( "akonadi_maildispatcher_agent" ); QVERIFY( mda.isValid() ); mda.setIsOnline( false ); // check that outbox is empty LocalFolders::self()->fetch(); QTest::kWaitForSignal( LocalFolders::self(), SIGNAL( foldersReady() ) ); verifyOutboxContents( 0 ); } void MessageQueueJobTest::testAddressesFromMime() { // TODO } void MessageQueueJobTest::testValidMessages() { // check transport int tid = TransportManager::self()->defaultTransportId(); QVERIFY2( tid >= 0, "I need a default transport, but there is none." ); // send a valid message using the default transport MessageQueueJob *qjob = new MessageQueueJob; qjob->setTransportId( tid ); Message::Ptr msg = Message::Ptr( new Message ); msg->setContent( "\nThis is message #1 from the MessageQueueJobTest unit test.\n" ); qjob->setMessage( msg ); qjob->setTo( SPAM_ADDRESS ); verifyOutboxContents( 0 ); AKVERIFYEXEC( qjob ); // fetch the message and verify it QTest::qWait( 1000 ); verifyOutboxContents( 1 ); ItemFetchJob *fjob = new ItemFetchJob( LocalFolders::self()->outbox() ); fjob->fetchScope().fetchFullPayload(); fjob->fetchScope().fetchAllAttributes(); AKVERIFYEXEC( fjob ); QCOMPARE( fjob->items().count(), 1 ); Item item = fjob->items().first(); QVERIFY( !item.remoteId().isEmpty() ); // stored by the resource QVERIFY( item.hasPayload() ); AddressAttribute *addrA = item.attribute(); QVERIFY( addrA ); QVERIFY( addrA->from().isEmpty() ); QCOMPARE( addrA->to().count(), 1 ); QCOMPARE( addrA->to(), SPAM_ADDRESS ); QCOMPARE( addrA->cc().count(), 0 ); QCOMPARE( addrA->bcc().count(), 0 ); DispatchModeAttribute *dA = item.attribute(); QVERIFY( dA ); QCOMPARE( dA->dispatchMode(), DispatchModeAttribute::Immediately ); // default mode SentBehaviourAttribute *sA = item.attribute(); QVERIFY( sA ); QCOMPARE( sA->sentBehaviour(), SentBehaviourAttribute::MoveToDefaultSentCollection ); // default sent collection TransportAttribute *tA = item.attribute(); QVERIFY( tA ); QCOMPARE( tA->transportId(), tid ); ErrorAttribute *eA = item.attribute(); QVERIFY( !eA ); // no error QCOMPARE( item.flags().count(), 1 ); QVERIFY( item.flags().contains( "queued" ) ); // delete message, for further tests ItemDeleteJob *djob = new ItemDeleteJob( item ); AKVERIFYEXEC( djob ); verifyOutboxContents( 0 ); // TODO test with no To: but only BCC: // TODO test due-date sending // TODO test sending with custom sent-mail collections } void MessageQueueJobTest::testInvalidMessages() { MessageQueueJob *job = 0; Message::Ptr msg; // without message job = new MessageQueueJob; job->setTransportId( TransportManager::self()->defaultTransportId() ); job->setTo( SPAM_ADDRESS ); QVERIFY( !job->exec() ); // without recipients job = new MessageQueueJob; msg = Message::Ptr( new Message ); msg->setContent( "\nThis is a message sent from the MessageQueueJobTest unittest. This shouldn't have been sent.\n" ); job->setMessage( msg ); job->setTransportId( TransportManager::self()->defaultTransportId() ); QVERIFY( !job->exec() ); // without transport job = new MessageQueueJob; msg = Message::Ptr( new Message ); msg->setContent( "\nThis is a message sent from the MessageQueueJobTest unittest. This shouldn't have been sent.\n" ); job->setMessage( msg ); job->setTo( SPAM_ADDRESS ); QVERIFY( !job->exec() ); // with AfterDueDate and no due date job = new MessageQueueJob; msg = Message::Ptr( new Message ); msg->setContent( "\nThis is a message sent from the MessageQueueJobTest unittest. This shouldn't have been sent.\n" ); job->setMessage( msg ); job->setTo( SPAM_ADDRESS ); job->setDispatchMode( DispatchModeAttribute::AfterDueDate ); QVERIFY( !job->exec() ); // with MoveToCollection and no sent-mail folder job = new MessageQueueJob; msg = Message::Ptr( new Message ); msg->setContent( "\nThis is a message sent from the MessageQueueJobTest unittest. This shouldn't have been sent.\n" ); job->setMessage( msg ); job->setTo( SPAM_ADDRESS ); job->setSentBehaviour( SentBehaviourAttribute::MoveToCollection ); QVERIFY( !job->exec() ); } void MessageQueueJobTest::verifyOutboxContents( qlonglong count ) { QVERIFY( LocalFolders::self()->isReady() ); Collection outbox = LocalFolders::self()->outbox(); QVERIFY( outbox.isValid() ); CollectionStatisticsJob *job = new CollectionStatisticsJob( outbox ); AKVERIFYEXEC( job ); QCOMPARE( job->statistics().count(), count ); } QTEST_AKONADIMAIN( MessageQueueJobTest, NoGUI ) #include "messagequeuejobtest.moc" diff --git a/outboxinterface/tests/racetest.cpp b/outboxinterface/tests/racetest.cpp deleted file mode 100644 index a40d1d390..000000000 --- a/outboxinterface/tests/racetest.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - Copyright 2009 Constantin Berzan - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#include "racetest.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#define TIMEOUT_SECONDS 20 -#define MAXCOUNT 10 -// NOTE: REQUESTER_EXE is defined by cmake. - -using namespace Akonadi; -using namespace OutboxInterface; - - -void RaceTest::initTestCase() -{ - QVERIFY( Control::start() ); - QTest::qWait( 1000 ); // give the MDA time to start so that we can kill it in peace -} - -void RaceTest::testMultipleProcesses_data() -{ - QTest::addColumn( "count" ); // how many processes to create - QTest::addColumn( "delay" ); // number of ms to wait before starting next process - - QTest::newRow( "1-nodelay" ) << 1 << 0; - QTest::newRow( "2-nodelay" ) << 2 << 0; - QTest::newRow( "5-nodelay" ) << 5 << 0; - QTest::newRow( "10-nodelay" ) << 10 << 0; - QTest::newRow( "2-shortdelay" ) << 2 << 100; - QTest::newRow( "5-shortdelay" ) << 5 << 100; - QTest::newRow( "10-shortdelay" ) << 10 << 100; - QTest::newRow( "2-longdelay" ) << 2 << 1000; - QTest::newRow( "5-longdelay" ) << 5 << 1000; - QTest::newRow( "5-verylongdelay" ) << 5 << 4000; - Q_ASSERT( 10 <= MAXCOUNT ); -} - -void RaceTest::testMultipleProcesses() -{ - QFETCH( int, count ); - QFETCH( int, delay ); - - killZombies(); - - // Remove all maildir instances (at most 1 really) and MDAs (which use LocalFolders). - // (This is to ensure that one of *our* instances is the main instance.) - AgentType::List types; - types.append( AgentManager::self()->type( "akonadi_maildir_resource" ) ); - types.append( AgentManager::self()->type( "akonadi_maildispatcher_agent" ) ); - AgentInstance::List instances = AgentManager::self()->instances(); - foreach( const AgentInstance &instance, instances ) { - if( types.contains( instance.type() ) ) { - kDebug() << "Removing instance of type" << instance.type().identifier(); - AgentManager::self()->removeInstance( instance ); - QTest::kWaitForSignal( AgentManager::self(), SIGNAL( instanceRemoved( const Akonadi::AgentInstance& ) ) ); - } - } - instances = AgentManager::self()->instances(); - foreach( const AgentInstance &instance, instances ) { - QVERIFY( !types.contains( instance.type() ) ); - } - - QSignalSpy *errorSpy[ MAXCOUNT ]; - QSignalSpy *finishedSpy[ MAXCOUNT ]; - for( int i = 0; i < count; i++ ) { - kDebug() << "Starting process" << i + 1 << "of" << count; - KProcess *proc = new KProcess; - procs.append( proc ); - proc->setProgram( REQUESTER_EXE ); - errorSpy[i] = new QSignalSpy( proc, SIGNAL( error( QProcess::ProcessError ) ) ); - finishedSpy[i] = new QSignalSpy( proc, SIGNAL( finished( int, QProcess::ExitStatus ) ) ); - proc->start(); - QTest::qWait( delay ); - } - kDebug() << "Launched" << count << "processes."; - - int seconds = 0; - int error, finished; - while( true ) { - seconds++; - QTest::qWait( 1000 ); - - error = 0; - finished = 0; - for( int i = 0; i < count; i++ ) { - if( errorSpy[i]->count() > 0 ) - error++; - if( finishedSpy[i]->count() > 0 ) - finished++; - } - kDebug() << seconds << "seconds elapsed." << error << "processes error'd," - << finished << "processes finished."; - - if( error + finished >= count ) - break; - -#if 0 - if( seconds >= TIMEOUT_SECONDS ) { - kDebug() << "Timeout, gdb master!"; - QTest::qWait( 1000*1000 ); - } -#endif - QVERIFY2( seconds < TIMEOUT_SECONDS, "Timeout" ); - } - - QCOMPARE( error, 0 ); - QCOMPARE( finished, count ); - for( int i = 0; i < count; i++ ) { - kDebug() << "Checking exit status of process" << i + 1 << "of" << count; - QCOMPARE( finishedSpy[i]->count(), 1 ); - QList args = finishedSpy[i]->takeFirst(); - QCOMPARE( args[0].toInt(), 2 ); - } - - while( !procs.isEmpty() ) { - KProcess *proc = procs.takeFirst(); - QCOMPARE( proc->exitStatus(), QProcess::NormalExit ); - QCOMPARE( proc->exitCode(), 2 ); - delete proc; - } - QVERIFY( procs.isEmpty() ); -} - -void RaceTest::killZombies() -{ - while( !procs.isEmpty() ) { - // These processes probably hung, and will never recover, so we need to kill them. - // (This happens if the last test failed.) - kDebug() << "Killing zombies from the past."; - KProcess *proc = procs.takeFirst(); - proc->kill(); - proc->deleteLater(); - } -} - -QTEST_AKONADIMAIN( RaceTest, NoGUI ) - -#include "racetest.moc" diff --git a/outboxinterface/tests/racetest.h b/outboxinterface/tests/racetest.h deleted file mode 100644 index b075af4b0..000000000 --- a/outboxinterface/tests/racetest.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright 2009 Constantin Berzan - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by - the Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This library 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 Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. -*/ - -#ifndef RACETEST_H -#define RACETEST_H - -#include -#include - -class KProcess; - - -/** - This tests the ability of LocalFolders to exist peacefully in multiple processes. - The main instance (normally the first one created) is supposed to create the - resource and collections, while the other instances are supposed to wait and - then just fetch the collections. - */ -class RaceTest : public QObject -{ - Q_OBJECT - - private Q_SLOTS: - void initTestCase(); - void testMultipleProcesses_data(); - void testMultipleProcesses(); - void killZombies(); - - private: - QList procs; - -}; - - -#endif diff --git a/outboxinterface/tests/sendqueued.cpp b/outboxinterface/tests/sendqueued.cpp index c973fb177..4396a6f2e 100644 --- a/outboxinterface/tests/sendqueued.cpp +++ b/outboxinterface/tests/sendqueued.cpp @@ -1,82 +1,82 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sendqueued.h" #include #include #include #include #include #include #include +#include -#include #include using namespace Akonadi; using namespace OutboxInterface; Runner::Runner() { Control::start(); connect( LocalFolders::self(), SIGNAL( foldersReady() ), this, SLOT( checkFolders() ) ); LocalFolders::self()->fetch(); } void Runner::checkFolders() { Collection outbox = LocalFolders::self()->outbox(); kDebug() << "Got outbox" << outbox.id(); if( !outbox.isValid() ) { KApplication::exit( 1 ); } FilterActionJob *fjob = new FilterActionJob( outbox, new SendQueuedAction, this ); connect( fjob, SIGNAL(result(KJob*)), this, SLOT(jobResult(KJob*)) ); } void Runner::jobResult( KJob *job ) { if( job->error() ) { kDebug() << "Job error:" << job->errorString(); KApplication::exit( 2 ); } else { kDebug() << "Job success."; KApplication::exit( 0 ); } } int main( int argc, char **argv ) { KCmdLineArgs::init( argc, argv, "sendqueued", 0, ki18n( "sendqueued" ), "0", ki18n( "An app that sends all queued messages" ) ); KApplication app; new Runner(); return app.exec(); } #include "sendqueued.moc"