1 // Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <util/io/fd.h>
10 #include <util/io/fd_share.h>
11 
12 #include <util/unittests/check_valgrind.h>
13 #include <util/unittests/fork.h>
14 
15 #include <gtest/gtest.h>
16 #include <unistd.h>
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <cstdio>
20 
21 using namespace isc::util::io;
22 using namespace isc::util::unittests;
23 
24 namespace {
25 
26 // We test that we can transfer a pipe over other pipe
TEST(FDShare,transfer)27 TEST(FDShare, transfer) {
28 
29     if (!isc::util::unittests::runningOnValgrind()) {
30         // Get a pipe and fork
31         int pipes[2];
32         ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_STREAM, 0, pipes));
33         const pid_t sender(fork());
34         ASSERT_NE(-1, sender);
35         if (sender) { // We are in parent
36             // Close the other side of pipe, we want only writable one
37             EXPECT_NE(-1, close(pipes[0]));
38             // Get a process to check data
39             int fd(0);
40             const pid_t checker(check_output(&fd, "data", 4));
41             ASSERT_NE(-1, checker);
42             // Now, send the file descriptor, close it and close the pipe
43             EXPECT_NE(-1, send_fd(pipes[1], fd));
44             EXPECT_NE(-1, close(pipes[1]));
45             EXPECT_NE(-1, close(fd));
46             // Check both subprocesses ended well
47             EXPECT_TRUE(process_ok(sender));
48             EXPECT_TRUE(process_ok(checker));
49         } else { // We are in child. We do not use ASSERT here
50             // Close the write end, we only read
51             if (close(pipes[1])) {
52                 exit(1);
53             }
54             // Get the file descriptor
55             const int fd(recv_fd(pipes[0]));
56             if (fd == -1) {
57                 exit(1);
58             }
59             // This pipe is not needed
60             if (close(pipes[0])) {
61                 exit(1);
62             }
63             // Send "data" through the received fd, close it and be done
64             if (!write_data(fd, "data", 4) || close(fd) == -1) {
65                 exit(1);
66             }
67             exit(0);
68         }
69     }
70 }
71 
72 }
73