From nobody Wed Feb 11 07:09:33 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 149311869022863.52609711894195; Tue, 25 Apr 2017 04:11:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 31C623DBC1; Tue, 25 Apr 2017 11:11:28 +0000 (UTC) Received: from colo-mx.corp.redhat.com (unknown [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 013B079C62; Tue, 25 Apr 2017 11:11:28 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id A60665EC60; Tue, 25 Apr 2017 11:11:27 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v3PBAc3m031892 for ; Tue, 25 Apr 2017 07:10:38 -0400 Received: by smtp.corp.redhat.com (Postfix) id 51DD890DC9; Tue, 25 Apr 2017 11:10:38 +0000 (UTC) Received: from caroline.brq.redhat.com (dhcp129-198.brq.redhat.com [10.34.129.198]) by smtp.corp.redhat.com (Postfix) with ESMTP id A79F617BA3; Tue, 25 Apr 2017 11:10:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 31C623DBC1 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 31C623DBC1 From: Martin Kletzander To: libvir-list@redhat.com Date: Tue, 25 Apr 2017 13:10:25 +0200 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Cc: =?UTF-8?q?Erik=20=C5=A0kult=C3=A9ty?= Subject: [libvirt] [PATCH v3 1/8] tests: Add virfilewrapper -- the new super "mock" X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 25 Apr 2017 11:11:29 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This mock (which is actually not mock at all, see later) can redirect all accesses to a path into another path. There is no need to create mocks for particular directories, you just create a directory with all the data a redirect the test there. In the future, this should also be able to register callbacks for calls/paths, e.g. when the test is going to write into anything under "/sys/devices", call function fce(); Then in the open() call we would add information about the fd into some structure and in write() we would call fce() with parameters like @path to write to, @data to be written and pointer to optional return value, so that fce() itself could stop the call from happening or change its behaviour. But that's an idea for a latter day. This is not a mock because it will not be preloaded, but compiled in the test itself. See future patches for usage. Signed-off-by: Martin Kletzander --- cfg.mk | 4 +- tests/Makefile.am | 2 +- tests/virfilewrapper.c | 281 +++++++++++++++++++++++++++++++++++++++++++++= ++++ tests/virfilewrapper.h | 31 ++++++ 4 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 tests/virfilewrapper.c create mode 100644 tests/virfilewrapper.h diff --git a/cfg.mk b/cfg.mk index c04a9911eb78..ed4129e418bc 100644 --- a/cfg.mk +++ b/cfg.mk @@ -1129,7 +1129,7 @@ exclude_file_name_regexp--sc_copyright_usage =3D \ ^COPYING(|\.LESSER)$$ exclude_file_name_regexp--sc_flags_usage =3D \ - ^(cfg\.mk|docs/|src/util/virnetdevtap\.c$$|tests/(vir(cgroup|pci|test|us= b)|nss|qemuxml2argv)mock\.c$$) + ^(cfg\.mk|docs/|src/util/virnetdevtap\.c$$|tests/((vir(cgroup|pci|test|u= sb)|nss|qemuxml2argv)mock|virfilewrapper)\.c$$) exclude_file_name_regexp--sc_libvirt_unmarked_diagnostics =3D \ ^(src/rpc/gendispatch\.pl$$|tests/) @@ -1258,7 +1258,7 @@ exclude_file_name_regexp--sc_prohibit_always-defined_= macros =3D \ ^tests/virtestmock.c$$ exclude_file_name_regexp--sc_prohibit_readdir =3D \ - ^tests/.*mock\.c$$ + ^tests/(.*mock|virfilewrapper)\.c$$ exclude_file_name_regexp--sc_prohibit_cross_inclusion =3D \ ^(src/util/virclosecallbacks\.h|src/util/virhostdev\.h)$$ diff --git a/tests/Makefile.am b/tests/Makefile.am index 279e9b7da866..2685098f4343 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1156,7 +1156,7 @@ virnumamock_la_CFLAGS =3D $(AM_CFLAGS) virnumamock_la_LDFLAGS =3D $(MOCKLIBS_LDFLAGS) virnumamock_la_LIBADD =3D $(MOCKLIBS_LIBS) else ! WITH_LINUX -EXTRA_DIST +=3D vircaps2xmltest.c virnumamock.c +EXTRA_DIST +=3D vircaps2xmltest.c virnumamock.c virfilewrapper.c virfilewr= apper.h endif ! WITH_LINUX if WITH_NSS diff --git a/tests/virfilewrapper.c b/tests/virfilewrapper.c new file mode 100644 index 000000000000..81537a6baf61 --- /dev/null +++ b/tests/virfilewrapper.c @@ -0,0 +1,281 @@ +/* + * virfilewrapper.c: Wrapper for universal file access + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#include + +#include "virmock.h" +#include "virfilewrapper.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "viralloc.h" +#include "virstring.h" +#include "virfile.h" + + +/* Mapping for prefix overrides */ +static size_t noverrides; +static const char **overrides; + +/* nprefixes =3D=3D noverrides, but two variables make it easier to use + * VIR_*_ELEMENT macros */ +static size_t nprefixes; +static const char **prefixes; + +/* TODO: callbacks */ + + +static int (*real_open)(const char *path, int flags, ...); +static FILE *(*real_fopen)(const char *path, const char *mode); +static int (*real_access)(const char *path, int mode); +static int (*real_stat)(const char *path, struct stat *sb); +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 int (*real_mkdir)(const char *path, mode_t mode); +static DIR *(*real_opendir)(const char *path); + +static void init_syms(void) +{ + if (real_fopen) + return; + + VIR_MOCK_REAL_INIT(fopen); + VIR_MOCK_REAL_INIT(access); + VIR_MOCK_REAL_INIT_ALT(lstat, __lxstat); + VIR_MOCK_REAL_INIT_ALT(stat, __xstat); + VIR_MOCK_REAL_INIT(mkdir); + VIR_MOCK_REAL_INIT(open); + VIR_MOCK_REAL_INIT(opendir); +} + + +int +virFileWrapperAddPrefix(const char *prefix, + const char *override) +{ + /* Both parameters are mandatory */ + if (!prefix || !override) + return -1; + + init_syms(); + + if (VIR_APPEND_ELEMENT_QUIET(prefixes, nprefixes, prefix) < 0 || + VIR_APPEND_ELEMENT_QUIET(overrides, noverrides, override) < 0) { + VIR_FREE(prefixes); + VIR_FREE(overrides); + return -1; + } + + return 0; +} + + +void +virFileWrapperRemovePrefix(const char *prefix) +{ + size_t i =3D 0; + + for (i =3D 0; i < noverrides; i++) { + if (STREQ(prefixes[i], prefix)) + break; + } + + if (i =3D=3D noverrides) + return; + + VIR_DELETE_ELEMENT(overrides, i, noverrides); + VIR_DELETE_ELEMENT(prefixes, i, nprefixes); +} + +void +virFileWrapperClearPrefixes(void) +{ + nprefixes =3D 0; + noverrides =3D 0; + + VIR_FREE(prefixes); + VIR_FREE(overrides); +} + +static char * +virFileWrapperOverridePrefix(const char *path) +{ + char *ret =3D NULL; + size_t i =3D 0; + + for (i =3D 0; i < noverrides; i++) { + const char *tmp =3D STRSKIP(path, prefixes[i]); + + if (!tmp) + continue; + + if (virAsprintfQuiet(&ret, "%s%s", overrides[i], tmp) < 0) + return NULL; + + break; + } + + if (!ret) + ignore_value(VIR_STRDUP_QUIET(ret, path)); + + return ret; +} + + +#define PATH_OVERRIDE(newpath, path) \ + do { \ + init_syms(); \ + \ + newpath =3D virFileWrapperOverridePrefix(path); \ + if (!newpath) \ + abort(); \ + } while (0) + + +FILE *fopen(const char *path, const char *mode) +{ + FILE *ret =3D NULL; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real_fopen(newpath, mode); + + VIR_FREE(newpath); + + return ret; +} + +int access(const char *path, int mode) +{ + int ret =3D -1; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real_access(newpath, mode); + + VIR_FREE(newpath); + + return ret; +} + +int __lxstat(int ver, const char *path, struct stat *sb) +{ + int ret =3D -1; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real___lxstat(ver, newpath, sb); + + VIR_FREE(newpath); + + return ret; +} + +int lstat(const char *path, struct stat *sb) +{ + int ret =3D -1; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real_lstat(newpath, sb); + + VIR_FREE(newpath); + + return ret; +} + +int __xstat(int ver, const char *path, struct stat *sb) +{ + int ret =3D -1; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real___xstat(ver, newpath, sb); + + VIR_FREE(newpath); + + return ret; +} + +int stat(const char *path, struct stat *sb) +{ + int ret =3D -1; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real_stat(newpath, sb); + + VIR_FREE(newpath); + + return ret; +} + +int mkdir(const char *path, mode_t mode) +{ + int ret =3D -1; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real_mkdir(newpath, mode); + + VIR_FREE(newpath); + + return ret; +} + +int open(const char *path, int flags, ...) +{ + int ret =3D -1; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real_open(newpath, flags); + + VIR_FREE(newpath); + + return ret; +} + +DIR *opendir(const char *path) +{ + DIR *ret =3D NULL; + char *newpath =3D NULL; + + PATH_OVERRIDE(newpath, path); + + ret =3D real_opendir(newpath); + + VIR_FREE(newpath); + + return ret; +} diff --git a/tests/virfilewrapper.h b/tests/virfilewrapper.h new file mode 100644 index 000000000000..612322c1d044 --- /dev/null +++ b/tests/virfilewrapper.h @@ -0,0 +1,31 @@ +/* + * virfilewrapper.h: Wrapper for universal file access + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#ifndef __VIR_FILE_MOCK_H__ + +int +virFileWrapperAddPrefix(const char *prefix, + const char *override); + +void +virFileWrapperRemovePrefix(const char *prefix); + +void +virFileWrapperClearPrefixes(void); + +#endif /* __VIR_FILE_MOCK_H__ */ --=20 2.12.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list