mirror of
https://github.com/XTXMarkets/ternfs.git
synced 2025-12-16 08:16:47 -06:00
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).
65 lines
2.7 KiB
Python
Executable File
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)],
|
|
)
|