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