blob: cfb675604e9e2f769f6dc5fe13299052ec3735b4 [file] [log] [blame]
// Copyright (c) 2012 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>
#include <stdio.h>
#include <sys/param.h>
#include <syslog.h>
#include <map>
extern "C" {
#include "cras_alsa_card.h"
#include "cras_alsa_io.h"
#include "cras_alsa_mixer.h"
#include "cras_alsa_ucm.h"
#include "cras_iodev.h"
#include "cras_types.h"
#include "cras_util.h"
#include "utlist.h"
}
namespace {
static size_t cras_alsa_mixer_create_called;
static struct cras_alsa_mixer* cras_alsa_mixer_create_return;
static size_t cras_alsa_mixer_destroy_called;
static size_t cras_alsa_iodev_create_called;
static struct cras_iodev** cras_alsa_iodev_create_return;
static struct cras_iodev fake_dev1, fake_dev2, fake_dev3, fake_dev4;
static struct cras_iodev* cras_alsa_iodev_create_default_return[] = {
&fake_dev1,
&fake_dev2,
&fake_dev3,
&fake_dev4,
};
static size_t cras_alsa_iodev_create_return_size;
static size_t cras_alsa_iodev_legacy_complete_init_called;
static size_t cras_alsa_iodev_ucm_add_nodes_and_jacks_called;
static size_t cras_alsa_iodev_ucm_complete_init_called;
static size_t cras_alsa_iodev_destroy_called;
static struct cras_iodev* cras_alsa_iodev_destroy_arg;
static size_t cras_alsa_iodev_index_called;
static std::map<struct cras_iodev*, unsigned int> cras_alsa_iodev_index_return;
static int alsa_iodev_has_hctl_jacks_return;
static size_t snd_ctl_open_called;
static size_t snd_ctl_open_return;
static size_t snd_ctl_close_called;
static size_t snd_ctl_close_return;
static size_t snd_ctl_pcm_next_device_called;
static bool snd_ctl_pcm_next_device_return_error;
static int* snd_ctl_pcm_next_device_set_devs;
static size_t snd_ctl_pcm_next_device_set_devs_size;
static size_t snd_ctl_pcm_next_device_set_devs_index;
static size_t snd_ctl_pcm_info_called;
static int* snd_ctl_pcm_info_rets;
static size_t snd_ctl_pcm_info_rets_size;
static size_t snd_ctl_pcm_info_rets_index;
static size_t snd_ctl_card_info_called;
static int snd_ctl_card_info_ret;
static size_t snd_hctl_open_called;
static int snd_hctl_open_return_value;
static int snd_hctl_close_called;
static size_t snd_hctl_nonblock_called;
static snd_hctl_t* snd_hctl_open_pointer_val;
static size_t snd_hctl_load_called;
static int snd_hctl_load_return_value;
static struct pollfd* snd_hctl_poll_descriptors_fds;
static size_t snd_hctl_poll_descriptors_num_fds;
static size_t snd_hctl_poll_descriptors_called;
static size_t cras_system_add_select_fd_called;
static std::vector<int> cras_system_add_select_fd_values;
static size_t cras_system_rm_select_fd_called;
static std::vector<int> cras_system_rm_select_fd_values;
static size_t snd_hctl_handle_events_called;
static size_t iniparser_freedict_called;
static size_t iniparser_load_called;
static struct cras_device_blocklist* fake_blocklist;
static int cras_device_blocklist_check_retval;
static unsigned ucm_create_called;
static char ucm_create_name[100];
static unsigned ucm_destroy_called;
static size_t ucm_get_dev_for_mixer_called;
static size_t ucm_get_flag_called;
static char ucm_get_flag_name[65];
static char* device_config_dir;
static const char* cras_card_config_dir;
static struct mixer_name* ucm_get_coupled_mixer_names_return_value;
static struct mixer_name* coupled_output_names_value;
static int ucm_has_fully_specified_ucm_flag_return_value;
static int ucm_get_sections_called;
static struct mixer_name* ucm_get_main_volume_names_return_value;
static struct ucm_section* ucm_get_sections_return_value;
static size_t cras_alsa_mixer_add_controls_in_section_called;
static int cras_alsa_mixer_add_controls_in_section_return_value;
static int cras_alsa_mixer_add_main_volume_control_by_name_called;
static int cras_alsa_mixer_add_main_volume_control_by_name_return_value;
static int ucm_get_echo_reference_dev_name_for_dev_called;
static size_t cras_system_check_ignore_ucm_suffix_called;
static bool cras_system_check_ignore_ucm_suffix_value;
static const char* ucm_get_echo_reference_dev_name_for_dev_return_value[4];
static void ResetStubData() {
cras_alsa_mixer_create_called = 0;
cras_alsa_mixer_create_return = reinterpret_cast<struct cras_alsa_mixer*>(1);
cras_alsa_mixer_destroy_called = 0;
cras_alsa_iodev_destroy_arg = NULL;
cras_alsa_iodev_create_called = 0;
cras_alsa_iodev_create_return = cras_alsa_iodev_create_default_return;
cras_alsa_iodev_create_return_size =
ARRAY_SIZE(cras_alsa_iodev_create_default_return);
cras_alsa_iodev_legacy_complete_init_called = 0;
cras_alsa_iodev_ucm_add_nodes_and_jacks_called = 0;
cras_alsa_iodev_ucm_complete_init_called = 0;
cras_alsa_iodev_destroy_called = 0;
cras_alsa_iodev_index_called = 0;
cras_alsa_iodev_index_return.clear();
alsa_iodev_has_hctl_jacks_return = 1;
snd_ctl_open_called = 0;
snd_ctl_open_return = 0;
snd_ctl_close_called = 0;
snd_ctl_close_return = 0;
snd_ctl_pcm_next_device_called = 0;
snd_ctl_pcm_next_device_return_error = false;
snd_ctl_pcm_next_device_set_devs_size = 0;
snd_ctl_pcm_next_device_set_devs_index = 0;
snd_ctl_pcm_info_called = 0;
snd_ctl_pcm_info_rets_size = 0;
snd_ctl_pcm_info_rets_index = 0;
snd_ctl_card_info_called = 0;
snd_ctl_card_info_ret = 0;
snd_hctl_open_called = 0;
snd_hctl_open_return_value = 0;
snd_hctl_open_pointer_val = reinterpret_cast<snd_hctl_t*>(0x4323);
snd_hctl_load_called = 0;
snd_hctl_load_return_value = 0;
snd_hctl_close_called = 0;
snd_hctl_nonblock_called = 0;
snd_hctl_poll_descriptors_num_fds = 0;
snd_hctl_poll_descriptors_called = 0;
snd_hctl_handle_events_called = 0;
snd_hctl_poll_descriptors_num_fds = 0;
snd_hctl_poll_descriptors_called = 0;
cras_system_add_select_fd_called = 0;
cras_system_add_select_fd_values.clear();
cras_system_rm_select_fd_called = 0;
cras_system_rm_select_fd_values.clear();
iniparser_freedict_called = 0;
iniparser_load_called = 0;
fake_blocklist = reinterpret_cast<struct cras_device_blocklist*>(3);
cras_device_blocklist_check_retval = 0;
ucm_create_called = 0;
memset(ucm_create_name, 0, sizeof(ucm_get_flag_name));
ucm_destroy_called = 0;
ucm_get_dev_for_mixer_called = 0;
ucm_get_flag_called = 0;
memset(ucm_get_flag_name, 0, sizeof(ucm_get_flag_name));
device_config_dir = reinterpret_cast<char*>(3);
cras_card_config_dir = NULL;
ucm_get_coupled_mixer_names_return_value = NULL;
ucm_get_main_volume_names_return_value = NULL;
mixer_name_free(coupled_output_names_value);
coupled_output_names_value = NULL;
ucm_has_fully_specified_ucm_flag_return_value = 0;
ucm_get_sections_called = 0;
ucm_get_sections_return_value = NULL;
cras_alsa_mixer_add_controls_in_section_called = 0;
cras_alsa_mixer_add_controls_in_section_return_value = 0;
cras_alsa_mixer_add_main_volume_control_by_name_called = 0;
cras_alsa_mixer_add_main_volume_control_by_name_return_value = 0;
ucm_get_echo_reference_dev_name_for_dev_called = 0;
cras_system_check_ignore_ucm_suffix_called = 0;
cras_system_check_ignore_ucm_suffix_value = 0;
fake_dev1.nodes = NULL;
fake_dev2.nodes = NULL;
fake_dev3.nodes = NULL;
fake_dev4.nodes = NULL;
}
TEST(AlsaCard, CreateFailInvalidCard) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 55;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
}
TEST(AlsaCard, CreateFailMixerInit) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
cras_alsa_mixer_create_return = static_cast<struct cras_alsa_mixer*>(NULL);
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(1, cras_alsa_mixer_create_called);
EXPECT_EQ(0, cras_alsa_mixer_destroy_called);
}
TEST(AlsaCard, CreateFailCtlOpen) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_ctl_open_return = -1;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(1, snd_ctl_open_called);
EXPECT_EQ(0, snd_ctl_close_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
EXPECT_EQ(0, cras_alsa_mixer_create_called);
}
TEST(AlsaCard, CreateFailHctlOpen) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_hctl_open_pointer_val = NULL;
snd_hctl_open_return_value = -1;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(1, snd_ctl_open_called);
EXPECT_EQ(1, snd_ctl_close_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
EXPECT_EQ(1, snd_hctl_open_called);
EXPECT_EQ(0, snd_hctl_nonblock_called);
EXPECT_EQ(0, snd_hctl_load_called);
EXPECT_EQ(1, cras_alsa_mixer_create_called);
cras_alsa_card_destroy(c);
}
TEST(AlsaCard, CreateFailHctlLoad) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_hctl_load_return_value = -1;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(1, snd_ctl_open_called);
EXPECT_EQ(1, snd_ctl_close_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
EXPECT_EQ(1, snd_hctl_open_called);
EXPECT_EQ(1, snd_hctl_nonblock_called);
EXPECT_EQ(1, snd_hctl_load_called);
EXPECT_EQ(0, cras_alsa_mixer_create_called);
}
TEST(AlsaCard, AddSelectForHctlNoDevices) {
struct pollfd poll_fds[] = {
{3, 0, 0},
};
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_hctl_poll_descriptors_fds = poll_fds;
snd_hctl_poll_descriptors_num_fds = ARRAY_SIZE(poll_fds);
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(1, snd_ctl_open_called);
EXPECT_EQ(1, snd_ctl_close_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
EXPECT_EQ(1, snd_hctl_open_called);
EXPECT_EQ(1, snd_hctl_nonblock_called);
EXPECT_EQ(1, snd_hctl_load_called);
EXPECT_EQ(1, cras_alsa_mixer_create_called);
EXPECT_EQ(0, cras_system_add_select_fd_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(0, cras_system_rm_select_fd_called);
}
TEST(AlsaCard, AddSelectForHctlWithDevices) {
struct pollfd poll_fds[] = {
{3, 0, 0},
};
int dev_nums[] = {0};
int info_rets[] = {0, -1};
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_hctl_poll_descriptors_fds = poll_fds;
snd_hctl_poll_descriptors_num_fds = ARRAY_SIZE(poll_fds);
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(2, snd_ctl_pcm_next_device_called);
EXPECT_EQ(1, cras_alsa_iodev_create_called);
EXPECT_EQ(0, cras_alsa_iodev_index_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(1, ucm_create_called);
EXPECT_EQ(1, ucm_get_dev_for_mixer_called);
EXPECT_EQ(1, ucm_get_flag_called);
EXPECT_EQ(0, strcmp(ucm_get_flag_name, "ExtraMainVolume"));
EXPECT_EQ(cras_card_config_dir, device_config_dir);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
EXPECT_EQ(1, snd_hctl_open_called);
EXPECT_EQ(1, snd_hctl_nonblock_called);
EXPECT_EQ(1, snd_hctl_load_called);
EXPECT_EQ(1, cras_alsa_mixer_create_called);
ASSERT_EQ(1, cras_system_add_select_fd_called);
EXPECT_EQ(3, cras_system_add_select_fd_values[0]);
cras_alsa_card_destroy(c);
EXPECT_EQ(ARRAY_SIZE(poll_fds), cras_system_rm_select_fd_called);
}
TEST(AlsaCard, CreateFailCtlCardInfo) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_ctl_card_info_ret = -1;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(1, snd_ctl_open_called);
EXPECT_EQ(1, snd_ctl_close_called);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateNoDevices) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 1;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(1, snd_ctl_pcm_next_device_called);
EXPECT_EQ(0, cras_alsa_iodev_create_called);
EXPECT_EQ(0, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(1, cras_alsa_card_get_index(c));
EXPECT_EQ(0, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(0, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateOneOutputNextDevError) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_return_error = true;
card_info.card_type = ALSA_CARD_TYPE_USB;
card_info.card_index = 0;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(snd_ctl_open_called, snd_ctl_close_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateOneOutput) {
struct cras_alsa_card* c;
int dev_nums[] = {0};
int info_rets[] = {0, -1};
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
card_info.card_type = ALSA_CARD_TYPE_USB;
card_info.card_index = 0;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(2, snd_ctl_pcm_next_device_called);
EXPECT_EQ(1, cras_alsa_iodev_create_called);
EXPECT_EQ(1, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(0, cras_alsa_iodev_index_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(1, ucm_create_called);
EXPECT_EQ(1, ucm_get_dev_for_mixer_called);
EXPECT_EQ(1, ucm_get_flag_called);
EXPECT_EQ(0, strcmp(ucm_get_flag_name, "ExtraMainVolume"));
EXPECT_EQ(cras_card_config_dir, device_config_dir);
EXPECT_EQ(0, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, ucm_destroy_called);
EXPECT_EQ(1, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[0], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateOneOutputBlocklisted) {
struct cras_alsa_card* c;
int dev_nums[] = {0};
int info_rets[] = {0, -1};
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
alsa_iodev_has_hctl_jacks_return = 0;
cras_device_blocklist_check_retval = 1;
card_info.card_type = ALSA_CARD_TYPE_USB;
card_info.card_index = 0;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(2, snd_ctl_pcm_next_device_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(0, cras_alsa_iodev_create_called);
EXPECT_EQ(0, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(cras_card_config_dir, device_config_dir);
cras_alsa_card_destroy(c);
EXPECT_EQ(0, cras_alsa_iodev_destroy_called);
EXPECT_EQ(NULL, cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateTwoOutputs) {
struct cras_alsa_card* c;
int dev_nums[] = {0, 3};
int info_rets[] = {0, -1, 0};
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(3, snd_ctl_pcm_next_device_called);
EXPECT_EQ(2, cras_alsa_iodev_create_called);
EXPECT_EQ(2, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(1, cras_alsa_iodev_index_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(cras_card_config_dir, device_config_dir);
EXPECT_EQ(0, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(2, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[1], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateTwoDuplicateDeviceIndex) {
struct cras_alsa_card* c;
int dev_nums[] = {0, 0};
int info_rets[] = {0, -1, 0};
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(3, snd_ctl_pcm_next_device_called);
EXPECT_EQ(1, cras_alsa_iodev_create_called);
EXPECT_EQ(2, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(1, cras_alsa_iodev_index_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(cras_card_config_dir, device_config_dir);
EXPECT_EQ(0, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[0], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateOneInput) {
struct cras_alsa_card* c;
int dev_nums[] = {0};
int info_rets[] = {-1, 0};
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(2, snd_ctl_pcm_next_device_called);
EXPECT_EQ(1, cras_alsa_iodev_create_called);
EXPECT_EQ(1, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(0, cras_alsa_iodev_index_called);
EXPECT_EQ(cras_card_config_dir, device_config_dir);
EXPECT_EQ(0, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[0], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateOneInputAndOneOutput) {
struct cras_alsa_card* c;
int dev_nums[] = {0};
int info_rets[] = {0, 0};
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(2, snd_ctl_pcm_next_device_called);
EXPECT_EQ(2, cras_alsa_iodev_create_called);
EXPECT_EQ(2, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(0, cras_alsa_iodev_index_called);
EXPECT_EQ(cras_card_config_dir, device_config_dir);
EXPECT_EQ(0, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(2, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[1], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateOneInputAndOneOutputTwoDevices) {
struct cras_alsa_card* c;
int dev_nums[] = {0, 3};
int info_rets[] = {0, -1, -1, 0};
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(3, snd_ctl_pcm_next_device_called);
EXPECT_EQ(2, cras_alsa_iodev_create_called);
EXPECT_EQ(2, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(0, cras_alsa_iodev_index_called);
EXPECT_EQ(cras_card_config_dir, device_config_dir);
EXPECT_EQ(0, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(2, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[1], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateOneOutputWithCoupledMixers) {
struct cras_alsa_card* c;
int dev_nums[] = {0};
int info_rets[] = {0, -1};
struct mixer_name *mixer_name_1, *mixer_name_2;
/* Use strdup because cras_alsa_card_create will delete it. */
const char *name1 = strdup("MixerName1"), *name2 = strdup("MixerName2");
cras_alsa_card_info card_info;
ResetStubData();
snd_ctl_pcm_next_device_set_devs_size = ARRAY_SIZE(dev_nums);
snd_ctl_pcm_next_device_set_devs = dev_nums;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
/* Creates a list of mixer names as return value of
* ucm_get_coupled_mixer_names. */
mixer_name_1 = (struct mixer_name*)malloc(sizeof(*mixer_name_1));
mixer_name_2 = (struct mixer_name*)malloc(sizeof(*mixer_name_2));
mixer_name_1->name = name1;
mixer_name_2->name = name2;
mixer_name_1->dir = CRAS_STREAM_OUTPUT;
mixer_name_2->dir = CRAS_STREAM_OUTPUT;
mixer_name_1->type = MIXER_NAME_VOLUME;
mixer_name_2->type = MIXER_NAME_VOLUME;
DL_APPEND(ucm_get_coupled_mixer_names_return_value, mixer_name_1);
DL_APPEND(ucm_get_coupled_mixer_names_return_value, mixer_name_2);
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(2, snd_ctl_pcm_next_device_called);
EXPECT_EQ(1, cras_alsa_iodev_create_called);
EXPECT_EQ(1, cras_alsa_iodev_legacy_complete_init_called);
EXPECT_EQ(0, cras_alsa_iodev_index_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(1, ucm_create_called);
EXPECT_EQ(1, ucm_get_dev_for_mixer_called);
EXPECT_EQ(1, ucm_get_flag_called);
EXPECT_EQ(0, strcmp(ucm_get_flag_name, "ExtraMainVolume"));
EXPECT_EQ(cras_card_config_dir, device_config_dir);
EXPECT_EQ(0, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
/* Checks cras_alsa_card_create can handle the list and pass the names to
* cras_alsa_mixer_create. */
struct mixer_name* m_name = coupled_output_names_value;
EXPECT_EQ(0, m_name ? strcmp(m_name->name, "MixerName1") : 1);
if (m_name)
m_name = m_name->next;
EXPECT_EQ(0, m_name ? strcmp(m_name->name, "MixerName2") : 1);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, ucm_destroy_called);
EXPECT_EQ(1, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[0], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
mixer_name_free(coupled_output_names_value);
coupled_output_names_value = NULL;
}
TEST(AlsaCard, CreateFullyUCMNoSections) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
ucm_has_fully_specified_ucm_flag_return_value = 1;
ucm_get_sections_return_value = NULL;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(0, cras_alsa_iodev_create_called);
EXPECT_EQ(0, cras_alsa_iodev_ucm_complete_init_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(1, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, ucm_destroy_called);
EXPECT_EQ(0, cras_alsa_iodev_destroy_called);
EXPECT_EQ(NULL, cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateFullyUCMTwoMainVolume) {
struct cras_alsa_card* c;
struct mixer_name *mixer_name_1, *mixer_name_2;
const char *name1 = strdup("MixerName1"), *name2 = strdup("MixerName2");
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
ucm_has_fully_specified_ucm_flag_return_value = 1;
/* Creates a list of mixer names as return value of
* ucm_get_main_volume_names_return_value. */
mixer_name_1 = (struct mixer_name*)malloc(sizeof(*mixer_name_1));
mixer_name_2 = (struct mixer_name*)malloc(sizeof(*mixer_name_2));
mixer_name_1->name = name1;
mixer_name_2->name = name2;
mixer_name_1->dir = CRAS_STREAM_OUTPUT;
mixer_name_2->dir = CRAS_STREAM_OUTPUT;
mixer_name_1->type = MIXER_NAME_MAIN_VOLUME;
mixer_name_2->type = MIXER_NAME_MAIN_VOLUME;
DL_APPEND(ucm_get_main_volume_names_return_value, mixer_name_1);
DL_APPEND(ucm_get_main_volume_names_return_value, mixer_name_2);
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(0, cras_alsa_iodev_create_called);
EXPECT_EQ(0, cras_alsa_iodev_ucm_complete_init_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(1, cras_alsa_mixer_add_main_volume_control_by_name_called);
EXPECT_EQ(1, ucm_get_sections_called);
EXPECT_EQ(0, cras_alsa_mixer_add_controls_in_section_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, ucm_destroy_called);
EXPECT_EQ(0, cras_alsa_iodev_destroy_called);
EXPECT_EQ(NULL, cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, TwoUCMSecionsDependentPCM) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
struct ucm_section* sections = NULL;
struct ucm_section* section;
/* Create UCM so that MIC1 and MIC2 will be two nodes on the same iodev. */
section = ucm_section_create("MIC1", "hw:0,3", 0, -1, CRAS_STREAM_INPUT,
"my-sound-card Headset Jack", "gpio");
DL_APPEND(sections, section);
section = ucm_section_create("MIC2", "hw:0,5", 0, 3, CRAS_STREAM_INPUT,
"my-sound-card Headset Jack", "gpio");
DL_APPEND(sections, section);
ResetStubData();
int info_rets[] = {0, 0};
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
ucm_has_fully_specified_ucm_flag_return_value = 1;
ucm_get_sections_return_value = sections;
ASSERT_NE(ucm_get_sections_return_value, (struct ucm_section*)NULL);
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(1, ucm_get_sections_called);
EXPECT_EQ(1, snd_ctl_pcm_info_called);
EXPECT_EQ(2, cras_alsa_mixer_add_controls_in_section_called);
EXPECT_EQ(1, cras_alsa_iodev_create_called);
EXPECT_EQ(2, cras_alsa_iodev_ucm_add_nodes_and_jacks_called);
EXPECT_EQ(1, cras_alsa_iodev_ucm_complete_init_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, ucm_destroy_called);
EXPECT_EQ(1, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[0], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
struct ucm_section* GenerateUcmSections(void) {
struct ucm_section* sections = NULL;
struct ucm_section* section;
section = ucm_section_create("Headphone", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT,
"my-sound-card Headset Jack", "gpio");
ucm_section_add_coupled(section, "HP-L", MIXER_NAME_VOLUME);
ucm_section_add_coupled(section, "HP-R", MIXER_NAME_VOLUME);
DL_APPEND(sections, section);
section = ucm_section_create("Speaker", "hw:0,1", 0, -1, CRAS_STREAM_OUTPUT,
NULL, NULL);
ucm_section_add_coupled(section, "SPK-L", MIXER_NAME_VOLUME);
ucm_section_add_coupled(section, "SPK-R", MIXER_NAME_VOLUME);
DL_APPEND(sections, section);
section = ucm_section_create("Internal Mic", "hw:0,1", 0, -1,
CRAS_STREAM_INPUT, NULL, NULL);
ucm_section_add_coupled(section, "INT-MIC-L", MIXER_NAME_VOLUME);
ucm_section_add_coupled(section, "INT-MIC-R", MIXER_NAME_VOLUME);
DL_APPEND(sections, section);
section = ucm_section_create("Mic", "hw:0,1", 1, -1, CRAS_STREAM_INPUT,
"my-sound-card Headset Jack", "gpio");
ucm_section_add_coupled(section, "MIC-L", MIXER_NAME_VOLUME);
ucm_section_add_coupled(section, "MIC-R", MIXER_NAME_VOLUME);
DL_APPEND(sections, section);
section = ucm_section_create("HDMI", "hw:0,1", 2, -1, CRAS_STREAM_OUTPUT,
NULL, NULL);
ucm_section_set_mixer_name(section, "HDMI");
DL_APPEND(sections, section);
return sections;
}
TEST(AlsaCard, CreateFullyUCMFailureOnControls) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
ucm_has_fully_specified_ucm_flag_return_value = 1;
ucm_get_sections_return_value = GenerateUcmSections();
ASSERT_NE(ucm_get_sections_return_value, (struct ucm_section*)NULL);
cras_alsa_mixer_add_controls_in_section_return_value = -EINVAL;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_EQ(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(1, ucm_get_sections_called);
EXPECT_EQ(1, cras_alsa_mixer_add_controls_in_section_called);
EXPECT_EQ(0, cras_alsa_iodev_create_called);
EXPECT_EQ(0, cras_alsa_iodev_ucm_complete_init_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, ucm_destroy_called);
EXPECT_EQ(0, cras_alsa_iodev_destroy_called);
EXPECT_EQ(NULL, cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, CreateFullyUCMFourDevicesFiveSections) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
int info_rets[] = {0, 0, 0, 0, 0, -1};
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
ucm_has_fully_specified_ucm_flag_return_value = 1;
ucm_get_sections_return_value = GenerateUcmSections();
cras_alsa_iodev_index_return[cras_alsa_iodev_create_return[0]] = 0;
cras_alsa_iodev_index_return[cras_alsa_iodev_create_return[1]] = 0;
cras_alsa_iodev_index_return[cras_alsa_iodev_create_return[2]] = 1;
cras_alsa_iodev_index_return[cras_alsa_iodev_create_return[3]] = 2;
ASSERT_NE(ucm_get_sections_return_value, (struct ucm_section*)NULL);
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(snd_ctl_close_called, snd_ctl_open_called);
EXPECT_EQ(1, snd_ctl_card_info_called);
EXPECT_EQ(1, ucm_get_sections_called);
EXPECT_EQ(5, snd_ctl_pcm_info_called);
EXPECT_EQ(5, cras_alsa_mixer_add_controls_in_section_called);
EXPECT_EQ(4, cras_alsa_iodev_create_called);
EXPECT_EQ(5, cras_alsa_iodev_ucm_add_nodes_and_jacks_called);
EXPECT_EQ(4, cras_alsa_iodev_ucm_complete_init_called);
cras_alsa_card_destroy(c);
EXPECT_EQ(1, ucm_destroy_called);
EXPECT_EQ(4, cras_alsa_iodev_destroy_called);
EXPECT_EQ(cras_alsa_iodev_create_return[3], cras_alsa_iodev_destroy_arg);
EXPECT_EQ(cras_alsa_mixer_create_called, cras_alsa_mixer_destroy_called);
EXPECT_EQ(iniparser_load_called, iniparser_freedict_called);
}
TEST(AlsaCard, GG) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
int info_rets[] = {0, 0, 0, 0, 0, -1};
struct cras_ionode nodes[4];
const char* echo_ref = "echo ref";
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
ucm_has_fully_specified_ucm_flag_return_value = 1;
ucm_get_sections_return_value = GenerateUcmSections();
fake_dev1.nodes = nodes;
fake_dev2.nodes = nodes + 1;
fake_dev3.nodes = nodes + 2;
fake_dev4.nodes = nodes + 3;
snprintf(nodes[0].name, CRAS_NODE_NAME_BUFFER_SIZE, "dev1");
snprintf(nodes[1].name, CRAS_NODE_NAME_BUFFER_SIZE, "dev2");
snprintf(nodes[2].name, CRAS_NODE_NAME_BUFFER_SIZE, "dev3");
snprintf(nodes[3].name, CRAS_NODE_NAME_BUFFER_SIZE, "echo ref");
ucm_get_echo_reference_dev_name_for_dev_return_value[0] = strdup(echo_ref);
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
NULL);
EXPECT_NE(static_cast<struct cras_alsa_card*>(NULL), c);
EXPECT_EQ(fake_dev1.echo_reference_dev, &fake_dev4);
cras_alsa_card_destroy(c);
}
TEST(AlsaCard, UCMSuffix) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
int info_rets[] = {0, 0, 0, 0, 0, -1};
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
ucm_has_fully_specified_ucm_flag_return_value = 1;
ucm_get_sections_return_value = GenerateUcmSections();
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
"1mic");
EXPECT_EQ(0, strcmp(ucm_create_name, "TestName.1mic"));
EXPECT_EQ(1, cras_system_check_ignore_ucm_suffix_called);
cras_alsa_card_destroy(c);
}
TEST(AlsaCard, UCMIgnoreSuffix) {
struct cras_alsa_card* c;
cras_alsa_card_info card_info;
int info_rets[] = {0, 0, 0, 0, 0, -1};
ResetStubData();
card_info.card_type = ALSA_CARD_TYPE_INTERNAL;
card_info.card_index = 0;
snd_ctl_pcm_info_rets_size = ARRAY_SIZE(info_rets);
snd_ctl_pcm_info_rets = info_rets;
ucm_has_fully_specified_ucm_flag_return_value = 1;
ucm_get_sections_return_value = GenerateUcmSections();
cras_system_check_ignore_ucm_suffix_value = true;
c = cras_alsa_card_create(&card_info, device_config_dir, fake_blocklist,
"1mic");
EXPECT_EQ(0, strcmp(ucm_create_name, "TestName"));
EXPECT_EQ(1, cras_system_check_ignore_ucm_suffix_called);
cras_alsa_card_destroy(c);
}
/* Stubs */
extern "C" {
struct cras_alsa_mixer* cras_alsa_mixer_create(const char* card_name) {
cras_alsa_mixer_create_called++;
return cras_alsa_mixer_create_return;
}
int cras_alsa_mixer_add_controls_by_name_matching(
struct cras_alsa_mixer* cmix,
struct mixer_name* extra_controls,
struct mixer_name* coupled_controls) {
/* Duplicate coupled_output_names to verify in the end of unittest
* because names will get freed later in cras_alsa_card_create. */
struct mixer_name* control;
DL_FOREACH (coupled_controls, control) {
coupled_output_names_value =
mixer_name_add(coupled_output_names_value, control->name,
CRAS_STREAM_OUTPUT, control->type);
}
return 0;
}
void cras_alsa_mixer_destroy(struct cras_alsa_mixer* cras_mixer) {
cras_alsa_mixer_destroy_called++;
}
struct cras_iodev* alsa_iodev_create(size_t card_index,
const char* card_name,
size_t device_index,
const char* pcm_name,
const char* dev_name,
const char* dev_id,
enum CRAS_ALSA_CARD_TYPE card_type,
int is_first,
struct cras_alsa_mixer* mixer,
const struct cras_card_config* config,
struct cras_use_case_mgr* ucm,
snd_hctl_t* hctl,
enum CRAS_STREAM_DIRECTION direction,
size_t usb_vid,
size_t usb_pid,
char* usb_serial_number) {
struct cras_iodev* result = NULL;
if (cras_alsa_iodev_create_called < cras_alsa_iodev_create_return_size)
result = cras_alsa_iodev_create_return[cras_alsa_iodev_create_called];
cras_alsa_iodev_create_called++;
return result;
}
void alsa_iodev_destroy(struct cras_iodev* iodev) {
cras_alsa_iodev_destroy_called++;
cras_alsa_iodev_destroy_arg = iodev;
}
int alsa_iodev_legacy_complete_init(struct cras_iodev* iodev) {
cras_alsa_iodev_legacy_complete_init_called++;
return 0;
}
int alsa_iodev_ucm_add_nodes_and_jacks(struct cras_iodev* iodev,
struct ucm_section* section) {
cras_alsa_iodev_ucm_add_nodes_and_jacks_called++;
return 0;
}
void alsa_iodev_ucm_complete_init(struct cras_iodev* iodev) {
cras_alsa_iodev_ucm_complete_init_called++;
}
unsigned alsa_iodev_index(struct cras_iodev* iodev) {
std::map<struct cras_iodev*, unsigned int>::iterator i;
cras_alsa_iodev_index_called++;
i = cras_alsa_iodev_index_return.find(iodev);
if (i != cras_alsa_iodev_index_return.end())
return i->second;
return 0;
}
int alsa_iodev_has_hctl_jacks(struct cras_iodev* iodev) {
return alsa_iodev_has_hctl_jacks_return;
}
size_t snd_pcm_info_sizeof() {
return 10;
}
size_t snd_ctl_card_info_sizeof() {
return 10;
}
int snd_ctl_open(snd_ctl_t** handle, const char* name, int card) {
snd_ctl_open_called++;
if (snd_ctl_open_return == 0)
*handle = reinterpret_cast<snd_ctl_t*>(0xff);
else
*handle = NULL;
return snd_ctl_open_return;
}
int snd_ctl_close(snd_ctl_t* handle) {
snd_ctl_close_called++;
return snd_ctl_close_return;
}
int snd_ctl_pcm_next_device(snd_ctl_t* ctl, int* device) {
if (snd_ctl_pcm_next_device_return_error) {
*device = 10;
return -1;
}
snd_ctl_pcm_next_device_called++;
if (snd_ctl_pcm_next_device_set_devs_index >=
snd_ctl_pcm_next_device_set_devs_size) {
*device = -1;
return 0;
}
*device =
snd_ctl_pcm_next_device_set_devs[snd_ctl_pcm_next_device_set_devs_index];
snd_ctl_pcm_next_device_set_devs_index++;
return 0;
}
void snd_pcm_info_set_device(snd_pcm_info_t* obj, unsigned int val) {}
void snd_pcm_info_set_subdevice(snd_pcm_info_t* obj, unsigned int val) {}
void snd_pcm_info_set_stream(snd_pcm_info_t* obj, snd_pcm_stream_t val) {}
const char* snd_pcm_info_get_name(const snd_pcm_info_t* obj) {
return "Fake device name";
}
const char* snd_pcm_info_get_id(const snd_pcm_info_t* obj) {
return "Fake device id";
}
int snd_ctl_pcm_info(snd_ctl_t* ctl, snd_pcm_info_t* info) {
int ret;
snd_ctl_pcm_info_called++;
if (snd_ctl_pcm_info_rets_index >= snd_ctl_pcm_info_rets_size) {
return -1;
}
ret = snd_ctl_pcm_info_rets[snd_ctl_pcm_info_rets_index];
snd_ctl_pcm_info_rets_index++;
return ret;
}
int snd_ctl_card_info(snd_ctl_t* ctl, snd_ctl_card_info_t* info) {
snd_ctl_card_info_called++;
return snd_ctl_card_info_ret;
}
const char* snd_ctl_card_info_get_name(const snd_ctl_card_info_t* obj) {
return "TestName";
}
const char* snd_ctl_card_info_get_id(const snd_ctl_card_info_t* obj) {
return "TestId";
}
int snd_hctl_open(snd_hctl_t** hctlp, const char* name, int mode) {
*hctlp = snd_hctl_open_pointer_val;
snd_hctl_open_called++;
return snd_hctl_open_return_value;
}
int snd_hctl_nonblock(snd_hctl_t* hctl, int nonblock) {
snd_hctl_nonblock_called++;
return 0;
}
int snd_hctl_load(snd_hctl_t* hctl) {
snd_hctl_load_called++;
return snd_hctl_load_return_value;
}
int snd_hctl_close(snd_hctl_t* hctl) {
snd_hctl_close_called++;
return 0;
}
int snd_hctl_poll_descriptors_count(snd_hctl_t* hctl) {
return snd_hctl_poll_descriptors_num_fds;
}
int snd_hctl_poll_descriptors(snd_hctl_t* hctl,
struct pollfd* pfds,
unsigned int space) {
unsigned int num = MIN(space, snd_hctl_poll_descriptors_num_fds);
memcpy(pfds, snd_hctl_poll_descriptors_fds, num * sizeof(*pfds));
snd_hctl_poll_descriptors_called++;
return num;
}
int snd_hctl_handle_events(snd_hctl_t* hctl) {
snd_hctl_handle_events_called++;
return 0;
}
int cras_system_add_select_fd(int fd,
void (*callback)(void* data),
void* callback_data) {
cras_system_add_select_fd_called++;
cras_system_add_select_fd_values.push_back(fd);
return 0;
}
void cras_system_rm_select_fd(int fd) {
cras_system_rm_select_fd_called++;
cras_system_rm_select_fd_values.push_back(fd);
}
struct cras_card_config* cras_card_config_create(const char* config_path,
const char* card_name) {
cras_card_config_dir = config_path;
return NULL;
}
void cras_card_config_destroy(struct cras_card_config* card_config) {}
struct cras_volume_curve* cras_card_config_get_volume_curve_for_control(
const struct cras_card_config* card_config,
const char* control_name) {
return NULL;
}
int cras_device_blocklist_check(struct cras_device_blocklist* blocklist,
unsigned vendor_id,
unsigned product_id,
unsigned device_index) {
EXPECT_EQ(fake_blocklist, blocklist);
return cras_device_blocklist_check_retval;
}
struct cras_use_case_mgr* ucm_create(const char* name) {
ucm_create_called++;
strncpy(ucm_create_name, name, sizeof(ucm_create_name) - 1);
return reinterpret_cast<struct cras_use_case_mgr*>(0x44);
}
void ucm_destroy(struct cras_use_case_mgr* mgr) {
ucm_destroy_called++;
}
char* ucm_get_dev_for_mixer(struct cras_use_case_mgr* mgr,
const char* mixer,
enum CRAS_STREAM_DIRECTION dir) {
ucm_get_dev_for_mixer_called++;
return strdup("device");
}
char* ucm_get_flag(struct cras_use_case_mgr* mgr, const char* flag_name) {
ucm_get_flag_called++;
strncpy(ucm_get_flag_name, flag_name, sizeof(ucm_get_flag_name) - 1);
return NULL;
}
struct mixer_name* ucm_get_coupled_mixer_names(struct cras_use_case_mgr* mgr,
const char* dev) {
return ucm_get_coupled_mixer_names_return_value;
}
int ucm_has_fully_specified_ucm_flag(struct cras_use_case_mgr* mgr) {
return ucm_has_fully_specified_ucm_flag_return_value;
}
struct mixer_name* ucm_get_main_volume_names(struct cras_use_case_mgr* mgr) {
return ucm_get_main_volume_names_return_value;
}
struct ucm_section* ucm_get_sections(struct cras_use_case_mgr* mgr) {
ucm_get_sections_called++;
return ucm_get_sections_return_value;
}
const char* ucm_get_echo_reference_dev_name_for_dev(
struct cras_use_case_mgr* mgr,
const char* dev) {
int idx = ucm_get_echo_reference_dev_name_for_dev_called++;
return ucm_get_echo_reference_dev_name_for_dev_return_value[idx];
}
int cras_alsa_mixer_add_main_volume_control_by_name(
struct cras_alsa_mixer* cmix,
struct mixer_name* mixer_names) {
cras_alsa_mixer_add_main_volume_control_by_name_called++;
return cras_alsa_mixer_add_main_volume_control_by_name_return_value;
}
int cras_alsa_mixer_add_controls_in_section(struct cras_alsa_mixer* cmix,
struct ucm_section* section) {
cras_alsa_mixer_add_controls_in_section_called++;
return cras_alsa_mixer_add_controls_in_section_return_value;
}
bool cras_system_check_ignore_ucm_suffix(const char* card_name) {
cras_system_check_ignore_ucm_suffix_called++;
return cras_system_check_ignore_ucm_suffix_value;
}
void ucm_free_mixer_names(struct mixer_name* names) {
struct mixer_name* m;
DL_FOREACH (names, m) {
DL_DELETE(names, m);
free((void*)m->name);
free(m);
}
}
} /* extern "C" */
} // namespace
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
openlog(NULL, LOG_PERROR, LOG_USER);
return RUN_ALL_TESTS();
}