test.cpp

Go to the documentation of this file.
00001 
00042 #include "linden_common.h"
00043 #include "llerrorcontrol.h"
00044 #include "lltut.h"
00045 
00046 #include <apr-1/apr_pools.h>
00047 #include <apr-1/apr_getopt.h>
00048 
00049 // the CTYPE_WORKAROUND is needed for linux dev stations that don't
00050 // have the broken libc6 packages needed by our out-of-date static 
00051 // libs (such as libcrypto and libcurl). -- Leviathan 20060113
00052 #ifdef CTYPE_WORKAROUND
00053 #       include "ctype_workaround.h"
00054 #endif
00055 
00056 
00057 namespace tut
00058 {
00059     test_runner_singleton runner;
00060 }
00061 
00062 class LLTestCallback : public tut::callback
00063 {
00064 public:
00065         LLTestCallback(bool verbose_mode) :
00066                 mVerboseMode(verbose_mode),
00067                 mTotalTests(0),
00068                 mPassedTests(0),
00069                 mFailedTests(0),
00070                 mSkippedTests(0),
00071                 mSkipedFailTests(0)
00072         {
00073         }
00074 
00075         void run_started()
00076         {
00077                 //std::cout << "run_started" << std::endl;
00078         }
00079 
00080         void test_completed(const tut::test_result& tr)
00081         {
00082                 ++mTotalTests;
00083                 std::ostringstream out;
00084                 out << "[" << tr.group << ", " << tr.test << "] ";
00085                 switch(tr.result)
00086                 {
00087                 case tut::test_result::ok:
00088                         ++mPassedTests;
00089                         out << "ok";
00090                         break;
00091                 case tut::test_result::fail:
00092                         ++mFailedTests;
00093                         out << "fail";
00094                         break;
00095                 case tut::test_result::ex:
00096                         ++mFailedTests;
00097                         out << "exception";
00098                         break;
00099                 case tut::test_result::warn:
00100                         ++mFailedTests;
00101                         out << "test destructor throw";
00102                         break;
00103                 case tut::test_result::term:
00104                         ++mFailedTests;
00105                         out << "abnormal termination";
00106                         break;
00107                 case tut::test_result::skip:
00108                         ++mSkippedTests;
00109                         out << "skipped";
00110                         break;
00111                 case tut::test_result::skip_fail:
00112                         ++mSkipedFailTests;
00113                         out << "skipped known failure";
00114                         break;
00115                 default:
00116                         ++mFailedTests;
00117                         out << "unknown";
00118                 }
00119                 if(mVerboseMode || (tr.result != tut::test_result::ok))
00120                 {
00121                         if(!tr.message.empty())
00122                         {
00123                                 out << ": '" << tr.message << "'";
00124                         }
00125                         std::cout << out.str() << std::endl;
00126                 }
00127         }
00128 
00129         void run_completed()
00130         {
00131                 std::cout << std::endl;
00132                 std::cout << "Total Tests:   " << mTotalTests << std::endl;
00133                 std::cout << "Passed Tests: " << mPassedTests << std::endl;
00134                 
00135                 if (mSkippedTests > 0)
00136                 {
00137                         std::cout << "Skipped Tests: " << mSkippedTests << std::endl;
00138                 }
00139 
00140                 if (mSkipedFailTests > 0)
00141                 {
00142                         std::cout << "Skipped known failures: " << mSkipedFailTests
00143                                 << std::endl;
00144                 }
00145 
00146                 if(mFailedTests > 0)
00147                 {
00148                         std::cout << "*********************************" << std::endl;
00149                         std::cout << "Failed Tests:   " << mFailedTests << std::endl;
00150                         std::cout << "Please report or fix the problem." << std::endl;
00151                         std::cout << "*********************************" << std::endl;
00152                         exit(1);
00153                 }
00154         }
00155 
00156 protected:
00157         bool mVerboseMode;
00158         int mTotalTests;
00159         int mPassedTests;
00160         int mFailedTests;
00161         int mSkippedTests;
00162         int mSkipedFailTests;
00163 };
00164 
00165 static const apr_getopt_option_t TEST_CL_OPTIONS[] =
00166 {
00167         {"help", 'h', 0, "Print the help message."},
00168         {"list", 'l', 0, "List available test groups."},
00169         {"verbose", 'v', 0, "Verbose output."},
00170         {"group", 'g', 1, "Run test group specified by option argument."},
00171         {"skip", 's', 1, "Skip test number specified by option argument. Only works when a specific group is being tested"},
00172         {"wait", 'w', 0, "Wait for input before exit."},
00173         {"debug", 'd', 0, "Emit full debug logs."},
00174         {0, 0, 0, 0}
00175 };
00176 
00177 void stream_usage(std::ostream& s, const char* app)
00178 {
00179         s << "Usage: " << app << " [OPTIONS]" << std::endl
00180           << std::endl;
00181 
00182         s << "This application runs the unit tests." << std::endl << std::endl;
00183 
00184         s << "Options: " << std::endl;
00185         const apr_getopt_option_t* option = &TEST_CL_OPTIONS[0];
00186         while(option->name)
00187         {
00188                 s << "  ";
00189                 s << "  -" << (char)option->optch << ", --" << option->name
00190                   << std::endl;
00191                 s << "\t" << option->description << std::endl << std::endl;
00192                 ++option;
00193         }
00194 
00195         s << "Examples:" << std::endl;
00196         s << "  " << app << " --verbose" << std::endl;
00197         s << "\tRun all the tests and report all results." << std::endl;
00198         s << "  " << app << " --list" << std::endl;
00199         s << "\tList all available test groups." << std::endl;
00200         s << "  " << app << " --group=uuid" << std::endl;
00201         s << "\tRun the test group 'uuid'." << std::endl;
00202         s << "  " << app << " --skip=2" << std::endl;
00203         s << "\tSkip test case 2." << std::endl;
00204 }
00205 
00206 void stream_groups(std::ostream& s, const char* app)
00207 {
00208         s << "Registered test groups:" << std::endl;
00209         tut::groupnames gl = tut::runner.get().list_groups();
00210         tut::groupnames::const_iterator it = gl.begin();
00211         tut::groupnames::const_iterator end = gl.end();
00212         for(; it != end; ++it)
00213         {
00214                 s << "  " << *(it) << std::endl;
00215         }
00216 }
00217 
00218 void wouldHaveCrashed(const std::string& message)
00219 {
00220         tut::fail("llerrs message: " + message);
00221 }
00222 
00223 int main(int argc, char **argv)
00224 {
00225         LLError::initForApplication(".");
00226         LLError::setFatalFunction(wouldHaveCrashed);
00227         LLError::setDefaultLevel(LLError::LEVEL_ERROR);
00228                 //< *TODO: should come from error config file. Note that we
00229                 // have a command line option that sets this to debug.
00230         
00231 #ifdef CTYPE_WORKAROUND
00232         ctype_workaround();
00233 #endif
00234 
00235         apr_initialize();
00236         apr_pool_t* pool = NULL;
00237         if(APR_SUCCESS != apr_pool_create(&pool, NULL))
00238         {
00239                 std::cerr << "Unable to initialize pool" << std::endl;
00240                 return 1;
00241         }
00242         apr_getopt_t* os = NULL;
00243         if(APR_SUCCESS != apr_getopt_init(&os, pool, argc, argv))
00244         {
00245                 std::cerr << "Unable to  pool" << std::endl;
00246                 return 1;
00247         }
00248 
00249         // values used for controlling application
00250         bool verbose_mode = false;
00251         bool wait_at_exit = false;
00252         int  skip_test_id = 0;
00253         std::string test_group;
00254 
00255         // values use for options parsing
00256         apr_status_t apr_err;
00257         const char* opt_arg = NULL;
00258         int opt_id = 0;
00259         while(true)
00260         {
00261                 apr_err = apr_getopt_long(os, TEST_CL_OPTIONS, &opt_id, &opt_arg);
00262                 if(APR_STATUS_IS_EOF(apr_err)) break;
00263                 if(apr_err)
00264                 {
00265                         char buf[255];          /* Flawfinder: ignore */
00266                         std::cerr << "Error parsing options: "
00267                                           << apr_strerror(apr_err, buf, 255) << std::endl;
00268                         return 1;
00269                 }
00270                 switch (opt_id)
00271                 {
00272                 case 'g':
00273                         test_group.assign(opt_arg);
00274                         break;
00275                 case 's':
00276                         skip_test_id = atoi(opt_arg);
00277                         break;                  
00278                 case 'h':
00279                         stream_usage(std::cout, argv[0]);
00280                         return 0;
00281                         break;
00282                 case 'l':
00283                         stream_groups(std::cout, argv[0]);
00284                         return 0;
00285                 case 'v':
00286                         verbose_mode = true;
00287                         break;
00288                 case 'w':
00289                         wait_at_exit = true;
00290                         break;
00291                 case 'd':
00292                         // *TODO: should come from error config file. We set it to
00293                         // ERROR by default, so this allows full debug levels.
00294                         LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
00295                         break;
00296                 default:
00297                         stream_usage(std::cerr, argv[0]);
00298                         return 1;
00299                         break;
00300                 }
00301         }
00302 
00303         // run the tests
00304         LLTestCallback callback(verbose_mode);
00305         tut::runner.get().set_callback(&callback);
00306         
00307         if(test_group.empty())
00308         {
00309                 tut::runner.get().run_tests();
00310         }
00311         else
00312         {
00313                 tut::runner.get().run_tests(test_group, skip_test_id);
00314         }
00315 
00316         if (wait_at_exit)
00317         {
00318                 std::cerr << "Waiting for input before exiting..." << std::endl;
00319                 std::cin.get();
00320         }
00321         
00322         apr_terminate();
00323         return 0;
00324 }

Generated on Fri May 16 08:34:32 2008 for SecondLife by  doxygen 1.5.5