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-2017 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>
25 #include <tap/basic.h>
26 #include <tap/hkl-tap.h>
31 typedef int (* test_func
) (HklEngine
*engine
, HklEngineList
*engine_list
, unsigned int n
);
33 static int __test(unsigned int nb_iter
, test_func f
, int foreach_mode
)
35 HklFactory
**factories
;
37 HklGeometry
*geometry
= NULL
;
38 HklDetector
*detector
= hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D
);
39 HklSample
*sample
= newSample(cu
);
40 HklEngineList
*engines
;
44 factories
= hkl_factory_get_all(&n
);
45 for(i
=0; i
<n
&& TRUE
== res
; i
++){
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
);
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
));
59 diag("failed at factory: \"%s\" engine: \"%s\" mode: \"%s\"",
60 hkl_geometry_name_get(geometry
),
61 hkl_engine_name_get(*engine
), *mode
);
69 for(j
=0; j
<nb_iter
; ++j
){
70 res
&= DIAG(f(*engine
, engines
, nb_iter
));
78 hkl_geometry_free(geometry
);
79 hkl_engine_list_free(engines
);
81 hkl_detector_free(detector
);
82 hkl_sample_free(sample
);
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)
94 HklEngineList
*engines
;
95 HklFactory
**factories
;
97 factories
= hkl_factory_get_all(&n
);
99 engines
= hkl_factory_create_new_engine_list(factories
[i
]);
100 hkl_engine_list_free(engines
);
103 ok(res
== TRUE
, "factories");
106 static int _get(HklEngine
*engine
, HklEngineList
*engine_list
, UNUSED
unsigned int n
)
111 HklGeometry
*geometry
= hkl_engine_list_geometry_get(engine_list
);
112 const darray_string
*pseudo_axes
= hkl_engine_pseudo_axis_names_get(engine
);
113 const size_t n_pseudo_axes
= darray_size(*pseudo_axes
);
114 double targets
[n_pseudo_axes
];
115 double currents
[n_pseudo_axes
];
117 /* randomize the geometry */
118 hkl_geometry_randomize(geometry
);
120 /* randomize the pseudoAxes values */
121 hkl_tap_engine_pseudo_axes_randomize(engine
,
122 targets
, n_pseudo_axes
,
125 /* randomize the parameters */
126 hkl_tap_engine_parameters_randomize(engine
);
128 /* pseudo -> geometry */
129 if(HKL_ENGINE_CAPABILITIES_INITIALIZABLE
& hkl_engine_capabilities_get(engine
))
130 res
&= DIAG(hkl_engine_initialized_set(engine
, TRUE
, NULL
));
131 res
&= DIAG(hkl_engine_pseudo_axis_values_get(engine
, currents
, n_pseudo_axes
,
132 HKL_UNIT_DEFAULT
, NULL
));
134 /* idem with error management */
136 res
&= DIAG(hkl_engine_pseudo_axis_values_get(engine
, currents
, n_pseudo_axes
,
137 HKL_UNIT_DEFAULT
, &error
));
138 res
&= DIAG(NULL
== error
);
139 for(i
=0; i
<n_pseudo_axes
; ++i
)
140 res
&= DIAG(targets
[i
] != currents
[i
]); /* TODO this test is almost true, need a real check */
147 ok(TRUE
== TEST_FOREACH_MODE(1, _get
), __func__
);
150 static int _set(HklEngine
*engine
, HklEngineList
*engine_list
, UNUSED
unsigned int n
)
152 GError
*error
= NULL
;
155 HklGeometry
*geometry
= hkl_engine_list_geometry_get(engine_list
);
156 const darray_string
*pseudo_axes
= hkl_engine_pseudo_axis_names_get(engine
);
157 const size_t n_pseudo_axes
= darray_size(*pseudo_axes
);
158 double targets
[n_pseudo_axes
];
159 double currents
[n_pseudo_axes
];
161 /* randomize the geometry */
162 hkl_geometry_randomize(geometry
);
164 /* for now skip the eulerians check */
165 if(!strcmp(hkl_engine_current_mode_get(engine
), "eulerians"))
169 HklGeometryList
*solutions
;
171 /* randomize the pseudoAxes values */
172 hkl_tap_engine_pseudo_axes_randomize(engine
,
173 targets
, n_pseudo_axes
,
176 /* randomize the parameters */
177 hkl_tap_engine_parameters_randomize(engine
);
179 /* pseudo -> geometry */
180 res
&= DIAG(hkl_engine_initialized_set(engine
, TRUE
, &error
));
182 /* geometry -> pseudo */
183 solutions
= hkl_engine_pseudo_axis_values_set(engine
,
184 targets
, n_pseudo_axes
,
185 HKL_UNIT_DEFAULT
, &error
);
187 const HklGeometryListItem
*item
;
189 HKL_GEOMETRY_LIST_FOREACH(item
, solutions
){
190 hkl_geometry_set(geometry
,
191 hkl_geometry_list_item_geometry_get(item
));
193 res
&= DIAG(hkl_engine_pseudo_axis_values_get(engine
, currents
, n_pseudo_axes
, HKL_UNIT_DEFAULT
, &error
));
194 for(j
=0; j
<n_pseudo_axes
; ++j
)
195 res
&= DIAG(fabs(targets
[j
] - currents
[j
]) < HKL_EPSILON
);
197 hkl_geometry_list_free(solutions
);
199 res
&= DIAG(error
!= NULL
);
200 g_clear_error(&error
);
204 fprintf(stderr
, " unreachable : %d/%d", unreachable
, i
);
206 fprintf(stderr
, " ko");
207 /* print the hkl internals if the test failed */
208 fprintf(stderr
, "\n expected : ");
209 for(uint j
=0; j
<n_pseudo_axes
; ++j
)
210 fprintf(stderr
, " %f", targets
[j
]);
211 fprintf(stderr
, " obtained : ");
212 for(uint j
=0; j
<n_pseudo_axes
; ++j
)
213 fprintf(stderr
, " %f", currents
[j
]);
214 hkl_engine_fprintf(stderr
, engine
);
217 fprintf(stderr
, " ok");
225 static void set(int nb_iter
)
227 ok(TRUE
== TEST_FOREACH_MODE(nb_iter
, _set
), __func__
);
231 static int _pseudo_axis_get(HklEngine
*engine
, UNUSED HklEngineList
*engine_list
, UNUSED
unsigned int n
)
233 static const char *bad
= "_bad_name_";
234 const darray_string
*pseudo_axis_names
= hkl_engine_pseudo_axis_names_get(engine
);
235 const char **pseudo_axis_name
;
236 const HklParameter
*pseudo_axis
;
240 darray_foreach(pseudo_axis_name
, *pseudo_axis_names
){
241 pseudo_axis
= hkl_engine_pseudo_axis_get(engine
, *pseudo_axis_name
, NULL
);
242 res
&= DIAG(NULL
!= pseudo_axis
);
245 pseudo_axis
= hkl_engine_pseudo_axis_get(engine
, *pseudo_axis_name
, &error
);
246 res
&= DIAG(NULL
!= pseudo_axis
);
247 res
&= DIAG(NULL
== error
);
251 pseudo_axis
= hkl_engine_pseudo_axis_get(engine
, bad
, NULL
);
252 res
&= DIAG(NULL
== pseudo_axis
);
255 pseudo_axis
= hkl_engine_pseudo_axis_get(engine
, bad
, &error
);
256 res
&= DIAG(NULL
== pseudo_axis
);
257 res
&= DIAG(error
!= NULL
);
258 g_clear_error(&error
);
263 static void pseudo_axis_get(void)
265 ok(TRUE
== TEST_FOREACH_ENGINE(1, _pseudo_axis_get
), __func__
);
268 static int _capabilities(HklEngine
*engine
, UNUSED HklEngineList
*engine_list
, UNUSED
unsigned int n
)
271 const unsigned long capabilities
= hkl_engine_capabilities_get(engine
);
273 /* all motors must have the read capabilities */
274 res
&= DIAG((capabilities
& HKL_ENGINE_CAPABILITIES_READABLE
) != 0);
276 /* all engines except the readonly (incidence, emergence) are writable */
277 if(strcmp("incidence", hkl_engine_name_get(engine
))
278 && strcmp("emergence", hkl_engine_name_get(engine
)))
279 res
&= DIAG((capabilities
& HKL_ENGINE_CAPABILITIES_WRITABLE
) != 0);
281 /* all psi engines must be initialisable */
282 if(!strcmp("psi", hkl_engine_name_get(engine
)))
283 res
&= DIAG((capabilities
& HKL_ENGINE_CAPABILITIES_INITIALIZABLE
) != 0);
288 static void capabilities(void)
290 ok(TRUE
== TEST_FOREACH_MODE(1, _capabilities
), __func__
);
293 static int _initialized(HklEngine
*engine
, UNUSED HklEngineList
*engine_list
, UNUSED
unsigned int n
)
296 GError
*error
= NULL
;
297 const unsigned long capabilities
= hkl_engine_capabilities_get(engine
);
299 if(HKL_ENGINE_CAPABILITIES_INITIALIZABLE
& capabilities
){
302 res
&= DIAG(TRUE
== hkl_engine_initialized_set(engine
, FALSE
, NULL
));
303 res
&= DIAG(FALSE
== hkl_engine_initialized_get(engine
));
304 tmp
= hkl_engine_initialized_set(engine
, TRUE
, NULL
);
305 res
&= DIAG(tmp
== hkl_engine_initialized_get(engine
));
307 res
&= DIAG(TRUE
== hkl_engine_initialized_set(engine
, FALSE
, &error
));
308 res
&= DIAG(FALSE
== hkl_engine_initialized_get(engine
));
309 res
&= DIAG(NULL
== error
);
310 tmp
= hkl_engine_initialized_set(engine
, TRUE
, &error
);
311 res
&= DIAG(tmp
== hkl_engine_initialized_get(engine
));
313 res
&= DIAG(NULL
== error
);
315 res
&= DIAG(NULL
!= error
);
316 g_clear_error(&error
);
319 /* non-initializable engine should not produce an error */
320 res
&= DIAG(TRUE
== hkl_engine_initialized_get(engine
));
321 res
&= DIAG(TRUE
== hkl_engine_initialized_set(engine
, TRUE
, NULL
));
322 res
&= DIAG(TRUE
== hkl_engine_initialized_get(engine
));
323 res
&= DIAG(TRUE
== hkl_engine_initialized_set(engine
, FALSE
, NULL
));
324 res
&= DIAG(TRUE
== hkl_engine_initialized_get(engine
));
326 res
&= DIAG(TRUE
== hkl_engine_initialized_set(engine
, TRUE
, &error
));
327 res
&= DIAG(TRUE
== hkl_engine_initialized_get(engine
));
328 res
&= DIAG(NULL
== error
);
329 res
&= DIAG(TRUE
== hkl_engine_initialized_set(engine
, FALSE
, &error
));
330 res
&= DIAG(TRUE
== hkl_engine_initialized_get(engine
));
331 res
&= DIAG(NULL
== error
);
337 static void initialized(void)
339 ok(TRUE
== TEST_FOREACH_MODE(1, _initialized
), __func__
);
342 HKLAPI
int hkl_engine_initialized_set(HklEngine
*self
, int initialized
,
343 GError
**error
) HKL_ARG_NONNULL(1) HKL_WARN_UNUSED_RESULT
;
345 static int _modes(HklEngine
*engine
, UNUSED HklEngineList
*engine_list
, UNUSED
unsigned int n
)
347 static const char *bad
= "__bad_mode_name__";
350 const darray_string
*modes
;
352 const char *current_mode
;
353 GError
*error
= NULL
;
355 modes
= hkl_engine_modes_names_get(engine
);
357 /* check that the current mode is available in the mode list. */
358 current_mode
= hkl_engine_current_mode_get(engine
);
360 darray_foreach(mode
, *modes
){
361 if(!strcmp(current_mode
, *mode
))
364 res
&= DIAG(TRUE
== ok
);
366 /* check that all modes can be set */
367 darray_foreach(mode
, *modes
){
368 res
&= DIAG(TRUE
== hkl_engine_current_mode_set(engine
, *mode
, NULL
));
370 res
&= DIAG(TRUE
== hkl_engine_current_mode_set(engine
, *mode
, &error
));
371 res
&= DIAG(NULL
== error
);
374 /* check for bad mode name */
375 res
&= DIAG(FALSE
== hkl_engine_current_mode_set(engine
, bad
, NULL
));
377 res
&= DIAG(FALSE
== hkl_engine_current_mode_set(engine
, bad
, &error
));
378 res
&= DIAG(NULL
!= error
);
379 g_clear_error(&error
);
384 static void modes(void)
386 ok(TRUE
== TEST_FOREACH_ENGINE(1, _modes
), __func__
);
389 static int _check_axes(const darray_string
*axes
, const darray_string
*refs
)
395 darray_foreach(axis
, *axes
){
396 darray_foreach(ref
, *refs
){
397 if(!strcmp(*axis
, *ref
))
407 static int _axis_names(HklEngine
*engine
, HklEngineList
*engine_list
, UNUSED
unsigned int n
)
410 HklGeometry
*geometry
;
411 const darray_string
*all_axes
;
412 const darray_string
*axes_r
;
413 const darray_string
*axes_w
;
415 geometry
= hkl_engine_list_geometry_get(engine_list
);
416 all_axes
= hkl_geometry_axis_names_get(geometry
);
418 /* check consistency of the engines, all axes should be in the
419 * list of the geometry axes */
420 axes_r
= hkl_engine_axis_names_get(engine
,
421 HKL_ENGINE_AXIS_NAMES_GET_READ
);
423 axes_w
= hkl_engine_axis_names_get(engine
,
424 HKL_ENGINE_AXIS_NAMES_GET_WRITE
);
426 res
&= DIAG(axes_r
!= NULL
);
427 res
&= DIAG(axes_w
!= NULL
);
428 res
&= DIAG(_check_axes(axes_r
, all_axes
));
429 res
&= DIAG(_check_axes(axes_w
, all_axes
));
434 static void axis_names(void)
436 ok(TRUE
== TEST_FOREACH_MODE(1, _axis_names
), __func__
);
440 static int _parameters(HklEngine
*engine
, UNUSED HklEngineList
*engine_list
, UNUSED
unsigned int n
)
442 static const char *bad
= "__bad_parameter_name__";
444 GError
*error
= NULL
;
445 const char **parameter
;
446 const darray_string
*parameters
= hkl_engine_parameters_names_get(engine
);
447 const HklParameter
*param
;
448 int n_values
= darray_size(*parameters
);
449 double values
[n_values
];
451 /* can not get a bad parameter */
452 param
= hkl_engine_parameter_get(engine
, bad
, NULL
);
453 res
&= DIAG(NULL
== param
);
455 param
= hkl_engine_parameter_get(engine
, bad
, &error
);
456 res
&= DIAG(NULL
== param
);
457 res
&= DIAG(NULL
!= error
);
458 g_clear_error(&error
);
460 /* it is possible to get and set all the parameters */
461 darray_foreach(parameter
, *parameters
){
463 param
= hkl_engine_parameter_get(engine
, *parameter
, NULL
);
464 res
&= DIAG(NULL
!= param
);
466 param
= hkl_engine_parameter_get(engine
, *parameter
, &error
);
467 res
&= DIAG(NULL
!= param
);
468 res
&= DIAG(NULL
== error
);
471 res
&= DIAG(TRUE
== hkl_engine_parameter_set(engine
, *parameter
, param
, NULL
));
472 res
&= DIAG(TRUE
== hkl_engine_parameter_set(engine
, *parameter
, param
, &error
));
473 res
&= DIAG(NULL
== error
);
475 res
&= DIAG(FALSE
== hkl_engine_parameter_set(engine
, bad
, param
, &error
));
476 res
&= DIAG(NULL
!= error
);
477 g_clear_error(&error
);
480 hkl_engine_parameters_values_get(engine
, values
, n_values
, HKL_UNIT_USER
);
482 res
&= DIAG(TRUE
== hkl_engine_parameters_values_set(engine
, values
, n_values
, HKL_UNIT_DEFAULT
, NULL
));
483 res
&= DIAG(TRUE
== hkl_engine_parameters_values_set(engine
, values
, n_values
, HKL_UNIT_DEFAULT
, &error
));
484 res
&= DIAG(NULL
== error
);
486 res
&= DIAG(TRUE
== hkl_engine_parameters_values_set(engine
, values
, n_values
, HKL_UNIT_USER
, NULL
));
487 res
&= DIAG(TRUE
== hkl_engine_parameters_values_set(engine
, values
, n_values
, HKL_UNIT_USER
, &error
));
488 res
&= DIAG(NULL
== error
);
493 static void parameters(void)
495 ok(TRUE
== TEST_FOREACH_MODE(1, _parameters
), __func__
);
498 static int _depends(HklEngine
*engine
, UNUSED HklEngineList
*engine_list
, UNUSED
unsigned int n
)
501 const char *name
= hkl_engine_name_get(engine
);
502 const unsigned int depends
= hkl_engine_dependencies_get(engine
);
504 if(!strcmp("hkl", name
))
505 res
&= DIAG((depends
& (HKL_ENGINE_DEPENDENCIES_AXES
| HKL_ENGINE_DEPENDENCIES_ENERGY
| HKL_ENGINE_DEPENDENCIES_SAMPLE
)) != 0);
506 if(!strcmp("eulerians", hkl_engine_name_get(engine
))){
507 res
&= DIAG((depends
& HKL_ENGINE_DEPENDENCIES_AXES
) != 0);
508 res
&= DIAG((depends
& HKL_ENGINE_DEPENDENCIES_ENERGY
) == 0);
509 res
&= DIAG((depends
& HKL_ENGINE_DEPENDENCIES_SAMPLE
) == 0);
511 if(!strcmp("q", name
)){
512 res
&= DIAG((depends
&(HKL_ENGINE_DEPENDENCIES_AXES
| HKL_ENGINE_DEPENDENCIES_ENERGY
)) != 0);
513 res
&= DIAG((depends
& HKL_ENGINE_DEPENDENCIES_SAMPLE
) == 0);
515 if(!strcmp("q2", name
)){
516 res
&= DIAG((depends
&(HKL_ENGINE_DEPENDENCIES_AXES
| HKL_ENGINE_DEPENDENCIES_ENERGY
)) != 0);
517 res
&= DIAG((depends
& HKL_ENGINE_DEPENDENCIES_SAMPLE
) == 0);
519 if(!strcmp("qper_qpar", name
)){
520 res
&= DIAG((depends
& (HKL_ENGINE_DEPENDENCIES_AXES
| HKL_ENGINE_DEPENDENCIES_ENERGY
)) != 0);
521 res
&= DIAG((depends
& HKL_ENGINE_DEPENDENCIES_SAMPLE
) == 0);
523 if(!strcmp("psi", name
))
524 res
&= DIAG((depends
& (HKL_ENGINE_DEPENDENCIES_AXES
| HKL_ENGINE_DEPENDENCIES_ENERGY
| HKL_ENGINE_DEPENDENCIES_SAMPLE
)) != 0);
529 static void depends(void)
531 ok(TRUE
== TEST_FOREACH_ENGINE(1, _depends
), __func__
);
534 int main(int argc
, char** argv
)