summaryrefslogtreecommitdiff
path: root/cras/src/tests/bt_device_unittest.cc
blob: 4f7cd86c77ffbf619d1a345c95d19de12340b765 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
// 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;
}

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;
    }

    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));
}

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);
}

/* 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) {
  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_send_msg = msg;
  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();
}