blob: c16dc52d91b1b4cc6ba87e858f806ef35c13e6d2 [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 <stdio.h>
#include <gtest/gtest.h>
#include <unistd.h>
extern "C" {
#include "audio_thread.h"
#include "cras_messages.h"
#include "cras_rclient.h"
#include "cras_rstream.h"
#include "cras_system_state.h"
}
// Stub data.
static int cras_rstream_create_return;
static struct cras_rstream *cras_rstream_create_stream_out;
static int cras_iodev_attach_stream_retval;
static size_t cras_system_set_volume_value;
static int cras_system_set_volume_called;
static size_t cras_system_set_capture_gain_value;
static int cras_system_set_capture_gain_called;
static size_t cras_system_set_mute_value;
static int cras_system_set_mute_called;
static size_t cras_system_set_user_mute_value;
static int cras_system_set_user_mute_called;
static size_t cras_system_set_mute_locked_value;
static int cras_system_set_mute_locked_called;
static size_t cras_system_set_capture_mute_value;
static int cras_system_set_capture_mute_called;
static size_t cras_system_set_capture_mute_locked_value;
static int cras_system_set_capture_mute_locked_called;
static size_t cras_make_fd_nonblocking_called;
static audio_thread* iodev_get_thread_return;
static int stream_list_add_stream_return;
static unsigned int stream_list_add_stream_called;
static unsigned int stream_list_disconnect_stream_called;
static unsigned int cras_iodev_list_rm_input_called;
static unsigned int cras_iodev_list_rm_output_called;
static struct cras_rstream dummy_rstream;
void ResetStubData() {
cras_rstream_create_return = 0;
cras_rstream_create_stream_out = (struct cras_rstream *)NULL;
cras_iodev_attach_stream_retval = 0;
cras_system_set_volume_value = 0;
cras_system_set_volume_called = 0;
cras_system_set_capture_gain_value = 0;
cras_system_set_capture_gain_called = 0;
cras_system_set_mute_value = 0;
cras_system_set_mute_called = 0;
cras_system_set_user_mute_value = 0;
cras_system_set_user_mute_called = 0;
cras_system_set_mute_locked_value = 0;
cras_system_set_mute_locked_called = 0;
cras_system_set_capture_mute_value = 0;
cras_system_set_capture_mute_called = 0;
cras_system_set_capture_mute_locked_value = 0;
cras_system_set_capture_mute_locked_called = 0;
cras_make_fd_nonblocking_called = 0;
iodev_get_thread_return = reinterpret_cast<audio_thread*>(0xad);
stream_list_add_stream_return = 0;
stream_list_add_stream_called = 0;
stream_list_disconnect_stream_called = 0;
cras_iodev_list_rm_output_called = 0;
cras_iodev_list_rm_input_called = 0;
}
namespace {
TEST(RClientSuite, CreateSendMessage) {
struct cras_rclient *rclient;
int rc;
struct cras_client_connected msg;
int pipe_fds[2];
ResetStubData();
rc = pipe(pipe_fds);
ASSERT_EQ(0, rc);
rclient = cras_rclient_create(pipe_fds[1], 800);
ASSERT_NE((void *)NULL, rclient);
rc = read(pipe_fds[0], &msg, sizeof(msg));
EXPECT_EQ(sizeof(msg), rc);
EXPECT_EQ(CRAS_CLIENT_CONNECTED, msg.header.id);
EXPECT_EQ(CRAS_CLIENT_CONNECTED, msg.header.id);
cras_rclient_destroy(rclient);
close(pipe_fds[0]);
close(pipe_fds[1]);
}
class RClientMessagesSuite : public testing::Test {
protected:
virtual void SetUp() {
int rc;
struct cras_client_connected msg;
rc = pipe(pipe_fds_);
if (rc < 0)
return;
rclient_ = cras_rclient_create(pipe_fds_[1], 800);
rc = read(pipe_fds_[0], &msg, sizeof(msg));
if (rc < 0)
return;
rstream_ = (struct cras_rstream *)calloc(1, sizeof(*rstream_));
stream_id_ = 0x10002;
connect_msg_.header.id = CRAS_SERVER_CONNECT_STREAM;
connect_msg_.header.length = sizeof(connect_msg_);
connect_msg_.stream_type = CRAS_STREAM_TYPE_DEFAULT;
connect_msg_.direction = CRAS_STREAM_OUTPUT;
connect_msg_.stream_id = stream_id_;
connect_msg_.buffer_frames = 480;
connect_msg_.cb_threshold = 240;
connect_msg_.flags = 0;
connect_msg_.format.num_channels = 2;
connect_msg_.format.frame_rate = 48000;
connect_msg_.format.format = SND_PCM_FORMAT_S16_LE;
connect_msg_.dev_idx = NO_DEVICE;
ResetStubData();
}
virtual void TearDown() {
cras_rclient_destroy(rclient_);
free(rstream_);
close(pipe_fds_[0]);
close(pipe_fds_[1]);
}
struct cras_connect_message connect_msg_;
struct cras_rclient *rclient_;
struct cras_rstream *rstream_;
size_t stream_id_;
int pipe_fds_[2];
};
TEST_F(RClientMessagesSuite, AudThreadAttachFail) {
struct cras_client_stream_connected out_msg;
int rc;
cras_rstream_create_stream_out = rstream_;
stream_list_add_stream_return = -EINVAL;
rc = cras_rclient_message_from_client(rclient_, &connect_msg_.header, 100);
EXPECT_EQ(0, rc);
rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg));
EXPECT_EQ(sizeof(out_msg), rc);
EXPECT_EQ(stream_id_, out_msg.stream_id);
EXPECT_NE(0, out_msg.err);
EXPECT_EQ(0, cras_iodev_list_rm_output_called);
EXPECT_EQ(1, stream_list_add_stream_called);
EXPECT_EQ(0, stream_list_disconnect_stream_called);
}
TEST_F(RClientMessagesSuite, ConnectMsgWithBadFd) {
struct cras_client_stream_connected out_msg;
int rc;
rc = cras_rclient_message_from_client(rclient_, &connect_msg_.header, -1);
EXPECT_EQ(0, rc);
rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg));
EXPECT_EQ(sizeof(out_msg), rc);
EXPECT_EQ(stream_id_, out_msg.stream_id);
EXPECT_NE(0, out_msg.err);
EXPECT_EQ(stream_list_add_stream_called,
stream_list_disconnect_stream_called);
}
TEST_F(RClientMessagesSuite, SuccessReply) {
struct cras_client_stream_connected out_msg;
int rc;
cras_rstream_create_stream_out = rstream_;
cras_iodev_attach_stream_retval = 0;
rc = cras_rclient_message_from_client(rclient_, &connect_msg_.header, 100);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_make_fd_nonblocking_called);
rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg));
EXPECT_EQ(sizeof(out_msg), rc);
EXPECT_EQ(stream_id_, out_msg.stream_id);
EXPECT_EQ(0, out_msg.err);
EXPECT_EQ(1, stream_list_add_stream_called);
EXPECT_EQ(0, stream_list_disconnect_stream_called);
}
TEST_F(RClientMessagesSuite, SuccessCreateThreadReply) {
struct cras_client_stream_connected out_msg;
int rc;
cras_rstream_create_stream_out = rstream_;
cras_iodev_attach_stream_retval = 0;
rc = cras_rclient_message_from_client(rclient_, &connect_msg_.header, 100);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_make_fd_nonblocking_called);
rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg));
EXPECT_EQ(sizeof(out_msg), rc);
EXPECT_EQ(stream_id_, out_msg.stream_id);
EXPECT_EQ(0, out_msg.err);
EXPECT_EQ(1, stream_list_add_stream_called);
EXPECT_EQ(0, stream_list_disconnect_stream_called);
}
TEST_F(RClientMessagesSuite, SetVolume) {
struct cras_set_system_volume msg;
int rc;
msg.header.id = CRAS_SERVER_SET_SYSTEM_VOLUME;
msg.header.length = sizeof(msg);
msg.volume = 66;
rc = cras_rclient_message_from_client(rclient_, &msg.header, -1);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_system_set_volume_called);
EXPECT_EQ(66, cras_system_set_volume_value);
}
TEST_F(RClientMessagesSuite, SetCaptureVolume) {
struct cras_set_system_volume msg;
int rc;
msg.header.id = CRAS_SERVER_SET_SYSTEM_CAPTURE_GAIN;
msg.header.length = sizeof(msg);
msg.volume = 66;
rc = cras_rclient_message_from_client(rclient_, &msg.header, -1);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_system_set_capture_gain_called);
EXPECT_EQ(66, cras_system_set_capture_gain_value);
}
TEST_F(RClientMessagesSuite, SetMute) {
struct cras_set_system_mute msg;
int rc;
msg.header.id = CRAS_SERVER_SET_SYSTEM_MUTE;
msg.header.length = sizeof(msg);
msg.mute = 1;
rc = cras_rclient_message_from_client(rclient_, &msg.header, -1);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_system_set_mute_called);
EXPECT_EQ(1, cras_system_set_mute_value);
msg.header.id = CRAS_SERVER_SET_SYSTEM_MUTE_LOCKED;
rc = cras_rclient_message_from_client(rclient_, &msg.header, -1);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_system_set_mute_locked_called);
EXPECT_EQ(1, cras_system_set_mute_locked_value);
}
TEST_F(RClientMessagesSuite, SetUserMute) {
struct cras_set_system_mute msg;
int rc;
msg.header.id = CRAS_SERVER_SET_USER_MUTE;
msg.header.length = sizeof(msg);
msg.mute = 1;
rc = cras_rclient_message_from_client(rclient_, &msg.header, -1);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_system_set_user_mute_called);
EXPECT_EQ(1, cras_system_set_user_mute_value);
}
TEST_F(RClientMessagesSuite, SetCaptureMute) {
struct cras_set_system_mute msg;
int rc;
msg.header.id = CRAS_SERVER_SET_SYSTEM_CAPTURE_MUTE;
msg.header.length = sizeof(msg);
msg.mute = 1;
rc = cras_rclient_message_from_client(rclient_, &msg.header, -1);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_system_set_capture_mute_called);
EXPECT_EQ(1, cras_system_set_capture_mute_value);
msg.header.id = CRAS_SERVER_SET_SYSTEM_CAPTURE_MUTE_LOCKED;
rc = cras_rclient_message_from_client(rclient_, &msg.header, -1);
EXPECT_EQ(0, rc);
EXPECT_EQ(1, cras_system_set_capture_mute_locked_called);
EXPECT_EQ(1, cras_system_set_capture_mute_locked_value);
}
} // namespace
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
/* stubs */
extern "C" {
struct audio_thread* cras_iodev_list_get_audio_thread() {
return iodev_get_thread_return;
}
void cras_iodev_list_add_active_node(enum CRAS_STREAM_DIRECTION dir,
cras_node_id_t node_id)
{
}
void cras_iodev_list_rm_active_node(enum CRAS_STREAM_DIRECTION dir,
cras_node_id_t node_id)
{
}
int audio_thread_rm_stream(audio_thread* thread,
cras_rstream* stream) {
return 0;
}
void audio_thread_add_output_dev(struct audio_thread *thread,
struct cras_iodev *odev)
{
}
int audio_thread_dump_thread_info(struct audio_thread *thread,
struct audio_debug_info *info)
{
return 0;
}
int audio_thread_suspend(struct audio_thread *thread)
{
return 0;
}
int audio_thread_resume(struct audio_thread *thread)
{
return 0;
}
const char *cras_config_get_socket_file_dir()
{
return "/tmp";
}
int cras_rstream_create(struct cras_rstream_config *stream_config,
struct cras_rstream **stream_out)
{
*stream_out = cras_rstream_create_stream_out;
return cras_rstream_create_return;
}
int cras_iodev_move_stream_type(uint32_t type, uint32_t index)
{
return 0;
}
int cras_iodev_list_rm_output(struct cras_iodev *output) {
cras_iodev_list_rm_output_called++;
return 0;
}
int cras_iodev_list_rm_input(struct cras_iodev *input) {
cras_iodev_list_rm_input_called++;
return 0;
}
int cras_server_disconnect_from_client_socket(int socket_fd) {
return 0;
}
int cras_make_fd_nonblocking(int fd)
{
cras_make_fd_nonblocking_called++;
return 0;
}
void cras_system_set_volume(size_t volume)
{
cras_system_set_volume_value = volume;
cras_system_set_volume_called++;
}
void cras_system_set_capture_gain(long gain)
{
cras_system_set_capture_gain_value = gain;
cras_system_set_capture_gain_called++;
}
// From system_state.
void cras_system_set_mute(int mute)
{
cras_system_set_mute_value = mute;
cras_system_set_mute_called++;
}
void cras_system_set_user_mute(int mute)
{
cras_system_set_user_mute_value = mute;
cras_system_set_user_mute_called++;
}
void cras_system_set_mute_locked(int mute)
{
cras_system_set_mute_locked_value = mute;
cras_system_set_mute_locked_called++;
}
void cras_system_set_capture_mute(int mute)
{
cras_system_set_capture_mute_value = mute;
cras_system_set_capture_mute_called++;
}
void cras_system_set_capture_mute_locked(int mute)
{
cras_system_set_capture_mute_locked_value = mute;
cras_system_set_capture_mute_locked_called++;
}
int cras_system_remove_alsa_card(size_t alsa_card_index)
{
return -1;
}
void cras_system_set_suspended(int suspended) {
}
struct cras_server_state *cras_system_state_get_no_lock()
{
return NULL;
}
key_t cras_sys_state_shm_key()
{
return 1;
}
void cras_dsp_reload_ini()
{
}
void cras_dsp_dump_info()
{
}
int cras_iodev_list_set_node_attr(int dev_index, int node_index,
enum ionode_attr attr, int value)
{
return 0;
}
void cras_iodev_list_select_node(enum CRAS_STREAM_DIRECTION direction,
cras_node_id_t node_id)
{
}
void cras_iodev_list_add_test_dev(enum TEST_IODEV_TYPE type) {
}
struct stream_list *cras_iodev_list_get_stream_list()
{
return NULL;
}
/* Handles sending a command to a test iodev. */
void cras_iodev_list_test_dev_command(unsigned int iodev_idx,
enum CRAS_TEST_IODEV_CMD command,
unsigned int data_len,
const uint8_t *data) {
}
int stream_list_add(struct stream_list *list,
struct cras_rstream_config *config,
struct cras_rstream **stream)
{
int ret;
*stream = &dummy_rstream;
stream_list_add_stream_called++;
ret = stream_list_add_stream_return;
if (ret)
stream_list_add_stream_return = -EINVAL;
dummy_rstream.direction = config->direction;
dummy_rstream.stream_id = config->stream_id;
return ret;
}
struct cras_rstream *stream_list_rm(struct stream_list *list,
cras_stream_id_t id)
{
stream_list_disconnect_stream_called++;
return NULL;
}
struct cras_rstream *stream_list_rm_all_client_streams(
struct stream_list *list, struct cras_rclient *rclient)
{
return NULL;
}
} // extern "C"