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 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <ctype.h> 44 #include <alloca.h> 45 #include <errno.h> 46 #include <sys/types.h> 47 #include <dirent.h> 48 #include <stdarg.h> 49 50 #include <fm/diagcode.h> 51 52 #define MAXLINE 10240 53 #define MAXARG 10 54 #define MAXKEY 100 55 #define MAXCODE 100 56 57 static char *Myname; 58 static char *Dict; 59 static int Line; 60 static int Errcount; 61 static fm_dc_handle_t *Dhp; 62 63 /*PRINTFLIKE1*/ 64 static void 65 err(const char *fmt, ...) 66 { 67 va_list ap; 68 69 va_start(ap, fmt); 70 (void) fprintf(stderr, "%s: %s:%d ", Myname, Dict, Line); 71 (void) vfprintf(stderr, fmt, ap); 72 (void) fprintf(stderr, "\n"); 73 Errcount++; 74 } 75 76 /* parse an expected errno value from test line (numeric or some symbolic) */ 77 static int 78 geterrno(const char *s) 79 { 80 if (*s == '\0' || isspace(*s)) 81 return (0); 82 else if (isdigit(*s)) 83 return (atoi(s)); 84 else if (strcmp(s, "EPERM") == 0) 85 return (EPERM); 86 else if (strcmp(s, "ENOENT") == 0) 87 return (ENOENT); 88 else if (strcmp(s, "ESRCH") == 0) 89 return (ESRCH); 90 else if (strcmp(s, "ENOMEM") == 0) 91 return (ENOMEM); 92 else if (strcmp(s, "EACCES") == 0) 93 return (EACCES); 94 else if (strcmp(s, "EINVAL") == 0) 95 return (EINVAL); 96 else if (strcmp(s, "ERANGE") == 0) 97 return (ERANGE); 98 else if (strcmp(s, "ENOMSG") == 0) 99 return (ENOMSG); 100 else if (strcmp(s, "ENOTSUP") == 0) 101 return (ENOTSUP); 102 else { 103 err("geterrno: don't know errno \"%s\"", s); 104 Errcount++; 105 return (0); 106 } 107 } 108 109 /* call fm_dc_opendict() as part of a test */ 110 static void 111 do_open(const char *dirpath, const char *dictname, char *argv[], int argc) 112 { 113 int reterrno; 114 int experrno; 115 116 if (argc != 2) { 117 err("argc != 2"); 118 return; 119 } 120 experrno = geterrno(argv[1]); 121 122 if ((Dhp = fm_dc_opendict(FM_DC_VERSION, dirpath, dictname)) == NULL) 123 reterrno = errno; 124 else 125 reterrno = 0; 126 127 if (reterrno != experrno) 128 err("opendict errno %d, expected %d", reterrno, experrno); 129 } 130 131 /* call fm_dc_closedict() as part of a test */ 132 static void 133 do_close(const char *dirpath, const char *dictname, char *argv[], int argc) 134 { 135 if (Dhp) { 136 fm_dc_closedict(Dhp); 137 Dhp = NULL; 138 } 139 } 140 141 /* call fm_dc_codelen() as part of a test */ 142 static void 143 do_codelen(const char *dirpath, const char *dictname, char *argv[], int argc) 144 { 145 int retcodelen; 146 int expcodelen; 147 148 if (argc != 3) { 149 err("argc != 3"); 150 return; 151 } 152 expcodelen = geterrno(argv[2]); 153 154 if (Dhp == NULL) { 155 err("codelen NULL handle"); 156 return; 157 } 158 159 retcodelen = fm_dc_codelen(Dhp); 160 161 if (retcodelen != expcodelen) 162 err("codelen %d, expected %d", retcodelen, expcodelen); 163 } 164 165 /* call fm_dc_maxkey() as part of a test */ 166 static void 167 do_maxkey(const char *dirpath, const char *dictname, char *argv[], int argc) 168 { 169 int retmaxkey; 170 int expmaxkey; 171 172 if (argc != 3) { 173 err("argc != 3"); 174 return; 175 } 176 expmaxkey = geterrno(argv[2]); 177 178 if (Dhp == NULL) { 179 err("maxkey NULL handle"); 180 return; 181 } 182 183 retmaxkey = fm_dc_maxkey(Dhp); 184 185 if (retmaxkey != expmaxkey) 186 err("maxkey %d, expected %d", retmaxkey, expmaxkey); 187 } 188 189 /* call fm_dc_key2code() as part of a test */ 190 static void 191 do_key2code(const char *dirpath, const char *dictname, char *argv[], int argc) 192 { 193 int reterrno; 194 int experrno; 195 const char *key[MAXKEY]; 196 char code[MAXCODE]; 197 int nel; 198 char *beginp; 199 char *endp; 200 201 if (argc < 3) { 202 err("argc < 3"); 203 return; 204 } 205 if (argc > 4) { 206 err("argc > 4"); 207 return; 208 } 209 experrno = geterrno(argv[1]); 210 211 /* convert key into array */ 212 nel = 0; 213 beginp = argv[2]; 214 while (nel < MAXKEY - 1) { 215 key[nel++] = beginp; 216 if ((endp = strchr(beginp, ' ')) != NULL) { 217 *endp++ = '\0'; 218 beginp = endp; 219 } else 220 break; 221 } 222 key[nel] = NULL; 223 224 if (Dhp == NULL) { 225 err("key2code NULL handle"); 226 return; 227 } 228 229 if (fm_dc_key2code(Dhp, key, code, MAXCODE) < 0) 230 reterrno = errno; 231 else 232 reterrno = 0; 233 234 if (reterrno != experrno) { 235 err("key2code errno %d, expected %d", reterrno, experrno); 236 return; 237 } 238 239 if (reterrno == 0 && argc > 3 && strcmp(code, argv[3])) 240 err("code \"%s\", expected \"%s\"", code, argv[3]); 241 } 242 243 /* call fm_dc_code2key() as part of a test */ 244 static void 245 do_code2key(const char *dirpath, const char *dictname, char *argv[], int argc) 246 { 247 int reterrno; 248 int experrno; 249 char keystr[MAXLINE]; 250 char *key[MAXKEY]; 251 int nel; 252 253 if (argc < 3) { 254 err("argc < 3"); 255 return; 256 } 257 if (argc > 4) { 258 err("argc > 4"); 259 return; 260 } 261 experrno = geterrno(argv[1]); 262 263 if (Dhp == NULL) { 264 err("code2key NULL handle"); 265 return; 266 } 267 268 if (fm_dc_code2key(Dhp, argv[2], key, fm_dc_maxkey(Dhp)) < 0) 269 reterrno = errno; 270 else 271 reterrno = 0; 272 273 if (reterrno != experrno) { 274 err("errno %d, expected %d", reterrno, experrno); 275 return; 276 } 277 278 if (reterrno) 279 return; 280 281 if (argc > 3) { 282 /* convert key into string */ 283 keystr[0] = '\0'; 284 for (nel = 0; key[nel]; nel++) { 285 if (nel) 286 (void) strcat(keystr, " "); 287 (void) strcat(keystr, key[nel]); 288 } 289 290 if (strcmp(keystr, argv[3])) 291 err("key \"%s\", expected \"%s\"", keystr, argv[3]); 292 } 293 for (nel = 0; key[nel]; nel++) 294 free(key[nel]); 295 } 296 297 /* call fm_dc_getprop() as part of a test */ 298 static void 299 do_getprop(const char *dirpath, const char *dictname, char *argv[], int argc) 300 { 301 int reterrno; 302 int experrno; 303 const char *val; 304 305 if (argc != 4) { 306 err("argc != 4"); 307 return; 308 } 309 experrno = geterrno(argv[1]); 310 311 if (Dhp == NULL) { 312 err("getprop NULL handle"); 313 return; 314 } 315 316 if ((val = fm_dc_getprop(Dhp, argv[2])) == NULL) 317 reterrno = errno; 318 else 319 reterrno = 0; 320 321 if (reterrno != experrno) { 322 err("getprop errno %d, expected %d", reterrno, experrno); 323 return; 324 } 325 326 if (reterrno == 0 && strcmp(val, argv[3])) 327 err("val \"%s\", expected \"%s\"", val, argv[3]); 328 } 329 330 /* scan a dictionary, looking for test directives embedded in the comments */ 331 static void 332 testdict(const char *dirpath, const char *dictname) 333 { 334 char linebuf[MAXLINE]; 335 char fname[MAXLINE]; 336 FILE *fp; 337 338 (void) snprintf(fname, MAXLINE, "%s/%s.dict", dirpath, dictname); 339 340 if ((fp = fopen(fname, "r")) == NULL) { 341 perror(fname); 342 Errcount++; 343 return; 344 } 345 346 Line = 0; 347 Dict = fname; 348 349 while (fgets(linebuf, MAXLINE, fp) != NULL) { 350 char *argv[MAXARG]; 351 int argc; 352 char *beginp; 353 char *endp; 354 355 Line++; 356 if (strncmp(linebuf, "#TEST:", 6)) 357 continue; 358 359 if ((endp = strchr(linebuf, '\n')) != NULL) 360 *endp = '\0'; 361 argc = 0; 362 beginp = &linebuf[6]; 363 while (argc < MAXARG - 1) { 364 argv[argc++] = beginp; 365 if ((endp = strchr(beginp, ':')) != NULL) { 366 *endp++ = '\0'; 367 beginp = endp; 368 } else 369 break; 370 } 371 argv[argc] = NULL; 372 373 if (strcmp(argv[0], "open") == 0) 374 do_open(dirpath, dictname, argv, argc); 375 else if (strcmp(argv[0], "close") == 0) 376 do_close(dirpath, dictname, argv, argc); 377 else if (strcmp(argv[0], "codelen") == 0) 378 do_codelen(dirpath, dictname, argv, argc); 379 else if (strcmp(argv[0], "maxkey") == 0) 380 do_maxkey(dirpath, dictname, argv, argc); 381 else if (strcmp(argv[0], "key2code") == 0) 382 do_key2code(dirpath, dictname, argv, argc); 383 else if (strcmp(argv[0], "code2key") == 0) 384 do_code2key(dirpath, dictname, argv, argc); 385 else if (strcmp(argv[0], "getprop") == 0) 386 do_getprop(dirpath, dictname, argv, argc); 387 else { 388 err("unknown TEST command: \"%s\"", argv[0]); 389 Errcount++; 390 } 391 } 392 393 (void) fclose(fp); 394 395 if (Dhp) { 396 fm_dc_closedict(Dhp); 397 Dhp = NULL; 398 } 399 } 400 401 /* scan a directory, looking for dictionaries to test against */ 402 int 403 main(int argc, char *argv[]) 404 { 405 DIR *dirp; 406 struct dirent *dp; 407 408 if ((Myname = strrchr(argv[0], '/')) == NULL) 409 Myname = argv[0]; 410 else 411 Myname++; 412 413 if (argc != 2) { 414 (void) fprintf(stderr, "usage: %s test-directory\n", argv[0]); 415 exit(1); 416 } 417 418 if ((dirp = opendir(argv[1])) == NULL) { 419 perror(argv[1]); 420 exit(1); 421 } 422 423 while ((dp = readdir(dirp)) != NULL) { 424 char *ptr; 425 426 if (dp->d_name[0] == '.') 427 continue; 428 429 if ((ptr = strrchr(dp->d_name, '.')) == NULL || 430 strcmp(ptr, ".dict")) 431 continue; 432 433 *ptr = '\0'; /* remove the extension */ 434 testdict(argv[1], dp->d_name); 435 } 436 (void) closedir(dirp); 437 438 if (Errcount == 0) 439 (void) printf("%s: All tests passed.\n", Myname); 440 441 return (Errcount); 442 } 443