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