15b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes/*
25b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * Copyright (C) 2013 The Android Open Source Project
35b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes *
45b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
55b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * you may not use this file except in compliance with the License.
65b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * You may obtain a copy of the License at
75b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes *
85b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
95b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes *
105b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * Unless required by applicable law or agreed to in writing, software
115b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
125b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * See the License for the specific language governing permissions and
145b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes * limitations under the License.
155b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes */
165b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes
175b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes#include <gtest/gtest.h>
185b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes
195b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes#include <errno.h>
20f04935c85e0b466f0d30d2cd4c0fa2fff62e7d6dChristopher Ferris#include <signal.h>
215b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes#include <stdlib.h>
225b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes#include <sys/select.h>
231021c05f1bef70d78cddff41b151787b8195cac9Brian Carlstrom#include <sys/types.h>
241021c05f1bef70d78cddff41b151787b8195cac9Brian Carlstrom#include <sys/wait.h>
255b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes
2633697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes#include "utils.h"
2733697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes
285b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott HughesTEST(sys_select, fd_set_smoke) {
295b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  fd_set fds;
305b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  FD_ZERO(&fds);
315b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes
325b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  for (size_t i = 0; i < 1024; ++i) {
335b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes    EXPECT_FALSE(FD_ISSET(i, &fds));
345b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  }
355b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes
365b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  FD_SET(0, &fds);
375b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  EXPECT_TRUE(FD_ISSET(0, &fds));
385b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  EXPECT_FALSE(FD_ISSET(1, &fds));
395b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  FD_SET(1, &fds);
405b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  EXPECT_TRUE(FD_ISSET(0, &fds));
415b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  EXPECT_TRUE(FD_ISSET(1, &fds));
425b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  FD_CLR(0, &fds);
435b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  EXPECT_FALSE(FD_ISSET(0, &fds));
445b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  EXPECT_TRUE(FD_ISSET(1, &fds));
455b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  FD_CLR(1, &fds);
465b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  EXPECT_FALSE(FD_ISSET(0, &fds));
475b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes  EXPECT_FALSE(FD_ISSET(1, &fds));
485b9310e502003e584bcb3a028ca3db7aa4d3f01bElliott Hughes}
4911952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
50e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris#define DELAY_MSG "1234"
51e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
52e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferrisstatic void DelayedWrite(int* pid, int* fd) {
53e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  int fds[2];
54e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_EQ(0, pipe(fds));
55e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
56e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  if ((*pid = fork()) == 0) {
57e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris    close(fds[0]);
58e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris    usleep(5000);
59e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris    EXPECT_EQ(5, write(fds[1], DELAY_MSG, sizeof(DELAY_MSG)));
60e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris    close(fds[1]);
61e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris    exit(0);
62e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  }
63e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_LT(0, *pid);
64e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  close(fds[1]);
65e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
66e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  *fd = fds[0];
67e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris}
68e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
69e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferrisstatic void DelayedWriteCleanup(int pid, int fd) {
70e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  char buf[sizeof(DELAY_MSG)];
71e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_EQ(static_cast<ssize_t>(sizeof(DELAY_MSG)), read(fd, buf, sizeof(DELAY_MSG)));
72e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_STREQ(DELAY_MSG, buf);
7333697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes
7433697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes  AssertChildExited(pid, 0);
75e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris}
76e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
7711952073af22568bba0b661f7a9d4402c443a888Elliott HughesTEST(sys_select, select_smoke) {
7811952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  fd_set r;
7911952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_ZERO(&r);
8011952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  fd_set w;
8111952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_ZERO(&w);
8211952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  fd_set e;
8311952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_ZERO(&e);
8411952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
8511952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_SET(STDIN_FILENO, &r);
8611952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_SET(STDOUT_FILENO, &w);
8711952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_SET(STDERR_FILENO, &w);
8811952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
8911952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  int max = STDERR_FILENO + 1;
9011952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
9111952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  // Invalid max fd.
9211952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  ASSERT_EQ(-1, select(-1, &r, &w, &e, NULL));
9311952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  ASSERT_EQ(EINVAL, errno);
9411952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
95dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  int num_fds = select(max, &r, &w, &e, NULL);
96e8efb96b9d6363256d6762bbd103e7ded7aa359cChristopher Ferris  // If there is data to be read on STDIN, then the number of
97e8efb96b9d6363256d6762bbd103e7ded7aa359cChristopher Ferris  // fds ready will be 3 instead of 2. Allow this case, but verify
98e8efb96b9d6363256d6762bbd103e7ded7aa359cChristopher Ferris  // every fd that is set.
99dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  ASSERT_TRUE(num_fds == 2 || num_fds == 3) << "Num fds returned " << num_fds;
100dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  ASSERT_TRUE(FD_ISSET(STDOUT_FILENO, &w));
101dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  ASSERT_TRUE(FD_ISSET(STDERR_FILENO, &w));
102dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  if (num_fds == 3) {
103dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris    ASSERT_TRUE(FD_ISSET(STDIN_FILENO, &r));
104dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  }
10511952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
10611952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  // Invalid timeout.
10711952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  timeval tv;
10811952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  tv.tv_sec = -1;
10911952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  tv.tv_usec = 0;
11011952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  ASSERT_EQ(-1, select(max, &r, &w, &e, &tv));
11111952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  ASSERT_EQ(EINVAL, errno);
11211952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
11311952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  // Valid timeout...
11411952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  tv.tv_sec = 1;
115e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  int pid, fd;
116e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  DelayedWrite(&pid, &fd);
117e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
118e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  FD_ZERO(&r);
119e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  FD_SET(fd, &r);
120e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_EQ(1, select(fd+1, &r, NULL, NULL, &tv));
121e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  // Both tv_sec and tv_nsec should have been updated.
122e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_EQ(0, tv.tv_sec);
123e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_NE(0, tv.tv_usec);
124e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
125e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  DelayedWriteCleanup(pid, fd);
12611952073af22568bba0b661f7a9d4402c443a888Elliott Hughes}
12711952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
12811952073af22568bba0b661f7a9d4402c443a888Elliott HughesTEST(sys_select, pselect_smoke) {
12911952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  sigset_t ss;
13011952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  sigemptyset(&ss);
13111952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  sigaddset(&ss, SIGPIPE);
13211952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
13311952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  fd_set r;
13411952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_ZERO(&r);
13511952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  fd_set w;
13611952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_ZERO(&w);
13711952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  fd_set e;
13811952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_ZERO(&e);
13911952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
14011952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_SET(STDIN_FILENO, &r);
14111952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_SET(STDOUT_FILENO, &w);
14211952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  FD_SET(STDERR_FILENO, &w);
14311952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
14411952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  int max = STDERR_FILENO + 1;
14511952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
14611952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  // Invalid max fd.
14711952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  ASSERT_EQ(-1, pselect(-1, &r, &w, &e, NULL, &ss));
14811952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  ASSERT_EQ(EINVAL, errno);
14911952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
150e8efb96b9d6363256d6762bbd103e7ded7aa359cChristopher Ferris  // If there is data to be read on STDIN, then the number of
151e8efb96b9d6363256d6762bbd103e7ded7aa359cChristopher Ferris  // fds ready will be 3 instead of 2. Allow this case, but verify
152e8efb96b9d6363256d6762bbd103e7ded7aa359cChristopher Ferris  // every fd that is set.
153dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  int num_fds = pselect(max, &r, &w, &e, NULL, &ss);
154dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  ASSERT_TRUE(num_fds == 2 || num_fds == 3) << "Num fds returned " << num_fds;
155dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  ASSERT_TRUE(FD_ISSET(STDOUT_FILENO, &w));
156dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  ASSERT_TRUE(FD_ISSET(STDERR_FILENO, &w));
157dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  if (num_fds == 3) {
158dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris    ASSERT_TRUE(FD_ISSET(STDIN_FILENO, &r));
159dd926b57a00d0a7d3c861897af303ea1c454fa01Christopher Ferris  }
16011952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
16111952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  // Invalid timeout.
16211952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  timespec tv;
16311952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  tv.tv_sec = -1;
16411952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  tv.tv_nsec = 0;
16511952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  ASSERT_EQ(-1, pselect(max, &r, &w, &e, &tv, &ss));
16611952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  ASSERT_EQ(EINVAL, errno);
16711952073af22568bba0b661f7a9d4402c443a888Elliott Hughes
16811952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  // Valid timeout...
16911952073af22568bba0b661f7a9d4402c443a888Elliott Hughes  tv.tv_sec = 1;
170e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  int pid, fd;
171e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  DelayedWrite(&pid, &fd);
172e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
173e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  FD_ZERO(&r);
174e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  FD_SET(fd, &r);
175e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_EQ(1, pselect(fd+1, &r, NULL, NULL, &tv, NULL));
176e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  // Neither tv_sec nor tv_nsec should have been updated.
177e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_EQ(1, tv.tv_sec);
178e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  ASSERT_EQ(0, tv.tv_nsec);
179e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris
180e3bb025b3d963e4aa412ab3eee35ca2187eb0ecaChristopher Ferris  DelayedWriteCleanup(pid, fd);
18111952073af22568bba0b661f7a9d4402c443a888Elliott Hughes}
182a6714d106b6dbab6cf994c8a4e1eff601a17d772Elliott Hughes
183a6714d106b6dbab6cf994c8a4e1eff601a17d772Elliott HughesTEST(sys_select, FD_ISSET_const) {
184a6714d106b6dbab6cf994c8a4e1eff601a17d772Elliott Hughes  const fd_set none = {};
185a6714d106b6dbab6cf994c8a4e1eff601a17d772Elliott Hughes  ASSERT_FALSE(FD_ISSET(atoi("0"), &none));
186a6714d106b6dbab6cf994c8a4e1eff601a17d772Elliott Hughes}
187