[CRIU] [PATCHv2 2/2] test/others/leave-stopped: implement test for new --leave-stopped option

Eugene Batalov eabatalov89 at gmail.com
Mon May 2 08:46:06 PDT 2016


From: Kravchenko Dmitrii <equivalence1 at gmail.com>

This patch implements a simple autotest for new --leave-stopped CRIU
restorer option. Test creates ps tree then checkpoints it.
Then test restores ps tree with --leave-stopped option.
Then test checks that every process in restored ps tree is in
stopped state.

Signed-off-by: Kravchenko Dmitrii <equivalence1 at gmail.com>
Signed-off-by: Eugene Batalov <eabatalov89 at gmail.com>
---
 test/others/leave-stopped/.gitignore      |  3 ++
 test/others/leave-stopped/Makefile        |  7 +++++
 test/others/leave-stopped/pstree.c        | 39 +++++++++++++++++++++++++
 test/others/leave-stopped/run.sh          | 31 ++++++++++++++++++++
 test/others/leave-stopped/tree_checker.py | 47 +++++++++++++++++++++++++++++++
 5 files changed, 127 insertions(+)
 create mode 100644 test/others/leave-stopped/.gitignore
 create mode 100644 test/others/leave-stopped/Makefile
 create mode 100644 test/others/leave-stopped/pstree.c
 create mode 100755 test/others/leave-stopped/run.sh
 create mode 100755 test/others/leave-stopped/tree_checker.py

diff --git a/test/others/leave-stopped/.gitignore b/test/others/leave-stopped/.gitignore
new file mode 100644
index 0000000..f0f7d9e
--- /dev/null
+++ b/test/others/leave-stopped/.gitignore
@@ -0,0 +1,3 @@
+dump/*
+nohup.out
+pstree
diff --git a/test/others/leave-stopped/Makefile b/test/others/leave-stopped/Makefile
new file mode 100644
index 0000000..83e91cc
--- /dev/null
+++ b/test/others/leave-stopped/Makefile
@@ -0,0 +1,7 @@
+pstree: pstree.c
+	gcc -pthread -std=c99 $< -o $@
+
+clean:
+	rm -f pstree
+
+.PHONY: clean
diff --git a/test/others/leave-stopped/pstree.c b/test/others/leave-stopped/pstree.c
new file mode 100644
index 0000000..a6e437c
--- /dev/null
+++ b/test/others/leave-stopped/pstree.c
@@ -0,0 +1,39 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <pthread.h>
+
+const size_t THREADS_N = 3;
+const size_t TREE_HEIGHT = 3;
+
+static void *hang(void *arg)
+{
+	(void)arg;
+	while (1)
+		sleep(UINT_MAX);
+}
+
+static void create_threads(void)
+{
+	pthread_t thread;
+
+	for (size_t i = 1; i < THREADS_N; i++)
+		pthread_create(&thread, NULL, hang, NULL);
+}
+
+int main(void)
+{
+	/**
+	 * just building full binary tree of processes
+	 */
+	for (size_t i = 1; i < TREE_HEIGHT; i++) {
+		if (fork()) {
+			if (fork())
+				break;
+		}
+	}
+
+	create_threads();
+
+	hang(NULL);
+}
diff --git a/test/others/leave-stopped/run.sh b/test/others/leave-stopped/run.sh
new file mode 100755
index 0000000..d2f2ec6
--- /dev/null
+++ b/test/others/leave-stopped/run.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+source ../env.sh || exit 1
+
+make || { echo "Failed to build"; exit 1; }
+
+DDIR="dump"
+
+rm -f nohup.out
+rm -rf ${DDIR}
+
+mkdir ${DDIR}
+
+setsid nohup ./pstree &
+root_pid=$!
+
+${CRIU} dump -D ${DDIR} -t ${root_pid} || \
+	{ echo "Failed to dump"; kill -9 -${root_pid}; exit 1; }
+${CRIU} restore -D ${DDIR} --leave-stopped -d || \
+	{ echo "Failed to restore"; exit 1; }
+
+./tree_checker.py ${root_pid}
+
+if [ $? -eq 0 ]; then
+	echo "PASS"
+	kill -9 -${root_pid}
+else
+	echo "FAIL"
+	kill -9 -${root_pid}
+	exit 1
+fi
diff --git a/test/others/leave-stopped/tree_checker.py b/test/others/leave-stopped/tree_checker.py
new file mode 100755
index 0000000..87d45e2
--- /dev/null
+++ b/test/others/leave-stopped/tree_checker.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python2
+
+import os
+import sys
+
+
+def get_thread_status(thread_dir):
+	for line in open(os.path.join(thread_dir, "status")).readlines():
+		if line.startswith("State:"):
+			return line.split(":", 1)[1].strip().split(' ')[0]
+	return None
+
+
+def is_process_stopped(pid):
+	tasks_dir = "/proc/{}/task".format(pid)
+
+	for thread_dir in os.listdir(tasks_dir):
+		thread_status = get_thread_status(os.path.join(tasks_dir, thread_dir))
+		if not thread_status == "T":
+			return False
+
+	thread_status = get_thread_status("/proc/{}".format(pid))
+	if not thread_status == "T":
+		return False
+
+	return True
+
+
+def check_tree(root_pid):
+	if not is_process_stopped(root_pid):
+		print "Process with pid {} is not stopped.".format(root_pid)
+		return False
+
+	f_children_path = "/proc/{0}/task/{0}/children".format(root_pid)
+
+	with open(f_children_path, "r") as f_children:
+		for line in f_children:
+			for child_pid in line.strip().split(" "):
+				if not check_tree(int(child_pid)):
+					return False
+
+	return True
+
+
+if __name__ == "__main__":
+	if not check_tree(sys.argv[1]):
+		sys.exit(1)
-- 
1.9.1



More information about the CRIU mailing list