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 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 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 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 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 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 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 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 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 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 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 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