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