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