Loading tests/integration/CMakeLists.txt +9 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,15 @@ if (GKFS_RENAME_SUPPORT) ) endif () if (GKFS_BUILD_FUSE) gkfs_add_python_test( NAME test_fuse_client PYTHON_VERSION 3.6 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/integration SOURCE fuse/ ) endif () if (GKFS_INSTALL_TESTS) install(DIRECTORY harness DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gkfs/tests/integration Loading tests/integration/conftest.py +16 −4 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ from pathlib import Path from harness.logger import logger, initialize_logging, finalize_logging from harness.cli import add_cli_options, set_default_log_formatter from harness.workspace import Workspace, FileCreator from harness.gkfs import Daemon, Client, ClientLibc, Proxy, ShellClient, ShellClientLibc, FwdDaemon, FwdClient, ShellFwdClient, FwdDaemonCreator, FwdClientCreator from harness.gkfs import Daemon, Client, ClientLibc, Proxy, ShellClient, ShellClientLibc, FwdDaemon, FwdClient, ShellFwdClient, FwdDaemonCreator, FwdClientCreator, FuseClient from harness.reporter import report_test_status, report_test_headline, report_assertion_pass def pytest_configure(config): Loading Loading @@ -225,3 +225,15 @@ def gkfwd_client_factory(test_workspace): """ return FwdClientCreator(test_workspace) @pytest.fixture def fuse_client(test_workspace): """ Sets up a gekkofs fuse client environment so that operations (system calls, library calls, ...) can be requested from a co-running daemon. """ fuse_client = FuseClient(test_workspace) yield fuse_client.run() fuse_client.shutdown() tests/integration/fuse/test_basic_operations.py 0 → 100644 +49 −0 Original line number Diff line number Diff line ################################################################################ # Copyright 2018-2025, Barcelona Supercomputing Center (BSC), Spain # # Copyright 2015-2025, Johannes Gutenberg Universitaet Mainz, Germany # # # # This software was partially supported by the # # EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). # # # # This software was partially supported by the # # ADA-FS project under the SPPEXA project funded by the DFG. # # # # This file is part of GekkoFS. # # # # GekkoFS is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # GekkoFS 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 General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with GekkoFS. If not, see <https://www.gnu.org/licenses/>. # # # # SPDX-License-Identifier: GPL-3.0-or-later # ################################################################################ import harness from pathlib import Path import errno import stat import os import ctypes import sh import sys import pytest import time from harness.logger import logger nonexisting = "nonexisting" def test_read(gkfs_daemon, fuse_client): file = gkfs_daemon.mountdir / "file" sh.bash("-c", "echo baum > " + str(file)) assert sh.ls(fuse_client.mountdir) == "file\n" assert sh.cat(file) == "baum\n" tests/integration/harness/gkfs.py +89 −11 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ gkfwd_client_log_level = 'all' gkfwd_client_log_syscall_filter = 'epoll_wait,epoll_create' gkfwd_daemon_active_log_pattern = r'Startup successful. Daemon is ready.' gkfs_fuse_client = 'fuse_client' def get_ip_addr(iface): return netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr'] Loading Loading @@ -1637,3 +1638,80 @@ class ShellFwdClient: @property def cwd(self): return self._workspace.twd class FuseClient: def __init__(self, workspace): self._workspace = workspace #self._cmd = sh.Command("printenv", ["/usr/bin/"])#self._workspace.bindirs) self._cmd = sh.Command(gkfs_fuse_client, self._workspace.bindirs) self._env = os.environ.copy() self._metadir = self.rootdir libdirs = ':'.join( filter(None, [os.environ.get('LD_LIBRARY_PATH', '')] + [str(p) for p in self._workspace.libdirs])) self._patched_env = { 'LD_LIBRARY_PATH' : libdirs, 'GKFS_HOSTS_FILE' : str(self.cwd / gkfs_hosts_file), 'LIBGKFS_HOSTS_FILE' : str(self.cwd / gkfs_hosts_file), # TODO wtf why? see gkfs::env::HOSTS_FILE } self._env.update(self._patched_env) def run(self): args = [ "-f", "-s", self._workspace.mountdir, "-o", "auto_unmount" ] print(f"spawning fuse client") print(f"cmdline: {self._cmd} " + " ".join(map(str, args))) print(f"patched env:\n{pformat(self._patched_env)}") self._proc = self._cmd( args, _env=self._env, # _out=sys.stdout, # _err=sys.stderr, _bg=True, ) print(f"fuse client process spawned (PID={self._proc.pid})") time.sleep(2) # give fuse time to register mount return self def shutdown(self): print(f"terminating fuse client and unmounting") sh.fusermount("-u", self._workspace.mountdir) try: self._proc.terminate() err = self._proc.wait() except sh.SignalException_SIGTERM: pass except Exception: raise @property def cwd(self): return self._workspace.twd @property def rootdir(self): return self._workspace.rootdir @property def mountdir(self): return self._workspace.mountdir @property def bindirs(self): return self._workspace.bindirs @property def logdir(self): return self._workspace.logdir @property def env(self): return self._env Loading
tests/integration/CMakeLists.txt +9 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,15 @@ if (GKFS_RENAME_SUPPORT) ) endif () if (GKFS_BUILD_FUSE) gkfs_add_python_test( NAME test_fuse_client PYTHON_VERSION 3.6 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/integration SOURCE fuse/ ) endif () if (GKFS_INSTALL_TESTS) install(DIRECTORY harness DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gkfs/tests/integration Loading
tests/integration/conftest.py +16 −4 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ from pathlib import Path from harness.logger import logger, initialize_logging, finalize_logging from harness.cli import add_cli_options, set_default_log_formatter from harness.workspace import Workspace, FileCreator from harness.gkfs import Daemon, Client, ClientLibc, Proxy, ShellClient, ShellClientLibc, FwdDaemon, FwdClient, ShellFwdClient, FwdDaemonCreator, FwdClientCreator from harness.gkfs import Daemon, Client, ClientLibc, Proxy, ShellClient, ShellClientLibc, FwdDaemon, FwdClient, ShellFwdClient, FwdDaemonCreator, FwdClientCreator, FuseClient from harness.reporter import report_test_status, report_test_headline, report_assertion_pass def pytest_configure(config): Loading Loading @@ -225,3 +225,15 @@ def gkfwd_client_factory(test_workspace): """ return FwdClientCreator(test_workspace) @pytest.fixture def fuse_client(test_workspace): """ Sets up a gekkofs fuse client environment so that operations (system calls, library calls, ...) can be requested from a co-running daemon. """ fuse_client = FuseClient(test_workspace) yield fuse_client.run() fuse_client.shutdown()
tests/integration/fuse/test_basic_operations.py 0 → 100644 +49 −0 Original line number Diff line number Diff line ################################################################################ # Copyright 2018-2025, Barcelona Supercomputing Center (BSC), Spain # # Copyright 2015-2025, Johannes Gutenberg Universitaet Mainz, Germany # # # # This software was partially supported by the # # EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). # # # # This software was partially supported by the # # ADA-FS project under the SPPEXA project funded by the DFG. # # # # This file is part of GekkoFS. # # # # GekkoFS is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # GekkoFS 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 General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with GekkoFS. If not, see <https://www.gnu.org/licenses/>. # # # # SPDX-License-Identifier: GPL-3.0-or-later # ################################################################################ import harness from pathlib import Path import errno import stat import os import ctypes import sh import sys import pytest import time from harness.logger import logger nonexisting = "nonexisting" def test_read(gkfs_daemon, fuse_client): file = gkfs_daemon.mountdir / "file" sh.bash("-c", "echo baum > " + str(file)) assert sh.ls(fuse_client.mountdir) == "file\n" assert sh.cat(file) == "baum\n"
tests/integration/harness/gkfs.py +89 −11 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ gkfwd_client_log_level = 'all' gkfwd_client_log_syscall_filter = 'epoll_wait,epoll_create' gkfwd_daemon_active_log_pattern = r'Startup successful. Daemon is ready.' gkfs_fuse_client = 'fuse_client' def get_ip_addr(iface): return netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr'] Loading Loading @@ -1637,3 +1638,80 @@ class ShellFwdClient: @property def cwd(self): return self._workspace.twd class FuseClient: def __init__(self, workspace): self._workspace = workspace #self._cmd = sh.Command("printenv", ["/usr/bin/"])#self._workspace.bindirs) self._cmd = sh.Command(gkfs_fuse_client, self._workspace.bindirs) self._env = os.environ.copy() self._metadir = self.rootdir libdirs = ':'.join( filter(None, [os.environ.get('LD_LIBRARY_PATH', '')] + [str(p) for p in self._workspace.libdirs])) self._patched_env = { 'LD_LIBRARY_PATH' : libdirs, 'GKFS_HOSTS_FILE' : str(self.cwd / gkfs_hosts_file), 'LIBGKFS_HOSTS_FILE' : str(self.cwd / gkfs_hosts_file), # TODO wtf why? see gkfs::env::HOSTS_FILE } self._env.update(self._patched_env) def run(self): args = [ "-f", "-s", self._workspace.mountdir, "-o", "auto_unmount" ] print(f"spawning fuse client") print(f"cmdline: {self._cmd} " + " ".join(map(str, args))) print(f"patched env:\n{pformat(self._patched_env)}") self._proc = self._cmd( args, _env=self._env, # _out=sys.stdout, # _err=sys.stderr, _bg=True, ) print(f"fuse client process spawned (PID={self._proc.pid})") time.sleep(2) # give fuse time to register mount return self def shutdown(self): print(f"terminating fuse client and unmounting") sh.fusermount("-u", self._workspace.mountdir) try: self._proc.terminate() err = self._proc.wait() except sh.SignalException_SIGTERM: pass except Exception: raise @property def cwd(self): return self._workspace.twd @property def rootdir(self): return self._workspace.rootdir @property def mountdir(self): return self._workspace.mountdir @property def bindirs(self): return self._workspace.bindirs @property def logdir(self): return self._workspace.logdir @property def env(self): return self._env