1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 #include <errno.h>
20 #include <signal.h>
21 #include <stdlib.h>
22 #include <sys/select.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 
26 #include "utils.h"
27 
TEST(sys_select,fd_set_smoke)28 TEST(sys_select, fd_set_smoke) {
29   fd_set fds;
30   FD_ZERO(&fds);
31 
32   for (size_t i = 0; i < 1024; ++i) {
33     EXPECT_FALSE(FD_ISSET(i, &fds));
34   }
35 
36   FD_SET(0, &fds);
37   EXPECT_TRUE(FD_ISSET(0, &fds));
38   EXPECT_FALSE(FD_ISSET(1, &fds));
39   FD_SET(1, &fds);
40   EXPECT_TRUE(FD_ISSET(0, &fds));
41   EXPECT_TRUE(FD_ISSET(1, &fds));
42   FD_CLR(0, &fds);
43   EXPECT_FALSE(FD_ISSET(0, &fds));
44   EXPECT_TRUE(FD_ISSET(1, &fds));
45   FD_CLR(1, &fds);
46   EXPECT_FALSE(FD_ISSET(0, &fds));
47   EXPECT_FALSE(FD_ISSET(1, &fds));
48 }
49 
50 #define DELAY_MSG "1234"
51 
DelayedWrite(int * pid,int * fd)52 static void DelayedWrite(int* pid, int* fd) {
53   int fds[2];
54   ASSERT_EQ(0, pipe(fds));
55 
56   if ((*pid = fork()) == 0) {
57     close(fds[0]);
58     usleep(5000);
59     EXPECT_EQ(5, write(fds[1], DELAY_MSG, sizeof(DELAY_MSG)));
60     close(fds[1]);
61     exit(0);
62   }
63   ASSERT_LT(0, *pid);
64   close(fds[1]);
65 
66   *fd = fds[0];
67 }
68 
DelayedWriteCleanup(int pid,int fd)69 static void DelayedWriteCleanup(int pid, int fd) {
70   char buf[sizeof(DELAY_MSG)];
71   ASSERT_EQ(static_cast<ssize_t>(sizeof(DELAY_MSG)), read(fd, buf, sizeof(DELAY_MSG)));
72   ASSERT_STREQ(DELAY_MSG, buf);
73 
74   AssertChildExited(pid, 0);
75 }
76 
TEST(sys_select,select_smoke)77 TEST(sys_select, select_smoke) {
78   fd_set r;
79   FD_ZERO(&r);
80   fd_set w;
81   FD_ZERO(&w);
82   fd_set e;
83   FD_ZERO(&e);
84 
85   FD_SET(STDIN_FILENO, &r);
86   FD_SET(STDOUT_FILENO, &w);
87   FD_SET(STDERR_FILENO, &w);
88 
89   int max = STDERR_FILENO + 1;
90 
91   // Invalid max fd.
92   ASSERT_EQ(-1, select(-1, &r, &w, &e, NULL));
93   ASSERT_EQ(EINVAL, errno);
94 
95   int num_fds = select(max, &r, &w, &e, NULL);
96   // If there is data to be read on STDIN, then the number of
97   // fds ready will be 3 instead of 2. Allow this case, but verify
98   // every fd that is set.
99   ASSERT_TRUE(num_fds == 2 || num_fds == 3) << "Num fds returned " << num_fds;
100   ASSERT_TRUE(FD_ISSET(STDOUT_FILENO, &w));
101   ASSERT_TRUE(FD_ISSET(STDERR_FILENO, &w));
102   if (num_fds == 3) {
103     ASSERT_TRUE(FD_ISSET(STDIN_FILENO, &r));
104   }
105 
106   // Invalid timeout.
107   timeval tv;
108   tv.tv_sec = -1;
109   tv.tv_usec = 0;
110   ASSERT_EQ(-1, select(max, &r, &w, &e, &tv));
111   ASSERT_EQ(EINVAL, errno);
112 
113   // Valid timeout...
114   tv.tv_sec = 1;
115   int pid, fd;
116   DelayedWrite(&pid, &fd);
117 
118   FD_ZERO(&r);
119   FD_SET(fd, &r);
120   ASSERT_EQ(1, select(fd+1, &r, NULL, NULL, &tv));
121   // Both tv_sec and tv_nsec should have been updated.
122   ASSERT_EQ(0, tv.tv_sec);
123   ASSERT_NE(0, tv.tv_usec);
124 
125   DelayedWriteCleanup(pid, fd);
126 }
127 
TEST(sys_select,pselect_smoke)128 TEST(sys_select, pselect_smoke) {
129   sigset_t ss;
130   sigemptyset(&ss);
131   sigaddset(&ss, SIGPIPE);
132 
133   fd_set r;
134   FD_ZERO(&r);
135   fd_set w;
136   FD_ZERO(&w);
137   fd_set e;
138   FD_ZERO(&e);
139 
140   FD_SET(STDIN_FILENO, &r);
141   FD_SET(STDOUT_FILENO, &w);
142   FD_SET(STDERR_FILENO, &w);
143 
144   int max = STDERR_FILENO + 1;
145 
146   // Invalid max fd.
147   ASSERT_EQ(-1, pselect(-1, &r, &w, &e, NULL, &ss));
148   ASSERT_EQ(EINVAL, errno);
149 
150   // If there is data to be read on STDIN, then the number of
151   // fds ready will be 3 instead of 2. Allow this case, but verify
152   // every fd that is set.
153   int num_fds = pselect(max, &r, &w, &e, NULL, &ss);
154   ASSERT_TRUE(num_fds == 2 || num_fds == 3) << "Num fds returned " << num_fds;
155   ASSERT_TRUE(FD_ISSET(STDOUT_FILENO, &w));
156   ASSERT_TRUE(FD_ISSET(STDERR_FILENO, &w));
157   if (num_fds == 3) {
158     ASSERT_TRUE(FD_ISSET(STDIN_FILENO, &r));
159   }
160 
161   // Invalid timeout.
162   timespec tv;
163   tv.tv_sec = -1;
164   tv.tv_nsec = 0;
165   ASSERT_EQ(-1, pselect(max, &r, &w, &e, &tv, &ss));
166   ASSERT_EQ(EINVAL, errno);
167 
168   // Valid timeout...
169   tv.tv_sec = 1;
170   int pid, fd;
171   DelayedWrite(&pid, &fd);
172 
173   FD_ZERO(&r);
174   FD_SET(fd, &r);
175   ASSERT_EQ(1, pselect(fd+1, &r, NULL, NULL, &tv, NULL));
176   // Neither tv_sec nor tv_nsec should have been updated.
177   ASSERT_EQ(1, tv.tv_sec);
178   ASSERT_EQ(0, tv.tv_nsec);
179 
180   DelayedWriteCleanup(pid, fd);
181 }
182