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 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 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 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 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 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 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 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 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 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 313 struct audio_thread *cras_iodev_list_get_audio_thread() 314 { 315 return NULL; 316 } 317 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 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 334 int main(int argc, char **argv) { 335 ::testing::InitGoogleTest(&argc, argv); 336 return RUN_ALL_TESTS(); 337 } 338