1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * diagcode library unit test
29 *
30 * usually run from "make test" target. takes a single argument
31 * which is the directory where the test dictionaries are found.
32 * this test driver scans the dictionaries for comments of the form:
33 * #TEST:<routine>:<errno>:<input>:<output>
34 * and executes that test.
35 *
36 * exit 0 and an "All tests passed" message means no failures. otherwise
37 * error messages are spewed as appropriate and exit value is non-zero.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include <alloca.h>
47 #include <errno.h>
48 #include <sys/types.h>
49 #include <dirent.h>
50 #include <stdarg.h>
51
52 #include <fm/diagcode.h>
53
54 #define MAXLINE 10240
55 #define MAXARG 10
56 #define MAXKEY 100
57 #define MAXCODE 100
58
59 static char *Myname;
60 static char *Dict;
61 static int Line;
62 static int Errcount;
63 static fm_dc_handle_t *Dhp;
64
65 /*PRINTFLIKE1*/
66 static void
err(const char * fmt,...)67 err(const char *fmt, ...)
68 {
69 va_list ap;
70
71 va_start(ap, fmt);
72 (void) fprintf(stderr, "%s: %s:%d ", Myname, Dict, Line);
73 (void) vfprintf(stderr, fmt, ap);
74 (void) fprintf(stderr, "\n");
75 Errcount++;
76 }
77
78 /* parse an expected errno value from test line (numeric or some symbolic) */
79 static int
geterrno(const char * s)80 geterrno(const char *s)
81 {
82 if (*s == '\0' || isspace(*s))
83 return (0);
84 else if (isdigit(*s))
85 return (atoi(s));
86 else if (strcmp(s, "EPERM") == 0)
87 return (EPERM);
88 else if (strcmp(s, "ENOENT") == 0)
89 return (ENOENT);
90 else if (strcmp(s, "ESRCH") == 0)
91 return (ESRCH);
92 else if (strcmp(s, "ENOMEM") == 0)
93 return (ENOMEM);
94 else if (strcmp(s, "EACCES") == 0)
95 return (EACCES);
96 else if (strcmp(s, "EINVAL") == 0)
97 return (EINVAL);
98 else if (strcmp(s, "ERANGE") == 0)
99 return (ERANGE);
100 else if (strcmp(s, "ENOMSG") == 0)
101 return (ENOMSG);
102 else if (strcmp(s, "ENOTSUP") == 0)
103 return (ENOTSUP);
104 else {
105 err("geterrno: don't know errno \"%s\"", s);
106 Errcount++;
107 return (0);
108 }
109 }
110
111 /* call fm_dc_opendict() as part of a test */
112 static void
do_open(const char * dirpath,const char * dictname,char * argv[],int argc)113 do_open(const char *dirpath, const char *dictname, char *argv[], int argc)
114 {
115 int reterrno;
116 int experrno;
117
118 if (argc != 2) {
119 err("argc != 2");
120 return;
121 }
122 experrno = geterrno(argv[1]);
123
124 if ((Dhp = fm_dc_opendict(FM_DC_VERSION, dirpath, dictname)) == NULL)
125 reterrno = errno;
126 else
127 reterrno = 0;
128
129 if (reterrno != experrno)
130 err("opendict errno %d, expected %d", reterrno, experrno);
131 }
132
133 /* call fm_dc_closedict() as part of a test */
134 static void
do_close(const char * dirpath,const char * dictname,char * argv[],int argc)135 do_close(const char *dirpath, const char *dictname, char *argv[], int argc)
136 {
137 if (Dhp) {
138 fm_dc_closedict(Dhp);
139 Dhp = NULL;
140 }
141 }
142
143 /* call fm_dc_codelen() as part of a test */
144 static void
do_codelen(const char * dirpath,const char * dictname,char * argv[],int argc)145 do_codelen(const char *dirpath, const char *dictname, char *argv[], int argc)
146 {
147 int retcodelen;
148 int expcodelen;
149
150 if (argc != 3) {
151 err("argc != 3");
152 return;
153 }
154 expcodelen = geterrno(argv[2]);
155
156 if (Dhp == NULL) {
157 err("codelen NULL handle");
158 return;
159 }
160
161 retcodelen = fm_dc_codelen(Dhp);
162
163 if (retcodelen != expcodelen)
164 err("codelen %d, expected %d", retcodelen, expcodelen);
165 }
166
167 /* call fm_dc_maxkey() as part of a test */
168 static void
do_maxkey(const char * dirpath,const char * dictname,char * argv[],int argc)169 do_maxkey(const char *dirpath, const char *dictname, char *argv[], int argc)
170 {
171 int retmaxkey;
172 int expmaxkey;
173
174 if (argc != 3) {
175 err("argc != 3");
176 return;
177 }
178 expmaxkey = geterrno(argv[2]);
179
180 if (Dhp == NULL) {
181 err("maxkey NULL handle");
182 return;
183 }
184
185 retmaxkey = fm_dc_maxkey(Dhp);
186
187 if (retmaxkey != expmaxkey)
188 err("maxkey %d, expected %d", retmaxkey, expmaxkey);
189 }
190
191 /* call fm_dc_key2code() as part of a test */
192 static void
do_key2code(const char * dirpath,const char * dictname,char * argv[],int argc)193 do_key2code(const char *dirpath, const char *dictname, char *argv[], int argc)
194 {
195 int reterrno;
196 int experrno;
197 const char *key[MAXKEY];
198 char code[MAXCODE];
199 int nel;
200 char *beginp;
201 char *endp;
202
203 if (argc < 3) {
204 err("argc < 3");
205 return;
206 }
207 if (argc > 4) {
208 err("argc > 4");
209 return;
210 }
211 experrno = geterrno(argv[1]);
212
213 /* convert key into array */
214 nel = 0;
215 beginp = argv[2];
216 while (nel < MAXKEY - 1) {
217 key[nel++] = beginp;
218 if ((endp = strchr(beginp, ' ')) != NULL) {
219 *endp++ = '\0';
220 beginp = endp;
221 } else
222 break;
223 }
224 key[nel] = NULL;
225
226 if (Dhp == NULL) {
227 err("key2code NULL handle");
228 return;
229 }
230
231 if (fm_dc_key2code(Dhp, key, code, MAXCODE) < 0)
232 reterrno = errno;
233 else
234 reterrno = 0;
235
236 if (reterrno != experrno) {
237 err("key2code errno %d, expected %d", reterrno, experrno);
238 return;
239 }
240
241 if (reterrno == 0 && argc > 3 && strcmp(code, argv[3]))
242 err("code \"%s\", expected \"%s\"", code, argv[3]);
243 }
244
245 /* call fm_dc_code2key() as part of a test */
246 static void
do_code2key(const char * dirpath,const char * dictname,char * argv[],int argc)247 do_code2key(const char *dirpath, const char *dictname, char *argv[], int argc)
248 {
249 int reterrno;
250 int experrno;
251 char keystr[MAXLINE];
252 char *key[MAXKEY];
253 int nel;
254
255 if (argc < 3) {
256 err("argc < 3");
257 return;
258 }
259 if (argc > 4) {
260 err("argc > 4");
261 return;
262 }
263 experrno = geterrno(argv[1]);
264
265 if (Dhp == NULL) {
266 err("code2key NULL handle");
267 return;
268 }
269
270 if (fm_dc_code2key(Dhp, argv[2], key, fm_dc_maxkey(Dhp)) < 0)
271 reterrno = errno;
272 else
273 reterrno = 0;
274
275 if (reterrno != experrno) {
276 err("errno %d, expected %d", reterrno, experrno);
277 return;
278 }
279
280 if (reterrno)
281 return;
282
283 if (argc > 3) {
284 /* convert key into string */
285 keystr[0] = '\0';
286 for (nel = 0; key[nel]; nel++) {
287 if (nel)
288 (void) strcat(keystr, " ");
289 (void) strcat(keystr, key[nel]);
290 }
291
292 if (strcmp(keystr, argv[3]))
293 err("key \"%s\", expected \"%s\"", keystr, argv[3]);
294 }
295 for (nel = 0; key[nel]; nel++)
296 free(key[nel]);
297 }
298
299 /* call fm_dc_getprop() as part of a test */
300 static void
do_getprop(const char * dirpath,const char * dictname,char * argv[],int argc)301 do_getprop(const char *dirpath, const char *dictname, char *argv[], int argc)
302 {
303 int reterrno;
304 int experrno;
305 const char *val;
306
307 if (argc != 4) {
308 err("argc != 4");
309 return;
310 }
311 experrno = geterrno(argv[1]);
312
313 if (Dhp == NULL) {
314 err("getprop NULL handle");
315 return;
316 }
317
318 if ((val = fm_dc_getprop(Dhp, argv[2])) == NULL)
319 reterrno = errno;
320 else
321 reterrno = 0;
322
323 if (reterrno != experrno) {
324 err("getprop errno %d, expected %d", reterrno, experrno);
325 return;
326 }
327
328 if (reterrno == 0 && strcmp(val, argv[3]))
329 err("val \"%s\", expected \"%s\"", val, argv[3]);
330 }
331
332 /* scan a dictionary, looking for test directives embedded in the comments */
333 static void
testdict(const char * dirpath,const char * dictname)334 testdict(const char *dirpath, const char *dictname)
335 {
336 char linebuf[MAXLINE];
337 char fname[MAXLINE];
338 FILE *fp;
339
340 (void) snprintf(fname, MAXLINE, "%s/%s.dict", dirpath, dictname);
341
342 if ((fp = fopen(fname, "r")) == NULL) {
343 perror(fname);
344 Errcount++;
345 return;
346 }
347
348 Line = 0;
349 Dict = fname;
350
351 while (fgets(linebuf, MAXLINE, fp) != NULL) {
352 char *argv[MAXARG];
353 int argc;
354 char *beginp;
355 char *endp;
356
357 Line++;
358 if (strncmp(linebuf, "#TEST:", 6))
359 continue;
360
361 if ((endp = strchr(linebuf, '\n')) != NULL)
362 *endp = '\0';
363 argc = 0;
364 beginp = &linebuf[6];
365 while (argc < MAXARG - 1) {
366 argv[argc++] = beginp;
367 if ((endp = strchr(beginp, ':')) != NULL) {
368 *endp++ = '\0';
369 beginp = endp;
370 } else
371 break;
372 }
373 argv[argc] = NULL;
374
375 if (strcmp(argv[0], "open") == 0)
376 do_open(dirpath, dictname, argv, argc);
377 else if (strcmp(argv[0], "close") == 0)
378 do_close(dirpath, dictname, argv, argc);
379 else if (strcmp(argv[0], "codelen") == 0)
380 do_codelen(dirpath, dictname, argv, argc);
381 else if (strcmp(argv[0], "maxkey") == 0)
382 do_maxkey(dirpath, dictname, argv, argc);
383 else if (strcmp(argv[0], "key2code") == 0)
384 do_key2code(dirpath, dictname, argv, argc);
385 else if (strcmp(argv[0], "code2key") == 0)
386 do_code2key(dirpath, dictname, argv, argc);
387 else if (strcmp(argv[0], "getprop") == 0)
388 do_getprop(dirpath, dictname, argv, argc);
389 else {
390 err("unknown TEST command: \"%s\"", argv[0]);
391 Errcount++;
392 }
393 }
394
395 (void) fclose(fp);
396
397 if (Dhp) {
398 fm_dc_closedict(Dhp);
399 Dhp = NULL;
400 }
401 }
402
403 /* scan a directory, looking for dictionaries to test against */
404 int
main(int argc,char * argv[])405 main(int argc, char *argv[])
406 {
407 DIR *dirp;
408 struct dirent *dp;
409
410 if ((Myname = strrchr(argv[0], '/')) == NULL)
411 Myname = argv[0];
412 else
413 Myname++;
414
415 if (argc != 2) {
416 (void) fprintf(stderr, "usage: %s test-directory\n", argv[0]);
417 exit(1);
418 }
419
420 if ((dirp = opendir(argv[1])) == NULL) {
421 perror(argv[1]);
422 exit(1);
423 }
424
425 while ((dp = readdir(dirp)) != NULL) {
426 char *ptr;
427
428 if (dp->d_name[0] == '.')
429 continue;
430
431 if ((ptr = strrchr(dp->d_name, '.')) == NULL ||
432 strcmp(ptr, ".dict"))
433 continue;
434
435 *ptr = '\0'; /* remove the extension */
436 testdict(argv[1], dp->d_name);
437 }
438 (void) closedir(dirp);
439
440 if (Errcount == 0)
441 (void) printf("%s: All tests passed.\n", Myname);
442
443 return (Errcount);
444 }
445