stack_btu_test.cc revision 47616530ceea2ea6432ffb35cd8a3fc0a56365b5
1/******************************************************************************
2 *
3 *  Copyright (C) 2017 The Android Open Source Project
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19#include <base/bind.h>
20#include <base/logging.h>
21#include <base/threading/thread.h>
22#include <gmock/gmock.h>
23#include <gtest/gtest.h>
24#include <semaphore.h>
25#include <time.h>
26#include <unistd.h>
27
28#include "btcore/include/module.h"
29#include "osi/include/alarm.h"
30#include "osi/include/fixed_queue.h"
31#include "osi/include/thread.h"
32#include "stack/include/btu.h"
33
34class TimeoutHelper {
35 public:
36  TimeoutHelper() { sem_init(&sem, 0, 0); }
37
38  ~TimeoutHelper() { sem_destroy(&sem); }
39
40  void wait(int seconds, base::Closure callback) {
41    struct timespec timeout;
42    clock_gettime(CLOCK_REALTIME, &timeout);
43    timeout.tv_sec += seconds;
44
45    int semvalue;
46    sem_getvalue(&sem, &semvalue);
47
48    // Call the callback if timeout occured
49    if (sem_timedwait(&sem, &timeout) == -1 && !callback.is_null()) {
50      callback.Run();
51    }
52  }
53
54  void notify() { sem_post(&sem); }
55
56 private:
57  sem_t sem;
58};
59
60TimeoutHelper helper;
61
62// External function definitions
63void btu_message_loop_run(void* context);
64void btu_task_start_up(void* context);
65void btu_task_shut_down(void* context);
66
67/* Below are methods and variables that must be implemented if we don't want to
68 * compile the whole stack. They will be removed, or changed into mocks one by
69 * one in the future, as the refactoring progresses */
70void btif_transfer_context(void (*)(unsigned short, char*), uint16_t, char*,
71                           int, void (*)(unsigned short, char*, char*)) {
72  helper.notify();
73};
74
75void btu_init_core(){};
76void btif_init_ok(unsigned short, char*){};
77void BTE_InitStack(){};
78void bta_sys_init(){};
79void bta_sys_free(){};
80void btu_free_core(){};
81const module_t* get_module(const char*) { return nullptr; };
82bool module_init(module_t const*) { return true; };
83void module_clean_up(module_t const*){};
84
85thread_t* bt_workqueue_thread;
86
87class BtuMessageLoopTest : public testing::Test {
88 public:
89  MOCK_METHOD0(TestCallback, void(void));
90  base::MessageLoop* message_loop;
91
92  virtual void SetUp() {
93    // Initialize alarms to prevent btu_task_shut_down from crashing
94    alarm_new("test alarm");
95    bt_workqueue_thread = thread_new("test alarm thread");
96
97    // btu_task_start_up calls btif_transfer_context to let the stack know
98    // start up is finished
99    btu_task_start_up(nullptr);
100    helper.wait(5, base::Bind(&BtuMessageLoopTest::Fail, base::Unretained(this),
101                              "BTU startup timed out"));
102  }
103
104  virtual void TearDown() {
105    btu_task_shut_down(nullptr);
106    alarm_cleanup();
107  }
108
109  void Fail(std::string message) { FAIL() << message; }
110};
111
112TEST_F(BtuMessageLoopTest, send_message) {
113  message_loop = get_message_loop();
114  EXPECT_FALSE(message_loop == nullptr);
115
116  EXPECT_CALL(*this, TestCallback()).Times(1);
117  message_loop->task_runner()->PostTask(
118      FROM_HERE,
119      base::Bind(&BtuMessageLoopTest::TestCallback, base::Unretained(this)));
120
121  message_loop->task_runner()->PostTask(
122      FROM_HERE, base::Bind(&TimeoutHelper::notify, base::Unretained(&helper)));
123
124  // Prevent the test from ending before the message loop posts the function
125  helper.wait(5, base::Bind(&BtuMessageLoopTest::Fail, base::Unretained(this),
126                            "Timed out waiting for callback"));
127}
128