mirror of
https://github.com/XTXMarkets/ternfs.git
synced 2026-01-06 02:49:45 -06:00
129 lines
4.9 KiB
Python
Executable File
129 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
import atexit
|
|
import shlex
|
|
import socket
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--functional', action='store_true')
|
|
parser.add_argument('--integration', action='store_true')
|
|
parser.add_argument('--short', action='store_true')
|
|
parser.add_argument('--quiet', action='store_true')
|
|
parser.add_argument('--kmod', default=None, type=str, help='Run the kmod tests with the provided base image')
|
|
parser.add_argument('--no-build', action='store_true')
|
|
args = parser.parse_args()
|
|
|
|
if sys.stdout.isatty():
|
|
def bold_print(fmt, *args, **kwargs):
|
|
print('\033[1m' + fmt + '\033[0m', *args, **kwargs)
|
|
else:
|
|
def bold_print(*args, **kwargs):
|
|
print(*args, **kwargs)
|
|
|
|
os.environ['PATH'] = f'/opt/go1.18.4/bin:{os.environ["PATH"]}'
|
|
|
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
|
os.chdir(script_dir)
|
|
|
|
# all running pids
|
|
processes = []
|
|
|
|
def process_status(p, fmt, *args, **kwargs):
|
|
print(repr(shlex.join(p.args)) + ': ' + fmt, *args, **kwargs)
|
|
|
|
def terminate_all_processes():
|
|
for process in processes:
|
|
if process.poll() is None: # not done yet
|
|
process_status(process, 'terminating')
|
|
process.terminate()
|
|
try:
|
|
process.wait(timeout=10) # wait at most 10 seconds
|
|
except subprocess.TimeoutExpired:
|
|
print('Process not terminating after 10 seconds, killing it')
|
|
process.kill()
|
|
|
|
atexit.register(terminate_all_processes)
|
|
|
|
def run_cmd(*args, **kwargs):
|
|
p = subprocess.Popen(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs)
|
|
process_status(p, 'start')
|
|
processes.append(p)
|
|
return p
|
|
|
|
def wait_cmd(p, timeout=None):
|
|
try:
|
|
output, _ = p.communicate(timeout=timeout)
|
|
except subprocess.TimeoutExpired:
|
|
return False
|
|
process_status(p, f'finished ({p.returncode})')
|
|
if p.returncode != 0 or not args.quiet:
|
|
if len(output) > 0:
|
|
process_status(p, 'output:')
|
|
sys.stdout.flush()
|
|
sys.stdout.buffer.write(output)
|
|
sys.stdout.flush()
|
|
else:
|
|
process_status(p, 'no output')
|
|
if p.returncode != 0:
|
|
sys.exit(p.returncode)
|
|
return True
|
|
|
|
def wait_cmds(ps):
|
|
done = [False]*len(ps)
|
|
while not all(done):
|
|
for i, p in enumerate(ps):
|
|
if done[i]:
|
|
continue
|
|
done[i] = wait_cmd(p, timeout=0.1)
|
|
|
|
if not args.no_build:
|
|
bold_print('building')
|
|
for r in ['alpine', 'sanitized', 'valgrind']:
|
|
wait_cmd(run_cmd(['./build.sh', r]))
|
|
wait_cmd(run_cmd(['make', 'bincode_tests'], cwd='kmod'))
|
|
|
|
if args.functional:
|
|
bold_print('functional tests')
|
|
wait_cmds(
|
|
[run_cmd(['./cpp/tests.sh']), run_cmd(['./bincode_tests'], cwd='kmod'), run_cmd(['go', 'test', './...'], cwd='go')],
|
|
)
|
|
|
|
if args.integration:
|
|
if args.short:
|
|
fuse_tests = 'history|direct|mounted|cp'
|
|
else:
|
|
# The mounted ones are long, and we don't rely on the FUSE driver critically,
|
|
# but we still want to test it in the short run.
|
|
fuse_tests = 'history|direct|cp'
|
|
|
|
bold_print('integration tests')
|
|
short = ['-short'] if args.short else []
|
|
tests = [
|
|
['./go/eggstests/eggstests', '-build-type', 'sanitized', '-binaries-dir', 'build/sanitized', '-verbose', '-repo-dir', '.', '-tmp-dir', '.', '-filter', fuse_tests, '-outgoing-packet-drop', '0.02'] + short,
|
|
# TODO explanation on why -block-service-killer does not work with all the tests (the duplicated FDs
|
|
# of the child processes confuse the FUSE driver)
|
|
['./go/eggstests/eggstests', '-build-type', 'alpine', '-binaries-dir', 'build/alpine', '-preserve-data-dir', '-verbose', '-block-service-killer', '-filter', 'direct', '-repo-dir', '.', '-tmp-dir', '.'] + short,
|
|
]
|
|
if not args.short:
|
|
# valgrind is super slow, it still surfaced bugs in the past but run the short
|
|
# versions only in the long tests.
|
|
tests.append(['./go/eggstests/eggstests', '-build-type', 'valgrind', '-binaries-dir', 'build/valgrind', '-verbose', '-repo-dir', '.', '-tmp-dir', '.', '-short', '-filter', fuse_tests])
|
|
# we need three free ports, we get them here upfront rather than in shuckle 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 + ['-shuckle-port', str(port)]) for test, port in zip(tests, ports)],
|
|
)
|
|
|
|
if args.kmod:
|
|
bold_print('kmod tests')
|
|
wait_cmd(run_cmd(['./kmod/ci.sh', args.kmod] + (['-short'] if args.short else []))) |