Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18826750
testdrv.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
20 KB
Subscribers
None
testdrv.c
View Options
/* testdrv.c - Test driver to run all tests w/o using the Makefile.
* Copyright (C) 2021 g10 Code GmbH
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifdef HAVE_CONFIG_H
#include
<config.h>
#endif
#include
<stdarg.h>
#include
<stdio.h>
#include
<ctype.h>
#include
<stdlib.h>
#include
<string.h>
#include
<errno.h>
#ifndef HAVE_W32_SYSTEM
# include <unistd.h>
# include <fcntl.h>
# include <sys/wait.h>
#endif
#include
<gpg-error.h>
/* For some macros. */
#include
"stopwatch.h"
#define PGM "testdrv"
/* Flags for testpgms. */
#define LONG_RUNNING 1
/* This is our list of tests which are run in this order. */
static
struct
{
const
char
*
name
;
const
char
*
pgm
;
const
char
*
args
;
unsigned
int
flags
;
/* e.g. LONG_RUNNING */
}
testpgms
[]
=
{
{
"version"
},
{
"t-secmem"
},
{
"mpitests"
},
{
"t-sexp"
},
{
"t-convert"
},
{
"t-mpi-bit"
},
{
"t-mpi-point"
},
{
"curves"
},
{
"t-lock"
},
{
"prime"
},
{
"basic"
},
{
"basic-disable-all-hwf"
,
"basic"
,
"--disable-hwf all"
},
{
"keygen"
},
{
"pubkey"
},
{
"hmac"
},
{
"hashtest"
},
{
"t-kdf"
},
{
"keygrip"
},
{
"fips186-dsa"
},
{
"aeswrap"
},
{
"pkcs1v2"
},
{
"random"
},
{
"dsa-rfc6979"
},
{
"t-ed25519"
},
{
"t-cv25519"
},
{
"t-x448"
},
{
"t-ed448"
},
{
"benchmark"
},
{
"bench-slope"
},
{
"hashtest-256g"
,
"hashtest"
,
"--gigs 256 SHA1 SHA256 SHA512 SM3"
,
LONG_RUNNING
},
{
NULL
}
};
/* Extra files needed for the above tests. */
static
const
char
*
extratestfiles
[]
=
{
"t-ed25519.inp"
,
"t-ed448.inp"
,
NULL
};
/* A couple of useful macros. */
#ifndef DIM
# define DIM(v) (sizeof(v)/sizeof((v)[0]))
#endif
#define DIMof(type,member) DIM(((type *)0)->member)
#define xfree(a) free ((a))
#define spacep(p) (*(p) == ' ' || *(p) == '\t')
/* If we have a decent libgpg-error we can use some gcc attributes. */
#ifdef GPGRT_ATTR_NORETURN
static
void
die
(
const
char
*
format
,
...)
GPGRT_ATTR_UNUSED
GPGRT_ATTR_NR_PRINTF
(
1
,
2
);
static
void
fail
(
const
char
*
format
,
...)
GPGRT_ATTR_UNUSED
GPGRT_ATTR_PRINTF
(
1
,
2
);
static
void
info
(
const
char
*
format
,
...)
\
GPGRT_ATTR_UNUSED
GPGRT_ATTR_PRINTF
(
1
,
2
);
static
void
printresult
(
const
char
*
format
,
...)
\
GPGRT_ATTR_UNUSED
GPGRT_ATTR_PRINTF
(
1
,
2
);
#endif
/*GPGRT_ATTR_NORETURN*/
#ifndef TESTDRV_EXEEXT
# ifdef HAVE_W32_SYSTEM
# define TESTDRV_EXEEXT ".exe"
# else
# define TESTDRV_EXEEXT ""
# endif
#endif
#ifdef HAVE_W32_SYSTEM
# define MYPID_T HANDLE
# define MYINVALID_PID INVALID_HANDLE_VALUE
#else
# define MYPID_T pid_t
# define MYINVALID_PID ((pid_t)(-1))
#endif
/* Standard global variables. */
static
int
verbose
;
static
int
debug
;
static
int
error_count
;
static
int
die_on_error
;
static
int
long_running
;
static
char
**
myenviron
;
static
int
testcount
,
failcount
,
passcount
,
skipcount
;
#ifdef HAVE_W32_SYSTEM
static
char
*
my_stpcpy
(
char
*
a
,
const
char
*
b
)
{
while
(
*
b
)
*
a
++
=
*
b
++
;
*
a
=
0
;
return
a
;
}
#endif
/*HAVE_W32_SYSTEM*/
/* Reporting functions. */
static
void
die
(
const
char
*
format
,
...)
{
va_list
arg_ptr
;
/* Avoid warning. */
(
void
)
debug
;
fflush
(
stdout
);
#ifdef HAVE_FLOCKFILE
flockfile
(
stderr
);
#endif
fprintf
(
stderr
,
"%s: "
,
PGM
);
va_start
(
arg_ptr
,
format
)
;
vfprintf
(
stderr
,
format
,
arg_ptr
);
va_end
(
arg_ptr
);
if
(
*
format
&&
format
[
strlen
(
format
)
-1
]
!=
'\n'
)
putc
(
'\n'
,
stderr
);
#ifdef HAVE_FLOCKFILE
funlockfile
(
stderr
);
#endif
exit
(
1
);
}
static
void
*
xmalloc
(
size_t
n
)
{
char
*
p
=
malloc
(
n
);
if
(
!
p
)
die
(
"malloc failed"
);
return
p
;
}
static
void
*
xcalloc
(
size_t
n
,
size_t
m
)
{
char
*
p
=
calloc
(
n
,
m
);
if
(
!
p
)
die
(
"calloc failed"
);
return
p
;
}
static
char
*
xstrdup
(
const
char
*
s
)
{
size_t
n
=
strlen
(
s
);
char
*
p
=
xmalloc
(
n
+
1
);
strcpy
(
p
,
s
);
return
p
;
}
static
void
fail
(
const
char
*
format
,
...)
{
va_list
arg_ptr
;
fflush
(
stdout
);
#ifdef HAVE_FLOCKFILE
flockfile
(
stderr
);
#endif
fprintf
(
stderr
,
"%s: "
,
PGM
);
va_start
(
arg_ptr
,
format
);
vfprintf
(
stderr
,
format
,
arg_ptr
);
va_end
(
arg_ptr
);
if
(
*
format
&&
format
[
strlen
(
format
)
-1
]
!=
'\n'
)
putc
(
'\n'
,
stderr
);
#ifdef HAVE_FLOCKFILE
funlockfile
(
stderr
);
#endif
if
(
die_on_error
)
exit
(
1
);
error_count
++
;
}
static
void
info
(
const
char
*
format
,
...)
{
va_list
arg_ptr
;
if
(
!
verbose
)
return
;
fflush
(
stdout
);
#ifdef HAVE_FLOCKFILE
flockfile
(
stderr
);
#endif
fprintf
(
stderr
,
"%s: "
,
PGM
);
va_start
(
arg_ptr
,
format
);
vfprintf
(
stderr
,
format
,
arg_ptr
);
if
(
*
format
&&
format
[
strlen
(
format
)
-1
]
!=
'\n'
)
putc
(
'\n'
,
stderr
);
va_end
(
arg_ptr
);
#ifdef HAVE_FLOCKFILE
funlockfile
(
stderr
);
#endif
}
static
void
printresult
(
const
char
*
format
,
...)
{
va_list
arg_ptr
;
fflush
(
stdout
);
#ifdef HAVE_FLOCKFILE
flockfile
(
stdout
);
#endif
va_start
(
arg_ptr
,
format
);
vfprintf
(
stdout
,
format
,
arg_ptr
);
if
(
*
format
&&
format
[
strlen
(
format
)
-1
]
!=
'\n'
)
putc
(
'\n'
,
stdout
);
va_end
(
arg_ptr
);
fflush
(
stdout
);
#ifdef HAVE_FLOCKFILE
funlockfile
(
stdout
);
#endif
}
/* Tokenize STRING using the set of delimiters in DELIM. Leading
* spaces and tabs are removed from all tokens. The caller must free
* the result. Returns a malloced and NULL delimited array with the
* tokens. */
static
char
**
strtokenize
(
const
char
*
string
,
const
char
*
delim
)
{
const
char
*
s
;
size_t
fields
;
size_t
bytes
,
n
;
char
*
buffer
;
char
*
p
,
*
px
,
*
pend
;
char
**
result
;
/* Count the number of fields. */
for
(
fields
=
1
,
s
=
strpbrk
(
string
,
delim
);
s
;
s
=
strpbrk
(
s
+
1
,
delim
))
fields
++
;
fields
++
;
/* Add one for the terminating NULL. */
/* Allocate an array for all fields, a terminating NULL, and space
for a copy of the string. */
bytes
=
fields
*
sizeof
*
result
;
if
(
bytes
/
sizeof
*
result
!=
fields
)
die
(
"integer overflow at %d
\n
"
,
__LINE__
);
n
=
strlen
(
string
)
+
1
;
bytes
+=
n
;
if
(
bytes
<
n
)
die
(
"integer overflow at %d
\n
"
,
__LINE__
);
result
=
xmalloc
(
bytes
);
buffer
=
(
char
*
)(
result
+
fields
);
/* Copy and parse the string. */
strcpy
(
buffer
,
string
);
for
(
n
=
0
,
p
=
buffer
;
(
pend
=
strpbrk
(
p
,
delim
));
p
=
pend
+
1
)
{
*
pend
=
0
;
while
(
spacep
(
p
))
p
++
;
for
(
px
=
pend
-
1
;
px
>=
p
&&
spacep
(
px
);
px
--
)
*
px
=
0
;
result
[
n
++
]
=
p
;
}
while
(
spacep
(
p
))
p
++
;
for
(
px
=
p
+
strlen
(
p
)
-
1
;
px
>=
p
&&
spacep
(
px
);
px
--
)
*
px
=
0
;
result
[
n
++
]
=
p
;
result
[
n
]
=
NULL
;
if
(
!
((
char
*
)(
result
+
n
+
1
)
==
buffer
))
die
(
"bug at %d
\n
"
,
__LINE__
);
return
result
;
}
#ifdef HAVE_W32_SYSTEM
/* Helper functions for Windows. */
static
char
*
build_w32_commandline_copy
(
char
*
buffer
,
const
char
*
string
)
{
char
*
p
=
buffer
;
const
char
*
s
;
if
(
!*
string
)
/* Empty string. */
p
=
my_stpcpy
(
p
,
"
\"\"
"
);
else
if
(
strpbrk
(
string
,
"
\t\n\v\f\"
"
))
{
/* Need to do some kind of quoting. */
p
=
my_stpcpy
(
p
,
"
\"
"
);
for
(
s
=
string
;
*
s
;
s
++
)
{
*
p
++
=
*
s
;
if
(
*
s
==
'\"'
)
*
p
++
=
*
s
;
}
*
p
++
=
'\"'
;
*
p
=
0
;
}
else
p
=
my_stpcpy
(
p
,
string
);
return
p
;
}
/* Build a command line for use with CreateProcess. This function
* either terminates the process or returns a malloced string. */
static
char
*
build_w32_commandline
(
const
char
*
pgmname
,
char
**
argv
)
{
int
i
,
n
;
const
char
*
s
;
char
*
buf
,
*
p
;
s
=
pgmname
;
n
=
strlen
(
s
)
+
1
+
2
;
/* (1 space, 2 quoting) */
for
(;
*
s
;
s
++
)
if
(
*
s
==
'\"'
)
n
++
;
/* Account for to be doubled inner quotes. */
for
(
i
=
0
;
argv
&&
(
s
=
argv
[
i
]);
i
++
)
{
n
+=
strlen
(
s
)
+
1
+
2
;
/* (1 space, 2 quoting) */
for
(;
*
s
;
s
++
)
if
(
*
s
==
'\"'
)
n
++
;
/* For doubling inner quotes. */
}
n
++
;
/* String terminator. */
buf
=
p
=
xmalloc
(
n
);
p
=
build_w32_commandline_copy
(
p
,
pgmname
);
for
(
i
=
0
;
argv
&&
argv
[
i
];
i
++
)
{
*
p
++
=
' '
;
p
=
build_w32_commandline_copy
(
p
,
argv
[
i
]);
}
return
buf
;
}
static
HANDLE
w32_open_null
(
int
for_write
)
{
HANDLE
hfile
;
hfile
=
CreateFileW
(
L
"nul"
,
for_write
?
GENERIC_WRITE
:
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
0
,
NULL
);
if
(
hfile
==
INVALID_HANDLE_VALUE
)
die
(
"can't open 'nul': ec=%lu
\n
"
,
(
unsigned
long
)
GetLastError
());
return
hfile
;
}
#endif
/*HAVE_W32_SYSTEM*/
/* Fork and exec the PGMNAME using ARGV as arguments (w/o pgmmname)
* and return the pid at PID. If ENVP is not NULL, add these strings
* as environment variables. Return -1 on severe errors. */
static
int
my_spawn
(
const
char
*
pgmname
,
char
**
argv
,
char
**
envp
,
MYPID_T
*
pid
)
{
#ifdef HAVE_W32_SYSTEM
int
rc
;
SECURITY_ATTRIBUTES
sec_attr
;
PROCESS_INFORMATION
pi
=
{
NULL
};
STARTUPINFO
si
;
char
*
cmdline
;
char
*
pgmnamefull
=
NULL
;
char
**
saveenviron
=
NULL
;
int
i
;
/* Prepare security attributes. */
memset
(
&
sec_attr
,
0
,
sizeof
sec_attr
);
sec_attr
.
nLength
=
sizeof
sec_attr
;
sec_attr
.
bInheritHandle
=
FALSE
;
if
(
!
(
strlen
(
pgmname
)
>
4
&&
!
strcmp
(
pgmname
+
strlen
(
pgmname
)
-4
,
".exe"
)))
{
pgmnamefull
=
xmalloc
(
strlen
(
pgmname
)
+
4
+
1
);
strcpy
(
my_stpcpy
(
pgmnamefull
,
pgmname
),
".exe"
);
pgmname
=
pgmnamefull
;
}
/* Build the command line. */
cmdline
=
build_w32_commandline
(
pgmname
,
argv
);
memset
(
&
si
,
0
,
sizeof
si
);
si
.
cb
=
sizeof
(
si
);
si
.
dwFlags
=
STARTF_USESTDHANDLES
;
si
.
hStdInput
=
w32_open_null
(
0
);
if
(
verbose
)
si
.
hStdOutput
=
GetStdHandle
(
STD_OUTPUT_HANDLE
);
else
si
.
hStdOutput
=
w32_open_null
(
1
);
si
.
hStdError
=
GetStdHandle
(
STD_ERROR_HANDLE
);
if
(
envp
)
{
for
(
i
=
0
;
envp
[
i
];
i
++
)
;
saveenviron
=
xcalloc
(
i
+
1
,
sizeof
*
saveenviron
);
for
(
i
=
0
;
envp
[
i
];
i
++
)
saveenviron
[
i
]
=
xstrdup
(
envp
[
i
]);
for
(
i
=
0
;
envp
[
i
];
i
++
)
putenv
(
envp
[
i
]);
}
if
(
debug
)
info
(
"CreateProcess, path='%s' cmdline='%s'
\n
"
,
pgmname
,
cmdline
);
if
(
!
CreateProcess
(
pgmname
,
/* Program to start. */
cmdline
,
/* Command line arguments. */
&
sec_attr
,
/* Process security attributes. */
&
sec_attr
,
/* Thread security attributes. */
TRUE
,
/* Inherit handles. */
(
CREATE_DEFAULT_ERROR_MODE
|
GetPriorityClass
(
GetCurrentProcess
())
|
CREATE_SUSPENDED
|
DETACHED_PROCESS
),
NULL
,
/* Environment. */
NULL
,
/* Use current drive/directory. */
&
si
,
/* Startup information. */
&
pi
/* Returns process information. */
))
{
fail
(
"CreateProcess failed: ec=%lu
\n
"
,
(
unsigned
long
)
GetLastError
());
rc
=
-1
;
}
else
rc
=
0
;
if
(
saveenviron
)
{
for
(
i
=
0
;
saveenviron
[
i
];
i
++
)
xfree
(
saveenviron
[
i
]);
xfree
(
saveenviron
);
}
xfree
(
cmdline
);
CloseHandle
(
si
.
hStdInput
);
if
(
!
verbose
)
CloseHandle
(
si
.
hStdOutput
);
xfree
(
pgmnamefull
);
pgmname
=
NULL
;
if
(
rc
)
return
rc
;
if
(
debug
)
info
(
"CreateProcess ready: hProcess=%p hThread=%p"
" dwProcessID=%d dwThreadId=%d
\n
"
,
pi
.
hProcess
,
pi
.
hThread
,
(
int
)
pi
.
dwProcessId
,
(
int
)
pi
.
dwThreadId
);
/* Process has been created suspended; resume it now. */
ResumeThread
(
pi
.
hThread
);
CloseHandle
(
pi
.
hThread
);
*
pid
=
pi
.
hProcess
;
return
0
;
#else
/*!HAVE_W32_SYSTEM*/
char
**
arg_list
;
int
i
,
j
;
int
fd
;
/* Create the command line argument array. */
i
=
0
;
if
(
argv
)
while
(
argv
[
i
])
i
++
;
arg_list
=
xcalloc
(
i
+
2
,
sizeof
*
arg_list
);
arg_list
[
0
]
=
strrchr
(
pgmname
,
'/'
);
if
(
arg_list
[
0
])
arg_list
[
0
]
++
;
else
arg_list
[
0
]
=
xstrdup
(
pgmname
);
if
(
argv
)
for
(
i
=
0
,
j
=
1
;
argv
[
i
];
i
++
,
j
++
)
arg_list
[
j
]
=
(
char
*
)
argv
[
i
];
*
pid
=
fork
();
if
(
*
pid
==
MYINVALID_PID
)
{
fail
(
"error forking process: %s
\n
"
,
strerror
(
errno
));
return
-1
;
}
if
(
!*
pid
)
{
/* This is the child. */
if
(
envp
)
for
(
i
=
0
;
envp
[
i
];
i
++
)
putenv
(
xstrdup
(
envp
[
i
]));
/* Assign /dev/null to stdin. */
fd
=
open
(
"/dev/null"
,
O_RDONLY
);
if
(
fd
==
-1
)
die
(
"failed to open '%s': %s
\n
"
,
"/dev/null"
,
strerror
(
errno
));
if
(
fd
!=
0
&&
dup2
(
fd
,
0
)
==
-1
)
die
(
"dup2(%d,0) failed: %s
\n
"
,
fd
,
strerror
(
errno
));
/* Assign /dev/null to stdout unless in verbose mode. */
if
(
!
verbose
)
{
fd
=
open
(
"/dev/null"
,
O_RDONLY
);
if
(
fd
==
-1
)
die
(
"failed to open '%s': %s
\n
"
,
"/dev/null"
,
strerror
(
errno
));
if
(
fd
!=
1
&&
dup2
(
fd
,
1
)
==
-1
)
die
(
"dup2(%d,1) failed: %s
\n
"
,
fd
,
strerror
(
errno
));
}
/* Exec the program. */
execv
(
pgmname
,
arg_list
);
info
(
"exec '%s' failed: %s
\n
"
,
pgmname
,
strerror
(
errno
));
_exit
(
127
);
/*NOTREACHED*/
}
/* This is the parent. */
xfree
(
arg_list
);
return
0
;
#endif
/*!HAVE_W32_SYSTEM*/
}
/* Wait for PID and return its exitcode at R_EXITCODE. PGMNAME is
* only used for diagnostics. */
static
int
my_wait
(
const
char
*
pgmname
,
MYPID_T
pid
,
int
*
r_exitcode
)
{
int
rc
=
-1
;
#ifdef HAVE_W32_SYSTEM
HANDLE
procs
[
1
];
DWORD
exc
;
int
code
;
if
(
pid
==
MYINVALID_PID
)
die
(
"invalid pid passed to my_wait
\n
"
);
procs
[
0
]
=
(
HANDLE
)
pid
;
code
=
WaitForMultipleObjects
(
1
,
procs
,
TRUE
,
INFINITE
);
switch
(
code
)
{
case
WAIT_TIMEOUT
:
/* Should not happen. */
fail
(
"waiting for process %p (%s) to terminate failed: timeout
\n
"
,
pid
,
pgmname
);
break
;
case
WAIT_FAILED
:
fail
(
"waiting for process %p (%s) to terminate failed: ec=%lu
\n
"
,
pid
,
pgmname
,
(
unsigned
long
)
GetLastError
());
break
;
case
WAIT_OBJECT_0
:
if
(
!
GetExitCodeProcess
(
procs
[
0
],
&
exc
))
{
fail
(
"error getting exit code for process %p (%s): ec=%lu
\n
"
,
pid
,
pgmname
,
(
unsigned
long
)
GetLastError
());
}
else
{
*
r_exitcode
=
(
int
)
exc
;
rc
=
0
;
}
break
;
default
:
fail
(
"WaitForMultipleObjects returned unexpected code %d
\n
"
,
code
);
break
;
}
CloseHandle
((
HANDLE
)
pid
);
#else
/*!HAVE_W32_SYSTEM*/
int
i
,
status
;
if
(
pid
==
MYINVALID_PID
)
die
(
"invalid pid passed to my_wait
\n
"
);
while
((
i
=
waitpid
(
pid
,
&
status
,
0
))
==
MYINVALID_PID
&&
errno
==
EINTR
)
;
if
(
i
==
MYINVALID_PID
)
{
fail
(
"waiting for process %d (%s) to terminate failed: %s
\n
"
,
(
int
)
pid
,
pgmname
,
strerror
(
errno
));
}
else
if
(
!
i
)
{
die
(
"waitpid returns unexpected code 0
\n
"
);
}
else
if
(
WIFEXITED
(
status
)
&&
WEXITSTATUS
(
status
)
==
127
)
{
fail
(
"error running '%s': probably not installed
\n
"
,
pgmname
);
}
else
if
(
WIFEXITED
(
status
)
&&
WEXITSTATUS
(
status
))
{
*
r_exitcode
=
WEXITSTATUS
(
status
);
rc
=
0
;
}
else
if
(
!
WIFEXITED
(
status
))
{
info
(
"error running '%s': terminated
\n
"
,
pgmname
);
rc
=
1
;
}
else
{
*
r_exitcode
=
0
;
rc
=
0
;
}
#endif
/*!HAVE_W32_SYSTEM*/
return
rc
;
}
static
void
run_one_test
(
int
idx
)
{
MYPID_T
pid
;
int
exitcode
,
rc
;
const
char
*
name
=
testpgms
[
idx
].
name
;
const
char
*
pgm
=
testpgms
[
idx
].
pgm
;
char
**
args
;
if
(
!
pgm
)
pgm
=
name
;
testcount
++
;
if
((
testpgms
[
idx
].
flags
&
LONG_RUNNING
)
&&
!
long_running
)
{
printresult
(
"SKIP: %s
\n
"
,
name
);
skipcount
++
;
return
;
}
args
=
testpgms
[
idx
].
args
?
strtokenize
(
testpgms
[
idx
].
args
,
" "
)
:
NULL
;
rc
=
my_spawn
(
pgm
,
args
,
myenviron
,
&
pid
);
xfree
(
args
);
if
(
rc
)
{
printresult
(
"FAIL: %s (error invoking test)
\n
"
,
name
);
failcount
++
;
return
;
}
rc
=
my_wait
(
pgm
,
pid
,
&
exitcode
);
if
(
rc
<
0
)
{
printresult
(
"FAIL: %s (error running test)
\n
"
,
name
);
failcount
++
;
}
else
if
(
rc
)
{
printresult
(
"FAIL: %s (test crashed)
\n
"
,
name
);
failcount
++
;
}
else
if
(
exitcode
==
77
)
{
printresult
(
"SKIP: %s
\n
"
,
name
);
skipcount
++
;
}
else
if
(
exitcode
==
1
)
{
printresult
(
"FAIL: %s
\n
"
,
name
);
failcount
++
;
}
else
if
(
exitcode
)
{
printresult
(
"FAIL: %s (exit code %d)
\n
"
,
name
,
exitcode
);
failcount
++
;
}
else
{
printresult
(
"PASS: %s
\n
"
,
name
);
passcount
++
;
}
}
static
void
runtests
(
char
**
argv
)
{
int
i
;
if
(
argv
&&
*
argv
)
{
for
(
;
*
argv
;
argv
++
)
{
for
(
i
=
0
;
testpgms
[
i
].
name
;
i
++
)
if
(
!
strcmp
(
testpgms
[
i
].
name
,
*
argv
))
{
run_one_test
(
i
);
break
;
}
if
(
!
testpgms
[
i
].
name
)
{
fail
(
"requested test '%s' not found
\n
"
,
*
argv
);
testcount
++
;
}
}
}
else
/* Run all tests. */
{
for
(
i
=
0
;
testpgms
[
i
].
name
;
i
++
)
run_one_test
(
i
);
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
last_argc
=
-1
;
int
listtests
=
0
;
int
i
;
const
char
*
srcdir
;
if
(
argc
)
{
argc
--
;
argv
++
;
}
while
(
argc
&&
last_argc
!=
argc
)
{
last_argc
=
argc
;
if
(
!
strcmp
(
*
argv
,
"--"
))
{
argc
--
;
argv
++
;
break
;
}
else
if
(
!
strcmp
(
*
argv
,
"--help"
))
{
fputs
(
"usage: "
PGM
" [options] [tests_to_run]
\n
"
"Options:
\n
"
" --verbose print timings etc.
\n
"
" --debug flyswatter
\n
"
" --list list all tests
\n
"
" --files list all files
\n
"
" --long include long running tests
\n
"
,
stdout
);
exit
(
0
);
}
else
if
(
!
strcmp
(
*
argv
,
"--verbose"
))
{
verbose
++
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--debug"
))
{
verbose
+=
2
;
debug
++
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--list"
))
{
listtests
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--files"
))
{
listtests
=
2
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--long"
))
{
long_running
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strncmp
(
*
argv
,
"--"
,
2
))
die
(
"unknown option '%s'"
,
*
argv
);
}
srcdir
=
getenv
(
"srcdir"
);
myenviron
=
xcalloc
(
2
,
sizeof
*
myenviron
);
myenviron
[
0
]
=
xstrdup
(
"GCRYPT_IN_REGRESSION_TEST=1"
);
#ifndef HAVE_W32_SYSTEM
if
(
!
access
(
"libgcrypt-standalone-tests"
,
F_OK
))
myenviron
[
1
]
=
xstrdup
(
"LD_LIBRARY_PATH=."
);
#endif
if
(
listtests
==
1
)
{
for
(
i
=
0
;
testpgms
[
i
].
name
;
i
++
)
{
printf
(
"%s"
,
testpgms
[
i
].
name
);
if
(
testpgms
[
i
].
pgm
||
testpgms
[
i
].
args
)
printf
(
" (%s %s)"
,
testpgms
[
i
].
pgm
?
testpgms
[
i
].
pgm
:
testpgms
[
i
].
name
,
testpgms
[
i
].
args
?
testpgms
[
i
].
args
:
""
);
if
(
testpgms
[
i
].
flags
)
{
putchar
(
' '
);
putchar
(
'['
);
if
(
testpgms
[
i
].
flags
)
fputs
(
"long"
,
stdout
);
putchar
(
']'
);
}
putchar
(
'\n'
);
}
}
else
if
(
listtests
==
2
)
{
for
(
i
=
0
;
testpgms
[
i
].
name
;
i
++
)
printf
(
"%s%s%s
\n
"
,
strcmp
(
TESTDRV_EXEEXT
,
".exe"
)
?
""
:
".libs/"
,
testpgms
[
i
].
pgm
?
testpgms
[
i
].
pgm
:
testpgms
[
i
].
name
,
TESTDRV_EXEEXT
);
for
(
i
=
0
;
extratestfiles
[
i
];
i
++
)
printf
(
"%s%s%s
\n
"
,
srcdir
?
srcdir
:
""
,
srcdir
?
"/"
:
""
,
extratestfiles
[
i
]);
}
else
{
start_timer
();
runtests
(
argv
);
stop_timer
();
printresult
(
"%d tests run, %d succeeded, %d failed, %d skipped.
\n
"
,
testcount
-
skipcount
,
passcount
,
failcount
,
skipcount
);
if
(
testcount
!=
passcount
+
failcount
+
skipcount
)
printresult
(
"Warning: Execution of some tests failed
\n
"
);
info
(
"All tests completed in %s. Errors: %d
\n
"
,
elapsed_time
(
1
),
error_count
+
failcount
);
}
for
(
i
=
0
;
myenviron
[
i
];
i
++
)
xfree
(
myenviron
[
i
]);
xfree
(
myenviron
);
return
!!
error_count
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Mon, Dec 23, 5:46 PM (5 m, 13 s)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
45/9b/bf47ca53a77d5c75860888d740be
Attached To
rC libgcrypt
Event Timeline
Log In to Comment