From 364f53a67a5161bfafe0d954cac112bcd8b2cbd7 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 29 May 2008 15:21:45 +0000 Subject: [PATCH] Generic test suite helpers for OOM testing --- ChangeLog | 7 +++ tests/Makefile.am | 1 + tests/oomtrace.pl | 41 ++++++++++++ tests/testutils.c | 155 +++++++++++++++++++++++++++++++++++++++++----- tests/testutils.h | 9 +++ 5 files changed, 198 insertions(+), 15 deletions(-) create mode 100644 tests/oomtrace.pl diff --git a/ChangeLog b/ChangeLog index 080e32fb89..ed7cc0acc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Thu May 29 11:12:00 EST 2008 Daniel P. Berrange + + * 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 * src/memory.c, src/memory.h, configure.ac: Add generics hooks diff --git a/tests/Makefile.am b/tests/Makefile.am index 214094f0a9..303388ce49 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -33,6 +33,7 @@ LDADDS = \ $(COVERAGE_LDFLAGS) EXTRA_DIST = \ + oomtrace.pl \ test-lib.sh \ xmlrpcserver.py \ test_conf.sh \ diff --git a/tests/oomtrace.pl b/tests/oomtrace.pl new file mode 100644 index 0000000000..c615ed93e6 --- /dev/null +++ b/tests/oomtrace.pl @@ -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; + } +} diff --git a/tests/testutils.c b/tests/testutils.c index ea2c59f0e4..da24093ee0 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -24,6 +24,12 @@ #include #include "testutils.h" #include "internal.h" +#include "memory.h" +#include "util.h" + +#if TEST_OOM_TRACE +#include +#endif #ifdef HAVE_PATHS_H #include @@ -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 +} diff --git a/tests/testutils.h b/tests/testutils.h index b1cd22e13b..5050926a90 100644 --- a/tests/testutils.h +++ b/tests/testutils.h @@ -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 -- GitLab