ctkCmdLineModuleFutureTest.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #include <ctkCmdLineModuleManager.h>
  16. #include <ctkCmdLineModuleFrontendFactory.h>
  17. #include <ctkCmdLineModuleFrontend.h>
  18. #include <ctkCmdLineModuleReference.h>
  19. #include <ctkCmdLineModuleDescription.h>
  20. #include <ctkCmdLineModuleParameter.h>
  21. #include <ctkCmdLineModuleRunException.h>
  22. #include <ctkCmdLineModuleFuture.h>
  23. #include "ctkCmdLineModuleSignalTester.h"
  24. #include "ctkCmdLineModuleBackendLocalProcess.h"
  25. #include "ctkTest.h"
  26. #include <QVariant>
  27. #include <QCoreApplication>
  28. #include <QDebug>
  29. #include <QFutureWatcher>
  30. //-----------------------------------------------------------------------------
  31. class ctkCmdLineModuleFrontendMockupFactory : public ctkCmdLineModuleFrontendFactory
  32. {
  33. public:
  34. virtual ctkCmdLineModuleFrontend* create(const ctkCmdLineModuleReference& moduleRef)
  35. {
  36. struct ModuleFrontendMockup : public ctkCmdLineModuleFrontend
  37. {
  38. ModuleFrontendMockup(const ctkCmdLineModuleReference& moduleRef)
  39. : ctkCmdLineModuleFrontend(moduleRef) {}
  40. virtual QObject* guiHandle() const { return NULL; }
  41. virtual QVariant value(const QString& parameter, int role) const
  42. {
  43. Q_UNUSED(role)
  44. QVariant value = currentValues[parameter];
  45. if (!value.isValid())
  46. return this->moduleReference().description().parameter(parameter).defaultValue();
  47. return value;
  48. }
  49. virtual void setValue(const QString& parameter, const QVariant& value)
  50. {
  51. currentValues[parameter] = value;
  52. }
  53. private:
  54. QHash<QString, QVariant> currentValues;
  55. };
  56. return new ModuleFrontendMockup(moduleRef);
  57. }
  58. virtual QString name() const { return "Mock-up"; }
  59. virtual QString description() const { return "A mock-up factory for testing."; }
  60. };
  61. //-----------------------------------------------------------------------------
  62. class ctkCmdLineModuleFutureTester : public QObject
  63. {
  64. Q_OBJECT
  65. private Q_SLOTS:
  66. void initTestCase();
  67. void init();
  68. void cleanup();
  69. void testStartFinish();
  70. void testProgress();
  71. void testPauseAndCancel();
  72. void testError();
  73. private:
  74. ctkCmdLineModuleFrontendMockupFactory factory;
  75. ctkCmdLineModuleBackendLocalProcess backend;
  76. ctkCmdLineModuleManager manager;
  77. ctkCmdLineModuleReference moduleRef;
  78. ctkCmdLineModuleFrontend* frontend;
  79. };
  80. //-----------------------------------------------------------------------------
  81. void ctkCmdLineModuleFutureTester::initTestCase()
  82. {
  83. manager.registerBackend(&backend);
  84. QUrl moduleUrl = QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + "/ctkCmdLineModuleTestBed");
  85. moduleRef = manager.registerModule(moduleUrl);
  86. }
  87. //-----------------------------------------------------------------------------
  88. void ctkCmdLineModuleFutureTester::init()
  89. {
  90. frontend = factory.create(moduleRef);
  91. }
  92. //-----------------------------------------------------------------------------
  93. void ctkCmdLineModuleFutureTester::cleanup()
  94. {
  95. delete frontend;
  96. }
  97. //-----------------------------------------------------------------------------
  98. void ctkCmdLineModuleFutureTester::testStartFinish()
  99. {
  100. QList<QString> expectedSignals;
  101. expectedSignals.push_back("module.started");
  102. expectedSignals.push_back("module.finished");
  103. ctkCmdLineModuleSignalTester signalTester;
  104. QFutureWatcher<ctkCmdLineModuleResult> watcher;
  105. QObject::connect(&watcher, SIGNAL(started()), &signalTester, SLOT(moduleStarted()));
  106. QObject::connect(&watcher, SIGNAL(finished()), &signalTester, SLOT(moduleFinished()));
  107. ctkCmdLineModuleFuture future = manager.run(frontend);
  108. watcher.setFuture(future);
  109. future.waitForFinished();
  110. QCoreApplication::processEvents();
  111. QVERIFY(signalTester.checkSignals(expectedSignals));
  112. }
  113. //-----------------------------------------------------------------------------
  114. void ctkCmdLineModuleFutureTester::testProgress()
  115. {
  116. QList<QString> expectedSignals;
  117. expectedSignals.push_back("module.started");
  118. // this signal is send when connecting a QFutureWatcher to
  119. // an already started QFuture
  120. expectedSignals.push_back("module.progressValueChanged");
  121. // the following two signals are send when the module reports "filter start"
  122. expectedSignals.push_back("module.progressValueChanged");
  123. expectedSignals.push_back("module.progressTextChanged");
  124. // this signal is send when the module reports progress for "output1"
  125. expectedSignals.push_back("module.progressValueChanged");
  126. // the following two signal are sent at the end to report
  127. // completion and the full standard output text.
  128. expectedSignals.push_back("module.progressValueChanged");
  129. expectedSignals.push_back("module.progressTextChanged");
  130. expectedSignals.push_back("module.finished");
  131. ctkCmdLineModuleSignalTester signalTester;
  132. QFutureWatcher<ctkCmdLineModuleResult> watcher;
  133. QObject::connect(&watcher, SIGNAL(started()), &signalTester, SLOT(moduleStarted()));
  134. QObject::connect(&watcher, SIGNAL(progressValueChanged(int)), &signalTester, SLOT(moduleProgressValueChanged(int)));
  135. QObject::connect(&watcher, SIGNAL(progressTextChanged(QString)), &signalTester, SLOT(moduleProgressTextChanged(QString)));
  136. QObject::connect(&watcher, SIGNAL(finished()), &signalTester, SLOT(moduleFinished()));
  137. frontend->setValue("numOutputsVar", 1);
  138. ctkCmdLineModuleFuture future = manager.run(frontend);
  139. watcher.setFuture(future);
  140. future.waitForFinished();
  141. // process pending events
  142. QCoreApplication::processEvents();
  143. QVERIFY(signalTester.checkSignals(expectedSignals));
  144. }
  145. //-----------------------------------------------------------------------------
  146. void ctkCmdLineModuleFutureTester::testPauseAndCancel()
  147. {
  148. ctkCmdLineModuleSignalTester signalTester;
  149. QFutureWatcher<ctkCmdLineModuleResult> watcher;
  150. QObject::connect(&watcher, SIGNAL(started()), &signalTester, SLOT(moduleStarted()));
  151. QObject::connect(&watcher, SIGNAL(paused()), &signalTester, SLOT(modulePaused()));
  152. QObject::connect(&watcher, SIGNAL(resumed()), &signalTester, SLOT(moduleResumed()));
  153. QObject::connect(&watcher, SIGNAL(canceled()), &signalTester, SLOT(moduleCanceled()));
  154. QObject::connect(&watcher, SIGNAL(finished()), &signalTester, SLOT(moduleFinished()));
  155. frontend->setValue("runtimeVar", 60);
  156. ctkCmdLineModuleFuture future = manager.run(frontend);
  157. watcher.setFuture(future);
  158. QList<QString> expectedSignals;
  159. expectedSignals.push_back("module.started");
  160. if (future.canPause())
  161. {
  162. // Due to Qt bug 12152, these two signals are reversed
  163. expectedSignals.push_back("module.resumed");
  164. expectedSignals.push_back("module.paused");
  165. }
  166. if (future.canCancel())
  167. {
  168. expectedSignals.push_back("module.canceled");
  169. }
  170. expectedSignals.push_back("module.finished");
  171. QTest::qWait(100);
  172. future.pause();
  173. QTest::qWait(100);
  174. QVERIFY(future.isRunning());
  175. if (future.canPause())
  176. {
  177. QVERIFY(future.isPaused());
  178. }
  179. future.togglePaused();
  180. QTest::qWait(100);
  181. QVERIFY(!future.isPaused());
  182. QVERIFY(future.isRunning());
  183. future.cancel();
  184. future.waitForFinished();
  185. // process pending events
  186. QCoreApplication::processEvents();
  187. QVERIFY(future.isCanceled());
  188. QVERIFY(future.isFinished());
  189. QVERIFY(signalTester.checkSignals(expectedSignals));
  190. }
  191. //-----------------------------------------------------------------------------
  192. void ctkCmdLineModuleFutureTester::testError()
  193. {
  194. frontend->setValue("fileVar", "output1");
  195. frontend->setValue("exitCodeVar", 24);
  196. frontend->setValue("errorTextVar", "Some error occured\n");
  197. QFutureWatcher<ctkCmdLineModuleResult> watcher;
  198. ctkCmdLineModuleFuture future = manager.run(frontend);
  199. watcher.setFuture(future);
  200. try
  201. {
  202. future.waitForFinished();
  203. QFAIL("Expected exception not thrown.");
  204. }
  205. catch (const ctkCmdLineModuleRunException& e)
  206. {
  207. QVERIFY2(e.errorCode() == 24, "Test matching error code");
  208. QVERIFY2(e.errorString() == "Some error occured\n", "Error text mismatch");
  209. }
  210. }
  211. // ----------------------------------------------------------------------------
  212. CTK_TEST_MAIN(ctkCmdLineModuleFutureTest)
  213. #include "moc_ctkCmdLineModuleFutureTest.cpp"