1 /* This file is part of the KDE project
2
3 Copyright (C) 2009 Dario Massarin <nekkar@libero.it>
4 Copyright (C) 2010 Matthias Fuchs <mat69@gmx.net>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10 */
11
12 #include "testtransfers.h"
13 #include "core/transfergrouphandler.h"
14 #include "core/transferhandler.h"
15 #include "core/kget.h"
16
17 #include "kget_debug.h"
18 #include "kget_interface.h"
19 #include "transfer_interface.h"
20 #include "verifier_interface.h"
21
22 #include <KIO/CommandLauncherJob>
23 #include <KDialogJobUiDelegate>
24
25 #include <QDBusConnection>
26 #include <QDBusConnectionInterface>
27 #include <QDBusPendingReply>
28 #include <QList>
29
30 #include <QTemporaryDir>
31 #include <QTest>
32
33 //FIXME not working fine if files or transfers are existing already
34 QHash<QString, int> Commands::s_stringCommands;
35 QHash<QString, int> Commands::s_transferChangeEvents;
36
Commands(const QString & source,QObject * parent)37 Commands::Commands(const QString &source, QObject *parent)
38 : QObject(parent),
39 m_timerId(-1),
40 m_source(source),
41 m_transfer(nullptr),
42 m_verifier(nullptr)
43 {
44 static int instance = 0;
45 if (!instance++) {
46 s_stringCommands["start"] = Start;
47 s_stringCommands["stop"] = Stop;
48 s_stringCommands["addchecksum"] = AddChecksum;
49 s_stringCommands["addpartialchecksums"] = AddPartialChecksums;
50 s_stringCommands["isverifyable"] = IsVerifyable;
51 s_stringCommands["verify"] = Verify;
52 s_stringCommands["findbrokenpieces"] = FindBrokenPieces;
53 s_stringCommands["repair"] = Repair;
54 s_stringCommands["setdirectory"] = SetDirectory;
55 s_stringCommands["wait"] = Wait;
56 s_stringCommands["randomaction"] = RandomAction;
57 s_stringCommands["verified"] = Verified;
58 s_stringCommands["changedevent"] = ChangedEvent;
59 s_stringCommands["brokenpieces"] = BrokenPieces;
60
61 s_transferChangeEvents["tc_filename"] = Transfer::Tc_FileName;
62 s_transferChangeEvents["tc_status"] = Transfer::Tc_Status;
63 s_transferChangeEvents["tc_totalsize"] = Transfer::Tc_TotalSize;
64 s_transferChangeEvents["tc_percent"] = Transfer::Tc_Percent;
65 s_transferChangeEvents["tc_downloadspeed"] = Transfer::Tc_DownloadSpeed;
66 s_transferChangeEvents["tc_remainingtime"] = Transfer::Tc_RemainingTime;
67 s_transferChangeEvents["tc_uploadspeed"] = Transfer::Tc_UploadSpeed;
68 s_transferChangeEvents["tc_uploadlimit"] = Transfer::Tc_UploadLimit;
69 s_transferChangeEvents["tc_downloadlimit"] = Transfer::Tc_DownloadLimit;
70 s_transferChangeEvents["tc_canresume"] = Transfer::Tc_CanResume;
71 s_transferChangeEvents["tc_downloadedsize"] = Transfer::Tc_DownloadedSize;
72 s_transferChangeEvents["tc_uploadedsize"] = Transfer::Tc_UploadedSize;
73 s_transferChangeEvents["tc_log"] = Transfer::Tc_Log;
74 s_transferChangeEvents["tc_group"] = Transfer::Tc_Group;
75 s_transferChangeEvents["tc_selection"] = Transfer::Tc_Selection;
76 }
77 }
78
parseCommands(const QDomElement & e,TestTransfers * transfer)79 QList<QPair<int, QVariant> > Commands::parseCommands(const QDomElement& e, TestTransfers *transfer)
80 {
81 QList<QPair<int, QVariant> > commands;
82
83 for (QDomElement elem = e.firstChildElement("command"); !elem.isNull(); elem = elem.nextSiblingElement("command")) {
84 const QString typeString = elem.attribute("type").toLower();
85
86 if (!s_stringCommands.contains(typeString)) {
87 qCDebug(KGET_DEBUG) << "Error while parsing, type" << typeString << "not supported.";
88 QWARN("Problem while parsing.");
89 return commands;
90 }
91 const int type = s_stringCommands[typeString];
92
93 QVariant data;
94 QStringList args;
95 for (QDomElement arg = elem.firstChildElement("arg"); !arg.isNull(); arg = arg.nextSiblingElement("arg")) {
96 args << arg.text();
97 }
98
99 switch (type) {
100 case Verify:
101 case FindBrokenPieces:
102 case Start:
103 case Stop:
104 commands.append(QPair<int, QVariant>(type, data));
105 break;
106 case IsVerifyable:
107 case Verified:
108 case Repair:
109 if (args.count() == 1) {
110 data = args.first();
111 if (data.canConvert(QVariant::Bool)) {
112 commands.append(QPair<int, QVariant>(type, data));
113 break;
114 }
115 }
116 qCDebug(KGET_DEBUG) << "Parsing IsVerifyable/Verified/Repair failed.";
117 QWARN("Problem while parsing.");
118 break;
119 case AddChecksum:
120 if (args.count() == 2) {
121 data = args;
122 commands.append(QPair<int, QVariant>(type, data));
123 } else {
124 qCDebug(KGET_DEBUG) << "Parsing setHash failed.";
125 QWARN("Problem while parsing.");
126 }
127 break;
128 case AddPartialChecksums: {
129 if (args.count() >= 3) {
130 bool worked;
131 QList<QVariant> list;
132 list << args[0];//Type
133 const qulonglong length = args[1].toULongLong(&worked);
134 if (worked) {
135 list << length;
136 for (int i = 2; i < args.count(); ++i) {
137 list << args[i];
138 }
139 data = list;
140 commands.append(QPair<int, QVariant>(type, data));
141 break;
142 }
143 }
144 qCDebug(KGET_DEBUG) << "Parsing AddPartialChecksums failed.";
145 QWARN("Problem while parsing.");
146 break;
147 }
148 case BrokenPieces: {
149 QList<QVariant> list;
150 bool worked = true;
151 foreach (const QString &arg, args) {
152 const int value = arg.toInt(&worked);
153 if (!worked) {
154 break;
155 }
156 list << value;
157 }
158 if (worked) {
159 data = list;
160 commands.append(QPair<int, QVariant>(type, data));
161 break;
162 }
163 qCDebug(KGET_DEBUG) << "Parsing BrokenPieces failed.";
164 QWARN("Problem while parsing.");
165 break;
166 }
167 case RandomAction: {
168 QList<QVariant> list;
169 if (args.count() == 1) {
170 data = args.takeFirst();
171 if (data.canConvert(QVariant::Bool) && !data.toBool()) {
172 list << data.toBool();
173 data = list;
174 commands.append(QPair<int, QVariant>(type, data));
175 break;
176 }
177 } else if (args.count() == 2) {
178 data = args.takeFirst();
179 if (data.canConvert(QVariant::Bool) && data.toBool()) {
180 list << data.toBool();
181 bool worked;
182 list << args.takeFirst().toInt(&worked);
183 if (worked) {
184 data = list;
185 commands.append(QPair<int, QVariant>(type, data));
186 break;
187 }
188 }
189 }
190 qCDebug(KGET_DEBUG) << "Parsing RandomAction failed.";
191 QWARN("Problem while parsing.");
192 break;
193 }
194 case SetDirectory:
195 if (args.count() == 2) {
196 data = args.last();
197 QString newDirectory = args.first();
198 if (transfer) {
199 newDirectory.replace("${DIR}/", transfer->tempDir());
200 }
201 if (!newDirectory.isEmpty() && data.canConvert(QVariant::Bool)) {
202 const bool shouldWork = data.toBool();
203 QList<QVariant> list;
204 list << newDirectory << shouldWork;
205 data = list;
206 commands.append(QPair<int, QVariant>(type, data));
207 break;
208 }
209 }
210 qCDebug(KGET_DEBUG) << "Parsing SetDirectory failed.";
211 QWARN("Problem while parsing.");
212 break;
213 case Wait:
214 if (args.count() == 1) {
215 bool worked;
216 data = args.first().toInt(&worked);
217 if (worked) {
218 commands.append(QPair<int, QVariant>(type, data));
219 break;
220 }
221 }
222 qCDebug(KGET_DEBUG) << "Parsing Wait failed.";
223 QWARN("Problem while parsing.");
224 break;
225 case ChangedEvent:
226 if (!args.isEmpty() && (args.count() <= 2)) {
227 QList<QVariant> list;
228 const QString typeString = args.first().toLower();
229 if (s_transferChangeEvents.contains(typeString)) {
230 int value = s_transferChangeEvents[typeString];
231 list << value;
232 if (args.count() == 2) {
233 bool worked;
234 value = args.last().toInt(&worked);
235 if (worked) {
236 list << value;
237 data = list;
238 commands.append(QPair<int, QVariant>(type, data));
239 break;
240 }
241 } else {
242 data = list;
243 commands.append(QPair<int, QVariant>(type, data));
244 break;
245 }
246 }
247 }
248 qCDebug(KGET_DEBUG) << "Parsing ChangedEvent failed" << args;
249 QWARN("Problem while parsing.");
250 break;
251 default:
252 QWARN("Default should never happen.");
253 break;
254 }
255 }
256
257 return commands;
258 }
259
source() const260 QString Commands::source() const
261 {
262 return m_source;
263 }
264
associateTransfer(OrgKdeKgetTransferInterface * transfer)265 void Commands::associateTransfer(OrgKdeKgetTransferInterface *transfer)
266 {
267 if (m_transfer) {
268 disconnect(m_transfer, nullptr, this, nullptr);
269 }
270 if (m_verifier) {
271 disconnect(m_verifier, nullptr, this, nullptr);
272 delete m_verifier;
273 }
274
275 m_transfer = transfer;
276 qCDebug(KGET_DEBUG) << this << "associated with" << m_transfer << m_source;
277
278 QDBusPendingReply<QString> reply = m_transfer->dest();
279 const QString dest = reply.value();
280
281 reply = m_transfer->verifier(dest);
282 m_verifier = new OrgKdeKgetVerifierInterface("org.kde.kget", reply.value(), QDBusConnection::sessionBus(), this);
283
284 connect(m_verifier, &OrgKdeKgetVerifierInterface::verified, this, &Commands::slotVerified);
285 connect(m_verifier, SIGNAL(brokenPieces(QStringList,qulonglong)), this, SLOT(slotBrokenPieces(QStringList,qulonglong)));
286 connect(m_transfer, &OrgKdeKgetTransferInterface::transferChangedEvent, this, &Commands::slotChangedEvent);
287 }
288
hasCommands() const289 bool Commands::hasCommands() const
290 {
291 return !m_commands.isEmpty();
292 }
293
setCommands(const QList<QPair<int,QVariant>> & commands)294 void Commands::setCommands(const QList<QPair<int, QVariant> > &commands)
295 {
296 m_commands = commands;
297 }
298
timerEvent(QTimerEvent * event)299 void Commands::timerEvent(QTimerEvent *event)
300 {
301 Q_UNUSED(event)
302
303 const int value = qrand() % 10;
304 //70% of the cases start, in 30% stop
305 if (value > 2) {
306 qCDebug(KGET_DEBUG) << this << "is randomly started.";
307 m_transfer->start();
308 } else {
309 qCDebug(KGET_DEBUG) << this << "is randomly stopped";
310 m_transfer->stop();
311 }
312 }
313
slotWaitEvent()314 void Commands::slotWaitEvent()
315 {
316 //wait is over so continue with executing commands
317 if (!m_commands.isEmpty()) {
318 m_commands.takeFirst();
319 executeCommands();
320 }
321 }
322
executeCommands()323 void Commands::executeCommands()
324 {
325 if (!m_transfer) {
326 QFAIL("Calling executeCommands when no transfer is set.");
327 }
328
329 //NOTE no checks are being done if the commands are correct, this is to ensure that KGet crashes
330 //on faulty commands making sure that those are found
331 while (!m_commands.isEmpty()) {
332 const QPair<int, QVariant> operation = m_commands.first();
333 const int type = operation.first;
334
335 if (type >= CustomEvent) {
336 return;
337 }
338 const QVariant command = operation.second;
339
340 switch (type) {
341 case Start:
342 m_transfer->start();
343 qCDebug(KGET_DEBUG) << this << "is started.";
344 break;
345 case Stop:
346 m_transfer->stop();
347 qCDebug(KGET_DEBUG) << this << "is stopped.";
348 break;
349 case AddChecksum: {
350 QStringList hash = command.toStringList();
351 qCDebug(KGET_DEBUG) << this << "adding hash" << hash;
352 QDBusPendingReply<void> reply = m_verifier->addChecksum(hash.takeFirst(), hash.takeLast());
353 break;
354 }
355 case AddPartialChecksums: {
356 QList<QVariant> list = command.toList();
357 qCDebug(KGET_DEBUG) << this << "adding partial hash" << list;
358 const QString type = list.takeFirst().toString();
359 const qulonglong length = list.takeFirst().toULongLong();
360 QStringList checksums;
361 foreach (const QVariant &value, list) {
362 checksums << value.toString();
363 }
364 m_verifier->addPartialChecksums(type, length, checksums);
365 break;
366 }
367 case IsVerifyable: {
368 const bool shouldWork = command.toBool();
369 QDBusPendingReply<bool> reply = m_verifier->isVerifyable();
370 qCDebug(KGET_DEBUG) << this << "isVerifyable" << reply.value();
371 QVERIFY(reply.value() == shouldWork);
372 break;
373 }
374 case Verify: {
375 qCDebug(KGET_DEBUG) << this << "verification started.";
376 m_verifier->verify();
377 break;
378 }
379 case FindBrokenPieces:
380 qCDebug(KGET_DEBUG) << this << "find broken pieces.";
381 m_verifier->brokenPieces();
382 break;
383 case Repair: {
384 const bool shouldWork = command.toBool();
385 QDBusPendingReply<QString> dest = m_transfer->dest();
386 QDBusPendingReply<bool> reply = m_transfer->repair(dest.value());
387
388 const bool isRepairable = reply.value();
389 qCDebug(KGET_DEBUG) << this << "repair started" << isRepairable;
390 QVERIFY(isRepairable == shouldWork);
391 break;
392 }
393 case SetDirectory: {
394 QList<QVariant> commands = command.toList();
395 const QString newDirectory = commands.takeFirst().toString();
396 const bool shouldWork = commands.takeFirst().toBool();
397 QDBusPendingReply<bool> reply = m_transfer->setDirectory(newDirectory);
398
399 const bool moveStarted = reply.value();
400 qCDebug(KGET_DEBUG) << this << "set changing directory started" << moveStarted;
401 QVERIFY(moveStarted == shouldWork);
402 break;
403 }
404 case Wait: {
405 const int time = command.toInt();
406 qCDebug(KGET_DEBUG) << this << "waiting for" << time << "msecs" << m_transfer;
407 QTimer::singleShot(time, this, &Commands::slotWaitEvent);
408 return;
409 break;
410 }
411 case RandomAction: {
412 QList<QVariant> commands = command.toList();
413 const bool turnOn = commands.takeFirst().toBool();
414 if (m_timerId == -1) {
415 if (turnOn) {
416 qCDebug(KGET_DEBUG) << this << "starting random timer.";
417 m_timerId = startTimer(commands.takeFirst().toInt());
418 }
419 } else {
420 qCDebug(KGET_DEBUG) << this << "killing random timer.";
421 killTimer(m_timerId);
422 m_timerId = -1;
423 if (turnOn) {
424 qCDebug(KGET_DEBUG) << this << "starting random timer.";
425 m_timerId = startTimer(commands.takeFirst().toInt());
426 }
427 }
428 break;
429 }
430 }
431
432 m_commands.takeFirst();
433 }
434 }
slotChangedEvent(int event)435 void Commands::slotChangedEvent(int event)
436 {
437 if (!m_transfer || m_commands.isEmpty()) {
438 return;
439 }
440
441 const QPair<int, QVariant> operation = m_commands.first();
442 const int type = operation.first;
443
444 if (type != ChangedEvent) {
445 return;
446 }
447
448 const QList<QVariant> commands = operation.second.toList();
449
450 //at least one and maximum two commands allowed;
451 if (commands.isEmpty() || commands.count() > 2) {
452 return;
453 }
454
455 bool worked;
456 const int eventType = commands.first().toInt(&worked);
457 if (!worked || !(eventType & event)) {
458 return;
459 }
460
461 if (commands.count() == 2) {
462 const int compareValue = commands.last().toInt(&worked);
463 if (!worked) {
464 return;
465 }
466
467 switch (eventType) {
468 case Transfer::Tc_Status: {
469 QDBusPendingReply<int> reply = m_transfer->status();
470 if (reply.value() == compareValue) {
471 m_commands.takeFirst();
472 executeCommands();
473 }
474 break;
475 }
476 case Transfer::Tc_Percent: {
477 QDBusPendingReply<int> reply = m_transfer->percent();
478 if (reply.value() >= compareValue) {
479 qCDebug(KGET_DEBUG) << this << "ChangedEvent percent.";
480 m_commands.takeFirst();
481 executeCommands();
482 }
483 break;
484 }
485 default:
486 break;
487 }
488 } else {
489 m_commands.takeFirst();
490 executeCommands();
491 }
492 }
493
slotVerified(bool verified)494 void Commands::slotVerified(bool verified)
495 {
496 if (!m_commands.isEmpty()) {
497 const QPair<int, QVariant> operation = m_commands.first();
498 const int type = operation.first;
499
500 if (type == Verified) {
501 const QVariant command = operation.second;
502 m_commands.takeFirst();
503 if (command.canConvert(QVariant::Bool)) {
504 const bool shouldWork = command.toBool();
505 qCDebug(KGET_DEBUG) << this << "is verified" << verified;
506 QVERIFY(verified == shouldWork);
507 }
508
509 executeCommands();
510 return;
511 }
512 }
513
514 qCDebug(KGET_DEBUG) << this << "is verified" << verified;
515 QVERIFY(verified);
516 }
517
slotBrokenPieces(const QStringList & offsets,qulonglong length)518 void Commands::slotBrokenPieces(const QStringList &offsets, qulonglong length)
519 {
520 if (m_commands.isEmpty()) {
521 return;
522 }
523
524 const QPair<int, QVariant> operation = m_commands.first();
525 const int type = operation.first;
526 if (type != BrokenPieces) {
527 return;
528 }
529
530 // QList<QVariant> list = brokenPieces.variant().toList();//FIXME
531 QList<QVariant> compareList = operation.second.toList();
532 if (offsets.count() != compareList.count()) {
533 QFAIL("Emitted brokenPieces list does not match.");
534 }
535 for (int i = 0; i < offsets.count(); ++i) {
536 QVERIFY(static_cast<int>(offsets[i].toULongLong() / length) == compareList[i].toInt());
537 }
538
539 m_commands.takeFirst();
540 executeCommands();
541 }
542
TestTransfers()543 TestTransfers::TestTransfers()
544 {
545 if(!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget")) {
546 const QString command = QStringLiteral("kget --showDropTarget --hideMainWindow");
547 auto *job = new KIO::CommandLauncherJob(command);
548 job->setDesktopName(QStringLiteral("org.kde.kget"));
549 job->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, nullptr));
550 job->start();
551 }
552
553 m_dir.reset(new QTemporaryDir());
554 qCDebug(KGET_DEBUG) << "Using temp dir:" << tempDir();
555
556 //TODO add a signal to check if the move worked!!
557
558 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdeedu-4.3.1.tar.bz2"
559 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdegames-4.3.1.tar.bz2"
560 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdegraphics-4.3.1.tar.bz2"
561 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdelibs-4.3.1.tar.bz2"
562 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdelibs-experimental-4.3.1.tar.bz2"
563 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdemultimedia-4.3.1.tar.bz2"
564 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdenetwork-4.3.1.tar.bz2"
565 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdepim-4.3.1.tar.bz2"
566 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdepim-runtime-4.3.1.tar.bz2"
567 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdepimlibs-4.3.1.tar.bz2"
568 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdeplasma-addons-4.3.1.tar.bz2"
569 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdesdk-4.3.1.tar.bz2"
570 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdetoys-4.3.1.tar.bz2"
571 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/kdewebdev-4.3.1.tar.bz2"
572 // << "http://mirrors.isc.org/pub/kde/stable/4.3.1/src/oxygen-icons-4.3.1.tar.bz2";
573
574 // << "6326cff7779dfadc1b18a3a6bbe7b0750fb7ceaf"
575 // << "576255ce66a0c089e0840bd90ea89d5705872bc8"
576 // << "d57d9007b95607c0ee925cc963d7e14798fc69f9"
577 // << "511532852caca9302c643fded4013ef1f57d5433"
578 // << "7d560817a186c4b7099d321ee4a58705962a59d3"
579 // << "ef50f869f1a6cdf91fe7808f095fccbd9463a7dd"
580 // << "57194b5f89b37329e562951c491fa18029c0b431"
581 // << "6fd0309dbd911e2667ec1c08d1f10f2626a54534"
582 // << "c39b0fc1d3721fb8c6074ba6a174ad8716c6c604"
583 // << "f4b04b21a6aa3accc530bc6c32cf0d820c611265"
584 // << "83421181dd3a80c4ac0ff5bab111b7f71f6a1192"
585 // << "ded236a12002b824f97856ce5dc882161ed437d2"
586 // << "31a60deafef34a02fb7de5339eed1c750a456d3b"
587 // << "28580c6f283fa7a6405f6a4415ebe9a4167f0992"
588 // << "75a82d2e80d946333f63e32db56767c3ed17ba33";
589 }
590
tempDir() const591 QString TestTransfers::tempDir() const
592 {
593 return m_dir->path();
594 }
595
parseFile()596 void TestTransfers::parseFile()
597 {
598 const QString xmlFile = QFINDTESTDATA("kget-test.xml");
599 QVERIFY(!xmlFile.isEmpty());
600 QFile file(xmlFile);
601 QVERIFY(file.open(QIODevice::ReadOnly));
602
603 QDomDocument doc;
604 if (!doc.setContent(&file)) {
605 QFAIL("Not able to set content.");
606 }
607
608 for (QDomElement elem = doc.firstChildElement("tests").firstChildElement("transfer"); !elem.isNull(); elem = elem.nextSiblingElement("transfer")) {
609 const QString source = elem.attribute("source");
610 if (source.isEmpty()) {
611 QFAIL("One transfer does not have an source attribute.");
612 return;
613 }
614 auto *transfer = new Commands(source, this);
615 transfer->setCommands(Commands::parseCommands(elem, this));
616 m_commands.append(transfer);
617 }
618 }
619
createTransfer()620 void TestTransfers::createTransfer()
621 {
622 if (m_commands.isEmpty()) {
623 QFAIL("No commands set.");
624 }
625
626
627 if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget")) {
628 qCDebug(KGET_DEBUG) << "Service not registered yet, retrying.";
629 QTimer::singleShot(500, this, &TestTransfers::createTransfer);
630 return;
631 }
632 QVERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget"));
633
634 OrgKdeKgetMainInterface kgetInterface("org.kde.kget", "/KGet", QDBusConnection::sessionBus());
635
636 foreach (Commands *command, m_commands) {
637 QDBusPendingReply<QStringList> reply = kgetInterface.addTransfer(command->source(), tempDir() + QUrl::fromLocalFile(command->source()).fileName(), false);
638 reply.waitForFinished();
639
640 if (reply.value().size()) {
641 qCDebug(KGET_DEBUG) << "TestTransfers::createTransfer -> transfer = " << reply.value();
642 auto *transfer = new OrgKdeKgetTransferInterface("org.kde.kget", reply.value().first(), QDBusConnection::sessionBus(), this);
643
644 command->associateTransfer(transfer);
645 command->executeCommands();
646 } else {
647 QFAIL("Reply NOT VALID!!!");
648 }
649 }
650 }
651
simpleTest()652 void TestTransfers::simpleTest()
653 {
654 parseFile();
655 createTransfer();
656
657 //execute as long as there are still commands left
658 forever {
659 bool abort = true;
660 foreach (Commands *commands, m_commands) {
661 if (commands->hasCommands()) {
662 abort = false;
663 break;
664 }
665 }
666
667 if (abort) {
668 break;
669 }
670 QTest::qWait(3000);
671 }
672 }
673
674 QTEST_MAIN(TestTransfers)
675
676