UVES Pipeline Reference Manual  5.4.2
irplib_plugin.c
1 /* $Id: irplib_plugin.c,v 1.40 2013-08-22 17:44:56 cgarcia Exp $
2  *
3  * This file is part of the irplib package
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: cgarcia $
23  * $Date: 2013-08-22 17:44:56 $
24  * $Revision: 1.40 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 /*-----------------------------------------------------------------------------
29  Includes
30  -----------------------------------------------------------------------------*/
31 
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 
36 #include <string.h>
37 #include <stdlib.h>
38 #include <assert.h>
39 
40 #include <cpl.h>
41 
42 
43 #include "irplib_plugin.h"
44 
45 /*----------------------------------------------------------------------------*/
55 /*----------------------------------------------------------------------------*/
56 
57 /*-----------------------------------------------------------------------------
58  Defines
59  -----------------------------------------------------------------------------*/
60 
61 /* Maximum line length in SOF-file */
62 #ifndef LINE_LEN_MAX
63 #define LINE_LEN_MAX 1024
64 #endif
65 
66 /* This device provides quite-random data */
67 #define DEV_RANDOM "/dev/urandom"
68 
69 /* Copied from cpl_tools.h */
70 #define recipe_assert(bool) \
71  ((bool) ? (cpl_msg_debug(cpl_func, \
72  "OK in " __FILE__ " line %d (CPL-error state: '%s' in %s): %s",__LINE__, \
73  cpl_error_get_message(), cpl_error_get_where(), #bool), 0) \
74  : (cpl_msg_error(cpl_func, \
75  "Failure in " __FILE__ " line %d (CPL-error state: '%s' in %s): %s", \
76  __LINE__, cpl_error_get_message(), cpl_error_get_where(), #bool), 1))
77 
78 
79 
80 /*-----------------------------------------------------------------------------
81  Private Function prototypes
82  -----------------------------------------------------------------------------*/
83 
84 static const cpl_parameter * irplib_parameterlist_get(const cpl_parameterlist *,
85  const char *,
86  const char *,
87  const char *);
88 
89 static void recipe_parameterlist_set(cpl_parameterlist *);
90 static cpl_boolean irplib_plugin_has_sof_from_env(const cpl_plugin *,
91  const char *);
92 
93 static void recipe_frameset_load(cpl_frameset *, const char *);
94 
95 static void recipe_sof_test_devfile(cpl_plugin *, const char *, size_t,
96  const char *[]);
97 static void recipe_sof_test_image_empty(cpl_plugin *, size_t, const char *[]);
98 static void recipe_sof_test_local(cpl_plugin *);
99 static void recipe_sof_test_from_env(cpl_plugin *);
100 static void recipe_frameset_empty(cpl_frameset *);
101 static void recipe_frameset_test_frame(const cpl_frame *);
102 static void recipe_frameset_test_frameset_diff(const cpl_frameset *,
103  const cpl_frameset *);
104 
105 static cpl_errorstate inistate;
106 
109 /*-----------------------------------------------------------------------------
110  Function definitions
111  -----------------------------------------------------------------------------*/
112 
113 /*----------------------------------------------------------------------------*/
123 /*----------------------------------------------------------------------------*/
124 const char * irplib_parameterlist_get_string(const cpl_parameterlist * self,
125  const char * instrume,
126  const char * recipe,
127  const char * parameter)
128 {
129 
130  const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
131  recipe, parameter);
132  const char * value;
133 
134  cpl_ensure(par != NULL, cpl_error_get_code(), NULL);
135 
136  value = cpl_parameter_get_string(par);
137 
138  if (value == NULL) (void)cpl_error_set_where(cpl_func);
139 
140  return value;
141 
142 }
143 
144 /*----------------------------------------------------------------------------*/
154 /*----------------------------------------------------------------------------*/
155 cpl_boolean irplib_parameterlist_get_bool(const cpl_parameterlist * self,
156  const char * instrume,
157  const char * recipe,
158  const char * parameter)
159 {
160 
161  const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
162  recipe, parameter);
163  cpl_errorstate prestate = cpl_errorstate_get();
164  cpl_boolean value;
165 
166 
167  cpl_ensure(par != NULL, cpl_error_get_code(), CPL_FALSE);
168 
169  value = cpl_parameter_get_bool(par);
170 
171  if (!cpl_errorstate_is_equal(prestate)) (void)cpl_error_set_where(cpl_func);
172 
173  return value;
174 
175 }
176 
177 
178 /*----------------------------------------------------------------------------*/
188 /*----------------------------------------------------------------------------*/
189 int irplib_parameterlist_get_int(const cpl_parameterlist * self,
190  const char * instrume,
191  const char * recipe,
192  const char * parameter)
193 {
194 
195  const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
196  recipe, parameter);
197  cpl_errorstate prestate = cpl_errorstate_get();
198  int value;
199 
200 
201  cpl_ensure(par != NULL, cpl_error_get_code(), 0);
202 
203  value = cpl_parameter_get_int(par);
204 
205  if (!cpl_errorstate_is_equal(prestate)) (void)cpl_error_set_where(cpl_func);
206 
207  return value;
208 }
209 
210 /*----------------------------------------------------------------------------*/
220 /*----------------------------------------------------------------------------*/
221 double irplib_parameterlist_get_double(const cpl_parameterlist * self,
222  const char * instrume,
223  const char * recipe,
224  const char * parameter)
225 {
226 
227  const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
228  recipe, parameter);
229  cpl_errorstate prestate = cpl_errorstate_get();
230  double value;
231 
232 
233  cpl_ensure(par != NULL, cpl_error_get_code(), 0.0);
234 
235  value = cpl_parameter_get_double(par);
236 
237  if (!cpl_errorstate_is_equal(prestate)) (void)cpl_error_set_where(cpl_func);
238 
239  return value;
240 }
241 
242 /*----------------------------------------------------------------------------*/
256 /*----------------------------------------------------------------------------*/
257 cpl_error_code irplib_parameterlist_set_string(cpl_parameterlist * self,
258  const char * instrume,
259  const char * recipe,
260  const char * parameter,
261  const char * defvalue,
262  const char * alias,
263  const char * context,
264  const char * man)
265 {
266 
267  cpl_error_code error;
268  cpl_parameter * par;
269  char * paramname = cpl_sprintf("%s.%s.%s", instrume, recipe,
270  parameter);
271 
272  cpl_ensure_code(paramname != NULL, cpl_error_get_code());
273 
274  par = cpl_parameter_new_value(paramname, CPL_TYPE_STRING, man, context,
275  defvalue);
276  cpl_free(paramname);
277 
278  cpl_ensure_code(par != NULL, cpl_error_get_code());
279 
280  error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
281  alias ? alias : parameter);
282  cpl_ensure_code(!error, error);
283 
284  error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
285  cpl_ensure_code(!error, error);
286 
287  error = cpl_parameterlist_append(self, par);
288  cpl_ensure_code(!error, error);
289 
290  return CPL_ERROR_NONE;
291 }
292 
293 
294 /*----------------------------------------------------------------------------*/
308 /*----------------------------------------------------------------------------*/
309 cpl_error_code irplib_parameterlist_set_bool(cpl_parameterlist * self,
310  const char * instrume,
311  const char * recipe,
312  const char * parameter,
313  cpl_boolean defvalue,
314  const char * alias,
315  const char * context,
316  const char * man)
317 {
318 
319  cpl_error_code error;
320  cpl_parameter * par;
321  char * paramname = cpl_sprintf("%s.%s.%s", instrume, recipe,
322  parameter);
323 
324  cpl_ensure_code(paramname != NULL, cpl_error_get_code());
325 
326  par = cpl_parameter_new_value(paramname, CPL_TYPE_BOOL, man, context,
327  defvalue);
328  cpl_free(paramname);
329 
330  cpl_ensure_code(par != NULL, cpl_error_get_code());
331 
332  error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
333  alias ? alias : parameter);
334  cpl_ensure_code(!error, error);
335 
336  error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
337  cpl_ensure_code(!error, error);
338 
339  error = cpl_parameterlist_append(self, par);
340  cpl_ensure_code(!error, error);
341 
342  return CPL_ERROR_NONE;
343 }
344 
345 
346 
347 /*----------------------------------------------------------------------------*/
361 /*----------------------------------------------------------------------------*/
362 cpl_error_code irplib_parameterlist_set_int(cpl_parameterlist * self,
363  const char * instrume,
364  const char * recipe,
365  const char * parameter,
366  int defvalue,
367  const char * alias,
368  const char * context,
369  const char * man)
370 {
371 
372  cpl_error_code error;
373  cpl_parameter * par;
374  char * paramname = cpl_sprintf("%s.%s.%s", instrume, recipe,
375  parameter);
376 
377  cpl_ensure_code(paramname != NULL, cpl_error_get_code());
378 
379  par = cpl_parameter_new_value(paramname, CPL_TYPE_INT, man, context,
380  defvalue);
381  cpl_free(paramname);
382 
383  cpl_ensure_code(par != NULL, cpl_error_get_code());
384 
385  error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
386  alias ? alias : parameter);
387  cpl_ensure_code(!error, error);
388 
389  error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
390  cpl_ensure_code(!error, error);
391 
392  error = cpl_parameterlist_append(self, par);
393  cpl_ensure_code(!error, error);
394 
395  return CPL_ERROR_NONE;
396 }
397 
398 
399 /*----------------------------------------------------------------------------*/
413 /*----------------------------------------------------------------------------*/
414 cpl_error_code irplib_parameterlist_set_double(cpl_parameterlist * self,
415  const char * instrume,
416  const char * recipe,
417  const char * parameter,
418  double defvalue,
419  const char * alias,
420  const char * context,
421  const char * man)
422 {
423 
424  cpl_error_code error;
425  cpl_parameter * par;
426  char * paramname = cpl_sprintf("%s.%s.%s", instrume, recipe,
427  parameter);
428 
429  cpl_ensure_code(paramname != NULL, cpl_error_get_code());
430 
431  par = cpl_parameter_new_value(paramname, CPL_TYPE_DOUBLE, man, context,
432  defvalue);
433  cpl_free(paramname);
434 
435  cpl_ensure_code(par != NULL, cpl_error_get_code());
436 
437  error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
438  alias ? alias : parameter);
439  cpl_ensure_code(!error, error);
440 
441  error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
442  cpl_ensure_code(!error, error);
443 
444  error = cpl_parameterlist_append(self, par);
445  cpl_ensure_code(!error, error);
446 
447  return CPL_ERROR_NONE;
448 }
449 
450 
451 /*----------------------------------------------------------------------------*/
465 /*----------------------------------------------------------------------------*/
466 int irplib_plugin_test(cpl_pluginlist * self, size_t nstr, const char *astr[]) {
467 
468  cpl_plugin * plugin;
469  cpl_recipe * recipe;
470  int (*recipe_create) (cpl_plugin *);
471  int (*recipe_exec ) (cpl_plugin *);
472  int (*recipe_deinit) (cpl_plugin *);
473  cpl_error_code error;
474  FILE * stream;
475  cpl_boolean is_debug;
476 
477 
478  is_debug = cpl_msg_get_level() <= CPL_MSG_DEBUG ? CPL_TRUE : CPL_FALSE;
479 
480  /* Modified from CPL unit tests */
481  stream = is_debug ? stdout : fopen("/dev/null", "a");
482 
483  inistate = cpl_errorstate_get();
484 
485  assert( nstr == 0 || astr != NULL );
486 
487  plugin = cpl_pluginlist_get_first(self);
488 
489  if (plugin == NULL) {
490  cpl_msg_warning(cpl_func, "With an empty pluginlist, "
491  "no tests can be made");
492  return 0;
493  }
494 
495  cpl_plugin_dump(plugin, stream);
496 
497  recipe_create = cpl_plugin_get_init(plugin);
498  cpl_test( recipe_create != NULL);
499 
500  recipe_exec = cpl_plugin_get_exec(plugin);
501  cpl_test( recipe_exec != NULL);
502 
503  recipe_deinit = cpl_plugin_get_deinit(plugin);
504  cpl_test( recipe_deinit != NULL);
505 
506  /* Only plugins of type recipe are tested (further) */
507  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
508  cpl_msg_warning(cpl_func, "This plugin is not of type recipe, "
509  "cannot test further");
510  return 0;
511  }
512 
513  if (recipe_create != NULL && recipe_exec != NULL && recipe_deinit != NULL) {
514 
515  cpl_test_zero(recipe_create(plugin));
516 
517  recipe = (cpl_recipe *) plugin;
518 
519  cpl_test_nonnull( recipe->parameters );
520 
521  recipe_parameterlist_set(recipe->parameters);
522 
523  cpl_parameterlist_dump(recipe->parameters, stream);
524 
525  recipe->frames = cpl_frameset_new();
526 
527  if (irplib_plugin_has_sof_from_env(plugin, "RECIPE_SOF_PATH")) {
528 
529  recipe_sof_test_from_env(plugin);
530 
531  } else {
532 
533  const cpl_msg_severity msg_level = cpl_msg_get_level();
534 
535  /* Unless the CPL_MSG_LEVEL has been explicitly set, turn off
536  terminal messaging completely while inside this function */
537  if (getenv("CPL_MSG_LEVEL") == NULL) cpl_msg_set_level(CPL_MSG_OFF);
538 
539  cpl_msg_info(cpl_func,"Checking handling of pre-existing CPL error "
540  "state - may produce warning(s)/error(s):");
541  cpl_error_set(cpl_func, CPL_ERROR_EOL);
542  /* Call recipe and expect non-zero return code */
543  cpl_test( recipe_exec(plugin) );
544  /* Expect also the CPL error code to be preserved */
545  cpl_test_error( CPL_ERROR_EOL );
546 
547  cpl_msg_info(cpl_func,"Checking handling of empty frameset - "
548  "may produce warning(s)/error(s):");
549  /* Call recipe and expect non-zero return code */
550  cpl_test( recipe_exec(plugin) );
551  error = cpl_error_get_code();
552  /* Expect also the CPL error code to be set */
553  cpl_test_error( error );
554  cpl_test( error );
555 
556  cpl_msg_info(cpl_func,"Checking handling of dummy frameset - "
557  "may produce warning(s)/error(s):");
558  do {
559  cpl_frame * f = cpl_frame_new();
560  error = cpl_frame_set_filename(f, "/dev/null");
561  cpl_test_eq_error(error, CPL_ERROR_NONE);
562  error = cpl_frame_set_tag(f, "RECIPE_DUMMY_TAG");
563  cpl_test_eq_error(error, CPL_ERROR_NONE);
564  error = cpl_frameset_insert(recipe->frames, f);
565  cpl_test_eq_error(error, CPL_ERROR_NONE);
566 
567  /* Call recipe and expect non-zero return code */
568  cpl_test( recipe_exec(plugin) );
569  error = cpl_error_get_code();
570  /* Expect also the CPL error code to be set */
571  cpl_test_error( error );
572  cpl_test( error );
573 
574  error = cpl_frameset_erase_frame(recipe->frames, f);
575  cpl_test_eq_error(error, CPL_ERROR_NONE);
576 
577  } while (0);
578 
579 #ifdef IRPLIB_TEST_RANDOM_SOF
580  recipe_sof_test_devfile(plugin, DEV_RANDOM, nstr, astr);
581 #endif
582 
583  recipe_sof_test_devfile(plugin, "/dev/null", nstr, astr);
584 
585  recipe_sof_test_devfile(plugin, ".", nstr, astr);
586 
587  recipe_sof_test_image_empty(plugin, nstr, astr);
588 
589  recipe_sof_test_local(plugin);
590 
591  cpl_msg_set_level(msg_level);
592 
593  }
594 
595  cpl_frameset_delete(recipe->frames);
596 
597  error = recipe_deinit(plugin);
598  cpl_test_eq_error(error, CPL_ERROR_NONE);
599  }
600 
601  if (stream != stdout) fclose(stream);
602 
603  return 0;
604 }
605 
608 /*----------------------------------------------------------------------------*/
618 /*----------------------------------------------------------------------------*/
619 static void recipe_parameterlist_set(cpl_parameterlist * self)
620 {
621 
622  cpl_parameter * p = cpl_parameterlist_get_first(self);
623 
624  for (; p != NULL; p = cpl_parameterlist_get_next(self)) {
625 
626  const char * envvar;
627  const char * svalue;
628 
629  /* FIXME: Needed ? */
630  if (cpl_parameter_get_default_flag(p)) continue;
631 
632  cpl_msg_debug(cpl_func, __FILE__ " line %u: OK", __LINE__);
633 
634  envvar = cpl_parameter_get_alias(p, CPL_PARAMETER_MODE_ENV);
635  svalue = envvar ? getenv(envvar) : NULL;
636 
637  switch (cpl_parameter_get_type(p)) {
638  case CPL_TYPE_BOOL: {
639  const int value
640  = svalue ? atoi(svalue) : cpl_parameter_get_default_bool(p);
641  cpl_parameter_set_bool(p, value);
642  break;
643  }
644  case CPL_TYPE_INT: {
645  const int value
646  = svalue ? atoi(svalue) : cpl_parameter_get_default_int(p);
647  cpl_parameter_set_int(p, value);
648  break;
649  }
650  case CPL_TYPE_DOUBLE: {
651  const double value
652  = svalue ? atof(svalue) : cpl_parameter_get_default_double(p);
653  cpl_parameter_set_double(p, value);
654  break;
655  }
656  case CPL_TYPE_STRING:
657  {
658  const char * s_default = cpl_parameter_get_default_string(p);
659  /* Replace NULL with "" */
660  const char * value
661  = svalue ? svalue : (s_default ? s_default : "");
662  cpl_parameter_set_string(p, value);
663  break;
664  }
665 
666  default:
667  assert( 0 ); /* It is a testing error to reach this point */
668  }
669  }
670 }
671 
672 
673 /*----------------------------------------------------------------------------*/
683 /*----------------------------------------------------------------------------*/
684 static void recipe_sof_test_devfile(cpl_plugin * plugin, const char * filename,
685  size_t nstr, const char *astr[])
686 {
687  cpl_recipe * recipe = (cpl_recipe*)plugin;
688  int (*recipe_exec) (cpl_plugin *);
689  cpl_frameset * copy;
690  cpl_error_code error;
691  size_t i;
692 
693 
694  if (nstr < 1) return;
695  if (filename == NULL) return;
696 
697  cpl_msg_info(cpl_func, "Testing recipe with %u %s as input ",
698  (unsigned)nstr, filename);
699 
700  for (i = 0; i < nstr; i++) {
701  cpl_frame * f = cpl_frame_new();
702 
703  error = cpl_frame_set_filename(f, filename);
704  cpl_test_eq_error(error, CPL_ERROR_NONE);
705 
706  error = cpl_frame_set_tag(f, astr[i]);
707  cpl_test_eq_error(error, CPL_ERROR_NONE);
708 
709  error = cpl_frameset_insert(recipe->frames, f);
710  cpl_test_eq_error(error, CPL_ERROR_NONE);
711  }
712 
713  copy = cpl_frameset_duplicate(recipe->frames);
714 
715  recipe_exec = cpl_plugin_get_exec(plugin);
716  cpl_test( recipe_exec != NULL);
717 
718  if (recipe_exec != NULL) {
719 
720  /* Call recipe and expect non-zero return code */
721  cpl_test( recipe_exec(plugin) );
722  error = cpl_error_get_code();
723  /* Expect also the CPL error code to be set */
724  cpl_test_error( error );
725  cpl_test( error );
726 
727  recipe_frameset_test_frameset_diff(recipe->frames, copy);
728 
729  recipe_frameset_empty(recipe->frames);
730  }
731 
732  cpl_frameset_delete(copy);
733 
734  return;
735 }
736 
737 /*----------------------------------------------------------------------------*/
744 /*----------------------------------------------------------------------------*/
745 static void recipe_sof_test_image_empty(cpl_plugin * plugin, size_t nstr,
746  const char *astr[])
747 {
748  cpl_recipe * recipe = (cpl_recipe*)plugin;
749  int (*recipe_exec) (cpl_plugin *);
750  cpl_frameset * copy;
751  cpl_error_code error;
752  size_t i;
753  const cpl_frame * frame;
754  cpl_image * iempty;
755  int retstat;
756 
757 
758  if (nstr < 1) return;
759 
760  cpl_msg_info(cpl_func, "Testing recipe with %u empty images as input ",
761  (unsigned)nstr);
762 
763  iempty = cpl_image_new(13, 17, CPL_TYPE_FLOAT);
764  cpl_test_nonnull(iempty);
765 
766  for (i = 0; i < nstr; i++) {
767  cpl_frame * f = cpl_frame_new();
768  char * rawname = cpl_sprintf("%s-raw%05u.fits",
769  cpl_plugin_get_name(plugin),
770  (unsigned)(i+1));
771 
772  error = cpl_image_save(iempty, rawname,CPL_BPP_IEEE_FLOAT, NULL,
773  CPL_IO_DEFAULT);
774  cpl_test_eq_error(error, CPL_ERROR_NONE);
775 
776  error = cpl_frame_set_filename(f, rawname);
777  cpl_test_eq_error(error, CPL_ERROR_NONE);
778 
779  error = cpl_frame_set_tag(f, astr[i]);
780  cpl_test_eq_error(error, CPL_ERROR_NONE);
781 
782  error = cpl_frameset_insert(recipe->frames, f);
783  cpl_test_eq_error(error, CPL_ERROR_NONE);
784 
785  cpl_free(rawname);
786  }
787  cpl_image_delete(iempty);
788 
789  copy = cpl_frameset_duplicate(recipe->frames);
790 
791  recipe_exec = cpl_plugin_get_exec(plugin);
792  cpl_test(recipe_exec != NULL);
793 
794  if (recipe_exec != NULL) {
795  cpl_frameset_iterator * iterator = NULL;
796 
797  /* Call recipe and expect consistency between return code and
798  CPL error */
799 
800  retstat = recipe_exec(plugin);
801  error = cpl_error_get_code();
802  /* Expect also the CPL error code to be set */
803  if (error == 0) {
804  cpl_test_zero(retstat);
805  } else {
806  cpl_test(retstat);
807  }
808  cpl_test_error( error );
809 
810  recipe_frameset_test_frameset_diff(recipe->frames, copy);
811 
812  for (frame = irplib_frameset_get_first_const(&iterator, recipe->frames);
813  frame != NULL;
814  frame = irplib_frameset_get_next_const(iterator))
815  {
816  cpl_test_zero( remove(cpl_frame_get_filename(frame)) );
817  }
818  cpl_frameset_iterator_delete(iterator);
819 
820  recipe_frameset_empty(recipe->frames);
821  }
822 
823  cpl_frameset_delete(copy);
824 
825  return;
826 }
827 
828 
829 /*----------------------------------------------------------------------------*/
837 /*----------------------------------------------------------------------------*/
838 cpl_boolean irplib_plugin_has_sof_from_env(const cpl_plugin * plugin,
839  const char * envname)
840 {
841  const char * recipename = cpl_plugin_get_name(plugin);
842  const char * sof_path = envname ? getenv(envname) : NULL;
843  cpl_frameset * frames;
844  char * sof_name;
845  const cpl_frame * ffirst;
846 
847  cpl_ensure(plugin != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
848  cpl_ensure(envname != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
849  cpl_ensure(recipename != NULL, CPL_ERROR_DATA_NOT_FOUND, CPL_FALSE);
850  cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), CPL_FALSE);
851 
852  if (sof_path == NULL) return CPL_FALSE;
853 
854  sof_name = cpl_sprintf("%s/%s.sof", sof_path, recipename);
855 
856  frames = cpl_frameset_new();
857  recipe_frameset_load(frames, sof_name);
858 
859  ffirst = cpl_frameset_get_position_const(frames, 0);
860 
861  cpl_free(sof_name);
862  cpl_frameset_delete(frames);
863 
864  cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), CPL_FALSE);
865 
866  return ffirst ? CPL_TRUE : CPL_FALSE;
867 
868 }
869 
870 /*----------------------------------------------------------------------------*/
877 /*----------------------------------------------------------------------------*/
878 static void recipe_sof_test_from_env(cpl_plugin * plugin)
879 {
880  cpl_recipe * recipe = (cpl_recipe*)plugin;
881  const char * recipename = cpl_plugin_get_name(plugin);
882  const char * var_name = "RECIPE_SOF_PATH";
883  const char * sof_path = getenv(var_name);
884  cpl_error_code error;
885 
886  char * sof_name;
887 
888  if (sof_path == NULL) {
889  cpl_msg_warning(cpl_func, "Environment variable %s is unset: "
890  "No SOFs to check", var_name);
891  return;
892  }
893 
894  cpl_msg_debug(cpl_func, "Checking for SOFs in %s", sof_path);
895 
896  cpl_test_nonnull( recipename );
897  if (recipename == NULL) return;
898 
899  sof_name = cpl_sprintf("%s/%s.sof", sof_path, recipename);
900 
901  cpl_msg_debug(cpl_func, "Checking for SOF %s", sof_name);
902 
903  recipe_frameset_load(recipe->frames, sof_name);
904 
905  if (!cpl_frameset_is_empty(recipe->frames)) {
906 
907  int (*recipe_exec ) (cpl_plugin *);
908  cpl_frameset * copy = cpl_frameset_duplicate(recipe->frames);
909 
910  recipe_exec = cpl_plugin_get_exec(plugin);
911  cpl_test(recipe_exec != NULL);
912 
913  if (recipe_exec != NULL) {
914  cpl_msg_info(cpl_func,"Checking handling of SOF: %s", sof_name);
915 
916  /* Call recipe and expect zero return code */
917  cpl_test_zero( recipe_exec(plugin) );
918  /* Expect also the CPL error code to be clear */
919  cpl_test_error(CPL_ERROR_NONE);
920 
921  error = cpl_dfs_update_product_header(recipe->frames);
922  cpl_test_eq_error(error, CPL_ERROR_NONE);
923 
924  recipe_frameset_test_frameset_diff(recipe->frames, copy);
925 
926  recipe_frameset_empty(recipe->frames);
927  }
928 
929  cpl_frameset_delete(copy);
930 
931  }
932 
933  cpl_free(sof_name);
934 
935  return;
936 }
937 
938 
939 
940 /*----------------------------------------------------------------------------*/
947 /*----------------------------------------------------------------------------*/
948 static void recipe_sof_test_local(cpl_plugin * plugin)
949 {
950  cpl_recipe * recipe = (cpl_recipe*)plugin;
951  const char * recipename = cpl_plugin_get_name(plugin);
952  cpl_error_code error;
953  char * sof_name = cpl_sprintf("%s.sof", recipename);
954 
955  cpl_msg_debug(cpl_func, "Checking for SOF %s", sof_name);
956 
957  recipe_frameset_load(recipe->frames, sof_name);
958 
959  if (!cpl_frameset_is_empty(recipe->frames)) {
960 
961  int (*recipe_exec ) (cpl_plugin *);
962  cpl_frameset * copy = cpl_frameset_duplicate(recipe->frames);
963 
964  recipe_exec = cpl_plugin_get_exec(plugin);
965  cpl_test(recipe_exec != NULL);
966 
967  if (recipe_exec != NULL) {
968 
969  cpl_msg_info(cpl_func,"Checking handling of SOF: %s", sof_name);
970 
971  /* Call recipe and expect zero return code */
972  cpl_test_zero( recipe_exec(plugin) );
973  /* Expect also the CPL error code to be clear */
974  cpl_test_error(CPL_ERROR_NONE);
975 
976  error = cpl_dfs_update_product_header(recipe->frames);
977  cpl_test_eq_error( error, CPL_ERROR_NONE );
978 
979  recipe_frameset_test_frameset_diff(recipe->frames, copy);
980 
981  recipe_frameset_empty(recipe->frames);
982  }
983 
984  cpl_frameset_delete(copy);
985  }
986 
987  cpl_free(sof_name);
988 
989  return;
990 }
991 
992 
993 
994 
995 /**********************************************************************/
1009 /**********************************************************************/
1010 
1011 static void recipe_frameset_load(cpl_frameset * set, const char *name)
1012 {
1013 
1014  FILE *fp;
1015  char line[LINE_LEN_MAX];
1016  char path[LINE_LEN_MAX], group[LINE_LEN_MAX], tag[LINE_LEN_MAX];
1017  int line_number;
1018 
1019  assert( set != NULL );
1020  assert( name != NULL );
1021 
1022  fp = fopen(name, "r");
1023  if (fp == NULL) {
1024  cpl_msg_debug(cpl_func, "Unable to open SOF file '%s'", name);
1025  return;
1026  }
1027 
1028  /* Loop over all the lines in the set-of-frames file */
1029  for (line_number = 0; fgets(line, LINE_LEN_MAX - 1, fp); line_number++) {
1030 
1031  char scan_fmt[50];
1032  cpl_frame_group grp;
1033  cpl_frame * frame;
1034  int n;
1035 
1036  if (line[0] == '#') continue;
1037 
1038  snprintf(scan_fmt, 49, "%%%ds %%%ds %%%ds", LINE_LEN_MAX - 1,
1039  LINE_LEN_MAX - 1, LINE_LEN_MAX - 1);
1040  n = sscanf(line, scan_fmt, path, tag, group);
1041 
1042  if (n < 1) {
1043  cpl_msg_warning(cpl_func, "Spurious line no. %d in %s: %s",
1044  line_number, name, line);
1045  break;
1046  }
1047 
1048  /* Allocate a new frame */
1049  frame = cpl_frame_new();
1050 
1051  /* Set the filename component of the frame */
1052  cpl_frame_set_filename(frame, path);
1053 
1054  /* Set the tag component of the frame (or set a default) */
1055  cpl_frame_set_tag(frame, n == 1 ? "" : tag);
1056 
1057  cpl_frameset_insert(set, frame);
1058 
1059  /* Set the group component of the frame (or set a default) */
1060  if (n < 3) continue;
1061 
1062  if (!strcmp(group, CPL_FRAME_GROUP_RAW_ID))
1063  grp = CPL_FRAME_GROUP_RAW;
1064  else if (!strcmp(group, CPL_FRAME_GROUP_CALIB_ID))
1065  grp = CPL_FRAME_GROUP_CALIB;
1066  else if (!strcmp(group, CPL_FRAME_GROUP_PRODUCT_ID))
1067  grp = CPL_FRAME_GROUP_PRODUCT;
1068  else
1069  grp = CPL_FRAME_GROUP_NONE;
1070 
1071  cpl_frame_set_group(frame, grp);
1072  }
1073 
1074  fclose(fp);
1075 
1076  return;
1077 
1078 }
1079 
1080 
1081 /*----------------------------------------------------------------------------*/
1091 /*----------------------------------------------------------------------------*/
1092 static
1093 const cpl_parameter * irplib_parameterlist_get(const cpl_parameterlist * self,
1094  const char * instrume,
1095  const char * recipe,
1096  const char * parameter)
1097 {
1098 
1099  char * paramname;
1100  const cpl_parameter * par;
1101 
1102 
1103  cpl_ensure(instrume != NULL, CPL_ERROR_NULL_INPUT, NULL);
1104  cpl_ensure(recipe != NULL, CPL_ERROR_NULL_INPUT, NULL);
1105  cpl_ensure(parameter != NULL, CPL_ERROR_NULL_INPUT, NULL);
1106 
1107  paramname = cpl_sprintf("%s.%s.%s", instrume, recipe, parameter);
1108 
1109  par = cpl_parameterlist_find_const(self, paramname);
1110 
1111  if (par == NULL) (void)cpl_error_set_message(cpl_func,
1112  cpl_error_get_code()
1113  ? cpl_error_get_code()
1114  : CPL_ERROR_DATA_NOT_FOUND,
1115  "%s", paramname);
1116 
1117  cpl_free(paramname);
1118 
1119  return par;
1120 
1121 }
1122 
1123 
1124 /*----------------------------------------------------------------------------*/
1150 /*----------------------------------------------------------------------------*/
1151 static void recipe_frameset_empty(cpl_frameset * self)
1152 {
1153  cpl_size i, n;
1154 
1155  if (self == NULL) {
1156  cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
1157  return;
1158  }
1159 
1160  n = cpl_frameset_get_size(self);
1161  for (i = 0; i < n; ++i)
1162  {
1163  cpl_frame * f = cpl_frameset_get_position(self, n-1-i);
1164  cpl_frameset_erase_frame(self, f);
1165  }
1166 }
1167 
1168 
1169 /*----------------------------------------------------------------------------*/
1189 /*----------------------------------------------------------------------------*/
1190 static void recipe_frameset_test_frame(const cpl_frame * self)
1191 {
1192 
1193  cpl_msg_info(cpl_func, "Validating new frame: %s",
1194  cpl_frame_get_filename(self));
1195 
1196  cpl_test_nonnull(self);
1197 
1198  /* Frame must be tagged */
1199  cpl_test_nonnull(cpl_frame_get_tag(self));
1200 
1201  /* New frames must be products */
1202  cpl_test_eq(cpl_frame_get_group(self), CPL_FRAME_GROUP_PRODUCT);
1203 
1204  if (cpl_frame_get_type(self) != CPL_FRAME_TYPE_PAF) {
1205  /* All but PAF (?) must be FITS */
1206  cpl_test_fits(cpl_frame_get_filename(self));
1207  } else {
1208  /* Frame must at least have a filename */
1209  cpl_test_nonnull(cpl_frame_get_filename(self));
1210  }
1211 }
1212 
1213 /*----------------------------------------------------------------------------*/
1234 /*----------------------------------------------------------------------------*/
1235 static void recipe_frameset_test_frameset_diff(const cpl_frameset * self,
1236  const cpl_frameset * other)
1237 {
1238 
1239  cpl_frameset_iterator * it1 = NULL;
1240  cpl_frameset_iterator * it2 = NULL;
1241  const cpl_frame * frame = irplib_frameset_get_first_const(&it2, other);
1242 
1243  /* First verify that filenames in other are non-NULL */
1244  for (;frame != NULL; frame = irplib_frameset_get_next_const(it2)) {
1245  const char * file = cpl_frame_get_filename(frame);
1246 
1247  if (file == NULL) {
1248  cpl_test_nonnull(cpl_frame_get_filename(frame));
1249  break;
1250  }
1251  }
1252  cpl_frameset_iterator_delete(it2);
1253  it2 = NULL;
1254  if (frame != NULL) return;
1255 
1256  frame = irplib_frameset_get_first_const(&it1, self);
1257 
1258  for (;frame != NULL; frame = irplib_frameset_get_next_const(it1)) {
1259  const cpl_frame * cmp;
1260  const char * file = cpl_frame_get_filename(frame);
1261 
1262  if (file == NULL) {
1263  cpl_test_nonnull(cpl_frame_get_filename(frame));
1264  continue;
1265  }
1266 
1267  cmp = irplib_frameset_get_first_const(&it2, other);
1268  for (;cmp != NULL; cmp = irplib_frameset_get_next_const(it2)) {
1269  const char * cfile = cpl_frame_get_filename(cmp);
1270 
1271  if (!strcmp(file, cfile)) break;
1272 
1273  }
1274  cpl_frameset_iterator_delete(it2);
1275  it2 = NULL;
1276  if (cmp == NULL) {
1277  /* frame is new */
1278 
1279  cpl_test_eq(cpl_frame_get_group(frame), CPL_FRAME_GROUP_PRODUCT);
1280  recipe_frameset_test_frame(frame);
1281  }
1282  }
1283 
1284  cpl_frameset_iterator_delete(it1);
1285 }