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 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 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 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 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 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 183 TEST(sys_select, FD_ISSET_const) { 184 const fd_set none = {}; 185 ASSERT_FALSE(FD_ISSET(atoi("0"), &none)); 186 } 187