| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 | 
							- /*=============================================================================
 
-   
 
-   Library: CTK
 
-   
 
-   Copyright (c) German Cancer Research Center,
 
-     Division of Medical and Biological Informatics
 
-     
 
-   Licensed under the Apache License, Version 2.0 (the "License");
 
-   you may not use this file except in compliance with the License.
 
-   You may obtain a copy of the License at
 
-   
 
-     http://www.apache.org/licenses/LICENSE-2.0
 
-     
 
-   Unless required by applicable law or agreed to in writing, software
 
-   distributed under the License is distributed on an "AS IS" BASIS,
 
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-   See the License for the specific language governing permissions and
 
-   limitations under the License.
 
-   
 
- =============================================================================*/
 
- #include <ctkCmdLineModuleManager.h>
 
- #include <ctkCmdLineModuleFrontendFactory.h>
 
- #include <ctkCmdLineModuleFrontend.h>
 
- #include <ctkCmdLineModuleReference.h>
 
- #include <ctkCmdLineModuleDescription.h>
 
- #include <ctkCmdLineModuleParameter.h>
 
- #include <ctkCmdLineModuleRunException.h>
 
- #include <ctkCmdLineModuleFuture.h>
 
- #include <ctkCmdLineModuleFutureWatcher.h>
 
- #include "ctkCmdLineModuleSignalTester.h"
 
- #include "ctkCmdLineModuleBackendLocalProcess.h"
 
- #include "ctkTest.h"
 
- #include <QVariant>
 
- #include <QCoreApplication>
 
- #include <QDebug>
 
- #include <QFutureWatcher>
 
- //-----------------------------------------------------------------------------
 
- class ctkCmdLineModuleFrontendMockupFactory : public ctkCmdLineModuleFrontendFactory
 
- {
 
- public:
 
-   virtual ctkCmdLineModuleFrontend* create(const ctkCmdLineModuleReference& moduleRef)
 
-   {
 
-     struct ModuleFrontendMockup : public ctkCmdLineModuleFrontend
 
-     {
 
-       ModuleFrontendMockup(const ctkCmdLineModuleReference& moduleRef)
 
-         : ctkCmdLineModuleFrontend(moduleRef) {}
 
-       virtual QObject* guiHandle() const { return NULL; }
 
-       virtual QVariant value(const QString& parameter, int role) const
 
-       {
 
-         Q_UNUSED(role)
 
-         QVariant value = currentValues[parameter];
 
-         if (!value.isValid())
 
-           return this->moduleReference().description().parameter(parameter).defaultValue();
 
-         return value;
 
-       }
 
-       virtual void setValue(const QString& parameter, const QVariant& value, int role = DisplayRole)
 
-       {
 
-         Q_UNUSED(role)
 
-         currentValues[parameter] = value;
 
-       }
 
-     private:
 
-       QHash<QString, QVariant> currentValues;
 
-     };
 
-     return new ModuleFrontendMockup(moduleRef);
 
-   }
 
-   virtual QString name() const { return "Mock-up"; }
 
-   virtual QString description() const { return "A mock-up factory for testing."; }
 
- };
 
- //-----------------------------------------------------------------------------
 
- class ctkCmdLineModuleFutureTester : public QObject
 
- {
 
-   Q_OBJECT
 
- public Q_SLOTS:
 
-   void ouputDataReady();
 
-   void errorDataReady();
 
- private Q_SLOTS:
 
-   void initTestCase();
 
-   void init();
 
-   void cleanup();
 
-   void testStartFinish();
 
-   void testProgress();
 
-   void testPauseAndCancel();
 
-   void testOutput();
 
-   void testError();
 
- private:
 
-   QByteArray outputData;
 
-   QByteArray errorData;
 
-   ctkCmdLineModuleFutureWatcher* currentWatcher;
 
-   ctkCmdLineModuleFrontendMockupFactory factory;
 
-   ctkCmdLineModuleBackendLocalProcess backend;
 
-   ctkCmdLineModuleManager manager;
 
-   ctkCmdLineModuleReference moduleRef;
 
-   ctkCmdLineModuleFrontend* frontend;
 
- };
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::ouputDataReady()
 
- {
 
-   if (this->currentWatcher)
 
-   {
 
-     outputData.append(currentWatcher->readPendingOutputData());
 
-   }
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::errorDataReady()
 
- {
 
-   if (this->currentWatcher)
 
-   {
 
-     errorData.append(currentWatcher->readPendingErrorData());
 
-   }
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::initTestCase()
 
- {
 
-   manager.registerBackend(&backend);
 
-   QUrl moduleUrl = QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + "/ctkCmdLineModuleTestBed");
 
-   moduleRef = manager.registerModule(moduleUrl);
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::init()
 
- {
 
-   currentWatcher = 0;
 
-   frontend = factory.create(moduleRef);
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::cleanup()
 
- {
 
-   delete frontend;
 
-   outputData.clear();
 
-   errorData.clear();
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::testStartFinish()
 
- {
 
-   QList<QString> expectedSignals;
 
-   expectedSignals << "module.started"
 
-                      // the following signals are send when connecting a QFutureWatcher to
 
-                      // an already started QFuture
 
-                   << "module.progressRangeChanged(0,0)"
 
-                   << "module.progressValueChanged(0)"
 
-                   << "module.progressRangeChanged(0,1002)"
 
-                      // the test module always reports error data when starting
 
-                   << "module.errorReady"
 
-                      // the following two signals are send when the module reports "filter start"
 
-                   << "module.progressValueChanged(1)"
 
-                   << "module.progressTextChanged(Does nothing useful)"
 
-                      // imageOutput result
 
-                   << "module.resultReadyAt(0,1)"
 
-                   << "module.resultReadyAt(0)"
 
-                      // exitStatusOutput result
 
-                   << "module.resultReadyAt(1,2)"
 
-                   << "module.resultReadyAt(1)"
 
-                      // final progress report from the module
 
-                   << "module.progressValueChanged(1000)"
 
-                      // <filter-end> progress value and text
 
-                   << "module.progressValueChanged(1001)"
 
-                   << "module.progressTextChanged(Finished successfully.)"
 
-                      // the following signal is sent at the end to report completion
 
-                   << "module.progressValueChanged(1002)"
 
-                   << "module.finished";
 
-   ctkCmdLineModuleSignalTester signalTester;
 
-   ctkCmdLineModuleFuture future = manager.run(frontend);
 
-   signalTester.setFuture(future);
 
-   future.waitForFinished();
 
-   QCoreApplication::processEvents();
 
-   QVERIFY(signalTester.checkSignals(expectedSignals));
 
-   QList<ctkCmdLineModuleResult> results;
 
-   results << ctkCmdLineModuleResult("imageOutput", "/tmp/out.nrrd");
 
-   results << ctkCmdLineModuleResult("exitStatusOutput", "Normal exit");
 
-   QCOMPARE(signalTester.results(), results);
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::testProgress()
 
- {
 
-   QList<QString> expectedSignals;
 
-   expectedSignals << "module.started"
 
-                      // the following signals are send when connecting a QFutureWatcher to
 
-                      // an already started QFuture
 
-                   << "module.progressRangeChanged(0,0)"
 
-                   << "module.progressValueChanged(0)"
 
-                   << "module.progressRangeChanged(0,1002)"
 
-                      // the test module always reports error data when starting
 
-                   << "module.errorReady"
 
-                      // the following two signals are send when the module reports "filter start"
 
-                   << "module.progressValueChanged(1)"
 
-                   << "module.progressTextChanged(Does nothing useful)"
 
-                      // the output data on the standard output channel
 
-                   << "module.outputReady"
 
-                      // this signal is send when the module reports progress for "output1"
 
-                   << "module.progressValueChanged(1000)"
 
-                   << "module.progressTextChanged(Calculating output 2...)"
 
-                      // first resultNumberOutput result
 
-                   << "module.resultReadyAt(0,1)"
 
-                   << "module.resultReadyAt(0)"
 
-                      // imageOutput result
 
-                   << "module.resultReadyAt(1,2)"
 
-                   << "module.resultReadyAt(1)"
 
-                      // exitStatusOutput result
 
-                   << "module.resultReadyAt(2,3)"
 
-                   << "module.resultReadyAt(2)"
 
-                      // <filter-end> progress value and text
 
-                   << "module.progressValueChanged(1001)"
 
-                   << "module.progressTextChanged(Finished successfully.)"
 
-                      // the following signal is sent at the end to report completion
 
-                   << "module.progressValueChanged(1002)"
 
-                   << "module.finished";
 
-   ctkCmdLineModuleSignalTester signalTester;
 
-   frontend->setValue("numOutputsVar", 1);
 
-   ctkCmdLineModuleFuture future = manager.run(frontend);
 
-   signalTester.setFuture(future);
 
-   future.waitForFinished();
 
-   // process pending events
 
-   QCoreApplication::processEvents();
 
-   QVERIFY(signalTester.checkSignals(expectedSignals));
 
-   QList<ctkCmdLineModuleResult> results;
 
-   results << ctkCmdLineModuleResult("resultNumberOutput", 1);
 
-   results << ctkCmdLineModuleResult("imageOutput", "/tmp/out.nrrd");
 
-   results << ctkCmdLineModuleResult("exitStatusOutput", "Normal exit");
 
-   QCOMPARE(signalTester.results(), results);
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::testPauseAndCancel()
 
- {
 
-   ctkCmdLineModuleSignalTester signalTester;
 
-   frontend->setValue("runtimeVar", 60);
 
-   ctkCmdLineModuleFuture future = manager.run(frontend);
 
-   signalTester.setFuture(future);
 
-   QList<QString> expectedSignals;
 
-   expectedSignals << "module.started"
 
-                   << "module.progressRangeChanged(0,0)"
 
-                   << "module.progressValueChanged(0)"
 
-                   << "module.progressRangeChanged(0,1002)"
 
-                   << "module.errorReady";
 
-   if (future.canPause())
 
-   {
 
-     // Due to Qt bug 12152, these two signals are reversed
 
-     expectedSignals.push_back("module.resumed");
 
-     expectedSignals.push_back("module.paused");
 
-   }
 
-   // the following two signals are send when the module reports "filter start"
 
-   expectedSignals << "module.progressValueChanged(1)"
 
-                   << "module.progressTextChanged(Does nothing useful)";
 
-   if (future.canCancel())
 
-   {
 
-     expectedSignals.push_back("module.canceled");
 
-   }
 
-   expectedSignals.push_back("module.finished");
 
-   QTest::qWait(100);
 
-   if (future.canPause())
 
-   {
 
-     future.pause();
 
-     QTest::qWait(100);
 
-     QVERIFY(future.isPaused());
 
-   }
 
-   QVERIFY(future.isRunning());
 
-   if (future.canPause())
 
-   {
 
-     future.togglePaused();
 
-     QTest::qWait(100);
 
-   }
 
-   QVERIFY(!future.isPaused());
 
-   QVERIFY(future.isRunning());
 
-   if (future.canCancel())
 
-   {
 
-     // give event processing a chance before killing the process
 
-     QTest::qWait(500);
 
-     future.cancel();
 
-   }
 
-   future.waitForFinished();
 
-   // process pending events
 
-   QCoreApplication::processEvents();
 
-   QVERIFY(future.isCanceled());
 
-   QVERIFY(future.isFinished());
 
-   QVERIFY(signalTester.checkSignals(expectedSignals));
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::testOutput()
 
- {
 
-   ctkCmdLineModuleSignalTester signalTester;
 
-   connect(signalTester.watcher(), SIGNAL(outputDataReady()), SLOT(ouputDataReady()));
 
-   connect(signalTester.watcher(), SIGNAL(errorDataReady()), SLOT(errorDataReady()));
 
-   this->currentWatcher = signalTester.watcher();
 
-   frontend->setValue("numOutputsVar", 2);
 
-   frontend->setValue("errorTextVar", "Final error msg.");
 
-   ctkCmdLineModuleFuture future = manager.run(frontend);
 
-   signalTester.setFuture(future);
 
-   future.waitForFinished();
 
-   // process pending events
 
-   QCoreApplication::processEvents();
 
-   QVERIFY(future.isFinished());
 
-   QList<QString> expectedSignals;
 
-   expectedSignals << "module.started"
 
-                      // the following signals are send when connecting a QFutureWatcher to
 
-                      // an already started QFuture
 
-                   << "module.progressRangeChanged(0,0)"
 
-                   << "module.progressValueChanged(0)"
 
-                   << "module.progressRangeChanged(0,1002)"
 
-                      // the test module always reports error data when starting
 
-                   << "module.errorReady"
 
-                      // the following two signals are send when the module reports "filter start"
 
-                   << "module.progressValueChanged(1)"
 
-                   << "module.progressTextChanged(Does nothing useful)"
 
-                      // the output data on the standard output channel "Output 1"
 
-                   << "module.outputReady"
 
-                      // this signal is send when the module reports progress for "output1"
 
-                   << "module.progressValueChanged(500)"
 
-                   << "module.progressTextChanged(Calculating output 2...)"
 
-                      // first resultNumberOutput result
 
-                   << "module.resultReadyAt(0,1)"
 
-                   << "module.resultReadyAt(0)"
 
-                      // the output data on the standard output channel "Output 2"
 
-                   << "module.outputReady"
 
-                      // this signal is send when the module reports progress for "output2"
 
-                   << "module.progressValueChanged(1000)"
 
-                   << "module.progressTextChanged(Calculating output 3...)"
 
-                      // second resultNumberOutput result
 
-                   << "module.resultReadyAt(1,2)"
 
-                   << "module.resultReadyAt(1)"
 
-                      // imageOutput result
 
-                   << "module.resultReadyAt(2,3)"
 
-                   << "module.resultReadyAt(2)"
 
-                      // exitStatusOutput result
 
-                   << "module.resultReadyAt(3,4)"
 
-                   << "module.resultReadyAt(3)"
 
-                      // <filter-end> progress value and text
 
-                   << "module.progressValueChanged(1001)"
 
-                   << "module.progressTextChanged(Finished successfully.)"
 
-                      // final error message
 
-                   << "module.errorReady"
 
-                      // the following signal is sent at the end to report completion
 
-                   << "module.progressValueChanged(1002)"
 
-                   << "module.finished";
 
-   QVERIFY(signalTester.checkSignals(expectedSignals));
 
-   const char* expectedOutput = "Output 1\nOutput 2\n";
 
-   const char* expectedError = "A superficial error message.\nFinal error msg.";
 
-   QCOMPARE(this->outputData.data(), expectedOutput);
 
-   QCOMPARE(this->errorData.data(), expectedError);
 
-   QCOMPARE(future.readAllOutputData().data(), expectedOutput);
 
-   QCOMPARE(future.readAllErrorData().data(), expectedError);
 
-   QList<ctkCmdLineModuleResult> results;
 
-   results << ctkCmdLineModuleResult("resultNumberOutput", 1);
 
-   results << ctkCmdLineModuleResult("resultNumberOutput", 2);
 
-   results << ctkCmdLineModuleResult("errorMsgOutput", "Final error msg.");
 
-   results << ctkCmdLineModuleResult("exitStatusOutput", "Normal exit");
 
-   QCOMPARE(signalTester.results(), results);
 
- }
 
- //-----------------------------------------------------------------------------
 
- void ctkCmdLineModuleFutureTester::testError()
 
- {
 
-   frontend->setValue("fileVar", "output1");
 
-   frontend->setValue("exitCodeVar", 24);
 
-   frontend->setValue("errorTextVar", "Some error occured\n");
 
-   ctkCmdLineModuleFuture future = manager.run(frontend);
 
-   try
 
-   {
 
-     future.waitForFinished();
 
-     QFAIL("Expected exception not thrown.");
 
-   }
 
-   catch (const ctkCmdLineModuleRunException& e)
 
-   {
 
-     QVERIFY2(e.errorCode() == 24, "Test matching error code");
 
-     QCOMPARE(future.readAllErrorData().data(), "A superficial error message.\nSome error occured\n");
 
-   }
 
- }
 
- // ----------------------------------------------------------------------------
 
- CTK_TEST_MAIN(ctkCmdLineModuleFutureTest)
 
- #include "moc_ctkCmdLineModuleFutureTest.cpp"
 
 
  |