235 lines
5.9 KiB
C
235 lines
5.9 KiB
C
static const char version[] = "$Id: test.c,v 1.10 2005/12/15 22:11:50 rbyrne Exp $";
|
|
|
|
/*
|
|
* Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
|
|
*
|
|
* See the COPYING file for the terms of usage and distribution.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
#include <sd/test.h>
|
|
#include <sd/malloc.h>
|
|
#include <sd/sprintf.h>
|
|
#include <sd/sd_xplatform.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
typedef XP_UINT64 usec_t;
|
|
|
|
#define MAX_NFUNC 100
|
|
|
|
struct __sd_test
|
|
{
|
|
const char* name;
|
|
char in_filename[128];
|
|
char ref_filename[128];
|
|
char out_filename[128];
|
|
FILE* in;
|
|
FILE* out;
|
|
FILE* err;
|
|
int verbose;
|
|
int timed;
|
|
sd_test_func_t** funcs;
|
|
int size;
|
|
int argc;
|
|
char** argv;
|
|
};
|
|
|
|
|
|
/******************************************************************************/
|
|
static usec_t now(void)
|
|
{
|
|
struct timeval tv;
|
|
|
|
SD_GETTIMEOFDAY(&tv, NULL);
|
|
return (usec_t) (tv.tv_sec * 1000000 + tv.tv_usec);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
static int test_compare(sd_test_t* this, int a_argc, char* a_argv[])
|
|
{
|
|
char cmd[1024];
|
|
|
|
|
|
#ifndef _WIN32
|
|
#warning access() routine should be defined in sd_xplatform
|
|
if (access(this->ref_filename, R_OK) || access(this->out_filename, R_OK))
|
|
return 1;
|
|
|
|
#else
|
|
/*
|
|
cf. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__access.2c_._waccess.asp
|
|
*/
|
|
if (_access(this->ref_filename, 04) == -1 ||
|
|
_access(this->out_filename, 04) == -1)
|
|
return 1;
|
|
#endif
|
|
snprintf(cmd, sizeof(cmd), "%s %s %s 1>/dev/null 2>&1", DIFF_CMD,
|
|
this->ref_filename, this->out_filename);
|
|
|
|
return ! system(cmd);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern sd_test_t* sd_test_new(int a_argc, char* a_argv[])
|
|
{
|
|
sd_test_t* this;
|
|
int c;
|
|
char* ptr;
|
|
|
|
this = sd_calloc(1, sizeof(sd_test_t));
|
|
this->funcs = sd_calloc(MAX_NFUNC, sizeof(sd_test_func_t *));
|
|
|
|
/*
|
|
* get rid of libtool frontend script
|
|
*/
|
|
ptr = strstr(a_argv[0], "lt-");
|
|
if (ptr)
|
|
this->name = ptr + 3;
|
|
else
|
|
this->name = a_argv[0];
|
|
|
|
snprintf(this->ref_filename, sizeof(this->ref_filename), "%s.ref",
|
|
this->name);
|
|
snprintf(this->in_filename, sizeof(this->in_filename), "%s.in",
|
|
this->name);
|
|
snprintf(this->out_filename, sizeof(this->out_filename), "%s.out",
|
|
this->name);
|
|
|
|
this->in = fopen(this->in_filename, "r");
|
|
this->out = fopen(this->out_filename, "w");
|
|
this->err = 0;
|
|
this->verbose= 0;
|
|
this->size = 0;
|
|
|
|
while ((c = SD_GETOPT(a_argc, a_argv, "vt")) != EOF) {
|
|
switch(c) {
|
|
case 'v': this->verbose = 1; break;
|
|
case 't': this->timed = 1; break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
this->argc = a_argc - (SD_OPTIND - 1);
|
|
this->argv = a_argv + (SD_OPTIND - 1);
|
|
return this;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern void sd_test_delete(sd_test_t* this)
|
|
{
|
|
if (!this)
|
|
return;
|
|
|
|
if (this->in) fclose(this->in);
|
|
if (this->out) fclose(this->out);
|
|
free(this->funcs);
|
|
free(this);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern const char* sd_test_get_name(const sd_test_t* this)
|
|
{
|
|
return this ? this->name : NULL;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern int sd_test_get_verbose(const sd_test_t* this)
|
|
{
|
|
return this ? this->verbose: 0;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern int sd_test_set_verbose(sd_test_t* this, int a_verbose)
|
|
{
|
|
if (!this)
|
|
return 0;
|
|
|
|
return this->verbose = a_verbose;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern FILE* sd_test_in(sd_test_t* this)
|
|
{
|
|
if (!this)
|
|
return NULL;
|
|
|
|
return this->in ? this->in : stdin;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern FILE* sd_test_out(sd_test_t* this)
|
|
{
|
|
if (!this)
|
|
return NULL;
|
|
|
|
if (this->verbose)
|
|
return stdout;
|
|
|
|
return this->out ? this->out : stdout;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern FILE* sd_test_err(sd_test_t* this)
|
|
{
|
|
if (!this)
|
|
return NULL;
|
|
|
|
return this->err ? this->err : stderr;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern int sd_test_run(sd_test_t* this, int argc, char* argv[])
|
|
{
|
|
int i, passed = 0;
|
|
|
|
if (!this)
|
|
return -1;
|
|
|
|
sd_test_add(this, test_compare);
|
|
|
|
fprintf(sd_test_err(this), "%s: ", this->name);
|
|
|
|
for (i = 0; i < this->size; i++) {
|
|
int t;
|
|
usec_t elapsed;
|
|
|
|
fprintf(sd_test_out(this), "=> test #%d :\n", i);
|
|
|
|
elapsed = now();
|
|
t = (*this->funcs[i])(this, this->argc, this->argv);
|
|
elapsed = now() - elapsed;
|
|
|
|
fprintf(sd_test_out(this), "=> test #%d : %s\n", i, t ? " passed" : " failed");
|
|
fflush(sd_test_out(this));
|
|
|
|
passed += (t != 0);
|
|
|
|
fprintf(sd_test_err(this), "%c", t ? '+' : '-');
|
|
if (this->timed)
|
|
fprintf(sd_test_err(this), "%lld ", elapsed);
|
|
}
|
|
|
|
fprintf(sd_test_err(this), " %d/%d %s.\n", passed, this->size,
|
|
passed == this->size ? " passed" : " failed");
|
|
|
|
return passed == this->size;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
extern int sd_test_add(sd_test_t* this, sd_test_func_t a_func)
|
|
{
|
|
if (!this)
|
|
return -1;
|
|
|
|
if (this->size == MAX_NFUNC)
|
|
return this->size;
|
|
|
|
this->funcs[this->size] = a_func;
|
|
|
|
return this->size++;
|
|
}
|