hdf5/test/ttsafe.c

351 lines
10 KiB
C
Raw Normal View History

/****************************************************************************
* NCSA HDF *
* Software Development Group *
* National Center for Supercomputing Applications *
* University of Illinois at Urbana-Champaign *
* 605 E. Springfield, Champaign IL 61820 *
* *
* For conditions of distribution and use, see the accompanying *
* hdf/COPYING file. *
* *
****************************************************************************/
#ifdef RCSID
static char RcsId[] = "@(#)$Revision$";
#endif
/* $Id$ */
/*
* FILE
* ttsafe.c - HDF5 threadsafe testing framework main file.
*
* REMARKS
* General test wrapper for HDF5 library thread safety test programs
*
* DESIGN
* Each test function should be implemented as function having no
* parameters and returning void (i.e. no return value). They should be put
* into the list of InitTest() calls in main() below. Functions which depend
* on other functionality should be placed below the InitTest() call for the
* base functionality testing.
* Each test module should include ttsafe.h and define a unique set of
* names for test files they create.
*
* BUGS/LIMITATIONS
*
* EXPORTED ROUTINES/VARIABLES:
* Two variables are exported: num_errs, and Verbosity.
*/
#if defined __MWERKS__
#include <console.h>
#endif
#include <stdarg.h>
#include <ttsafe.h>
#ifndef H5_HAVE_THREADSAFE
int main(void)
{
printf("Test skipped because THREADSAFE not enabled\n");
return 0;
}
#else
#define MAXNUMOFTESTS 50
#define HDF5_TEST_MASTER
#define MAX_NUM_NAME 1000
#define NAME_OFFSET 6 /* offset for "name<num>" */
/* Internal Variables */
static int Index = 0;
/* Global variables */
int num_errs = 0;
int Verbosity;
/* ANY new test needs to have a prototype in tproto.h */
struct TestStruct {
int NumErrors;
char Description[64];
int SkipFlag;
char Name[16];
void (*Call)(void);
void (*Cleanup)(void);
} Test[MAXNUMOFTESTS];
static void InitTest(const char *TheName, void (*TheCall) (void),
void (*Cleanup) (void), const char *TheDescr);
static void usage(void);
static void InitTest(const char *TheName, void (*TheCall) (void),
void (*Cleanup) (void), const char *TheDescr)
{
if (Index >= MAXNUMOFTESTS) {
print_func("Uh-oh, too many tests added, increase MAXNUMOFTEST!\n");
exit(-1);
}
HDstrcpy(Test[Index].Description, TheDescr);
HDstrcpy(Test[Index].Name, TheName);
Test[Index].Call = TheCall;
Test[Index].Cleanup = Cleanup;
Test[Index].NumErrors = -1;
Test[Index].SkipFlag = 0;
Index++;
}
static void usage(void)
{
intn i;
print_func("Usage: ttsafe [-v[erbose] (l[ow]|m[edium]|h[igh]|0-10)] \n");
print_func(" [-[e]x[clude] name+] \n");
print_func(" [-o[nly] name+] \n");
print_func(" [-b[egin] name] \n");
print_func(" [-s[ummary]] \n");
print_func(" [-c[leanoff]] \n");
print_func(" [-n[ocaching]] \n");
print_func(" [-h[elp]] \n");
print_func("\n\n");
print_func("verbose controls the amount of information displayed\n");
print_func("exclude to exclude tests by name\n");
print_func("only to name tests which should be run\n");
print_func("begin start at the name of the test givin\n");
print_func("summary prints a summary of test results at the end\n");
print_func("cleanoff does not delete *.hdf files after execution of tests\n");
print_func("nocaching do not turn on low-level DD caching\n");
print_func("help print out this information\n");
print_func("\n\n");
print_func("This program currently tests the following: \n\n");
print_func("%16s %s\n", "Name", "Description");
print_func("%16s %s\n", "----", "-----------");
for (i = 0; i < Index; i++)
print_func("%16s %s\n", Test[i].Name, Test[i].Description);
print_func("\n\n");
}
/*
* This routine is designed to provide equivalent functionality to 'printf'
* and allow easy replacement for environments which don't have stdin/stdout
* available. (i.e. Windows & the Mac)
*/
int
print_func(const char *format, ...)
{
va_list arglist;
int ret_value;
va_start(arglist, format);
ret_value = vprintf(format, arglist);
va_end(arglist);
return ret_value;
}
char *gen_name(int value)
{
char *temp;
int i, length;
length = num_digits(MAX_NUM_NAME - 1);
temp = (char *)malloc((NAME_OFFSET + length + 1) * sizeof(char));
temp = strcpy(temp, "attrib");
temp[NAME_OFFSET + length] = '\0';
for (i = length - 1; i >= 0; i--) {
temp[NAME_OFFSET + i] = (char)((int)'0' + value % 10);
value = value / 10;
}
return temp;
}
/* pre-condition: num must be a non-negative number */
int num_digits(int num)
{
int i;
if (num == 0)
return 1;
for (i = 0; num > 0; i++)
num = num / 10;
return i;
}
int main(int argc, char *argv[])
{
int CLLoop; /* Command Line Loop */
int Loop, Loop1, Summary = 0, CleanUp = 1, Cache = 1;
uintn major, minor, release;
#if defined __MWERKS__
argc = ccommand(&argv);
#endif
#if !(defined MAC || defined __MWERKS__ || defined SYMANTEC_C)
/* Un-buffer the stdout and stderr */
setbuf(stderr, NULL);
setbuf(stdout, NULL);
#endif
/*
* Turn off automatic error reporting since we do it ourselves.
* Besides, half the functions this test calls are private, so
* automatic error reporting wouldn't do much good since it's
* triggered at the API layer.
*/
H5Eset_auto (NULL, NULL);
/* Tests are generally arranged from least to most complexity... */
InitTest("dcreate", tts_dcreate, cleanup_dcreate,
"multi-dataset creation");
InitTest("error", tts_error, cleanup_error,
"per-thread error stacks");
InitTest("cancel", tts_cancel, cleanup_cancel,
"thread cancellation safety test");
InitTest("acreate", tts_acreate, cleanup_acreate,
"multi-attribute creation");
Verbosity = 4; /* Default Verbosity is Low */
H5get_libversion(&major, &minor, &release);
print_func("\nFor help use: ttsafe -help\n");
print_func("Linked with hdf5 version %u.%u release %u\n",
(unsigned)major, (unsigned)minor, (unsigned)release);
for (CLLoop = 1; CLLoop < argc; CLLoop++) {
if (argc > CLLoop + 1 &&
(HDstrcmp(argv[CLLoop], "-verbose") == 0 ||
HDstrcmp(argv[CLLoop], "-v") == 0)) {
if (argv[CLLoop + 1][0] == 'l')
Verbosity = 4;
else if (argv[CLLoop + 1][0] == 'm')
Verbosity = 6;
else if (argv[CLLoop + 1][0] == 'h')
Verbosity = 10;
else
Verbosity = atoi(argv[CLLoop + 1]);
} /* end if */
if (argc > CLLoop &&
(HDstrcmp(argv[CLLoop], "-summary") == 0 ||
HDstrcmp(argv[CLLoop], "-s") == 0))
Summary = 1;
if (argc > CLLoop &&
(HDstrcmp(argv[CLLoop], "-help") == 0 ||
HDstrcmp(argv[CLLoop], "-h") == 0)) {
usage();
exit(0);
}
if (argc > CLLoop &&
(HDstrcmp(argv[CLLoop], "-cleanoff") == 0 ||
HDstrcmp(argv[CLLoop], "-c") == 0))
CleanUp = 0;
if (argc > CLLoop &&
(HDstrcmp(argv[CLLoop], "-nocache") == 0 ||
HDstrcmp(argv[CLLoop], "-n") == 0)) {
Cache = 0;
print_func("Cache = %d\n", Cache);
}
if (argc > CLLoop + 1 &&
(HDstrcmp(argv[CLLoop], "-exclude") == 0 ||
HDstrcmp(argv[CLLoop], "-x") == 0))
for (Loop = CLLoop + 1; Loop < argc && argv[Loop][0] != '-'; Loop++)
for (Loop1 = 0; Loop1 < Index; Loop1++)
if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0)
Test[Loop1].SkipFlag = 1;
if (argc > CLLoop + 1 &&
(HDstrcmp(argv[CLLoop], "-begin") == 0 ||
HDstrcmp(argv[CLLoop], "-b") == 0))
for (Loop = CLLoop + 1; Loop < argc && argv[Loop][0] != '-'; Loop++)
for (Loop1 = 0; Loop1 < Index; Loop1++) {
if (HDstrcmp(argv[Loop], Test[Loop1].Name) != 0)
Test[Loop1].SkipFlag = 1;
if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0)
Loop1 = Index;
}
if (argc > CLLoop + 1 &&
(HDstrcmp(argv[CLLoop], "-only") == 0 ||
HDstrcmp(argv[CLLoop], "-o") == 0)) {
for (Loop = 0; Loop < Index; Loop++)
Test[Loop].SkipFlag = 1;
for (Loop = CLLoop + 1; Loop < argc && argv[Loop][0] != '-'; Loop++)
for (Loop1 = 0; Loop1 < Index; Loop1++)
if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0)
Test[Loop1].SkipFlag = 0;
}
} /* end for */
#ifdef NOT_YET
if (Cache)
/* turn on caching, unless we were instucted not to */
Hcache(CACHE_ALL_FILES, TRUE);
#endif /* NOT_YET */
for (Loop = 0; Loop < Index; Loop++)
if (Test[Loop].SkipFlag) {
MESSAGE(2, ("Skipping -- %s \n", Test[Loop].Description));
} else {
MESSAGE(2, ("Testing -- %s (%s) \n", Test[Loop].Description,
Test[Loop].Name));
MESSAGE(5, ("===============================================\n"));
Test[Loop].NumErrors = num_errs;
Test[Loop].Call();
Test[Loop].NumErrors = num_errs - Test[Loop].NumErrors;
MESSAGE(5, ("===============================================\n"));
MESSAGE(5, ("There were %d errors detected.\n\n",
(int)Test[Loop].NumErrors));
}
MESSAGE(2, ("\n\n"))
if (num_errs)
print_func("!!! %d Error(s) were detected !!!\n\n", (int) num_errs);
else
print_func("All tests were successful. \n\n");
if (Summary) {
print_func("Summary of Test Results:\n");
print_func("Name of Test Errors Description of Test\n");
print_func("---------------- ------ --------------------------------------\n");
for (Loop = 0; Loop < Index; Loop++) {
if (Test[Loop].NumErrors == -1)
print_func("%16s %6s %s\n", Test[Loop].Name,
"N/A", Test[Loop].Description);
else
print_func("%16s %6d %s\n", Test[Loop].Name,
(int)Test[Loop].NumErrors,
Test[Loop].Description);
}
print_func("\n\n");
}
if (CleanUp && !getenv("HDF5_NOCLEANUP")) {
MESSAGE(2, ("\nCleaning Up temp files...\n\n"));
/* call individual cleanup routines in each source module */
for (Loop = 0; Loop < Index; Loop++)
if (!Test[Loop].SkipFlag && Test[Loop].Cleanup!=NULL)
Test[Loop].Cleanup();
}
return num_errs;
} /* end main() */
#endif /*H5_HAVE_THREADSAFE*/