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