1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <gtest/gtest.h>
6 #include <string>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include <unistd.h>
10 #include <vector>
11
12 #include "cras_util.h"
13
14 namespace {
15
16 static std::vector<struct timespec> time_now;
17
TEST(Util,SendRecvTwoFileDescriptors)18 TEST(Util, SendRecvTwoFileDescriptors) {
19 int fd[2];
20 int fd2[2];
21 int send_fds[2];
22 int sock[2];
23 char buf[256] = {0};
24 int new_fds[2];
25 char msg[] = "multi-fd";
26 unsigned int num_fds = 2;
27
28 /* Create a pipe and a pair of sockets. Then send the write end of
29 * the pipe (fd[1]) through the socket, and receive it as
30 * new_fd */
31 ASSERT_EQ(0, pipe(fd));
32 ASSERT_EQ(0, pipe(fd2));
33 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
34
35 send_fds[0] = fd[1];
36 send_fds[1] = fd2[1];
37 ASSERT_GE(cras_send_with_fds(sock[0], msg, strlen(msg), send_fds, num_fds),
38 0);
39 ASSERT_GE(cras_recv_with_fds(sock[1], buf, strlen(msg), new_fds, &num_fds),
40 0);
41 ASSERT_STREQ(msg, buf);
42 ASSERT_EQ(2, num_fds);
43 ASSERT_NE(-1, new_fds[0]);
44 ASSERT_NE(-1, new_fds[1]);
45
46 close(sock[0]);
47 close(sock[1]);
48 close(fd[1]);
49 close(fd2[1]);
50
51 /* Send a character to the new_fd, and receive it from the read end
52 * of the pipe (fd[0]) */
53 ASSERT_EQ(1, write(new_fds[0], "a", 1));
54 ASSERT_EQ(1, read(fd[0], buf, 1));
55 ASSERT_EQ('a', buf[0]);
56 ASSERT_EQ(1, write(new_fds[1], "b", 1));
57 ASSERT_EQ(1, read(fd2[0], buf, 1));
58 ASSERT_EQ('b', buf[0]);
59
60 close(fd[0]);
61 close(fd2[0]);
62 close(new_fds[0]);
63 close(new_fds[1]);
64 }
65
TEST(Util,SendOneRecvTwoFileDescriptors)66 TEST(Util, SendOneRecvTwoFileDescriptors) {
67 int fd[2];
68 int sock[2];
69 char buf[256] = {0};
70 int new_fds[2];
71 char msg[] = "multi-fd";
72 unsigned int num_fds = 2;
73
74 /* Create a pipe and a pair of sockets. Then send the write end of
75 * the pipe (fd[1]) through the socket, and receive it as
76 * new_fd */
77 ASSERT_EQ(0, pipe(fd));
78 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
79
80 ASSERT_GE(cras_send_with_fds(sock[0], msg, strlen(msg), &fd[1], 1), 0);
81 ASSERT_GE(cras_recv_with_fds(sock[1], buf, strlen(msg), new_fds, &num_fds),
82 0);
83 ASSERT_STREQ(msg, buf);
84 ASSERT_EQ(1, num_fds);
85 ASSERT_NE(-1, new_fds[0]);
86 ASSERT_EQ(-1, new_fds[1]);
87
88 close(sock[0]);
89 close(sock[1]);
90 close(fd[1]);
91
92 /* Send a character to the new_fd, and receive it from the read end
93 * of the pipe (fd[0]) */
94 ASSERT_EQ(1, write(new_fds[0], "a", 1));
95 ASSERT_EQ(1, read(fd[0], buf, 1));
96 ASSERT_EQ('a', buf[0]);
97
98 close(fd[0]);
99 close(new_fds[0]);
100 close(new_fds[1]);
101 }
102
TEST(Util,SendRecvFileDescriptor)103 TEST(Util, SendRecvFileDescriptor) {
104 int fd[2];
105 int sock[2];
106 char buf[256] = {0};
107 int new_fd;
108 char msg[] = "hello";
109 unsigned int num_fds = 1;
110
111 /* Create a pipe and a pair of sockets. Then send the write end of
112 * the pipe (fd[1]) through the socket, and receive it as
113 * new_fd */
114 ASSERT_EQ(0, pipe(fd));
115 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
116
117 ASSERT_EQ(5, cras_send_with_fds(sock[0], msg, strlen(msg), &fd[1], num_fds));
118 ASSERT_EQ(5,
119 cras_recv_with_fds(sock[1], buf, strlen(msg), &new_fd, &num_fds));
120 ASSERT_STREQ(msg, buf);
121 ASSERT_EQ(1, num_fds);
122
123 close(sock[0]);
124 close(sock[1]);
125 close(fd[1]);
126
127 /* Send a character to the new_fd, and receive it from the read end
128 * of the pipe (fd[0]) */
129 ASSERT_EQ(1, write(new_fd, "a", 1));
130 ASSERT_EQ(1, read(fd[0], buf, 1));
131 ASSERT_EQ('a', buf[0]);
132
133 close(fd[0]);
134 close(new_fd);
135 }
136
TEST(Util,SendRecvNoDescriptors)137 TEST(Util, SendRecvNoDescriptors) {
138 char buf[256] = {0};
139 char msg[] = "no descriptors";
140 unsigned int num_fds = 0;
141 int sock[2];
142
143 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
144
145 ASSERT_GE(cras_send_with_fds(sock[0], msg, strlen(msg), NULL, num_fds), 0);
146 ASSERT_GE(cras_recv_with_fds(sock[1], buf, strlen(msg), NULL, &num_fds), 0);
147 ASSERT_STREQ(msg, buf);
148 ASSERT_EQ(0, num_fds);
149
150 close(sock[0]);
151 close(sock[1]);
152 }
153
TEST(Util,TimevalAfter)154 TEST(Util, TimevalAfter) {
155 struct timeval t0, t1;
156 t0.tv_sec = 0;
157 t0.tv_usec = 0;
158 t1.tv_sec = 0;
159 t1.tv_usec = 0;
160 ASSERT_FALSE(timeval_after(&t0, &t1));
161 ASSERT_FALSE(timeval_after(&t1, &t0));
162 t0.tv_usec = 1;
163 ASSERT_TRUE(timeval_after(&t0, &t1));
164 ASSERT_FALSE(timeval_after(&t1, &t0));
165 t1.tv_sec = 1;
166 ASSERT_FALSE(timeval_after(&t0, &t1));
167 ASSERT_TRUE(timeval_after(&t1, &t0));
168 }
169
TEST(Util,FramesToTime)170 TEST(Util, FramesToTime) {
171 struct timespec t;
172
173 cras_frames_to_time(24000, 48000, &t);
174 EXPECT_EQ(0, t.tv_sec);
175 EXPECT_EQ(500000000, t.tv_nsec);
176
177 cras_frames_to_time(48000, 48000, &t);
178 EXPECT_EQ(1, t.tv_sec);
179 EXPECT_EQ(0, t.tv_nsec);
180
181 cras_frames_to_time(60000, 48000, &t);
182 EXPECT_EQ(1, t.tv_sec);
183 EXPECT_EQ(250000000, t.tv_nsec);
184
185 cras_frames_to_time(191999, 192000, &t);
186 EXPECT_EQ(0, t.tv_sec);
187 EXPECT_EQ(999994791, t.tv_nsec);
188 }
189
TEST(Util,TimeToFrames)190 TEST(Util, TimeToFrames) {
191 struct timespec t;
192 unsigned int frames;
193
194 t.tv_sec = 0;
195 t.tv_nsec = 500000000;
196 frames = cras_time_to_frames(&t, 48000);
197 EXPECT_EQ(24000, frames);
198
199 t.tv_sec = 1;
200 t.tv_nsec = 500000000;
201 frames = cras_time_to_frames(&t, 48000);
202 EXPECT_EQ(72000, frames);
203
204 t.tv_sec = 0;
205 t.tv_nsec = 0;
206 frames = cras_time_to_frames(&t, 48000);
207 EXPECT_EQ(0, frames);
208 }
209
TEST(Util,FramesToMs)210 TEST(Util, FramesToMs) {
211
212 EXPECT_EQ(500, cras_frames_to_ms(24000, 48000));
213 EXPECT_EQ(0, cras_frames_to_ms(1, 48000));
214 EXPECT_EQ(10, cras_frames_to_ms(480, 48000));
215 EXPECT_EQ(10, cras_frames_to_ms(488, 48000));
216 EXPECT_EQ(50, cras_frames_to_ms(800, 16000));
217 }
218
TEST(Util,TimespecToMs)219 TEST(Util, TimespecToMs) {
220 struct timespec ts;
221
222 ts.tv_sec = 0;
223 ts.tv_nsec = 500000000;
224 EXPECT_EQ(500, timespec_to_ms(&ts));
225
226 ts.tv_sec = 0;
227 ts.tv_nsec = 0;
228 EXPECT_EQ(0, timespec_to_ms(&ts));
229
230 ts.tv_sec = 0;
231 ts.tv_nsec = 2;
232 EXPECT_EQ(1, timespec_to_ms(&ts));
233
234 ts.tv_sec = 0;
235 ts.tv_nsec = 10000000;
236 EXPECT_EQ(10, timespec_to_ms(&ts));
237
238 ts.tv_sec = 1;
239 ts.tv_nsec = 0;
240 EXPECT_EQ(1000, timespec_to_ms(&ts));
241
242 ts.tv_sec = 1;
243 ts.tv_nsec = 1;
244 EXPECT_EQ(1001, timespec_to_ms(&ts));
245 }
246
TEST(Util,FramesSinceTime)247 TEST(Util, FramesSinceTime) {
248 struct timespec t, tn;
249 unsigned int frames;
250
251 t.tv_sec = 0;
252 t.tv_nsec = 500000000;
253
254 tn.tv_sec = 2;
255 tn.tv_nsec = 0;
256 time_now.push_back(tn);
257 frames = cras_frames_since_time(&t, 48000);
258 EXPECT_EQ(72000, frames);
259
260 tn.tv_sec = 0;
261 time_now.push_back(tn);
262 frames = cras_frames_since_time(&t, 48000);
263 EXPECT_EQ(0, frames);
264 }
265
266 // Test cras_poll().
TEST(Util,CrasPoll)267 TEST(Util, CrasPoll) {
268 int pipe_fds[2];
269 struct pollfd poll_fd;
270 std::string output;
271 struct timespec timeout;
272 char buf[256];
273
274 ASSERT_EQ(0, pipe(pipe_fds));
275 poll_fd.fd = pipe_fds[0];
276 poll_fd.events = POLLIN;
277 ASSERT_NE(0, poll_fd.fd >= 0);
278
279 // Simple poll.
280 output = "Hello";
281 EXPECT_EQ(output.size() + 1,
282 write(pipe_fds[1], output.c_str(), output.size() + 1));
283 EXPECT_EQ(1, cras_poll(&poll_fd, 1, NULL, NULL));
284 ASSERT_EQ(static_cast<ssize_t>(output.size() + 1),
285 read(pipe_fds[0], buf, sizeof(buf)));
286 EXPECT_EQ(0, strcmp(output.c_str(), buf));
287
288 // Negative time.
289 timeout.tv_sec = 0;
290 timeout.tv_nsec = -10000000;
291 EXPECT_EQ(-ETIMEDOUT, cras_poll(&poll_fd, 1, &timeout, NULL));
292 timeout.tv_sec = -1;
293 timeout.tv_nsec = 10000000;
294 EXPECT_EQ(-ETIMEDOUT, cras_poll(&poll_fd, 1, &timeout, NULL));
295
296 // Timeout.
297 timeout.tv_sec = 0;
298 timeout.tv_nsec = 0;
299 time_now.push_back(timeout);
300 timeout.tv_nsec = 1100000;
301 time_now.push_back(timeout);
302 timeout.tv_nsec = 1000000;
303 EXPECT_EQ(-ETIMEDOUT, cras_poll(&poll_fd, 1, &timeout, NULL));
304 EXPECT_EQ(timeout.tv_nsec, -100000);
305
306 EXPECT_EQ(0, close(pipe_fds[0]));
307 EXPECT_EQ(0, close(pipe_fds[1]));
308 }
309
310 /* Stubs */
311 extern "C" {
312
clock_gettime(clockid_t clk_id,struct timespec * tp)313 int clock_gettime(clockid_t clk_id, struct timespec *tp) {
314 std::vector<struct timespec>::iterator i = time_now.begin();
315 if (i != time_now.end()) {
316 *tp = *i;
317 time_now.erase(i);
318 }
319 else
320 memset(tp, 0, sizeof(*tp));
321 return 0;
322 }
323
324 } // extern "C"
325
326 } // namespace
327
main(int argc,char ** argv)328 int main(int argc, char **argv) {
329 ::testing::InitGoogleTest(&argc, argv);
330 return RUN_ALL_TESTS();
331 }
332