mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
Generic test suite helpers for OOM testing
This commit is contained in:
parent
18da6991e1
commit
364f53a67a
@ -1,3 +1,10 @@
|
||||
Thu May 29 11:12:00 EST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||
|
||||
* tests/testutils.c, tests/testutils.h: Add generic main()
|
||||
impl for test programs to leverage OOM testing
|
||||
* tests/Makefile.am, tests/oomtrace.pl: post-processor for
|
||||
generating file/line number backtraces from OOM reports.
|
||||
|
||||
Thu May 29 11:12:00 EST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||
|
||||
* src/memory.c, src/memory.h, configure.ac: Add generics hooks
|
||||
|
@ -33,6 +33,7 @@ LDADDS = \
|
||||
$(COVERAGE_LDFLAGS)
|
||||
|
||||
EXTRA_DIST = \
|
||||
oomtrace.pl \
|
||||
test-lib.sh \
|
||||
xmlrpcserver.py \
|
||||
test_conf.sh \
|
||||
|
41
tests/oomtrace.pl
Normal file
41
tests/oomtrace.pl
Normal file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
(my $ME = $0) =~ s|.*/||;
|
||||
# use File::Coda; # http://meyering.net/code/Coda/
|
||||
END {
|
||||
defined fileno STDOUT or return;
|
||||
close STDOUT and return;
|
||||
warn "$ME: failed to close standard output: $!\n";
|
||||
$? ||= 1;
|
||||
}
|
||||
|
||||
|
||||
my @data = <>;
|
||||
|
||||
|
||||
my %trace;
|
||||
my %lines;
|
||||
|
||||
foreach (@data) {
|
||||
if (/^\s*TRACE:\s+(\S+?)(?:\(.*\))?\s+\[0x(.*)\]\s*$/ ) {
|
||||
$trace{$2} = $1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $key (keys %trace) {
|
||||
my $val = $trace{$key};
|
||||
my $info = $val =~ /\?\?/ ? $val : `addr2line -e $val $key`;
|
||||
$lines{$key} = $info;
|
||||
}
|
||||
|
||||
|
||||
foreach (@data) {
|
||||
if (/^\s*TRACE:\s+(\S+?)(?:\(.*\))?\s+\[0x(.*)\]\s*$/ ) {
|
||||
print $lines{$2};
|
||||
} else {
|
||||
print;
|
||||
}
|
||||
}
|
@ -24,6 +24,12 @@
|
||||
#include <limits.h>
|
||||
#include "testutils.h"
|
||||
#include "internal.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
|
||||
#if TEST_OOM_TRACE
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PATHS_H
|
||||
#include <paths.h>
|
||||
@ -38,6 +44,10 @@
|
||||
((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
|
||||
((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
|
||||
|
||||
static unsigned int testOOM = 0;
|
||||
static unsigned int testDebug = 0;
|
||||
static unsigned int testCounter = 0;
|
||||
|
||||
double
|
||||
virtTestCountAverage(double *items, int nitems)
|
||||
{
|
||||
@ -60,12 +70,13 @@ virtTestRun(const char *title, int nloops, int (*body)(const void *data), const
|
||||
{
|
||||
int i, ret = 0;
|
||||
double *ts = NULL;
|
||||
static int counter = 0;
|
||||
|
||||
counter++;
|
||||
testCounter++;
|
||||
|
||||
fprintf(stderr, "%2d) %-65s ... ", counter, title);
|
||||
fflush(stderr);
|
||||
if (testOOM < 2) {
|
||||
fprintf(stderr, "%2d) %-65s ... ", testCounter, title);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
if (nloops > 1 && (ts = calloc(nloops,
|
||||
sizeof(double)))==NULL)
|
||||
@ -83,13 +94,15 @@ virtTestRun(const char *title, int nloops, int (*body)(const void *data), const
|
||||
ts[i] = DIFF_MSEC(&after, &before);
|
||||
}
|
||||
}
|
||||
if (ret == 0 && ts)
|
||||
fprintf(stderr, "OK [%.5f ms]\n",
|
||||
virtTestCountAverage(ts, nloops));
|
||||
else if (ret == 0)
|
||||
fprintf(stderr, "OK\n");
|
||||
else
|
||||
fprintf(stderr, "FAILED\n");
|
||||
if (testOOM < 2) {
|
||||
if (ret == 0 && ts)
|
||||
fprintf(stderr, "OK [%.5f ms]\n",
|
||||
virtTestCountAverage(ts, nloops));
|
||||
else if (ret == 0)
|
||||
fprintf(stderr, "OK\n");
|
||||
else
|
||||
fprintf(stderr, "FAILED\n");
|
||||
}
|
||||
|
||||
free(ts);
|
||||
return ret;
|
||||
@ -232,13 +245,14 @@ int virtTestDifference(FILE *stream,
|
||||
const char *expectEnd = expect + (strlen(expect)-1);
|
||||
const char *actualStart = actual;
|
||||
const char *actualEnd = actual + (strlen(actual)-1);
|
||||
const char *debug;
|
||||
|
||||
if ((debug = getenv("DEBUG_TESTS")) == NULL)
|
||||
if (testOOM < 2)
|
||||
return 0;
|
||||
|
||||
if (STREQ(debug, "") ||
|
||||
STREQ(debug, "1")) {
|
||||
if (!testDebug)
|
||||
return 0;
|
||||
|
||||
if (testDebug < 2) {
|
||||
/* Skip to first character where they differ */
|
||||
while (*expectStart && *actualStart &&
|
||||
*actualStart == *expectStart) {
|
||||
@ -272,3 +286,114 @@ int virtTestDifference(FILE *stream,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
virtTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED,
|
||||
virErrorPtr err ATTRIBUTE_UNUSED)
|
||||
{ }
|
||||
|
||||
static void
|
||||
virtTestErrorHook(void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#if TEST_OOM_TRACE
|
||||
void *trace[30];
|
||||
int ntrace = ARRAY_CARDINALITY(trace);
|
||||
int i;
|
||||
char **symbols = NULL;
|
||||
|
||||
ntrace = backtrace(trace, ntrace);
|
||||
symbols = backtrace_symbols(trace, ntrace);
|
||||
if (symbols) {
|
||||
fprintf(stderr, "Failing an allocation at:\n");
|
||||
for (i = 0 ; i < ntrace ; i++) {
|
||||
if (symbols[i])
|
||||
fprintf(stderr, " TRACE: %s\n", symbols[i]);
|
||||
}
|
||||
free(symbols);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int virtTestMain(int argc,
|
||||
char **argv,
|
||||
int (*func)(int, char **))
|
||||
{
|
||||
#if TEST_OOM
|
||||
int ret;
|
||||
int approxAlloc = 0;
|
||||
int n;
|
||||
char *oomStr = NULL, *debugStr;
|
||||
int oomCount;
|
||||
|
||||
if ((debugStr = getenv("VIR_TEST_DEBUG")) != NULL) {
|
||||
if (virStrToLong_i(debugStr, NULL, 10, &testDebug) < 0)
|
||||
testDebug = 0;
|
||||
|
||||
if (testDebug < 0)
|
||||
testDebug = 0;
|
||||
}
|
||||
|
||||
if ((oomStr = getenv("VIR_TEST_OOM")) != NULL) {
|
||||
if (virStrToLong_i(oomStr, NULL, 10, &oomCount) < 0)
|
||||
oomCount = 0;
|
||||
|
||||
if (oomCount < 0)
|
||||
oomCount = 0;
|
||||
if (oomCount)
|
||||
testOOM = 1;
|
||||
}
|
||||
|
||||
if (testOOM)
|
||||
virAllocTestInit();
|
||||
|
||||
/* Run once to count allocs, and ensure it passes :-) */
|
||||
ret = (func)(argc, argv);
|
||||
if (ret != EXIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (testDebug)
|
||||
virAllocTestHook(virtTestErrorHook, NULL);
|
||||
|
||||
|
||||
if (testOOM) {
|
||||
/* Makes next test runs quiet... */
|
||||
testOOM++;
|
||||
virSetErrorFunc(NULL, virtTestErrorFuncQuiet);
|
||||
|
||||
approxAlloc = virAllocTestCount();
|
||||
testCounter++;
|
||||
if (testDebug)
|
||||
fprintf(stderr, "%d) OOM...\n", testCounter);
|
||||
else
|
||||
fprintf(stderr, "%d) OOM of %d allocs ", testCounter, approxAlloc);
|
||||
|
||||
/* Run once for each alloc, failing a different one
|
||||
and validating that the test case failed */
|
||||
for (n = 0; n < approxAlloc ; n++) {
|
||||
if (!testDebug) {
|
||||
fprintf(stderr, ".");
|
||||
fflush(stderr);
|
||||
}
|
||||
virAllocTestOOM(n+1, oomCount);
|
||||
|
||||
if (((func)(argc, argv)) != EXIT_FAILURE) {
|
||||
ret = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (testDebug)
|
||||
fprintf(stderr, " ... OOM of %d allocs", approxAlloc);
|
||||
|
||||
if (ret == EXIT_SUCCESS)
|
||||
fprintf(stderr, " OK\n");
|
||||
else
|
||||
fprintf(stderr, " FAILED\n");
|
||||
}
|
||||
return ret;
|
||||
|
||||
#else
|
||||
return (func)(argc, argv);
|
||||
#endif
|
||||
}
|
||||
|
@ -37,6 +37,15 @@ extern "C" {
|
||||
const char *expect,
|
||||
const char *actual);
|
||||
|
||||
int virtTestMain(int argc,
|
||||
char **argv,
|
||||
int (*func)(int, char **));
|
||||
|
||||
#define VIRT_TEST_MAIN(func) \
|
||||
int main(int argc, char **argv) { \
|
||||
return virtTestMain(argc,argv, func); \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user