SINFONI Pipeline Reference Manual  2.6.0
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  const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
130  recipe, parameter);
131 
132  if (par == NULL) {
133 
134  (void)cpl_error_set_where(cpl_func);
135 
136  return NULL;
137  } else {
138  const char * value = cpl_parameter_get_string(par);
139 
140  if (value == NULL) (void)cpl_error_set_where(cpl_func);
141 
142  return value;
143  }
144 }
145 
146 /*----------------------------------------------------------------------------*/
156 /*----------------------------------------------------------------------------*/
157 cpl_boolean irplib_parameterlist_get_bool(const cpl_parameterlist * self,
158  const char * instrume,
159  const char * recipe,
160  const char * parameter)
161 {
162  const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
163  recipe, parameter);
164 
165  if (par == NULL) {
166 
167  (void)cpl_error_set_where(cpl_func);
168 
169  return CPL_FALSE;
170  } else {
171  cpl_errorstate prestate = cpl_errorstate_get();
172  const cpl_boolean value = cpl_parameter_get_bool(par);
173 
174  if (!cpl_errorstate_is_equal(prestate))
175  (void)cpl_error_set_where(cpl_func);
176 
177  return value;
178  }
179 }
180 
181 
182 /*----------------------------------------------------------------------------*/
192 /*----------------------------------------------------------------------------*/
193 int irplib_parameterlist_get_int(const cpl_parameterlist * self,
194  const char * instrume,
195  const char * recipe,
196  const char * parameter)
197 {
198  const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
199  recipe, parameter);
200 
201  if (par == NULL) {
202 
203  (void)cpl_error_set_where(cpl_func);
204 
205  return 0;
206  } else {
207  cpl_errorstate prestate = cpl_errorstate_get();
208  const int value = cpl_parameter_get_int(par);
209 
210  if (!cpl_errorstate_is_equal(prestate))
211  (void)cpl_error_set_where(cpl_func);
212 
213  return value;
214  }
215 }
216 
217 /*----------------------------------------------------------------------------*/
227 /*----------------------------------------------------------------------------*/
228 double irplib_parameterlist_get_double(const cpl_parameterlist * self,
229  const char * instrume,
230  const char * recipe,
231  const char * parameter)
232 {
233  const cpl_parameter * par = irplib_parameterlist_get(self, instrume,
234  recipe, parameter);
235 
236  if (par == NULL) {
237 
238  (void)cpl_error_set_where(cpl_func);
239 
240  return 0.0;
241  } else {
242  cpl_errorstate prestate = cpl_errorstate_get();
243  const double value = cpl_parameter_get_double(par);
244 
245  if (!cpl_errorstate_is_equal(prestate))
246  (void)cpl_error_set_where(cpl_func);
247 
248  return value;
249  }
250 }
251 
252 /*----------------------------------------------------------------------------*/
266 /*----------------------------------------------------------------------------*/
267 cpl_error_code irplib_parameterlist_set_string(cpl_parameterlist * self,
268  const char * instrume,
269  const char * recipe,
270  const char * parameter,
271  const char * defvalue,
272  const char * alias,
273  const char * context,
274  const char * man)
275 {
276 
277  cpl_error_code error;
278  cpl_parameter * par;
279  char * paramname = cpl_sprintf("%s.%s.%s", instrume, recipe,
280  parameter);
281 
282  cpl_ensure_code(paramname != NULL, cpl_error_get_code());
283 
284  par = cpl_parameter_new_value(paramname, CPL_TYPE_STRING, man, context,
285  defvalue);
286  cpl_free(paramname);
287 
288  cpl_ensure_code(par != NULL, cpl_error_get_code());
289 
290  error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
291  alias ? alias : parameter);
292  cpl_ensure_code(!error, error);
293 
294  error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
295  cpl_ensure_code(!error, error);
296 
297  error = cpl_parameterlist_append(self, par);
298  cpl_ensure_code(!error, error);
299 
300  return CPL_ERROR_NONE;
301 }
302 
303 
304 /*----------------------------------------------------------------------------*/
318 /*----------------------------------------------------------------------------*/
319 cpl_error_code irplib_parameterlist_set_bool(cpl_parameterlist * self,
320  const char * instrume,
321  const char * recipe,
322  const char * parameter,
323  cpl_boolean defvalue,
324  const char * alias,
325  const char * context,
326  const char * man)
327 {
328 
329  cpl_error_code error;
330  cpl_parameter * par;
331  char * paramname = cpl_sprintf("%s.%s.%s", instrume, recipe,
332  parameter);
333 
334  cpl_ensure_code(paramname != NULL, cpl_error_get_code());
335 
336  par = cpl_parameter_new_value(paramname, CPL_TYPE_BOOL, man, context,
337  defvalue);
338  cpl_free(paramname);
339 
340  cpl_ensure_code(par != NULL, cpl_error_get_code());
341 
342  error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
343  alias ? alias : parameter);
344  cpl_ensure_code(!error, error);
345 
346  error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
347  cpl_ensure_code(!error, error);
348 
349  error = cpl_parameterlist_append(self, par);
350  cpl_ensure_code(!error, error);
351 
352  return CPL_ERROR_NONE;
353 }
354 
355 
356 
357 /*----------------------------------------------------------------------------*/
371 /*----------------------------------------------------------------------------*/
372 cpl_error_code irplib_parameterlist_set_int(cpl_parameterlist * self,
373  const char * instrume,
374  const char * recipe,
375  const char * parameter,
376  int defvalue,
377  const char * alias,
378  const char * context,
379  const char * man)
380 {
381 
382  cpl_error_code error;
383  cpl_parameter * par;
384  char * paramname = cpl_sprintf("%s.%s.%s", instrume, recipe,
385  parameter);
386 
387  cpl_ensure_code(paramname != NULL, cpl_error_get_code());
388 
389  par = cpl_parameter_new_value(paramname, CPL_TYPE_INT, man, context,
390  defvalue);
391  cpl_free(paramname);
392 
393  cpl_ensure_code(par != NULL, cpl_error_get_code());
394 
395  error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
396  alias ? alias : parameter);
397  cpl_ensure_code(!error, error);
398 
399  error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
400  cpl_ensure_code(!error, error);
401 
402  error = cpl_parameterlist_append(self, par);
403  cpl_ensure_code(!error, error);
404 
405  return CPL_ERROR_NONE;
406 }
407 
408 
409 /*----------------------------------------------------------------------------*/
423 /*----------------------------------------------------------------------------*/
424 cpl_error_code irplib_parameterlist_set_double(cpl_parameterlist * self,
425  const char * instrume,
426  const char * recipe,
427  const char * parameter,
428  double defvalue,
429  const char * alias,
430  const char * context,
431  const char * man)
432 {
433 
434  cpl_error_code error;
435  cpl_parameter * par;
436  char * paramname = cpl_sprintf("%s.%s.%s", instrume, recipe,
437  parameter);
438 
439  cpl_ensure_code(paramname != NULL, cpl_error_get_code());
440 
441  par = cpl_parameter_new_value(paramname, CPL_TYPE_DOUBLE, man, context,
442  defvalue);
443  cpl_free(paramname);
444 
445  cpl_ensure_code(par != NULL, cpl_error_get_code());
446 
447  error = cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
448  alias ? alias : parameter);
449  cpl_ensure_code(!error, error);
450 
451  error = cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
452  cpl_ensure_code(!error, error);
453 
454  error = cpl_parameterlist_append(self, par);
455  cpl_ensure_code(!error, error);
456 
457  return CPL_ERROR_NONE;
458 }
459 
460 
461 /*----------------------------------------------------------------------------*/
475 /*----------------------------------------------------------------------------*/
476 int irplib_plugin_test(cpl_pluginlist * self, size_t nstr, const char *astr[]) {
477 
478  cpl_plugin * plugin;
479  int (*recipe_create) (cpl_plugin *);
480  int (*recipe_exec ) (cpl_plugin *);
481  int (*recipe_deinit) (cpl_plugin *);
482  FILE * stream;
483  cpl_boolean is_debug;
484 
485 
486  is_debug = cpl_msg_get_level() <= CPL_MSG_DEBUG ? CPL_TRUE : CPL_FALSE;
487 
488  /* Modified from CPL unit tests */
489  stream = is_debug ? stdout : fopen("/dev/null", "a");
490 
491  inistate = cpl_errorstate_get();
492 
493  assert( nstr == 0 || astr != NULL );
494 
495  plugin = cpl_pluginlist_get_first(self);
496 
497  if (plugin == NULL) {
498  cpl_msg_warning(cpl_func, "With an empty pluginlist, "
499  "no tests can be made");
500  return 0;
501  }
502 
503  cpl_plugin_dump(plugin, stream);
504 
505  recipe_create = cpl_plugin_get_init(plugin);
506  cpl_test( recipe_create != NULL);
507 
508  recipe_exec = cpl_plugin_get_exec(plugin);
509  cpl_test( recipe_exec != NULL);
510 
511  recipe_deinit = cpl_plugin_get_deinit(plugin);
512  cpl_test( recipe_deinit != NULL);
513 
514  /* Only plugins of type recipe are tested (further) */
515  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
516  cpl_msg_warning(cpl_func, "This plugin is not of type recipe, "
517  "cannot test further");
518  return 0;
519  }
520 
521  if (recipe_create != NULL && recipe_exec != NULL && recipe_deinit != NULL) {
522 
523  cpl_error_code error;
524  cpl_recipe * recipe;
525 
526  cpl_test_zero(recipe_create(plugin));
527 
528  recipe = (cpl_recipe *) plugin;
529 
530  cpl_test_nonnull( recipe->parameters );
531 
532  recipe_parameterlist_set(recipe->parameters);
533 
534  cpl_parameterlist_dump(recipe->parameters, stream);
535 
536  recipe->frames = cpl_frameset_new();
537 
538  if (irplib_plugin_has_sof_from_env(plugin, "RECIPE_SOF_PATH")) {
539 
540  recipe_sof_test_from_env(plugin);
541 
542  } else {
543 
544  const cpl_msg_severity msg_level = cpl_msg_get_level();
545 
546  /* Unless the CPL_MSG_LEVEL has been explicitly set, turn off
547  terminal messaging completely while inside this function */
548  if (getenv("CPL_MSG_LEVEL") == NULL) cpl_msg_set_level(CPL_MSG_OFF);
549 
550  cpl_msg_info(cpl_func,"Checking handling of pre-existing CPL error "
551  "state - may produce warning(s)/error(s):");
552  cpl_error_set(cpl_func, CPL_ERROR_EOL);
553  /* Call recipe and expect non-zero return code */
554  cpl_test( recipe_exec(plugin) );
555  /* Expect also the CPL error code to be preserved */
556  cpl_test_error( CPL_ERROR_EOL );
557 
558  cpl_msg_info(cpl_func,"Checking handling of empty frameset - "
559  "may produce warning(s)/error(s):");
560  /* Call recipe and expect non-zero return code */
561  cpl_test( recipe_exec(plugin) );
562  error = cpl_error_get_code();
563  /* Expect also the CPL error code to be set */
564  cpl_test_error( error );
565  cpl_test( error );
566 
567  cpl_msg_info(cpl_func,"Checking handling of dummy frameset - "
568  "may produce warning(s)/error(s):");
569  do {
570  cpl_frame * f = cpl_frame_new();
571  error = cpl_frame_set_filename(f, "/dev/null");
572  cpl_test_eq_error(error, CPL_ERROR_NONE);
573  error = cpl_frame_set_tag(f, "RECIPE_DUMMY_TAG");
574  cpl_test_eq_error(error, CPL_ERROR_NONE);
575  error = cpl_frameset_insert(recipe->frames, f);
576  cpl_test_eq_error(error, CPL_ERROR_NONE);
577 
578  /* Call recipe and expect non-zero return code */
579  cpl_test( recipe_exec(plugin) );
580  error = cpl_error_get_code();
581  /* Expect also the CPL error code to be set */
582  cpl_test_error( error );
583  cpl_test( error );
584 
585  error = cpl_frameset_erase_frame(recipe->frames, f);
586  cpl_test_eq_error(error, CPL_ERROR_NONE);
587 
588  } while (0);
589 
590 #ifdef IRPLIB_TEST_RANDOM_SOF
591  recipe_sof_test_devfile(plugin, DEV_RANDOM, nstr, astr);
592 #endif
593 
594  recipe_sof_test_devfile(plugin, "/dev/null", nstr, astr);
595 
596  recipe_sof_test_devfile(plugin, ".", nstr, astr);
597 
598  recipe_sof_test_image_empty(plugin, nstr, astr);
599 
600  recipe_sof_test_local(plugin);
601 
602  cpl_msg_set_level(msg_level);
603 
604  }
605 
606  cpl_frameset_delete(recipe->frames);
607 
608  error = recipe_deinit(plugin);
609  cpl_test_eq_error(error, CPL_ERROR_NONE);
610  }
611 
612  if (stream != stdout) fclose(stream);
613 
614  return 0;
615 }
616 
619 /*----------------------------------------------------------------------------*/
629 /*----------------------------------------------------------------------------*/
630 static void recipe_parameterlist_set(cpl_parameterlist * self)
631 {
632 
633  cpl_parameter * p = cpl_parameterlist_get_first(self);
634 
635  for (; p != NULL; p = cpl_parameterlist_get_next(self)) {
636 
637  const char * envvar;
638  const char * svalue;
639 
640  /* FIXME: Needed ? */
641  if (cpl_parameter_get_default_flag(p)) continue;
642 
643  cpl_msg_debug(cpl_func, __FILE__ " line %u: OK", __LINE__);
644 
645  envvar = cpl_parameter_get_alias(p, CPL_PARAMETER_MODE_ENV);
646  svalue = envvar ? getenv(envvar) : NULL;
647 
648  switch (cpl_parameter_get_type(p)) {
649  case CPL_TYPE_BOOL: {
650  const int value
651  = svalue ? atoi(svalue) : cpl_parameter_get_default_bool(p);
652  cpl_parameter_set_bool(p, value);
653  break;
654  }
655  case CPL_TYPE_INT: {
656  const int value
657  = svalue ? atoi(svalue) : cpl_parameter_get_default_int(p);
658  cpl_parameter_set_int(p, value);
659  break;
660  }
661  case CPL_TYPE_DOUBLE: {
662  const double value
663  = svalue ? atof(svalue) : cpl_parameter_get_default_double(p);
664  cpl_parameter_set_double(p, value);
665  break;
666  }
667  case CPL_TYPE_STRING:
668  {
669  const char * s_default = cpl_parameter_get_default_string(p);
670  /* Replace NULL with "" */
671  const char * value
672  = svalue ? svalue : (s_default ? s_default : "");
673  cpl_parameter_set_string(p, value);
674  break;
675  }
676 
677  default:
678  assert( 0 ); /* It is a testing error to reach this point */
679  }
680  }
681 }
682 
683 
684 /*----------------------------------------------------------------------------*/
694 /*----------------------------------------------------------------------------*/
695 static void recipe_sof_test_devfile(cpl_plugin * plugin, const char * filename,
696  size_t nstr, const char *astr[])
697 {
698  cpl_recipe * recipe = (cpl_recipe*)plugin;
699  int (*recipe_exec) (cpl_plugin *);
700  cpl_frameset * copy;
701  cpl_error_code error;
702  size_t i;
703 
704 
705  if (nstr < 1) return;
706  if (filename == NULL) return;
707 
708  cpl_msg_info(cpl_func, "Testing recipe with %u %s as input ",
709  (unsigned)nstr, filename);
710 
711  for (i = 0; i < nstr; i++) {
712  cpl_frame * f = cpl_frame_new();
713 
714  error = cpl_frame_set_filename(f, filename);
715  cpl_test_eq_error(error, CPL_ERROR_NONE);
716 
717  error = cpl_frame_set_tag(f, astr[i]);
718  cpl_test_eq_error(error, CPL_ERROR_NONE);
719 
720  error = cpl_frameset_insert(recipe->frames, f);
721  cpl_test_eq_error(error, CPL_ERROR_NONE);
722  }
723 
724  copy = cpl_frameset_duplicate(recipe->frames);
725 
726  recipe_exec = cpl_plugin_get_exec(plugin);
727  cpl_test( recipe_exec != NULL);
728 
729  if (recipe_exec != NULL) {
730 
731  /* Call recipe and expect non-zero return code */
732  cpl_test( recipe_exec(plugin) );
733  error = cpl_error_get_code();
734  /* Expect also the CPL error code to be set */
735  cpl_test_error( error );
736  cpl_test( error );
737 
738  recipe_frameset_test_frameset_diff(recipe->frames, copy);
739 
740  recipe_frameset_empty(recipe->frames);
741  }
742 
743  cpl_frameset_delete(copy);
744 
745  return;
746 }
747 
748 /*----------------------------------------------------------------------------*/
755 /*----------------------------------------------------------------------------*/
756 static void recipe_sof_test_image_empty(cpl_plugin * plugin, size_t nstr,
757  const char *astr[])
758 {
759  cpl_recipe * recipe = (cpl_recipe*)plugin;
760  int (*recipe_exec) (cpl_plugin *);
761  cpl_frameset * copy;
762  cpl_error_code error;
763  size_t i;
764  cpl_image * iempty;
765 
766 
767  if (nstr < 1) return;
768 
769  cpl_msg_info(cpl_func, "Testing recipe with %u empty images as input ",
770  (unsigned)nstr);
771 
772  iempty = cpl_image_new(13, 17, CPL_TYPE_FLOAT);
773  cpl_test_nonnull(iempty);
774 
775  for (i = 0; i < nstr; i++) {
776  cpl_frame * f = cpl_frame_new();
777  char * rawname = cpl_sprintf("%s-raw%05u.fits",
778  cpl_plugin_get_name(plugin),
779  (unsigned)(i+1));
780 
781  error = cpl_image_save(iempty, rawname,CPL_BPP_IEEE_FLOAT, NULL,
782  CPL_IO_DEFAULT);
783  cpl_test_eq_error(error, CPL_ERROR_NONE);
784 
785  error = cpl_frame_set_filename(f, rawname);
786  cpl_test_eq_error(error, CPL_ERROR_NONE);
787 
788  error = cpl_frame_set_tag(f, astr[i]);
789  cpl_test_eq_error(error, CPL_ERROR_NONE);
790 
791  error = cpl_frameset_insert(recipe->frames, f);
792  cpl_test_eq_error(error, CPL_ERROR_NONE);
793 
794  cpl_free(rawname);
795  }
796  cpl_image_delete(iempty);
797 
798  copy = cpl_frameset_duplicate(recipe->frames);
799 
800  recipe_exec = cpl_plugin_get_exec(plugin);
801  cpl_test(recipe_exec != NULL);
802 
803  if (recipe_exec != NULL) {
804  const cpl_frame * frame;
805  cpl_frameset_iterator * iterator = NULL;
806  int retstat;
807 
808  /* Call recipe and expect consistency between return code and
809  CPL error */
810 
811  retstat = recipe_exec(plugin);
812  error = cpl_error_get_code();
813  /* Expect also the CPL error code to be set */
814  if (error == 0) {
815  cpl_test_zero(retstat);
816  } else {
817  cpl_test(retstat);
818  }
819  cpl_test_error( error );
820 
821  recipe_frameset_test_frameset_diff(recipe->frames, copy);
822 
823  for (frame = irplib_frameset_get_first_const(&iterator, recipe->frames);
824  frame != NULL;
825  frame = irplib_frameset_get_next_const(iterator))
826  {
827  cpl_test_zero( remove(cpl_frame_get_filename(frame)) );
828  }
829  cpl_frameset_iterator_delete(iterator);
830 
831  recipe_frameset_empty(recipe->frames);
832  }
833 
834  cpl_frameset_delete(copy);
835 
836  return;
837 }
838 
839 
840 /*----------------------------------------------------------------------------*/
848 /*----------------------------------------------------------------------------*/
849 cpl_boolean irplib_plugin_has_sof_from_env(const cpl_plugin * plugin,
850  const char * envname)
851 {
852  const char * recipename = cpl_plugin_get_name(plugin);
853  const char * sof_path = envname ? getenv(envname) : NULL;
854  cpl_frameset * frames;
855  char * sof_name;
856  const cpl_frame * ffirst;
857 
858  cpl_ensure(plugin != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
859  cpl_ensure(envname != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
860  cpl_ensure(recipename != NULL, CPL_ERROR_DATA_NOT_FOUND, CPL_FALSE);
861  cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), CPL_FALSE);
862 
863  if (sof_path == NULL) return CPL_FALSE;
864 
865  sof_name = cpl_sprintf("%s/%s.sof", sof_path, recipename);
866 
867  frames = cpl_frameset_new();
868  recipe_frameset_load(frames, sof_name);
869 
870  ffirst = cpl_frameset_get_position_const(frames, 0);
871 
872  cpl_free(sof_name);
873  cpl_frameset_delete(frames);
874 
875  cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), CPL_FALSE);
876 
877  return ffirst ? CPL_TRUE : CPL_FALSE;
878 
879 }
880 
881 /*----------------------------------------------------------------------------*/
888 /*----------------------------------------------------------------------------*/
889 static void recipe_sof_test_from_env(cpl_plugin * plugin)
890 {
891  cpl_recipe * recipe = (cpl_recipe*)plugin;
892  const char * recipename = cpl_plugin_get_name(plugin);
893  const char * var_name = "RECIPE_SOF_PATH";
894  const char * sof_path = getenv(var_name);
895 
896  char * sof_name;
897 
898  if (sof_path == NULL) {
899  cpl_msg_warning(cpl_func, "Environment variable %s is unset: "
900  "No SOFs to check", var_name);
901  return;
902  }
903 
904  cpl_msg_debug(cpl_func, "Checking for SOFs in %s", sof_path);
905 
906  cpl_test_nonnull( recipename );
907  if (recipename == NULL) return;
908 
909  sof_name = cpl_sprintf("%s/%s.sof", sof_path, recipename);
910 
911  cpl_msg_debug(cpl_func, "Checking for SOF %s", sof_name);
912 
913  recipe_frameset_load(recipe->frames, sof_name);
914 
915  if (!cpl_frameset_is_empty(recipe->frames)) {
916 
917  int (*recipe_exec ) (cpl_plugin *);
918  cpl_frameset * copy = cpl_frameset_duplicate(recipe->frames);
919 
920  recipe_exec = cpl_plugin_get_exec(plugin);
921  cpl_test(recipe_exec != NULL);
922 
923  if (recipe_exec != NULL) {
924  cpl_error_code error;
925  cpl_msg_info(cpl_func,"Checking handling of SOF: %s", sof_name);
926 
927  /* Call recipe and expect zero return code */
928  cpl_test_zero( recipe_exec(plugin) );
929  /* Expect also the CPL error code to be clear */
930  cpl_test_error(CPL_ERROR_NONE);
931 
932  error = cpl_dfs_update_product_header(recipe->frames);
933  cpl_test_eq_error(error, CPL_ERROR_NONE);
934 
935  recipe_frameset_test_frameset_diff(recipe->frames, copy);
936 
937  recipe_frameset_empty(recipe->frames);
938  }
939 
940  cpl_frameset_delete(copy);
941 
942  }
943 
944  cpl_free(sof_name);
945 
946  return;
947 }
948 
949 
950 
951 /*----------------------------------------------------------------------------*/
958 /*----------------------------------------------------------------------------*/
959 static void recipe_sof_test_local(cpl_plugin * plugin)
960 {
961  cpl_recipe * recipe = (cpl_recipe*)plugin;
962  const char * recipename = cpl_plugin_get_name(plugin);
963  char * sof_name = cpl_sprintf("%s.sof", recipename);
964 
965  cpl_msg_debug(cpl_func, "Checking for SOF %s", sof_name);
966 
967  recipe_frameset_load(recipe->frames, sof_name);
968 
969  if (!cpl_frameset_is_empty(recipe->frames)) {
970 
971  int (*recipe_exec ) (cpl_plugin *);
972  cpl_frameset * copy = cpl_frameset_duplicate(recipe->frames);
973 
974  recipe_exec = cpl_plugin_get_exec(plugin);
975  cpl_test(recipe_exec != NULL);
976 
977  if (recipe_exec != NULL) {
978  cpl_error_code error;
979 
980  cpl_msg_info(cpl_func,"Checking handling of SOF: %s", sof_name);
981 
982  /* Call recipe and expect zero return code */
983  cpl_test_zero( recipe_exec(plugin) );
984  /* Expect also the CPL error code to be clear */
985  cpl_test_error(CPL_ERROR_NONE);
986 
987  error = cpl_dfs_update_product_header(recipe->frames);
988  cpl_test_eq_error( error, CPL_ERROR_NONE );
989 
990  recipe_frameset_test_frameset_diff(recipe->frames, copy);
991 
992  recipe_frameset_empty(recipe->frames);
993  }
994 
995  cpl_frameset_delete(copy);
996  }
997 
998  cpl_free(sof_name);
999 
1000  return;
1001 }
1002 
1003 
1004 
1005 
1006 /**********************************************************************/
1020 /**********************************************************************/
1021 
1022 static void recipe_frameset_load(cpl_frameset * set, const char *name)
1023 {
1024 
1025  FILE *fp;
1026  char line[LINE_LEN_MAX];
1027  char path[LINE_LEN_MAX], group[LINE_LEN_MAX], tag[LINE_LEN_MAX];
1028  int line_number;
1029 
1030  assert( set != NULL );
1031  assert( name != NULL );
1032 
1033  fp = fopen(name, "r");
1034  if (fp == NULL) {
1035  cpl_msg_debug(cpl_func, "Unable to open SOF file '%s'", name);
1036  return;
1037  }
1038 
1039  /* Loop over all the lines in the set-of-frames file */
1040  for (line_number = 0; fgets(line, LINE_LEN_MAX - 1, fp); line_number++) {
1041 
1042  char scan_fmt[50];
1043  cpl_frame_group grp;
1044  cpl_frame * frame;
1045  int n;
1046 
1047  if (line[0] == '#') continue;
1048 
1049  snprintf(scan_fmt, 49, "%%%ds %%%ds %%%ds", LINE_LEN_MAX - 1,
1050  LINE_LEN_MAX - 1, LINE_LEN_MAX - 1);
1051  n = sscanf(line, scan_fmt, path, tag, group);
1052 
1053  if (n < 1) {
1054  cpl_msg_warning(cpl_func, "Spurious line no. %d in %s: %s",
1055  line_number, name, line);
1056  break;
1057  }
1058 
1059  /* Allocate a new frame */
1060  frame = cpl_frame_new();
1061 
1062  /* Set the filename component of the frame */
1063  cpl_frame_set_filename(frame, path);
1064 
1065  /* Set the tag component of the frame (or set a default) */
1066  cpl_frame_set_tag(frame, n == 1 ? "" : tag);
1067 
1068  cpl_frameset_insert(set, frame);
1069 
1070  /* Set the group component of the frame (or set a default) */
1071  if (n < 3) continue;
1072 
1073  if (!strcmp(group, CPL_FRAME_GROUP_RAW_ID))
1074  grp = CPL_FRAME_GROUP_RAW;
1075  else if (!strcmp(group, CPL_FRAME_GROUP_CALIB_ID))
1076  grp = CPL_FRAME_GROUP_CALIB;
1077  else if (!strcmp(group, CPL_FRAME_GROUP_PRODUCT_ID))
1078  grp = CPL_FRAME_GROUP_PRODUCT;
1079  else
1080  grp = CPL_FRAME_GROUP_NONE;
1081 
1082  cpl_frame_set_group(frame, grp);
1083  }
1084 
1085  fclose(fp);
1086 
1087  return;
1088 
1089 }
1090 
1091 
1092 /*----------------------------------------------------------------------------*/
1102 /*----------------------------------------------------------------------------*/
1103 static
1104 const cpl_parameter * irplib_parameterlist_get(const cpl_parameterlist * self,
1105  const char * instrume,
1106  const char * recipe,
1107  const char * parameter)
1108 {
1109 
1110  char * paramname;
1111  const cpl_parameter * par;
1112 
1113 
1114  cpl_ensure(instrume != NULL, CPL_ERROR_NULL_INPUT, NULL);
1115  cpl_ensure(recipe != NULL, CPL_ERROR_NULL_INPUT, NULL);
1116  cpl_ensure(parameter != NULL, CPL_ERROR_NULL_INPUT, NULL);
1117 
1118  paramname = cpl_sprintf("%s.%s.%s", instrume, recipe, parameter);
1119 
1120  par = cpl_parameterlist_find_const(self, paramname);
1121 
1122  if (par == NULL) (void)cpl_error_set_message(cpl_func,
1123  cpl_error_get_code()
1124  ? cpl_error_get_code()
1125  : CPL_ERROR_DATA_NOT_FOUND,
1126  "%s", paramname);
1127 
1128  cpl_free(paramname);
1129 
1130  return par;
1131 
1132 }
1133 
1134 
1135 /*----------------------------------------------------------------------------*/
1161 /*----------------------------------------------------------------------------*/
1162 static void recipe_frameset_empty(cpl_frameset * self)
1163 {
1164  cpl_size i, n;
1165 
1166  if (self == NULL) {
1167  cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
1168  return;
1169  }
1170 
1171  n = cpl_frameset_get_size(self);
1172  for (i = 0; i < n; ++i)
1173  {
1174  cpl_frame * f = cpl_frameset_get_position(self, n-1-i);
1175  cpl_frameset_erase_frame(self, f);
1176  }
1177 }
1178 
1179 
1180 /*----------------------------------------------------------------------------*/
1200 /*----------------------------------------------------------------------------*/
1201 static void recipe_frameset_test_frame(const cpl_frame * self)
1202 {
1203 
1204  cpl_msg_info(cpl_func, "Validating new frame: %s",
1205  cpl_frame_get_filename(self));
1206 
1207  cpl_test_nonnull(self);
1208 
1209  /* Frame must be tagged */
1210  cpl_test_nonnull(cpl_frame_get_tag(self));
1211 
1212  /* New frames must be products */
1213  cpl_test_eq(cpl_frame_get_group(self), CPL_FRAME_GROUP_PRODUCT);
1214 
1215  if (cpl_frame_get_type(self) != CPL_FRAME_TYPE_PAF) {
1216  /* All but PAF (?) must be FITS */
1217  cpl_test_fits(cpl_frame_get_filename(self));
1218  } else {
1219  /* Frame must at least have a filename */
1220  cpl_test_nonnull(cpl_frame_get_filename(self));
1221  }
1222 }
1223 
1224 /*----------------------------------------------------------------------------*/
1245 /*----------------------------------------------------------------------------*/
1246 static void recipe_frameset_test_frameset_diff(const cpl_frameset * self,
1247  const cpl_frameset * other)
1248 {
1249 
1250  cpl_frameset_iterator * it1 = NULL;
1251  cpl_frameset_iterator * it2 = NULL;
1252  const cpl_frame * frame = irplib_frameset_get_first_const(&it2, other);
1253 
1254  /* First verify that filenames in other are non-NULL */
1255  for (;frame != NULL; frame = irplib_frameset_get_next_const(it2)) {
1256  const char * file = cpl_frame_get_filename(frame);
1257 
1258  if (file == NULL) {
1259  cpl_test_nonnull(cpl_frame_get_filename(frame));
1260  break;
1261  }
1262  }
1263  cpl_frameset_iterator_delete(it2);
1264  it2 = NULL;
1265  if (frame != NULL) return;
1266 
1267  frame = irplib_frameset_get_first_const(&it1, self);
1268 
1269  for (;frame != NULL; frame = irplib_frameset_get_next_const(it1)) {
1270  const cpl_frame * cmp;
1271  const char * file = cpl_frame_get_filename(frame);
1272 
1273  if (file == NULL) {
1274  cpl_test_nonnull(cpl_frame_get_filename(frame));
1275  continue;
1276  }
1277 
1278  cmp = irplib_frameset_get_first_const(&it2, other);
1279  for (;cmp != NULL; cmp = irplib_frameset_get_next_const(it2)) {
1280  const char * cfile = cpl_frame_get_filename(cmp);
1281 
1282  if (!strcmp(file, cfile)) break;
1283 
1284  }
1285  cpl_frameset_iterator_delete(it2);
1286  it2 = NULL;
1287  if (cmp == NULL) {
1288  /* frame is new */
1289 
1290  cpl_test_eq(cpl_frame_get_group(frame), CPL_FRAME_GROUP_PRODUCT);
1291  recipe_frameset_test_frame(frame);
1292  }
1293  }
1294 
1295  cpl_frameset_iterator_delete(it1);
1296 }