1 /*
2 * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /*
20 * Check that select() timeouts correctly.
21 */
22 #include <unistd.h>
23 #include <errno.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <fcntl.h>
27
28 #include "test.h"
29 #include "safe_macros.h"
30
31 char *TCID = "select04";
32 int TST_TOTAL = 1;
33
34 static char *opt_sleep_us;
35
36 static option_t opts[] = {
37 {"s:", NULL, &opt_sleep_us},
38 {NULL, NULL, NULL},
39 };
40
41 static void help(void);
42 static void setup(void);
43 static void cleanup(void);
44
45 static int fds[2];
46
main(int ac,char ** av)47 int main(int ac, char **av)
48 {
49 int lc, treshold;
50 long long elapsed_us, sleep_us = 100000;
51 struct timeval timeout;
52 fd_set sfds;
53
54 tst_parse_opts(ac, av, opts, help);
55
56 if (opt_sleep_us) {
57 sleep_us = atoll(opt_sleep_us);
58
59 if (sleep_us == 0) {
60 tst_brkm(TBROK, NULL, "Invalid timeout '%s'",
61 opt_sleep_us);
62 }
63 }
64
65 treshold = sleep_us / 100 + 20000;
66
67 setup();
68
69 FD_ZERO(&sfds);
70
71 for (lc = 0; TEST_LOOPING(lc); lc++) {
72 FD_SET(fds[0], &sfds);
73 timeout = tst_us_to_timeval(sleep_us);
74
75 tst_timer_start(CLOCK_MONOTONIC);
76 TEST(select(1, &sfds, NULL, NULL, &timeout));
77 tst_timer_stop();
78
79 if (TEST_RETURN != 0) {
80 tst_resm(TFAIL, "select() haven't timeouted ret=%li",
81 TEST_RETURN);
82 continue;
83 }
84
85 elapsed_us = tst_timer_elapsed_us();
86
87 if (elapsed_us < sleep_us) {
88 tst_resm(TFAIL,
89 "select() woken up too early %llius, expected %llius",
90 elapsed_us, sleep_us);
91 continue;
92 }
93
94 if (elapsed_us - sleep_us > treshold) {
95 tst_resm(TFAIL,
96 "select() slept too long %llius, expected %llius, threshold %i",
97 elapsed_us, sleep_us, treshold);
98 continue;
99 }
100
101 tst_resm(TPASS, "select() slept %llius, expected %llius, treshold %i",
102 elapsed_us, sleep_us, treshold);
103 }
104
105 cleanup();
106 tst_exit();
107 }
108
setup(void)109 static void setup(void)
110 {
111 tst_timer_check(CLOCK_MONOTONIC);
112
113 SAFE_PIPE(NULL, fds);
114 }
115
cleanup(void)116 static void cleanup(void)
117 {
118 if (close(fds[0]))
119 tst_resm(TWARN | TERRNO, "close(fds[0]) failed");
120
121 if (close(fds[1]))
122 tst_resm(TWARN | TERRNO, "close(fds[1]) failed");
123 }
124
help(void)125 static void help(void)
126 {
127 printf(" -s select() timeout lenght in us\n");
128 }
129