| // Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <gtest/gtest.h> |
| |
| extern "C" { |
| |
| // To test static functions. |
| #include "cras_bt_io.c" |
| } |
| |
| static struct cras_bt_device *fake_device = |
| reinterpret_cast<struct cras_bt_device*>(0x123); |
| static unsigned int cras_iodev_add_node_called; |
| static unsigned int cras_iodev_rm_node_called; |
| static unsigned int cras_iodev_free_format_called; |
| static unsigned int cras_iodev_set_active_node_called; |
| static unsigned int cras_iodev_list_add_output_called; |
| static unsigned int cras_iodev_list_rm_output_called; |
| static unsigned int cras_iodev_list_add_input_called; |
| static unsigned int cras_iodev_list_rm_input_called; |
| static unsigned int cras_bt_device_set_active_profile_called; |
| static unsigned int cras_bt_device_set_active_profile_val; |
| static int cras_bt_device_get_active_profile_ret; |
| static int cras_bt_device_switch_profile_on_open_called; |
| static int cras_bt_device_switch_profile_on_close_called; |
| static int cras_bt_device_can_switch_to_a2dp_ret; |
| static int cras_bt_device_has_a2dp_ret; |
| static int is_utf8_string_ret_value; |
| |
| void ResetStubData() { |
| cras_iodev_add_node_called = 0; |
| cras_iodev_rm_node_called = 0; |
| cras_iodev_free_format_called = 0; |
| cras_iodev_set_active_node_called = 0; |
| cras_iodev_list_add_output_called = 0; |
| cras_iodev_list_rm_output_called = 0; |
| cras_iodev_list_add_input_called = 0; |
| cras_iodev_list_rm_input_called = 0; |
| cras_bt_device_set_active_profile_called = 0; |
| cras_bt_device_set_active_profile_val = 0; |
| cras_bt_device_get_active_profile_ret = 0; |
| cras_bt_device_switch_profile_on_open_called= 0; |
| cras_bt_device_switch_profile_on_close_called = 0; |
| cras_bt_device_can_switch_to_a2dp_ret = 0; |
| cras_bt_device_has_a2dp_ret = 0; |
| is_utf8_string_ret_value = 1; |
| } |
| |
| namespace { |
| |
| class BtIoBasicSuite : public testing::Test { |
| protected: |
| virtual void SetUp() { |
| ResetStubData(); |
| SetUpIodev(&iodev_, CRAS_STREAM_OUTPUT); |
| SetUpIodev(&iodev2_, CRAS_STREAM_OUTPUT); |
| |
| update_supported_formats_called_ = 0; |
| frames_queued_called_ = 0; |
| delay_frames_called_ = 0; |
| get_buffer_called_ = 0; |
| put_buffer_called_ = 0; |
| is_open_called_ = 0; |
| open_dev_called_ = 0; |
| close_dev_called_ = 0; |
| dev_running_called_ = 0; |
| } |
| |
| virtual void TearDown() { |
| } |
| |
| static void SetUpIodev(struct cras_iodev *d, |
| enum CRAS_STREAM_DIRECTION dir) { |
| d->direction = dir; |
| d->update_supported_formats = update_supported_formats; |
| d->frames_queued = frames_queued; |
| d->delay_frames = delay_frames; |
| d->get_buffer = get_buffer; |
| d->put_buffer = put_buffer; |
| d->is_open = is_open; |
| d->open_dev = open_dev; |
| d->close_dev = close_dev; |
| d->dev_running = dev_running; |
| } |
| |
| // Stub functions for the iodev structure. |
| static int update_supported_formats(struct cras_iodev *iodev) { |
| iodev->supported_rates = (size_t *)calloc( |
| 2, sizeof(*iodev->supported_rates)); |
| iodev->supported_rates[0] = 48000; |
| iodev->supported_rates[1] = 0; |
| iodev->supported_channel_counts = (size_t *)calloc( |
| 2, sizeof(*iodev->supported_channel_counts)); |
| iodev->supported_channel_counts[0] = 2; |
| iodev->supported_channel_counts[1] = 0; |
| iodev->supported_formats = (snd_pcm_format_t *)calloc( |
| 2, sizeof(*iodev->supported_formats)); |
| iodev->supported_formats[0] = SND_PCM_FORMAT_S16_LE; |
| iodev->supported_formats[1] = (snd_pcm_format_t)0; |
| update_supported_formats_called_++; |
| return 0; |
| } |
| static int frames_queued(const cras_iodev* iodev) { |
| frames_queued_called_++; |
| return 0; |
| } |
| static int delay_frames(const cras_iodev* iodev) { |
| delay_frames_called_++; |
| return 0; |
| } |
| static int get_buffer(cras_iodev* iodev, |
| struct cras_audio_area** area, |
| unsigned int* num) { |
| get_buffer_called_++; |
| return 0; |
| } |
| static int put_buffer(cras_iodev* iodev, |
| unsigned int num) { |
| put_buffer_called_++; |
| return 0; |
| } |
| static int is_open(const cras_iodev* iodev) { |
| is_open_called_++; |
| return 0; |
| } |
| static int open_dev(cras_iodev* iodev) { |
| open_dev_called_++; |
| return 0; |
| } |
| static int close_dev(cras_iodev* iodev) { |
| close_dev_called_++; |
| return 0; |
| } |
| static int dev_running(const cras_iodev* iodev) { |
| dev_running_called_++; |
| return 1; |
| } |
| |
| static struct cras_iodev *bt_iodev; |
| static struct cras_iodev iodev_; |
| static struct cras_iodev iodev2_; |
| static unsigned int update_supported_formats_called_; |
| static unsigned int frames_queued_called_; |
| static unsigned int delay_frames_called_; |
| static unsigned int get_buffer_called_; |
| static unsigned int put_buffer_called_; |
| static unsigned int is_open_called_; |
| static unsigned int open_dev_called_; |
| static unsigned int close_dev_called_; |
| static unsigned int dev_running_called_; |
| }; |
| |
| struct cras_iodev *BtIoBasicSuite::bt_iodev; |
| struct cras_iodev BtIoBasicSuite::iodev_; |
| struct cras_iodev BtIoBasicSuite::iodev2_; |
| unsigned int BtIoBasicSuite::update_supported_formats_called_; |
| unsigned int BtIoBasicSuite::frames_queued_called_; |
| unsigned int BtIoBasicSuite::delay_frames_called_; |
| unsigned int BtIoBasicSuite::get_buffer_called_; |
| unsigned int BtIoBasicSuite::put_buffer_called_; |
| unsigned int BtIoBasicSuite::is_open_called_; |
| unsigned int BtIoBasicSuite::open_dev_called_; |
| unsigned int BtIoBasicSuite::close_dev_called_; |
| unsigned int BtIoBasicSuite::dev_running_called_; |
| |
| TEST_F(BtIoBasicSuite, CreateBtIo) { |
| struct cras_audio_area *fake_area; |
| struct cras_audio_format fake_fmt; |
| unsigned fr; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); |
| EXPECT_NE((void *)NULL, bt_iodev); |
| EXPECT_EQ(&iodev_, active_profile_dev(bt_iodev)); |
| EXPECT_EQ(1, cras_iodev_list_add_output_called); |
| bt_iodev->format = &fake_fmt; |
| bt_iodev->update_supported_formats(bt_iodev); |
| EXPECT_EQ(1, update_supported_formats_called_); |
| |
| bt_iodev->open_dev(bt_iodev); |
| EXPECT_EQ(1, open_dev_called_); |
| bt_iodev->is_open(bt_iodev); |
| EXPECT_EQ(1, is_open_called_); |
| bt_iodev->frames_queued(bt_iodev); |
| EXPECT_EQ(1, frames_queued_called_); |
| bt_iodev->get_buffer(bt_iodev, &fake_area, &fr); |
| EXPECT_EQ(1, get_buffer_called_); |
| bt_iodev->put_buffer(bt_iodev, fr); |
| EXPECT_EQ(1, put_buffer_called_); |
| bt_iodev->dev_running(bt_iodev); |
| EXPECT_EQ(1, dev_running_called_); |
| bt_iodev->close_dev(bt_iodev); |
| EXPECT_EQ(1, close_dev_called_); |
| EXPECT_EQ(1, cras_iodev_free_format_called); |
| cras_bt_io_destroy(bt_iodev); |
| EXPECT_EQ(1, cras_iodev_list_rm_output_called); |
| } |
| |
| TEST_F(BtIoBasicSuite, SwitchProfileOnUpdateFormatForInputDev) { |
| ResetStubData(); |
| iodev_.direction = CRAS_STREAM_INPUT; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); |
| |
| cras_bt_device_get_active_profile_ret = CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE; |
| bt_iodev->update_supported_formats(bt_iodev); |
| |
| EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY | |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY, |
| cras_bt_device_set_active_profile_val); |
| EXPECT_EQ(1, cras_bt_device_switch_profile_on_open_called); |
| } |
| |
| TEST_F(BtIoBasicSuite, NoSwitchProfileOnUpdateFormatForInputDevAlreadyOnHfp) { |
| ResetStubData(); |
| iodev_.direction = CRAS_STREAM_INPUT; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); |
| |
| /* No need to switch profile if already on HFP. */ |
| cras_bt_device_get_active_profile_ret = |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY; |
| bt_iodev->update_supported_formats(bt_iodev); |
| |
| EXPECT_EQ(0, cras_bt_device_switch_profile_on_open_called); |
| } |
| |
| TEST_F(BtIoBasicSuite, SwitchProfileOnCloseInputDev) { |
| ResetStubData(); |
| iodev_.direction = CRAS_STREAM_INPUT; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); |
| |
| cras_bt_device_get_active_profile_ret = |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY | |
| CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY; |
| cras_bt_device_has_a2dp_ret = 1; |
| bt_iodev->close_dev(bt_iodev); |
| |
| EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE, |
| cras_bt_device_set_active_profile_val); |
| EXPECT_EQ(1, cras_bt_device_switch_profile_on_close_called); |
| } |
| |
| TEST_F(BtIoBasicSuite, NoSwitchProfileOnCloseInputDevNoSupportA2dp) { |
| ResetStubData(); |
| iodev_.direction = CRAS_STREAM_INPUT; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); |
| |
| cras_bt_device_get_active_profile_ret = |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY | |
| CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY; |
| cras_bt_device_has_a2dp_ret = 0; |
| bt_iodev->close_dev(bt_iodev); |
| |
| EXPECT_EQ(0, cras_bt_device_switch_profile_on_close_called); |
| } |
| |
| TEST_F(BtIoBasicSuite, SwitchProfileOnAppendA2dpDev) { |
| ResetStubData(); |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); |
| |
| cras_bt_device_can_switch_to_a2dp_ret = 1; |
| cras_bt_io_append(bt_iodev, &iodev2_, |
| CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); |
| |
| EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE, |
| cras_bt_device_set_active_profile_val); |
| EXPECT_EQ(1, cras_bt_device_switch_profile_on_open_called); |
| } |
| |
| TEST_F(BtIoBasicSuite, NoSwitchProfileOnAppendHfpDev) { |
| ResetStubData(); |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); |
| |
| cras_bt_device_can_switch_to_a2dp_ret = 1; |
| cras_bt_io_append(bt_iodev, &iodev2_, |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); |
| |
| EXPECT_EQ(0, cras_bt_device_switch_profile_on_open_called); |
| } |
| |
| TEST_F(BtIoBasicSuite, CreateSetDeviceActiveProfileToA2DP) { |
| ResetStubData(); |
| cras_bt_device_get_active_profile_ret = |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY; |
| cras_bt_device_can_switch_to_a2dp_ret = 1; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); |
| |
| EXPECT_EQ(1, cras_bt_device_set_active_profile_called); |
| EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE, |
| cras_bt_device_set_active_profile_val); |
| cras_bt_io_destroy(bt_iodev); |
| } |
| |
| TEST_F(BtIoBasicSuite, CreateNoSetDeviceActiveProfileToA2DP) { |
| ResetStubData(); |
| cras_bt_device_get_active_profile_ret = |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY; |
| cras_bt_device_can_switch_to_a2dp_ret = 0; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); |
| |
| EXPECT_EQ(0, cras_bt_device_set_active_profile_called); |
| cras_bt_io_destroy(bt_iodev); |
| } |
| |
| TEST_F(BtIoBasicSuite, CreateSetDeviceActiveProfileToHFP) { |
| ResetStubData(); |
| cras_bt_device_get_active_profile_ret = 0; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY); |
| |
| EXPECT_EQ( |
| CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY | |
| CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY, |
| cras_bt_device_set_active_profile_val); |
| cras_bt_io_destroy(bt_iodev); |
| } |
| |
| TEST_F(BtIoBasicSuite, CreateDeviceWithInvalidUTF8Name) { |
| ResetStubData(); |
| strcpy(iodev_.info.name, "Something BT"); |
| iodev_.info.name[0] = 0xfe; |
| is_utf8_string_ret_value = 0; |
| bt_iodev = cras_bt_io_create(fake_device, &iodev_, |
| CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE); |
| |
| ASSERT_STREQ("BLUETOOTH", bt_iodev->active_node->name); |
| } |
| |
| } // namespace |
| |
| int main(int argc, char **argv) { |
| ::testing::InitGoogleTest(&argc, argv); |
| return RUN_ALL_TESTS(); |
| } |
| |
| extern "C" { |
| |
| // Cras iodev |
| void cras_iodev_add_node(struct cras_iodev *iodev, struct cras_ionode *node) |
| { |
| cras_iodev_add_node_called++; |
| iodev->nodes = node; |
| } |
| |
| void cras_iodev_rm_node(struct cras_iodev *iodev, struct cras_ionode *node) |
| { |
| cras_iodev_rm_node_called++; |
| iodev->nodes = NULL; |
| } |
| |
| void cras_iodev_free_format(struct cras_iodev *iodev) |
| { |
| cras_iodev_free_format_called++; |
| } |
| |
| void cras_iodev_set_active_node(struct cras_iodev *iodev, |
| struct cras_ionode *node) |
| { |
| cras_iodev_set_active_node_called++; |
| iodev->active_node = node; |
| } |
| |
| int cras_iodev_set_node_attr(struct cras_ionode *ionode, |
| enum ionode_attr attr, int value) |
| { |
| return 0; |
| } |
| |
| // From iodev list. |
| int cras_iodev_list_add_output(struct cras_iodev *output) |
| { |
| cras_iodev_list_add_output_called++; |
| return 0; |
| } |
| |
| int cras_iodev_list_rm_output(struct cras_iodev *dev) |
| { |
| cras_iodev_list_rm_output_called++; |
| return 0; |
| } |
| |
| int cras_iodev_list_add_input(struct cras_iodev *output) |
| { |
| cras_iodev_list_add_input_called++; |
| return 0; |
| } |
| |
| int cras_iodev_list_rm_input(struct cras_iodev *dev) |
| { |
| cras_iodev_list_rm_input_called++; |
| return 0; |
| } |
| |
| // From bt device |
| int cras_bt_device_get_active_profile(const struct cras_bt_device *device) |
| { |
| return cras_bt_device_get_active_profile_ret; |
| } |
| |
| void cras_bt_device_set_active_profile(struct cras_bt_device *device, |
| unsigned int profile) |
| { |
| cras_bt_device_set_active_profile_called++; |
| cras_bt_device_set_active_profile_val = profile; |
| } |
| |
| int cras_bt_device_has_a2dp(struct cras_bt_device *device) |
| { |
| return cras_bt_device_has_a2dp_ret; |
| } |
| |
| int cras_bt_device_can_switch_to_a2dp(struct cras_bt_device *device) |
| { |
| return cras_bt_device_can_switch_to_a2dp_ret; |
| } |
| |
| int cras_bt_device_switch_profile_on_close(struct cras_bt_device *device, |
| struct cras_iodev *bt_iodev) |
| { |
| cras_bt_device_switch_profile_on_close_called++; |
| return 0; |
| } |
| |
| int cras_bt_device_switch_profile_on_open(struct cras_bt_device *device, |
| struct cras_iodev *bt_iodev) |
| { |
| cras_bt_device_switch_profile_on_open_called++; |
| return 0; |
| } |
| |
| int is_utf8_string(const char* string) |
| { |
| return is_utf8_string_ret_value; |
| } |
| } // extern "C" |