mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
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: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
47d2dc831a
commit
6326865e6b
1
.gitignore
vendored
1
.gitignore
vendored
@ -169,6 +169,7 @@
|
||||
/tests/objectlocking.cm[ix]
|
||||
/tests/reconnect
|
||||
/tests/ssh
|
||||
/tests/test_file_access.txt
|
||||
/tests/test_conf
|
||||
/tools/libvirt-guests.sh
|
||||
/tools/virt-login-shell
|
||||
|
11
HACKING
11
HACKING
@ -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
|
||||
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
|
||||
|
@ -189,6 +189,19 @@
|
||||
under gdb or Valgrind.
|
||||
</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><p>The Valgrind test should produce similar output to
|
||||
<code>make check</code>. If the output has traces within libvirt
|
||||
|
@ -18,7 +18,9 @@
|
||||
|
||||
# old automake does not provide abs_{src,build}dir variables
|
||||
abs_builddir = $(shell pwd)
|
||||
abs_topbuilddir = $(shell cd .. && pwd)
|
||||
abs_srcdir = $(shell cd $(srcdir) && pwd)
|
||||
abs_topsrcdir = $(shell cd $(top_srcdir) && pwd)
|
||||
|
||||
SHELL = $(PREFERABLY_POSIX_SHELL)
|
||||
|
||||
@ -33,7 +35,9 @@ INCLUDES = \
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Dabs_builddir="\"$(abs_builddir)\"" \
|
||||
-Dabs_topbuilddir="\"$(abs_topbuilddir)\"" \
|
||||
-Dabs_srcdir="\"$(abs_srcdir)\"" \
|
||||
-Dabs_topsrcdir="\"$(abs_topsrcdir)\"" \
|
||||
$(LIBXML_CFLAGS) \
|
||||
$(LIBNL_CFLAGS) \
|
||||
$(GNUTLS_CFLAGS) \
|
||||
@ -1147,7 +1151,9 @@ virtestmock_la_SOURCES = \
|
||||
virtestmock.c
|
||||
virtestmock_la_CFLAGS = $(AM_CFLAGS)
|
||||
virtestmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
|
||||
virtestmock_la_LIBADD = $(MOCKLIBS_LIBS)
|
||||
virtestmock_la_LIBADD = \
|
||||
$(MOCKLIBS_LIBS) \
|
||||
../src/libvirt_util.la
|
||||
else ! WITH_LINUX
|
||||
EXTRA_DIST += virusbtest.c virusbmock.c \
|
||||
virnetdevbandwidthtest.c virnetdevbandwidthmock.c \
|
||||
|
@ -156,6 +156,11 @@ virtTestRun(const char *title,
|
||||
{
|
||||
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())
|
||||
fprintf(stderr, " ");
|
||||
|
||||
@ -280,6 +285,7 @@ virtTestRun(const char *title,
|
||||
}
|
||||
#endif /* TEST_OOM */
|
||||
|
||||
unsetenv("VIR_TEST_MOCK_TESTNAME");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -832,8 +838,11 @@ virTestSetEnvPath(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define TEST_MOCK (abs_builddir "/.libs/virtestmock.so")
|
||||
|
||||
int virtTestMain(int argc,
|
||||
char **argv,
|
||||
const char *lib,
|
||||
int (*func)(void))
|
||||
{
|
||||
int ret;
|
||||
@ -842,6 +851,18 @@ int virtTestMain(int argc,
|
||||
char *oomstr;
|
||||
#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]);
|
||||
|
||||
if (virTestSetEnvPath() < 0)
|
||||
@ -850,9 +871,6 @@ int virtTestMain(int argc,
|
||||
if (!virFileExists(abs_srcdir))
|
||||
return EXIT_AM_HARDFAIL;
|
||||
|
||||
progname = last_component(argv[0]);
|
||||
if (STRPREFIX(progname, "lt-"))
|
||||
progname += 3;
|
||||
if (argc > 1) {
|
||||
fprintf(stderr, "Usage: %s\n", argv[0]);
|
||||
fputs("effective environment variables:\n"
|
||||
|
@ -102,12 +102,13 @@ const char *virtTestCounterNext(void);
|
||||
|
||||
int virtTestMain(int argc,
|
||||
char **argv,
|
||||
const char *lib,
|
||||
int (*func)(void));
|
||||
|
||||
/* Setup, then call func() */
|
||||
# define VIRT_TEST_MAIN(func) \
|
||||
int main(int argc, char **argv) { \
|
||||
return virtTestMain(argc, argv, func); \
|
||||
# define VIRT_TEST_MAIN(func) \
|
||||
int main(int argc, char **argv) { \
|
||||
return virtTestMain(argc, argv, NULL, func); \
|
||||
}
|
||||
|
||||
# define VIRT_TEST_PRELOAD(lib) \
|
||||
@ -132,8 +133,7 @@ int virtTestMain(int argc,
|
||||
|
||||
# define VIRT_TEST_MAIN_PRELOAD(func, lib) \
|
||||
int main(int argc, char **argv) { \
|
||||
VIRT_TEST_PRELOAD(lib); \
|
||||
return virtTestMain(argc, argv, func); \
|
||||
return virtTestMain(argc, argv, lib, func); \
|
||||
}
|
||||
|
||||
virCapsPtr virTestGenericCapsInit(void);
|
||||
|
@ -24,9 +24,14 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <execinfo.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "configmake.h"
|
||||
#include "virstring.h"
|
||||
#include "viralloc.h"
|
||||
#include "virfile.h"
|
||||
|
||||
static int (*real_open)(const char *path, int flags, ...);
|
||||
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);
|
||||
static int (*real_lstat)(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)
|
||||
{
|
||||
if (real_open)
|
||||
@ -49,9 +59,90 @@ static void init_syms(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();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user