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 34 class 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 60 TimeoutHelper helper; 61 62 // External function definitions 63 void btu_message_loop_run(void* context); 64 void btu_task_start_up(void* context); 65 void 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 */ 70 void btif_transfer_context(void (*)(unsigned short, char*), uint16_t, char*, 71 int, void (*)(unsigned short, char*, char*)) { 72 helper.notify(); 73 }; 74 75 void btu_init_core(){}; 76 void btif_init_ok(unsigned short, char*){}; 77 void BTE_InitStack(){}; 78 void bta_sys_init(){}; 79 void bta_sys_free(){}; 80 void btu_free_core(){}; 81 const module_t* get_module(const char*) { return nullptr; }; 82 bool module_init(module_t const*) { return true; }; 83 void module_clean_up(module_t const*){}; 84 85 thread_t* bt_workqueue_thread; 86 87 class 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 112 TEST_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