1#include "../../include/sane/config.h"
2
3#include <stdlib.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <fcntl.h>
7#include <errno.h>
8#include <string.h>
9#include <assert.h>
10
11/* sane includes for the sanei functions called */
12#include "../include/sane/sane.h"
13#include "../include/sane/saneopts.h"
14#include "../include/sane/sanei.h"
15
16static SANE_Option_Descriptor none_opt = {
17  SANE_NAME_SCAN_TL_X,
18  SANE_TITLE_SCAN_TL_X,
19  SANE_DESC_SCAN_TL_X,
20  SANE_TYPE_INT,
21  SANE_UNIT_NONE,
22  sizeof (SANE_Word),
23  0,
24  SANE_CONSTRAINT_NONE,
25  {NULL}
26};
27
28
29static SANE_Option_Descriptor none_bool_opt = {
30  SANE_NAME_SCAN_TL_X,
31  SANE_TITLE_SCAN_TL_X,
32  SANE_DESC_SCAN_TL_X,
33  SANE_TYPE_BOOL,
34  SANE_UNIT_NONE,
35  sizeof (SANE_Word),
36  0,
37  SANE_CONSTRAINT_NONE,
38  {NULL}
39};
40
41/* range for int constraint */
42static const SANE_Range int_range = {
43  3,				/* minimum */
44  18,				/* maximum */
45  3				/* quantization */
46};
47
48/* range for sane fixed constraint */
49static const SANE_Range fixed_range = {
50  SANE_FIX(1.0),		/* minimum */
51  SANE_FIX(431.8),		/* maximum */
52  SANE_FIX(0.01)				/* quantization */
53};
54
55static SANE_Option_Descriptor int_opt = {
56  SANE_NAME_SCAN_TL_X,
57  SANE_TITLE_SCAN_TL_X,
58  SANE_DESC_SCAN_TL_X,
59  SANE_TYPE_FIXED,
60  SANE_UNIT_MM,
61  sizeof (SANE_Word),
62  0,
63  SANE_CONSTRAINT_RANGE,
64  {NULL}
65};
66
67static SANE_Option_Descriptor fixed_opt = {
68  SANE_NAME_SCAN_TL_X,
69  SANE_TITLE_SCAN_TL_X,
70  SANE_DESC_SCAN_TL_X,
71  SANE_TYPE_FIXED,
72  SANE_UNIT_MM,
73  sizeof (SANE_Word),
74  0,
75  SANE_CONSTRAINT_RANGE,
76  {NULL}
77};
78
79#define ARRAY_SIZE 7
80
81static SANE_Option_Descriptor array_opt = {
82  SANE_NAME_SCAN_TL_X,
83  SANE_TITLE_SCAN_TL_X,
84  SANE_DESC_SCAN_TL_X,
85  SANE_TYPE_FIXED,
86  SANE_UNIT_MM,
87  sizeof (SANE_Word) * ARRAY_SIZE,
88  0,
89  SANE_CONSTRAINT_RANGE,
90  {NULL}
91};
92
93#define WORD_SIZE 9
94static const SANE_Int dpi_list[] =
95  { WORD_SIZE - 1, 100, 200, 300, 400, 500, 600, 700, 800 };
96
97static SANE_Option_Descriptor word_array_opt = {
98  SANE_NAME_SCAN_RESOLUTION,
99  SANE_TITLE_SCAN_RESOLUTION,
100  SANE_DESC_SCAN_RESOLUTION,
101  SANE_TYPE_INT,
102  SANE_UNIT_DPI,
103  sizeof (SANE_Word) * WORD_SIZE,
104  100,
105  SANE_CONSTRAINT_WORD_LIST,
106  {NULL}
107};
108
109static const SANE_String_Const string_list[] = {
110  SANE_VALUE_SCAN_MODE_LINEART,
111  SANE_VALUE_SCAN_MODE_HALFTONE,
112  SANE_VALUE_SCAN_MODE_GRAY,
113  "linelength",
114  0
115};
116
117static SANE_Option_Descriptor string_array_opt = {
118  SANE_NAME_SCAN_MODE,
119  SANE_TITLE_SCAN_MODE,
120  SANE_DESC_SCAN_MODE,
121  SANE_TYPE_STRING,
122  SANE_UNIT_NONE,
123  8,
124  0,
125  SANE_CONSTRAINT_STRING_LIST,
126  {NULL}
127};
128
129
130/******************************/
131/* start of tests definitions */
132/******************************/
133
134/*
135 * constrained int
136 */
137static void
138min_int_value (void)
139{
140  SANE_Int value = int_range.min;
141  SANE_Word info = 0;
142  SANE_Status status;
143
144  status = sanei_constrain_value (&int_opt, &value, &info);
145
146  /* check results */
147  assert (status == SANE_STATUS_GOOD);
148  assert (info == 0);
149  assert (value == int_range.min);
150}
151
152static void
153max_int_value (void)
154{
155  SANE_Int value = int_range.max;
156  SANE_Word info = 0;
157  SANE_Status status;
158
159  status = sanei_constrain_value (&int_opt, &value, &info);
160
161  /* check results */
162  assert (status == SANE_STATUS_GOOD);
163  assert (info == 0);
164  assert (value == int_range.max);
165}
166
167static void
168below_min_int_value (void)
169{
170  SANE_Int value = int_range.min - 1;
171  SANE_Word info = 0;
172  SANE_Status status;
173
174  status = sanei_constrain_value (&int_opt, &value, &info);
175
176  /* check results */
177  assert (status == SANE_STATUS_GOOD);
178  assert (info == SANE_INFO_INEXACT);
179  assert (value == int_range.min);
180}
181
182/* rounded to lower value */
183static void
184quant1_int_value (void)
185{
186  SANE_Int value = int_range.min + 1;
187  SANE_Word info = 0;
188  SANE_Status status;
189
190  status = sanei_constrain_value (&int_opt, &value, &info);
191
192  /* check results */
193  assert (status == SANE_STATUS_GOOD);
194  assert (info == SANE_INFO_INEXACT);
195  assert (value == int_range.min);
196}
197
198/* rounded to higher value */
199static void
200quant2_int_value (void)
201{
202  SANE_Int value = int_range.min + int_range.quant - 1;
203  SANE_Word info = 0;
204  SANE_Status status;
205
206  status = sanei_constrain_value (&int_opt, &value, &info);
207
208  /* check results */
209  assert (status == SANE_STATUS_GOOD);
210  assert (info == SANE_INFO_INEXACT);
211  assert (value == int_range.min + int_range.quant);
212}
213
214static void
215in_range_int_value (void)
216{
217  SANE_Int value = int_range.min + int_range.quant;
218  SANE_Word info = 0;
219  SANE_Status status;
220
221  status = sanei_constrain_value (&int_opt, &value, &info);
222
223  /* check results */
224  assert (status == SANE_STATUS_GOOD);
225  assert (info == 0);
226  assert (value == int_range.min + int_range.quant);
227}
228
229static void
230above_max_int_value (void)
231{
232  SANE_Int value = int_range.max + 1;
233  SANE_Word info = 0;
234  SANE_Status status;
235
236  status = sanei_constrain_value (&int_opt, &value, &info);
237
238  /* check results */
239  assert (status == SANE_STATUS_GOOD);
240  assert (info == SANE_INFO_INEXACT);
241  assert (value == int_range.max);
242}
243
244/*
245 * constrained fixed value
246 */
247static void
248min_fixed_value (void)
249{
250  SANE_Int value = fixed_range.min;
251  SANE_Word info = 0;
252  SANE_Status status;
253
254  status = sanei_constrain_value (&fixed_opt, &value, &info);
255
256  /* check results */
257  assert (status == SANE_STATUS_GOOD);
258  assert (info == 0);
259  assert (value == fixed_range.min);
260}
261
262static void
263max_fixed_value (void)
264{
265  SANE_Int value = fixed_range.max;
266  SANE_Word info = 0;
267  SANE_Status status;
268
269  status = sanei_constrain_value (&fixed_opt, &value, &info);
270
271  /* check results */
272  assert (status == SANE_STATUS_GOOD);
273  assert (info == 0);
274  assert (value == fixed_range.max);
275}
276
277static void
278below_min_fixed_value (void)
279{
280  SANE_Int value = fixed_range.min - 1;
281  SANE_Word info = 0;
282  SANE_Status status;
283
284  status = sanei_constrain_value (&fixed_opt, &value, &info);
285
286  /* check results */
287  assert (status == SANE_STATUS_GOOD);
288  assert (info == SANE_INFO_INEXACT);
289  assert (value == fixed_range.min);
290}
291
292/* rounded to lower value */
293static void
294quant1_fixed_value (void)
295{
296  SANE_Int value = fixed_range.min + fixed_range.quant/3;
297  SANE_Word info = 0;
298  SANE_Status status;
299
300  status = sanei_constrain_value (&fixed_opt, &value, &info);
301
302  /* check results */
303  assert (status == SANE_STATUS_GOOD);
304  assert (info == SANE_INFO_INEXACT);
305  assert (value == fixed_range.min);
306}
307
308/* rounded to higher value */
309static void
310quant2_fixed_value (void)
311{
312  SANE_Int value = fixed_range.min + fixed_range.quant - fixed_range.quant/3;
313  SANE_Word info = 0;
314  SANE_Status status;
315
316  status = sanei_constrain_value (&fixed_opt, &value, &info);
317
318  /* check results */
319  assert (status == SANE_STATUS_GOOD);
320  assert (info == SANE_INFO_INEXACT);
321  assert (value == fixed_range.min + fixed_range.quant);
322}
323
324static void
325in_range_fixed_value (void)
326{
327  SANE_Int value = fixed_range.min + fixed_range.quant;
328  SANE_Word info = 0;
329  SANE_Status status;
330
331  status = sanei_constrain_value (&fixed_opt, &value, &info);
332
333  /* check results */
334  assert (status == SANE_STATUS_GOOD);
335  assert (info == 0);
336  assert (value == fixed_range.min + fixed_range.quant);
337}
338
339static void
340above_max_fixed_value (void)
341{
342  SANE_Int value = fixed_range.max + 1;
343  SANE_Word info = 0;
344  SANE_Status status;
345
346  status = sanei_constrain_value (&fixed_opt, &value, &info);
347
348  /* check results */
349  assert (status == SANE_STATUS_GOOD);
350  assert (info == SANE_INFO_INEXACT);
351  assert (value == fixed_range.max);
352}
353
354
355static void
356above_max_word (void)
357{
358  SANE_Word value = 25000;
359  SANE_Word info = 0;
360  SANE_Status status;
361
362  status = sanei_constrain_value (&word_array_opt, &value, &info);
363
364  /* check results */
365  assert (status == SANE_STATUS_GOOD);
366  assert (info == SANE_INFO_INEXACT);
367  assert (value == 800);
368}
369
370
371static void
372below_max_word (void)
373{
374  SANE_Word value = 1;
375  SANE_Word info = 0;
376  SANE_Status status;
377
378  status = sanei_constrain_value (&word_array_opt, &value, &info);
379
380  /* check results */
381  assert (status == SANE_STATUS_GOOD);
382  assert (info == SANE_INFO_INEXACT);
383  assert (value == 100);
384}
385
386static void
387closest_200_word (void)
388{
389  SANE_Word value = 249;
390  SANE_Word info = 0;
391  SANE_Status status;
392
393  status = sanei_constrain_value (&word_array_opt, &value, &info);
394
395  /* check results */
396  assert (status == SANE_STATUS_GOOD);
397  assert (info == SANE_INFO_INEXACT);
398  assert (value == 200);
399}
400
401
402static void
403closest_300_word (void)
404{
405  SANE_Word value = 251;
406  SANE_Word info = 0;
407  SANE_Status status;
408
409  status = sanei_constrain_value (&word_array_opt, &value, &info);
410
411  /* check results */
412  assert (status == SANE_STATUS_GOOD);
413  assert (info == SANE_INFO_INEXACT);
414  assert (value == 300);
415}
416
417
418static void
419exact_400_word (void)
420{
421  SANE_Word value = 400;
422  SANE_Word info = 0;
423  SANE_Status status;
424
425  status = sanei_constrain_value (&word_array_opt, &value, &info);
426
427  /* check results */
428  assert (status == SANE_STATUS_GOOD);
429  assert (info == 0);
430  assert (value == 400);
431}
432
433/*
434 * constrained int array
435 */
436static void
437min_int_array (void)
438{
439  SANE_Int value[ARRAY_SIZE];
440  SANE_Word info = 0;
441  SANE_Status status;
442  int i;
443
444  for (i = 0; i < ARRAY_SIZE; i++)
445    {
446      value[i] = int_range.min;
447    }
448  status = sanei_constrain_value (&array_opt, value, &info);
449
450  /* check results */
451  assert (status == SANE_STATUS_GOOD);
452  assert (info == 0);
453  for (i = 0; i < ARRAY_SIZE; i++)
454    {
455      assert (value[i] == int_range.min);
456    }
457}
458
459static void
460max_int_array (void)
461{
462  SANE_Int value[ARRAY_SIZE];
463  SANE_Word info = 0;
464  SANE_Status status;
465  int i;
466
467  for (i = 0; i < ARRAY_SIZE; i++)
468    {
469      value[i] = int_range.max;
470    }
471
472  status = sanei_constrain_value (&array_opt, value, &info);
473
474  /* check results */
475  assert (status == SANE_STATUS_GOOD);
476  assert (info == 0);
477  for (i = 0; i < ARRAY_SIZE; i++)
478    {
479      assert (value[i] == int_range.max);
480    }
481}
482
483static void
484below_min_int_array (void)
485{
486  SANE_Int value[ARRAY_SIZE];
487  SANE_Word info = 0;
488  SANE_Status status;
489  int i;
490
491  for (i = 0; i < ARRAY_SIZE; i++)
492    {
493      value[i] = int_range.min - 1;
494    }
495
496  status = sanei_constrain_value (&array_opt, &value, &info);
497
498  /* check results */
499  assert (status == SANE_STATUS_GOOD);
500  assert (info == SANE_INFO_INEXACT);
501  for (i = 0; i < ARRAY_SIZE; i++)
502    {
503      assert (value[i] == int_range.min);
504    }
505}
506
507/* rounded to lower value */
508static void
509quant1_int_array (void)
510{
511  SANE_Int value[ARRAY_SIZE];
512  SANE_Word info = 0;
513  SANE_Status status;
514  int i;
515
516  for (i = 0; i < ARRAY_SIZE; i++)
517    {
518      value[i] = int_range.min + 1;
519    }
520  status = sanei_constrain_value (&array_opt, &value, &info);
521
522  /* check results */
523  assert (status == SANE_STATUS_GOOD);
524  assert (info == SANE_INFO_INEXACT);
525  for (i = 0; i < ARRAY_SIZE; i++)
526    {
527      assert (value[i] == int_range.min);
528    }
529}
530
531/* rounded to higher value */
532static void
533quant2_int_array (void)
534{
535  SANE_Int value[ARRAY_SIZE];
536  SANE_Word info = 0;
537  SANE_Status status;
538  int i;
539
540  for (i = 0; i < ARRAY_SIZE; i++)
541    {
542      value[i] = int_range.min + int_range.quant - 1;
543    }
544  status = sanei_constrain_value (&array_opt, &value, &info);
545
546  /* check results */
547  assert (status == SANE_STATUS_GOOD);
548  assert (info == SANE_INFO_INEXACT);
549  for (i = 0; i < ARRAY_SIZE; i++)
550    {
551      assert (value[i] == int_range.min + int_range.quant);
552    }
553}
554
555static void
556in_range_int_array (void)
557{
558  SANE_Int value[ARRAY_SIZE];
559  SANE_Word info = 0;
560  SANE_Status status;
561  int i;
562
563  for (i = 0; i < ARRAY_SIZE; i++)
564    {
565      value[i] = int_range.min + int_range.quant;
566    }
567
568  status = sanei_constrain_value (&array_opt, &value, &info);
569
570  /* check results */
571  assert (status == SANE_STATUS_GOOD);
572  assert (info == 0);
573  for (i = 0; i < ARRAY_SIZE; i++)
574    {
575      assert (value[i] == int_range.min + int_range.quant);
576    }
577}
578
579static void
580above_max_int_array (void)
581{
582  SANE_Int value[ARRAY_SIZE];
583  SANE_Word info = 0;
584  SANE_Status status;
585  int i;
586
587  for (i = 0; i < ARRAY_SIZE; i++)
588    {
589      value[i] = int_range.max + 1;
590    }
591  status = sanei_constrain_value (&array_opt, &value, &info);
592
593  /* check results */
594  assert (status == SANE_STATUS_GOOD);
595  assert (info == SANE_INFO_INEXACT);
596  for (i = 0; i < ARRAY_SIZE; i++)
597    {
598      assert (value[i] == int_range.max);
599    }
600}
601
602static void
603wrong_string_array (void)
604{
605  SANE_Char value[9] = "wrong";
606  SANE_Word info = 0;
607  SANE_Status status;
608
609  status = sanei_constrain_value (&string_array_opt, &value, &info);
610
611  /* check results */
612  assert (status == SANE_STATUS_INVAL);
613  assert (info == 0);
614}
615
616
617static void
618none_int (void)
619{
620  SANE_Int value = 555;
621  SANE_Word info = 0;
622  SANE_Status status;
623
624  status = sanei_constrain_value (&none_opt, &value, &info);
625
626  /* check results */
627  assert (status == SANE_STATUS_GOOD);
628  assert (info == 0);
629}
630
631
632static void
633none_bool_nok (void)
634{
635  SANE_Bool value = 555;
636  SANE_Word info = 0;
637  SANE_Status status;
638
639  status = sanei_constrain_value (&none_bool_opt, &value, &info);
640
641  /* check results */
642  assert (status == SANE_STATUS_INVAL);
643  assert (info == 0);
644}
645
646
647static void
648none_bool_ok (void)
649{
650  SANE_Bool value = SANE_FALSE;
651  SANE_Word info = 0;
652  SANE_Status status;
653
654  status = sanei_constrain_value (&none_bool_opt, &value, &info);
655
656  /* check results */
657  assert (status == SANE_STATUS_GOOD);
658  assert (info == 0);
659}
660
661/**
662 * several partial match
663 */
664static void
665string_array_several (void)
666{
667  SANE_Char value[9] = "Line";
668  SANE_Word info = 0;
669  SANE_Status status;
670
671  status = sanei_constrain_value (&string_array_opt, &value, &info);
672
673  /* check results */
674  assert (status == SANE_STATUS_INVAL);
675  assert (info == 0);
676}
677
678/**
679 * unique partial match
680 */
681static void
682partial_string_array (void)
683{
684  SANE_Char value[9] = "Linea";
685  SANE_Word info = 0;
686  SANE_Status status;
687
688  status = sanei_constrain_value (&string_array_opt, &value, &info);
689
690  /* check results */
691  assert (status == SANE_STATUS_GOOD);
692  assert (info == 0);
693}
694
695static void
696string_array_ignorecase (void)
697{
698  SANE_Char value[9] = "lineart";
699  SANE_Word info = 0;
700  SANE_Status status;
701
702  status = sanei_constrain_value (&string_array_opt, &value, &info);
703
704  /* check results */
705  assert (status == SANE_STATUS_GOOD);
706  assert (info == 0);
707}
708
709static void
710string_array_ok (void)
711{
712  SANE_Char value[9] = "Lineart";
713  SANE_Word info = 0;
714  SANE_Status status;
715
716  status = sanei_constrain_value (&string_array_opt, &value, &info);
717
718  /* check results */
719  assert (status == SANE_STATUS_GOOD);
720  assert (info == 0);
721}
722
723/**
724 * run the test suite for sanei constrain related tests
725 */
726static void
727sanei_constrain_suite (void)
728{
729  /* to be compatible with pre-C99 compilers */
730  int_opt.constraint.range = &int_range;
731  fixed_opt.constraint.range = &fixed_range;
732  array_opt.constraint.range = &int_range;
733  word_array_opt.constraint.word_list = dpi_list;
734  string_array_opt.constraint.string_list = string_list;
735
736  /* tests for constrained int value */
737  min_int_value ();
738  max_int_value ();
739  below_min_int_value ();
740  above_max_int_value ();
741  quant1_int_value ();
742  quant2_int_value ();
743  in_range_int_value ();
744
745  /* tests for sane fixed constrained value */
746  min_fixed_value ();
747  max_fixed_value ();
748  below_min_fixed_value ();
749  above_max_fixed_value ();
750  quant1_fixed_value ();
751  quant2_fixed_value ();
752  in_range_fixed_value ();
753
754  /* tests for constrained int array */
755  min_int_array ();
756  max_int_array ();
757  below_min_int_array ();
758  above_max_int_array ();
759  quant1_int_array ();
760  quant2_int_array ();
761  in_range_int_array ();
762
763  /* tests for word lists */
764  above_max_word ();
765  below_max_word ();
766  closest_200_word ();
767  closest_300_word ();
768  exact_400_word ();
769
770  /* tests for string lists */
771  wrong_string_array ();
772  partial_string_array ();
773  string_array_ok ();
774  string_array_ignorecase ();
775  string_array_several ();
776
777  /* constraint none tests  */
778  none_int ();
779  none_bool_nok ();
780  none_bool_ok ();
781}
782
783/**
784 * main function to run the test suites
785 */
786int
787main (void)
788{
789  /* run suites */
790  sanei_constrain_suite ();
791
792  return 0;
793}
794
795/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
796