1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
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 #include <base/logging.h>
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 #include "bta_groups.h"
23 #include "types/bluetooth/uuid.h"
24 #include "types/raw_address.h"
25
26 std::map<std::string, int> mock_function_count_map;
27
28 namespace bluetooth {
29 namespace groups {
30
31 using ::testing::_;
32 using ::testing::DoAll;
33 using ::testing::Invoke;
34 using ::testing::Mock;
35 using ::testing::Return;
36 using ::testing::SaveArg;
37 using ::testing::SetArgPointee;
38 using ::testing::Test;
39
40 using bluetooth::groups::DeviceGroups;
41 using bluetooth::groups::DeviceGroupsCallbacks;
42
43 DeviceGroupsCallbacks* dev_callbacks;
44
GetTestAddress(int index)45 RawAddress GetTestAddress(int index) {
46 CHECK_LT(index, UINT8_MAX);
47 RawAddress result = {
48 {0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
49 return result;
50 }
51
52 class MockGroupsCallbacks : public DeviceGroupsCallbacks {
53 public:
54 MockGroupsCallbacks() = default;
55 MockGroupsCallbacks(const MockGroupsCallbacks&) = delete;
56 MockGroupsCallbacks& operator=(const MockGroupsCallbacks&) = delete;
57
58 ~MockGroupsCallbacks() override = default;
59
60 MOCK_METHOD((void), OnGroupAdded,
61 (const RawAddress& address, const bluetooth::Uuid& uuid,
62 int group_id),
63 (override));
64 MOCK_METHOD((void), OnGroupMemberAdded,
65 (const RawAddress& address, int group_id), (override));
66
67 MOCK_METHOD((void), OnGroupRemoved,
68 (const bluetooth::Uuid& uuid, int group_id), (override));
69 MOCK_METHOD((void), OnGroupMemberRemoved,
70 (const RawAddress& address, int group_id), (override));
71 MOCK_METHOD((void), OnGroupAddFromStorage,
72 (const RawAddress& address, const bluetooth::Uuid& uuid,
73 int group_id),
74 (override));
75 };
76
77 class GroupsTest : public ::testing::Test {
78 protected:
SetUp()79 void SetUp() override {
80 mock_function_count_map.clear();
81 callbacks.reset(new MockGroupsCallbacks());
82 }
83
TearDown()84 void TearDown() override { DeviceGroups::CleanUp(callbacks.get()); }
85
86 std::unique_ptr<MockGroupsCallbacks> callbacks;
87 };
88
TEST_F(GroupsTest,test_initialize)89 TEST_F(GroupsTest, test_initialize) {
90 DeviceGroups::Initialize(callbacks.get());
91 ASSERT_TRUE(DeviceGroups::Get());
92 DeviceGroups::CleanUp(callbacks.get());
93 }
94
TEST_F(GroupsTest,test_initialize_twice)95 TEST_F(GroupsTest, test_initialize_twice) {
96 DeviceGroups::Initialize(callbacks.get());
97 DeviceGroups* dev_groups_p = DeviceGroups::Get();
98 DeviceGroups::Initialize(callbacks.get());
99 ASSERT_EQ(dev_groups_p, DeviceGroups::Get());
100 DeviceGroups::CleanUp(callbacks.get());
101 dev_groups_p->CleanUp(callbacks.get());
102 }
103
TEST_F(GroupsTest,test_cleanup_initialized)104 TEST_F(GroupsTest, test_cleanup_initialized) {
105 DeviceGroups::Initialize(callbacks.get());
106 DeviceGroups::CleanUp(callbacks.get());
107 ASSERT_FALSE(DeviceGroups::Get());
108 }
109
TEST_F(GroupsTest,test_cleanup_uninitialized)110 TEST_F(GroupsTest, test_cleanup_uninitialized) {
111 DeviceGroups::CleanUp(callbacks.get());
112 ASSERT_FALSE(DeviceGroups::Get());
113 }
114
TEST_F(GroupsTest,test_groups_add_single_device)115 TEST_F(GroupsTest, test_groups_add_single_device) {
116 EXPECT_CALL(*callbacks, OnGroupAdded(GetTestAddress(1), Uuid::kEmpty, 7));
117 DeviceGroups::Initialize(callbacks.get());
118 DeviceGroups::Get()->AddDevice(GetTestAddress(1), Uuid::kEmpty, 7);
119 DeviceGroups::CleanUp(callbacks.get());
120 }
121
TEST_F(GroupsTest,test_groups_add_two_devices)122 TEST_F(GroupsTest, test_groups_add_two_devices) {
123 EXPECT_CALL(*callbacks, OnGroupAdded(GetTestAddress(1), _, 7));
124 EXPECT_CALL(*callbacks, OnGroupMemberAdded(GetTestAddress(2), 7));
125 DeviceGroups::Initialize(callbacks.get());
126 DeviceGroups::Get()->AddDevice(GetTestAddress(1), Uuid::kEmpty, 7);
127 DeviceGroups::Get()->AddDevice(GetTestAddress(2), Uuid::kEmpty, 7);
128 DeviceGroups::CleanUp(callbacks.get());
129 }
130
TEST_F(GroupsTest,test_groups_remove_device)131 TEST_F(GroupsTest, test_groups_remove_device) {
132 EXPECT_CALL(*callbacks, OnGroupMemberRemoved(GetTestAddress(2), 7));
133 DeviceGroups::Initialize(callbacks.get());
134 DeviceGroups::Get()->AddDevice(GetTestAddress(2), Uuid::kEmpty, 7);
135 DeviceGroups::Get()->RemoveDevice(GetTestAddress(2));
136 ASSERT_EQ(kGroupUnknown,
137 DeviceGroups::Get()->GetGroupId(GetTestAddress(2), Uuid::kEmpty));
138 ASSERT_EQ(kGroupUnknown,
139 DeviceGroups::Get()->GetGroupId(GetTestAddress(3), Uuid::kEmpty));
140 DeviceGroups::CleanUp(callbacks.get());
141 }
142
TEST_F(GroupsTest,test_add_multiple_devices)143 TEST_F(GroupsTest, test_add_multiple_devices) {
144 EXPECT_CALL(*callbacks, OnGroupAdded(GetTestAddress(2), Uuid::kEmpty, 7));
145 EXPECT_CALL(*callbacks, OnGroupMemberAdded(_, 7)).Times(2);
146 DeviceGroups::Initialize(callbacks.get());
147 DeviceGroups::Get()->AddDevice(GetTestAddress(2), Uuid::kEmpty, 7);
148 DeviceGroups::Get()->AddDevice(GetTestAddress(3), Uuid::kEmpty, 7);
149 DeviceGroups::Get()->AddDevice(GetTestAddress(4), Uuid::kEmpty, 7);
150 DeviceGroups::CleanUp(callbacks.get());
151 }
152
TEST_F(GroupsTest,test_remove_multiple_devices)153 TEST_F(GroupsTest, test_remove_multiple_devices) {
154 EXPECT_CALL(*callbacks, OnGroupMemberRemoved(_, _)).Times(3);
155 DeviceGroups::Initialize(callbacks.get());
156 DeviceGroups::Get()->AddDevice(GetTestAddress(2), Uuid::kEmpty, 7);
157 DeviceGroups::Get()->AddDevice(GetTestAddress(3), Uuid::kEmpty, 7);
158 DeviceGroups::Get()->AddDevice(GetTestAddress(4), Uuid::kEmpty, 7);
159 DeviceGroups::Get()->RemoveDevice(GetTestAddress(2));
160 DeviceGroups::Get()->RemoveDevice(GetTestAddress(3));
161 DeviceGroups::Get()->RemoveDevice(GetTestAddress(4));
162 DeviceGroups::CleanUp(callbacks.get());
163 }
164
TEST_F(GroupsTest,test_add_multiple_groups)165 TEST_F(GroupsTest, test_add_multiple_groups) {
166 EXPECT_CALL(*callbacks, OnGroupAdded(_, _, _)).Times(2);
167 DeviceGroups::Initialize(callbacks.get());
168 DeviceGroups::Get()->AddDevice(GetTestAddress(1), Uuid::kEmpty, 8);
169 DeviceGroups::Get()->AddDevice(GetTestAddress(1), Uuid::kEmpty, 9);
170 DeviceGroups::CleanUp(callbacks.get());
171 }
172
TEST_F(GroupsTest,test_remove_multiple_groups)173 TEST_F(GroupsTest, test_remove_multiple_groups) {
174 Uuid uuid1 = Uuid::GetRandom();
175 Uuid uuid2 = Uuid::GetRandom();
176 ASSERT_NE(uuid1, uuid2);
177
178 EXPECT_CALL(*callbacks, OnGroupAdded(_, _, _)).Times(2);
179 DeviceGroups::Initialize(callbacks.get());
180 DeviceGroups::Get()->AddDevice(GetTestAddress(1), uuid1, 8);
181 DeviceGroups::Get()->AddDevice(GetTestAddress(1), uuid2, 9);
182 DeviceGroups::Get()->AddDevice(GetTestAddress(2), uuid2, 9);
183
184 EXPECT_CALL(*callbacks, OnGroupMemberRemoved(GetTestAddress(1), 8));
185 EXPECT_CALL(*callbacks, OnGroupMemberRemoved(GetTestAddress(1), 9));
186 EXPECT_CALL(*callbacks, OnGroupRemoved(uuid1, 8));
187 EXPECT_CALL(*callbacks, OnGroupRemoved(uuid2, 9)).Times(0);
188 DeviceGroups::Get()->RemoveDevice(GetTestAddress(1));
189
190 DeviceGroups::CleanUp(callbacks.get());
191 }
192
TEST_F(GroupsTest,test_remove_device_fo_devices)193 TEST_F(GroupsTest, test_remove_device_fo_devices) {
194 Uuid uuid1 = Uuid::GetRandom();
195 Uuid uuid2 = Uuid::GetRandom();
196 EXPECT_CALL(*callbacks, OnGroupAdded(_, _, _)).Times(2);
197 DeviceGroups::Initialize(callbacks.get());
198 DeviceGroups::Get()->AddDevice(GetTestAddress(1), uuid1, 8);
199 DeviceGroups::Get()->AddDevice(GetTestAddress(1), uuid2, 9);
200
201 EXPECT_CALL(*callbacks, OnGroupRemoved(uuid1, 8));
202 EXPECT_CALL(*callbacks, OnGroupRemoved(uuid2, 9)).Times(0);
203
204 DeviceGroups::Get()->RemoveDevice(GetTestAddress(1), 8);
205
206 Mock::VerifyAndClearExpectations(&callbacks);
207
208 EXPECT_CALL(*callbacks, OnGroupRemoved(uuid1, 8)).Times(0);
209 EXPECT_CALL(*callbacks, OnGroupRemoved(uuid2, 9));
210
211 DeviceGroups::Get()->RemoveDevice(GetTestAddress(1), 9);
212 }
213
TEST_F(GroupsTest,test_add_devices_different_group_id)214 TEST_F(GroupsTest, test_add_devices_different_group_id) {
215 DeviceGroups::Initialize(callbacks.get());
216 DeviceGroups::Get()->AddDevice(GetTestAddress(2), Uuid::kEmpty, 10);
217 DeviceGroups::Get()->AddDevice(GetTestAddress(3), Uuid::kEmpty, 11);
218 auto group_id_1 =
219 DeviceGroups::Get()->GetGroupId(GetTestAddress(2), Uuid::kEmpty);
220 auto group_id_2 =
221 DeviceGroups::Get()->GetGroupId(GetTestAddress(3), Uuid::kEmpty);
222 ASSERT_TRUE(group_id_1 != group_id_2);
223 DeviceGroups::CleanUp(callbacks.get());
224 }
225
TEST_F(GroupsTest,test_group_id_assign)226 TEST_F(GroupsTest, test_group_id_assign) {
227 int captured_gid1 = kGroupUnknown;
228 int captured_gid2 = kGroupUnknown;
229
230 DeviceGroups::Initialize(callbacks.get());
231 EXPECT_CALL(*callbacks, OnGroupAdded(GetTestAddress(1), _, _))
232 .WillOnce(SaveArg<2>(&captured_gid1));
233 EXPECT_CALL(*callbacks, OnGroupAdded(GetTestAddress(2), _, _))
234 .WillOnce(SaveArg<2>(&captured_gid2));
235
236 int gid1 = DeviceGroups::Get()->AddDevice(GetTestAddress(1), Uuid::kEmpty,
237 bluetooth::groups::kGroupUnknown);
238 int gid2 = DeviceGroups::Get()->AddDevice(GetTestAddress(2), Uuid::kEmpty);
239 int gid3 = DeviceGroups::Get()->AddDevice(GetTestAddress(2), Uuid::kEmpty);
240 ASSERT_NE(bluetooth::groups::kGroupUnknown, gid1);
241 ASSERT_NE(bluetooth::groups::kGroupUnknown, gid2);
242 ASSERT_EQ(gid2, gid3);
243 ASSERT_EQ(gid1, captured_gid1);
244 ASSERT_EQ(gid2, captured_gid2);
245
246 DeviceGroups::CleanUp(callbacks.get());
247 }
248
TEST_F(GroupsTest,test_storage_calls)249 TEST_F(GroupsTest, test_storage_calls) {
250 ASSERT_EQ(0, mock_function_count_map["btif_storage_load_bonded_groups"]);
251 DeviceGroups::Initialize(callbacks.get());
252 ASSERT_EQ(1, mock_function_count_map["btif_storage_load_bonded_groups"]);
253
254 ASSERT_EQ(0, mock_function_count_map["btif_storage_add_groups"]);
255 DeviceGroups::Get()->AddDevice(GetTestAddress(1), Uuid::kEmpty, 7);
256 DeviceGroups::Get()->AddDevice(GetTestAddress(1), Uuid::kEmpty, 8);
257 ASSERT_EQ(2, mock_function_count_map["btif_storage_add_groups"]);
258
259 DeviceGroups::Get()->AddDevice(GetTestAddress(2), Uuid::kEmpty, 7);
260 DeviceGroups::Get()->AddDevice(GetTestAddress(3), Uuid::kEmpty, 7);
261 ASSERT_EQ(4, mock_function_count_map["btif_storage_add_groups"]);
262
263 ASSERT_EQ(0, mock_function_count_map["btif_storage_remove_groups"]);
264 DeviceGroups::Get()->RemoveDevice(GetTestAddress(1));
265 DeviceGroups::Get()->RemoveDevice(GetTestAddress(2));
266 DeviceGroups::Get()->RemoveDevice(GetTestAddress(3));
267 ASSERT_EQ(3, mock_function_count_map["btif_storage_remove_groups"]);
268
269 DeviceGroups::CleanUp(callbacks.get());
270 }
271
TEST_F(GroupsTest,test_storage_content)272 TEST_F(GroupsTest, test_storage_content) {
273 int gid1 = bluetooth::groups::kGroupUnknown;
274 int gid2 = bluetooth::groups::kGroupUnknown;
275 Uuid uuid1 = Uuid::GetRandom();
276 Uuid uuid2 = Uuid::GetRandom();
277 ASSERT_NE(uuid1, uuid2);
278
279 DeviceGroups::Initialize(callbacks.get());
280 gid1 = DeviceGroups::Get()->AddDevice(GetTestAddress(1), uuid1, gid1);
281 DeviceGroups::Get()->AddDevice(GetTestAddress(2), uuid1, gid1);
282 gid2 = DeviceGroups::Get()->AddDevice(GetTestAddress(2), uuid2, gid2);
283 ASSERT_NE(bluetooth::groups::kGroupUnknown, gid1);
284 ASSERT_NE(gid1, gid2);
285
286 std::vector<uint8_t> dev1_storage;
287 std::vector<uint8_t> dev2_storage;
288
289 // Store to byte buffer
290 DeviceGroups::GetForStorage(GetTestAddress(1), dev1_storage);
291 DeviceGroups::GetForStorage(GetTestAddress(2), dev2_storage);
292 ASSERT_NE(0u, dev1_storage.size());
293 ASSERT_TRUE(dev2_storage.size() > dev1_storage.size());
294
295 // Clean it up
296 DeviceGroups::CleanUp(callbacks.get());
297 ASSERT_EQ(nullptr, DeviceGroups::Get());
298
299 // Restore dev1 from the byte buffer
300 DeviceGroups::Initialize(callbacks.get());
301 EXPECT_CALL(*callbacks, OnGroupAdded(GetTestAddress(1), uuid1, gid1));
302 DeviceGroups::AddFromStorage(GetTestAddress(1), dev1_storage);
303
304 // Restore dev2 from the byte buffer
305 EXPECT_CALL(*callbacks, OnGroupAdded(GetTestAddress(2), uuid2, gid2));
306 EXPECT_CALL(*callbacks, OnGroupMemberAdded(GetTestAddress(2), gid1)).Times(1);
307 DeviceGroups::AddFromStorage(GetTestAddress(2), dev2_storage);
308
309 DeviceGroups::CleanUp(callbacks.get());
310 }
311
312 } // namespace groups
313 } // namespace bluetooth
314