| // 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 <unistd.h> |
| |
| extern "C" { |
| #include "audio_thread.h" |
| #include "cras_bt_log.h" |
| #include "cras_main_thread_log.h" |
| #include "cras_messages.h" |
| #include "cras_rclient.h" |
| #include "cras_rstream.h" |
| #include "cras_system_state.h" |
| |
| // Access to data structures and static functions. |
| #include "cras_control_rclient.c" |
| #include "cras_rclient_util.c" |
| } |
| |
| // Stub data. |
| static int audio_thread_config_global_remix_called; |
| static float audio_thread_config_global_remix_copy[CRAS_MAX_REMIX_CHANNELS * |
| CRAS_MAX_REMIX_CHANNELS]; |
| 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_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 int cras_system_state_dump_snapshots_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_audio_shm mock_shm; |
| static struct cras_rstream mock_rstream; |
| static size_t cras_observer_num_ops_registered; |
| static size_t cras_observer_register_notify_called; |
| static size_t cras_observer_add_called; |
| static void* cras_observer_add_context_value; |
| static struct cras_observer_client* cras_observer_add_return_value; |
| static size_t cras_observer_get_ops_called; |
| static struct cras_observer_ops cras_observer_ops_value; |
| static size_t cras_observer_set_ops_called; |
| static size_t cras_observer_ops_are_empty_called; |
| static struct cras_observer_ops cras_observer_ops_are_empty_empty_ops; |
| static size_t cras_observer_remove_called; |
| |
| void ResetStubData() { |
| audio_thread_config_global_remix_called = 0; |
| memset(audio_thread_config_global_remix_copy, 0, |
| sizeof(audio_thread_config_global_remix_copy)); |
| 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_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_system_state_dump_snapshots_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; |
| cras_observer_num_ops_registered = 0; |
| cras_observer_register_notify_called = 0; |
| cras_observer_add_called = 0; |
| cras_observer_add_return_value = |
| reinterpret_cast<struct cras_observer_client*>(1); |
| cras_observer_add_context_value = NULL; |
| cras_observer_get_ops_called = 0; |
| memset(&cras_observer_ops_value, 0, sizeof(cras_observer_ops_value)); |
| cras_observer_set_ops_called = 0; |
| cras_observer_ops_are_empty_called = 0; |
| memset(&cras_observer_ops_are_empty_empty_ops, 0, |
| sizeof(cras_observer_ops_are_empty_empty_ops)); |
| cras_observer_remove_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_control_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); |
| |
| rclient->ops->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_control_rclient_create(pipe_fds_[1], 1); |
| 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_.proto_version = CRAS_PROTO_VER; |
| 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; |
| connect_msg_.client_shm_size = 0; |
| btlog = cras_bt_event_log_init(); |
| main_log = main_thread_event_log_init(); |
| ResetStubData(); |
| } |
| |
| virtual void TearDown() { |
| rclient_->ops->destroy(rclient_); |
| free(rstream_); |
| close(pipe_fds_[0]); |
| close(pipe_fds_[1]); |
| cras_bt_event_log_deinit(btlog); |
| main_thread_event_log_deinit(main_log); |
| } |
| |
| void RegisterNotification(enum CRAS_CLIENT_MESSAGE_ID msg_id, |
| void* callback, |
| void** ops_address); |
| |
| struct cras_connect_message connect_msg_; |
| struct cras_rclient* rclient_; |
| struct cras_rstream* rstream_; |
| size_t stream_id_; |
| int pipe_fds_[2]; |
| int fd_; |
| }; |
| |
| 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; |
| |
| fd_ = 100; |
| rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, |
| &fd_, 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(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 = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, |
| NULL, 0); |
| 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, StreamConnectMessageValidDirection) { |
| struct cras_client_stream_connected out_msg; |
| int rc; |
| int called = 0; |
| |
| for (int i = 0; i < CRAS_NUM_DIRECTIONS; i++) { |
| connect_msg_.direction = static_cast<CRAS_STREAM_DIRECTION>(i); |
| if (connect_msg_.direction == CRAS_STREAM_UNDEFINED) |
| continue; |
| called++; |
| cras_rstream_create_stream_out = rstream_; |
| cras_iodev_attach_stream_retval = 0; |
| |
| fd_ = 100; |
| rc = rclient_->ops->handle_message_from_client( |
| rclient_, &connect_msg_.header, &fd_, 1); |
| EXPECT_EQ(0, rc); |
| EXPECT_EQ(called, 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(called, stream_list_add_stream_called); |
| EXPECT_EQ(0, stream_list_disconnect_stream_called); |
| } |
| } |
| |
| TEST_F(RClientMessagesSuite, StreamConnectMessageInvalidDirection) { |
| struct cras_client_stream_connected out_msg; |
| int rc; |
| |
| connect_msg_.direction = CRAS_STREAM_UNDEFINED; |
| cras_rstream_create_stream_out = rstream_; |
| cras_iodev_attach_stream_retval = 0; |
| |
| fd_ = 100; |
| rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, |
| &fd_, 1); |
| EXPECT_EQ(0, rc); |
| EXPECT_EQ(0, 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(-EINVAL, out_msg.err); |
| EXPECT_EQ(0, stream_list_add_stream_called); |
| EXPECT_EQ(0, stream_list_disconnect_stream_called); |
| } |
| |
| TEST_F(RClientMessagesSuite, StreamConnectMessageInvalidClientId) { |
| struct cras_client_stream_connected out_msg; |
| int rc; |
| |
| connect_msg_.stream_id = 0x20002; // stream_id with invalid client_id |
| |
| fd_ = 100; |
| rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, |
| &fd_, 1); |
| EXPECT_EQ(0, rc); |
| EXPECT_EQ(0, cras_make_fd_nonblocking_called); |
| EXPECT_EQ(0, stream_list_add_stream_called); |
| EXPECT_EQ(0, stream_list_disconnect_stream_called); |
| |
| rc = read(pipe_fds_[0], &out_msg, sizeof(out_msg)); |
| EXPECT_EQ(sizeof(out_msg), rc); |
| EXPECT_EQ(-EINVAL, out_msg.err); |
| EXPECT_EQ(connect_msg_.stream_id, out_msg.stream_id); |
| } |
| |
| 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; |
| |
| fd_ = 100; |
| rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, |
| &fd_, 1); |
| 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; |
| |
| fd_ = 100; |
| rc = rclient_->ops->handle_message_from_client(rclient_, &connect_msg_.header, |
| &fd_, 1); |
| 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 = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| EXPECT_EQ(0, rc); |
| EXPECT_EQ(1, cras_system_set_volume_called); |
| EXPECT_EQ(66, cras_system_set_volume_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 = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| 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 = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| 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 = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| 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 = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| 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 = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| EXPECT_EQ(0, rc); |
| EXPECT_EQ(1, cras_system_set_capture_mute_locked_called); |
| EXPECT_EQ(1, cras_system_set_capture_mute_locked_value); |
| } |
| |
| TEST_F(RClientMessagesSuite, DumpSnapshots) { |
| struct cras_dump_snapshots msg; |
| int rc; |
| cras_fill_dump_snapshots(&msg); |
| rc = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| EXPECT_EQ(0, rc); |
| EXPECT_EQ(1, cras_system_state_dump_snapshots_called); |
| } |
| |
| TEST_F(RClientMessagesSuite, ConfigGlobalRemix) { |
| int rc; |
| struct cras_config_global_remix msg; |
| const int num_channels = 2; |
| float coefficient[4] = {0.1, 0.2, 0.3, 0.4}; |
| cras_fill_config_global_remix_command(&msg, num_channels, coefficient, |
| num_channels * num_channels); |
| |
| rc = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| EXPECT_EQ(0, rc); |
| EXPECT_EQ(1, audio_thread_config_global_remix_called); |
| for (unsigned i = 0; i < (unsigned)num_channels * num_channels; i++) { |
| EXPECT_EQ(audio_thread_config_global_remix_copy[i], coefficient[i]); |
| } |
| } |
| |
| void RClientMessagesSuite::RegisterNotification( |
| enum CRAS_CLIENT_MESSAGE_ID msg_id, |
| void* callback, |
| void** ops_address) { |
| struct cras_register_notification msg; |
| int do_register = callback != NULL ? 1 : 0; |
| int rc; |
| |
| cras_observer_register_notify_called++; |
| |
| cras_fill_register_notification_message(&msg, msg_id, do_register); |
| EXPECT_EQ(msg.header.length, sizeof(msg)); |
| EXPECT_EQ(msg.header.id, CRAS_SERVER_REGISTER_NOTIFICATION); |
| EXPECT_EQ(msg.do_register, do_register); |
| EXPECT_EQ(msg.msg_id, msg_id); |
| |
| rc = |
| rclient_->ops->handle_message_from_client(rclient_, &msg.header, NULL, 0); |
| EXPECT_EQ(0, rc); |
| EXPECT_EQ(cras_observer_register_notify_called, cras_observer_get_ops_called); |
| EXPECT_EQ(cras_observer_register_notify_called, |
| cras_observer_ops_are_empty_called); |
| if (msg.do_register) |
| cras_observer_num_ops_registered++; |
| if (cras_observer_num_ops_registered == 1) { |
| if (msg.do_register) { |
| EXPECT_EQ(1, cras_observer_add_called); |
| EXPECT_EQ(rclient_, cras_observer_add_context_value); |
| EXPECT_EQ(rclient_->observer, cras_observer_add_return_value); |
| } else { |
| EXPECT_EQ(1, cras_observer_remove_called); |
| EXPECT_EQ(rclient_->observer, (struct cras_observer_client*)NULL); |
| } |
| } else { |
| EXPECT_EQ(cras_observer_register_notify_called - 1, |
| cras_observer_set_ops_called); |
| } |
| if (!msg.do_register) |
| cras_observer_num_ops_registered--; |
| if (cras_observer_num_ops_registered) { |
| EXPECT_EQ(callback, *ops_address); |
| } |
| } |
| |
| TEST_F(RClientMessagesSuite, RegisterStatusNotification) { |
| /* First registration for this client. */ |
| RegisterNotification(CRAS_CLIENT_OUTPUT_VOLUME_CHANGED, |
| (void*)send_output_volume_changed, |
| (void**)&cras_observer_ops_value.output_volume_changed); |
| |
| /* Second registration for this client. */ |
| RegisterNotification(CRAS_CLIENT_CAPTURE_GAIN_CHANGED, |
| (void*)send_capture_gain_changed, |
| (void**)&cras_observer_ops_value.capture_gain_changed); |
| |
| /* Deregister output_volume. */ |
| RegisterNotification(CRAS_CLIENT_OUTPUT_VOLUME_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.output_volume_changed); |
| |
| /* Register/deregister all msg_ids. */ |
| |
| RegisterNotification(CRAS_CLIENT_OUTPUT_MUTE_CHANGED, |
| (void*)send_output_mute_changed, |
| (void**)&cras_observer_ops_value.output_mute_changed); |
| RegisterNotification(CRAS_CLIENT_OUTPUT_MUTE_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.output_mute_changed); |
| |
| RegisterNotification(CRAS_CLIENT_CAPTURE_MUTE_CHANGED, |
| (void*)send_capture_mute_changed, |
| (void**)&cras_observer_ops_value.capture_mute_changed); |
| RegisterNotification(CRAS_CLIENT_CAPTURE_MUTE_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.capture_mute_changed); |
| |
| RegisterNotification(CRAS_CLIENT_NODES_CHANGED, (void*)send_nodes_changed, |
| (void**)&cras_observer_ops_value.nodes_changed); |
| RegisterNotification(CRAS_CLIENT_NODES_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.nodes_changed); |
| |
| RegisterNotification(CRAS_CLIENT_ACTIVE_NODE_CHANGED, |
| (void*)send_active_node_changed, |
| (void**)&cras_observer_ops_value.active_node_changed); |
| RegisterNotification(CRAS_CLIENT_ACTIVE_NODE_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.active_node_changed); |
| |
| RegisterNotification( |
| CRAS_CLIENT_OUTPUT_NODE_VOLUME_CHANGED, |
| (void*)send_output_node_volume_changed, |
| (void**)&cras_observer_ops_value.output_node_volume_changed); |
| RegisterNotification( |
| CRAS_CLIENT_OUTPUT_NODE_VOLUME_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.output_node_volume_changed); |
| |
| RegisterNotification( |
| CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED, |
| (void*)send_node_left_right_swapped_changed, |
| (void**)&cras_observer_ops_value.node_left_right_swapped_changed); |
| RegisterNotification( |
| CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.node_left_right_swapped_changed); |
| |
| RegisterNotification( |
| CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED, (void*)send_input_node_gain_changed, |
| (void**)&cras_observer_ops_value.input_node_gain_changed); |
| RegisterNotification( |
| CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.input_node_gain_changed); |
| |
| RegisterNotification( |
| CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED, |
| (void*)send_num_active_streams_changed, |
| (void**)&cras_observer_ops_value.num_active_streams_changed); |
| RegisterNotification( |
| CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.num_active_streams_changed); |
| |
| /* Deregister last. */ |
| RegisterNotification(CRAS_CLIENT_CAPTURE_GAIN_CHANGED, NULL, |
| (void**)&cras_observer_ops_value.capture_gain_changed); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendOutputVolumeChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_volume_changed* msg = |
| (struct cras_client_volume_changed*)buf; |
| const int32_t volume = 90; |
| |
| send_output_volume_changed(void_client, volume); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_OUTPUT_VOLUME_CHANGED); |
| EXPECT_EQ(msg->volume, volume); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendOutputMuteChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_mute_changed* msg = (struct cras_client_mute_changed*)buf; |
| const int muted = 1; |
| const int user_muted = 0; |
| const int mute_locked = 1; |
| |
| send_output_mute_changed(void_client, muted, user_muted, mute_locked); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_OUTPUT_MUTE_CHANGED); |
| EXPECT_EQ(msg->muted, muted); |
| EXPECT_EQ(msg->user_muted, user_muted); |
| EXPECT_EQ(msg->mute_locked, mute_locked); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendCaptureMuteChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_mute_changed* msg = (struct cras_client_mute_changed*)buf; |
| const int muted = 1; |
| const int mute_locked = 0; |
| |
| send_capture_mute_changed(void_client, muted, mute_locked); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_CAPTURE_MUTE_CHANGED); |
| EXPECT_EQ(msg->muted, muted); |
| EXPECT_EQ(msg->mute_locked, mute_locked); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendNodesChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_nodes_changed* msg = |
| (struct cras_client_nodes_changed*)buf; |
| |
| send_nodes_changed(void_client); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_NODES_CHANGED); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendActiveNodeChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_active_node_changed* msg = |
| (struct cras_client_active_node_changed*)buf; |
| const enum CRAS_STREAM_DIRECTION dir = CRAS_STREAM_INPUT; |
| const cras_node_id_t node_id = 0x0001000200030004; |
| |
| send_active_node_changed(void_client, dir, node_id); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_ACTIVE_NODE_CHANGED); |
| EXPECT_EQ(msg->direction, (int32_t)dir); |
| EXPECT_EQ((uint64_t)msg->node_id, node_id); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendOutputNodeVolumeChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_node_value_changed* msg = |
| (struct cras_client_node_value_changed*)buf; |
| const cras_node_id_t node_id = 0x0001000200030004; |
| const int32_t value = 90; |
| |
| send_output_node_volume_changed(void_client, node_id, value); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_OUTPUT_NODE_VOLUME_CHANGED); |
| EXPECT_EQ(msg->node_id, node_id); |
| EXPECT_EQ(msg->value, value); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendNodeLeftRightSwappedChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_node_value_changed* msg = |
| (struct cras_client_node_value_changed*)buf; |
| const cras_node_id_t node_id = 0x0001000200030004; |
| const int32_t value = 0; |
| |
| send_node_left_right_swapped_changed(void_client, node_id, value); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED); |
| EXPECT_EQ(msg->node_id, node_id); |
| EXPECT_EQ(msg->value, value); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendNodeInputNodeGainChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_node_value_changed* msg = |
| (struct cras_client_node_value_changed*)buf; |
| const cras_node_id_t node_id = 0x0001000200030004; |
| const int32_t value = -19; |
| |
| send_input_node_gain_changed(void_client, node_id, value); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED); |
| EXPECT_EQ(msg->node_id, node_id); |
| EXPECT_EQ(msg->value, value); |
| } |
| |
| TEST_F(RClientMessagesSuite, SendNumActiveStreamsChanged) { |
| void* void_client = reinterpret_cast<void*>(rclient_); |
| char buf[1024]; |
| ssize_t rc; |
| struct cras_client_num_active_streams_changed* msg = |
| (struct cras_client_num_active_streams_changed*)buf; |
| const enum CRAS_STREAM_DIRECTION dir = CRAS_STREAM_INPUT; |
| const uint32_t num_active_streams = 3; |
| |
| send_num_active_streams_changed(void_client, dir, num_active_streams); |
| rc = read(pipe_fds_[0], buf, sizeof(buf)); |
| ASSERT_EQ(rc, (ssize_t)sizeof(*msg)); |
| EXPECT_EQ(msg->header.id, CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED); |
| EXPECT_EQ(msg->direction, (int32_t)dir); |
| EXPECT_EQ(msg->num_active_streams, num_active_streams); |
| } |
| |
| } // namespace |
| |
| int main(int argc, char** argv) { |
| ::testing::InitGoogleTest(&argc, argv); |
| return RUN_ALL_TESTS(); |
| } |
| |
| /* stubs */ |
| extern "C" { |
| |
| struct cras_bt_event_log* btlog; |
| struct main_thread_event_log* main_log; |
| |
| 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; |
| } |
| |
| int audio_thread_config_global_remix(struct audio_thread* thread, |
| unsigned int num_channels, |
| const float* coefficient) { |
| audio_thread_config_global_remix_called++; |
| memcpy(audio_thread_config_global_remix_copy, coefficient, |
| num_channels * num_channels * sizeof(coefficient)); |
| return 0; |
| } |
| |
| int audio_thread_set_aec_dump(struct audio_thread* thread, |
| cras_stream_id_t stream_id, |
| unsigned int start, |
| int fd) { |
| return 0; |
| } |
| |
| int audio_thread_event_log_shm_fd() { |
| return -1; |
| } |
| |
| #ifdef HAVE_WEBRTC_APM |
| void cras_apm_list_reload_aec_config() {} |
| #endif |
| |
| void cras_system_set_bt_wbs_enabled(bool enabled) {} |
| |
| const char* cras_config_get_socket_file_dir() { |
| return CRAS_UT_TMPDIR; |
| } |
| |
| 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; |
| } |
| |
| unsigned int cras_rstream_get_effects(const struct cras_rstream* stream) { |
| return 0; |
| } |
| |
| 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_state_dump_snapshots() { |
| cras_system_state_dump_snapshots_called++; |
| } |
| |
| void cras_system_set_volume(size_t volume) { |
| cras_system_set_volume_value = volume; |
| cras_system_set_volume_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_fd() { |
| return 1; |
| } |
| |
| void cras_dsp_reload_ini() {} |
| |
| void cras_dsp_dump_info() {} |
| |
| int cras_iodev_list_set_node_attr(cras_node_id_t id, |
| 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) {} |
| |
| void cras_iodev_list_configure_global_remix_converter( |
| unsigned int num_channels, |
| const float* coefficient) {} |
| |
| int stream_list_add(struct stream_list* list, |
| struct cras_rstream_config* config, |
| struct cras_rstream** stream) { |
| int ret; |
| |
| *stream = &mock_rstream; |
| |
| stream_list_add_stream_called++; |
| ret = stream_list_add_stream_return; |
| if (ret) |
| stream_list_add_stream_return = -EINVAL; |
| |
| mock_rstream.shm = &mock_shm; |
| mock_rstream.direction = config->direction; |
| mock_rstream.stream_id = config->stream_id; |
| |
| return ret; |
| } |
| |
| int stream_list_rm(struct stream_list* list, cras_stream_id_t id) { |
| stream_list_disconnect_stream_called++; |
| return 0; |
| } |
| |
| int stream_list_rm_all_client_streams(struct stream_list* list, |
| struct cras_rclient* rclient) { |
| return 0; |
| } |
| |
| int cras_send_with_fds(int sockfd, |
| const void* buf, |
| size_t len, |
| int* fd, |
| unsigned int num_fds) { |
| return write(sockfd, buf, len); |
| } |
| |
| char* cras_iodev_list_get_hotword_models(cras_node_id_t node_id) { |
| return NULL; |
| } |
| |
| int cras_iodev_list_set_hotword_model(cras_node_id_t id, |
| const char* model_name) { |
| return 0; |
| } |
| |
| struct cras_observer_client* cras_observer_add( |
| const struct cras_observer_ops* ops, |
| void* context) { |
| cras_observer_add_called++; |
| cras_observer_add_context_value = context; |
| memcpy(&cras_observer_ops_value, ops, sizeof(cras_observer_ops_value)); |
| return cras_observer_add_return_value; |
| } |
| |
| void cras_observer_get_ops(const struct cras_observer_client* client, |
| struct cras_observer_ops* ops) { |
| cras_observer_get_ops_called++; |
| memcpy(ops, &cras_observer_ops_value, sizeof(*ops)); |
| } |
| |
| void cras_observer_set_ops(struct cras_observer_client* client, |
| const struct cras_observer_ops* ops) { |
| cras_observer_set_ops_called++; |
| memcpy(&cras_observer_ops_value, ops, sizeof(cras_observer_ops_value)); |
| } |
| |
| int cras_observer_ops_are_empty(const struct cras_observer_ops* ops) { |
| cras_observer_ops_are_empty_called++; |
| return memcmp(&cras_observer_ops_are_empty_empty_ops, ops, |
| sizeof(cras_observer_ops_are_empty_empty_ops)) == 0; |
| } |
| |
| void cras_observer_remove(struct cras_observer_client* client) { |
| cras_observer_remove_called++; |
| } |
| |
| bool cras_audio_format_valid(const struct cras_audio_format* fmt) { |
| return true; |
| } |
| |
| struct packet_status_logger* cras_hfp_ag_get_wbs_logger() { |
| return NULL; |
| } |
| |
| void detect_rtc_stream_pair(struct stream_list* list, |
| struct cras_rstream* stream) { |
| return; |
| } |
| |
| void cras_system_set_hotword_pause_at_suspend(bool pause) {} |
| |
| } // extern "C" |