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