From 89c5fc9b068f9a08e3c6cb5fea2b45a46aaa5b57 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Thu, 20 Sep 2018 22:22:35 +0000 Subject: [PATCH] zdtm: create a few external descriptros Currently, we create only one external resource to check how it is handled by criu. It is better to create more than one. Signed-off-by: Andrei Vagin Signed-off-by: Andrei Vagin --- test/inhfd/fifo.py | 2 +- test/inhfd/pipe.py | 7 +++- test/inhfd/socket.py | 4 +- test/inhfd/tty.py | 20 ++++++++-- test/zdtm.py | 89 +++++++++++++++++++++++++++++--------------- 5 files changed, 84 insertions(+), 38 deletions(-) diff --git a/test/inhfd/fifo.py b/test/inhfd/fifo.py index bd4017ec4..64e5f8f13 100755 --- a/test/inhfd/fifo.py +++ b/test/inhfd/fifo.py @@ -28,7 +28,7 @@ def create_fds(): global id_str id_str = "file[%x:%x]" % (mnt_id, os.fstat(fd1.fileno()).st_ino) - return (fd2, fd1) + return [(fd2, fd1)] def filename(pipef): diff --git a/test/inhfd/pipe.py b/test/inhfd/pipe.py index 4635a6cc1..318dc862d 100755 --- a/test/inhfd/pipe.py +++ b/test/inhfd/pipe.py @@ -2,8 +2,11 @@ import os def create_fds(): - (fd1, fd2) = os.pipe() - return (os.fdopen(fd2, "wb"), os.fdopen(fd1, "rb")) + pipes = [] + for i in range(10): + (fd1, fd2) = os.pipe() + pipes.append((os.fdopen(fd2, "wb"), os.fdopen(fd1, "rb"))) + return pipes def filename(pipef): diff --git a/test/inhfd/socket.py b/test/inhfd/socket.py index d7e434046..feba0e0c6 100755 --- a/test/inhfd/socket.py +++ b/test/inhfd/socket.py @@ -4,7 +4,9 @@ import os def create_fds(): (sk1, sk2) = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM) - return (sk1.makefile("wb"), sk2.makefile("rb")) + (sk3, sk4) = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM) + return [(sk1.makefile("wb"), sk2.makefile("rb")), + (sk3.makefile("wb"), sk4.makefile("rb"))] def __sock_ino(sockf): diff --git a/test/inhfd/tty.py b/test/inhfd/tty.py index 519b6bcbc..ae76a96d4 100755 --- a/test/inhfd/tty.py +++ b/test/inhfd/tty.py @@ -1,16 +1,30 @@ +# vim: noet ts=8 sw=8 sts=8 import fcntl import os import pty import termios +ctl = False + + def child_prep(fd): + global ctl + if ctl: + return + ctl = True fcntl.ioctl(fd.fileno(), termios.TIOCSCTTY, 1) def create_fds(): - (fd1, fd2) = pty.openpty() - return (os.fdopen(fd2, "wb"), os.fdopen(fd1, "rb")) + ttys = [] + for i in range(10): + (fd1, fd2) = pty.openpty() + newattr = termios.tcgetattr(fd1) + newattr[3] &= ~termios.ICANON & ~termios.ECHO + termios.tcsetattr(fd1, termios.TCSADRAIN, newattr) + ttys.append((os.fdopen(fd1, "wb"), os.fdopen(fd2, "rb"))) + return ttys def filename(pipef): @@ -20,4 +34,4 @@ def filename(pipef): def dump_opts(sockf): st = os.fstat(sockf.fileno()) - return ["--external", 'tty[%x:%x]' % (st.st_rdev, st.st_dev)] + return "--external", 'tty[%x:%x]' % (st.st_rdev, st.st_dev) diff --git a/test/zdtm.py b/test/zdtm.py index 97f9da009..ea328c01f 100755 --- a/test/zdtm.py +++ b/test/zdtm.py @@ -580,28 +580,35 @@ class inhfd_test: 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 + self.__files = None + self.__peer_file_names = [] + self.__dump_opts = [] + + def __get_message(self, i): + return b"".join([random.choice(string.ascii_letters).encode() for _ in range(10)]) + b"%06d" % i def start(self): - self.__message = b"".join([random.choice(string.ascii_letters).encode() for _ in range(16)]) - (self.__my_file, peer_file) = self.__fdtyp.create_fds() + self.__files = 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") + i = 0 + for my_file, peer_file in self.__files: + msg = self.__get_message(i) + my_file.write(msg) + my_file.flush() + data = peer_file.read(len(msg)) + if data != msg: + raise test_fail_exc("FDs screwup: %r %r" % (msg, data)) + i += 1 start_pipe = os.pipe() self.__peer_pid = os.fork() if self.__peer_pid == 0: os.setsid() - getattr(self.__fdtyp, "child_prep", lambda fd: None)(peer_file) + for _, peer_file in self.__files: + getattr(self.__fdtyp, "child_prep", lambda fd: None)(peer_file) try: os.unlink(self.__name + ".out") @@ -611,29 +618,45 @@ class inhfd_test: os.dup2(fd, 1) os.dup2(fd, 2) os.close(0) - self.__my_file.close() + for my_file, _ in self.__files: + my_file.close() os.close(start_pipe[0]) os.close(start_pipe[1]) - try: - data = peer_file.read(16) - except Exception as e: - print("Unable to read a peer file: %s" % e) - sys.exit(1) + i = 0 + for _, peer_file in self.__files: + msg = self.__get_message(i) + my_file.close() + try: + data = peer_file.read(16) + except Exception as e: + print("Unable to read a peer file: %s" % e) + sys.exit(1) - if data != self.__message: - print("%r %r" % (data, self.__message)) - sys.exit(data == self.__message and 42 or 2) + if data != msg: + print("%r %r" % (data, msg)) + i += 1 + sys.exit(data == msg 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) + for _, peer_file in self.__files: + self.__peer_file_names.append(self.__fdtyp.filename(peer_file)) + self.__dump_opts += self.__fdtyp.dump_opts(peer_file) + + self.__fds = set(os.listdir("/proc/%s/fd" % self.__peer_pid)) def stop(self): - self.__my_file.write(self.__message) - self.__my_file.flush() + fds = set(os.listdir("/proc/%s/fd" % self.__peer_pid)) + if fds != self.__fds: + raise test_fail_exc("File descriptors mismatch: %s %s" % (fds, self.__fds)) + i = 0 + for my_file, _ in self.__files: + msg = self.__get_message(i) + my_file.write(msg) + my_file.flush() + i += 1 pid, status = os.waitpid(self.__peer_pid, 0) with open(self.__name + ".out") as output: print(output.read()) @@ -654,18 +677,22 @@ class inhfd_test: 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 + self.__files = None def getdopts(self): return self.__dump_opts def getropts(self): - (self.__my_file, self.__peer_file) = self.__fdtyp.create_fds() - fd = self.__peer_file.fileno() - fdflags = fcntl.fcntl(fd, fcntl.F_GETFD) & ~fcntl.FD_CLOEXEC - fcntl.fcntl(fd, fcntl.F_SETFD, fdflags) - return ["--restore-sibling", "--inherit-fd", "fd[%d]:%s" % (fd, self.__peer_file_name)] + self.__files = self.__fdtyp.create_fds() + ropts = ["--restore-sibling"] + for i in range(len(self.__files)): + my_file, peer_file = self.__files[i] + fd = peer_file.fileno() + fdflags = fcntl.fcntl(fd, fcntl.F_GETFD) & ~fcntl.FD_CLOEXEC + fcntl.fcntl(fd, fcntl.F_SETFD, fdflags) + peer_file_name = self.__peer_file_names[i] + ropts.extend(["--inherit-fd", "fd[%d]:%s" % (fd, peer_file_name)]) + return ropts def print_output(self): pass