irplib_test.c

00001 /*                                                                              *
00002  *   This file is part of the ESO IRPLIB package                                *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019  
00020 #ifdef HAVE_CONFIG_H
00021 #  include <config.h>
00022 #endif
00023 
00024 /*-----------------------------------------------------------------------------
00025                                 Includes
00026  -----------------------------------------------------------------------------*/
00027 
00028 #include <irplib_test.h>
00029 
00030 /* irplib_sprintf() */
00031 #include <irplib_utils.h>
00032 
00033 #include <cpl.h>
00034 
00035 /* fabs() */
00036 #include <math.h>
00037 /* strlen() */
00038 #include <string.h>
00039 
00040 /* clock() */
00041 #include <time.h>
00042 
00043 #ifndef CPL_HAS_UNIT_TEST
00044 
00045 /*----------------------------------------------------------------------------*/
00049 /*----------------------------------------------------------------------------*/
00050 
00051 /*-----------------------------------------------------------------------------
00052                                 Implementation
00053  -----------------------------------------------------------------------------*/
00054 
00058 static unsigned long irplib_test_nfail = 0; 
00059 static clock_t irplib_test_start; 
00060 
00061 /*----------------------------------------------------------------------------*/
00070 /*----------------------------------------------------------------------------*/
00071 static void
00072 test(int expression, const char *message,
00073      const char *function, const char *file, unsigned line)
00074 {
00075     const char *error_state = (cpl_error_get_code() != CPL_ERROR_NONE) ?
00076         irplib_sprintf(" (CPL-error state: '%s' at %s)",
00077                        cpl_error_get_message(), cpl_error_get_where()) :
00078         NULL;
00079     
00080     if (expression) {
00081         cpl_msg_debug(function,
00082                       "OK at %s:%u%s: %s",
00083                       file, line, error_state != NULL ? error_state : "",
00084                       message);
00085     } else {
00086         if (irplib_test_nfail + 1 > irplib_test_nfail) {
00087             irplib_test_nfail++;
00088         }
00089         else {
00090             cpl_msg_error(function, "Number of errors (%lu) overflow!",
00091                           irplib_test_nfail);
00092         }
00093         
00094         cpl_msg_error(function,
00095                       "Failure at %s:%u%s: %s",
00096                       file, line, error_state != NULL ? error_state : "",
00097                       message);
00098     }
00099 
00100     if (error_state != NULL)
00101         {
00102             cpl_free((char *)error_state);
00103         }
00104 
00105     return;
00106 }
00107 
00108 
00109 /*----------------------------------------------------------------------------*/
00119 /*----------------------------------------------------------------------------*/
00120 void 
00121 irplib_test_macro(int expression, const char *expr_string,
00122                   const char *function, const char *file, unsigned line)
00123 {
00124     const char *message = irplib_sprintf("(%s) = %d", expr_string, expression);
00125 
00126     test(expression, message,
00127          function, file, line);
00128 
00129     cpl_free((char *)message);
00130 
00131     return;
00132 }
00133 
00134 /*----------------------------------------------------------------------------*/
00146 /*----------------------------------------------------------------------------*/
00147 void 
00148 irplib_test_eq_macro(int first,  const char *first_string,
00149                      int second, const char *second_string,
00150                      const char *function, const char *file, unsigned line)
00151 {
00152     const char *message =
00153         irplib_sprintf("(%s) = %d; (%s) = %d",
00154                        first_string, first,
00155                        second_string, second);
00156 
00157     test(first == second, message,
00158          function, file, line);
00159 
00160     cpl_free((char *)message);
00161 
00162     return;
00163 }
00164 
00165 /*----------------------------------------------------------------------------*/
00177 /*----------------------------------------------------------------------------*/
00178 void 
00179 irplib_test_eq_string_macro(const char *first,  const char *first_string,
00180                 const char *second, const char *second_string,
00181                 const char *function, 
00182                 const char *file, unsigned line)
00183 {
00184     const char *message;
00185 
00186     message = irplib_sprintf("%s = '%s'; %s = '%s'",
00187                              first_string, first != NULL ? first : "NULL",
00188                              second_string, second != NULL ? second : "NULL");
00189 
00190     test(first != NULL && second != NULL && strcmp(first, second) == 0, 
00191          message,
00192          function, file, line);
00193 
00194     cpl_free((char *)message);
00195 
00196     return;
00197 }
00198 
00199 /*----------------------------------------------------------------------------*/
00215 /*----------------------------------------------------------------------------*/
00216 void 
00217 irplib_test_abs_macro(double first,  const char *first_string,
00218                       double second, const char *second_string,
00219                       double tolerance, const char *tolerance_string,
00220                       const char *function, const char *file, unsigned line)
00221 {
00222     const char *message =
00223         irplib_sprintf("|%s - (%s)| = |%g - (%g)| <= %g = %s",
00224                        first_string, second_string, first, second,
00225                        tolerance, tolerance_string);
00226 
00227     test(fabs(first - second) <= tolerance, message,
00228          function, file, line);
00229     /* Note: fails if tolerance is negative */
00230 
00231     cpl_free((char *)message);
00232 
00233     return;
00234 }
00235 
00236 /*----------------------------------------------------------------------------*/
00252 /*----------------------------------------------------------------------------*/
00253 void 
00254 irplib_test_rel_macro(double first,  const char *first_string,
00255                       double second, const char *second_string,
00256                       double tolerance, const char *tolerance_string,
00257                       const char *function, const char *file, unsigned line)
00258 {
00259     const char *message;
00260     
00261     if (first == 0 || second == 0) {
00262         /* Division by zero -> fail */
00263         message = irplib_sprintf("%s = %g; %s = %g (division by zero)",
00264                                  first_string, first,
00265                                  second_string, second);
00266         test(0, message,
00267              function, file, line);
00268     }
00269     else {
00270         message = 
00271             irplib_sprintf("|%s - (%s)|/|%s| = |%g - (%g)|/|%g| <= %g = %s and "
00272                            "|%s - (%s)|/|%s| = |%g - (%g)|/|%g| <= %g = %s",
00273                            first_string, second_string, first_string,
00274                            first, second, first, tolerance, tolerance_string,
00275                            first_string, second_string, second_string,
00276                            first, second, second, tolerance, tolerance_string);            
00277         
00278         test(fabs((first - second)/first ) <= tolerance &&
00279              fabs((first - second)/second) <= tolerance, message,
00280              function, file, line);
00281         /* Note: fails if tolerance is negative */
00282     }
00283 
00284     cpl_free((char *)message);
00285 
00286     return;
00287 }
00288 
00289 
00290 /*----------------------------------------------------------------------------*/
00297 /*----------------------------------------------------------------------------*/
00298 void
00299 irplib_test_init_macro(const char *file)
00300 {
00301     /* Build message domain + log filename
00302        from source file name */
00303     
00304     unsigned len = strlen(file);
00305     int able_to_parse_filename;
00306 
00307 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 0, 0)
00308     cpl_init(CPL_INIT_DEFAULT);
00309 #else
00310     cpl_init();
00311 #endif
00312     irplib_reset();
00313 
00314     if (len < strlen("s.c") || strcmp(file + len - strlen(".c"), ".c") != 0)
00315         {
00316             able_to_parse_filename = 0;
00317             /* Here, we should issue a warning but we need to
00318                initialize the CPL message system first */
00319         }
00320     else
00321         {
00322             /* Form domain from filename by removing ".c" suffix
00323                and stripping any path prefix */
00324 
00325             const char dir_delimiter = '/'; /* UNIX only! */
00326             unsigned path_length = 0;       /* Length of path prefix 
00327                                                including final '/' */
00328             int i;
00329 
00330             for (i = len - strlen(".c") - 1; i >= 0; i--)
00331                 {
00332                     if (file[i] == dir_delimiter && path_length == 0)
00333                         {
00334                             path_length = i + 1;
00335                         }
00336                 }
00337             
00338             able_to_parse_filename = (len - path_length - strlen(".c") >= 1);
00339             if (able_to_parse_filename)
00340                 {
00341                     const char *logfile;
00342                     char *domain;
00343 
00344                     domain = cpl_strdup(file + path_length);
00345                     domain[len - path_length - strlen(".c")] = '\0';
00346 
00347                     cpl_msg_set_domain(domain);
00348                     
00349                     logfile = irplib_sprintf("%s.log", domain);
00350                     cpl_msg_set_log_name(logfile);
00351                     
00352                     cpl_free((char *)logfile);
00353                     cpl_free(domain);
00354                 }
00355             /* else: Use default domain + logfilename */
00356         }
00357 
00358     /* Adopt the policy that the unit test is quiet
00359        unless something is wrong.
00360        Dump debugging info to the log file */
00361     cpl_msg_set_level(CPL_MSG_WARNING); 
00362     cpl_msg_set_log_level(CPL_MSG_DEBUG);
00363     
00364     if (!able_to_parse_filename)
00365         {
00366             cpl_msg_warning(cpl_func,
00367                             "Source file name '%s' does not match [base].c. ",
00368                             file);
00369         }
00370 
00371     if (cpl_error_get_code() != CPL_ERROR_NONE)
00372         {
00373             cpl_msg_error(cpl_func,
00374                           "Failure during initialization: %s at %s",
00375                           cpl_error_get_message(), cpl_error_get_where());
00376         }
00377 
00378     irplib_test_start = clock();
00379 
00380     return;
00381 }
00382 
00383 /*----------------------------------------------------------------------------*/
00393 /*----------------------------------------------------------------------------*/
00394 unsigned
00395 irplib_test_end_macro(const char *function, const char *file, unsigned line)
00396 {
00397     const clock_t time_to_test = clock() - irplib_test_start;
00398     const int memory_is_empty = cpl_memory_is_empty();
00399 
00400     cpl_msg_info(cpl_func, "Time to test [s]: %g",
00401                  (double)time_to_test/CLOCKS_PER_SEC);
00402 
00403     irplib_test_eq_macro(cpl_error_get_code(), "cpl_error_get_code()",
00404                          CPL_ERROR_NONE, "CPL_ERROR_NONE",
00405                          function, file, line);
00406 
00407     irplib_test_macro(memory_is_empty,
00408                       "memory_is_empty",
00409                       function, file, line);
00410     
00411     if (!memory_is_empty) {
00412         cpl_msg_error(function, "Memory leak detected:");
00413         cpl_memory_dump(); 
00414     }
00415 
00416     cpl_end();
00417 
00418     return irplib_test_nfail;
00419 }
00420 
00423 #endif

Generated on Thu Nov 15 14:32:26 2007 for UVES Pipeline Reference Manual by  doxygen 1.5.1