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
|
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "l2cap/internal/dynamic_channel_impl.h"
#include "common/testing/bind_test_util.h"
#include "l2cap/cid.h"
#include "l2cap/classic/internal/link_mock.h"
#include "l2cap/internal/parameter_provider_mock.h"
#include "os/handler.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace bluetooth {
namespace l2cap {
namespace internal {
using classic::internal::testing::MockLink;
using l2cap::internal::testing::MockParameterProvider;
using ::testing::Return;
class L2capClassicDynamicChannelImplTest : public ::testing::Test {
public:
static void SyncHandler(os::Handler* handler) {
std::promise<void> promise;
auto future = promise.get_future();
handler->Post(common::BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)));
future.wait_for(std::chrono::milliseconds(3));
}
protected:
void SetUp() override {
thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
l2cap_handler_ = new os::Handler(thread_);
}
void TearDown() override {
l2cap_handler_->Clear();
delete l2cap_handler_;
delete thread_;
}
os::Thread* thread_ = nullptr;
os::Handler* l2cap_handler_ = nullptr;
};
class StatusCapture {
public:
hci::ErrorCode value = hci::ErrorCode::SUCCESS;
void capture(hci::ErrorCode status) {
value = status;
}
};
TEST_F(L2capClassicDynamicChannelImplTest, get_device) {
MockParameterProvider mock_parameter_provider;
MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider);
const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::PUBLIC_IDENTITY_ADDRESS};
EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device));
DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, &mock_classic_link,
l2cap_handler_);
EXPECT_EQ(device, dynamic_channel_impl.GetDevice());
}
TEST_F(L2capClassicDynamicChannelImplTest, close_triggers_callback) {
MockParameterProvider mock_parameter_provider;
MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider);
const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::PUBLIC_IDENTITY_ADDRESS};
EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device));
DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, &mock_classic_link,
l2cap_handler_);
// Register on close callback
auto user_handler = std::make_unique<os::Handler>(thread_);
StatusCapture* my_status = new StatusCapture();
dynamic_channel_impl.RegisterOnCloseCallback(user_handler->BindOnceOn(my_status, &StatusCapture::capture));
// Channel closure should trigger such callback
dynamic_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION);
SyncHandler(user_handler.get());
EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status->value);
user_handler->Clear();
delete my_status;
}
TEST_F(L2capClassicDynamicChannelImplTest, register_callback_after_close_should_call_immediately) {
MockParameterProvider mock_parameter_provider;
MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider);
const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::PUBLIC_IDENTITY_ADDRESS};
EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device));
DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, &mock_classic_link,
l2cap_handler_);
// Channel closure should do nothing
dynamic_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION);
// Register on close callback should trigger callback immediately
auto user_handler = std::make_unique<os::Handler>(thread_);
StatusCapture* my_status = new StatusCapture();
dynamic_channel_impl.RegisterOnCloseCallback(user_handler->BindOnceOn(my_status, &StatusCapture::capture));
SyncHandler(user_handler.get());
EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status->value);
user_handler->Clear();
delete my_status;
}
TEST_F(L2capClassicDynamicChannelImplTest, close_twice_should_fail) {
MockParameterProvider mock_parameter_provider;
MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider);
const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::PUBLIC_IDENTITY_ADDRESS};
EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device));
DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, &mock_classic_link,
l2cap_handler_);
// Register on close callback
auto user_handler = std::make_unique<os::Handler>(thread_);
StatusCapture* my_status = new StatusCapture();
dynamic_channel_impl.RegisterOnCloseCallback(user_handler->BindOnceOn(my_status, &StatusCapture::capture));
// Channel closure should trigger such callback
dynamic_channel_impl.OnClosed(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION);
SyncHandler(user_handler.get());
EXPECT_EQ(hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION, my_status->value);
// 2nd OnClose() callback should fail
EXPECT_DEATH(dynamic_channel_impl.OnClosed(hci::ErrorCode::PAGE_TIMEOUT), ".*OnClosed.*");
user_handler->Clear();
delete my_status;
}
TEST_F(L2capClassicDynamicChannelImplTest, multiple_registeration_should_fail) {
MockParameterProvider mock_parameter_provider;
MockLink mock_classic_link(l2cap_handler_, &mock_parameter_provider);
const hci::AddressWithType device{{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::PUBLIC_IDENTITY_ADDRESS};
EXPECT_CALL(mock_classic_link, GetDevice()).WillRepeatedly(Return(device));
DynamicChannelImpl dynamic_channel_impl(0x01, kFirstDynamicChannel, kFirstDynamicChannel, &mock_classic_link,
l2cap_handler_);
// Register on close callback
auto user_handler = std::make_unique<os::Handler>(thread_);
StatusCapture* my_status = new StatusCapture();
dynamic_channel_impl.RegisterOnCloseCallback(user_handler->BindOnceOn(my_status, &StatusCapture::capture));
EXPECT_DEATH(
dynamic_channel_impl.RegisterOnCloseCallback(user_handler->BindOnce([](hci::ErrorCode status) { FAIL(); })),
".*RegisterOnCloseCallback.*");
user_handler->Clear();
delete my_status;
}
} // namespace internal
} // namespace l2cap
} // namespace bluetooth
|