Loading tests/integration/directories/test_sfind_diagnostic.pydeleted 100644 → 0 +0 −147 Original line number Diff line number Diff line import logging import os import time from pathlib import Path import pytest from harness.gkfs import Client, Daemon, ShellClient, find_command log = logging.getLogger(__name__) SFIND_DIAG_TIMEOUT = 180 def _read_text(path, limit=12000): try: data = Path(path).read_text(errors="replace") except OSError as exc: return f"<could not read {path}: {exc}>" if len(data) <= limit: return data return data[-limit:] def _collect_workspace_logs(test_workspace): chunks = [] for base in (test_workspace.logdir, test_workspace.twd): if not Path(base).exists(): continue for path in sorted(Path(base).glob("**/*")): if path.is_file() and path.suffix in (".log", ".txt"): chunks.append(f"\n--- {path} ---\n{_read_text(path)}") return "".join(chunks) if chunks else "<no workspace logs found>" def _sfind_env(conf, buff_size, iteration): return { "GKFS_USE_DIRENTS_COMPRESSION": conf["compress"], "LIBGKFS_DENTRY_CACHE": conf["cache"], "LIBGKFS_DIRENTS_BUFF_SIZE": str(buff_size), "LIBGKFS_LOG": "debug", "LIBGKFS_LOG_PER_PROCESS": "ON", "MALLOC_CHECK_": "3", "MALLOC_PERTURB_": str(1 + (iteration % 254)), "SFIND_NUM_THREADS": str(conf["threads"]), } @pytest.mark.parametrize("buff_size", ["4096", "5242880"]) @pytest.mark.parametrize("conf", [ {"compress": "OFF", "cache": "OFF", "threads": 1}, {"compress": "ON", "cache": "OFF", "threads": 1}, {"compress": "OFF", "cache": "ON", "threads": 1}, {"compress": "ON", "cache": "ON", "threads": 1}, {"compress": "OFF", "cache": "OFF", "threads": 20}, {"compress": "ON", "cache": "ON", "threads": 20}, ]) def test_sfind_repeated_teardown_diagnostic(test_workspace, request, conf, buff_size): """Stress sfind until the random SIGSEGV is reproducible with logs. The observed failure exits with -11 after printing MATCHED 2000/2000, so this diagnostic repeats only the sfind phase and records whether the crash depends on compression, dentry cache, buffer size, or sfind thread count. """ repetitions = int(os.environ.get("GKFS_SFIND_DIAG_REPETITIONS", "25")) file_count = int(os.environ.get("GKFS_SFIND_DIAG_FILES", "2000")) populate_daemon = Daemon( request.config.getoption("--interface"), "rocksdb", test_workspace, env={ "GKFS_DAEMON_LOG_LEVEL": "debug", "GKFS_USE_DIRENTS_COMPRESSION": "OFF", }) populate_daemon.run() mount_dir = test_workspace.mountdir test_dir = mount_dir / "sfind_diagnostic_dir" io_client = Client(test_workspace) try: ret = io_client.mkdir(str(test_dir), 0o755) assert ret.retval == 0, f"mkdir failed: errno={ret.errno}" ret = io_client.create_n_files( str(test_dir), file_count, env={ "GKFS_USE_DIRENTS_COMPRESSION": "OFF", "LIBGKFS_DENTRY_CACHE": "OFF", "LIBGKFS_LOG": "debug", "LIBGKFS_LOG_PER_PROCESS": "ON", }) assert ret.retval == 0, f"population failed: errno={ret.errno}" assert ret.files_created == file_count finally: populate_daemon.shutdown() time.sleep(1) test_daemon = Daemon( request.config.getoption("--interface"), "rocksdb", test_workspace, env={ "GKFS_DAEMON_LOG_LEVEL": "debug", "GKFS_USE_DIRENTS_COMPRESSION": conf["compress"], }) test_daemon.run() sfind_bin = find_command("sfind", test_workspace.bindirs) assert sfind_bin, "sfind binary not found" try: shell = ShellClient(test_workspace) failures = [] for iteration in range(repetitions): env = _sfind_env(conf, buff_size, iteration) ret = shell.run( str(sfind_bin), str(test_dir), "-S", "1", "-M", str(mount_dir), timeout=SFIND_DIAG_TIMEOUT, env=env) stdout = ret.stdout.decode(errors="replace") if ret.stdout else "" stderr = ret.stderr.decode(errors="replace") if ret.stderr else "" log.info( "sfind diagnostic iteration=%s conf=%s buff_size=%s exit=%s\n" "stdout:\n%s\nstderr:\n%s", iteration, conf, buff_size, ret.exit_code, stdout, stderr) if ret.exit_code != 0 or f"MATCHED {file_count}/{file_count}" not in stdout: failures.append((iteration, ret.exit_code, stdout, stderr)) if ret.exit_code == -11: break if failures: iteration, exit_code, stdout, stderr = failures[0] pytest.fail( "sfind diagnostic reproduced failure\n" f"iteration: {iteration}\n" f"conf: {conf}\n" f"buff_size: {buff_size}\n" f"exit_code: {exit_code}\n" f"stdout:\n{stdout}\n" f"stderr:\n{stderr}\n" f"workspace logs:\n{_collect_workspace_logs(test_workspace)}") finally: test_daemon.shutdown() No newline at end of file Loading
tests/integration/directories/test_sfind_diagnostic.pydeleted 100644 → 0 +0 −147 Original line number Diff line number Diff line import logging import os import time from pathlib import Path import pytest from harness.gkfs import Client, Daemon, ShellClient, find_command log = logging.getLogger(__name__) SFIND_DIAG_TIMEOUT = 180 def _read_text(path, limit=12000): try: data = Path(path).read_text(errors="replace") except OSError as exc: return f"<could not read {path}: {exc}>" if len(data) <= limit: return data return data[-limit:] def _collect_workspace_logs(test_workspace): chunks = [] for base in (test_workspace.logdir, test_workspace.twd): if not Path(base).exists(): continue for path in sorted(Path(base).glob("**/*")): if path.is_file() and path.suffix in (".log", ".txt"): chunks.append(f"\n--- {path} ---\n{_read_text(path)}") return "".join(chunks) if chunks else "<no workspace logs found>" def _sfind_env(conf, buff_size, iteration): return { "GKFS_USE_DIRENTS_COMPRESSION": conf["compress"], "LIBGKFS_DENTRY_CACHE": conf["cache"], "LIBGKFS_DIRENTS_BUFF_SIZE": str(buff_size), "LIBGKFS_LOG": "debug", "LIBGKFS_LOG_PER_PROCESS": "ON", "MALLOC_CHECK_": "3", "MALLOC_PERTURB_": str(1 + (iteration % 254)), "SFIND_NUM_THREADS": str(conf["threads"]), } @pytest.mark.parametrize("buff_size", ["4096", "5242880"]) @pytest.mark.parametrize("conf", [ {"compress": "OFF", "cache": "OFF", "threads": 1}, {"compress": "ON", "cache": "OFF", "threads": 1}, {"compress": "OFF", "cache": "ON", "threads": 1}, {"compress": "ON", "cache": "ON", "threads": 1}, {"compress": "OFF", "cache": "OFF", "threads": 20}, {"compress": "ON", "cache": "ON", "threads": 20}, ]) def test_sfind_repeated_teardown_diagnostic(test_workspace, request, conf, buff_size): """Stress sfind until the random SIGSEGV is reproducible with logs. The observed failure exits with -11 after printing MATCHED 2000/2000, so this diagnostic repeats only the sfind phase and records whether the crash depends on compression, dentry cache, buffer size, or sfind thread count. """ repetitions = int(os.environ.get("GKFS_SFIND_DIAG_REPETITIONS", "25")) file_count = int(os.environ.get("GKFS_SFIND_DIAG_FILES", "2000")) populate_daemon = Daemon( request.config.getoption("--interface"), "rocksdb", test_workspace, env={ "GKFS_DAEMON_LOG_LEVEL": "debug", "GKFS_USE_DIRENTS_COMPRESSION": "OFF", }) populate_daemon.run() mount_dir = test_workspace.mountdir test_dir = mount_dir / "sfind_diagnostic_dir" io_client = Client(test_workspace) try: ret = io_client.mkdir(str(test_dir), 0o755) assert ret.retval == 0, f"mkdir failed: errno={ret.errno}" ret = io_client.create_n_files( str(test_dir), file_count, env={ "GKFS_USE_DIRENTS_COMPRESSION": "OFF", "LIBGKFS_DENTRY_CACHE": "OFF", "LIBGKFS_LOG": "debug", "LIBGKFS_LOG_PER_PROCESS": "ON", }) assert ret.retval == 0, f"population failed: errno={ret.errno}" assert ret.files_created == file_count finally: populate_daemon.shutdown() time.sleep(1) test_daemon = Daemon( request.config.getoption("--interface"), "rocksdb", test_workspace, env={ "GKFS_DAEMON_LOG_LEVEL": "debug", "GKFS_USE_DIRENTS_COMPRESSION": conf["compress"], }) test_daemon.run() sfind_bin = find_command("sfind", test_workspace.bindirs) assert sfind_bin, "sfind binary not found" try: shell = ShellClient(test_workspace) failures = [] for iteration in range(repetitions): env = _sfind_env(conf, buff_size, iteration) ret = shell.run( str(sfind_bin), str(test_dir), "-S", "1", "-M", str(mount_dir), timeout=SFIND_DIAG_TIMEOUT, env=env) stdout = ret.stdout.decode(errors="replace") if ret.stdout else "" stderr = ret.stderr.decode(errors="replace") if ret.stderr else "" log.info( "sfind diagnostic iteration=%s conf=%s buff_size=%s exit=%s\n" "stdout:\n%s\nstderr:\n%s", iteration, conf, buff_size, ret.exit_code, stdout, stderr) if ret.exit_code != 0 or f"MATCHED {file_count}/{file_count}" not in stdout: failures.append((iteration, ret.exit_code, stdout, stderr)) if ret.exit_code == -11: break if failures: iteration, exit_code, stdout, stderr = failures[0] pytest.fail( "sfind diagnostic reproduced failure\n" f"iteration: {iteration}\n" f"conf: {conf}\n" f"buff_size: {buff_size}\n" f"exit_code: {exit_code}\n" f"stdout:\n{stdout}\n" f"stderr:\n{stderr}\n" f"workspace logs:\n{_collect_workspace_logs(test_workspace)}") finally: test_daemon.shutdown() No newline at end of file