Files
ternfs-XTXMarkets/integration.py
Francesco Mazzoli 01f9d5addf Improve FUSE, run all tests with it
The FUSE driver, up to now, had no way to know when the user had
"explicitly" closed a file. Instead it linked the TernFS file on
flush, which could cause nasty situation. The classic example
is a fork causing the FD to a TernFS file being present in the forked
process, and then the process dying causing a spurious flush.

This commit adds a way to detect when a flush is due to a close(),
which allows us to link the file only in the cases where that happened,
which is a much better heuristic and close to what we do in the kernel
module.

This commit also contains various other improvements to make all tests
pass under FUSE. The big remaining item is changing how files are read
(they're currently read all upfront and then kept in memory).
2025-09-18 18:09:43 +01:00

65 lines
2.7 KiB
Python
Executable File

#!/usr/bin/env -S python3 -u
# Copyright 2025 XTX Markets Technologies Limited
#
# SPDX-License-Identifier: GPL-2.0-or-later
import argparse
import socket
import os
import subprocess
from common import *
parser = argparse.ArgumentParser()
parser.add_argument('--short', action='store_true')
parser.add_argument('--docker', action='store_true')
parser.add_argument('--leader-only', action='store_true', help='Run only LogsDB leader with LEADER_NO_FOLLOWERS')
parser.add_argument('--close-tracker-object', default=None, type=str, help='Run fuse driver with the given close tracker object')
args = parser.parse_args()
script_dir = os.path.dirname(os.path.realpath(__file__))
os.chdir(script_dir)
if args.docker:
build_sanitized = 'build/ubuntusanitized'
build_release = 'build/ubuntu'
build_valgrind = 'build/ubuntuvalgrind'
# setup right user -- we need it with a name because of fusermount
gid = int(os.environ['GID'])
uid = int(os.environ['UID'])
subprocess.run(['groupadd', '-g', str(gid), 'restech'])
subprocess.run(['useradd', '-u', str(uid), '-g', 'restech', 'restechprod'])
os.setgid(gid)
os.setuid(uid)
else:
build_sanitized = 'build/sanitized'
build_release = 'build/release'
build_valgrind = 'build/valgrind'
bold_print('integration tests')
short = ['-short'] if args.short else []
leader_only = ['-leader-only'] if args.leader_only else []
# -block-service-killer does not work with FUSE driver, unless we're using
# the close tracker (the duplicated FDs of the child processes confuse the
# FUSE driver).
close_tracker_object = ['-block-service-killer', '-close-tracker-object', args.close_tracker_object] if args.close_tracker_object else []
tests = [
['./go/terntests/terntests', '-binaries-dir', build_sanitized, '-verbose', '-repo-dir', '.', '-tmp-dir', '.', '-outgoing-packet-drop', '0.02'] + short + leader_only,
# valgrind is super slow, it still surfaced bugs in the past but only run a couple of tests
# and only short
['./go/terntests/terntests', '-binaries-dir', build_valgrind, '-verbose', '-repo-dir', '.', '-tmp-dir', '.', '-short', '-filter', 'history|direct|cp'] + leader_only,
]
# we need three free ports, we get them here upfront rather than in registry to reduce
# the chance of races -- if we got it from the integration tests it'll be while
# tons of things are started in another integration test
ports = []
for _ in range(len(tests)):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('', 0))
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Ensure the port is immediately reusable
ports.append(s.getsockname()[1])
wait_cmds(
[run_cmd(test + ['-registry-port', str(port)]) for test, port in zip(tests, ports)],
)