00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035
00036 #include <stdlib.h>
00037 #include <assert.h>
00038 #include <cpl.h>
00039
00040
00041 #include "irplib_plugin.h"
00042 #include "irplib_utils.h"
00043 #include "irplib_error.h"
00044
00045
00055
00056
00057
00058
00059
00060
00061
00062 #ifndef LINE_LEN_MAX
00063 #define LINE_LEN_MAX 1024
00064 #endif
00065
00066
00067 #define DEV_RANDOM "/dev/urandom"
00068
00069
00070 #define recipe_assert(bool) \
00071 ((bool) ? (cpl_msg_debug(cpl_func, \
00072 "OK in " __FILE__ " line %d (CPL-error state: '%s' in %s): %s",__LINE__, \
00073 cpl_error_get_message(), cpl_error_get_where(), #bool), 0) \
00074 : (cpl_msg_error(cpl_func, \
00075 "Failure in " __FILE__ " line %d (CPL-error state: '%s' in %s): %s", \
00076 __LINE__, cpl_error_get_message(), cpl_error_get_where(), #bool), 1))
00077
00078
00079
00080
00081
00082
00083
00084 static const cpl_parameter * irplib_parameterlist_get(const cpl_parameterlist *,
00085 const char *,
00086 const char *,
00087 const char *);
00088
00089 static void recipe_msg_set_level_from_env(void);
00090 static void recipe_parameterlist_set_defaults(cpl_parameterlist *);
00091 static void recipe_frameset_load(cpl_frameset *, const char *);
00092
00093 static int recipe_sof_test_random(cpl_plugin *, size_t, const char *[]);
00094 static int recipe_sof_test_from_env(cpl_plugin *);
00095
00098
00099
00100
00101
00102
00112
00113 const char * irplib_parameterlist_get_string(const cpl_parameterlist * self,
00114 const char * instrume,
00115 const char * recipe,
00116 const char * parameter)
00117 {
00118
00119 const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
00120 recipe, parameter);
00121 const char * value;
00122
00123 cpl_ensure(par != NULL, cpl_error_get_code(), NULL);
00124
00125 cpl_ensure(cpl_parameter_get_type(par) == CPL_TYPE_STRING,
00126 CPL_ERROR_TYPE_MISMATCH, NULL);
00127
00128 value = cpl_parameter_get_string(par);
00129
00130 cpl_ensure(value != NULL, cpl_error_get_code(), NULL);
00131
00132 return value;
00133
00134 }
00135
00136
00146
00147 cpl_boolean irplib_parameterlist_get_bool(const cpl_parameterlist * self,
00148 const char * instrume,
00149 const char * recipe,
00150 const char * parameter)
00151 {
00152
00153 const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
00154 recipe, parameter);
00155 const cpl_error_code prestate = cpl_error_get_code();
00156 cpl_boolean value;
00157
00158 cpl_ensure(par != NULL, cpl_error_get_code(), CPL_FALSE);
00159
00160 cpl_ensure(cpl_parameter_get_type(par) == CPL_TYPE_BOOL,
00161 CPL_ERROR_TYPE_MISMATCH, CPL_FALSE);
00162
00163 value = cpl_parameter_get_bool(par);
00164
00165
00166 if (cpl_error_get_code() != prestate) cpl_error_set_where(cpl_func);
00167
00168 return value;
00169
00170 }
00171
00172
00173
00183
00184 int irplib_parameterlist_get_int(const cpl_parameterlist * self,
00185 const char * instrume,
00186 const char * recipe,
00187 const char * parameter)
00188 {
00189
00190 const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
00191 recipe, parameter);
00192 const cpl_error_code prestate = cpl_error_get_code();
00193 int value;
00194
00195 cpl_ensure(par != NULL, cpl_error_get_code(), 0);
00196
00197 cpl_ensure(cpl_parameter_get_type(par) == CPL_TYPE_INT,
00198 CPL_ERROR_TYPE_MISMATCH, 0);
00199
00200 value = cpl_parameter_get_int(par);
00201
00202
00203 if (cpl_error_get_code() != prestate) cpl_error_set_where(cpl_func);
00204
00205 return value;
00206 }
00207
00208
00218
00219 double irplib_parameterlist_get_double(const cpl_parameterlist * self,
00220 const char * instrume,
00221 const char * recipe,
00222 const char * parameter)
00223 {
00224
00225 const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
00226 recipe, parameter);
00227 const cpl_error_code prestate = cpl_error_get_code();
00228 double value;
00229
00230 cpl_ensure(par != NULL, cpl_error_get_code(), 0.0);
00231
00232 cpl_ensure(cpl_parameter_get_type(par) == CPL_TYPE_DOUBLE,
00233 CPL_ERROR_TYPE_MISMATCH, 0.0);
00234
00235 value = cpl_parameter_get_double(par);
00236
00237
00238 if (cpl_error_get_code() != prestate) cpl_error_set_where(cpl_func);
00239
00240 return value;
00241 }
00242
00243
00257
00258 cpl_error_code irplib_parameterlist_set_string(cpl_parameterlist * self,
00259 const char * instrume,
00260 const char * recipe,
00261 const char * parameter,
00262 const char * defvalue,
00263 const char * alias,
00264 const char * context,
00265 const char * man)
00266 {
00267
00268 cpl_error_code error;
00269 cpl_parameter * par;
00270 char * paramname = irplib_sprintf("%s.%s.%s",
00271 instrume, recipe,
00272 parameter);
00273
00274 cpl_ensure_code(paramname != NULL, cpl_error_get_code());
00275
00276 par = cpl_parameter_new_value(paramname, CPL_TYPE_STRING, man, context,
00277 defvalue);
00278 cpl_free(paramname);
00279
00280 cpl_ensure_code(par != NULL, cpl_error_get_code());
00281
00282 error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, alias);
00283 cpl_ensure_code(!error, error);
00284
00285 error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
00286 cpl_ensure_code(!error, error);
00287
00288 error = cpl_parameterlist_append(self, par);
00289 cpl_ensure_code(!error, error);
00290
00291 return CPL_ERROR_NONE;
00292 }
00293
00294
00295
00309
00310 cpl_error_code irplib_parameterlist_set_bool(cpl_parameterlist * self,
00311 const char * instrume,
00312 const char * recipe,
00313 const char * parameter,
00314 cpl_boolean defvalue,
00315 const char * alias,
00316 const char * context,
00317 const char * man)
00318 {
00319
00320 cpl_error_code error;
00321 cpl_parameter * par;
00322 char * paramname = irplib_sprintf("%s.%s.%s",
00323 instrume, recipe,
00324 parameter);
00325
00326 cpl_ensure_code(paramname != NULL, cpl_error_get_code());
00327
00328 par = cpl_parameter_new_value(paramname, CPL_TYPE_BOOL, man, context,
00329 defvalue);
00330 cpl_free(paramname);
00331
00332 cpl_ensure_code(par != NULL, cpl_error_get_code());
00333
00334 error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, alias);
00335 cpl_ensure_code(!error, error);
00336
00337 error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
00338 cpl_ensure_code(!error, error);
00339
00340 error = cpl_parameterlist_append(self, par);
00341 cpl_ensure_code(!error, error);
00342
00343 return CPL_ERROR_NONE;
00344 }
00345
00346
00347
00348
00362
00363 cpl_error_code irplib_parameterlist_set_int(cpl_parameterlist * self,
00364 const char * instrume,
00365 const char * recipe,
00366 const char * parameter,
00367 int defvalue,
00368 const char * alias,
00369 const char * context,
00370 const char * man)
00371 {
00372
00373 cpl_error_code error;
00374 cpl_parameter * par;
00375 char * paramname = irplib_sprintf("%s.%s.%s",
00376 instrume, recipe,
00377 parameter);
00378
00379 cpl_ensure_code(paramname != NULL, cpl_error_get_code());
00380
00381 par = cpl_parameter_new_value(paramname, CPL_TYPE_INT, man, context,
00382 defvalue);
00383 cpl_free(paramname);
00384
00385 cpl_ensure_code(par != NULL, cpl_error_get_code());
00386
00387 error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, alias);
00388 cpl_ensure_code(!error, error);
00389
00390 error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
00391 cpl_ensure_code(!error, error);
00392
00393 error = cpl_parameterlist_append(self, par);
00394 cpl_ensure_code(!error, error);
00395
00396 return CPL_ERROR_NONE;
00397 }
00398
00399
00400
00414
00415 cpl_error_code irplib_parameterlist_set_double(cpl_parameterlist * self,
00416 const char * instrume,
00417 const char * recipe,
00418 const char * parameter,
00419 double defvalue,
00420 const char * alias,
00421 const char * context,
00422 const char * man)
00423 {
00424
00425 cpl_error_code error;
00426 cpl_parameter * par;
00427 char * paramname = irplib_sprintf("%s.%s.%s",
00428 instrume, recipe,
00429 parameter);
00430
00431 cpl_ensure_code(paramname != NULL, cpl_error_get_code());
00432
00433 par = cpl_parameter_new_value(paramname, CPL_TYPE_DOUBLE, man, context,
00434 defvalue);
00435 cpl_free(paramname);
00436
00437 cpl_ensure_code(par != NULL, cpl_error_get_code());
00438
00439 error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, alias);
00440 cpl_ensure_code(!error, error);
00441
00442 error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
00443 cpl_ensure_code(!error, error);
00444
00445 error = cpl_parameterlist_append(self, par);
00446 cpl_ensure_code(!error, error);
00447
00448 return CPL_ERROR_NONE;
00449 }
00450
00451
00452
00464
00465 int irplib_plugin_test(cpl_pluginlist * self, size_t nstr, const char *astr[]) {
00466
00467 cpl_plugin * plugin;
00468 cpl_recipe * recipe;
00469 int (*recipe_create) (cpl_plugin *);
00470 int (*recipe_exec ) (cpl_plugin *);
00471 int (*recipe_deinit) (cpl_plugin *);
00472 const cpl_msg_severity msg_level = cpl_msg_get_level();
00473
00474 int recipe_nfail = 0;
00475 cpl_boolean is_debug;
00476
00477
00478 cpl_msg_set_level(CPL_MSG_OFF);
00479 recipe_msg_set_level_from_env();
00480
00481 is_debug = cpl_msg_get_level() <= CPL_MSG_DEBUG ? CPL_TRUE : CPL_FALSE;
00482
00483 assert( nstr == 0 || astr != NULL );
00484
00485 plugin = cpl_pluginlist_get_first(self);
00486
00487 if (plugin == NULL) {
00488 cpl_msg_warning(cpl_func, "With an empty pluginlist, "
00489 "no tests can be made");
00490 cpl_msg_set_level(msg_level);
00491 return 0;
00492 }
00493
00494 if (is_debug) cpl_plugin_dump(plugin, stdout);
00495
00496 recipe_create = cpl_plugin_get_init(plugin);
00497 recipe_exec = cpl_plugin_get_exec(plugin);
00498 recipe_deinit = cpl_plugin_get_deinit(plugin);
00499
00500
00501 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
00502 cpl_msg_warning(cpl_func, "This plugin is not of type recipe, "
00503 "cannot test further");
00504 cpl_msg_set_level(msg_level);
00505 return 0;
00506 }
00507
00508 recipe_nfail += recipe_assert( recipe_create(plugin) == 0);
00509
00510 recipe = (cpl_recipe *) plugin;
00511
00512 recipe_nfail += recipe_assert( recipe->parameters != NULL);
00513
00514 recipe_parameterlist_set_defaults(recipe->parameters);
00515
00516 if (is_debug) cpl_parameterlist_dump(recipe->parameters, stdout);
00517
00518 recipe->frames = cpl_frameset_new();
00519
00520 cpl_msg_info(cpl_func,"Checking handling of pre-existing CPL error state - "
00521 "may produce warning(s)/error(s):");
00522 cpl_error_set(cpl_func, CPL_ERROR_UNSPECIFIED);
00523
00524 recipe_nfail += recipe_assert( recipe_exec(plugin) != 0 );
00525
00526 recipe_nfail += recipe_assert( cpl_error_get_code() == CPL_ERROR_UNSPECIFIED );
00527
00528 irplib_error_dump(CPL_MSG_WARNING, CPL_MSG_DEBUG);
00529 cpl_msg_debug(cpl_func, "Resetting error state");
00530 irplib_error_reset();
00531
00532 cpl_msg_info(cpl_func,"Checking handling of empty frameset - "
00533 "may produce warning(s)/error(s):");
00534
00535 recipe_nfail += recipe_assert( recipe_exec(plugin) != 0 );
00536
00537 recipe_nfail += recipe_assert( cpl_error_get_code() != CPL_ERROR_NONE );
00538
00539 irplib_error_dump(CPL_MSG_WARNING, CPL_MSG_DEBUG);
00540 cpl_msg_debug(cpl_func, "Resetting error state");
00541 irplib_error_reset();
00542
00543 cpl_msg_info(cpl_func,"Checking handling of dummy frameset - "
00544 "may produce warning(s)/error(s):");
00545 do {
00546 cpl_frame * f = cpl_frame_new();
00547 recipe_nfail += recipe_assert( cpl_frame_set_filename(f, "/dev/null") == 0);
00548 recipe_nfail += recipe_assert( cpl_frame_set_tag(f, "RECIPE_DUMMY_TAG") == 0);
00549 recipe_nfail += recipe_assert( cpl_frameset_insert(recipe->frames, f) == 0);
00550
00551
00552 recipe_nfail += recipe_assert( recipe_exec(plugin) != 0 );
00553
00554 recipe_nfail += recipe_assert( cpl_error_get_code() != CPL_ERROR_NONE );
00555
00556 irplib_error_dump(CPL_MSG_WARNING, CPL_MSG_DEBUG);
00557 cpl_msg_debug(cpl_func, "Resetting error state");
00558 irplib_error_reset();
00559
00560 recipe_nfail += recipe_assert( cpl_frameset_erase_frame(recipe->frames, f)
00561 == CPL_ERROR_NONE );
00562
00563 } while (0);
00564
00565 recipe_nfail += recipe_sof_test_random(plugin, nstr, astr);
00566
00567 recipe_nfail += recipe_sof_test_from_env(plugin);
00568
00569 cpl_frameset_delete(recipe->frames);
00570
00571 recipe_nfail += recipe_assert( recipe_deinit(plugin) == 0 );
00572
00573 recipe_nfail += recipe_assert( cpl_error_get_code() == CPL_ERROR_NONE );
00574
00575 if (recipe_nfail) cpl_msg_error(cpl_func, "%d test(s) failed", recipe_nfail);
00576
00577 cpl_msg_set_level(msg_level);
00578 return recipe_nfail;
00579 }
00580
00583
00600
00601 static void recipe_msg_set_level_from_env(void)
00602 {
00603
00604 const char * level = getenv("RECIPE_MSG_LEVEL");
00605
00606 if (level == NULL) return;
00607
00608 if (!strcmp(level, "debug"))
00609 cpl_msg_set_level(CPL_MSG_DEBUG);
00610 else if (!strcmp(level, "info"))
00611 cpl_msg_set_level(CPL_MSG_INFO);
00612 else if (!strcmp(level, "warning"))
00613 cpl_msg_set_level(CPL_MSG_WARNING);
00614 else if (!strcmp(level, "error"))
00615 cpl_msg_set_level(CPL_MSG_ERROR);
00616 else if (!strcmp(level, "off"))
00617 cpl_msg_set_level(CPL_MSG_OFF);
00618
00619 return;
00620
00621 }
00622
00623
00624
00625
00635
00636 static void recipe_parameterlist_set_defaults(cpl_parameterlist *parlist)
00637 {
00638
00639 cpl_parameter * p = cpl_parameterlist_get_first(parlist);
00640
00641 for (; p != NULL; p = cpl_parameterlist_get_next(parlist)) {
00642
00643 if (cpl_parameter_get_default_flag(p)) continue;
00644
00645 cpl_msg_debug(cpl_func, __FILE__ " line %u: OK", __LINE__);
00646
00647 switch (cpl_parameter_get_type(p)) {
00648 case CPL_TYPE_BOOL:
00649 cpl_parameter_set_bool(p, cpl_parameter_get_default_bool(p));
00650 break;
00651 case CPL_TYPE_INT:
00652 cpl_parameter_set_int(p, cpl_parameter_get_default_int(p));
00653 break;
00654 case CPL_TYPE_DOUBLE:
00655 cpl_parameter_set_double(p, cpl_parameter_get_default_double(p));
00656 break;
00657 case CPL_TYPE_STRING:
00658 {
00659 const char * s_default = cpl_parameter_get_default_string(p);
00660
00661 cpl_parameter_set_string(p, s_default != NULL ? s_default : "");
00662 break;
00663 }
00664
00665 default:
00666 assert( 0 );
00667 }
00668 }
00669 }
00670
00671
00672
00679
00680 static int recipe_sof_test_random(cpl_plugin * plugin, size_t nstr,
00681 const char *astr[])
00682 {
00683 cpl_recipe * recipe = (cpl_recipe*)plugin;
00684
00685 int (*recipe_exec) (cpl_plugin *);
00686
00687
00688 int recipe_nfail = 0;
00689 size_t i;
00690
00691
00692 if (nstr < 1) return recipe_nfail;
00693
00694 cpl_msg_info(cpl_func, "Testing recipe with %u " DEV_RANDOM " as input ",
00695 (unsigned)nstr);
00696
00697 for (i = 0; i < nstr; i++) {
00698 cpl_frame * f = cpl_frame_new();
00699
00700 recipe_nfail += recipe_assert( cpl_frame_set_filename(f, DEV_RANDOM) == 0);
00701 recipe_nfail += recipe_assert( cpl_frame_set_tag(f, astr[i]) == 0);
00702 recipe_nfail += recipe_assert( cpl_frameset_insert(recipe->frames, f) == 0);
00703 }
00704
00705 recipe_exec = cpl_plugin_get_exec(plugin);
00706
00707
00708 recipe_nfail += recipe_assert( recipe_exec(plugin) != 0 );
00709
00710 recipe_nfail += recipe_assert( cpl_error_get_code() != CPL_ERROR_NONE );
00711
00712 irplib_error_dump(CPL_MSG_WARNING, CPL_MSG_DEBUG);
00713 cpl_msg_debug(cpl_func, "Resetting error state");
00714 irplib_error_reset();
00715
00716 for (i = 0; i < nstr; i++) {
00717 cpl_frame * f = cpl_frameset_get_first(recipe->frames);
00718 recipe_nfail +=
00719 recipe_assert( cpl_frameset_erase_frame(recipe->frames, f)
00720 == CPL_ERROR_NONE );
00721 }
00722
00723 return recipe_nfail;
00724 }
00725
00726
00727
00734
00735 static int recipe_sof_test_from_env(cpl_plugin * plugin)
00736 {
00737 cpl_recipe * recipe = (cpl_recipe*)plugin;
00738 const char * recipename = cpl_plugin_get_name(plugin);
00739 const char * var_name = "RECIPE_SOF_PATH";
00740 const char * sof_path = getenv(var_name);
00741
00742
00743 int recipe_nfail = 0;
00744
00745 char * sof_name;
00746
00747 if (sof_path == NULL) {
00748 cpl_msg_warning(cpl_func, "Environment variable %s is unset: "
00749 "No SOFs to check", var_name);
00750 return recipe_nfail;
00751 }
00752
00753 cpl_msg_debug(cpl_func, "Checking for SOFs in %s", sof_path);
00754
00755 if (recipename == NULL) {
00756 recipe_nfail += recipe_assert(recipename != NULL);
00757 return recipe_nfail;
00758 }
00759
00760 sof_name = irplib_sprintf("%s/%s.sof", sof_path, recipename);
00761
00762 cpl_msg_debug(cpl_func, "Checking for SOF %s", sof_name);
00763
00764 recipe_frameset_load(recipe->frames, sof_name);
00765
00766 if (!cpl_frameset_is_empty(recipe->frames)) {
00767
00768 int (*recipe_exec ) (cpl_plugin *);
00769
00770 recipe_exec = cpl_plugin_get_exec(plugin);
00771
00772 cpl_msg_info(cpl_func,"Checking handling of SOF: %s", sof_name);
00773 recipe_nfail += recipe_assert( recipe_exec(plugin) == 0 );
00774 recipe_nfail += recipe_assert( cpl_error_get_code() == CPL_ERROR_NONE );
00775
00776 }
00777
00778 cpl_free(sof_name);
00779
00780 return recipe_nfail;
00781 }
00782
00783
00797
00798
00799 static void recipe_frameset_load(cpl_frameset * set, const char *name)
00800 {
00801
00802 FILE *fp;
00803 char line[LINE_LEN_MAX];
00804 char path[LINE_LEN_MAX], group[LINE_LEN_MAX], tag[LINE_LEN_MAX];
00805 int line_number;
00806
00807 assert( set != NULL );
00808 assert( name != NULL );
00809
00810 fp = fopen(name, "r");
00811 if (fp == NULL) {
00812 cpl_msg_debug(cpl_func, "Unable to open SOF file '%s'", name);
00813 return;
00814 }
00815
00816
00817 for (line_number = 0; fgets(line, LINE_LEN_MAX - 1, fp); line_number++) {
00818
00819 cpl_frame_group grp;
00820 cpl_frame * frame;
00821 int n;
00822
00823 if (line[0] == '#') continue;
00824
00825 n = sscanf(line, "%s %s %s", path, tag, group);
00826
00827 if (n < 1) {
00828 cpl_msg_warning(cpl_func, "Spurious line no. %d in %s: %s",
00829 line_number, name, line);
00830 break;
00831 }
00832
00833
00834 frame = cpl_frame_new();
00835
00836
00837 cpl_frame_set_filename(frame, path);
00838
00839
00840 cpl_frame_set_tag(frame, n == 1 ? "" : tag);
00841
00842 cpl_frameset_insert(set, frame);
00843
00844
00845 if (n < 3) continue;
00846
00847 if (!strcmp(group, CPL_FRAME_GROUP_RAW_ID))
00848 grp = CPL_FRAME_GROUP_RAW;
00849 else if (!strcmp(group, CPL_FRAME_GROUP_CALIB_ID))
00850 grp = CPL_FRAME_GROUP_CALIB;
00851 else if (!strcmp(group, CPL_FRAME_GROUP_PRODUCT_ID))
00852 grp = CPL_FRAME_GROUP_PRODUCT;
00853 else
00854 grp = CPL_FRAME_GROUP_NONE;
00855
00856 cpl_frame_set_group(frame, grp);
00857 }
00858
00859 fclose(fp);
00860
00861 return;
00862
00863 }
00864
00865
00866
00876
00877 static const cpl_parameter * irplib_parameterlist_get(const cpl_parameterlist
00878 * self,
00879 const char * instrume,
00880 const char * recipe,
00881 const char * parameter)
00882 {
00883
00884 const cpl_parameter * par;
00885 char * paramname;
00886
00887
00888 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
00889 cpl_ensure(instrume != NULL, CPL_ERROR_NULL_INPUT, NULL);
00890 cpl_ensure(recipe != NULL, CPL_ERROR_NULL_INPUT, NULL);
00891 cpl_ensure(parameter != NULL, CPL_ERROR_NULL_INPUT, NULL);
00892
00893 paramname = irplib_sprintf("%s.%s.%s", instrume, recipe,
00894 parameter);
00895
00896 cpl_ensure(paramname != NULL, cpl_error_get_code(), NULL);
00897
00898
00899 par = cpl_parameterlist_find((cpl_parameterlist*)self, paramname);
00900
00901 cpl_free(paramname);
00902
00903 return par;
00904
00905 }
00906