1 /* Copyright 2013 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
6 #include <gtest/gtest.h>
7 #include <stdint.h>
8 #include <time.h>
9
10 extern "C" {
11 #include "cras_hfp_info.c"
12 }
13
14 static struct hfp_info *info;
15 static struct cras_iodev dev;
16 static cras_audio_format format;
17
18 static thread_callback thread_cb;
19 static void *cb_data;
20 static timespec ts;
21
ResetStubData()22 void ResetStubData() {
23 format.format = SND_PCM_FORMAT_S16_LE;
24 format.num_channels = 1;
25 format.frame_rate = 8000;
26 dev.format = &format;
27 }
28
29 namespace {
30
TEST(HfpInfo,AddRmDev)31 TEST(HfpInfo, AddRmDev) {
32 info = hfp_info_create();
33 ASSERT_NE(info, (void *)NULL);
34 dev.direction = CRAS_STREAM_OUTPUT;
35
36 /* Test add dev */
37 ASSERT_EQ(0, hfp_info_add_iodev(info, &dev));
38 ASSERT_TRUE(hfp_info_has_iodev(info));
39
40 /* Test remove dev */
41 ASSERT_EQ(0, hfp_info_rm_iodev(info, &dev));
42 ASSERT_FALSE(hfp_info_has_iodev(info));
43
44 hfp_info_destroy(info);
45 }
46
TEST(HfpInfo,AddRmDevInvalid)47 TEST(HfpInfo, AddRmDevInvalid) {
48 info = hfp_info_create();
49 ASSERT_NE(info, (void *)NULL);
50
51 dev.direction = CRAS_STREAM_OUTPUT;
52
53 /* Remove an iodev which doesn't exist */
54 ASSERT_NE(0, hfp_info_rm_iodev(info, &dev));
55
56 /* Adding an iodev twice returns error code */
57 ASSERT_EQ(0, hfp_info_add_iodev(info, &dev));
58 ASSERT_NE(0, hfp_info_add_iodev(info, &dev));
59
60 hfp_info_destroy(info);
61 }
62
TEST(HfpInfo,AcquirePlaybackBuffer)63 TEST(HfpInfo, AcquirePlaybackBuffer) {
64 unsigned buffer_frames, buffer_frames2, queued;
65 uint8_t *samples;
66
67 ResetStubData();
68
69 info = hfp_info_create();
70 ASSERT_NE(info, (void *)NULL);
71
72 hfp_info_start(1, 48, info);
73 dev.direction = CRAS_STREAM_OUTPUT;
74 ASSERT_EQ(0, hfp_info_add_iodev(info, &dev));
75
76 buffer_frames = 500;
77 hfp_buf_acquire(info, &dev, &samples, &buffer_frames);
78 ASSERT_EQ(500, buffer_frames);
79
80 hfp_buf_release(info, &dev, 500);
81 ASSERT_EQ(500, hfp_buf_queued(info, &dev));
82
83 /* Assert the amount of frames of available buffer + queued buf is
84 * greater than or equal to the buffer size, 2 bytes per frame
85 */
86 queued = hfp_buf_queued(info, &dev);
87 buffer_frames = 500;
88 hfp_buf_acquire(info, &dev, &samples, &buffer_frames);
89 ASSERT_GE(info->playback_buf->used_size / 2, buffer_frames + queued);
90
91 /* Consume all queued data from read buffer */
92 buf_increment_read(info->playback_buf, queued * 2);
93
94 queued = hfp_buf_queued(info, &dev);
95 ASSERT_EQ(0, queued);
96
97 /* Assert consecutive acquire buffer will acquire full used size of buffer */
98 buffer_frames = 500;
99 hfp_buf_acquire(info, &dev, &samples, &buffer_frames);
100 hfp_buf_release(info, &dev, buffer_frames);
101
102 buffer_frames2 = 500;
103 hfp_buf_acquire(info, &dev, &samples, &buffer_frames2);
104 hfp_buf_release(info, &dev, buffer_frames2);
105
106 ASSERT_GE(info->playback_buf->used_size / 2, buffer_frames + buffer_frames2);
107
108 hfp_info_destroy(info);
109 }
110
TEST(HfpInfo,AcquireCaptureBuffer)111 TEST(HfpInfo, AcquireCaptureBuffer) {
112 unsigned buffer_frames, buffer_frames2;
113 uint8_t *samples;
114
115 ResetStubData();
116
117 info = hfp_info_create();
118 ASSERT_NE(info, (void *)NULL);
119
120 hfp_info_start(1, 48, info);
121 dev.direction = CRAS_STREAM_INPUT;
122 ASSERT_EQ(0, hfp_info_add_iodev(info, &dev));
123
124 /* Put fake data 100 bytes(50 frames) in capture buf for test */
125 buf_increment_write(info->capture_buf, 100);
126
127 /* Assert successfully acquire and release 100 bytes of data */
128 buffer_frames = 50;
129 hfp_buf_acquire(info, &dev, &samples, &buffer_frames);
130 ASSERT_EQ(50, buffer_frames);
131
132 hfp_buf_release(info, &dev, buffer_frames);
133 ASSERT_EQ(0, hfp_buf_queued(info, &dev));
134
135 /* Push fake data to capture buffer */
136 buf_increment_write(info->capture_buf, info->capture_buf->used_size - 100);
137 buf_increment_write(info->capture_buf, 100);
138
139 /* Assert consecutive acquire call will consume the whole buffer */
140 buffer_frames = 1000;
141 hfp_buf_acquire(info, &dev, &samples, &buffer_frames);
142 hfp_buf_release(info, &dev, buffer_frames);
143 ASSERT_GE(1000, buffer_frames);
144
145 buffer_frames2 = 1000;
146 hfp_buf_acquire(info, &dev, &samples, &buffer_frames2);
147 hfp_buf_release(info, &dev, buffer_frames2);
148
149 ASSERT_GE(info->capture_buf->used_size / 2, buffer_frames + buffer_frames2);
150
151 hfp_info_destroy(info);
152 }
153
TEST(HfpInfo,HfpReadWriteFD)154 TEST(HfpInfo, HfpReadWriteFD) {
155 int rc;
156 int sock[2];
157 uint8_t sample[480];
158 uint8_t *buf;
159 unsigned buffer_count;
160
161 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
162
163 info = hfp_info_create();
164 ASSERT_NE(info, (void *)NULL);
165
166 dev.direction = CRAS_STREAM_INPUT;
167 hfp_info_start(sock[1], 48, info);
168 ASSERT_EQ(0, hfp_info_add_iodev(info, &dev));
169
170 /* Mock the sco fd and send some fake data */
171 send(sock[0], sample, 48, 0);
172
173 rc = hfp_read(info);
174 ASSERT_EQ(48, rc);
175
176 rc = hfp_buf_queued(info, &dev);
177 ASSERT_EQ(48 / 2, rc);
178
179 /* Fill the write buffer*/
180 buffer_count = info->capture_buf->used_size;
181 buf = buf_write_pointer_size(info->capture_buf, &buffer_count);
182 buf_increment_write(info->capture_buf, buffer_count);
183 ASSERT_NE((void *)NULL, buf);
184
185 rc = hfp_read(info);
186 ASSERT_EQ(0, rc);
187
188 ASSERT_EQ(0, hfp_info_rm_iodev(info, &dev));
189 dev.direction = CRAS_STREAM_OUTPUT;
190 ASSERT_EQ(0, hfp_info_add_iodev(info, &dev));
191
192 /* Initial buffer is empty */
193 rc = hfp_write(info);
194 ASSERT_EQ(0, rc);
195
196 buffer_count = 1024;
197 buf = buf_write_pointer_size(info->playback_buf, &buffer_count);
198 buf_increment_write(info->playback_buf, buffer_count);
199
200 rc = hfp_write(info);
201 ASSERT_EQ(48, rc);
202
203 rc = recv(sock[0], sample, 48, 0);
204 ASSERT_EQ(48, rc);
205
206 hfp_info_destroy(info);
207 }
208
TEST(HfpInfo,StartHfpInfo)209 TEST(HfpInfo, StartHfpInfo) {
210 int sock[2];
211
212 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
213
214 info = hfp_info_create();
215 ASSERT_NE(info, (void *)NULL);
216
217 hfp_info_start(sock[0], 48, info);
218 ASSERT_EQ(1, hfp_info_running(info));
219 ASSERT_EQ(cb_data, (void *)info);
220
221 hfp_info_stop(info);
222 ASSERT_EQ(0, hfp_info_running(info));
223 ASSERT_EQ(NULL, cb_data);
224
225 hfp_info_destroy(info);
226 }
227
TEST(HfpInfo,StartHfpInfoAndRead)228 TEST(HfpInfo, StartHfpInfoAndRead) {
229 int rc;
230 int sock[2];
231 uint8_t sample[480];
232
233 ResetStubData();
234
235 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
236
237 info = hfp_info_create();
238 ASSERT_NE(info, (void *)NULL);
239
240 /* Start and send two chunk of fake data */
241 hfp_info_start(sock[1], 48, info);
242 send(sock[0], sample ,48, 0);
243 send(sock[0], sample ,48, 0);
244
245 /* Trigger thread callback */
246 thread_cb((struct hfp_info *)cb_data);
247
248 dev.direction = CRAS_STREAM_INPUT;
249 ASSERT_EQ(0, hfp_info_add_iodev(info, &dev));
250
251 /* Expect no data read, since no idev present at previous thread callback */
252 rc = hfp_buf_queued(info, &dev);
253 ASSERT_EQ(0, rc);
254
255 /* Trigger thread callback after idev added. */
256 ts.tv_sec = 0;
257 ts.tv_nsec = 5000000;
258 thread_cb((struct hfp_info *)cb_data);
259
260 rc = hfp_buf_queued(info, &dev);
261 ASSERT_EQ(48 / 2, rc);
262
263 /* Assert wait time is unchanged. */
264 ASSERT_EQ(0, ts.tv_sec);
265 ASSERT_EQ(5000000, ts.tv_nsec);
266
267 hfp_info_stop(info);
268 ASSERT_EQ(0, hfp_info_running(info));
269
270 hfp_info_destroy(info);
271 }
272
TEST(HfpInfo,StartHfpInfoAndWrite)273 TEST(HfpInfo, StartHfpInfoAndWrite) {
274 int rc;
275 int sock[2];
276 uint8_t sample[480];
277
278 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
279
280 info = hfp_info_create();
281 ASSERT_NE(info, (void *)NULL);
282
283 hfp_info_start(sock[1], 48, info);
284 send(sock[0], sample ,48, 0);
285 send(sock[0], sample ,48, 0);
286
287 /* Trigger thread callback */
288 thread_cb((struct hfp_info *)cb_data);
289
290 dev.direction = CRAS_STREAM_OUTPUT;
291 ASSERT_EQ(0, hfp_info_add_iodev(info, &dev));
292
293 /* Assert queued samples unchanged before output device added */
294 ASSERT_EQ(0, hfp_buf_queued(info, &dev));
295
296 /* Put some fake data and trigger thread callback again */
297 buf_increment_write(info->playback_buf, 1008);
298 thread_cb((struct hfp_info *)cb_data);
299
300 /* Assert some samples written */
301 rc = recv(sock[0], sample ,48, 0);
302 ASSERT_EQ(48, rc);
303 ASSERT_EQ(480, hfp_buf_queued(info, &dev));
304
305 hfp_info_stop(info);
306 hfp_info_destroy(info);
307 }
308
309 } // namespace
310
311 extern "C" {
312
cras_iodev_list_get_audio_thread()313 struct audio_thread *cras_iodev_list_get_audio_thread()
314 {
315 return NULL;
316 }
317
audio_thread_add_callback(int fd,thread_callback cb,void * data)318 void audio_thread_add_callback(int fd, thread_callback cb,
319 void *data)
320 {
321 thread_cb = cb;
322 cb_data = data;
323 return;
324 }
325
audio_thread_rm_callback_sync(struct audio_thread * thread,int fd)326 int audio_thread_rm_callback_sync(struct audio_thread *thread, int fd)
327 {
328 thread_cb = NULL;
329 cb_data = NULL;
330 return 0;
331 }
332 }
333
main(int argc,char ** argv)334 int main(int argc, char **argv) {
335 ::testing::InitGoogleTest(&argc, argv);
336 return RUN_ALL_TESTS();
337 }
338