[hkl] fix the test suite due to binoculars new projection signature.
[hkl.git] / tests / hkl-pseudoaxis-t.c
blob958d31b70de16bc7d6af32b2f1f281d078dfa404
1 /* This file is part of the hkl library.
3 * The hkl library is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * The hkl library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with the hkl library. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright (C) 2003-2019, 2021 Synchrotron SOLEIL
17 * L'Orme des Merisiers Saint-Aubin
18 * BP 48 91192 GIF-sur-YVETTE CEDEX
20 * Authors: Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>
22 #include <alloca.h>
23 #include <string.h>
24 #include "hkl.h"
25 #include <tap/basic.h>
26 #include <tap/hkl-tap.h>
28 #define DEBUG
30 typedef int (* test_func) (HklEngine *engine, HklEngineList *engine_list, unsigned int n);
32 static int __test(unsigned int nb_iter, test_func f, int foreach_mode)
34 HklFactory **factories;
35 size_t i, j, n;
36 HklGeometry *geometry = NULL;
37 HklDetector *detector = hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D);
38 struct Sample cu = CU;
39 HklSample *sample = newSample(cu);
40 HklEngineList *engines;
41 int res = TRUE;
42 const char **mode;
44 factories = hkl_factory_get_all(&n);
45 for(i=0; i<n && TRUE == res; i++){
46 HklEngine **engine;
48 geometry = hkl_factory_create_new_geometry(factories[i]);
49 engines = hkl_factory_create_new_engine_list(factories[i]);
50 hkl_engine_list_init(engines, geometry, detector, sample);
51 darray_foreach(engine, *hkl_engine_list_engines_get(engines)){
52 const darray_string *modes = hkl_engine_modes_names_get(*engine);
53 if (foreach_mode){
54 darray_foreach(mode, *modes){
55 res &= DIAG(hkl_engine_current_mode_set(*engine, *mode, NULL));
56 for(j=0; j<nb_iter; ++j){
57 res &= DIAG(f(*engine, engines, nb_iter));
58 if(!res){
59 diag("failed at factory: \"%s\" engine: \"%s\" mode: \"%s\"",
60 hkl_geometry_name_get(geometry),
61 hkl_engine_name_get(*engine), *mode);
62 break;
65 if(!res)
66 break;
68 }else{
69 for(j=0; j<nb_iter; ++j){
70 res &= DIAG(f(*engine, engines, nb_iter));
71 if(!res)
72 break;
75 if(!res)
76 break;
78 hkl_geometry_free(geometry);
79 hkl_engine_list_free(engines);
81 hkl_detector_free(detector);
82 hkl_sample_free(sample);
84 return res;
87 #define TEST_FOREACH_ENGINE(_nb_iter, _f) __test(_nb_iter, _f, 0)
88 #define TEST_FOREACH_MODE(_nb_iter, _f) __test(_nb_iter, _f, 1)
90 static void factories(void)
92 int res = TRUE;
93 size_t i, n;
94 HklEngineList *engines;
95 HklFactory **factories;
97 factories = hkl_factory_get_all(&n);
98 for(i=0;i<n; i++){
99 engines = hkl_factory_create_new_engine_list(factories[i]);
100 hkl_engine_list_free(engines);
103 ok(res == TRUE, "factories");
106 static void parameters(void)
108 int res = TRUE;
109 size_t i, n;
110 HklEngineList *engines;
111 HklFactory **factories;
112 const darray_string *parameters_names;
114 factories = hkl_factory_get_all(&n);
115 for(i=0;i<n; i++){
116 size_t size;
117 double values[1];
119 engines = hkl_factory_create_new_engine_list(factories[i]);
121 /* check parameters names */
122 parameters_names = hkl_engine_list_parameters_names_get(engines);
123 size = darray_size(*parameters_names);
124 if(!strcmp("SOLEIL SIXS MED2+3 v2", hkl_factory_name_get(factories[i]))){
125 const HklParameter *p;
127 /* get */
128 res &= DIAG(size == 1);
129 p = hkl_engine_list_parameter_get(engines, "eta_a_rotation", NULL);
130 res &= DIAG(p != NULL);
132 /* set */
133 res &= DIAG(hkl_engine_list_parameter_set(engines, "eta_a_rotation", p, NULL));
135 /* values_get */
136 hkl_engine_list_parameters_values_get(engines,
137 values, ARRAY_SIZE(values),
138 HKL_UNIT_USER);
139 res &= DIAG(values[0] == 0.0);
141 /* values set */
142 values[0] = 1.0;
143 res &= DIAG(hkl_engine_list_parameters_values_set(engines,
144 values, ARRAY_SIZE(values),
145 HKL_UNIT_USER, NULL));
146 hkl_engine_list_parameters_values_get(engines,
147 values, ARRAY_SIZE(values),
148 HKL_UNIT_USER);
149 res &= DIAG(values[0] == 1.0);
150 } else {
151 res &= DIAG(size == 0);
154 hkl_engine_list_free(engines);
157 ok(res == TRUE, "parameters");
161 static int _get(HklEngine *engine, HklEngineList *engine_list, UNUSED unsigned int n)
163 uint i;
164 GError *error;
165 int res = TRUE;
166 HklGeometry *geometry = hkl_engine_list_geometry_get(engine_list);
167 const darray_string *pseudo_axes = hkl_engine_pseudo_axis_names_get(engine);
168 const size_t n_pseudo_axes = darray_size(*pseudo_axes);
169 double targets[n_pseudo_axes];
170 double currents[n_pseudo_axes];
172 /* randomize the geometry */
173 hkl_geometry_randomize(geometry);
175 /* randomize the pseudoAxes values */
176 hkl_tap_engine_pseudo_axes_randomize(engine,
177 targets, n_pseudo_axes,
178 HKL_UNIT_DEFAULT);
180 /* randomize the parameters */
181 hkl_tap_engine_parameters_randomize(engine);
183 /* pseudo -> geometry */
184 if(HKL_ENGINE_CAPABILITIES_INITIALIZABLE & hkl_engine_capabilities_get(engine))
185 res &= DIAG(hkl_engine_initialized_set(engine, TRUE, NULL));
186 res &= DIAG(hkl_engine_pseudo_axis_values_get(engine, currents, n_pseudo_axes,
187 HKL_UNIT_DEFAULT, NULL));
189 /* idem with error management */
190 error = NULL;
191 res &= DIAG(hkl_engine_pseudo_axis_values_get(engine, currents, n_pseudo_axes,
192 HKL_UNIT_DEFAULT, &error));
193 res &= DIAG(NULL == error);
194 for(i=0; i<n_pseudo_axes; ++i)
195 res &= DIAG(targets[i] != currents[i]); /* TODO this test is almost true, need a real check */
197 return res;
200 static void get()
202 ok(TRUE == TEST_FOREACH_MODE(1, _get), __func__);
205 static int _set(HklEngine *engine, HklEngineList *engine_list, UNUSED unsigned int n)
207 GError *error = NULL;
208 int unreachable = 0;
209 int res = TRUE;
210 HklGeometry *geometry = hkl_engine_list_geometry_get(engine_list);
211 const darray_string *pseudo_axes = hkl_engine_pseudo_axis_names_get(engine);
212 const size_t n_pseudo_axes = darray_size(*pseudo_axes);
213 double targets[n_pseudo_axes];
214 double currents[n_pseudo_axes];
216 /* randomize the geometry */
217 hkl_geometry_randomize(geometry);
219 /* for now skip the eulerians check */
220 if(!strcmp(hkl_engine_current_mode_get(engine), "eulerians"))
221 return TRUE;
223 size_t j;
224 HklGeometryList *solutions;
226 /* randomize the pseudoAxes values */
227 hkl_tap_engine_pseudo_axes_randomize(engine,
228 targets, n_pseudo_axes,
229 HKL_UNIT_DEFAULT);
231 /* randomize the parameters */
232 hkl_tap_engine_parameters_randomize(engine);
234 /* pseudo -> geometry */
235 res &= DIAG(hkl_engine_initialized_set(engine, TRUE, &error));
237 /* geometry -> pseudo */
238 solutions = hkl_engine_pseudo_axis_values_set(engine,
239 targets, n_pseudo_axes,
240 HKL_UNIT_DEFAULT, &error);
241 if(solutions) {
242 const HklGeometryListItem *item;
244 HKL_GEOMETRY_LIST_FOREACH(item, solutions){
245 hkl_geometry_set(geometry,
246 hkl_geometry_list_item_geometry_get(item));
248 res &= DIAG(hkl_engine_pseudo_axis_values_get(engine, currents, n_pseudo_axes, HKL_UNIT_DEFAULT, &error));
249 for(j=0; j<n_pseudo_axes; ++j)
250 res &= DIAG(fabs(targets[j] - currents[j]) < HKL_EPSILON);
252 hkl_geometry_list_free(solutions);
253 }else{
254 res &= DIAG(error != NULL);
255 g_clear_error(&error);
256 unreachable++;
258 #if 0
259 fprintf(stderr, " unreachable : %d/%d", unreachable, i);
260 if(!res){
261 fprintf(stderr, " ko");
262 /* print the hkl internals if the test failed */
263 fprintf(stderr, "\n expected : ");
264 for(uint j=0; j<n_pseudo_axes; ++j)
265 fprintf(stderr, " %f", targets[j]);
266 fprintf(stderr, " obtained : ");
267 for(uint j=0; j<n_pseudo_axes; ++j)
268 fprintf(stderr, " %f", currents[j]);
269 hkl_engine_fprintf(stderr, engine);
270 exit(0);
271 }else{
272 fprintf(stderr, " ok");
274 #endif
276 return res;
280 static void set(int nb_iter)
282 ok(TRUE == TEST_FOREACH_MODE(nb_iter, _set), __func__);
286 static int _pseudo_axis_get(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
288 static const char *bad = "_bad_name_";
289 const darray_string *pseudo_axis_names = hkl_engine_pseudo_axis_names_get(engine);
290 const char **pseudo_axis_name;
291 const HklParameter *pseudo_axis;
292 int res = TRUE;
293 GError *error;
295 darray_foreach(pseudo_axis_name, *pseudo_axis_names){
296 pseudo_axis = hkl_engine_pseudo_axis_get(engine, *pseudo_axis_name, NULL);
297 res &= DIAG(NULL != pseudo_axis);
299 error = NULL;
300 pseudo_axis = hkl_engine_pseudo_axis_get(engine, *pseudo_axis_name, &error);
301 res &= DIAG(NULL != pseudo_axis);
302 res &= DIAG(NULL == error);
305 /* error */
306 pseudo_axis = hkl_engine_pseudo_axis_get(engine, bad, NULL);
307 res &= DIAG(NULL == pseudo_axis);
309 error = NULL;
310 pseudo_axis = hkl_engine_pseudo_axis_get(engine, bad, &error);
311 res &= DIAG(NULL == pseudo_axis);
312 res &= DIAG(error != NULL);
313 g_clear_error(&error);
315 return res;
318 static void pseudo_axis_get(void)
320 ok(TRUE == TEST_FOREACH_ENGINE(1, _pseudo_axis_get), __func__);
323 static int _capabilities(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
325 int res = TRUE;
326 const unsigned long capabilities = hkl_engine_capabilities_get(engine);
328 /* all motors must have the read capabilities */
329 res &= DIAG((capabilities & HKL_ENGINE_CAPABILITIES_READABLE) != 0);
331 /* all engines except the readonly (incidence, emergence) are writable */
332 if(strcmp("incidence", hkl_engine_name_get(engine))
333 && strcmp("emergence", hkl_engine_name_get(engine)))
334 res &= DIAG((capabilities & HKL_ENGINE_CAPABILITIES_WRITABLE) != 0);
336 /* all psi engines must be initialisable */
337 if(!strcmp("psi", hkl_engine_name_get(engine)))
338 res &= DIAG((capabilities & HKL_ENGINE_CAPABILITIES_INITIALIZABLE) != 0);
340 return res;
343 static void capabilities(void)
345 ok(TRUE == TEST_FOREACH_MODE(1, _capabilities), __func__);
348 static int _initialized(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
350 int res = TRUE;
351 GError *error = NULL;
352 const unsigned long capabilities = hkl_engine_capabilities_get(engine);
354 if(HKL_ENGINE_CAPABILITIES_INITIALIZABLE & capabilities){
355 int tmp;
357 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, FALSE, NULL));
358 res &= DIAG(FALSE == hkl_engine_initialized_get(engine));
359 tmp = hkl_engine_initialized_set(engine, TRUE, NULL);
360 res &= DIAG(tmp == hkl_engine_initialized_get(engine));
362 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, FALSE, &error));
363 res &= DIAG(FALSE == hkl_engine_initialized_get(engine));
364 res &= DIAG(NULL == error);
365 tmp = hkl_engine_initialized_set(engine, TRUE, &error);
366 res &= DIAG(tmp == hkl_engine_initialized_get(engine));
367 if(tmp)
368 res &= DIAG(NULL == error);
369 else{
370 res &= DIAG(NULL != error);
371 g_clear_error(&error);
373 }else{
374 /* non-initializable engine should not produce an error */
375 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
376 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, TRUE, NULL));
377 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
378 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, FALSE, NULL));
379 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
381 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, TRUE, &error));
382 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
383 res &= DIAG(NULL == error);
384 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, FALSE, &error));
385 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
386 res &= DIAG(NULL == error);
389 return res;
392 static void initialized(void)
394 ok(TRUE == TEST_FOREACH_MODE(1, _initialized), __func__);
397 HKLAPI int hkl_engine_initialized_set(HklEngine *self, int initialized,
398 GError **error) HKL_ARG_NONNULL(1) HKL_WARN_UNUSED_RESULT;
401 static int _modes(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
403 static const char *bad = "__bad_mode_name__";
404 int res = TRUE;
405 int ok;
406 const darray_string *modes;
407 const char **mode;
408 const char *current_mode;
409 GError *error = NULL;
411 modes = hkl_engine_modes_names_get(engine);
413 /* check that the current mode is available in the mode list. */
414 current_mode = hkl_engine_current_mode_get(engine);
415 ok = FALSE;
416 darray_foreach(mode, *modes){
417 if(!strcmp(current_mode, *mode))
418 ok = TRUE;
420 res &= DIAG(TRUE == ok);
422 /* check that all modes can be set */
423 darray_foreach(mode, *modes){
424 res &= DIAG(TRUE == hkl_engine_current_mode_set(engine, *mode, NULL));
426 res &= DIAG(TRUE == hkl_engine_current_mode_set(engine, *mode, &error));
427 res &= DIAG(NULL == error);
430 /* check for bad mode name */
431 res &= DIAG(FALSE == hkl_engine_current_mode_set(engine, bad, NULL));
433 res &= DIAG(FALSE == hkl_engine_current_mode_set(engine, bad, &error));
434 res &= DIAG(NULL != error);
435 g_clear_error(&error);
437 return res;
440 static void modes(void)
442 ok(TRUE == TEST_FOREACH_ENGINE(1, _modes), __func__);
445 static int _check_axes(const darray_string *axes, const darray_string *refs)
447 int ko = TRUE;
448 const char **axis;
449 const char **ref;
451 darray_foreach(axis, *axes){
452 darray_foreach(ref, *refs){
453 if(!strcmp(*axis, *ref))
454 ko = FALSE;
456 if(ko)
457 break;
458 ko = TRUE;
460 return ko;
463 static int _axis_names(HklEngine *engine, HklEngineList *engine_list, UNUSED unsigned int n)
465 int res = TRUE;
466 HklGeometry *geometry;
467 const darray_string *all_axes;
468 const darray_string *axes_r;
469 const darray_string *axes_w;
471 geometry = hkl_engine_list_geometry_get(engine_list);
472 all_axes = hkl_geometry_axis_names_get(geometry);
474 /* check consistency of the engines, all axes should be in the
475 * list of the geometry axes */
476 axes_r = hkl_engine_axis_names_get(engine,
477 HKL_ENGINE_AXIS_NAMES_GET_READ);
479 axes_w = hkl_engine_axis_names_get(engine,
480 HKL_ENGINE_AXIS_NAMES_GET_WRITE);
482 res &= DIAG(axes_r != NULL);
483 res &= DIAG(axes_w != NULL);
484 res &= DIAG(_check_axes(axes_r, all_axes));
485 res &= DIAG(_check_axes(axes_w, all_axes));
487 return res;
490 static void axis_names(void)
492 ok(TRUE == TEST_FOREACH_MODE(1, _axis_names), __func__);
496 static int _mode_parameters(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
498 static const char *bad = "__bad_parameter_name__";
499 int res = TRUE;
500 GError *error = NULL;
501 const char **parameter;
502 const darray_string *parameters = hkl_engine_parameters_names_get(engine);
503 const HklParameter *param;
504 int n_values = darray_size(*parameters);
505 double values[n_values];
507 /* can not get a bad parameter */
508 param = hkl_engine_parameter_get(engine, bad, NULL);
509 res &= DIAG(NULL == param);
511 param = hkl_engine_parameter_get(engine, bad, &error);
512 res &= DIAG(NULL == param);
513 res &= DIAG(NULL != error);
514 g_clear_error(&error);
516 /* it is possible to get and set all the parameters */
517 darray_foreach(parameter, *parameters){
518 /* get */
519 param = hkl_engine_parameter_get(engine, *parameter, NULL);
520 res &= DIAG(NULL != param);
522 param = hkl_engine_parameter_get(engine, *parameter, &error);
523 res &= DIAG(NULL != param);
524 res &= DIAG(NULL == error);
526 /* set */
527 res &= DIAG(TRUE == hkl_engine_parameter_set(engine, *parameter, param, NULL));
528 res &= DIAG(TRUE == hkl_engine_parameter_set(engine, *parameter, param, &error));
529 res &= DIAG(NULL == error);
531 res &= DIAG(FALSE == hkl_engine_parameter_set(engine, bad, param, &error));
532 res &= DIAG(NULL != error);
533 g_clear_error(&error);
536 hkl_engine_parameters_values_get(engine, values, n_values, HKL_UNIT_USER);
538 res &= DIAG(TRUE == hkl_engine_parameters_values_set(engine, values, n_values, HKL_UNIT_DEFAULT, NULL));
539 res &= DIAG(TRUE == hkl_engine_parameters_values_set(engine, values, n_values, HKL_UNIT_DEFAULT, &error));
540 res &= DIAG(NULL == error);
542 res &= DIAG(TRUE == hkl_engine_parameters_values_set(engine, values, n_values, HKL_UNIT_USER, NULL));
543 res &= DIAG(TRUE == hkl_engine_parameters_values_set(engine, values, n_values, HKL_UNIT_USER, &error));
544 res &= DIAG(NULL == error);
546 return res;
549 static void mode_parameters(void)
551 ok(TRUE == TEST_FOREACH_MODE(1, _mode_parameters), __func__);
554 static int _depends(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
556 int res = TRUE;
557 const char *name = hkl_engine_name_get(engine);
558 const unsigned int depends = hkl_engine_dependencies_get(engine);
560 if(!strcmp("hkl", name))
561 res &= DIAG((depends & (HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY | HKL_ENGINE_DEPENDENCIES_SAMPLE)) != 0);
562 if(!strcmp("eulerians", hkl_engine_name_get(engine))){
563 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_AXES) != 0);
564 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_ENERGY) == 0);
565 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_SAMPLE) == 0);
567 if(!strcmp("q", name)){
568 res &= DIAG((depends &(HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY)) != 0);
569 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_SAMPLE) == 0);
571 if(!strcmp("q2", name)){
572 res &= DIAG((depends &(HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY)) != 0);
573 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_SAMPLE) == 0);
575 if(!strcmp("qper_qpar", name)){
576 res &= DIAG((depends & (HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY)) != 0);
577 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_SAMPLE) == 0);
579 if(!strcmp("psi", name))
580 res &= DIAG((depends & (HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY | HKL_ENGINE_DEPENDENCIES_SAMPLE)) != 0);
582 return res;
585 static void depends(void)
587 ok(TRUE == TEST_FOREACH_ENGINE(1, _depends), __func__);
590 int main(int argc, char** argv)
592 double n;
594 plan(11);
596 if (argc > 1)
597 n = atoi(argv[1]);
598 else
599 n = 10;
601 factories();
602 parameters();
603 get();
604 set(n);
605 pseudo_axis_get();
606 capabilities();
607 initialized();
608 modes();
609 axis_names();
610 mode_parameters();
611 depends();
613 return 0;