• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2020 Google, Inc.
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 "common/metric_id_manager.h"
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include <thread>
24 
25 namespace testing {
26 
27 using bluetooth::common::MetricIdManager;
28 
kthAddress(uint32_t k)29 static bluetooth::hci::Address kthAddress(uint32_t k) {
30   uint8_t array[6] = {0, 0, 0, 0, 0, 0};
31   for (int i = 5; i >= 2; i--) {
32     array[i] = k % 256;
33     k = k / 256;
34   }
35   bluetooth::hci::Address addr(array);
36   return addr;
37 }
38 
generateAddresses(const uint32_t num)39 static std::unordered_map<bluetooth::hci::Address, int> generateAddresses(const uint32_t num) {
40   // generate first num of mac address -> id pairs
41   // input may is always valid 256^6 = 2^48 > 2^32
42   std::unordered_map<bluetooth::hci::Address, int> device_map;
43   for (size_t key = 0; key < num; key++) {
44     device_map[kthAddress(key)] = key + MetricIdManager::kMinId;
45   }
46   return device_map;
47 }
48 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerInitCloseTest)49 TEST(BluetoothMetricIdManagerTest, MetricIdManagerInitCloseTest) {
50   auto& manager = MetricIdManager::GetInstance();
51   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
52   MetricIdManager::Callback callback = [](const bluetooth::hci::Address&, const int) {
53     return true;
54   };
55   ASSERT_TRUE(manager.Init(paired_device_map, callback, callback));
56   ASSERT_FALSE(manager.Init(paired_device_map, callback, callback));
57   ASSERT_TRUE(manager.Close());
58 }
59 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerNotCloseTest)60 TEST(BluetoothMetricIdManagerTest, MetricIdManagerNotCloseTest) {
61   auto& manager = MetricIdManager::GetInstance();
62   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
63   MetricIdManager::Callback callback = [](const bluetooth::hci::Address&, const int) {
64     return true;
65   };
66   ASSERT_TRUE(manager.Init(paired_device_map, callback, callback));
67 
68   // should fail because it isn't closed
69   ASSERT_FALSE(manager.Init(paired_device_map, callback, callback));
70   ASSERT_TRUE(manager.Close());
71 }
72 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerScanDeviceFromEmptyTest)73 TEST(BluetoothMetricIdManagerTest, MetricIdManagerScanDeviceFromEmptyTest) {
74   auto& manager = MetricIdManager::GetInstance();
75   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
76   MetricIdManager::Callback callback = [](const bluetooth::hci::Address&, const int) {
77     return true;
78   };
79   // test empty map, next id should be kMinId
80   ASSERT_TRUE(manager.Init(paired_device_map, callback, callback));
81   ASSERT_EQ(manager.AllocateId(kthAddress(0)), MetricIdManager::kMinId);
82   ASSERT_EQ(manager.AllocateId(kthAddress(1)), MetricIdManager::kMinId + 1);
83   ASSERT_EQ(manager.AllocateId(kthAddress(0)), MetricIdManager::kMinId);
84   ASSERT_EQ(manager.AllocateId(kthAddress(2)), MetricIdManager::kMinId + 2);
85   ASSERT_TRUE(manager.Close());
86 }
87 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerScanDeviceFromFilledTest)88 TEST(BluetoothMetricIdManagerTest, MetricIdManagerScanDeviceFromFilledTest) {
89   auto& manager = MetricIdManager::GetInstance();
90   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
91   MetricIdManager::Callback callback = [](const bluetooth::hci::Address&, const int) {
92     return true;
93   };
94   int id =
95           static_cast<int>(MetricIdManager::kMaxNumPairedDevicesInMemory) + MetricIdManager::kMinId;
96   // next id should be MetricIdManager::kMaxNumPairedDevicesInMemory
97   paired_device_map = generateAddresses(MetricIdManager::kMaxNumPairedDevicesInMemory);
98   ASSERT_TRUE(manager.Init(paired_device_map, callback, callback));
99   // try new values not in the map, should get new id.
100   ASSERT_EQ(manager.AllocateId(kthAddress(INT_MAX)), id);
101   ASSERT_EQ(manager.AllocateId(kthAddress(INT_MAX - 1)), id + 1);
102   ASSERT_EQ(manager.AllocateId(kthAddress(INT_MAX)), id);
103   ASSERT_EQ(manager.AllocateId(kthAddress(INT_MAX - 2)), id + 2);
104   ASSERT_TRUE(manager.Close());
105 }
106 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerAllocateExistingTest)107 TEST(BluetoothMetricIdManagerTest, MetricIdManagerAllocateExistingTest) {
108   auto& manager = MetricIdManager::GetInstance();
109   std::unordered_map<bluetooth::hci::Address, int> paired_device_map =
110           generateAddresses(MetricIdManager::kMaxNumPairedDevicesInMemory);
111 
112   MetricIdManager::Callback callback = [](const bluetooth::hci::Address&, const int) {
113     return true;
114   };
115   int id = MetricIdManager::kMinId;
116   // next id should be MetricIdManager::kMaxNumPairedDevicesInMemory
117   ASSERT_TRUE(manager.Init(paired_device_map, callback, callback));
118 
119   // try values already in the map, should get new id.
120   ASSERT_EQ(manager.AllocateId(bluetooth::hci::Address({0, 0, 0, 0, 0, 0})), id);
121   ASSERT_EQ(manager.AllocateId(bluetooth::hci::Address({0, 0, 0, 0, 0, 1})), id + 1);
122   ASSERT_EQ(manager.AllocateId(bluetooth::hci::Address({0, 0, 0, 0, 0, 0})), id);
123   ASSERT_EQ(manager.AllocateId(bluetooth::hci::Address({0, 0, 0, 0, 0, 2})), id + 2);
124   ASSERT_TRUE(manager.Close());
125 }
126 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerMainTest1)127 TEST(BluetoothMetricIdManagerTest, MetricIdManagerMainTest1) {
128   auto& manager = MetricIdManager::GetInstance();
129   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
130   int placeholder = 22;
131   int* pointer = &placeholder;
132   MetricIdManager::Callback save_callback = [pointer](const bluetooth::hci::Address&, const int) {
133     *pointer = *pointer * 2;
134     return true;
135   };
136   MetricIdManager::Callback forget_callback = [pointer](const bluetooth::hci::Address&, const int) {
137     *pointer = *pointer / 2;
138     return true;
139   };
140 
141   ASSERT_TRUE(manager.Init(paired_device_map, save_callback, forget_callback));
142   ASSERT_EQ(manager.AllocateId(bluetooth::hci::Address({0, 0, 0, 0, 0, 0})),
143             MetricIdManager::kMinId);
144   // save it and make sure the callback is called
145   ASSERT_TRUE(manager.SaveDevice(bluetooth::hci::Address({0, 0, 0, 0, 0, 0})));
146   ASSERT_EQ(placeholder, 44);
147 
148   // should fail, since id of device is not allocated
149   ASSERT_FALSE(manager.SaveDevice(bluetooth::hci::Address({0, 0, 0, 0, 0, 1})));
150   ASSERT_EQ(placeholder, 44);
151 
152   // save it and make sure the callback is called
153   ASSERT_EQ(manager.AllocateId(bluetooth::hci::Address({0, 0, 0, 0, 0, 2})),
154             MetricIdManager::kMinId + 1);
155   ASSERT_EQ(manager.AllocateId(bluetooth::hci::Address({0, 0, 0, 0, 0, 3})),
156             MetricIdManager::kMinId + 2);
157   ASSERT_TRUE(manager.SaveDevice(bluetooth::hci::Address({0, 0, 0, 0, 0, 2})));
158   ASSERT_EQ(placeholder, 88);
159   ASSERT_TRUE(manager.SaveDevice(bluetooth::hci::Address({0, 0, 0, 0, 0, 3})));
160   ASSERT_EQ(placeholder, 176);
161 
162   // should be true but callback won't be called, since id had been saved
163   ASSERT_TRUE(manager.SaveDevice(bluetooth::hci::Address({0, 0, 0, 0, 0, 0})));
164   ASSERT_EQ(placeholder, 176);
165 
166   // forget
167   manager.ForgetDevice(bluetooth::hci::Address({0, 0, 0, 0, 0, 1}));
168   ASSERT_EQ(placeholder, 176);
169   manager.ForgetDevice(bluetooth::hci::Address({0, 0, 0, 0, 0, 2}));
170   ASSERT_EQ(placeholder, 88);
171 
172   ASSERT_TRUE(manager.Close());
173 }
174 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerFullPairedMap)175 TEST(BluetoothMetricIdManagerTest, MetricIdManagerFullPairedMap) {
176   auto& manager = MetricIdManager::GetInstance();
177   // preset a full map
178   std::unordered_map<bluetooth::hci::Address, int> paired_device_map =
179           generateAddresses(MetricIdManager::kMaxNumPairedDevicesInMemory);
180   int placeholder = 243;
181   int* pointer = &placeholder;
182   MetricIdManager::Callback save_callback = [pointer](const bluetooth::hci::Address&, const int) {
183     *pointer = *pointer * 2;
184     return true;
185   };
186   MetricIdManager::Callback forget_callback = [pointer](const bluetooth::hci::Address&, const int) {
187     *pointer = *pointer / 3;
188     return true;
189   };
190 
191   ASSERT_TRUE(manager.Init(paired_device_map, save_callback, forget_callback));
192 
193   // check if all preset ids are there.
194   // comments based on kMaxNumPairedDevicesInMemory = 200. It can change.
195   int key = 0;
196   for (key = 0; key < static_cast<int>(MetricIdManager::kMaxNumPairedDevicesInMemory); key++) {
197     ASSERT_EQ(manager.AllocateId(kthAddress(key)), key + MetricIdManager::kMinId);
198   }
199   // paired: 0, 1, 2 ... 199,
200   // scanned:
201 
202   int id =
203           static_cast<int>(MetricIdManager::kMaxNumPairedDevicesInMemory + MetricIdManager::kMinId);
204   // next id should be MetricIdManager::kMaxNumPairedDevicesInMemory +
205   // MetricIdManager::kMinId
206 
207   ASSERT_EQ(manager.AllocateId(kthAddress(key)), id++);
208   // paired: 0, 1, 2 ... 199,
209   // scanned: 200
210 
211   // save it and make sure the callback is called
212   ASSERT_TRUE(manager.SaveDevice(kthAddress(key)));
213   // one key is evicted, another key is saved so *2/3
214   ASSERT_EQ(placeholder, 162);
215 
216   // paired: 1, 2 ... 199, 200,
217   // scanned:
218 
219   ASSERT_EQ(manager.AllocateId(kthAddress(0)), id++);
220   // paired: 1, 2 ... 199, 200
221   // scanned: 0
222 
223   // key == 200
224   // should fail, since id of device is not allocated
225   ASSERT_FALSE(manager.SaveDevice(kthAddress(key + 1)));
226   ASSERT_EQ(placeholder, 162);
227   // paired: 1, 2 ... 199, 200,
228   // scanned: 0
229 
230   ASSERT_EQ(manager.AllocateId(kthAddress(key + 1)), id++);
231   ASSERT_TRUE(manager.SaveDevice(kthAddress(key + 1)));
232   // one key is evicted, another key is saved so *2/3,
233   ASSERT_EQ(placeholder, 108);
234   // paired: 2 ... 199, 200, 201
235   // scanned: 0
236 
237   ASSERT_EQ(manager.AllocateId(kthAddress(1)), id++);
238   // paired: 2 ... 199, 200, 201,
239   // scanned: 0, 1
240 
241   // save it and make sure the callback is called
242   ASSERT_EQ(manager.AllocateId(kthAddress(key + 2)), id++);
243   ASSERT_EQ(manager.AllocateId(kthAddress(key + 3)), id++);
244   // paired: 2 ... 199, 200, 201,
245   // scanned: 0, 1, 202, 203
246 
247   placeholder = 9;
248   ASSERT_TRUE(manager.SaveDevice(kthAddress(key + 2)));
249   // one key is evicted, another key is saved so *2/3,
250   ASSERT_EQ(placeholder, 6);
251   ASSERT_TRUE(manager.SaveDevice(kthAddress(key + 3)));
252   // one key is evicted, another key is saved so *2/3,
253   ASSERT_EQ(placeholder, 4);
254   // paired: 4 ... 199, 200, 201, 202, 203
255   // scanned: 0, 1
256 
257   // should be true but callback won't be called, since id had been saved
258   ASSERT_TRUE(manager.SaveDevice(kthAddress(key + 2)));
259   ASSERT_EQ(placeholder, 4);
260 
261   placeholder = 27;
262   // forget
263   manager.ForgetDevice(kthAddress(key + 200));
264   ASSERT_EQ(placeholder, 27);  // should fail, no such a key
265   manager.ForgetDevice(kthAddress(key + 2));
266   ASSERT_EQ(placeholder, 9);
267   // paired: 4 ... 199, 200, 201, 203
268   // scanned: 0, 1
269 
270   // save it and make sure the callback is called
271   ASSERT_EQ(manager.AllocateId(kthAddress(key + 2)), id++);
272   ASSERT_EQ(manager.AllocateId(kthAddress(key + 4)), id++);
273   ASSERT_EQ(manager.AllocateId(kthAddress(key + 5)), id++);
274   // paired: 4 ... 199, 200, 201, 203
275   // scanned: 0, 1, 202, 204, 205
276 
277   ASSERT_TRUE(manager.SaveDevice(kthAddress(key + 2)));
278   ASSERT_EQ(placeholder, 18);  // no key is evicted, a key is saved so *2,
279 
280   // should be true but callback won't be called, since id had been saved
281   ASSERT_TRUE(manager.SaveDevice(kthAddress(key + 3)));
282   ASSERT_EQ(placeholder, 18);  // no such a key in scanned
283   ASSERT_TRUE(manager.SaveDevice(kthAddress(key + 4)));
284   // one key is evicted, another key is saved so *2/3
285   ASSERT_EQ(placeholder, 12);
286   // paired: 5 6 ... 199, 200, 201, 203, 202, 204
287   // scanned: 0, 1, 205
288 
289   // verify paired:
290   for (key = 5; key <= 199; key++) {
291     placeholder = 3;
292     manager.ForgetDevice(kthAddress(key));
293     ASSERT_EQ(placeholder, 1);
294   }
295   for (size_t k = MetricIdManager::kMaxNumPairedDevicesInMemory;
296        k <= MetricIdManager::kMaxNumPairedDevicesInMemory + 4; k++) {
297     placeholder = 3;
298     manager.ForgetDevice(kthAddress(k));
299     ASSERT_EQ(placeholder, 1);
300   }
301 
302   // verify scanned
303   placeholder = 4;
304   ASSERT_TRUE(manager.SaveDevice(kthAddress(0)));
305   ASSERT_TRUE(manager.SaveDevice(kthAddress(1)));
306   ASSERT_TRUE(manager.SaveDevice(kthAddress(MetricIdManager::kMaxNumPairedDevicesInMemory + 5)));
307   ASSERT_EQ(placeholder, 32);
308 
309   ASSERT_TRUE(manager.Close());
310 }
311 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerFullScannedMap)312 TEST(BluetoothMetricIdManagerTest, MetricIdManagerFullScannedMap) {
313   auto& manager = MetricIdManager::GetInstance();
314   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
315   int placeholder = 22;
316   int* pointer = &placeholder;
317   MetricIdManager::Callback save_callback = [pointer](const bluetooth::hci::Address&, const int) {
318     *pointer = *pointer * 2;
319     return true;
320   };
321   MetricIdManager::Callback forget_callback = [pointer](const bluetooth::hci::Address&, const int) {
322     *pointer = *pointer / 2;
323     return true;
324   };
325 
326   ASSERT_TRUE(manager.Init(paired_device_map, save_callback, forget_callback));
327 
328   // allocate kMaxNumUnpairedDevicesInMemory ids
329   // comments based on kMaxNumUnpairedDevicesInMemory = 200
330   for (int key = 0; key < static_cast<int>(MetricIdManager::kMaxNumUnpairedDevicesInMemory);
331        key++) {
332     ASSERT_EQ(manager.AllocateId(kthAddress(key)), key + MetricIdManager::kMinId);
333   }
334   // scanned: 0, 1, 2 ... 199,
335   // paired:
336 
337   int id = MetricIdManager::kMaxNumUnpairedDevicesInMemory + MetricIdManager::kMinId;
338   bluetooth::hci::Address addr = kthAddress(MetricIdManager::kMaxNumUnpairedDevicesInMemory);
339   ASSERT_EQ(manager.AllocateId(addr), id);
340   // scanned: 1, 2 ... 199, 200
341 
342   // save it and make sure the callback is called
343   ASSERT_TRUE(manager.SaveDevice(addr));
344   ASSERT_EQ(manager.AllocateId(addr), id);
345   ASSERT_EQ(placeholder, 44);
346   // paired: 200,
347   // scanned: 1, 2 ... 199,
348   id++;
349 
350   addr = kthAddress(MetricIdManager::kMaxNumUnpairedDevicesInMemory + 1);
351   ASSERT_EQ(manager.AllocateId(addr), id++);
352   // paired: 200,
353   // scanned: 1, 2 ... 199, 201
354 
355   // try to allocate for device 0, 1, 2, 3, 4....199
356   // we should have a new id every time,
357   // since the scanned map is full at this point
358   for (int key = 0; key < static_cast<int>(MetricIdManager::kMaxNumUnpairedDevicesInMemory);
359        key++) {
360     ASSERT_EQ(manager.AllocateId(kthAddress(key)), id++);
361   }
362   ASSERT_TRUE(manager.Close());
363 }
364 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerMultiThreadPressureTest)365 TEST(BluetoothMetricIdManagerTest, MetricIdManagerMultiThreadPressureTest) {
366   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
367   auto& manager = MetricIdManager::GetInstance();
368   int placeholder = 22;
369   int* pointer = &placeholder;
370   MetricIdManager::Callback save_callback = [pointer](const bluetooth::hci::Address&, const int) {
371     *pointer = *pointer + 1;
372     return true;
373   };
374   MetricIdManager::Callback forget_callback = [pointer](const bluetooth::hci::Address&, const int) {
375     *pointer = *pointer - 1;
376     return true;
377   };
378   ASSERT_TRUE(manager.Init(paired_device_map, save_callback, forget_callback));
379 
380   // make sure no deadlock
381   std::vector<std::thread> workers;
382   for (int key = 0; key < static_cast<int>(MetricIdManager::kMaxNumUnpairedDevicesInMemory);
383        key++) {
384     workers.push_back(std::thread([key]() {
385       auto& manager = MetricIdManager::GetInstance();
386       bluetooth::hci::Address fake_mac_address = kthAddress(key);
387       manager.AllocateId(fake_mac_address);
388       ASSERT_TRUE(manager.SaveDevice(fake_mac_address));
389       manager.ForgetDevice(fake_mac_address);
390     }));
391   }
392   for (auto& worker : workers) {
393     worker.join();
394   }
395   ASSERT_TRUE(manager.IsEmpty());
396   ASSERT_TRUE(manager.Close());
397 }
398 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerWrapAroundTest1)399 TEST(BluetoothMetricIdManagerTest, MetricIdManagerWrapAroundTest1) {
400   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
401   auto& manager = MetricIdManager::GetInstance();
402   MetricIdManager::Callback callback = [](const bluetooth::hci::Address&, const int) {
403     return true;
404   };
405 
406   // make a sparse paired_device_map
407   int min_id = MetricIdManager::kMinId;
408   paired_device_map[kthAddress(min_id)] = min_id;
409   paired_device_map[kthAddress(min_id + 1)] = min_id + 1;
410   paired_device_map[kthAddress(min_id + 3)] = min_id + 3;
411   paired_device_map[kthAddress(min_id + 4)] = min_id + 4;
412 
413   int max_id = MetricIdManager::kMaxId;
414   paired_device_map[kthAddress(max_id - 3)] = max_id - 3;
415   paired_device_map[kthAddress(max_id - 4)] = max_id - 4;
416 
417   ASSERT_TRUE(manager.Init(paired_device_map, callback, callback));
418 
419   // next id should be max_id - 2, max_id - 1, max_id, min_id + 2, min_id + 5
420   ASSERT_EQ(manager.AllocateId(kthAddress(max_id - 2)), max_id - 2);
421   ASSERT_EQ(manager.AllocateId(kthAddress(max_id - 1)), max_id - 1);
422   ASSERT_EQ(manager.AllocateId(kthAddress(max_id)), max_id);
423   ASSERT_EQ(manager.AllocateId(kthAddress(min_id + 2)), min_id + 2);
424   ASSERT_EQ(manager.AllocateId(kthAddress(min_id + 5)), min_id + 5);
425 
426   ASSERT_TRUE(manager.Close());
427 }
428 
TEST(BluetoothMetricIdManagerTest,MetricIdManagerWrapAroundTest2)429 TEST(BluetoothMetricIdManagerTest, MetricIdManagerWrapAroundTest2) {
430   std::unordered_map<bluetooth::hci::Address, int> paired_device_map;
431   auto& manager = MetricIdManager::GetInstance();
432   MetricIdManager::Callback callback = [](const bluetooth::hci::Address&, const int) {
433     return true;
434   };
435 
436   // make a sparse paired_device_map
437   int min_id = MetricIdManager::kMinId;
438   int max_id = MetricIdManager::kMaxId;
439   paired_device_map[kthAddress(max_id)] = max_id;
440 
441   ASSERT_TRUE(manager.Init(paired_device_map, callback, callback));
442 
443   // next id should be min_id, min_id + 1
444   ASSERT_EQ(manager.AllocateId(kthAddress(min_id)), min_id);
445   ASSERT_EQ(manager.AllocateId(kthAddress(min_id + 1)), min_id + 1);
446 
447   ASSERT_TRUE(manager.Close());
448 }
449 
450 }  // namespace testing
451