From nobody Sun Feb 8 21:29:18 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 1491403473220580.3157947190714; Wed, 5 Apr 2017 07:44:33 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BC63C61D37; Wed, 5 Apr 2017 14:44:31 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7F430A4069; Wed, 5 Apr 2017 14:44:31 +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 3336918521CA; Wed, 5 Apr 2017 14:44:31 +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 v35EbIPX007253 for ; Wed, 5 Apr 2017 10:37:18 -0400 Received: by smtp.corp.redhat.com (Postfix) id C86CA78DE4; Wed, 5 Apr 2017 14:37:18 +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 AC224784C8; Wed, 5 Apr 2017 14:37:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com BC63C61D37 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.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 BC63C61D37 From: Martin Kletzander To: libvir-list@redhat.com Date: Wed, 5 Apr 2017 16:36:27 +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 v2 04/12] tests: Add virfilemock -- 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.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 05 Apr 2017 14:44:32 +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 | 2 +- tests/virfilemock.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ tests/virfilemock.h | 31 ++++++ 3 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 tests/virfilemock.c create mode 100644 tests/virfilemock.h diff --git a/cfg.mk b/cfg.mk index 89e03ca0e32c..52a684462457 100644 --- a/cfg.mk +++ b/cfg.mk @@ -1117,7 +1117,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|us= b|file)|nss|qemuxml2argv)mock\.c$$) exclude_file_name_regexp--sc_libvirt_unmarked_diagnostics =3D \ ^(src/rpc/gendispatch\.pl$$|tests/) diff --git a/tests/virfilemock.c b/tests/virfilemock.c new file mode 100644 index 000000000000..b199a64188a1 --- /dev/null +++ b/tests/virfilemock.c @@ -0,0 +1,281 @@ +/* + * virfilemock.c: Mock for universal file access mocking + * + * 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 "virfilemock.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 +virFileMockAddPrefix(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 +virFileMockRemovePrefix(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 +virFileMockClearPrefixes(void) +{ + nprefixes =3D 0; + noverrides =3D 0; + + VIR_FREE(prefixes); + VIR_FREE(overrides); +} + +static char * +virFileMockOverridePrefix(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 virFileMockOverridePrefix(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/virfilemock.h b/tests/virfilemock.h new file mode 100644 index 000000000000..eeca7d8b125a --- /dev/null +++ b/tests/virfilemock.h @@ -0,0 +1,31 @@ +/* + * virfilemock.h: Mock for universal file access mocking + * + * 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 +virFileMockAddPrefix(const char *prefix, + const char *override); + +void +virFileMockRemovePrefix(const char *prefix); + +void +virFileMockClearPrefixes(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