blob: 326de4b06eb85a5bf541d14d351f1895eec9a400 [file] [log] [blame]
/*
* Copyright (c) International Business Machines Corp., 2004
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* FILE NAME : dm_test.c
*
* PURPOSE : Define functions and variables common to all DMAPI test cases
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include "dm_test.h"
#define TEST_NAME "dm_test"
int dm_StartingVariation = 0;
int dm_StoppingVariation = INT32_MAX;
int dm_CurrentVariation = 0;
u_int dm_FileLoggingLevel = 0;
u_int dm_TerminalLoggingLevel = 0;
char *dm_LogFileName = "dm_logfile";
u_int dm_PassedVariations = 0;
u_int dm_FailedVariations = 0;
u_int dm_SkippedVariations = 0;
char *dm_TestCaseName = TEST_NAME;
int dm_fdLogFile;
FILE *dm_fpLogFile;
int dm_argc = 0;
char **dm_argv = NULL;
int dm_FileNewlineNeeded;
int dm_TerminalNewlineNeeded;
void dm_ParseCommandLineOptions(int argc, char **argv) {
int i;
char *p;
if ((p = strrchr(argv[0], '/')) != NULL)
dm_TestCaseName = ++p;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
if (strcmp(&argv[i][1], "runfrom") == 0) {
if (i < argc - 1 && argv[i+1][0] != '-')
dm_StartingVariation = atoi(argv[++i]);
else
dm_Error("invalid/missing runfrom argument\n");
} else if (strcmp(&argv[i][1], "runto") == 0) {
if (i < argc - 1 && argv[i+1][0] != '-')
dm_StoppingVariation = atoi(argv[++i]);
else
dm_Error("invalid/missing runto argument\n");
} else if (strcmp(&argv[i][1], "runonly") == 0) {
if (i < argc - 1 && argv[i+1][0] != '-') {
dm_StartingVariation = atoi(argv[++i]);
dm_StoppingVariation = dm_StartingVariation;
} else
dm_Error("invalid/missing runonly argument\n");
} else if (strcmp(&argv[i][1], "loglevel") == 0) {
if (i < argc - 1 && argv[i+1][0] != '-')
dm_FileLoggingLevel = atoi(argv[++i]);
else
dm_Error("invalid/missing loglevel argument\n");
} else if (strcmp(&argv[i][1], "termlevel") == 0) {
if (i < argc - 1 && argv[i+1][0] != '-')
dm_TerminalLoggingLevel = atoi(argv[++i]);
else
dm_Error("invalid/missing termlevel argument\n");
} else if (strcmp(&argv[i][1], "logname") == 0) {
if (i < argc - 1 && argv[i+1][0] != '-')
dm_LogFileName = argv[++i];
else
dm_Error("invalid/missing filename argument\n");
} else if (strcmp(&argv[i][1], "?") == 0 ||
strcmp(&argv[i][1], "help") == 0 ||
strcmp(&argv[i][1], "-help") == 0) {
printf("%s usage:\n", argv[0]);
printf("\t-runfrom n: set starting variation to n\n");
printf("\t-runto n: set stopping variation to n\n");
printf("\t-runonly n: run only variation n\n");
printf("\t-loglevel n: set file logging level to n\n");
printf("\t-termlevel n: set terminal logging level to n\n");
printf("\t-logname s: set file log name to s\n");
exit(0);
} else if (i < argc - 1 && argv[i+1][0] != '-')
i++;
}
}
dm_argc = argc;
dm_argv = argv;
}
char *dm_GetCommandLineOption(char *option) {
int i;
if (!dm_argc)
dm_Error("Cannot get command line option without calling DMOPT_PARSE");
for (i = 1; i < dm_argc; i++)
if (dm_argv[i][0] == '-' &&
strcmp(&dm_argv[i][1], option) == 0 &&
i < dm_argc - 1 && dm_argv[i+1][0] != '-')
return dm_argv[i+1];
return NULL;
}
void dm_StartLogging(void) {
struct utsname buf;
char version[256];
struct timeval tv;
struct tm *pDT = NULL;
struct tm sDT;
int i;
if (dm_fpLogFile)
dm_Error("Cannot start logging when log file already open");
dm_fdLogFile = open(dm_LogFileName, O_CREAT|O_APPEND|O_SYNC|O_WRONLY,
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
if (dm_fdLogFile == -1)
dm_Error("Unable to open log file %s", dm_LogFileName);
dm_fpLogFile = fdopen(dm_fdLogFile, "a");
if (dm_fpLogFile == NULL)
dm_Error("Unable to fdopen log file %s", dm_LogFileName);
if (uname(&buf) == -1)
strcpy(version, "Unknown Linux version");
else
sprintf(version, "%s %s", buf.sysname, buf.release);
if (gettimeofday(&tv, NULL) != -1)
pDT = (struct tm *)localtime_r(&tv.tv_sec, &sDT);
if (dm_FileLoggingLevel) {
fprintf(dm_fpLogFile, "%s running on %s\n", TEST_NAME, version);
fprintf(dm_fpLogFile, "%s invoked with ", dm_TestCaseName);
for (i = 1; i < dm_argc; i++)
fprintf(dm_fpLogFile, "%s ", dm_argv[i]);
if (pDT)
fprintf(dm_fpLogFile, "\n%s starting at %02u:%02u:%02u on %02u/%02u/%04u\n", dm_TestCaseName, pDT->tm_hour, pDT->tm_min, pDT->tm_sec, pDT->tm_mon+1, pDT->tm_mday, pDT->tm_year+1900);
else
fprintf(dm_fpLogFile, "\n%s starting\n", dm_TestCaseName);
}
if (dm_TerminalLoggingLevel) {
printf("%s running on %s\n", TEST_NAME, version);
printf("%s invoked with ", dm_TestCaseName);
for (i = 1; i < dm_argc; i++)
printf("%s ", dm_argv[i]);
if (pDT)
printf("\n%s starting at %02u:%02u:%02u on %02u/%02u/%04u\n", dm_TestCaseName, pDT->tm_hour, pDT->tm_min, pDT->tm_sec, pDT->tm_mon+1, pDT->tm_mday, pDT->tm_year+1900);
else
printf("\n%s starting\n", dm_TestCaseName);
}
}
void dm_StopLogging(void) {
struct timeval tv;
struct tm *pDT = NULL;
struct tm sDT;
int ranVariations = 0;
int percentSuccess = 0;
if (!dm_fpLogFile)
dm_Error("Cannot stop logging when log file not already open");
ranVariations = dm_PassedVariations + dm_FailedVariations;
if (dm_PassedVariations)
percentSuccess = (dm_PassedVariations * 100)/ranVariations;
if (gettimeofday(&tv, NULL) != -1)
pDT = (struct tm *)localtime_r(&tv.tv_sec, &sDT);
if (dm_FileLoggingLevel) {
if (pDT)
fprintf(dm_fpLogFile, "%s stopping at %02u:%02u:%02u on %02u/%02u/%04u\n", dm_TestCaseName, pDT->tm_hour, pDT->tm_min, pDT->tm_sec, pDT->tm_mon+1, pDT->tm_mday, pDT->tm_year+1900);
else
fprintf(dm_fpLogFile, "%s stopping\n", dm_TestCaseName);
fprintf(dm_fpLogFile, "%s status: %u executed, %u passed, %u failed, %u skipped (%u%%)\n", dm_TestCaseName, ranVariations, dm_PassedVariations, dm_FailedVariations, dm_SkippedVariations, percentSuccess);
}
if (dm_TerminalLoggingLevel) {
if (pDT)
printf("%s stopping at %02u:%02u:%02u on %02u/%02u/%04u\n", dm_TestCaseName, pDT->tm_hour, pDT->tm_min, pDT->tm_sec, pDT->tm_mon+1, pDT->tm_mday, pDT->tm_year+1900);
else
printf("%s stopping\n", dm_TestCaseName);
printf("%s status: %u executed, %u passed, %u failed, %u skipped (%u%%)\n", dm_TestCaseName, ranVariations, dm_PassedVariations, dm_FailedVariations, dm_SkippedVariations, percentSuccess);
}
fclose(dm_fpLogFile);
close(dm_fdLogFile);
}
void dm_Error(char *format, ...) {
va_list args;
char fmtmsg[256];
/*
* Format error message including message inserts
*/
va_start(args, format);
vsprintf(fmtmsg, format, args);
va_end(args);
/*
* Display error message if not detached or Presentation Manager process
*/
printf("\n%s fatal error: %s\n", TEST_NAME, fmtmsg);
}
void dm_LogPrintf(u_int level, char *format, ...) {
va_list args;
va_start(args, format);
if (level <= dm_FileLoggingLevel) {
fprintf(dm_fpLogFile, "[%s %d %d] ", dm_TestCaseName, getpid(), level);
vfprintf(dm_fpLogFile, format, args);
dm_FileNewlineNeeded = 1;
}
va_end(args);
va_start(args, format);
if (level <= dm_TerminalLoggingLevel) {
printf("[%s %d %d] ", dm_TestCaseName, getpid(), level);
vprintf(format, args);
dm_TerminalNewlineNeeded = 1;
}
va_end(args);
}
int dm_ExecuteVariation(int var) {
if (dm_CurrentVariation)
dm_Error("Cannot execute variation while variation active\n");
if (var < dm_StartingVariation || var > dm_StoppingVariation)
return 0;
dm_CurrentVariation = var;
if (dm_FileNewlineNeeded)
fputc('\n', dm_fpLogFile);
if (dm_TerminalNewlineNeeded)
putchar('\n');
dm_LogPrintf(DMLVL_DEBUG, "Variation %d starting\n", var);
return 1;
}
void dm_PassVariation(void) {
if (!dm_CurrentVariation)
dm_Error("Cannot pass variation while variation not active\n");
dm_LogPrintf(DMLVL_DEBUG, "Variation %d passed\n\n", dm_CurrentVariation);
dm_FileNewlineNeeded = dm_TerminalNewlineNeeded = 0;
dm_PassedVariations++;
dm_CurrentVariation = 0;
}
void dm_FailVariation(void) {
if (!dm_CurrentVariation)
dm_Error("Cannot fail variation while variation not active\n");
dm_LogPrintf(DMLVL_DEBUG, "Variation %d failed\n\n", dm_CurrentVariation);
dm_FileNewlineNeeded = dm_TerminalNewlineNeeded = 0;
dm_FailedVariations++;
dm_CurrentVariation = 0;
}
void dm_SkipVariation(void) {
if (!dm_CurrentVariation)
dm_Error("Cannot skip variation while variation not active\n");
dm_LogPrintf(DMLVL_DEBUG, "Variation %d skipped\n\n", dm_CurrentVariation);
dm_FileNewlineNeeded = dm_TerminalNewlineNeeded = 0;
dm_SkippedVariations++;
dm_CurrentVariation = 0;
}
void dm_EndVariation_SuccessExpected(char *funcname, int expectedRC, int actualRC)
{
if (actualRC == expectedRC) {
DMLOG_PRINT(DMLVL_DEBUG, "%s passed with expected rc = %d\n", funcname, expectedRC);
DMVAR_PASS();
} else {
DMLOG_PRINT(DMLVL_ERR, "%s failed with unexpected rc = %d (errno = %d)\n", funcname, actualRC, errno);
DMVAR_FAIL();
}
}
void dm_EndVariation_FailureExpected(char *funcname, int expectedRC, int actualRC, int expectedErrno)
{
if (actualRC == expectedRC) {
if (errno == expectedErrno) {
DMLOG_PRINT(DMLVL_DEBUG, "%s passed with expected rc = %d and expected errno = %d\n", funcname, expectedRC, expectedErrno);
DMVAR_PASS();
} else {
DMLOG_PRINT(DMLVL_ERR, "%s failed with expected rc = %d but unexpected errno = %d (expected %d)\n", funcname, expectedRC, errno, expectedErrno);
DMVAR_FAIL();
}
} else {
DMLOG_PRINT(DMLVL_ERR, "%s failed with unexpected rc = %d\n", funcname, actualRC);
DMVAR_FAIL();
}
}
int dm_CheckVariation_SuccessExpected(int expectedRC, int actualRC, dm_eventtype_t expectedEvent, dm_eventtype_t actualEvent)
{
if (expectedEvent == actualEvent) {
if (actualRC == expectedRC) {
DMLOG_PRINT(DMLVL_DEBUG, "Passed, received expected event %d\n", expectedEvent);
return DMSTAT_PASS;
} else {
DMLOG_PRINT(DMLVL_ERR, "Failed, received expected event %d but unexpected rc = %d (expected %d)\n", expectedEvent, actualRC, expectedRC);
return DMSTAT_FAIL;
}
} else {
DMLOG_PRINT(DMLVL_ERR, "Failed, received unexpected event %d (expected %d)\n", actualEvent, expectedEvent);
return DMSTAT_FAIL;
}
}
int dm_CheckVariation_FailureExpected(int expectedRC, int actualRC, int expectedErrno, dm_eventtype_t expectedEvent, dm_eventtype_t actualEvent)
{
if (expectedEvent == actualEvent) {
if (actualRC == expectedRC) {
if (errno == expectedErrno) {
DMLOG_PRINT(DMLVL_DEBUG, "Passed, received expected event %d\n", expectedEvent);
return DMSTAT_PASS;
} else {
DMLOG_PRINT(DMLVL_ERR, "Failed, received expected event %d but unexpected errno = %d (expected %d)\n", expectedEvent, errno, expectedErrno);
return DMSTAT_FAIL;
}
} else {
DMLOG_PRINT(DMLVL_ERR, "Failed, received expected event %d but unexpected rc = %d (expected %d)\n", expectedEvent, actualRC, expectedRC);
return DMSTAT_FAIL;
}
} else {
DMLOG_PRINT(DMLVL_ERR, "Failed, received unexpected event %d (expected %d)\n", actualEvent, expectedEvent);
return DMSTAT_FAIL;
}
}
void dm_LogHandle(char *hdl, int len) {
int i;
char outbuf[256], *pch;
memset(outbuf, 0, sizeof(outbuf));
for (i = 0, pch = outbuf; i < len; i++, pch += 3)
sprintf(pch, " %02X", hdl[i]);
DMLOG_PRINT(DMLVL_DEBUG, "Handle: %s\n", outbuf);
}
/* This static array is for the persistent managed region test */
dm_region_t dm_PMR_regbuf[PMR_NUM_REGIONS] = {
#ifdef MULTIPLE_REGIONS
{ 0, 1000, DM_REGION_WRITE },
{ 2000, 1000, DM_REGION_TRUNCATE },
{ 3005, 995, DM_REGION_READ },
{ 5432, 2345, DM_REGION_NOEVENT },
#endif
{ 8000, 0, DM_REGION_READ|DM_REGION_WRITE|DM_REGION_TRUNCATE }
};
/* Include implementation-dependent functions and variables */
#include "dm_impl.h"