test.c

00001 /*                                                                              *
00002  *   This file is part of the ESO FORS   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 <test.h>
00029 
00030 #include <fors_utils.h>
00031 
00032 #include <cpl.h>
00033 #include <math.h>  /* fabs() */
00034 #include <string.h> /* strlen() */
00035 
00036 /*----------------------------------------------------------------------------*/
00040 /*----------------------------------------------------------------------------*/
00041 
00042 /*-----------------------------------------------------------------------------
00043                                 Implementation
00044  -----------------------------------------------------------------------------*/
00045 
00049 static unsigned long test_nfail = 0; 
00050 static cpl_errorstate error_init;
00051 
00052 /*----------------------------------------------------------------------------*/
00061 /*----------------------------------------------------------------------------*/
00062 static void
00063 _test(int expression, const char *message,
00064      const char *function, const char *file, unsigned line)
00065 {
00066     const char *error_state = (cpl_error_get_code() != CPL_ERROR_NONE) ?
00067         cpl_sprintf(" (CPL-error state: '%s' at %s)",
00068                        cpl_error_get_message(), cpl_error_get_where()) :
00069         NULL;
00070     
00071     if (expression) {
00072         cpl_msg_debug(function,
00073                       "OK at %s:%u%s: %s",
00074                       file, line, error_state != NULL ? error_state : "",
00075                       message);
00076     } else {
00077         if (test_nfail + 1 > test_nfail) {
00078             test_nfail++;
00079         }
00080         else {
00081             cpl_msg_error(function, "Number of errors (%lu) overflow!",
00082                           test_nfail);
00083         }
00084         
00085         cpl_msg_error(function,
00086                       "Failure at %s:%u%s: %s",
00087                       file, line, error_state != NULL ? error_state : "",
00088                       message);
00089     }
00090 
00091     if (error_state != NULL)
00092         {
00093             cpl_free((char *)error_state);
00094         }
00095 
00096     return;
00097 }
00098 
00099 
00100 /*----------------------------------------------------------------------------*/
00110 /*----------------------------------------------------------------------------*/
00111 void 
00112 test_macro(int expression, const char *expr_string,
00113                   const char *function, const char *file, unsigned line)
00114 {
00115     const char *message = cpl_sprintf("(%s) = %d", expr_string, expression);
00116 
00117     _test(expression, message,
00118          function, file, line);
00119 
00120     cpl_free((char *)message);
00121 
00122     return;
00123 }
00124 
00125 /*----------------------------------------------------------------------------*/
00137 /*----------------------------------------------------------------------------*/
00138 void 
00139 test_eq_macro(int first,  const char *first_string,
00140                      int second, const char *second_string,
00141                      const char *function, const char *file, unsigned line)
00142 {
00143     const char *message =
00144         cpl_sprintf("(%s) = %d; (%s) = %d",
00145                        first_string, first,
00146                        second_string, second);
00147 
00148     _test(first == second, message,
00149          function, file, line);
00150 
00151     cpl_free((char *)message);
00152 
00153     return;
00154 }
00155 
00156 /*----------------------------------------------------------------------------*/
00168 /*----------------------------------------------------------------------------*/
00169 void 
00170 test_eq_string_macro(const char *first,  const char *first_string,
00171                 const char *second, const char *second_string,
00172                 const char *function, 
00173                 const char *file, unsigned line)
00174 {
00175     const char *message;
00176 
00177     message = cpl_sprintf("%s = '%s'; %s = '%s'",
00178                              first_string, first != NULL ? first : "NULL",
00179                              second_string, second != NULL ? second : "NULL");
00180 
00181     _test(first != NULL && second != NULL && strcmp(first, second) == 0, 
00182          message,
00183          function, file, line);
00184 
00185     cpl_free((char *)message);
00186 
00187     return;
00188 }
00189 
00190 /*----------------------------------------------------------------------------*/
00206 /*----------------------------------------------------------------------------*/
00207 void 
00208 test_abs_macro(double first,  const char *first_string,
00209                       double second, const char *second_string,
00210                       double tolerance, const char *tolerance_string,
00211                       const char *function, const char *file, unsigned line)
00212 {
00213     const char *message =
00214         cpl_sprintf("|%s - (%s)| = |%g - (%g)| <= %g = %s",
00215                        first_string, second_string, first, second,
00216                        tolerance, tolerance_string);
00217 
00218     _test(fabs(first - second) <= tolerance, message,
00219          function, file, line);
00220     /* Note: fails if tolerance is negative */
00221 
00222     cpl_free((char *)message);
00223 
00224     return;
00225 }
00226 
00227 /*----------------------------------------------------------------------------*/
00243 /*----------------------------------------------------------------------------*/
00244 void 
00245 test_rel_macro(double first,  const char *first_string,
00246                       double second, const char *second_string,
00247                       double tolerance, const char *tolerance_string,
00248                       const char *function, const char *file, unsigned line)
00249 {
00250     const char *message;
00251     
00252     if (first == 0 || second == 0) {
00253         /* Division by zero -> fail */
00254         message = cpl_sprintf("%s = %g; %s = %g (division by zero)",
00255                                  first_string, first,
00256                                  second_string, second);
00257         _test(0, message,
00258              function, file, line);
00259     }
00260     else {
00261         message = 
00262             cpl_sprintf("|%s - (%s)|/|%s| = |%g - (%g)|/|%g| <= %g = %s and "
00263                            "|%s - (%s)|/|%s| = |%g - (%g)|/|%g| <= %g = %s",
00264                            first_string, second_string, first_string,
00265                            first, second, first, tolerance, tolerance_string,
00266                            first_string, second_string, second_string,
00267                            first, second, second, tolerance, tolerance_string);            
00268         
00269         _test(fabs((first - second)/first ) <= tolerance &&
00270              fabs((first - second)/second) <= tolerance, message,
00271              function, file, line);
00272         /* Note: fails if tolerance is negative */
00273     }
00274 
00275     cpl_free((char *)message);
00276 
00277     return;
00278 }
00279 
00280 
00281 /*----------------------------------------------------------------------------*/
00288 /*----------------------------------------------------------------------------*/
00289 void
00290 test_init_macro(const char *file)
00291 {
00292     /* Build message domain + log filename
00293        from source file name */
00294     
00295     unsigned len = strlen(file);
00296     int able_to_parse_filename;
00297 
00298     cpl_init(CPL_INIT_DEFAULT);
00299     error_init = cpl_errorstate_get();
00300     srand(0);
00301 
00302     if (len < strlen("s.c") || strcmp(file + len - strlen(".c"), ".c") != 0)
00303         {
00304             able_to_parse_filename = 0;
00305             /* Here, we should issue a warning but we need to
00306                initialize the CPL message system first */
00307         }
00308     else
00309         {
00310             /* Form domain from filename by removing ".c" suffix
00311                and stripping any path prefix */
00312 
00313             const char dir_delimiter = '/'; /* UNIX only! */
00314             unsigned path_length = 0;       /* Length of path prefix 
00315                                                including final '/' */
00316             int i;
00317 
00318             for (i = len - strlen(".c") - 1; i >= 0; i--)
00319                 {
00320                     if (file[i] == dir_delimiter && path_length == 0)
00321                         {
00322                             path_length = i + 1;
00323                         }
00324                 }
00325             
00326             able_to_parse_filename = (len - path_length - strlen(".c") >= 1);
00327             if (able_to_parse_filename)
00328                 {
00329                     const char *logfile;
00330                     char *domain;
00331 
00332                     domain = cpl_strdup(file + path_length);
00333                     domain[len - path_length - strlen(".c")] = '\0';
00334 
00335                     cpl_msg_set_domain(domain);
00336                     
00337                     logfile = cpl_sprintf("%s.log", domain);
00338                     cpl_msg_set_log_name(logfile);
00339                     
00340                     cpl_free((char *)logfile);
00341                     cpl_free(domain);
00342                 }
00343             /* else: Use default domain + logfilename */
00344         }
00345 
00346     /* Adopt the policy that the unit test is quiet
00347        unless something is wrong.
00348        Dump debugging info to the log file */
00349     cpl_msg_set_level(CPL_MSG_WARNING); 
00350     cpl_msg_set_log_level(CPL_MSG_DEBUG);
00351     
00352     if (!able_to_parse_filename)
00353         {
00354             cpl_msg_warning(cpl_func,
00355                             "Source file name '%s' does not match [base].c. ",
00356                             file);
00357         }
00358 
00359     if (cpl_error_get_code() != CPL_ERROR_NONE)
00360         {
00361             cpl_msg_error(cpl_func,
00362                           "Failure during initialization: %s at %s",
00363                           cpl_error_get_message(), cpl_error_get_where());
00364         }
00365 
00366     return;
00367 }
00368 
00369 /*----------------------------------------------------------------------------*/
00379 /*----------------------------------------------------------------------------*/
00380 unsigned
00381 test_end_macro(const char *function, const char *file, unsigned line)
00382 {
00383     const int memory_is_empty = cpl_memory_is_empty();
00384 
00385     test_eq_macro(cpl_error_get_code(), "cpl_error_get_code()",
00386                   CPL_ERROR_NONE, "CPL_ERROR_NONE",
00387                   function, file, line);
00388 
00389     if (cpl_error_get_code() != CPL_ERROR_NONE) {
00390         cpl_errorstate_dump(error_init, CPL_FALSE, NULL);
00391     }
00392 
00393     test_macro(memory_is_empty,
00394                "memory_is_empty",
00395                function, file, line);
00396     
00397     if (!memory_is_empty) {
00398         cpl_msg_error(function, "Memory leak detected:");
00399         cpl_memory_dump(); 
00400     }
00401 
00402     cpl_end();
00403 
00404     return test_nfail;
00405 }
00406 
00407 
00408 
00409 
00410 
00411 #undef cleanup
00412 #define cleanup \
00413 do { \
00414     cpl_propertylist_delete(product_header); \
00415 } while(0)
00416 /*----------------------------------------------------------------------------*/
00426 /*----------------------------------------------------------------------------*/
00427 void 
00428 test_recipe_output(const cpl_frameset *frames,
00429                    const char *const product_tags[], int n_prod,
00430            const char *main_product,
00431            const char *const qc[], int n_qc)
00432 {
00433     cpl_propertylist *product_header = NULL;
00434     
00435     int i;
00436     for (i = 0; i < n_prod; i++) {
00437         const cpl_frame *product = cpl_frameset_find_const(frames, product_tags[i]);
00438         test( product != NULL );
00439         test_eq( cpl_frame_get_group(product), CPL_FRAME_GROUP_PRODUCT );
00440         
00441         cpl_propertylist_delete(product_header);
00442         product_header = cpl_propertylist_load(cpl_frame_get_filename(product), 0);
00443         
00444         assure( !cpl_error_get_code(), return, 
00445                 "Failed to load product header" );
00446         
00447         
00448     if (strcmp(product_tags[i], main_product) == 0) {
00449         /* Must always be present */
00450         test( cpl_propertylist_has(product_header,
00451                        "ESO QC DID") );
00452     }
00453     else {
00454         test( !cpl_propertylist_has(product_header,
00455                     "ESO QC DID") );
00456     }
00457         
00458         int j;
00459         for (j = 0; j < n_qc; j++) {
00460         
00461             const char *full_qc_name = cpl_sprintf("ESO %s", qc[j]);
00462         
00463         cpl_msg_debug(cpl_func, 
00464               "Looking for '%s' in '%s'",
00465               qc[j], product_tags[i]);
00466         
00467         if (strcmp(product_tags[i], main_product) == 0) {
00468         test( cpl_propertylist_has(product_header,
00469                        full_qc_name) );
00470         }
00471         else {
00472         test( !cpl_propertylist_has(product_header,
00473                        full_qc_name) );
00474         }
00475         
00476         cpl_free((void *)full_qc_name);
00477         }
00478     }
00479     
00480     cleanup;
00481     return;
00482 }
00483 

Generated on Fri Mar 4 09:46:01 2011 for FORS Pipeline Reference Manual by  doxygen 1.4.7