BASIS  version 1.2.3 (revision 2104)
testdriver.h
Go to the documentation of this file.
00001 /**
00002  * @file  testdriver.h
00003  * @brief Default test driver include file.
00004  *
00005  * This file is specified as INCLUDE argument to the create_test_sourcelist()
00006  * command of CMake which generates the code of the test driver. Such test
00007  * driver is used, in particular, to run a test which generates an output image.
00008  * The resulting image can then be compared by the test driver to one or more
00009  * baseline images. Note the difference to plain non-image processing based
00010  * unit tests. These shall make use of the unit testing frameworks included
00011  * with BASIS instead (see test.h for a C++ unit testing framework).
00012  *
00013  * This file in particular declares the functions which are used to parse
00014  * the command-line arguments of the test driver and those which are used by
00015  * the code fragments defined in the files testdriver-before-test.inc and
00016  * testdriver-after-test.inc.
00017  *
00018  * Currently available test driver implementations included by this file are:
00019  * - testdriver.hxx
00020  * - testdriver-itk.hxx
00021  *
00022  * This file is in parts a modified version of the itkTestDriverInclude.h
00023  * file which is part of the TestKernel module of the ITK 4 project.
00024  *
00025  * Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen<br />
00026  * Copyright Insight Software Consortium.<br />
00027  * Copyright (c) 2011 University of Pennsylvania.
00028  *
00029  * Portions of this file are subject to the VTK Toolkit Version 3 copyright.
00030  *
00031  * For complete copyright, license and disclaimer of warranty information
00032  * please refer to the COPYRIGHT file.
00033  *
00034  * Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00035  */
00036 
00037  /*=========================================================================
00038  *
00039  *  Copyright Insight Software Consortium
00040  *
00041  *  Licensed under the Apache License, Version 2.0 (the "License");
00042  *  you may not use this file except in compliance with the License.
00043  *  You may obtain a copy of the License at
00044  *
00045  *         http://www.apache.org/licenses/LICENSE-2.0.txt
00046  *
00047  *  Unless required by applicable law or agreed to in writing, software
00048  *  distributed under the License is distributed on an "AS IS" BASIS,
00049  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00050  *  See the License for the specific language governing permissions and
00051  *  limitations under the License.
00052  *
00053  *=========================================================================*/
00054 /*=========================================================================
00055  *
00056  *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
00057  *
00058  *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
00059  *
00060  *  For complete copyright, license and disclaimer of warranty information
00061  *  please refer to the NOTICE file at the top of the ITK source tree.
00062  *
00063  *=========================================================================*/
00064 
00065 #pragma once
00066 #ifndef _SBIA_BASIS_TESTDRIVER_H
00067 #define _SBIA_BASIS_TESTDRIVER_H
00068 
00069 
00070 #include <string>
00071 #include <map>
00072 #include <vector>
00073 #include <iostream>
00074 #include <fstream>
00075 #include <cstdio> // remove() - removes a file
00076 #include <limits> // used in basistest-after-test.inc
00077 
00078 #include <sbia/basis/config.h>
00079 #include <sbia/basis/except.h>
00080 #include <sbia/basis/assert.h>
00081 #include <sbia/basis/path.h>    // get_file_name() - basistest-after-test.inc
00082 #include <sbia/basis/CmdLine.h> // parsing of command-line arguments
00083 
00084 
00085 // acceptable in test driver includes
00086 using namespace std;
00087 using namespace sbia::basis;
00088 
00089  
00090 // ===========================================================================
00091 // arguments
00092 // ===========================================================================
00093 
00094 /// @brief Maximum dimension of images used for testing.
00095 const unsigned int BASIS_MAX_TEST_IMAGE_DIMENSION = 6;
00096 
00097 // ---------------------------------------------------------------------------
00098 // environment
00099 MultiStringArg add_before_libpath(
00100         "", "add-before-libpath",
00101         "Add a path to the library path environment. This option takes"
00102         " care of choosing the right environment variable for your system.",
00103         false, "<dir>");
00104 
00105 MultiStringArg add_before_env(
00106         "", "add-before-env",
00107         "Add an environment variable named <name> with the given value."
00108         " The seperator used is the default one on the system.",
00109         false, "<name> <value>", 2);
00110 
00111 MultiStringArg add_before_env_with_sep(
00112         "", "add-before-env-with-sep",
00113         "Add an environment variable named <name> with the given value.",
00114         false, "<name> <value> <sep>", 3);
00115 
00116 // ---------------------------------------------------------------------------
00117 // regression testing
00118 
00119 /// @brief Structure holding arguments to --compare option and currently
00120 ///        set tolerances to be used for the regression test.
00121 struct RegressionTest {
00122     string       test_image_file;
00123     string       baseline_image_file;
00124     double       intensity_tolerance;
00125     unsigned int max_number_of_differences;
00126     unsigned int tolerance_radius;
00127 };
00128 
00129 /// @brief Container storing added regression tests, one for each occurrence
00130 ///        of the --compare option.
00131 vector<RegressionTest> regression_tests;
00132 
00133 /// @brief Visitor used to handle --compare option.
00134 class CompareVisitor : public TCLAP::Visitor
00135 {
00136 public:
00137     CompareVisitor() {}
00138     ~CompareVisitor() {}
00139     void visit();
00140 };
00141 
00142 CompareVisitor compare_visitor;
00143 
00144 MultiStringArg compare(
00145         "", "compare",
00146         "Compare the <test> image to the <baseline> image using the"
00147         " current tolerances. If the test image should be compared to"
00148         " to more than one baseline image, specify the file name of"
00149         " the main baseline image and name the other baseline images"
00150         " similarly with only a numerical suffix appended to the"
00151         " basename of the image file path using a dot (.) as separator."
00152         " For example, name your baseline images baseline.nii,"
00153         " baseline.1.nii, baseline.2.nii,..., and specify baseline.nii"
00154         " second argument value.",
00155         false, "<test> <baseline>", 2, false, &compare_visitor);
00156 
00157 DoubleArg intensity_tolerance(
00158         "", "intensity-tolerance",
00159         "The accepted maximum difference between image intensities"
00160         " to use for the following regression tests."
00161         // default should be printed automatically
00162         " (default: 2.0)",
00163         false, 2.0, "<float>", true);
00164 
00165 UIntArg max_number_of_differences(
00166         "", "max-number-of-differences",
00167         "When comparing images specified with the following --compare option(s),"
00168         " allow the given number of image elements to differ.",
00169         false, 0, "<n>", true);
00170 
00171 UIntArg tolerance_radius(
00172         "", "tolerance-radius",
00173         "At most one image element in the neighborhood specified by the"
00174         " given radius has to fulfill the criteria of the following"
00175         " regression tests",
00176         false, 0, "<int>", true);
00177 
00178 // ---------------------------------------------------------------------------
00179 // test execution
00180 StringArg redirect_output(
00181         "", "redirect-output",
00182         "Redirects the test output to the specified file.",
00183         false, "", "<file>");
00184 
00185 UIntArg max_number_of_threads(
00186         "", "max-number-of-threads",
00187         "Use at most <n> threads. Set explicitly to n=1 to disable"
00188         " multi-threading. Note that the test itself still may use"
00189         " more threads, but the regression tests will not.",
00190         false, 0, "<n>");
00191 
00192 SwitchArg full_output(
00193         "", "full-output",
00194         "Causes the full output of the test to be passed to CDash.",
00195         false);
00196 
00197 MultiSwitchArg verbose(
00198         "v", "verbose",
00199         "Increase verbosity of output messages.",
00200         false);
00201 
00202 // ---------------------------------------------------------------------------
00203 // test / test command
00204 SwitchArg clean_cwd_before_test(
00205         "", "clean-cwd-before",
00206         "Request the removal of all files and directories from the current"
00207         " working directory before the execution of the test. This option is"
00208         " in particular useful if the test writes any results to the current"
00209         " working directory.",
00210         false);
00211 
00212 SwitchArg clean_cwd_after_test(
00213         "", "clean-cwd-after",
00214         "Request the removal of all files and directories from the current"
00215         " working directory after the successful execution of the test."
00216         " This option is in particular useful if the test writes any results"
00217         " to the current working directory.",
00218         false);
00219 
00220 #ifdef BASIS_STANDALONE_TESTDRIVER
00221 
00222 PositionalArgs testcmd(
00223         "testcmd",
00224         "The external test command and its command-line arguments."
00225         " This command is executed by the test driver after altering the"
00226         " environment as subprocess. After the subprocess finished, the"
00227         " requested regression tests are performed by the test driver."
00228         " Note that if the -- option is not given before the test command,"
00229         " labeled arguments following the test command will be considered"
00230         " to be options of the test driver if known by the test driver.",
00231         true, "[--] <test command> <arg>...");
00232 
00233 SwitchArg noprocess(
00234         "", "noprocess",
00235         "Do not run any test subprocess but only perform the regression tests.",
00236         true);
00237 
00238 #else // defined(BASIS_STANDALONE_TESTDRIVER)
00239 
00240 PositionalArgs testcmd(
00241         "testcmd",
00242         "The name of the test to run and optional arguments."
00243         " Displays a list of available tests if this argument is omitted"
00244         " and waits for the user to input the number of the test to run."
00245         " Exist with error if an invalid test was specified."
00246         " Note that if the -- option is not given before the test name,"
00247         " labeled arguments following the test name will be considered"
00248         " to be options of the test driver if known by the test driver."
00249         " Otherwise, if the option is unknown to the test driver or the"
00250         " -- option has been given before the test name, the remaining"
00251         " arguments are passed on to the test.",
00252         false, "", "[--] [<test name> [<arg>...]]");
00253 
00254 #endif // defined(BASIS_STANDALONE_TESTDRIVER)
00255 
00256 // ===========================================================================
00257 // initialization
00258 // ===========================================================================
00259 
00260 /**
00261  * @brief Parse command-line arguments and initialize test driver.
00262  *
00263  *
00264  * @param [in] argc Number of arguments.
00265  * @param [in] argv Command-line arguments.
00266  */
00267 void testdriversetup(int* argc, char** argv[]);
00268 
00269 // ===========================================================================
00270 // image regression testing
00271 // ===========================================================================
00272 
00273 /**
00274  * @brief Generate list of names of baseline files from a given template filename.
00275  *
00276  * The list of baseline file names is generated from the template filename using
00277  * the following algorithm:
00278  * -# Strip the file name suffix.
00279  * -# Append a suffix containing of a dot (.) and a digit, i.e., .x
00280  * -# Append the original file name suffix.
00281  * It the file exists, increment x and continue.
00282  *
00283  * Additionally, if a file @p filename_template exists, it is the first
00284  * element in the resulting list.
00285  *
00286  * @param [in] filename_template File path template.
00287  *
00288  * @return List of baseline filenames or empty list if no such files exist.
00289  */
00290 vector<string> get_baseline_filenames(string filename_template);
00291 
00292 /**
00293  * @brief Compare output image to baseline image.
00294  *
00295  * This function compares a given image to a baseline image and returns a
00296  * regression test result depending on how well the output image matches the
00297  * baseline image given the provided tolerance arguments.
00298  *
00299  * @param [in] imagefile                 Output image file of test run.
00300  * @param [in] baseline                  Baseline image file.
00301  * @param [in] intensity_tolerance       Maximum tolerable intensity difference.
00302  * @param [in] max_number_of_differences Maximum number of differing pixels.
00303  * @param [in] tolerance_radius          Tolerance radius.
00304  * @param [in] report                    Level of test report to generate.
00305  *                                       If zero, no report is generated.
00306  *                                       If greater than zero, a report is
00307  *                                       generated. Similar to the verbosity of
00308  *                                       a program, is this parameter used to
00309  *                                       set the verbosity of the report. Most
00310  *                                       implementations yet only either
00311  *                                       generate a (full) report or none.
00312  */
00313 int image_regression_test(const char*  imagefile,
00314                           const char*  baseline,
00315                           double       intensity_tolerance = 2.0,
00316                           unsigned int max_number_of_differences = 0,
00317                           unsigned int tolerance_radius = 0,
00318                           int          report = 0);
00319 
00320 
00321 // inline definitions
00322 #include "testdriver.hxx"
00323 
00324 
00325 #endif // _SBIA_BASIS_TESTDRIVER_H