提交 6326865e 编写于 作者: M Michal Privoznik

virtestmock: Print invalid file accesses into a file

All the accesses to files outside our build or source directories
are now identified and appended into a file for later processing.
The location of the file that contains all the records can be
controlled via VIR_TEST_FILE_ACCESS env variable and defaults to
abs_builddir "/test_file_access.txt".

The script that will process the access file is to be added in
next commit.
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 47d2dc83
...@@ -169,6 +169,7 @@ ...@@ -169,6 +169,7 @@
/tests/objectlocking.cm[ix] /tests/objectlocking.cm[ix]
/tests/reconnect /tests/reconnect
/tests/ssh /tests/ssh
/tests/test_file_access.txt
/tests/test_conf /tests/test_conf
/tools/libvirt-guests.sh /tools/libvirt-guests.sh
/tools/virt-login-shell /tools/virt-login-shell
......
...@@ -152,6 +152,17 @@ There is also a "./run" script at the top level, to make it easier to run ...@@ -152,6 +152,17 @@ There is also a "./run" script at the top level, to make it easier to run
programs that have not yet been installed, as well as to wrap invocations of programs that have not yet been installed, as well as to wrap invocations of
various tests under gdb or Valgrind. various tests under gdb or Valgrind.
When running our test suite it may happen that the test result is
nondeterministic because of the test suite relying on a particular file in the
system being accessible or having some specific value. To catch this kind of
errors, the test suite has a module for that prints any path touched that
fulfils constraints described above into a file. To enable it just set
"VIR_TEST_FILE_ACCESS" environment variable. Then
"VIR_TEST_FILE_ACCESS_OUTPUT" environment variable can alter location where
the file is stored.
VIR_TEST_FILE_ACCESS=1 VIR_TEST_FILE_ACCESS_OUTPUT="/tmp/file_access.txt" ./qemuxml2argvtest
(9) The Valgrind test should produce similar output to "make check". If the output (9) The Valgrind test should produce similar output to "make check". If the output
......
...@@ -189,6 +189,19 @@ ...@@ -189,6 +189,19 @@
under gdb or Valgrind. under gdb or Valgrind.
</p> </p>
<p>When running our test suite it may happen that the test result is
nondeterministic because of the test suite relying on a particular file
in the system being accessible or having some specific value. To catch
this kind of errors, the test suite has a module for that prints any
path touched that fulfils constraints described above
into a file. To enable it just set
<code>VIR_TEST_FILE_ACCESS</code> environment variable.
Then <code>VIR_TEST_FILE_ACCESS_OUTPUT</code> environment
variable can alter location where the file is stored.</p>
<pre>
VIR_TEST_FILE_ACCESS=1 VIR_TEST_FILE_ACCESS_OUTPUT="/tmp/file_access.txt" ./qemuxml2argvtest
</pre>
</li> </li>
<li><p>The Valgrind test should produce similar output to <li><p>The Valgrind test should produce similar output to
<code>make check</code>. If the output has traces within libvirt <code>make check</code>. If the output has traces within libvirt
......
...@@ -18,7 +18,9 @@ ...@@ -18,7 +18,9 @@
# old automake does not provide abs_{src,build}dir variables # old automake does not provide abs_{src,build}dir variables
abs_builddir = $(shell pwd) abs_builddir = $(shell pwd)
abs_topbuilddir = $(shell cd .. && pwd)
abs_srcdir = $(shell cd $(srcdir) && pwd) abs_srcdir = $(shell cd $(srcdir) && pwd)
abs_topsrcdir = $(shell cd $(top_srcdir) && pwd)
SHELL = $(PREFERABLY_POSIX_SHELL) SHELL = $(PREFERABLY_POSIX_SHELL)
...@@ -33,7 +35,9 @@ INCLUDES = \ ...@@ -33,7 +35,9 @@ INCLUDES = \
AM_CFLAGS = \ AM_CFLAGS = \
-Dabs_builddir="\"$(abs_builddir)\"" \ -Dabs_builddir="\"$(abs_builddir)\"" \
-Dabs_topbuilddir="\"$(abs_topbuilddir)\"" \
-Dabs_srcdir="\"$(abs_srcdir)\"" \ -Dabs_srcdir="\"$(abs_srcdir)\"" \
-Dabs_topsrcdir="\"$(abs_topsrcdir)\"" \
$(LIBXML_CFLAGS) \ $(LIBXML_CFLAGS) \
$(LIBNL_CFLAGS) \ $(LIBNL_CFLAGS) \
$(GNUTLS_CFLAGS) \ $(GNUTLS_CFLAGS) \
...@@ -1147,7 +1151,9 @@ virtestmock_la_SOURCES = \ ...@@ -1147,7 +1151,9 @@ virtestmock_la_SOURCES = \
virtestmock.c virtestmock.c
virtestmock_la_CFLAGS = $(AM_CFLAGS) virtestmock_la_CFLAGS = $(AM_CFLAGS)
virtestmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS) virtestmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
virtestmock_la_LIBADD = $(MOCKLIBS_LIBS) virtestmock_la_LIBADD = \
$(MOCKLIBS_LIBS) \
../src/libvirt_util.la
else ! WITH_LINUX else ! WITH_LINUX
EXTRA_DIST += virusbtest.c virusbmock.c \ EXTRA_DIST += virusbtest.c virusbmock.c \
virnetdevbandwidthtest.c virnetdevbandwidthmock.c \ virnetdevbandwidthtest.c virnetdevbandwidthmock.c \
......
...@@ -156,6 +156,11 @@ virtTestRun(const char *title, ...@@ -156,6 +156,11 @@ virtTestRun(const char *title,
{ {
int ret = 0; int ret = 0;
/* Some test are fragile about environ settings. If that's
* the case, don't poison it. */
if (getenv("VIR_TEST_MOCK_PROGNAME"))
setenv("VIR_TEST_MOCK_TESTNAME", title, 1);
if (testCounter == 0 && !virTestGetVerbose()) if (testCounter == 0 && !virTestGetVerbose())
fprintf(stderr, " "); fprintf(stderr, " ");
...@@ -280,6 +285,7 @@ virtTestRun(const char *title, ...@@ -280,6 +285,7 @@ virtTestRun(const char *title,
} }
#endif /* TEST_OOM */ #endif /* TEST_OOM */
unsetenv("VIR_TEST_MOCK_TESTNAME");
return ret; return ret;
} }
...@@ -832,8 +838,11 @@ virTestSetEnvPath(void) ...@@ -832,8 +838,11 @@ virTestSetEnvPath(void)
return ret; return ret;
} }
#define TEST_MOCK (abs_builddir "/.libs/virtestmock.so")
int virtTestMain(int argc, int virtTestMain(int argc,
char **argv, char **argv,
const char *lib,
int (*func)(void)) int (*func)(void))
{ {
int ret; int ret;
...@@ -842,6 +851,18 @@ int virtTestMain(int argc, ...@@ -842,6 +851,18 @@ int virtTestMain(int argc,
char *oomstr; char *oomstr;
#endif #endif
if (getenv("VIR_TEST_FILE_ACCESS"))
VIRT_TEST_PRELOAD(TEST_MOCK);
if (lib)
VIRT_TEST_PRELOAD(lib);
progname = last_component(argv[0]);
if (STRPREFIX(progname, "lt-"))
progname += 3;
setenv("VIR_TEST_MOCK_PROGNAME", progname, 1);
virFileActivateDirOverride(argv[0]); virFileActivateDirOverride(argv[0]);
if (virTestSetEnvPath() < 0) if (virTestSetEnvPath() < 0)
...@@ -850,9 +871,6 @@ int virtTestMain(int argc, ...@@ -850,9 +871,6 @@ int virtTestMain(int argc,
if (!virFileExists(abs_srcdir)) if (!virFileExists(abs_srcdir))
return EXIT_AM_HARDFAIL; return EXIT_AM_HARDFAIL;
progname = last_component(argv[0]);
if (STRPREFIX(progname, "lt-"))
progname += 3;
if (argc > 1) { if (argc > 1) {
fprintf(stderr, "Usage: %s\n", argv[0]); fprintf(stderr, "Usage: %s\n", argv[0]);
fputs("effective environment variables:\n" fputs("effective environment variables:\n"
......
...@@ -102,12 +102,13 @@ const char *virtTestCounterNext(void); ...@@ -102,12 +102,13 @@ const char *virtTestCounterNext(void);
int virtTestMain(int argc, int virtTestMain(int argc,
char **argv, char **argv,
const char *lib,
int (*func)(void)); int (*func)(void));
/* Setup, then call func() */ /* Setup, then call func() */
# define VIRT_TEST_MAIN(func) \ # define VIRT_TEST_MAIN(func) \
int main(int argc, char **argv) { \ int main(int argc, char **argv) { \
return virtTestMain(argc, argv, func); \ return virtTestMain(argc, argv, NULL, func); \
} }
# define VIRT_TEST_PRELOAD(lib) \ # define VIRT_TEST_PRELOAD(lib) \
...@@ -132,8 +133,7 @@ int virtTestMain(int argc, ...@@ -132,8 +133,7 @@ int virtTestMain(int argc,
# define VIRT_TEST_MAIN_PRELOAD(func, lib) \ # define VIRT_TEST_MAIN_PRELOAD(func, lib) \
int main(int argc, char **argv) { \ int main(int argc, char **argv) { \
VIRT_TEST_PRELOAD(lib); \ return virtTestMain(argc, argv, lib, func); \
return virtTestMain(argc, argv, func); \
} }
virCapsPtr virTestGenericCapsInit(void); virCapsPtr virTestGenericCapsInit(void);
......
...@@ -24,9 +24,14 @@ ...@@ -24,9 +24,14 @@
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <execinfo.h>
#include <sys/file.h>
#include "internal.h" #include "internal.h"
#include "configmake.h" #include "configmake.h"
#include "virstring.h"
#include "viralloc.h"
#include "virfile.h"
static int (*real_open)(const char *path, int flags, ...); static int (*real_open)(const char *path, int flags, ...);
static FILE *(*real_fopen)(const char *path, const char *mode); static FILE *(*real_fopen)(const char *path, const char *mode);
...@@ -36,6 +41,11 @@ static int (*real___xstat)(int ver, const char *path, struct stat *sb); ...@@ -36,6 +41,11 @@ static int (*real___xstat)(int ver, const char *path, struct stat *sb);
static int (*real_lstat)(const char *path, struct stat *sb); static int (*real_lstat)(const char *path, struct stat *sb);
static int (*real___lxstat)(int ver, const char *path, struct stat *sb); static int (*real___lxstat)(int ver, const char *path, struct stat *sb);
static const char *progname;
const char *output;
#define VIR_FILE_ACCESS_DEFAULT abs_builddir "/test_file_access.txt"
static void init_syms(void) static void init_syms(void)
{ {
if (real_open) if (real_open)
...@@ -49,9 +59,90 @@ static void init_syms(void) ...@@ -49,9 +59,90 @@ static void init_syms(void)
} }
static void static void
checkPath(const char *path ATTRIBUTE_UNUSED) printFile(const char *file)
{ {
/* Nada */ FILE *fp;
const char *testname = getenv("VIR_TEST_MOCK_TESTNAME");
if (!progname) {
progname = getenv("VIR_TEST_MOCK_PROGNAME");
if (!progname)
return;
output = getenv("VIR_TEST_FILE_ACCESS_OUTPUT");
if (!output)
output = VIR_FILE_ACCESS_DEFAULT;
}
if (!(fp = real_fopen(output, "a"))) {
fprintf(stderr, "Unable to open %s: %s\n", output, strerror(errno));
abort();
}
if (flock(fileno(fp), LOCK_EX) < 0) {
fprintf(stderr, "Unable to lock %s: %s\n", output, strerror(errno));
fclose(fp);
abort();
}
/* Now append the following line into the output file:
* $file: $progname $testname */
fprintf(fp, "%s: %s", file, progname);
if (testname)
fprintf(fp, ": %s", testname);
fputc('\n', fp);
flock(fileno(fp), LOCK_UN);
fclose(fp);
}
static void
checkPath(const char *path)
{
char *fullPath = NULL;
char *relPath = NULL;
char *crippledPath = NULL;
if (path[0] != '/' &&
virAsprintfQuiet(&relPath, "./%s", path) < 0)
goto error;
/* Le sigh. Both canonicalize_file_name() and realpath()
* expect @path to exist otherwise they return an error. So
* if we are called over an non-existent file, this could
* return an error. In that case do our best and hope we will
* catch possible error. */
if ((fullPath = canonicalize_file_name(relPath ? relPath : path))) {
path = fullPath;
} else {
/* Yeah, our worst nightmares just became true. Path does
* not exist. Cut off the last component and retry. */
if (VIR_STRDUP_QUIET(crippledPath, relPath ? relPath : path) < 0)
goto error;
virFileRemoveLastComponent(crippledPath);
if ((fullPath = canonicalize_file_name(crippledPath)))
path = fullPath;
}
if (!STRPREFIX(path, abs_topsrcdir) &&
!STRPREFIX(path, abs_topbuilddir)) {
printFile(path);
}
VIR_FREE(crippledPath);
VIR_FREE(relPath);
VIR_FREE(fullPath);
return;
error:
fprintf(stderr, "Out of memory\n");
abort();
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册