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
dm_ParseCommandLineOptions(int argc,char ** argv)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
dm_GetCommandLineOption(char * option)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
dm_StartLogging(void)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
dm_StopLogging(void)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
dm_Error(char * format,...)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
dm_LogPrintf(u_int level,char * format,...)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
dm_ExecuteVariation(int var)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
dm_PassVariation(void)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
dm_FailVariation(void)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
dm_SkipVariation(void)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
dm_EndVariation_SuccessExpected(char * funcname,int expectedRC,int actualRC)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
dm_EndVariation_FailureExpected(char * funcname,int expectedRC,int actualRC,int expectedErrno)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
dm_CheckVariation_SuccessExpected(int expectedRC,int actualRC,dm_eventtype_t expectedEvent,dm_eventtype_t actualEvent)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
dm_CheckVariation_FailureExpected(int expectedRC,int actualRC,int expectedErrno,dm_eventtype_t expectedEvent,dm_eventtype_t actualEvent)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
dm_LogHandle(char * hdl,int len)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