普通文本  |  348行  |  9.25 KB

// 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" {
#include "cras_bt_io.h"
#include "cras_bt_device.h"
#include "cras_iodev.h"
#include "cras_main_message.h"

#define FAKE_OBJ_PATH "/obj/path"
}

static struct cras_iodev *cras_bt_io_create_profile_ret;
static struct cras_iodev *cras_bt_io_append_btio_val;
static struct cras_ionode* cras_bt_io_get_profile_ret;
static unsigned int cras_bt_io_create_called;
static unsigned int cras_bt_io_append_called;
static unsigned int cras_bt_io_remove_called;
static unsigned int cras_bt_io_destroy_called;
static enum cras_bt_device_profile cras_bt_io_create_profile_val;
static enum cras_bt_device_profile cras_bt_io_append_profile_val;
static unsigned int cras_bt_io_try_remove_ret;

static cras_main_message *cras_main_message_send_msg;
static cras_message_callback cras_main_message_add_handler_callback;
static void *cras_main_message_add_handler_callback_data;

void ResetStubData() {
  cras_bt_io_get_profile_ret = NULL;
  cras_bt_io_create_called = 0;
  cras_bt_io_append_called = 0;
  cras_bt_io_remove_called = 0;
  cras_bt_io_destroy_called = 0;
  cras_bt_io_try_remove_ret = 0;
  cras_main_message_send_msg = NULL;
}

namespace {

class BtDeviceTestSuite : public testing::Test {
  protected:
    virtual void SetUp() {
      ResetStubData();
      bt_iodev1.direction = CRAS_STREAM_OUTPUT;
      bt_iodev1.update_active_node = update_active_node;
      bt_iodev2.direction = CRAS_STREAM_INPUT;
      bt_iodev2.update_active_node = update_active_node;
      d1_.direction = CRAS_STREAM_OUTPUT;
      d1_.update_active_node = update_active_node;
      d2_.direction = CRAS_STREAM_OUTPUT;
      d2_.update_active_node = update_active_node;
      d3_.direction = CRAS_STREAM_INPUT;
      d3_.update_active_node = update_active_node;
    }

    virtual void TearDown() {
      if(cras_main_message_send_msg)
        free(cras_main_message_send_msg);
    }

    static void update_active_node(struct cras_iodev *iodev,
                                   unsigned node_idx,
                                   unsigned dev_enabled) {
    }

    struct cras_iodev bt_iodev1;
    struct cras_iodev bt_iodev2;
    struct cras_iodev d3_;
    struct cras_iodev d2_;
    struct cras_iodev d1_;
};

TEST(BtDeviceSuite, CreateBtDevice) {
  struct cras_bt_device *device;

  device = cras_bt_device_create(NULL, FAKE_OBJ_PATH);
  EXPECT_NE((void *)NULL, device);

  device = cras_bt_device_get(FAKE_OBJ_PATH);
  EXPECT_NE((void *)NULL, device);

  cras_bt_device_destroy(device);
  device = cras_bt_device_get(FAKE_OBJ_PATH);
  EXPECT_EQ((void *)NULL, device);
}

TEST_F(BtDeviceTestSuite, AppendRmIodev) {
  struct cras_bt_device *device;
  device = cras_bt_device_create(NULL, FAKE_OBJ_PATH);
  bt_iodev1.nodes = reinterpret_cast<struct cras_ionode*>(0x123);
  cras_bt_io_create_profile_ret = &bt_iodev1;
  cras_bt_device_append_iodev(device, &d1_,
      CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
  EXPECT_EQ(1, cras_bt_io_create_called);
  EXPECT_EQ(0, cras_bt_io_append_called);
  EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE,
            cras_bt_io_create_profile_val);
  cras_bt_device_set_active_profile(device,
      CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);

  cras_bt_device_append_iodev(device, &d2_,
      CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
  EXPECT_EQ(1, cras_bt_io_create_called);
  EXPECT_EQ(1, cras_bt_io_append_called);
  EXPECT_EQ(CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY,
  	    cras_bt_io_append_profile_val);
  EXPECT_EQ(&bt_iodev1, cras_bt_io_append_btio_val);

  /* Test HFP disconnected and switch to A2DP. */
  cras_bt_io_get_profile_ret = bt_iodev1.nodes;
  cras_bt_io_try_remove_ret = CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE;
  cras_bt_device_set_active_profile(
      device, CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
  cras_bt_device_rm_iodev(device, &d2_);
  EXPECT_EQ(1, cras_bt_io_remove_called);

  /* Test A2DP disconnection will cause bt_io destroy. */
  cras_bt_io_try_remove_ret = 0;
  cras_bt_device_rm_iodev(device, &d1_);
  EXPECT_EQ(1, cras_bt_io_remove_called);
  EXPECT_EQ(1, cras_bt_io_destroy_called);
  EXPECT_EQ(0, cras_bt_device_get_active_profile(device));
  cras_bt_device_destroy(device);
}

TEST_F(BtDeviceTestSuite, SwitchProfile) {
  struct cras_bt_device *device;

  ResetStubData();
  device = cras_bt_device_create(NULL, FAKE_OBJ_PATH);
  cras_bt_io_create_profile_ret = &bt_iodev1;
  cras_bt_device_append_iodev(device, &d1_,
      CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
  cras_bt_io_create_profile_ret = &bt_iodev2;
  cras_bt_device_append_iodev(device, &d3_,
      CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);

  cras_bt_device_start_monitor();
  cras_bt_device_switch_profile_enable_dev(device, &bt_iodev1);

  /* Two bt iodevs were all active. */
  cras_main_message_add_handler_callback(
      cras_main_message_send_msg,
      cras_main_message_add_handler_callback_data);

  /* One bt iodev was active, the other was not. */
  cras_bt_device_switch_profile_enable_dev(device, &bt_iodev2);
  cras_main_message_add_handler_callback(
      cras_main_message_send_msg,
      cras_main_message_add_handler_callback_data);

  /* Output bt iodev wasn't active, close the active input iodev. */
  cras_bt_device_switch_profile(device, &bt_iodev2);
  cras_main_message_add_handler_callback(
      cras_main_message_send_msg,
      cras_main_message_add_handler_callback_data);
  cras_bt_device_destroy(device);
}

/* Stubs */
extern "C" {

/* From bt_io */
struct cras_iodev *cras_bt_io_create(
        struct cras_bt_device *device,
				struct cras_iodev *dev,
				enum cras_bt_device_profile profile)
{
  cras_bt_io_create_called++;
  cras_bt_io_create_profile_val = profile;
  return cras_bt_io_create_profile_ret;
}
void cras_bt_io_destroy(struct cras_iodev *bt_iodev)
{
  cras_bt_io_destroy_called++;
}
struct cras_ionode* cras_bt_io_get_profile(
    struct cras_iodev *bt_iodev,
    enum cras_bt_device_profile profile)
{
  return cras_bt_io_get_profile_ret;
}
int cras_bt_io_append(struct cras_iodev *bt_iodev,
		      struct cras_iodev *dev,
		      enum cras_bt_device_profile profile)
{
  cras_bt_io_append_called++;
  cras_bt_io_append_profile_val = profile;
  cras_bt_io_append_btio_val = bt_iodev;
  return 0;
}
int cras_bt_io_on_profile(struct cras_iodev *bt_iodev,
                          enum cras_bt_device_profile profile)
{
  return 0;
}
int cras_bt_io_update_buffer_size(struct cras_iodev *bt_iodev)
{
  return 0;
}
unsigned int cras_bt_io_try_remove(struct cras_iodev *bt_iodev,
           struct cras_iodev *dev)
{
  return cras_bt_io_try_remove_ret;
}
int cras_bt_io_remove(struct cras_iodev *bt_iodev,
		                  struct cras_iodev *dev)
{
  cras_bt_io_remove_called++;
  return 0;
}

/* From bt_adapter */
struct cras_bt_adapter *cras_bt_adapter_get(const char *object_path)
{
  return NULL;
}
const char *cras_bt_adapter_address(const struct cras_bt_adapter *adapter)
{
  return NULL;
}

int cras_bt_adapter_on_usb(struct cras_bt_adapter *adapter)
{
  return 1;
}

/* From bt_profile */
void cras_bt_profile_on_device_disconnected(struct cras_bt_device *device)
{
}

/* From hfp_ag_profile */
struct hfp_slc_handle *cras_hfp_ag_get_slc(struct cras_bt_device *device)
{
  return NULL;
}

void cras_hfp_ag_suspend_connected_device(struct cras_bt_device *device)
{
}

void cras_a2dp_suspend_connected_device(struct cras_bt_device *device)
{
}

void cras_a2dp_start(struct cras_bt_device *device)
{
}

int cras_hfp_ag_start(struct cras_bt_device *device)
{
  return 0;
}

void cras_hfp_ag_suspend()
{
}

/* From hfp_slc */
int hfp_event_speaker_gain(struct hfp_slc_handle *handle, int gain)
{
  return 0;
}

/* From iodev_list */

int cras_iodev_open(struct cras_iodev *dev, unsigned int cb_level,
                    const struct cras_audio_format *fmt)
{
  return 0;
}

int cras_iodev_close(struct cras_iodev *dev) {
  return 0;
}

int cras_iodev_list_dev_is_enabled(const struct cras_iodev *dev)
{
  return 0;
}

void cras_iodev_list_disable_dev(struct cras_iodev *dev)
{
}

void cras_iodev_list_enable_dev(struct cras_iodev *dev)
{
}

void cras_iodev_list_notify_node_volume(struct cras_ionode *node)
{
}

int cras_main_message_send(struct cras_main_message *msg)
{
  // cras_main_message is a local variable from caller, we should allocate
  // memory from heap and copy its data
  if(cras_main_message_send_msg)
    free(cras_main_message_send_msg);
  cras_main_message_send_msg =
    (struct cras_main_message *)calloc(1, msg->length);
  memcpy((void *)cras_main_message_send_msg, (void *)msg, msg->length);
  return 0;
}

int cras_main_message_add_handler(enum CRAS_MAIN_MESSAGE_TYPE type,
          cras_message_callback callback,
          void *callback_data)
{
  cras_main_message_add_handler_callback = callback;
  cras_main_message_add_handler_callback_data = callback_data;
  return 0;
}

/* From cras_system_state */
struct cras_tm *cras_system_state_get_tm()
{
  return NULL;
}

/* From cras_tm */
struct cras_timer *cras_tm_create_timer(
    struct cras_tm *tm,
    unsigned int ms,
    void (*cb)(struct cras_timer *t, void *data),
    void *cb_data)
{
  return NULL;
}

void cras_tm_cancel_timer(struct cras_tm *tm, struct cras_timer *t)
{
}

} // extern "C"
} // namespace

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}