~ubuntu-branches/ubuntu/trusty/kdepimlibs/trusty

« back to all changes in this revision

Viewing changes to akonadi/tests/testrunner/setup.cpp

  • Committer: Package Import Robot
  • Author(s): Rohan Garg, Rohan Garg, Philip Muškovac
  • Date: 2013-11-23 17:36:44 UTC
  • mfrom: (1.1.102)
  • Revision ID: package-import@ubuntu.com-20131123173644-p5ow94192ezsny8g
Tags: 4:4.11.80-0ubuntu1
[ Rohan Garg ]
* New upstream beta release
  - Bump akonadi requirement to 1.10.45
  - Update install files
  - Update symbols

[ Philip Muškovac ]
* kdepimlibs-dev/-dbg breaks/replaces kdepim-runtime/-dbg (<< 4:4.11.80)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright (c) 2008  Igor Trindade Oliveira <igor_trindade@yahoo.com.br>
 
3
 * Copyright (c) 2013  Volker Krause <vkrause@kde.org>
3
4
 *
4
5
 * This library is free software; you can redistribute it and/or
5
6
 * modify it under the terms of the GNU Lesser General Public
17
18
 
18
19
#include "setup.h"
19
20
#include "config.h" //krazy:exclude=includes
20
 
#include "dbusconnectionpool.h"
21
 
#include "symbols.h"
22
 
 
23
 
#include <kapplication.h>
 
21
 
 
22
#include <akonadi/agentinstance.h>
 
23
#include <akonadi/agentinstancecreatejob.h>
 
24
#include <akonadi/resourcesynchronizationjob.h>
 
25
 
 
26
#include <KConfig>
24
27
#include <kconfiggroup.h>
25
28
#include <kdebug.h>
26
29
#include <KProcess>
27
30
#include <KStandardDirs>
28
 
#include <KToolInvocation>
29
31
 
30
32
#include <QtCore/QCoreApplication>
31
33
#include <QtCore/QDir>
32
34
#include <QtCore/QFile>
33
35
#include <QtCore/QFileInfo>
34
36
#include <QtCore/QTimer>
35
 
#include <QSignalMapper>
36
 
#include <QtDBus/QDBusConnectionInterface>
37
 
#include <QtDBus/QDBusInterface>
38
 
#include <QtDBus/QDBusReply>
39
 
#include <QtNetwork/QHostInfo>
40
37
 
41
 
#include <signal.h>
42
38
#include <unistd.h>
43
39
 
44
 
#ifdef __APPLE__
45
 
#include <AvailabilityMacros.h>
46
 
#endif
47
 
 
48
 
QMap<QString, QString> SetupTest::environment() const
49
 
{
50
 
  QMap<QString, QString> env;
51
 
 
52
 
  foreach ( const QString& val, QProcess::systemEnvironment() ) {
53
 
    const int p = val.indexOf( QLatin1Char( '=' ) );
54
 
    if ( p > 0 ) {
55
 
      env[ val.left( p ).toUpper() ] = val.mid( p + 1 );
56
 
    }
57
 
  }
58
 
 
59
 
  return env;
60
 
}
61
 
 
62
 
 
63
 
bool SetupTest::clearEnvironment()
64
 
{
65
 
  const QStringList keys = environment().keys();
66
 
 
67
 
  foreach ( const QString& key, keys ) {
68
 
    if ( key != QLatin1String( "HOME" ) ) {
69
 
// work around a bug in the Mac OS X 10.4.0 SDK
70
 
#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4)
71
 
      /* on OSX 10.4, unsetenv is a void, not a boolean */
72
 
      unsetenv( key.toLatin1() );
73
 
#else
74
 
      if ( !unsetenv( key.toLatin1() ) ) {
75
 
        return false;
76
 
      }
77
 
#endif
78
 
    }
79
 
  }
80
 
 
81
 
  return true;
82
 
}
83
 
 
84
 
int SetupTest::addDBusToEnvironment( QIODevice& io )
85
 
{
86
 
  QByteArray data = io.readLine();
87
 
  int pid = -1;
88
 
  Symbols *symbol = Symbols::instance();
89
 
 
90
 
  while ( data.size() ) {
91
 
    if ( data[ data.size() - 1 ] == '\n' ) {
92
 
      data.resize( data.size() - 1 );
93
 
    }
94
 
 
95
 
    QString val( data );
96
 
    const int p = val.indexOf( '=' );
97
 
    if ( p > 0 ) {
98
 
      const QString name = val.left( p ).toUpper();
99
 
      val = val.mid( p + 1 );
100
 
      if ( name == QLatin1String( "DBUS_SESSION_BUS_PID" ) ) {
101
 
        pid = val.toInt();
102
 
        setenv( name.toLatin1(), val.toAscii(), 1 );
103
 
        symbol->insertSymbol( name, val );
104
 
      } else if ( name == QLatin1String( "DBUS_SESSION_BUS_ADDRESS" ) ) {
105
 
        setenv( name.toLatin1(), val.toAscii(), 1 );
106
 
        symbol->insertSymbol( name, val );
107
 
      }
108
 
    }
109
 
    data = io.readLine();
110
 
  }
111
 
 
112
 
  return pid;
113
 
}
114
 
 
115
 
void SetupTest::generateDBusConfigFile( const QString& path )
116
 
{
117
 
    static const char* configFileContents =
118
 
        "<!DOCTYPE busconfig PUBLIC \"-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN\"\n"
119
 
        "\"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd\">\n"
120
 
        "<busconfig>\n"
121
 
        "<type>session</type>"
122
 
        "<keep_umask/>\n"
123
 
        "<listen>unix:path=%1</listen>\n"
124
 
        "<standard_session_servicedirs />\n"
125
 
        "<policy context=\"default\">\n"
126
 
        "<allow send_destination=\"*\" eavesdrop=\"true\"/>\n"
127
 
        "<allow eavesdrop=\"true\"/>\n"
128
 
        "<allow own=\"*\"/>\n"
129
 
        "</policy>\n"
130
 
        "</busconfig>\n";
131
 
 
132
 
    QFile confFile(path);
133
 
    if ( confFile.open( QIODevice::WriteOnly ) ) {
134
 
        const QString socketPath = basePath() + QDir::separator() + QLatin1String("dbus.socket");
135
 
        const QString data = QString::fromLatin1( configFileContents ).arg( socketPath );
136
 
        const qint64 bytes = confFile.write( data.toUtf8() );
137
 
        Q_ASSERT( bytes > 0 );
138
 
    }
139
 
}
140
 
 
141
 
int SetupTest::startDBusDaemon()
142
 
{
143
 
  QStringList dbusargs;
144
 
#ifdef Q_OS_MAC
145
 
  const QString dbusConfigFilePath = basePath() + QDir::separator() + QLatin1String("dbus-session.conf");
146
 
  generateDBusConfigFile( dbusConfigFilePath );
147
 
  Q_ASSERT( QFile::exists( dbusConfigFilePath ) );
148
 
 
149
 
  dbusargs << QString::fromLatin1("--config-file=%1").arg( dbusConfigFilePath );
150
 
#endif
151
 
 
152
 
  QProcess dbusprocess;
153
 
  dbusprocess.start( QLatin1String("dbus-launch"), dbusargs );
154
 
  bool ok = dbusprocess.waitForStarted() && dbusprocess.waitForFinished();
155
 
  if ( !ok ) {
156
 
    kWarning() << "error starting dbus-launch";
157
 
    dbusprocess.kill();
158
 
    exit(1); // failure to start an internal dbus must be considered a fatal unit test error
159
 
  }
160
 
 
161
 
  int dbuspid = addDBusToEnvironment( dbusprocess );
162
 
  return dbuspid;
163
 
}
164
 
 
165
 
void SetupTest::stopDBusDaemon( int dbuspid )
166
 
{
167
 
  kDebug() << dbuspid;
168
 
  if ( dbuspid )
169
 
    kill( dbuspid, 15 );
170
 
  sleep( 1 );
171
 
 
172
 
  if ( dbuspid )
173
 
    kill( dbuspid, 9 );
174
 
}
175
 
 
176
 
void SetupTest::registerWithInternalDBus( const QString &address )
177
 
{
178
 
  // FIXME: make this work on Windows, address is always empty there as dbus-launch does not return any environment variables like on Unix there
179
 
#ifndef Q_OS_WIN
180
 
  mInternalBus = QDBusConnection::connectToBus( address, QLatin1String( "InternalBus" ) );
181
 
#endif
182
 
  mInternalBus.registerService( QLatin1String( "org.kde.Akonadi.Testrunner" ) );
183
 
  mInternalBus.registerObject( QLatin1String( "/MainApplication" ),
184
 
                                KApplication::kApplication(),
185
 
                                QDBusConnection::ExportScriptableSlots |
186
 
                                QDBusConnection::ExportScriptableProperties |
187
 
                                QDBusConnection::ExportAdaptors );
188
 
  mInternalBus.registerObject( QLatin1String( "/" ), this, QDBusConnection::ExportScriptableSlots );
189
 
 
190
 
  connect( mInternalBus.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
191
 
           this, SLOT(dbusNameOwnerChanged(QString,QString,QString)) );
192
 
}
193
 
 
194
40
bool SetupTest::startAkonadiDaemon()
195
41
{
 
42
  Q_ASSERT(Akonadi::ServerManager::hasInstanceIdentifier());
 
43
 
196
44
  if ( !mAkonadiDaemonProcess ) {
197
45
    mAkonadiDaemonProcess = new KProcess( this );
198
46
    connect( mAkonadiDaemonProcess, SIGNAL(finished(int)),
199
47
            this, SLOT(slotAkonadiDaemonProcessFinished(int)) );
200
48
  }
201
49
 
202
 
  mAkonadiDaemonProcess->setProgram( QLatin1String( "akonadi_control" ) );
 
50
  mAkonadiDaemonProcess->setProgram( QLatin1String( "akonadi_control" ), QStringList() << QLatin1String("--instance") << instanceId() );
203
51
  mAkonadiDaemonProcess->start();
204
52
  const bool started = mAkonadiDaemonProcess->waitForStarted( 5000 );
205
53
  kDebug() << "Started akonadi daemon with pid:" << mAkonadiDaemonProcess->pid();
225
73
{
226
74
  if ( mAgentsCreated )
227
75
    return;
228
 
 
229
 
  // Start KLauncher now, so that kdeinit4 and kded4 are started. Otherwise, those might get started
230
 
  // on demand, for example in the Knut resource.
231
 
  // This on-demand starting can cause crashes due to timing issues.
232
 
  KToolInvocation::klauncher();
233
 
 
234
76
  mAgentsCreated = true;
235
77
  Config *config = Config::instance();
236
 
  QDBusInterface agentDBus( QLatin1String( "org.freedesktop.Akonadi.Control" ), QLatin1String( "/AgentManager" ),
237
 
                            QLatin1String( "org.freedesktop.Akonadi.AgentManager" ), mInternalBus );
238
 
 
239
78
  const QList<QPair<QString,bool> > agents = config->agents();
240
79
  typedef QPair<QString,bool> StringBoolPair;
241
80
  foreach ( const StringBoolPair &agent, agents ) {
242
81
    kDebug() << "Creating agent" << agent.first << "...";
243
 
    QDBusReply<QString> reply = agentDBus.call( QLatin1String( "createAgentInstance" ), agent.first );
244
 
    if ( reply.isValid() && !reply.value().isEmpty() ) {
245
 
      mPendingAgents << reply.value();
246
 
      mPendingResources << reply.value();
247
 
      if ( agent.second ) {
248
 
        mPendingSyncs << reply.value();
249
 
      }
250
 
    } else {
251
 
      kError() << "createAgentInstance call failed:" << reply.error();
252
 
    }
 
82
    ++mSetupJobCount;
 
83
    Akonadi::AgentInstanceCreateJob *job = new Akonadi::AgentInstanceCreateJob( agent.first, this );
 
84
    job->setProperty( "sync", agent.second );
 
85
    connect( job, SIGNAL(result(KJob*)), SLOT(agentCreationResult(KJob*)) );
 
86
    job->start();
253
87
  }
254
88
 
255
 
  if ( mPendingAgents.isEmpty() )
 
89
  if ( isSetupDone() )
256
90
    emit setupDone();
257
91
}
258
92
 
259
 
void SetupTest::dbusNameOwnerChanged( const QString &name, const QString &oldOwner, const QString &newOwner )
 
93
void SetupTest::agentCreationResult(KJob* job)
260
94
{
261
 
  kDebug() << name << oldOwner << newOwner;
262
 
 
263
 
  if ( name == QLatin1String( "org.freedesktop.Akonadi.Control" ) ) {
264
 
    if ( oldOwner.isEmpty() ) // startup
265
 
      setupAgents();
266
 
    else if ( mShuttingDown ) // our own shutdown
267
 
      shutdownHarder();
 
95
  --mSetupJobCount;
 
96
  if ( job->error() ) {
 
97
    kError() << job->errorString();
 
98
    setupFailed();
268
99
    return;
269
100
  }
270
 
 
271
 
  if ( name.startsWith( QLatin1String( "org.freedesktop.Akonadi.Agent." ) ) && oldOwner.isEmpty() ) {
272
 
    const QString identifier = name.mid( 30 );
273
 
    if ( mPendingAgents.contains( identifier ) ) {
274
 
      kDebug() << "Agent" << identifier << "started.";
275
 
      mPendingAgents.removeAll( identifier );
276
 
      if ( mPendingAgents.isEmpty() && mPendingResources.isEmpty() )
277
 
        QTimer::singleShot( 5000, this, SLOT(synchronizeResources()) );
278
 
    }
279
 
  }
280
 
 
281
 
  if ( name.startsWith( QLatin1String( "org.freedesktop.Akonadi.Resource." ) ) && oldOwner.isEmpty() ) {
282
 
    const QString identifier = name.mid( 33 );
283
 
    if ( mPendingResources.contains( identifier ) ) {
284
 
      kDebug() << "Resource" << identifier << "registered.";
285
 
      mPendingResources.removeAll( identifier );
286
 
      if ( mPendingAgents.isEmpty() && mPendingResources.isEmpty() )
287
 
        QTimer::singleShot( 5000, this, SLOT(synchronizeResources()) );
288
 
    }
289
 
  }
290
 
}
291
 
 
292
 
void SetupTest::synchronizeResources()
293
 
{
294
 
  foreach ( const QString &id, mPendingSyncs ) {
295
 
    QDBusInterface *iface = new QDBusInterface( QString::fromLatin1( "org.freedesktop.Akonadi.Resource.%1").arg( id ),
296
 
      "/", "org.freedesktop.Akonadi.Resource", mInternalBus, this );
297
 
    mSyncMapper->setMapping( iface, id );
298
 
    connect( iface, SIGNAL(synchronized()), mSyncMapper, SLOT(map()) );
299
 
    if ( mPendingSyncs.contains( id ) ) {
300
 
      kDebug() << "Synchronizing resource" << id << "...";
301
 
      QDBusReply<void> reply = iface->call( "synchronize" );
302
 
      if ( !reply.isValid() )
303
 
        kError() << "Syncing resource" << id << "failed: " << reply.error();
304
 
    }
305
 
  }
306
 
}
307
 
 
308
 
void SetupTest::resourceSynchronized(const QString& agentId)
309
 
{
310
 
  if ( mPendingSyncs.contains( agentId ) ) {
311
 
    kDebug() << "Agent" << agentId << "synchronized.";
312
 
    mPendingSyncs.removeAll( agentId );
313
 
    if ( mPendingSyncs.isEmpty() )
314
 
      emit setupDone();
 
101
  const bool needsSync = job->property( "sync" ).toBool();
 
102
  if (needsSync) {
 
103
    ++mSetupJobCount;
 
104
    Akonadi::ResourceSynchronizationJob *sync = new Akonadi::ResourceSynchronizationJob(
 
105
      qobject_cast<Akonadi::AgentInstanceCreateJob*>(job)->instance(), this );
 
106
    connect( sync, SIGNAL(result(KJob*)), SLOT(synchronizationResult(KJob*)) );
 
107
    sync->start();
 
108
  }
 
109
 
 
110
  if ( isSetupDone() )
 
111
    emit setupDone();
 
112
}
 
113
 
 
114
void SetupTest::synchronizationResult(KJob* job)
 
115
{
 
116
  --mSetupJobCount;
 
117
  if ( job->error() ) {
 
118
    kError() << job->errorString();
 
119
    setupFailed();
 
120
  }
 
121
 
 
122
  if ( isSetupDone() )
 
123
    emit setupDone();
 
124
}
 
125
 
 
126
void SetupTest::serverStateChanged(Akonadi::ServerManager::State state)
 
127
{
 
128
  if ( state == Akonadi::ServerManager::Running )
 
129
    setupAgents();
 
130
  else if ( mShuttingDown && state == Akonadi::ServerManager::NotRunning )
 
131
    shutdownHarder();
 
132
}
 
133
 
 
134
void SetupTest::copyXdgDirectory(const QString& src, const QString& dst)
 
135
{
 
136
  const QDir srcDir( src );
 
137
  foreach ( const QFileInfo &fi, srcDir.entryInfoList( QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot ) ) {
 
138
    if (fi.isDir()) {
 
139
      if ( fi.fileName() == QLatin1String("akonadi") ) {
 
140
        // namespace according to instance identifier
 
141
        copyDirectory( fi.absoluteFilePath(), dst + QDir::separator() + QLatin1String("akonadi") + QDir::separator()
 
142
                       + QLatin1String("instance") + QDir::separator() + instanceId() );
 
143
      } else {
 
144
        copyDirectory( fi.absoluteFilePath(), dst + QDir::separator() + fi.fileName() );
 
145
      }
 
146
    } else {
 
147
      QFile::copy( fi.absoluteFilePath(), dst + QDir::separator() + fi.fileName() );
 
148
    }
 
149
  }
 
150
}
 
151
 
 
152
void SetupTest::copyKdeHomeDirectory(const QString& src, const QString& dst)
 
153
{
 
154
  const QDir srcDir( src );
 
155
  QDir::root().mkpath( dst );
 
156
 
 
157
  foreach ( const QFileInfo &fi, srcDir.entryInfoList( QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot ) ) {
 
158
    if ( fi.isDir() ) {
 
159
      copyKdeHomeDirectory( fi.absoluteFilePath(), dst + QDir::separator() + fi.fileName() );
 
160
    } else {
 
161
      if ( fi.fileName().startsWith( QLatin1String("akonadi_") ) && fi.fileName().endsWith( QLatin1String("rc") ) ) {
 
162
        // namespace according to instance identifier
 
163
        const QString baseName = fi.fileName().left( fi.fileName().size() - 2 );
 
164
        QFile::copy( fi.absoluteFilePath(), dst + QDir::separator() + Akonadi::ServerManager::addNamespace( baseName ) + QLatin1String("rc") );
 
165
      } else {
 
166
        QFile::copy( fi.absoluteFilePath(), dst + QDir::separator() + fi.fileName() );
 
167
      }
 
168
    }
315
169
  }
316
170
}
317
171
 
318
172
void SetupTest::copyDirectory( const QString &src, const QString &dst )
319
173
{
320
 
  QDir srcDir( src );
321
 
  srcDir.setFilter( QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot );
 
174
  const QDir srcDir( src );
 
175
  QDir::root().mkpath( dst );
322
176
 
323
 
  const QFileInfoList list = srcDir.entryInfoList();
324
 
  for ( int i = 0; i < list.size(); ++i ) {
325
 
    if ( list.at( i ).isDir() ) {
326
 
      const QDir tmpDir( dst );
327
 
      tmpDir.mkdir( list.at( i ).fileName() );
328
 
      copyDirectory( list.at( i ).absoluteFilePath(), dst + QDir::separator() + list.at( i ).fileName() );
 
177
  foreach ( const QFileInfo &fi, srcDir.entryInfoList( QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot ) ) {
 
178
    if ( fi.isDir() ) {
 
179
      copyDirectory( fi.absoluteFilePath(), dst + QDir::separator() + fi.fileName() );
329
180
    } else {
330
 
      QFile::copy( srcDir.absolutePath() + QDir::separator() + list.at( i ).fileName(), dst + QDir::separator() + list.at( i ).fileName() );
 
181
      QFile::copy( fi.absoluteFilePath(), dst + QDir::separator() + fi.fileName() );
331
182
    }
332
183
  }
333
184
}
334
185
 
335
186
void SetupTest::createTempEnvironment()
336
187
{
 
188
  kDebug() << "Creating test environment in" << basePath();
 
189
 
337
190
  const QDir tmpDir( basePath() );
338
191
  const QString testRunnerKdeHomeDir = QLatin1String( "kdehome" );
339
192
  const QString testRunnerDataDir = QLatin1String( "data" );
340
193
  const QString testRunnerConfigDir = QLatin1String( "config" );
 
194
  const QString testRunnerTmpDir = QLatin1String( "tmp" );
341
195
 
342
196
  tmpDir.mkdir( testRunnerKdeHomeDir );
343
197
  tmpDir.mkdir( testRunnerConfigDir );
344
198
  tmpDir.mkdir( testRunnerDataDir );
 
199
  tmpDir.mkdir( testRunnerTmpDir );
345
200
 
346
201
  const Config *config = Config::instance();
347
 
  copyDirectory( config->kdeHome(), basePath() + testRunnerKdeHomeDir );
348
 
  copyDirectory( config->xdgConfigHome(), basePath() + testRunnerConfigDir  );
349
 
  copyDirectory( config->xdgDataHome(), basePath() + testRunnerDataDir );
 
202
  copyKdeHomeDirectory( config->kdeHome(), basePath() + testRunnerKdeHomeDir );
 
203
  copyXdgDirectory( config->xdgConfigHome(), basePath() + testRunnerConfigDir );
 
204
  copyXdgDirectory( config->xdgDataHome(), basePath() + testRunnerDataDir );
350
205
 
351
 
  // copy sycoca file from the host to increase startup speed
352
 
  const QString sycoca = KStandardDirs::locateLocal( "cache", "ksycoca4" );
353
 
  const QString cacheDir = basePath() + testRunnerKdeHomeDir + QDir::separator() + "cache-" + QHostInfo::localHostName() + QDir::separator();
354
 
  QFile::copy( sycoca, cacheDir + "ksycoca4" );
355
 
  QFile::copy( sycoca + "stamp", cacheDir + "ksycoca4stamp" );
 
206
  setEnvironmentVariable( "KDEHOME", basePath() + testRunnerKdeHomeDir );
 
207
  setEnvironmentVariable( "XDG_DATA_HOME", basePath() + testRunnerDataDir );
 
208
  setEnvironmentVariable( "XDG_CONFIG_HOME", basePath() + testRunnerConfigDir );
 
209
  setEnvironmentVariable( "TMPDIR", basePath() + testRunnerTmpDir );
356
210
}
357
211
 
358
212
// TODO Qt5: use QDir::removeRecursively
383
237
 
384
238
SetupTest::SetupTest() :
385
239
  mAkonadiDaemonProcess( 0 ),
386
 
  mInternalBus( Akonadi::DBusConnectionPool::threadConnection() ),
387
240
  mShuttingDown( false ),
388
 
  mSyncMapper( new QSignalMapper( this ) ),
389
241
  mAgentsCreated( false ),
390
 
  mTrackAkonadiProcess( true )
 
242
  mTrackAkonadiProcess( true ),
 
243
  mSetupJobCount( 0 ),
 
244
  mExitCode( 0 )
391
245
{
392
 
 
393
 
  clearEnvironment();
 
246
  setupInstanceId();
394
247
  cleanTempEnvironment();
395
248
  createTempEnvironment();
396
249
 
397
 
  setenv( "KDEHOME", qPrintable( QString( basePath() + "kdehome" ) ), 1 );
398
 
  setenv( "XDG_DATA_HOME", qPrintable( QString( basePath() + "data" ) ), 1 );
399
 
  setenv( "XDG_CONFIG_HOME", qPrintable( QString( basePath() + "config" ) ), 1 );
 
250
  // switch off agent auto-starting by default, can be re-enabled if really needed inside the config.xml
 
251
  setEnvironmentVariable( "AKONADI_DISABLE_AGENT_AUTOSTART", "true" );
 
252
  setEnvironmentVariable( "AKONADI_TESTRUNNER_PID", QString::number( QCoreApplication::instance()->applicationPid() ) );
 
253
 
400
254
  QHashIterator<QString, QString> iter( Config::instance()->envVars() );
401
255
  while( iter.hasNext() ) {
402
256
    iter.next();
403
257
    kDebug() << "Setting environment variable" << iter.key() << "=" << iter.value();
404
 
    setenv( qPrintable( iter.key() ), qPrintable( iter.value() ), 1 );
 
258
    setEnvironmentVariable( iter.key().toLocal8Bit(), iter.value() );
405
259
  }
406
260
 
407
261
  // No kres-migrator please
409
263
  KConfigGroup migrationCfg( &migratorConfig, "Migration" );
410
264
  migrationCfg.writeEntry( "Enabled", false );
411
265
 
412
 
  Symbols *symbol = Symbols::instance();
413
 
  symbol->insertSymbol( "KDEHOME", basePath() + QLatin1String( "kdehome" ) );
414
 
  symbol->insertSymbol( "XDG_DATA_HOME", basePath() + QLatin1String( "data" ) );
415
 
  symbol->insertSymbol( "XDG_CONFIG_HOME", basePath() + QLatin1String( "config" ) );
416
 
  symbol->insertSymbol( "AKONADI_TESTRUNNER_PID", QString::number( QCoreApplication::instance()->applicationPid() ) );
417
 
 
418
 
  mDBusDaemonPid = startDBusDaemon();
419
 
 
420
 
  const QString dbusAddress = symbol->symbols()[ QLatin1String( "DBUS_SESSION_BUS_ADDRESS" ) ];
421
 
  registerWithInternalDBus( dbusAddress );
422
 
 
423
 
  connect( mSyncMapper, SIGNAL(mapped(QString)), SLOT(resourceSynchronized(QString)) );
 
266
  connect( Akonadi::ServerManager::self(), SIGNAL(stateChanged(Akonadi::ServerManager::State)),
 
267
           SLOT(serverStateChanged(Akonadi::ServerManager::State)) );
 
268
 
 
269
  QDBusConnection::sessionBus().registerService( QLatin1String( "org.kde.Akonadi.Testrunner-" ) + QString::number( QCoreApplication::instance()->applicationPid() ) );
 
270
  QDBusConnection::sessionBus().registerObject( QLatin1String( "/" ), this, QDBusConnection::ExportScriptableSlots );
424
271
}
425
272
 
426
273
SetupTest::~SetupTest()
433
280
  if ( mShuttingDown )
434
281
    return;
435
282
  mShuttingDown = true;
436
 
  // check first if the Akonadi server is still running, otherwise D-Bus auto-launch will actually start it here
437
 
  if ( mInternalBus.interface()->isServiceRegistered( "org.freedesktop.Akonadi.Control" ) ) {
438
 
    kDebug() << "Shutting down Akonadi control...";
439
 
    QDBusInterface controlIface( QLatin1String( "org.freedesktop.Akonadi.Control" ), QLatin1String( "/ControlManager" ),
440
 
                                QLatin1String( "org.freedesktop.Akonadi.ControlManager" ), mInternalBus );
441
 
    QDBusReply<void> reply = controlIface.call( "shutdown" );
442
 
    if ( !reply.isValid() ) {
443
 
      kWarning() << "Failed to shutdown Akonadi control: " << reply.error().message();
444
 
      shutdownKde();
 
283
 
 
284
  switch ( Akonadi::ServerManager::self()->state() ) {
 
285
    case Akonadi::ServerManager::Running:
 
286
    case Akonadi::ServerManager::Starting:
 
287
    case Akonadi::ServerManager::Upgrading:
 
288
      kDebug() << "Shutting down Akonadi control...";
 
289
      Akonadi::ServerManager::self()->stop();
 
290
      // safety timeout
 
291
      QTimer::singleShot( 30 * 1000, this, SLOT(shutdownHarder()) );
 
292
      break;
 
293
    case Akonadi::ServerManager::NotRunning:
 
294
    case Akonadi::ServerManager::Broken:
445
295
      shutdownHarder();
446
 
    } else {
 
296
    case Akonadi::ServerManager::Stopping:
447
297
      // safety timeout
448
298
      QTimer::singleShot( 30 * 1000, this, SLOT(shutdownHarder()) );
449
 
    }
450
 
    // in case we indirectly started KDE processes, stop those before we kill their D-Bus
451
 
    shutdownKde();
452
 
  } else {
453
 
    shutdownHarder();
454
 
  }
455
 
}
456
 
 
457
 
void SetupTest::shutdownKde()
458
 
{
459
 
  if ( mInternalBus.interface()->isServiceRegistered( "org.kde.klauncher" ) ) {
460
 
    QDBusInterface klauncherIface( QLatin1String( "org.kde.klauncher" ), QLatin1String( "/" ),
461
 
                                  QLatin1String( "org.kde.KLauncher" ), mInternalBus );
462
 
    QDBusReply<void> reply = klauncherIface.call( "terminate_kdeinit" );
463
 
    if ( !reply.isValid() )
464
 
      kDebug() << reply.error();
465
 
  }
466
 
  if ( mInternalBus.interface()->isServiceRegistered( "org.kde.kded" ) ) {
467
 
    QDBusInterface klauncherIface( QLatin1String( "org.kde.kded" ), QLatin1String( "/kded" ),
468
 
                                  QLatin1String( "org.kde.kded" ), mInternalBus );
469
 
    QDBusReply<void> reply = klauncherIface.call( "quit" );
470
 
    if ( !reply.isValid() )
471
 
      kDebug() << reply.error();
 
299
      break;
472
300
  }
473
301
}
474
302
 
477
305
  kDebug();
478
306
  mShuttingDown = false;
479
307
  stopAkonadiDaemon();
480
 
  stopDBusDaemon( mDBusDaemonPid );
481
 
  QCoreApplication::instance()->quit();
 
308
  QCoreApplication::instance()->exit( mExitCode );
482
309
}
483
310
 
484
311
void SetupTest::restartAkonadiServer()
485
312
{
486
313
  kDebug();
487
314
  disconnect( mAkonadiDaemonProcess, SIGNAL(finished(int)), this, 0 );
488
 
  QDBusInterface controlIface( QLatin1String( "org.freedesktop.Akonadi.Control" ), QLatin1String( "/ControlManager" ),
489
 
                              QLatin1String( "org.freedesktop.Akonadi.ControlManager" ), mInternalBus );
490
 
  QDBusReply<void> reply = controlIface.call( "shutdown" );
491
 
  if ( !reply.isValid() )
492
 
    kWarning() << "Failed to shutdown Akonadi control: " << reply.error().message();
 
315
  Akonadi::ServerManager::self()->stop();
493
316
  const bool shutdownResult = mAkonadiDaemonProcess->waitForFinished();
494
317
  if ( !shutdownResult ) {
495
318
    kWarning() << "Akonadi control did not shut down in time, killing it.";
503
326
           this, SLOT(slotAkonadiDaemonProcessFinished(int)));
504
327
}
505
328
 
506
 
 
507
329
QString SetupTest::basePath() const
508
330
{
509
331
  QString sysTempDirPath = QDir::tempPath();
537
359
  mTrackAkonadiProcess = track;
538
360
}
539
361
 
 
362
QString SetupTest::instanceId() const
 
363
{
 
364
  return QLatin1String("testrunner-") + QString::number( QCoreApplication::instance()->applicationPid() );
 
365
}
 
366
 
 
367
void SetupTest::setupInstanceId()
 
368
{
 
369
  setEnvironmentVariable("AKONADI_INSTANCE", instanceId());
 
370
}
 
371
 
 
372
bool SetupTest::isSetupDone() const
 
373
{
 
374
  return mSetupJobCount == 0 && mExitCode == 0;
 
375
}
 
376
 
 
377
void SetupTest::setupFailed()
 
378
{
 
379
  mExitCode = 1;
 
380
  shutdown();
 
381
}
 
382
 
 
383
void SetupTest::setEnvironmentVariable(const QByteArray& name, const QString& value)
 
384
{
 
385
  mEnvVars.push_back( qMakePair(name, value.toLocal8Bit()) );
 
386
  setenv( name, qPrintable(value), 1 );
 
387
}
 
388
 
 
389
QVector< SetupTest::EnvVar > SetupTest::environmentVariables() const
 
390
{
 
391
  return mEnvVars;
 
392
}