ctkCmdLineModuleTestBed.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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 <ctkCommandLineParser.h>
  16. #include <QCoreApplication>
  17. #include <QTextStream>
  18. #include <QFile>
  19. #include <QDebug>
  20. #include <QTime>
  21. #include <cstdlib>
  22. #ifdef Q_OS_WIN
  23. #include <windows.h>
  24. #else
  25. #include <time.h>
  26. #endif
  27. void sleep_ms(int ms)
  28. {
  29. #ifdef Q_OS_WIN
  30. Sleep(ms);
  31. #else
  32. struct timespec nanostep;
  33. nanostep.tv_sec = static_cast<time_t>(ms / 1000);
  34. nanostep.tv_nsec = ((ms % 1000) * 1000.0 * 1000.0);
  35. nanosleep(&nanostep, NULL);
  36. #endif
  37. }
  38. int main(int argc, char* argv[])
  39. {
  40. QCoreApplication app(argc, argv);
  41. // This is used by QSettings
  42. QCoreApplication::setOrganizationName("CommonTK");
  43. QCoreApplication::setApplicationName("CmdLineModuleTestBed");
  44. ctkCommandLineParser parser;
  45. // Use Unix-style argument names
  46. parser.setArgumentPrefix("--", "-");
  47. // Add command line argument names
  48. parser.addArgument("help", "h", QVariant::Bool, "Show this help text");
  49. parser.addArgument("xml", "", QVariant::Bool, "Print a XML description of this modules command line interface");
  50. parser.addArgument("runtime", "", QVariant::Int, "Runtime in seconds", 1);
  51. parser.addArgument("numOutputs", "", QVariant::Int, "Number of outpusts", 0);
  52. parser.addArgument("exitCode", "", QVariant::Int, "Exit code", 0);
  53. parser.addArgument("exitCrash", "", QVariant::Bool, "Force crash", false);
  54. parser.addArgument("exitTime", "", QVariant::Int, "Exit time", 0);
  55. parser.addArgument("errorText", "", QVariant::String, "Error text printed at the end");
  56. QTextStream out(stdout, QIODevice::WriteOnly | QIODevice::Text);
  57. QTextStream err(stderr, QIODevice::WriteOnly | QIODevice::Text);
  58. // Parse the command line arguments
  59. bool ok = false;
  60. QHash<QString, QVariant> parsedArgs = parser.parseArguments(QCoreApplication::arguments(), &ok);
  61. if (!ok)
  62. {
  63. err << "Error parsing arguments:" << parser.errorString() << endl;
  64. return EXIT_FAILURE;
  65. }
  66. // Show a help message
  67. if (parsedArgs.contains("help") || parsedArgs.contains("h"))
  68. {
  69. out << parser.helpText();
  70. out.setFieldWidth(parser.fieldWidth());
  71. out.setFieldAlignment(QTextStream::AlignLeft);
  72. out << " <output-path>" << "Path to the output image" << endl;
  73. return EXIT_SUCCESS;
  74. }
  75. if (parsedArgs.contains("xml"))
  76. {
  77. QFile xmlDescription(":/ctkCmdLineModuleTestBed.xml");
  78. xmlDescription.open(QIODevice::ReadOnly);
  79. out << xmlDescription.readAll();
  80. return EXIT_SUCCESS;
  81. }
  82. if (parser.unparsedArguments().isEmpty())
  83. {
  84. err << "Error parsing arguments: <output-path> argument missing" << endl;
  85. return EXIT_FAILURE;
  86. }
  87. // Do something
  88. float runtime = parsedArgs["runtime"].toFloat();
  89. int numOutputs = parsedArgs["numOutputs"].toInt();
  90. float exitTime = parsedArgs["exitTime"].toFloat();
  91. int exitTimeMillis = static_cast<long>(exitTime/2.0 * 1000.0);
  92. int exitCode = parsedArgs["exitCode"].toInt();
  93. bool exitCrash = parsedArgs["exitCrash"].toBool();
  94. QString errorText = parsedArgs["errorText"].toString();
  95. QString imageOutput = parser.unparsedArguments().at(0);
  96. err << "A superficial error message." << endl;
  97. // sleep 500ms to give the "errorReady" signal a chance
  98. sleep_ms(500);
  99. QStringList outputs;
  100. for (int i = 0; i < numOutputs; ++i)
  101. {
  102. outputs << "Output " + QString::number(i+1);
  103. }
  104. float stepTime = outputs.size() ? runtime / static_cast<float>(outputs.size()) : runtime;
  105. QTime time;
  106. time.start();
  107. out << "<filter-start>\n";
  108. out << "<filter-name>Test Filter</filter-name>\n";
  109. out << "<filter-comment>Does nothing useful</filter-comment>\n";
  110. out << "</filter-start>" << endl;
  111. if (outputs.empty())
  112. {
  113. outputs.push_back("dummy");
  114. }
  115. float progressStep = 1.0f / static_cast<float>(outputs.size());
  116. for(int i = 0; i < outputs.size(); ++i)
  117. {
  118. QString output = outputs[i];
  119. if (exitTimeMillis != 0 && exitTimeMillis < time.elapsed())
  120. {
  121. if (exitCrash)
  122. {
  123. int* crash = 0;
  124. *crash = 5;
  125. }
  126. if (exitCode != 0 && !errorText.isEmpty())
  127. {
  128. err << errorText;
  129. }
  130. return exitCode;
  131. }
  132. // simulate some work
  133. sleep_ms(stepTime*1000);
  134. // print the first output
  135. if (output != "dummy")
  136. {
  137. out << output << endl;
  138. // report progress
  139. out << QString("<filter-progress-text progress=\"%1\">").arg((i+1)*progressStep)
  140. << "Calculating output " << (i+2) << "...</filter-progress-text>" << endl;
  141. // report the current output number as a result
  142. out << "<filter-result name=\"resultNumberOutput\">" << (i+1) << "</filter-result>" << endl;
  143. }
  144. }
  145. // sleep 500ms to avoid squashing the last progress event with the finished event
  146. sleep_ms(500);
  147. if (!errorText.isEmpty())
  148. {
  149. err << errorText;
  150. out << "<filter-result name=\"errorMsgOutput\">" << errorText << "</filter-result>" << endl;
  151. }
  152. else
  153. {
  154. out << "<filter-result name=\"imageOutput\">" << imageOutput << "</filter-result>" << endl;
  155. }
  156. out << "<filter-result name=\"exitStatusOutput\">";
  157. if (exitCrash)
  158. {
  159. out << "Crashed</filter-result>" << endl;
  160. int* crash = 0;
  161. *crash = 5;
  162. }
  163. else
  164. {
  165. out << "Normal exit</filter-result>" << endl;
  166. sleep_ms(100);
  167. out << "<filter-progress>1</filter-progress>" << endl;
  168. sleep_ms(100);
  169. out << "<filter-end><filter-comment>Finished successfully.</filter-comment></filter-end>" << endl;
  170. sleep_ms(100);
  171. }
  172. return exitCode;
  173. }