1 /* 2 * Copyright (c) International Business Machines Corp., 2004 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /* 20 * FILE NAME : dm_test.c 21 * 22 * PURPOSE : Define functions and variables common to all DMAPI test cases 23 * 24 */ 25 26 #include <stdio.h> 27 #include <string.h> 28 #include <stdlib.h> 29 #include <stdarg.h> 30 #include <stdint.h> 31 #include <errno.h> 32 #include <time.h> 33 #include <fcntl.h> 34 #include <unistd.h> 35 #include <sys/time.h> 36 #include <sys/stat.h> 37 #include <sys/utsname.h> 38 #include "dm_test.h" 39 40 #define TEST_NAME "dm_test" 41 42 int dm_StartingVariation = 0; 43 int dm_StoppingVariation = INT32_MAX; 44 int dm_CurrentVariation = 0; 45 u_int dm_FileLoggingLevel = 0; 46 u_int dm_TerminalLoggingLevel = 0; 47 char *dm_LogFileName = "dm_logfile"; 48 u_int dm_PassedVariations = 0; 49 u_int dm_FailedVariations = 0; 50 u_int dm_SkippedVariations = 0; 51 char *dm_TestCaseName = TEST_NAME; 52 int dm_fdLogFile; 53 FILE *dm_fpLogFile; 54 int dm_argc = 0; 55 char **dm_argv = NULL; 56 int dm_FileNewlineNeeded; 57 int dm_TerminalNewlineNeeded; 58 59 void dm_ParseCommandLineOptions(int argc, char **argv) 60 { 61 62 int i; 63 char *p; 64 65 if ((p = strrchr(argv[0], '/')) != NULL) 66 dm_TestCaseName = ++p; 67 68 for (i = 1; i < argc; i++) { 69 if (argv[i][0] == '-') { 70 if (strcmp(&argv[i][1], "runfrom") == 0) { 71 if (i < argc - 1 && argv[i + 1][0] != '-') 72 dm_StartingVariation = atoi(argv[++i]); 73 else 74 dm_Error 75 ("invalid/missing runfrom argument\n"); 76 } else if (strcmp(&argv[i][1], "runto") == 0) { 77 if (i < argc - 1 && argv[i + 1][0] != '-') 78 dm_StoppingVariation = atoi(argv[++i]); 79 else 80 dm_Error 81 ("invalid/missing runto argument\n"); 82 } else if (strcmp(&argv[i][1], "runonly") == 0) { 83 if (i < argc - 1 && argv[i + 1][0] != '-') { 84 dm_StartingVariation = atoi(argv[++i]); 85 dm_StoppingVariation = 86 dm_StartingVariation; 87 } else 88 dm_Error 89 ("invalid/missing runonly argument\n"); 90 } else if (strcmp(&argv[i][1], "loglevel") == 0) { 91 if (i < argc - 1 && argv[i + 1][0] != '-') 92 dm_FileLoggingLevel = atoi(argv[++i]); 93 else 94 dm_Error 95 ("invalid/missing loglevel argument\n"); 96 } else if (strcmp(&argv[i][1], "termlevel") == 0) { 97 if (i < argc - 1 && argv[i + 1][0] != '-') 98 dm_TerminalLoggingLevel = 99 atoi(argv[++i]); 100 else 101 dm_Error 102 ("invalid/missing termlevel argument\n"); 103 } else if (strcmp(&argv[i][1], "logname") == 0) { 104 if (i < argc - 1 && argv[i + 1][0] != '-') 105 dm_LogFileName = argv[++i]; 106 else 107 dm_Error 108 ("invalid/missing filename argument\n"); 109 } else if (strcmp(&argv[i][1], "?") == 0 110 || strcmp(&argv[i][1], "help") == 0 111 || strcmp(&argv[i][1], "-help") == 0) { 112 printf("%s usage:\n", argv[0]); 113 printf 114 ("\t-runfrom n: set starting variation to n\n"); 115 printf 116 ("\t-runto n: set stopping variation to n\n"); 117 printf("\t-runonly n: run only variation n\n"); 118 printf 119 ("\t-loglevel n: set file logging level to n\n"); 120 printf 121 ("\t-termlevel n: set terminal logging level to n\n"); 122 printf 123 ("\t-logname s: set file log name to s\n"); 124 exit(0); 125 } else if (i < argc - 1 && argv[i + 1][0] != '-') 126 i++; 127 } 128 } 129 130 dm_argc = argc; 131 dm_argv = argv; 132 133 } 134 135 char *dm_GetCommandLineOption(char *option) 136 { 137 138 int i; 139 140 if (!dm_argc) 141 dm_Error 142 ("Cannot get command line option without calling DMOPT_PARSE"); 143 144 for (i = 1; i < dm_argc; i++) 145 if (dm_argv[i][0] == '-' && 146 strcmp(&dm_argv[i][1], option) == 0 && 147 i < dm_argc - 1 && dm_argv[i + 1][0] != '-') 148 return dm_argv[i + 1]; 149 return NULL; 150 151 } 152 153 void dm_StartLogging(void) 154 { 155 156 struct utsname buf; 157 char version[256]; 158 struct timeval tv; 159 struct tm *pDT = NULL; 160 struct tm sDT; 161 int i; 162 163 if (dm_fpLogFile) 164 dm_Error("Cannot start logging when log file already open"); 165 166 dm_fdLogFile = 167 open(dm_LogFileName, O_CREAT | O_APPEND | O_SYNC | O_WRONLY, 168 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 169 170 if (dm_fdLogFile == -1) 171 dm_Error("Unable to open log file %s", dm_LogFileName); 172 173 dm_fpLogFile = fdopen(dm_fdLogFile, "a"); 174 175 if (dm_fpLogFile == NULL) 176 dm_Error("Unable to fdopen log file %s", dm_LogFileName); 177 178 if (uname(&buf) == -1) 179 strcpy(version, "Unknown Linux version"); 180 else 181 sprintf(version, "%s %s", buf.sysname, buf.release); 182 183 if (gettimeofday(&tv, NULL) != -1) 184 pDT = (struct tm *)localtime_r(&tv.tv_sec, &sDT); 185 186 if (dm_FileLoggingLevel) { 187 fprintf(dm_fpLogFile, "%s running on %s\n", TEST_NAME, version); 188 fprintf(dm_fpLogFile, "%s invoked with ", dm_TestCaseName); 189 for (i = 1; i < dm_argc; i++) 190 fprintf(dm_fpLogFile, "%s ", dm_argv[i]); 191 if (pDT) 192 fprintf(dm_fpLogFile, 193 "\n%s starting at %02u:%02u:%02u on %02u/%02u/%04u\n", 194 dm_TestCaseName, pDT->tm_hour, pDT->tm_min, 195 pDT->tm_sec, pDT->tm_mon + 1, pDT->tm_mday, 196 pDT->tm_year + 1900); 197 else 198 fprintf(dm_fpLogFile, "\n%s starting\n", 199 dm_TestCaseName); 200 201 } 202 203 if (dm_TerminalLoggingLevel) { 204 printf("%s running on %s\n", TEST_NAME, version); 205 printf("%s invoked with ", dm_TestCaseName); 206 for (i = 1; i < dm_argc; i++) 207 printf("%s ", dm_argv[i]); 208 if (pDT) 209 printf 210 ("\n%s starting at %02u:%02u:%02u on %02u/%02u/%04u\n", 211 dm_TestCaseName, pDT->tm_hour, pDT->tm_min, 212 pDT->tm_sec, pDT->tm_mon + 1, pDT->tm_mday, 213 pDT->tm_year + 1900); 214 else 215 printf("\n%s starting\n", dm_TestCaseName); 216 } 217 218 } 219 220 void dm_StopLogging(void) 221 { 222 223 struct timeval tv; 224 struct tm *pDT = NULL; 225 struct tm sDT; 226 int ranVariations = 0; 227 int percentSuccess = 0; 228 229 if (!dm_fpLogFile) 230 dm_Error("Cannot stop logging when log file not already open"); 231 232 ranVariations = dm_PassedVariations + dm_FailedVariations; 233 234 if (dm_PassedVariations) 235 percentSuccess = (dm_PassedVariations * 100) / ranVariations; 236 237 if (gettimeofday(&tv, NULL) != -1) 238 pDT = (struct tm *)localtime_r(&tv.tv_sec, &sDT); 239 240 if (dm_FileLoggingLevel) { 241 if (pDT) 242 fprintf(dm_fpLogFile, 243 "%s stopping at %02u:%02u:%02u on %02u/%02u/%04u\n", 244 dm_TestCaseName, pDT->tm_hour, pDT->tm_min, 245 pDT->tm_sec, pDT->tm_mon + 1, pDT->tm_mday, 246 pDT->tm_year + 1900); 247 else 248 fprintf(dm_fpLogFile, "%s stopping\n", dm_TestCaseName); 249 250 fprintf(dm_fpLogFile, 251 "%s status: %u executed, %u passed, %u failed, %u skipped (%u%%)\n", 252 dm_TestCaseName, ranVariations, dm_PassedVariations, 253 dm_FailedVariations, dm_SkippedVariations, 254 percentSuccess); 255 } 256 257 if (dm_TerminalLoggingLevel) { 258 if (pDT) 259 printf 260 ("%s stopping at %02u:%02u:%02u on %02u/%02u/%04u\n", 261 dm_TestCaseName, pDT->tm_hour, pDT->tm_min, 262 pDT->tm_sec, pDT->tm_mon + 1, pDT->tm_mday, 263 pDT->tm_year + 1900); 264 else 265 printf("%s stopping\n", dm_TestCaseName); 266 267 printf 268 ("%s status: %u executed, %u passed, %u failed, %u skipped (%u%%)\n", 269 dm_TestCaseName, ranVariations, dm_PassedVariations, 270 dm_FailedVariations, dm_SkippedVariations, percentSuccess); 271 } 272 273 fclose(dm_fpLogFile); 274 close(dm_fdLogFile); 275 276 } 277 278 void dm_Error(char *format, ...) 279 { 280 va_list args; 281 char fmtmsg[256]; 282 283 /* 284 * Format error message including message inserts 285 */ 286 va_start(args, format); 287 vsprintf(fmtmsg, format, args); 288 va_end(args); 289 290 /* 291 * Display error message if not detached or Presentation Manager process 292 */ 293 printf("\n%s fatal error: %s\n", TEST_NAME, fmtmsg); 294 295 } 296 297 void dm_LogPrintf(u_int level, char *format, ...) 298 { 299 300 va_list args; 301 302 va_start(args, format); 303 if (level <= dm_FileLoggingLevel) { 304 fprintf(dm_fpLogFile, "[%s %d %d] ", dm_TestCaseName, getpid(), 305 level); 306 vfprintf(dm_fpLogFile, format, args); 307 dm_FileNewlineNeeded = 1; 308 } 309 va_end(args); 310 va_start(args, format); 311 if (level <= dm_TerminalLoggingLevel) { 312 printf("[%s %d %d] ", dm_TestCaseName, getpid(), level); 313 vprintf(format, args); 314 dm_TerminalNewlineNeeded = 1; 315 } 316 va_end(args); 317 318 } 319 320 int dm_ExecuteVariation(int var) 321 { 322 323 if (dm_CurrentVariation) 324 dm_Error("Cannot execute variation while variation active\n"); 325 if (var < dm_StartingVariation || var > dm_StoppingVariation) 326 return 0; 327 328 dm_CurrentVariation = var; 329 330 if (dm_FileNewlineNeeded) 331 fputc('\n', dm_fpLogFile); 332 if (dm_TerminalNewlineNeeded) 333 putchar('\n'); 334 335 dm_LogPrintf(DMLVL_DEBUG, "Variation %d starting\n", var); 336 337 return 1; 338 339 } 340 341 void dm_PassVariation(void) 342 { 343 344 if (!dm_CurrentVariation) 345 dm_Error("Cannot pass variation while variation not active\n"); 346 347 dm_LogPrintf(DMLVL_DEBUG, "Variation %d passed\n\n", 348 dm_CurrentVariation); 349 dm_FileNewlineNeeded = dm_TerminalNewlineNeeded = 0; 350 351 dm_PassedVariations++; 352 353 dm_CurrentVariation = 0; 354 355 } 356 357 void dm_FailVariation(void) 358 { 359 360 if (!dm_CurrentVariation) 361 dm_Error("Cannot fail variation while variation not active\n"); 362 363 dm_LogPrintf(DMLVL_DEBUG, "Variation %d failed\n\n", 364 dm_CurrentVariation); 365 dm_FileNewlineNeeded = dm_TerminalNewlineNeeded = 0; 366 367 dm_FailedVariations++; 368 369 dm_CurrentVariation = 0; 370 371 } 372 373 void dm_SkipVariation(void) 374 { 375 376 if (!dm_CurrentVariation) 377 dm_Error("Cannot skip variation while variation not active\n"); 378 379 dm_LogPrintf(DMLVL_DEBUG, "Variation %d skipped\n\n", 380 dm_CurrentVariation); 381 dm_FileNewlineNeeded = dm_TerminalNewlineNeeded = 0; 382 383 dm_SkippedVariations++; 384 385 dm_CurrentVariation = 0; 386 387 } 388 389 void dm_EndVariation_SuccessExpected(char *funcname, int expectedRC, 390 int actualRC) 391 { 392 393 if (actualRC == expectedRC) { 394 DMLOG_PRINT(DMLVL_DEBUG, "%s passed with expected rc = %d\n", 395 funcname, expectedRC); 396 DMVAR_PASS(); 397 } else { 398 DMLOG_PRINT(DMLVL_ERR, 399 "%s failed with unexpected rc = %d (errno = %d)\n", 400 funcname, actualRC, errno); 401 DMVAR_FAIL(); 402 } 403 404 } 405 406 void dm_EndVariation_FailureExpected(char *funcname, int expectedRC, 407 int actualRC, int expectedErrno) 408 { 409 410 if (actualRC == expectedRC) { 411 if (errno == expectedErrno) { 412 DMLOG_PRINT(DMLVL_DEBUG, 413 "%s passed with expected rc = %d and expected errno = %d\n", 414 funcname, expectedRC, expectedErrno); 415 DMVAR_PASS(); 416 } else { 417 DMLOG_PRINT(DMLVL_ERR, 418 "%s failed with expected rc = %d but unexpected errno = %d (expected %d)\n", 419 funcname, expectedRC, errno, expectedErrno); 420 DMVAR_FAIL(); 421 } 422 } else { 423 DMLOG_PRINT(DMLVL_ERR, "%s failed with unexpected rc = %d\n", 424 funcname, actualRC); 425 DMVAR_FAIL(); 426 } 427 428 } 429 430 int dm_CheckVariation_SuccessExpected(int expectedRC, int actualRC, 431 dm_eventtype_t expectedEvent, 432 dm_eventtype_t actualEvent) 433 { 434 435 if (expectedEvent == actualEvent) { 436 if (actualRC == expectedRC) { 437 DMLOG_PRINT(DMLVL_DEBUG, 438 "Passed, received expected event %d\n", 439 expectedEvent); 440 return DMSTAT_PASS; 441 } else { 442 DMLOG_PRINT(DMLVL_ERR, 443 "Failed, received expected event %d but unexpected rc = %d (expected %d)\n", 444 expectedEvent, actualRC, expectedRC); 445 return DMSTAT_FAIL; 446 } 447 } else { 448 DMLOG_PRINT(DMLVL_ERR, 449 "Failed, received unexpected event %d (expected %d)\n", 450 actualEvent, expectedEvent); 451 return DMSTAT_FAIL; 452 } 453 454 } 455 456 int dm_CheckVariation_FailureExpected(int expectedRC, int actualRC, 457 int expectedErrno, 458 dm_eventtype_t expectedEvent, 459 dm_eventtype_t actualEvent) 460 { 461 462 if (expectedEvent == actualEvent) { 463 if (actualRC == expectedRC) { 464 if (errno == expectedErrno) { 465 DMLOG_PRINT(DMLVL_DEBUG, 466 "Passed, received expected event %d\n", 467 expectedEvent); 468 return DMSTAT_PASS; 469 } else { 470 DMLOG_PRINT(DMLVL_ERR, 471 "Failed, received expected event %d but unexpected errno = %d (expected %d)\n", 472 expectedEvent, errno, 473 expectedErrno); 474 return DMSTAT_FAIL; 475 } 476 } else { 477 DMLOG_PRINT(DMLVL_ERR, 478 "Failed, received expected event %d but unexpected rc = %d (expected %d)\n", 479 expectedEvent, actualRC, expectedRC); 480 return DMSTAT_FAIL; 481 } 482 } else { 483 DMLOG_PRINT(DMLVL_ERR, 484 "Failed, received unexpected event %d (expected %d)\n", 485 actualEvent, expectedEvent); 486 return DMSTAT_FAIL; 487 } 488 489 } 490 491 void dm_LogHandle(char *hdl, int len) 492 { 493 494 int i; 495 char outbuf[256], *pch; 496 497 memset(outbuf, 0, sizeof(outbuf)); 498 499 for (i = 0, pch = outbuf; i < len; i++, pch += 3) 500 sprintf(pch, " %02X", hdl[i]); 501 502 DMLOG_PRINT(DMLVL_DEBUG, "Handle: %s\n", outbuf); 503 504 } 505 506 /* This static array is for the persistent managed region test */ 507 dm_region_t dm_PMR_regbuf[PMR_NUM_REGIONS] = { 508 #ifdef MULTIPLE_REGIONS 509 {0, 1000, DM_REGION_WRITE} 510 , 511 {2000, 1000, DM_REGION_TRUNCATE} 512 , 513 {3005, 995, DM_REGION_READ} 514 , 515 {5432, 2345, DM_REGION_NOEVENT} 516 , 517 #endif 518 {8000, 0, DM_REGION_READ | DM_REGION_WRITE | DM_REGION_TRUNCATE} 519 }; 520 521 /* Include implementation-dependent functions and variables */ 522 #include "dm_impl.h" 523