test/others: add tests for check() with pycriu

Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit is contained in:
Radostin Stoyanov 2025-10-26 10:00:39 +00:00 committed by Andrei Vagin
parent 567f70ce19
commit 0fa6ff3d18
9 changed files with 215 additions and 0 deletions

View file

@ -452,6 +452,7 @@ ruff:
test/inhfd/*.py \ test/inhfd/*.py \
test/others/rpc/config_file.py \ test/others/rpc/config_file.py \
test/others/action-script/check_actions.py \ test/others/action-script/check_actions.py \
test/others/pycriu/*.py \
lib/pycriu/criu.py \ lib/pycriu/criu.py \
lib/pycriu/__init__.py \ lib/pycriu/__init__.py \
lib/pycriu/images/pb2dict.py \ lib/pycriu/images/pb2dict.py \

1
test/others/pycriu/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
build/

View file

@ -0,0 +1,63 @@
.SHELLFLAGS := -eu -o pipefail -c
.ONESHELL:
CRIU ?= ../../../criu/criu
BUILD_DIR ?= build
SOCKET_NAME ?= criu_service.socket
PIDFILE_NAME ?= pidfile
SERVICE_LOG ?= service.log
PYTHON ?= python3
PIDFILE := $(BUILD_DIR)/$(PIDFILE_NAME)
CRIU_SOCKET := $(BUILD_DIR)/$(SOCKET_NAME)
STATUS_FIFO := $(BUILD_DIR)/startup.status
STATUS_FD := 200
run: start
cleanup() { $(MAKE) --no-print-directory stop || true; }
trap cleanup EXIT INT TERM
"$(PYTHON)" test_check.py
"$(PYTHON)" test_check_fail.py
"$(PYTHON)" test_check_images_dir.py
"$(PYTHON)" test_check_work_dir_fd.py
start:
mkdir -p "$(BUILD_DIR)"
if [ -s "$(PIDFILE)" ] && kill -0 "$$(cat "$(PIDFILE)")" 2>/dev/null; then
echo "Service running (PID $$(cat "$(PIDFILE)"))."
exit 0
fi
if ! command -v "$(CRIU)" >/dev/null 2>&1; then
echo "CRIU not found at $(CRIU)"
exit 1
fi
mkfifo "$(STATUS_FIFO)"
exec $(STATUS_FD)<>"$(STATUS_FIFO)"
"$(CRIU)" service \
-v4 \
-W "$(BUILD_DIR)" \
--address "$(SOCKET_NAME)" \
-d \
--pidfile "$(PIDFILE_NAME)" \
-o "$(SERVICE_LOG)" \
--status-fd "$(STATUS_FD)"
"$(PYTHON)" read.py "$(STATUS_FIFO)"
stop:
if [ ! -s "$(PIDFILE)" ]; then
echo "pidfile missing or empty"
exit 1
fi
pid=$$(cat "$(PIDFILE)")
if kill -0 "$$pid" 2>/dev/null; then
kill -9 "$$pid" || true
fi
rm -f "$(PIDFILE)" "$(CRIU_SOCKET)" "$(STATUS_FIFO)"
clean:
if [ -s "$(PIDFILE)" ] && kill -0 "$$(cat "$(PIDFILE)")" 2>/dev/null; then
kill -9 "$$(cat "$(PIDFILE)")" || true
fi
rm -rf "$(BUILD_DIR)"
.PHONY: start stop clean run

1
test/others/pycriu/read.py Symbolic link
View file

@ -0,0 +1 @@
../rpc/read.py

View file

@ -0,0 +1,29 @@
#!/usr/bin/env python3
import os
import sys
# Add ../../../lib so we can import pycriu
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
LIB_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "../../../lib"))
if LIB_DIR not in sys.path:
sys.path.insert(0, LIB_DIR)
import pycriu # noqa: E402
def main():
socket_path = os.path.join(SCRIPT_DIR, "build", "criu_service.socket")
criu = pycriu.criu()
criu.use_sk(socket_path)
try:
criu.check()
except Exception as e:
print(f"FAIL: {e}")
return 1
print("PASS")
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,32 @@
#!/usr/bin/env python3
import os
import sys
# Add ../../../lib so we can import pycriu
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
LIB_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "../../../lib"))
if LIB_DIR not in sys.path:
sys.path.insert(0, LIB_DIR)
import pycriu # noqa: E402
def main():
socket_path = os.path.join(SCRIPT_DIR, "build", "criu_service.socket")
criu = pycriu.criu()
criu.use_sk(socket_path)
# Intentionally set only log_file (no images/work dir) to ensure check() fails
criu.opts.log_file = "check.log"
try:
criu.check()
except Exception:
print("PASS")
return 0
print("FAIL: check() did not fail when log_file is set without images/work dir")
return 1
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,44 @@
#!/usr/bin/env python3
import os
import sys
# Add ../../../lib so we can import pycriu
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
LIB_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "../../../lib"))
if LIB_DIR not in sys.path:
sys.path.insert(0, LIB_DIR)
import pycriu # noqa: E402
def _log_path(images_dir, log_file):
return log_file if os.path.isabs(log_file) else os.path.join(images_dir, log_file)
def main():
build_dir = os.path.join(SCRIPT_DIR, "build")
socket_path = os.path.join(build_dir, "criu_service.socket")
criu = pycriu.criu()
criu.use_sk(socket_path)
criu.opts.images_dir = build_dir
criu.opts.log_file = "check.log"
criu.opts.log_level = 4
try:
criu.check()
except Exception as e:
lp = _log_path(build_dir, criu.opts.log_file)
msg = f"FAIL: {e} ({'see log: ' + lp if os.path.exists(lp) else 'no log found'})"
print(msg)
return 1
lp = _log_path(build_dir, criu.opts.log_file)
if not (os.path.isfile(lp) and os.path.getsize(lp) > 0):
print(f"FAIL: log file missing or empty: {lp}")
return 1
print("PASS")
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,44 @@
#!/usr/bin/env python3
import os
import sys
# Add ../../../lib so we can import pycriu
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
LIB_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "../../../lib"))
if LIB_DIR not in sys.path:
sys.path.insert(0, LIB_DIR)
import pycriu # noqa: E402
def main():
build_dir = os.path.join(SCRIPT_DIR, "build")
socket_path = os.path.join(build_dir, "criu_service.socket")
os.makedirs(build_dir, exist_ok=True)
# Open a directory FD to use as work_dir_fd (prefer O_PATH if available)
flags = getattr(os, "O_PATH", 0) or os.O_RDONLY
fd = os.open(build_dir, flags)
criu = pycriu.criu()
criu.use_sk(socket_path)
criu.opts.work_dir_fd = fd
criu.opts.log_file = "check.log"
criu.opts.log_level = 4
try:
criu.check()
except Exception as e:
print(f"FAIL: {e}")
return 1
finally:
try:
os.close(fd)
except Exception:
pass
print("PASS")
return 0
if __name__ == "__main__":
sys.exit(main())

0
test/others/rpc/read.py Normal file → Executable file
View file