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 /*----------------------------------------------------------------------------*/
00043 /*----------------------------------------------------------------------------*/
00044 
00045 /*-----------------------------------------------------------------------------
00046                                 Implementation
00047  -----------------------------------------------------------------------------*/
00048 
00052 static unsigned long irplib_test_nfail = 0; 
00053 
00054 /*----------------------------------------------------------------------------*/
00063 /*----------------------------------------------------------------------------*/
00064 static void
00065 test(int expression, const char *message,
00066      const char *function, const char *file, unsigned line)
00067 {
00068     const char *error_state = (cpl_error_get_code() != CPL_ERROR_NONE) ?
00069         irplib_sprintf(" (CPL-error state: '%s' at %s)",
00070                        cpl_error_get_message(), cpl_error_get_where()) :
00071         NULL;
00072     
00073     if (expression) {
00074         cpl_msg_debug(function,
00075                       "OK at %s:%u%s: %s",
00076                       file, line, error_state != NULL ? error_state : "",
00077                       message);
00078     } else {
00079         if (irplib_test_nfail + 1 > irplib_test_nfail) {
00080             irplib_test_nfail++;
00081         }
00082         else {
00083             cpl_msg_error(function, "Number of errors (%lu) overflow!",
00084                           irplib_test_nfail);
00085         }
00086         
00087         cpl_msg_error(function,
00088                       "Failure at %s:%u%s: %s",
00089                       file, line, error_state != NULL ? error_state : "",
00090                       message);
00091     }
00092 
00093     if (error_state != NULL)
00094         {
00095             cpl_free((char *)error_state);
00096         }
00097 
00098     return;
00099 }
00100 
00101 
00102 /*----------------------------------------------------------------------------*/
00112 /*----------------------------------------------------------------------------*/
00113 void 
00114 irplib_test_macro(int expression, const char *expr_string,
00115                   const char *function, const char *file, unsigned line)
00116 {
00117     const char *message = irplib_sprintf("(%s) = %d", expr_string, expression);
00118 
00119     test(expression, message,
00120          function, file, line);
00121 
00122     cpl_free((char *)message);
00123 
00124     return;
00125 }
00126 
00127 /*----------------------------------------------------------------------------*/
00139 /*----------------------------------------------------------------------------*/
00140 void 
00141 irplib_test_eq_macro(int first,  const char *first_string,
00142                      int second, const char *second_string,
00143                      const char *function, const char *file, unsigned line)
00144 {
00145     const char *message =
00146         irplib_sprintf("(%s) = %d; (%s) = %d",
00147                        first_string, first,
00148                        second_string, second);
00149 
00150     test(first == second, message,
00151          function, file, line);
00152 
00153     cpl_free((char *)message);
00154 
00155     return;
00156 }
00157 
00158 /*----------------------------------------------------------------------------*/
00170 /*----------------------------------------------------------------------------*/
00171 void 
00172 irplib_test_eq_string_macro(const char *first,  const char *first_string,
00173                 const char *second, const char *second_string,
00174                 const char *function, 
00175                 const char *file, unsigned line)
00176 {
00177     const char *message;
00178 
00179     message = irplib_sprintf("%s = '%s'; %s = '%s'",
00180                              first_string, first != NULL ? first : "NULL",
00181                              second_string, second != NULL ? second : "NULL");
00182 
00183     test(first != NULL && second != NULL && strcmp(first, second) == 0, 
00184          message,
00185          function, file, line);
00186 
00187     cpl_free((char *)message);
00188 
00189     return;
00190 }
00191 
00192 /*----------------------------------------------------------------------------*/
00208 /*----------------------------------------------------------------------------*/
00209 void 
00210 irplib_test_abs_macro(double first,  const char *first_string,
00211                       double second, const char *second_string,
00212                       double tolerance, const char *tolerance_string,
00213                       const char *function, const char *file, unsigned line)
00214 {
00215     const char *message =
00216         irplib_sprintf("|%s - (%s)| = |%g - (%g)| <= %g = %s",
00217                        first_string, second_string, first, second,
00218                        tolerance, tolerance_string);
00219 
00220     test(fabs(first - second) <= tolerance, message,
00221          function, file, line);
00222     /* Note: fails if tolerance is negative */
00223 
00224     cpl_free((char *)message);
00225 
00226     return;
00227 }
00228 
00229 /*----------------------------------------------------------------------------*/
00245 /*----------------------------------------------------------------------------*/
00246 void 
00247 irplib_test_rel_macro(double first,  const char *first_string,
00248                       double second, const char *second_string,
00249                       double tolerance, const char *tolerance_string,
00250                       const char *function, const char *file, unsigned line)
00251 {
00252     const char *message;
00253     
00254     if (first == 0 || second == 0) {
00255         /* Division by zero -> fail */
00256         message = irplib_sprintf("%s = %g; %s = %g (division by zero)",
00257                                  first_string, first,
00258                                  second_string, second);
00259         test(0, message,
00260              function, file, line);
00261     }
00262     else {
00263         message = 
00264             irplib_sprintf("|%s - (%s)|/|%s| = |%g - (%g)|/|%g| <= %g = %s and "
00265                            "|%s - (%s)|/|%s| = |%g - (%g)|/|%g| <= %g = %s",
00266                            first_string, second_string, first_string,
00267                            first, second, first, tolerance, tolerance_string,
00268                            first_string, second_string, second_string,
00269                            first, second, second, tolerance, tolerance_string);            
00270         
00271         test(fabs((first - second)/first ) <= tolerance &&
00272              fabs((first - second)/second) <= tolerance, message,
00273              function, file, line);
00274         /* Note: fails if tolerance is negative */
00275     }
00276 
00277     cpl_free((char *)message);
00278 
00279     return;
00280 }
00281 
00282 
00283 /*----------------------------------------------------------------------------*/
00290 /*----------------------------------------------------------------------------*/
00291 void
00292 irplib_test_init_macro(const char *file)
00293 {
00294     /* Build message domain + log filename
00295        from source file name */
00296     
00297     unsigned len = strlen(file);
00298     int able_to_parse_filename;
00299 
00300     cpl_init();
00301     irplib_reset();
00302 
00303     if (len < strlen("s.c") || strcmp(file + len - strlen(".c"), ".c") != 0)
00304         {
00305             able_to_parse_filename = 0;
00306             /* Here, we should issue a warning but we need to
00307                initialize the CPL message system first */
00308         }
00309     else
00310         {
00311             /* Form domain from filename by removing ".c" suffix
00312                and stripping any path prefix */
00313 
00314             const char dir_delimiter = '/'; /* UNIX only! */
00315             unsigned path_length = 0;       /* Length of path prefix 
00316                                                including final '/' */
00317             int i;
00318 
00319             for (i = len - strlen(".c") - 1; i >= 0; i--)
00320                 {
00321                     if (file[i] == dir_delimiter && path_length == 0)
00322                         {
00323                             path_length = i + 1;
00324                         }
00325                 }
00326             
00327             able_to_parse_filename = (len - path_length - strlen(".c") >= 1);
00328             if (able_to_parse_filename)
00329                 {
00330                     const char *logfile;
00331                     char *domain;
00332 
00333                     domain = cpl_strdup(file + path_length);
00334                     domain[len - path_length - strlen(".c")] = '\0';
00335 
00336                     cpl_msg_set_domain(domain);
00337                     
00338                     logfile = irplib_sprintf("%s.log", domain);
00339                     cpl_msg_set_log_name(logfile);
00340                     
00341                     cpl_free((char *)logfile);
00342                     cpl_free(domain);
00343                 }
00344             /* else: Use default domain + logfilename */
00345         }
00346 
00347     /* Adopt the policy that the unit test is quiet
00348        unless something is wrong.
00349        Dump debugging info to the log file */
00350     cpl_msg_set_level(CPL_MSG_WARNING); 
00351     cpl_msg_set_log_level(CPL_MSG_DEBUG);
00352     
00353     if (!able_to_parse_filename)
00354         {
00355             cpl_msg_warning(cpl_func,
00356                             "Source file name '%s' does not match [base].c. ",
00357                             file);
00358         }
00359 
00360     if (cpl_error_get_code() != CPL_ERROR_NONE)
00361         {
00362             cpl_msg_error(cpl_func,
00363                           "Failure during initialization: %s at %s",
00364                           cpl_error_get_message(), cpl_error_get_where());
00365         }
00366 
00367     return;
00368 }
00369 
00370 /*----------------------------------------------------------------------------*/
00380 /*----------------------------------------------------------------------------*/
00381 unsigned
00382 irplib_test_end_macro(const char *function, const char *file, unsigned line)
00383 {
00384     const int memory_is_empty = cpl_memory_is_empty();
00385 
00386     irplib_test_eq_macro(cpl_error_get_code(), "cpl_error_get_code()",
00387                          CPL_ERROR_NONE, "CPL_ERROR_NONE",
00388                          function, file, line);
00389 
00390     irplib_test_macro(memory_is_empty,
00391                       "memory_is_empty",
00392                       function, file, line);
00393     
00394     if (!memory_is_empty) {
00395         cpl_msg_error(function, "Memory leak detected:");
00396         cpl_memory_dump(); 
00397     }
00398 
00399     cpl_end();
00400 
00401     return irplib_test_nfail;
00402 }
00403 

Generated on Tue Jun 19 14:39:14 2007 for UVES Pipeline Reference Manual by  doxygen 1.4.6