Bounds check terms based in ICU norm
[idzebra-moved-to-github.git] / dict / scantest.c
1 /* This file is part of the Zebra server.
2    Copyright (C) 1994-2011 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <yaz/log.h>
27 #include <yaz/test.h>
28 #include <yaz/options.h>
29 #include <idzebra/dict.h>
30
31 struct handle_info {
32     int b;
33     int a;
34     int start_cut;
35     int end_cut;
36     char **ar;
37 };
38
39 static int handler(char *name, const char *info, int pos, void *client)
40 {
41     struct handle_info *hi = (struct handle_info *) client;
42     int idx;
43     if (pos > 0)
44         idx = hi->a - pos + hi->b;
45     else
46         idx = -pos - 1;
47
48     if (idx < 0)
49         return 0;
50     if (idx < hi->start_cut || idx > hi->end_cut)
51     {
52         return 1;
53     }
54
55     hi->ar[idx] = malloc(strlen(name)+1);
56     strcpy(hi->ar[idx], name);
57
58     return 0;
59 }
60
61 int do_scan(Dict dict, int before, int after, const char *sterm,
62             char **cmp_strs,
63             int verbose, int start_cut, int end_cut)
64 {
65     struct handle_info hi;
66     char scan_term[1024];
67
68     int i;
69     int errors = 0;
70
71     strcpy(scan_term, sterm);
72     hi.start_cut = start_cut;
73     hi.end_cut = end_cut;
74     hi.a = after;
75     hi.b = before;
76     hi.ar = malloc(sizeof(char*) * (after+before+1));
77     for (i = 0; i <= after+before; i++)
78         hi.ar[i] = 0;
79     yaz_log(YLOG_DEBUG, "dict_scan before=%d after=%d term=%s",
80             before, after, scan_term);
81     dict_scan (dict, scan_term, &before, &after, &hi, handler);
82     for (i = 0; i < hi.a+hi.b; i++)
83     {
84         if (!cmp_strs)
85         {
86             if (i >= start_cut &&  i <= end_cut)
87             {
88                 if (!hi.ar[i])
89                 {
90                     printf ("--> FAIL i=%d hi.ar[i] == NULL\n", i);
91                     errors++;
92                 }
93             }
94             else
95             {
96                 if (hi.ar[i])
97                 {
98                     printf ("--> FAIL i=%d hi.ar[i] = %s\n", i, hi.ar[i]);
99                     errors++;
100                 }
101             }
102         }
103         else
104         {
105             if (i >= start_cut && i <= end_cut)
106             {
107                 if (!hi.ar[i])
108                 {
109                     printf ("--> FAIL i=%d strs == NULL\n", i);
110                     errors++;
111                 }
112                 else if (!cmp_strs[i])
113                 {
114                     printf ("--> FAIL i=%d cmp_strs == NULL\n", i);
115                     errors++;
116                 }
117                 else if (strcmp(cmp_strs[i], hi.ar[i]))
118                 {
119                     printf ("--> FAIL i=%d expected %s\n", i, cmp_strs[i]);
120                     errors++;
121                 }
122             }
123             else
124             {
125                 if (hi.ar[i])
126                 {
127                     printf ("--> FAIL i=%d hi.ar[i] != NULL\n", i);
128                     errors++;
129                 }
130             }
131         }
132         if (verbose || errors)
133         {
134             if (i == hi.b)
135                 printf ("* ");
136             else
137                 printf ("  ");
138             if (hi.ar[i])
139                 printf ("%s", hi.ar[i]);
140             else
141                 printf ("NULL");
142             putchar('\n');
143         }
144         if (hi.ar[i])
145             free(hi.ar[i]);
146     }
147     free(hi.ar);
148     return errors;
149 }
150
151 static void tst(Dict dict, int start, int number)
152 {
153     int i;
154
155     /* insert again with original value again */
156     for (i = start; i < number; i += 100)
157     {
158         int v = i;
159         char w[32];
160         sprintf(w, "%d", i);
161         YAZ_CHECK_EQ(dict_insert(dict, w, sizeof(v), &v), 2);
162     }
163     /* insert again with different value */
164     for (i = start; i < number; i += 100)
165     {
166         int v = i-1;
167         char w[32];
168         sprintf(w, "%d", i);
169         YAZ_CHECK_EQ(dict_insert(dict, w, sizeof(v), &v), 1);
170     }
171     /* insert again with original value again */
172     for (i = start; i < number; i += 100)
173     {
174         int v = i;
175         char w[32];
176         sprintf(w, "%d", i);
177         YAZ_CHECK_EQ(dict_insert(dict, w, sizeof(v), &v), 1);
178     }
179
180 #if 1
181     {
182         char *cs[] = {
183             "4497",
184             "4498",
185             "4499",
186             "45"};
187         YAZ_CHECK_EQ(do_scan(dict, 2, 2, "4499", cs, 0, 0, 3), 0);
188     }
189 #endif
190 #if 1
191     {
192         char *cs[] = {
193             "4498",
194             "4499",
195             "45",
196             "450"};
197         YAZ_CHECK_EQ(do_scan(dict, 2, 2, "45", cs, 0, 0, 3), 0);
198     }
199 #endif
200 #if 1
201     /* bug 4592 */
202     {
203         char *cs[] = {
204             "4499",
205             "45", /* missing entry ! */
206             "450",
207             "4500"};
208         YAZ_CHECK_EQ(do_scan(dict, 4, 0, "4501", cs, 0, 0, 4), 0);
209     }
210 #endif
211 #if 1
212     {
213         char *cs[] = {
214             "9996",
215             "9997",
216             "9998",
217             "9999"};
218         YAZ_CHECK_EQ(do_scan(dict, 4, 0, "a", cs, 0, 0, 4), 0);
219         YAZ_CHECK_EQ(do_scan(dict, 3, 1, "9999", cs, 0, 0, 4), 0);
220     }
221 #endif
222 #if 1
223     {
224         char *cs[] = {
225             "10",
226             "100",
227             "1000",
228             "1001" };
229         YAZ_CHECK_EQ(do_scan(dict, 0, 4, "10", cs, 0, 0, 4), 0);
230         YAZ_CHECK_EQ(do_scan(dict, 0, 4, "1", cs, 0, 0, 4), 0);
231         YAZ_CHECK_EQ(do_scan(dict, 0, 4, " ", cs, 0, 0, 4), 0);
232         YAZ_CHECK_EQ(do_scan(dict, 0, 4, "", cs, 0, 0, 4), 0);
233     }
234 #endif
235 #if 1
236     for (i = 0; i < 20; i++)
237         YAZ_CHECK_EQ(do_scan(dict, 20, 20, "45", 0, 0, 20-i, 20+i), 0);
238 #endif
239 }
240
241 int main(int argc, char **argv)
242 {
243     BFiles bfs = 0;
244     Dict dict = 0;
245     int i;
246     int ret;
247     int before = 0, after = 0, number = 10000;
248     char scan_term[1024];
249     char *arg;
250
251     YAZ_CHECK_INIT(argc, argv);
252
253     strcpy(scan_term, "1004");
254     while ((ret = options("b:a:t:n:v:", argv, argc, &arg)) != -2)
255     {
256         switch(ret)
257         {
258         case 0:
259             break;
260         case 'b':
261             before = atoi(arg);
262             break;
263         case 'a':
264             after = atoi(arg);
265             break;
266         case 't':
267             if (strlen(arg) >= sizeof(scan_term)-1)
268             {
269                 fprintf(stderr, "scan term too long\n");
270                 exit(1);
271             }
272             strcpy(scan_term, arg);
273             break;
274         case 'n':
275             number = atoi(arg);
276             break;
277         case 'v':
278             yaz_log_init_level(yaz_log_mask_str(arg));
279         }
280     }
281
282     bfs = bfs_create(".:100M", 0);
283     YAZ_CHECK(bfs);
284     if (bfs)
285     {
286         bf_reset(bfs);
287         dict = dict_open(bfs, "dict", 100, 1, 0, 0);
288         YAZ_CHECK(dict);
289     }
290     if (dict)
291     {
292         int start = 10;
293         /* Insert "10", "11", "12", .. "99", "100", ... number */
294         for (i = start; i<number; i++)
295         {
296             char w[32];
297             sprintf(w, "%d", i);
298             YAZ_CHECK_EQ(dict_insert(dict, w, sizeof(int), &i), 0);
299         }
300
301         if (after > 0 || before > 0)
302             do_scan(dict, before, after, scan_term, 0, 1, 0, after+1);
303         else
304             tst(dict, start, number);
305
306         dict_close(dict);
307     }
308     if (bfs)
309         bfs_destroy(bfs);
310     YAZ_CHECK_TERM;
311 }
312 /*
313  * Local variables:
314  * c-basic-offset: 4
315  * c-file-style: "Stroustrup"
316  * indent-tabs-mode: nil
317  * End:
318  * vim: shiftwidth=4 tabstop=8 expandtab
319  */
320