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