From 86d1705a8ace349b078616569418e6b7e2eca1aa Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Fri, 13 May 2016 13:42:13 +0200 Subject: [PATCH] virmock.h: Introduce VIR_MOCK_CALL_STAT There is some magic going on when it comes to stat() or lstat(). Basically, stat() can either be a regular function, an inline function that calls __xstat(_STAT_VER, ...) or a macro that does the same as the inline func. Don't ask why is that, just read the documentation in sys/stat.h and make sure you have a bucket next to you. Anyway, currently there will not be both stat and __xstat symbols at the same time, as one of them gets overwritten to the other one during compilation. But this is not true anymore once we start chaining our mocking libraries. Therefore we need a wrapper that calls desired function from glibc. Signed-off-by: Michal Privoznik --- tests/vircgroupmock.c | 14 +++++++------- tests/virmock.h | 23 +++++++++++++++++++++++ tests/virpcimock.c | 19 +++++++++---------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c index ce6fd46266..c2d3b807cd 100644 --- a/tests/vircgroupmock.c +++ b/tests/vircgroupmock.c @@ -558,7 +558,7 @@ int __lxstat(int ver, const char *path, struct stat *sb) errno = ENOMEM; return -1; } - ret = real___lxstat(ver, newpath, sb); + ret = VIR_MOCK_CALL_LSTAT(ver, newpath, sb); free(newpath); } else if (STRPREFIX(path, fakedevicedir0)) { sb->st_mode = S_IFBLK; @@ -569,7 +569,7 @@ int __lxstat(int ver, const char *path, struct stat *sb) sb->st_rdev = makedev(9, 0); return 0; } else { - ret = real___lxstat(ver, path, sb); + ret = VIR_MOCK_CALL_LSTAT(ver, path, sb); } return ret; } @@ -589,7 +589,7 @@ int lstat(const char *path, struct stat *sb) errno = ENOMEM; return -1; } - ret = real_lstat(newpath, sb); + ret = VIR_MOCK_CALL_LSTAT(_STAT_VER, newpath, sb); free(newpath); } else if (STRPREFIX(path, fakedevicedir0)) { sb->st_mode = S_IFBLK; @@ -600,7 +600,7 @@ int lstat(const char *path, struct stat *sb) sb->st_rdev = makedev(9, 0); return 0; } else { - ret = real_lstat(path, sb); + ret = VIR_MOCK_CALL_LSTAT(_STAT_VER, path, sb); } return ret; } @@ -620,7 +620,7 @@ int __xstat(int ver, const char *path, struct stat *sb) errno = ENOMEM; return -1; } - ret = real___xstat(ver, newpath, sb); + ret = VIR_MOCK_CALL_STAT(ver, newpath, sb); free(newpath); } else if (STRPREFIX(path, fakedevicedir0)) { sb->st_mode = S_IFBLK; @@ -631,7 +631,7 @@ int __xstat(int ver, const char *path, struct stat *sb) sb->st_rdev = makedev(9, 0); return 0; } else { - ret = real___xstat(ver, path, sb); + ret = VIR_MOCK_CALL_STAT(ver, path, sb); } return ret; } @@ -671,7 +671,7 @@ int stat(const char *path, struct stat *sb) if (!(newpath = strdup(path))) return -1; } - ret = real_stat(newpath, sb); + ret = VIR_MOCK_CALL_STAT(_STAT_VER, newpath, sb); free(newpath); return ret; } diff --git a/tests/virmock.h b/tests/virmock.h index 62a7c8fed4..27c03ba0aa 100644 --- a/tests/virmock.h +++ b/tests/virmock.h @@ -27,6 +27,7 @@ # endif # include # include +# include # include "internal.h" @@ -254,6 +255,28 @@ static void (*real_##name)(void); \ void name(void) +static inline int +callStat(int (*realStat)(const char *, struct stat *), + int (*realXstat)(int, const char *, struct stat *), + int __ver, const char *__filename, struct stat *__stat_buf) +{ + if (!realXstat) { + if (__ver == _STAT_VER) { + return realStat(__filename, __stat_buf); + } else { + fprintf(stderr, "Not handled __xstat(ver=%d)", __ver); + abort(); + } + } + + return realXstat(__ver, __filename, __stat_buf); +} + +# define VIR_MOCK_CALL_STAT(__ver, __filename, __stat_buf) \ + callStat(real_stat, real___xstat, __ver, __filename, __stat_buf) +# define VIR_MOCK_CALL_LSTAT(__ver, __filename, __stat_buf) \ + callStat(real_lstat, real___lxstat, __ver, __filename, __stat_buf) + /* * The VIR_MOCK_WRAP_NNN_MMM() macros are intended for use in the * individual test suites. The define a stub implementation of diff --git a/tests/virpcimock.c b/tests/virpcimock.c index e9408aa0ae..60b3b74bf5 100644 --- a/tests/virpcimock.c +++ b/tests/virpcimock.c @@ -353,8 +353,7 @@ pci_device_new_from_stub(const struct pciDevice *data) /* If there is a config file for the device within virpcitestdata dir, * symlink it. Otherwise create a dummy config file. */ - if ((real_stat && real_stat(configSrc, &sb) == 0) || - (real___xstat && real___xstat(_STAT_VER, configSrc, &sb) == 0)) { + if (VIR_MOCK_CALL_STAT(_STAT_VER, configSrc, &sb) == 0) { /* On success, copy @configSrc into the destination (a copy, * rather than a symlink, is required since we write into the * file, and parallel VPATH builds must not stomp on the @@ -869,10 +868,10 @@ __lxstat(int ver, const char *path, struct stat *sb) char *newpath; if (getrealpath(&newpath, path) < 0) return -1; - ret = real___lxstat(ver, newpath, sb); + ret = VIR_MOCK_CALL_LSTAT(ver, newpath, sb); VIR_FREE(newpath); } else { - ret = real___lxstat(ver, path, sb); + ret = VIR_MOCK_CALL_LSTAT(ver, path, sb); } return ret; } @@ -888,10 +887,10 @@ lstat(const char *path, struct stat *sb) char *newpath; if (getrealpath(&newpath, path) < 0) return -1; - ret = real_lstat(newpath, sb); + ret = VIR_MOCK_CALL_LSTAT(_STAT_VER, newpath, sb); VIR_FREE(newpath); } else { - ret = real_lstat(path, sb); + ret = VIR_MOCK_CALL_LSTAT(_STAT_VER, path, sb); } return ret; } @@ -907,10 +906,10 @@ __xstat(int ver, const char *path, struct stat *sb) char *newpath; if (getrealpath(&newpath, path) < 0) return -1; - ret = real___xstat(ver, newpath, sb); + ret = VIR_MOCK_CALL_STAT(ver, newpath, sb); VIR_FREE(newpath); } else { - ret = real___xstat(ver, path, sb); + ret = VIR_MOCK_CALL_STAT(ver, path, sb); } return ret; } @@ -926,10 +925,10 @@ stat(const char *path, struct stat *sb) char *newpath; if (getrealpath(&newpath, path) < 0) return -1; - ret = real_stat(newpath, sb); + ret = VIR_MOCK_CALL_STAT(_STAT_VER, newpath, sb); VIR_FREE(newpath); } else { - ret = real_stat(path, sb); + ret = VIR_MOCK_CALL_STAT(_STAT_VER, path, sb); } return ret; }