/tests/objectlocking.cm[ix]
/tests/reconnect
/tests/ssh
+/tests/test_file_access.txt
/tests/test_conf
/tools/libvirt-guests.sh
/tools/virt-login-shell
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
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
# 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)
AM_CFLAGS = \
-Dabs_builddir="\"$(abs_builddir)\"" \
+ -Dabs_topbuilddir="\"$(abs_topbuilddir)\"" \
-Dabs_srcdir="\"$(abs_srcdir)\"" \
+ -Dabs_topsrcdir="\"$(abs_topsrcdir)\"" \
$(LIBXML_CFLAGS) \
$(LIBNL_CFLAGS) \
$(GNUTLS_CFLAGS) \
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 \
{
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, " ");
}
#endif /* TEST_OOM */
+ unsetenv("VIR_TEST_MOCK_TESTNAME");
return ret;
}
return ret;
}
+#define TEST_MOCK (abs_builddir "/.libs/virtestmock.so")
+
int virtTestMain(int argc,
char **argv,
+ const char *lib,
int (*func)(void))
{
int ret;
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)
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"
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) \
# 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);
#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);
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)
}
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();
}