1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <sys/socket.h>
20
21 #include "bta/dm/bta_dm_sec_int.h"
22 #include "bta/test/bta_test_fixtures.h"
23 #include "stack/include/btm_status.h"
24 #include "test/mock/mock_stack_btm_interface.h"
25 #include "test/mock/mock_stack_rnr_interface.h"
26 #include "types/raw_address.h"
27
28 using ::testing::_;
29 using ::testing::ElementsAre;
30 using ::testing::Return;
31
32 namespace {
33 const RawAddress kRawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
34 const RawAddress kRawAddress2({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});
35 const DEV_CLASS kDeviceClass = {0x11, 0x22, 0x33};
36
37 constexpr char kRemoteName[] = "TheRemoteName";
38
39 } // namespace
40
41 // Test hooks
42 namespace bluetooth {
43 namespace legacy {
44 namespace testing {
45
46 tBTM_STATUS bta_dm_sp_cback(tBTM_SP_EVT event, tBTM_SP_EVT_DATA* p_data);
47
48 } // namespace testing
49 } // namespace legacy
50 } // namespace bluetooth
51
52 class BtaSecTest : public BtaWithHwOnTest {
53 protected:
SetUp()54 void SetUp() override {
55 BtaWithHwOnTest::SetUp();
56 bluetooth::testing::stack::rnr::set_interface(&mock_stack_rnr_interface_);
57 }
58
TearDown()59 void TearDown() override {
60 bluetooth::testing::stack::rnr::reset_interface();
61 BtaWithHwOnTest::TearDown();
62 }
63
64 bluetooth::testing::stack::rnr::Mock mock_stack_rnr_interface_;
65 };
66
TEST_F(BtaSecTest,bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithName)67 TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithName) {
68 constexpr uint32_t kNumVal = 1234;
69 static bool callback_sent = false;
70
71 static tBTA_DM_SP_CFM_REQ cfm_req{};
72 bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) {
73 callback_sent = true;
74 cfm_req = p_data->cfm_req;
75 });
76
77 tBTM_SP_EVT_DATA data = {
78 .cfm_req =
79 {
80 // tBTM_SP_CFM_REQ
81 .bd_addr = kRawAddress,
82 .dev_class = {},
83 .bd_name = {},
84 .num_val = kNumVal,
85 .just_works = false,
86 .loc_auth_req = BTM_AUTH_SP_YES,
87 .rmt_auth_req = BTM_AUTH_SP_YES,
88 .loc_io_caps = BTM_IO_CAP_NONE,
89 .rmt_io_caps = BTM_IO_CAP_NONE,
90 },
91 };
92 data.cfm_req.dev_class = kDeviceClass;
93 bd_name_from_char_pointer(data.cfm_req.bd_name, kRemoteName);
94
95 ASSERT_EQ(
96 btm_status_text(tBTM_STATUS::BTM_CMD_STARTED),
97 btm_status_text(bluetooth::legacy::testing::bta_dm_sp_cback(BTM_SP_CFM_REQ_EVT, &data)));
98 ASSERT_EQ(kNumVal, bta_dm_sec_cb.num_val);
99 ASSERT_TRUE(callback_sent);
100
101 ASSERT_EQ(kRawAddress, cfm_req.bd_addr);
102 ASSERT_THAT(cfm_req.dev_class, ElementsAre(kDeviceClass[0], kDeviceClass[1], kDeviceClass[2]));
103 ASSERT_STREQ(kRemoteName, reinterpret_cast<const char*>(cfm_req.bd_name));
104 ASSERT_EQ(kNumVal, cfm_req.num_val);
105 ASSERT_EQ(false, cfm_req.just_works);
106 ASSERT_EQ(BTM_AUTH_SP_YES, cfm_req.loc_auth_req);
107 ASSERT_EQ(BTM_AUTH_SP_YES, cfm_req.rmt_auth_req);
108 ASSERT_EQ(BTM_IO_CAP_NONE, cfm_req.loc_io_caps);
109 ASSERT_EQ(BTM_IO_CAP_NONE, cfm_req.rmt_io_caps);
110 }
111
TEST_F(BtaSecTest,bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRSuccess)112 TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRSuccess) {
113 constexpr uint32_t kNumVal = 1234;
114 static bool callback_sent = false;
115 reset_mock_btm_client_interface();
116
117 EXPECT_CALL(mock_stack_rnr_interface_, BTM_ReadRemoteDeviceName(_, _, _))
118 .WillOnce(Return(tBTM_STATUS::BTM_CMD_STARTED));
119
120 static tBTA_DM_SP_CFM_REQ cfm_req{};
121 bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) {
122 callback_sent = true;
123 cfm_req = p_data->cfm_req;
124 });
125
126 tBTM_SP_EVT_DATA data = {
127 .cfm_req =
128 {
129 // tBTM_SP_CFM_REQ
130 .bd_addr = kRawAddress,
131 .dev_class = {},
132 .bd_name = {0}, // No name available
133 .num_val = kNumVal,
134 .just_works = false,
135 .loc_auth_req = BTM_AUTH_SP_YES,
136 .rmt_auth_req = BTM_AUTH_SP_YES,
137 .loc_io_caps = BTM_IO_CAP_NONE,
138 .rmt_io_caps = BTM_IO_CAP_NONE,
139 },
140 };
141 data.cfm_req.dev_class = kDeviceClass;
142
143 ASSERT_EQ(
144 btm_status_text(tBTM_STATUS::BTM_CMD_STARTED),
145 btm_status_text(bluetooth::legacy::testing::bta_dm_sp_cback(BTM_SP_CFM_REQ_EVT, &data)));
146 ASSERT_EQ(kNumVal, bta_dm_sec_cb.num_val);
147 ASSERT_FALSE(callback_sent);
148 }
149
TEST_F(BtaSecTest,bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRFail)150 TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRFail) {
151 constexpr uint32_t kNumVal = 1234;
152 static bool callback_sent = false;
153
154 EXPECT_CALL(mock_stack_rnr_interface_, BTM_ReadRemoteDeviceName(_, _, _))
155 .WillOnce(Return(tBTM_STATUS::BTM_SUCCESS));
156
157 static tBTA_DM_SP_CFM_REQ cfm_req{};
158 bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) {
159 callback_sent = true;
160 cfm_req = p_data->cfm_req;
161 });
162
163 tBTM_SP_EVT_DATA data = {
164 .cfm_req =
165 {
166 // tBTM_SP_CFM_REQ
167 .bd_addr = kRawAddress,
168 .dev_class = {},
169 .bd_name = {0},
170 .num_val = kNumVal,
171 .just_works = false,
172 .loc_auth_req = BTM_AUTH_SP_YES,
173 .rmt_auth_req = BTM_AUTH_SP_YES,
174 .loc_io_caps = BTM_IO_CAP_NONE,
175 .rmt_io_caps = BTM_IO_CAP_NONE,
176 },
177 };
178 data.cfm_req.dev_class = kDeviceClass;
179
180 ASSERT_EQ(
181 btm_status_text(tBTM_STATUS::BTM_CMD_STARTED),
182 btm_status_text(bluetooth::legacy::testing::bta_dm_sp_cback(BTM_SP_CFM_REQ_EVT, &data)));
183 ASSERT_EQ(kNumVal, bta_dm_sec_cb.num_val);
184 ASSERT_TRUE(callback_sent);
185
186 ASSERT_EQ(kRawAddress, cfm_req.bd_addr);
187 ASSERT_THAT(cfm_req.dev_class, ElementsAre(kDeviceClass[0], kDeviceClass[1], kDeviceClass[2]));
188 ASSERT_EQ(kNumVal, cfm_req.num_val);
189 ASSERT_EQ(false, cfm_req.just_works);
190 ASSERT_EQ(BTM_AUTH_SP_YES, cfm_req.loc_auth_req);
191 ASSERT_EQ(BTM_AUTH_SP_YES, cfm_req.rmt_auth_req);
192 ASSERT_EQ(BTM_IO_CAP_NONE, cfm_req.loc_io_caps);
193 ASSERT_EQ(BTM_IO_CAP_NONE, cfm_req.rmt_io_caps);
194 }
195
TEST_F(BtaSecTest,bta_dm_sp_cback__BTM_SP_KEY_NOTIF_EVT)196 TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_KEY_NOTIF_EVT) {
197 constexpr uint32_t kPassKey = 1234;
198 static bool callback_sent = false;
199
200 ON_CALL(mock_stack_rnr_interface_, BTM_ReadRemoteDeviceName(_, _, _))
201 .WillByDefault(Return(tBTM_STATUS::BTM_CMD_STARTED));
202
203 static tBTA_DM_SP_KEY_NOTIF key_notif{};
204 bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) {
205 callback_sent = true;
206 key_notif = p_data->key_notif;
207 });
208
209 tBTM_SP_EVT_DATA data = {
210 .key_notif =
211 {
212 // tBTM_SP_KEY_NOTIF
213 .bd_addr = kRawAddress,
214 .dev_class = {},
215 .bd_name = {},
216 .passkey = kPassKey,
217 },
218 };
219 data.key_notif.dev_class = kDeviceClass;
220 bd_name_from_char_pointer(data.key_notif.bd_name, kRemoteName);
221
222 ASSERT_EQ(btm_status_text(tBTM_STATUS::BTM_CMD_STARTED),
223 btm_status_text(
224 bluetooth::legacy::testing::bta_dm_sp_cback(BTM_SP_KEY_NOTIF_EVT, &data)));
225 ASSERT_EQ(kPassKey, bta_dm_sec_cb.num_val);
226 ASSERT_TRUE(callback_sent);
227
228 ASSERT_EQ(kRawAddress, key_notif.bd_addr);
229 ASSERT_THAT(key_notif.dev_class, ElementsAre(kDeviceClass[0], kDeviceClass[1], kDeviceClass[2]));
230 ASSERT_STREQ(kRemoteName, reinterpret_cast<const char*>(key_notif.bd_name));
231 ASSERT_EQ(kPassKey, key_notif.passkey);
232 }
233