BASIS  version 1.2.3 (revision 2104)
testdriver.hxx
Go to the documentation of this file.
00001 /**
00002  * @file  testdriver.hxx
00003  * @brief Default test driver implementation.
00004  *
00005  * Copyright (c) 2011 University of Pennsylvania. All rights reserved.<br />
00006  * See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00007  *
00008  * Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00009  */
00010 
00011 #pragma once
00012 #ifndef _SBIA_BASIS_TESTDRIVER_HXX
00013 #define _SBIA_BASIS_TESTDRIVER_HXX
00014 
00015 
00016 #if WINDOWS
00017 #  include <Winsock2.h> // gethostbyname()
00018 #  ifdef max
00019 #    undef max
00020 #  endif
00021 #  pragma comment(lib, "Ws2_32.lib")
00022 #else
00023 #  include <netdb.h> // gethostbyname()
00024 #endif
00025 
00026 #ifdef ITK_VERSION
00027 #  include "testdriver-itk.hxx"
00028 #endif
00029 
00030 
00031 // acceptable in .cxx file of test driver
00032 using namespace sbia::basis;
00033 
00034 
00035 // ===========================================================================
00036 // initialization
00037 // ===========================================================================
00038 
00039 // ---------------------------------------------------------------------------
00040 void testdriversetup(int* argc, char** argv[])
00041 {
00042     try {
00043         string name;
00044         #ifdef TESTDRIVER_NAME
00045             name = TESTDRIVER_NAME;
00046         #else
00047             name = "testdriver";
00048         #endif
00049         #ifdef ITK_VERSION
00050             name += " build with ITK ";
00051             name += ITK_VERSION;
00052         #endif
00053 
00054         // -------------------------------------------------------------------
00055         // construct command-line
00056         CmdLine cmd(
00057                 // program identification
00058                 name, cProjectName,
00059                 // description
00060                 "This program alters the environment, runs a test and "
00061                 "compares the output image to one or more baseline images.",
00062                 // example usage
00063                 "EXECNAME GaussFilter --compare output.nii baseline.nii"
00064                 "\n"
00065                 "Runs the test GaussFilter which presumably writes the"
00066                 " gaussian smoothed image to the image file output.nii."
00067                 " Compares the image produced by the test to the reference"
00068                 " image named baseline.nii with default intensity tolerance.",
00069                 // version information
00070                 cVersionAndRevision,
00071                 "Copyright (c) 2011 University of Pennsylvania."
00072                 " All rights reserved.");
00073 
00074         cmd.add(add_before_libpath);
00075         cmd.add(add_before_env);
00076         cmd.add(clean_cwd_before_test);
00077         cmd.add(clean_cwd_after_test);
00078         cmd.add(compare);
00079         cmd.add(max_number_of_differences);
00080         cmd.add(intensity_tolerance);
00081         cmd.add(tolerance_radius);
00082         cmd.add(redirect_output);
00083         cmd.add(max_number_of_threads);
00084         cmd.add(full_output);
00085         cmd.add(verbose);
00086 
00087         #ifdef BASIS_STANDALONE_TESTDRIVER
00088         cmd.xorAdd(noprocess, testcmd);
00089         #else
00090         cmd.add(testcmd);
00091         #endif
00092 
00093         // -------------------------------------------------------------------
00094         // parse command-line
00095         cmd.parse(*argc, *argv);
00096 
00097         // -------------------------------------------------------------------
00098         // rearrange argc and argv of main()
00099         if (testcmd.isSet()) {
00100             for (unsigned int i = 0; i < testcmd.getValue().size(); i++) {
00101                 for (int j = 1; j < (*argc); j++) {
00102                     if (testcmd.getValue()[i] == (*argv)[j]) {
00103                         (*argv)[i + 1] = (*argv)[j];
00104                         break;
00105                     }
00106                 }
00107             }
00108             *argc = static_cast<int>(testcmd.getValue().size()) + 1;
00109             (*argv)[*argc] = NULL;
00110         } else {
00111             *argc = 1;
00112             (*argv)[1] = NULL;
00113         }
00114 
00115         // Reset ignoring flag of TCLAP library. Otherwise, when a test
00116         // uses the TCLAP library to parse its arguments, the labeled
00117         // arguments will be immediately ignored.
00118         // This required the addition of the stopIgnoring() method to TCLAP::Arg.
00119         TCLAP::Arg::stopIgnoring();
00120 
00121     // -----------------------------------------------------------------------
00122     // catch specification exceptions - parse errors are already taken care of
00123     } catch (CmdLineException& e) {
00124         cerr << e.error() << endl;
00125         exit(1);
00126     }
00127 
00128     // -----------------------------------------------------------------------
00129     // add host name as Dart/CDash measurement
00130     char hostname[256] = "unknown";
00131     #if WINDOWS
00132         WSADATA wsaData;
00133         WSAStartup(MAKEWORD(2, 2), &wsaData);
00134         gethostname(hostname, sizeof(hostname));
00135         WSACleanup();
00136     #else
00137         gethostname(hostname, sizeof(hostname));
00138     #endif
00139     hostname[255] = '\0';
00140 
00141     cout << "<DartMeasurement name=\"Host Name\" type=\"string\">";
00142     cout << hostname;
00143     cout <<  "</DartMeasurement>" << endl;
00144 
00145     cout << "<DartMeasurement name=\"Working Directory\" type=\"string\">";
00146     cout << get_working_directory();
00147     cout <<  "</DartMeasurement>" << endl;
00148 
00149     #ifdef ITK_VERSION
00150     cout << "<DartMeasurement name=\"ITK Version\" type=\"string\">";
00151     cout << ITK_VERSION;
00152     cout <<  "</DartMeasurement>" << endl;
00153     #endif
00154 
00155     // -----------------------------------------------------------------------
00156     // register ITK IO factories
00157     #ifdef ITK_VERSION
00158         RegisterRequiredFactories();
00159     #endif
00160 }
00161 
00162 // ===========================================================================
00163 // image regression testing
00164 // ===========================================================================
00165 
00166 // ---------------------------------------------------------------------------
00167 void CompareVisitor::visit()
00168 {
00169     assert(compare.getValue().size() != 0);
00170     assert((compare.getValue().size() % 2) == 0);
00171 
00172     RegressionTest regression_test;
00173 
00174     regression_test.test_image_file           = compare.getValue()[compare.getValue().size() - 2];
00175     regression_test.baseline_image_file       = compare.getValue()[compare.getValue().size() - 1];
00176     regression_test.intensity_tolerance       = intensity_tolerance.getValue();
00177     regression_test.max_number_of_differences = max_number_of_differences.getValue();
00178     regression_test.tolerance_radius          = tolerance_radius.getValue();
00179 
00180     regression_tests.push_back(regression_test);
00181 }
00182 
00183 // ---------------------------------------------------------------------------
00184 vector<string> get_baseline_filenames(string filename_template)
00185 {
00186     vector<string> baselines;
00187 
00188     ifstream ifs(filename_template.c_str());
00189     if (ifs) baselines.push_back(filename_template);
00190 
00191     int               x   = 0;
00192     string::size_type pos = filename_template.rfind(".");
00193     string            suffix;
00194 
00195     if (pos != string::npos) {
00196         suffix = filename_template.substr(pos);
00197         filename_template.erase(pos);
00198     }
00199     while (++x) {
00200         ostringstream filename;
00201         filename << filename_template << '.' << x << suffix;
00202         ifstream ifs(filename.str().c_str());
00203         if (!ifs) break;
00204         ifs.close();
00205         baselines.push_back(filename.str());
00206     }
00207     return baselines;
00208 }
00209 
00210 // ---------------------------------------------------------------------------
00211 int image_regression_test(const char*  imagefile,
00212                           const char*  baseline,
00213                           double       intensity_tolerance,
00214                           unsigned int max_number_of_differences,
00215                           unsigned int tolerance_radius,
00216                           int          report)
00217 {
00218     #ifdef ITK_VERSION
00219         return RegressionTestImage(imagefile,
00220                                    baseline,
00221                                    report,
00222                                    intensity_tolerance,
00223                                    max_number_of_differences,
00224                                    tolerance_radius);
00225     #else
00226         BASIS_THROW(runtime_error,
00227                     "Not implemented yet! Use ITK implementation instead, i.e.,"
00228                     << " install ITK 3.14 or greater (including versions after 4.0)"
00229                     << " and reconfigure the build tree of " << cProjectName << ". Ensure that"
00230                     << " the ITK_DIR variable is set to the directory of the ITKConfig.cmake file"
00231                     << " and that the variable USE_ITK is set to ON. Then rebuild " << cProjectName
00232                     << " and optionally install it again.");
00233     #endif
00234 }
00235 
00236 
00237 #endif // _SBIA_BASIS_TESTDRIVER_HXX