[CRIU] [PATCH 2/2] zdtm.py: Add inhfd tests for --inherit-fd option

Pavel Emelyanov xemul at parallels.com
Mon Oct 12 11:54:33 PDT 2015


This option cannot be tested using classic zdtm tests as it implies
some data created before restore and passed through criu restore down
to the restored process (descriptor in our case).

So add inhfd_test class that creates such.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 test/inhfd.desc           |  1 +
 test/inhfd/pipe.py        | 31 +++++++++++++++++
 test/inhfd/pipe.py.desc   |  1 +
 test/inhfd/socket.py      | 15 +++++++++
 test/inhfd/socket.py.desc |  1 +
 test/zdtm.py              | 85 ++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 test/inhfd.desc
 create mode 100755 test/inhfd/pipe.py
 create mode 100644 test/inhfd/pipe.py.desc
 create mode 100755 test/inhfd/socket.py
 create mode 100644 test/inhfd/socket.py.desc

diff --git a/test/inhfd.desc b/test/inhfd.desc
new file mode 100644
index 0000000..e44278a
--- /dev/null
+++ b/test/inhfd.desc
@@ -0,0 +1 @@
+{ 'dir': 'inhfd/', 'exclude': [ ] }
diff --git a/test/inhfd/pipe.py b/test/inhfd/pipe.py
new file mode 100755
index 0000000..b355af8
--- /dev/null
+++ b/test/inhfd/pipe.py
@@ -0,0 +1,31 @@
+import os
+
+class pipef:
+	def __init__(self, fd):
+		self.__fd = fd
+
+	def read(self, blen):
+		return os.read(self.__fd, blen)
+
+	def write(self, msg):
+		return os.write(self.__fd, msg)
+
+	def flush(self):
+		pass
+
+	def close(self):
+		os.close(self.__fd)
+		self.__fd = -1
+
+	def fileno(self):
+		return self.__fd
+
+def create_fds():
+	(fd1, fd2) = os.pipe()
+	return (pipef(fd2), pipef(fd1))
+
+def filename(pipef):
+	return 'pipe:[%d]' % os.fstat(pipef.fileno()).st_ino
+
+def dump_opts(sockf):
+	return [ ]
diff --git a/test/inhfd/pipe.py.desc b/test/inhfd/pipe.py.desc
new file mode 100644
index 0000000..10666c8
--- /dev/null
+++ b/test/inhfd/pipe.py.desc
@@ -0,0 +1 @@
+{ 'flavor': 'h' }
diff --git a/test/inhfd/socket.py b/test/inhfd/socket.py
new file mode 100755
index 0000000..9b88da0
--- /dev/null
+++ b/test/inhfd/socket.py
@@ -0,0 +1,15 @@
+import socket
+import os
+
+def create_fds():
+	(sk1, sk2) = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
+	return (sk1.makefile("w"), sk2.makefile("r"))
+
+def __sock_ino(sockf):
+	return os.fstat(sockf.fileno()).st_ino
+
+def filename(sockf):
+	return 'socket:[%d]' % __sock_ino(sockf)
+
+def dump_opts(sockf):
+	return ['--ext-unix-sk=%d' % __sock_ino(sockf)]
diff --git a/test/inhfd/socket.py.desc b/test/inhfd/socket.py.desc
new file mode 100644
index 0000000..10666c8
--- /dev/null
+++ b/test/inhfd/socket.py.desc
@@ -0,0 +1 @@
+{ 'flavor': 'h' }
diff --git a/test/zdtm.py b/test/zdtm.py
index bcbd537..a27f592 100755
--- a/test/zdtm.py
+++ b/test/zdtm.py
@@ -12,6 +12,10 @@ import signal
 import atexit
 import sys
 import linecache
+import random
+import string
+import imp
+import socket
 
 prev_line = None
 def traceit(f, e, a):
@@ -279,7 +283,86 @@ class zdtm_test:
 			print " <<< " + "=" * 32
 
 
-test_classes = { 'zdtm': zdtm_test }
+class inhfd_test:
+	def __init__(self, name, desc, flavor):
+		self.__name = os.path.basename(name)
+		print "Load %s" % name
+		self.__fdtyp = imp.load_source(self.__name, name)
+		self.__my_file = None
+		self.__peer_pid = 0
+		self.__peer_file = None
+		self.__peer_file_name = None
+		self.__dump_opts = None
+
+	def start(self):
+		self.__message = "".join([random.choice(string.ascii_letters) for _ in range(16)])
+		(self.__my_file, peer_file) = self.__fdtyp.create_fds()
+
+		# Check FDs returned for inter-connection
+		self.__my_file.write(self.__message)
+		self.__my_file.flush()
+		if peer_file.read(16) != self.__message:
+			raise test_fail_exc("FDs screwup")
+
+		start_pipe = os.pipe()
+		self.__peer_pid = os.fork()
+		if self.__peer_pid == 0:
+			os.setsid()
+			os.close(0)
+			os.close(1)
+			os.close(2)
+		 	self.__my_file.close()
+			os.close(start_pipe[0])
+			os.close(start_pipe[1])
+			try:
+				data = peer_file.read(16)
+			except:
+				sys.exit(1)
+
+			sys.exit(data == self.__message and 42 or 2)
+
+		os.close(start_pipe[1])
+		os.read(start_pipe[0], 12)
+		os.close(start_pipe[0])
+
+		self.__peer_file_name = self.__fdtyp.filename(peer_file)
+		self.__dump_opts = self.__fdtyp.dump_opts(peer_file)
+
+	def stop(self):
+		self.__my_file.write(self.__message)
+		self.__my_file.flush()
+		pid, status = os.waitpid(self.__peer_pid, 0)
+		if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 42:
+			raise test_fail_exc("test failed with %d" % status)
+
+	def kill(self):
+		if self.__peer_pid:
+			os.kill(self.__peer_pid, signal.SIGKILL)
+
+	def getname(self):
+		return self.__name
+
+	def getpid(self):
+		return "%s" % self.__peer_pid
+
+	def gone(self, force = True):
+		os.waitpid(self.__peer_pid, 0)
+		wait_pid_die(self.__peer_pid, self.__name)
+		self.__my_file = None
+		self.__peer_file = None
+
+	def getdopts(self):
+		return self.__dump_opts
+
+	def getropts(self):
+		(self.__my_file, self.__peer_file) = self.__fdtyp.create_fds()
+		return ["--restore-sibling", "--inherit-fd", "fd[%d]:%s" % (self.__peer_file.fileno(), self.__peer_file_name)]
+
+	def print_output(self):
+		pass
+
+
+test_classes = { 'zdtm': zdtm_test, 'inhfd': inhfd_test }
 
 #
 # CRIU when launched using CLI
-- 
1.9.3




More information about the CRIU mailing list