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