1 // Copyright (c) 2014 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
7 extern "C" {
8
9 // To test static functions.
10 #include "cras_bt_io.c"
11 #include "utlist.h"
12 }
13
14 static struct cras_bt_device *fake_device =
15 reinterpret_cast<struct cras_bt_device*>(0x123);
16 static unsigned int cras_iodev_add_node_called;
17 static unsigned int cras_iodev_rm_node_called;
18 static unsigned int cras_iodev_free_format_called;
19 static unsigned int cras_iodev_free_resources_called;
20 static unsigned int cras_iodev_set_active_node_called;
21 static unsigned int cras_iodev_list_add_output_called;
22 static unsigned int cras_iodev_list_rm_output_called;
23 static unsigned int cras_iodev_list_add_input_called;
24 static unsigned int cras_iodev_list_rm_input_called;
25 static unsigned int cras_bt_device_set_active_profile_called;
26 static unsigned int cras_bt_device_set_active_profile_val;
27 static int cras_bt_device_get_active_profile_ret;
28 static int cras_bt_device_switch_profile_enable_dev_called;
29 static int cras_bt_device_switch_profile_called;
30 static int cras_bt_device_can_switch_to_a2dp_ret;
31 static int cras_bt_device_has_a2dp_ret;
32 static int is_utf8_string_ret_value;
33
ResetStubData()34 void ResetStubData() {
35 cras_iodev_add_node_called = 0;
36 cras_iodev_rm_node_called = 0;
37 cras_iodev_free_format_called = 0;
38 cras_iodev_free_resources_called = 0;
39 cras_iodev_set_active_node_called = 0;
40 cras_iodev_list_add_output_called = 0;
41 cras_iodev_list_rm_output_called = 0;
42 cras_iodev_list_add_input_called = 0;
43 cras_iodev_list_rm_input_called = 0;
44 cras_bt_device_set_active_profile_called = 0;
45 cras_bt_device_set_active_profile_val = 0;
46 cras_bt_device_get_active_profile_ret = 0;
47 cras_bt_device_switch_profile_enable_dev_called= 0;
48 cras_bt_device_switch_profile_called = 0;
49 cras_bt_device_can_switch_to_a2dp_ret = 0;
50 cras_bt_device_has_a2dp_ret = 0;
51 is_utf8_string_ret_value = 1;
52 }
53
54 namespace {
55
56 class BtIoBasicSuite : public testing::Test {
57 protected:
SetUp()58 virtual void SetUp() {
59 ResetStubData();
60 SetUpIodev(&iodev_, CRAS_STREAM_OUTPUT);
61 SetUpIodev(&iodev2_, CRAS_STREAM_OUTPUT);
62
63 update_supported_formats_called_ = 0;
64 frames_queued_called_ = 0;
65 delay_frames_called_ = 0;
66 get_buffer_called_ = 0;
67 put_buffer_called_ = 0;
68 configure_dev_called_ = 0;
69 close_dev_called_ = 0;
70 }
71
TearDown()72 virtual void TearDown() {
73 }
74
SetUpIodev(struct cras_iodev * d,enum CRAS_STREAM_DIRECTION dir)75 static void SetUpIodev(struct cras_iodev *d,
76 enum CRAS_STREAM_DIRECTION dir) {
77 d->direction = dir;
78 d->update_supported_formats = update_supported_formats;
79 d->frames_queued = frames_queued;
80 d->delay_frames = delay_frames;
81 d->get_buffer = get_buffer;
82 d->put_buffer = put_buffer;
83 d->configure_dev = configure_dev;
84 d->close_dev = close_dev;
85 d->supported_rates = NULL;
86 d->supported_channel_counts = NULL;
87 d->supported_formats = NULL;
88 }
89
90 // Stub functions for the iodev structure.
update_supported_formats(struct cras_iodev * iodev)91 static int update_supported_formats(struct cras_iodev *iodev) {
92 free(iodev->supported_rates);
93 free(iodev->supported_channel_counts);
94 free(iodev->supported_formats);
95 iodev->supported_rates = (size_t *)calloc(
96 2, sizeof(*iodev->supported_rates));
97 iodev->supported_rates[0] = 48000;
98 iodev->supported_rates[1] = 0;
99 iodev->supported_channel_counts = (size_t *)calloc(
100 2, sizeof(*iodev->supported_channel_counts));
101 iodev->supported_channel_counts[0] = 2;
102 iodev->supported_channel_counts[1] = 0;
103 iodev->supported_formats = (snd_pcm_format_t *)calloc(
104 2, sizeof(*iodev->supported_formats));
105 iodev->supported_formats[0] = SND_PCM_FORMAT_S16_LE;
106 iodev->supported_formats[1] = (snd_pcm_format_t)0;
107 update_supported_formats_called_++;
108 return 0;
109 }
frames_queued(const cras_iodev * iodev,struct timespec * tstamp)110 static int frames_queued(const cras_iodev* iodev,
111 struct timespec *tstamp) {
112 frames_queued_called_++;
113 return 0;
114 }
delay_frames(const cras_iodev * iodev)115 static int delay_frames(const cras_iodev* iodev) {
116 delay_frames_called_++;
117 return 0;
118 }
get_buffer(cras_iodev * iodev,struct cras_audio_area ** area,unsigned int * num)119 static int get_buffer(cras_iodev* iodev,
120 struct cras_audio_area** area,
121 unsigned int* num) {
122 get_buffer_called_++;
123 return 0;
124 }
put_buffer(cras_iodev * iodev,unsigned int num)125 static int put_buffer(cras_iodev* iodev,
126 unsigned int num) {
127 put_buffer_called_++;
128 return 0;
129 }
configure_dev(cras_iodev * iodev)130 static int configure_dev(cras_iodev* iodev) {
131 configure_dev_called_++;
132 return 0;
133 }
close_dev(cras_iodev * iodev)134 static int close_dev(cras_iodev* iodev) {
135 free(iodev->format);
136 free(iodev->ext_format);
137 iodev->format = NULL;
138 iodev->ext_format = NULL;
139 close_dev_called_++;
140 return 0;
141 }
142
143 static struct cras_iodev *bt_iodev;
144 static struct cras_iodev iodev_;
145 static struct cras_iodev iodev2_;
146 static unsigned int update_supported_formats_called_;
147 static unsigned int frames_queued_called_;
148 static unsigned int delay_frames_called_;
149 static unsigned int get_buffer_called_;
150 static unsigned int put_buffer_called_;
151 static unsigned int configure_dev_called_;
152 static unsigned int close_dev_called_;
153 };
154
155 struct cras_iodev *BtIoBasicSuite::bt_iodev;
156 struct cras_iodev BtIoBasicSuite::iodev_;
157 struct cras_iodev BtIoBasicSuite::iodev2_;
158 unsigned int BtIoBasicSuite::update_supported_formats_called_;
159 unsigned int BtIoBasicSuite::frames_queued_called_;
160 unsigned int BtIoBasicSuite::delay_frames_called_;
161 unsigned int BtIoBasicSuite::get_buffer_called_;
162 unsigned int BtIoBasicSuite::put_buffer_called_;
163 unsigned int BtIoBasicSuite::configure_dev_called_;
164 unsigned int BtIoBasicSuite::close_dev_called_;
165
TEST_F(BtIoBasicSuite,CreateBtIo)166 TEST_F(BtIoBasicSuite, CreateBtIo) {
167 struct cras_audio_area *fake_area;
168 struct cras_audio_format fake_fmt;
169 struct timespec tstamp;
170 unsigned fr;
171 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
172 CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
173 EXPECT_NE((void *)NULL, bt_iodev);
174 EXPECT_EQ(&iodev_, active_profile_dev(bt_iodev));
175 EXPECT_EQ(1, cras_iodev_list_add_output_called);
176 bt_iodev->open_dev(bt_iodev);
177 bt_iodev->format = &fake_fmt;
178 bt_iodev->update_supported_formats(bt_iodev);
179 EXPECT_EQ(1, update_supported_formats_called_);
180
181 bt_iodev->configure_dev(bt_iodev);
182 EXPECT_EQ(1, configure_dev_called_);
183 bt_iodev->frames_queued(bt_iodev, &tstamp);
184 EXPECT_EQ(1, frames_queued_called_);
185 bt_iodev->get_buffer(bt_iodev, &fake_area, &fr);
186 EXPECT_EQ(1, get_buffer_called_);
187 bt_iodev->put_buffer(bt_iodev, fr);
188 EXPECT_EQ(1, put_buffer_called_);
189 bt_iodev->close_dev(bt_iodev);
190 EXPECT_EQ(1, close_dev_called_);
191 EXPECT_EQ(1, cras_iodev_free_format_called);
192 cras_bt_io_destroy(bt_iodev);
193 EXPECT_EQ(1, cras_iodev_free_resources_called);
194 EXPECT_EQ(1, cras_iodev_list_rm_output_called);
195
196 free(iodev_.supported_rates);
197 free(iodev_.supported_channel_counts);
198 free(iodev_.supported_formats);
199 }
200
TEST_F(BtIoBasicSuite,SwitchProfileOnOpenDevForInputDev)201 TEST_F(BtIoBasicSuite, SwitchProfileOnOpenDevForInputDev) {
202 ResetStubData();
203 iodev_.direction = CRAS_STREAM_INPUT;
204 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
205 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
206
207 cras_bt_device_get_active_profile_ret = CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE;
208 bt_iodev->open_dev(bt_iodev);
209
210 EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY |
211 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY,
212 cras_bt_device_set_active_profile_val);
213 EXPECT_EQ(1, cras_bt_device_switch_profile_enable_dev_called);
214 cras_bt_io_destroy(bt_iodev);
215 }
216
TEST_F(BtIoBasicSuite,NoSwitchProfileOnOpenDevForInputDevAlreadyOnHfp)217 TEST_F(BtIoBasicSuite, NoSwitchProfileOnOpenDevForInputDevAlreadyOnHfp) {
218 ResetStubData();
219 iodev_.direction = CRAS_STREAM_INPUT;
220 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
221 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
222
223 /* No need to switch profile if already on HFP. */
224 cras_bt_device_get_active_profile_ret =
225 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY;
226 bt_iodev->open_dev(bt_iodev);
227
228 EXPECT_EQ(0, cras_bt_device_switch_profile_enable_dev_called);
229 cras_bt_io_destroy(bt_iodev);
230 }
231
TEST_F(BtIoBasicSuite,SwitchProfileOnCloseInputDev)232 TEST_F(BtIoBasicSuite, SwitchProfileOnCloseInputDev) {
233 ResetStubData();
234 iodev_.direction = CRAS_STREAM_INPUT;
235 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
236 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
237
238 cras_bt_device_get_active_profile_ret =
239 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY |
240 CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY;
241 cras_bt_device_has_a2dp_ret = 1;
242 bt_iodev->close_dev(bt_iodev);
243
244 EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE,
245 cras_bt_device_set_active_profile_val);
246 EXPECT_EQ(1, cras_bt_device_switch_profile_called);
247 cras_bt_io_destroy(bt_iodev);
248 }
249
TEST_F(BtIoBasicSuite,NoSwitchProfileOnCloseInputDevNoSupportA2dp)250 TEST_F(BtIoBasicSuite, NoSwitchProfileOnCloseInputDevNoSupportA2dp) {
251 ResetStubData();
252 iodev_.direction = CRAS_STREAM_INPUT;
253 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
254 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
255
256 cras_bt_device_get_active_profile_ret =
257 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY |
258 CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY;
259 cras_bt_device_has_a2dp_ret = 0;
260 bt_iodev->close_dev(bt_iodev);
261
262 EXPECT_EQ(0, cras_bt_device_switch_profile_called);
263 cras_bt_io_destroy(bt_iodev);
264 }
265
TEST_F(BtIoBasicSuite,SwitchProfileOnAppendA2dpDev)266 TEST_F(BtIoBasicSuite, SwitchProfileOnAppendA2dpDev) {
267 ResetStubData();
268 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
269 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
270
271 cras_bt_device_can_switch_to_a2dp_ret = 1;
272 cras_bt_io_append(bt_iodev, &iodev2_,
273 CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
274
275 EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE,
276 cras_bt_device_set_active_profile_val);
277 EXPECT_EQ(0, cras_bt_device_switch_profile_enable_dev_called);
278 EXPECT_EQ(1, cras_bt_device_switch_profile_called);
279 cras_bt_io_destroy(bt_iodev);
280 }
281
TEST_F(BtIoBasicSuite,NoSwitchProfileOnAppendHfpDev)282 TEST_F(BtIoBasicSuite, NoSwitchProfileOnAppendHfpDev) {
283 ResetStubData();
284 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
285 CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
286
287 cras_bt_device_can_switch_to_a2dp_ret = 1;
288 cras_bt_io_append(bt_iodev, &iodev2_,
289 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
290
291 EXPECT_EQ(0, cras_bt_device_switch_profile_enable_dev_called);
292 cras_bt_io_destroy(bt_iodev);
293 }
294
TEST_F(BtIoBasicSuite,CreateSetDeviceActiveProfileToA2DP)295 TEST_F(BtIoBasicSuite, CreateSetDeviceActiveProfileToA2DP) {
296 ResetStubData();
297 cras_bt_device_get_active_profile_ret =
298 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY;
299 cras_bt_device_can_switch_to_a2dp_ret = 1;
300 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
301 CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
302
303 EXPECT_EQ(1, cras_bt_device_set_active_profile_called);
304 EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE,
305 cras_bt_device_set_active_profile_val);
306 cras_bt_io_destroy(bt_iodev);
307 }
308
TEST_F(BtIoBasicSuite,CreateNoSetDeviceActiveProfileToA2DP)309 TEST_F(BtIoBasicSuite, CreateNoSetDeviceActiveProfileToA2DP) {
310 ResetStubData();
311 cras_bt_device_get_active_profile_ret =
312 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY;
313 cras_bt_device_can_switch_to_a2dp_ret = 0;
314 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
315 CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
316
317 EXPECT_EQ(0, cras_bt_device_set_active_profile_called);
318 cras_bt_io_destroy(bt_iodev);
319 }
320
TEST_F(BtIoBasicSuite,CreateSetDeviceActiveProfileToHFP)321 TEST_F(BtIoBasicSuite, CreateSetDeviceActiveProfileToHFP) {
322 ResetStubData();
323 cras_bt_device_get_active_profile_ret = 0;
324 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
325 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
326
327 EXPECT_EQ(
328 CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY |
329 CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY,
330 cras_bt_device_set_active_profile_val);
331 cras_bt_io_destroy(bt_iodev);
332 }
333
TEST_F(BtIoBasicSuite,CreateDeviceWithInvalidUTF8Name)334 TEST_F(BtIoBasicSuite, CreateDeviceWithInvalidUTF8Name) {
335 ResetStubData();
336 strcpy(iodev_.info.name, "Something BT");
337 iodev_.info.name[0] = 0xfe;
338 is_utf8_string_ret_value = 0;
339 bt_iodev = cras_bt_io_create(fake_device, &iodev_,
340 CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
341
342 ASSERT_STREQ("BLUETOOTH", bt_iodev->active_node->name);
343 cras_bt_io_destroy(bt_iodev);
344 }
345
346 } // namespace
347
main(int argc,char ** argv)348 int main(int argc, char **argv) {
349 ::testing::InitGoogleTest(&argc, argv);
350 return RUN_ALL_TESTS();
351 }
352
353 extern "C" {
354
355 // Cras iodev
cras_iodev_add_node(struct cras_iodev * iodev,struct cras_ionode * node)356 void cras_iodev_add_node(struct cras_iodev *iodev, struct cras_ionode *node)
357 {
358 cras_iodev_add_node_called++;
359 DL_APPEND(iodev->nodes, node);
360 }
361
cras_iodev_rm_node(struct cras_iodev * iodev,struct cras_ionode * node)362 void cras_iodev_rm_node(struct cras_iodev *iodev, struct cras_ionode *node)
363 {
364 cras_iodev_rm_node_called++;
365 DL_DELETE(iodev->nodes, node);
366 }
367
cras_iodev_free_format(struct cras_iodev * iodev)368 void cras_iodev_free_format(struct cras_iodev *iodev)
369 {
370 cras_iodev_free_format_called++;
371 }
372
cras_iodev_set_active_node(struct cras_iodev * iodev,struct cras_ionode * node)373 void cras_iodev_set_active_node(struct cras_iodev *iodev,
374 struct cras_ionode *node)
375 {
376 cras_iodev_set_active_node_called++;
377 iodev->active_node = node;
378 }
379
cras_iodev_set_node_attr(struct cras_ionode * ionode,enum ionode_attr attr,int value)380 int cras_iodev_set_node_attr(struct cras_ionode *ionode,
381 enum ionode_attr attr, int value)
382 {
383 return 0;
384 }
385
cras_iodev_free_resources(struct cras_iodev * iodev)386 void cras_iodev_free_resources(struct cras_iodev *iodev)
387 {
388 cras_iodev_free_resources_called++;
389 }
390
391 // From iodev list.
cras_iodev_list_add_output(struct cras_iodev * output)392 int cras_iodev_list_add_output(struct cras_iodev *output)
393 {
394 cras_iodev_list_add_output_called++;
395 return 0;
396 }
397
cras_iodev_list_rm_output(struct cras_iodev * dev)398 int cras_iodev_list_rm_output(struct cras_iodev *dev)
399 {
400 cras_iodev_list_rm_output_called++;
401 return 0;
402 }
403
cras_iodev_list_add_input(struct cras_iodev * output)404 int cras_iodev_list_add_input(struct cras_iodev *output)
405 {
406 cras_iodev_list_add_input_called++;
407 return 0;
408 }
409
cras_iodev_list_rm_input(struct cras_iodev * dev)410 int cras_iodev_list_rm_input(struct cras_iodev *dev)
411 {
412 cras_iodev_list_rm_input_called++;
413 return 0;
414 }
415
416 // From bt device
cras_bt_device_get_active_profile(const struct cras_bt_device * device)417 int cras_bt_device_get_active_profile(const struct cras_bt_device *device)
418 {
419 return cras_bt_device_get_active_profile_ret;
420 }
421
cras_bt_device_set_active_profile(struct cras_bt_device * device,unsigned int profile)422 void cras_bt_device_set_active_profile(struct cras_bt_device *device,
423 unsigned int profile)
424 {
425 cras_bt_device_set_active_profile_called++;
426 cras_bt_device_set_active_profile_val = profile;
427 }
428
cras_bt_device_has_a2dp(struct cras_bt_device * device)429 int cras_bt_device_has_a2dp(struct cras_bt_device *device)
430 {
431 return cras_bt_device_has_a2dp_ret;
432 }
433
cras_bt_device_can_switch_to_a2dp(struct cras_bt_device * device)434 int cras_bt_device_can_switch_to_a2dp(struct cras_bt_device *device)
435 {
436 return cras_bt_device_can_switch_to_a2dp_ret;
437 }
438
cras_bt_device_switch_profile(struct cras_bt_device * device,struct cras_iodev * bt_iodev)439 int cras_bt_device_switch_profile(struct cras_bt_device *device,
440 struct cras_iodev *bt_iodev)
441 {
442 cras_bt_device_switch_profile_called++;
443 return 0;
444 }
445
cras_bt_device_switch_profile_enable_dev(struct cras_bt_device * device,struct cras_iodev * bt_iodev)446 int cras_bt_device_switch_profile_enable_dev(struct cras_bt_device *device,
447 struct cras_iodev *bt_iodev)
448 {
449 cras_bt_device_switch_profile_enable_dev_called++;
450 return 0;
451 }
452
cras_bt_device_object_path(const struct cras_bt_device * device)453 const char *cras_bt_device_object_path(const struct cras_bt_device *device)
454 {
455 return "/fake/object/path";
456 }
457
cras_bt_device_get_use_hardware_volume(struct cras_bt_device * device)458 int cras_bt_device_get_use_hardware_volume(struct cras_bt_device *device)
459 {
460 return 1;
461 }
462
is_utf8_string(const char * string)463 int is_utf8_string(const char* string)
464 {
465 return is_utf8_string_ret_value;
466 }
467
cras_iodev_default_no_stream_playback(struct cras_iodev * odev,int enable)468 int cras_iodev_default_no_stream_playback(struct cras_iodev *odev, int enable)
469 {
470 return 0;
471 }
472
473 } // extern "C"
474