1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "storage/config_cache.h"
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <cstdio>
23 
24 #include "hci/enum_helper.h"
25 #include "storage/config_keys.h"
26 #include "storage/device.h"
27 
28 namespace testing {
29 
30 namespace {
GetTestAddress(int i)31 std::string GetTestAddress(int i) {
32   std::string res = "00:00:00:00:00:00";
33   res.reserve(res.size() + 1);
34   std::snprintf(res.data(), res.capacity(), "AA:BB:CC:DD:EE:%02d", i);
35   return res;
36 }
37 }  // namespace
38 
39 using bluetooth::storage::ConfigCache;
40 using bluetooth::storage::Device;
41 using SectionAndPropertyValue = bluetooth::storage::ConfigCache::SectionAndPropertyValue;
42 
TEST(ConfigCacheTest,simple_set_get_test)43 TEST(ConfigCacheTest, simple_set_get_test) {
44   ConfigCache config(100, Device::kLinkKeyProperties);
45   config.SetProperty("A", "B", "C");
46   auto value = config.GetProperty("A", "B");
47   ASSERT_TRUE(value);
48   ASSERT_EQ(*value, "C");
49 }
50 
TEST(ConfigCacheTest,empty_values_test)51 TEST(ConfigCacheTest, empty_values_test) {
52   ConfigCache config(100, Device::kLinkKeyProperties);
53   ASSERT_DEATH({ config.SetProperty("", "B", "C"); }, "Empty section name not allowed");
54   ASSERT_DEATH({ config.SetProperty("A", "", "C"); }, "Empty property name not allowed");
55   // empty value is allowed
56   config.SetProperty("A", "B", "");
57   auto value = config.GetProperty("A", "B");
58   ASSERT_TRUE(value);
59   ASSERT_EQ(*value, "");
60 }
61 
TEST(ConfigCacheTest,insert_boundary_device_with_linkkey_test)62 TEST(ConfigCacheTest, insert_boundary_device_with_linkkey_test) {
63   ConfigCache config(2, Device::kLinkKeyProperties);
64   config.SetProperty("A", "B", "C");
65   config.SetProperty("CC:DD:EE:FF:00:10", BTIF_STORAGE_KEY_NAME, "Hello");
66   config.SetProperty("CC:DD:EE:FF:00:09", BTIF_STORAGE_KEY_NAME, "Hello 2");
67   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
68   ASSERT_TRUE(config.GetProperty("CC:DD:EE:FF:00:10", BTIF_STORAGE_KEY_NAME));
69 }
70 
TEST(ConfigCacheTest,comparison_test)71 TEST(ConfigCacheTest, comparison_test) {
72   ConfigCache config_1(2, Device::kLinkKeyProperties);
73   config_1.SetProperty("A", "B", "C");
74   config_1.SetProperty("CC:DD:EE:FF:00:10", BTIF_STORAGE_KEY_NAME, "Hello");
75   config_1.SetProperty("CC:DD:EE:FF:00:09", BTIF_STORAGE_KEY_NAME, "Hello 2");
76   config_1.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
77   ConfigCache config_2(2, Device::kLinkKeyProperties);
78   config_2.SetProperty("A", "B", "C");
79   config_2.SetProperty("CC:DD:EE:FF:00:10", BTIF_STORAGE_KEY_NAME, "Hello");
80   config_2.SetProperty("CC:DD:EE:FF:00:09", BTIF_STORAGE_KEY_NAME, "Hello 2");
81   config_2.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
82   ASSERT_EQ(config_1, config_2);
83   // Config with different temp device order should not be equal
84   ASSERT_TRUE(config_2.GetProperty("CC:DD:EE:FF:00:10", BTIF_STORAGE_KEY_NAME));
85   ASSERT_NE(config_1, config_2);
86   ASSERT_TRUE(config_1.GetProperty("CC:DD:EE:FF:00:10", BTIF_STORAGE_KEY_NAME));
87   ASSERT_EQ(config_1, config_2);
88   // Config with different persistent device order should not be equal
89   config_1.SetProperty("CC:DD:EE:FF:00:12", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
90   config_2.RemoveSection("CC:DD:EE:FF:00:11");
91   config_2.SetProperty("CC:DD:EE:FF:00:12", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
92   config_2.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
93   ASSERT_NE(config_1, config_2);
94   // Config with different capacity should not be equal
95   ConfigCache config_3(3, Device::kLinkKeyProperties);
96   config_3.SetProperty("A", "B", "C");
97   config_3.SetProperty("CC:DD:EE:FF:00:10", BTIF_STORAGE_KEY_NAME, "Hello");
98   config_3.SetProperty("CC:DD:EE:FF:00:09", BTIF_STORAGE_KEY_NAME, "Hello 2");
99   config_3.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
100   config_3.SetProperty("CC:DD:EE:FF:00:12", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
101   ASSERT_NE(config_1, config_3);
102   // Empty config should not be equal to non-empty ones
103   ConfigCache config_4(2, Device::kLinkKeyProperties);
104   ASSERT_NE(config_1, config_4);
105   // Empty configs should be equal
106   ConfigCache config_5(2, Device::kLinkKeyProperties);
107   ASSERT_EQ(config_4, config_5);
108   // Empty configs with different capacity should not be equal
109   ConfigCache config_6(3, Device::kLinkKeyProperties);
110   ASSERT_NE(config_4, config_6);
111 }
112 
TEST(ConfigCacheTest,empty_string_test)113 TEST(ConfigCacheTest, empty_string_test) {
114   ConfigCache config(100, Device::kLinkKeyProperties);
115   config.SetProperty("A", "B", "");
116   auto value = config.GetProperty("A", "B");
117   ASSERT_TRUE(value);
118   ASSERT_EQ(*value, "");
119 }
120 
TEST(ConfigCacheTest,mac_address_set_get_test)121 TEST(ConfigCacheTest, mac_address_set_get_test) {
122   ConfigCache config(100, Device::kLinkKeyProperties);
123   config.SetProperty("A", "B", "C");
124   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
125   auto value = config.GetProperty("A", "B");
126   ASSERT_TRUE(value);
127   ASSERT_EQ(*value, "C");
128   value = config.GetProperty("AA:BB:CC:DD:EE:FF", "B");
129   ASSERT_TRUE(value);
130   ASSERT_EQ(*value, "C");
131   ASSERT_FALSE(config.GetProperty("A", "BC"));
132   ASSERT_FALSE(config.GetProperty("ABC", "B"));
133 }
134 
TEST(ConfigCacheTest,has_section_and_property_test)135 TEST(ConfigCacheTest, has_section_and_property_test) {
136   ConfigCache config(100, Device::kLinkKeyProperties);
137   config.SetProperty("A", "B", "C");
138   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
139   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
140   ASSERT_TRUE(config.HasSection("A"));
141   ASSERT_TRUE(config.HasSection("AA:BB:CC:DD:EE:FF"));
142   ASSERT_TRUE(config.HasProperty("A", "B"));
143   ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
144   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
145   auto value = config.GetProperty("AA:BB:CC:DD:EE:FF", "C");
146   ASSERT_TRUE(value);
147   ASSERT_EQ(*value, "D");
148   value = config.GetProperty("AA:BB:CC:DD:EE:FF", "B");
149   ASSERT_TRUE(value);
150   ASSERT_EQ(*value, "C");
151   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "E");
152   value = config.GetProperty("AA:BB:CC:DD:EE:FF", "B");
153   ASSERT_TRUE(value);
154   ASSERT_THAT(value, Optional(StrEq("E")));
155   ASSERT_FALSE(config.HasSection("Ab"));
156   ASSERT_FALSE(config.HasSection("AA:11:CC:DD:EE:FF"));
157   ASSERT_FALSE(config.HasProperty("A", "bB"));
158   ASSERT_FALSE(config.HasProperty("AA:BB:11:DD:EE:FF", "B"));
159 }
160 
TEST(ConfigCacheTest,remove_section_test)161 TEST(ConfigCacheTest, remove_section_test) {
162   ConfigCache config(100, Device::kLinkKeyProperties);
163   config.SetProperty("A", "B", "C");
164   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
165   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
166   ASSERT_TRUE(config.HasSection("A"));
167   ASSERT_TRUE(config.HasSection("AA:BB:CC:DD:EE:FF"));
168   ASSERT_TRUE(config.HasProperty("A", "B"));
169   ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
170   ASSERT_TRUE(config.RemoveSection("AA:BB:CC:DD:EE:FF"));
171   ASSERT_TRUE(config.RemoveSection("A"));
172   ASSERT_FALSE(config.HasProperty("A", "B"));
173   ASSERT_FALSE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
174 }
175 
TEST(ConfigCacheTest,remove_property_test)176 TEST(ConfigCacheTest, remove_property_test) {
177   ConfigCache config(100, Device::kLinkKeyProperties);
178   config.SetProperty("A", "B", "C");
179   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
180   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
181   ASSERT_TRUE(config.HasSection("A"));
182   ASSERT_TRUE(config.HasSection("AA:BB:CC:DD:EE:FF"));
183   ASSERT_TRUE(config.HasProperty("A", "B"));
184   ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
185   ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "C"));
186   ASSERT_TRUE(config.RemoveProperty("AA:BB:CC:DD:EE:FF", "B"));
187   ASSERT_FALSE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
188   ASSERT_FALSE(config.GetProperty("AA:BB:CC:DD:EE:FF", "B"));
189 }
190 
TEST(ConfigCacheTest,remove_all_properties_from_section_test)191 TEST(ConfigCacheTest, remove_all_properties_from_section_test) {
192   ConfigCache config(100, Device::kLinkKeyProperties);
193   config.SetProperty("A", "B", "C");
194   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
195   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
196   ASSERT_TRUE(config.HasSection("A"));
197   ASSERT_TRUE(config.HasSection("AA:BB:CC:DD:EE:FF"));
198   ASSERT_TRUE(config.HasProperty("A", "B"));
199   ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
200   ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "C"));
201   ASSERT_TRUE(config.RemoveSection("AA:BB:CC:DD:EE:FF"));
202   ASSERT_FALSE(config.HasSection("AA:BB:CC:DD:EE:FF"));
203   ASSERT_FALSE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
204   ASSERT_FALSE(config.GetProperty("AA:BB:CC:DD:EE:FF", "C"));
205 }
206 
TEST(ConfigCacheTest,get_persistent_devices_test)207 TEST(ConfigCacheTest, get_persistent_devices_test) {
208   ConfigCache config(100, Device::kLinkKeyProperties);
209   config.SetProperty("A", "B", "C");
210   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
211   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
212   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
213   ASSERT_TRUE(config.HasProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY));
214   ASSERT_THAT(config.GetPersistentSections(), ElementsAre("CC:DD:EE:FF:00:11"));
215   config.SetProperty("AA:BB:CC:DD:EE:FF", BTIF_STORAGE_KEY_LINK_KEY, "DEERDEERDEER");
216   ASSERT_THAT(config.GetPersistentSections(),
217               ElementsAre("CC:DD:EE:FF:00:11", "AA:BB:CC:DD:EE:FF"));
218   ASSERT_TRUE(config.RemoveProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY));
219   ASSERT_THAT(config.GetPersistentSections(), ElementsAre("AA:BB:CC:DD:EE:FF"));
220 }
221 
TEST(ConfigCacheTest,appoaching_temporary_config_limit_test)222 TEST(ConfigCacheTest, appoaching_temporary_config_limit_test) {
223   ConfigCache config(2, Device::kLinkKeyProperties);
224   for (int i = 0; i < 10; ++i) {
225     config.SetProperty(GetTestAddress(i), BTIF_STORAGE_KEY_NAME, "Hello" + std::to_string(i));
226     if (i % 2 == 0) {
227       config.SetProperty(GetTestAddress(i), BTIF_STORAGE_KEY_LINK_KEY, "Key" + std::to_string(i));
228     }
229   }
230   for (int i = 0; i < 10; ++i) {
231     if (i % 2 == 0) {
232       ASSERT_TRUE(config.HasSection(GetTestAddress(i)));
233       ASSERT_TRUE(config.HasProperty(GetTestAddress(i), BTIF_STORAGE_KEY_LINK_KEY));
234       ASSERT_THAT(config.GetProperty(GetTestAddress(i), BTIF_STORAGE_KEY_NAME),
235                   Optional(StrEq("Hello" + std::to_string(i))));
236     } else if (i >= 7) {
237       ASSERT_TRUE(config.HasSection(GetTestAddress(i)));
238       ASSERT_THAT(config.GetProperty(GetTestAddress(i), BTIF_STORAGE_KEY_NAME),
239                   Optional(StrEq("Hello" + std::to_string(i))));
240     } else {
241       ASSERT_FALSE(config.HasSection(GetTestAddress(i)));
242     }
243   }
244   ASSERT_THAT(config.GetPersistentSections(),
245               ElementsAre(GetTestAddress(0), GetTestAddress(2), GetTestAddress(4),
246                           GetTestAddress(6), GetTestAddress(8)));
247 }
248 
TEST(ConfigCacheTest,remove_section_with_property_test)249 TEST(ConfigCacheTest, remove_section_with_property_test) {
250   ConfigCache config(100, Device::kLinkKeyProperties);
251   config.SetProperty("A", "B", "C");
252   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
253   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
254   config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
255   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
256   config.RemoveSectionWithProperty("B");
257   ASSERT_FALSE(config.HasSection("A"));
258   ASSERT_FALSE(config.HasSection("AA:BB:CC:DD:EE:FF"));
259   ASSERT_FALSE(config.HasSection("CC:DD:EE:FF:00:11"));
260 }
261 
TEST(ConfigCacheTest,persistent_config_changed_callback_test)262 TEST(ConfigCacheTest, persistent_config_changed_callback_test) {
263   ConfigCache config(100, Device::kLinkKeyProperties);
264   int num_change = 0;
265   config.SetPersistentConfigChangedCallback([&num_change] { num_change++; });
266   config.SetProperty("A", "B", "C");
267   ASSERT_EQ(num_change, 1);
268   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
269   ASSERT_EQ(num_change, 1);
270   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
271   ASSERT_EQ(num_change, 1);
272   config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
273   ASSERT_EQ(num_change, 1);
274   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
275   ASSERT_EQ(num_change, 2);
276   config.RemoveProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY);
277   ASSERT_EQ(num_change, 3);
278   config.RemoveSectionWithProperty("B");
279   ASSERT_EQ(num_change, 4);
280 }
281 
TEST(ConfigCacheTest,fix_device_type_inconsistency_missing_devtype_no_keys_test)282 TEST(ConfigCacheTest, fix_device_type_inconsistency_missing_devtype_no_keys_test) {
283   ConfigCache config(100, Device::kLinkKeyProperties);
284   config.SetProperty("A", "B", "C");
285   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
286   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
287 
288   auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
289 
290   ASSERT_TRUE(hadInconsistencies);
291   ASSERT_THAT(config.GetProperty("AA:BB:CC:DD:EE:FF", BTIF_STORAGE_KEY_DEV_TYPE),
292               Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::BR_EDR))));
293 }
294 
TEST(ConfigCacheTest,fix_device_type_inconsistency_consistent_devtype_test)295 TEST(ConfigCacheTest, fix_device_type_inconsistency_consistent_devtype_test) {
296   // arrange
297   ConfigCache config(100, Device::kLinkKeyProperties);
298   config.SetProperty("A", "B", "C");
299   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
300   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
301   config.SetProperty("AA:BB:CC:DD:EE:FF", BTIF_STORAGE_KEY_DEV_TYPE,
302                      std::to_string(bluetooth::hci::DeviceType::BR_EDR));
303 
304   config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
305   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_DEV_TYPE,
306                      std::to_string(bluetooth::hci::DeviceType::BR_EDR));
307   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
308 
309   // act
310   auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
311 
312   // assert
313   ASSERT_FALSE(hadInconsistencies);
314   ASSERT_THAT(config.GetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_DEV_TYPE),
315               Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::BR_EDR))));
316 }
317 
TEST(ConfigCacheTest,fix_device_type_inconsistency_devtype_should_be_dual_test)318 TEST(ConfigCacheTest, fix_device_type_inconsistency_devtype_should_be_dual_test) {
319   // arrange
320   ConfigCache config(100, Device::kLinkKeyProperties);
321   config.SetProperty("A", "B", "C");
322   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
323   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
324   config.SetProperty("AA:BB:CC:DD:EE:FF", BTIF_STORAGE_KEY_DEV_TYPE,
325                      std::to_string(bluetooth::hci::DeviceType::BR_EDR));
326 
327   config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
328   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_DEV_TYPE,
329                      std::to_string(bluetooth::hci::DeviceType::BR_EDR));
330   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
331   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LE_KEY_PENC, "AABBAABBCCDDEE");
332 
333   // act
334   auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
335 
336   // assert
337   ASSERT_TRUE(hadInconsistencies);
338   ASSERT_THAT(config.GetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_DEV_TYPE),
339               Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::DUAL))));
340 }
341 
TEST(ConfigCacheTest,fix_device_type_inconsistency_devtype_should_be_le_not_classic_test)342 TEST(ConfigCacheTest, fix_device_type_inconsistency_devtype_should_be_le_not_classic_test) {
343   // arrange
344   ConfigCache config(100, Device::kLinkKeyProperties);
345   config.SetProperty("A", "B", "C");
346   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
347   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
348   config.SetProperty("AA:BB:CC:DD:EE:FF", BTIF_STORAGE_KEY_DEV_TYPE,
349                      std::to_string(bluetooth::hci::DeviceType::BR_EDR));
350 
351   config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
352   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_DEV_TYPE,
353                      std::to_string(bluetooth::hci::DeviceType::BR_EDR));
354   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LE_KEY_PENC, "AABBAABBCCDDEE");
355 
356   // act
357   auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
358 
359   // assert
360   ASSERT_TRUE(hadInconsistencies);
361   ASSERT_THAT(config.GetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_DEV_TYPE),
362               Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::LE))));
363 }
364 
TEST(ConfigCacheTest,fix_device_type_inconsistency_devtype_dont_override_dual_test)365 TEST(ConfigCacheTest, fix_device_type_inconsistency_devtype_dont_override_dual_test) {
366   // arrange
367   ConfigCache config(100, Device::kLinkKeyProperties);
368   config.SetProperty("A", "B", "C");
369   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
370   config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
371   config.SetProperty("AA:BB:CC:DD:EE:FF", BTIF_STORAGE_KEY_DEV_TYPE,
372                      std::to_string(bluetooth::hci::DeviceType::BR_EDR));
373 
374   config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
375   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_DEV_TYPE,
376                      std::to_string(bluetooth::hci::DeviceType::DUAL));
377   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
378   config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LE_KEY_PENC, "AABBAABBCCDDEE");
379 
380   // act
381   auto hadInconsistencies = config.FixDeviceTypeInconsistencies();
382 
383   // assert
384   ASSERT_FALSE(hadInconsistencies);
385   ASSERT_THAT(config.GetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_DEV_TYPE),
386               Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::DUAL))));
387 }
388 
TEST(ConfigCacheTest,test_get_section_with_property)389 TEST(ConfigCacheTest, test_get_section_with_property) {
390   ConfigCache config(100, Device::kLinkKeyProperties);
391   config.SetProperty("A", "B", "C");
392   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
393   config.SetProperty("AA:BB:CC:DD:EE:EF", "C", "D");
394   ASSERT_THAT(
395           config.GetSectionNamesWithProperty("B"),
396           ElementsAre(SectionAndPropertyValue{.section = "A", .property = "C"},
397                       SectionAndPropertyValue{.section = "AA:BB:CC:DD:EE:FF", .property = "C"}));
398 }
399 
TEST(ConfigCacheTest,test_get_sections_matching_at_least_one_property)400 TEST(ConfigCacheTest, test_get_sections_matching_at_least_one_property) {
401   ConfigCache config(100, Device::kLinkKeyProperties);
402   config.SetProperty("A", "B", "C");
403   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
404   config.SetProperty("AA:BB:CC:DD:EE:EF", "C", "D");
405   ASSERT_TRUE(
406           config.HasAtLeastOneMatchingPropertiesInSection("AA:BB:CC:DD:EE:FF", {"B", "C", "D"}));
407   ASSERT_TRUE(config.HasAtLeastOneMatchingPropertiesInSection("A", {"B", "C", "D"}));
408   ASSERT_FALSE(config.HasAtLeastOneMatchingPropertiesInSection("AA:BB:CC:DD:EE:FF", {"BC", "D"}));
409 }
410 
TEST(ConfigCacheTest,test_empty_persistent_properties)411 TEST(ConfigCacheTest, test_empty_persistent_properties) {
412   ConfigCache config(100, {});
413   config.SetProperty("A", "B", "C");
414   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
415   config.SetProperty("AA:BB:CC:DD:EE:EF", "C", "D");
416   config.SetProperty("AA:BB:CC:DD:EE:EF", BTIF_STORAGE_KEY_LINK_KEY, "D");
417   ASSERT_TRUE(
418           config.HasAtLeastOneMatchingPropertiesInSection("AA:BB:CC:DD:EE:FF", {"B", "C", "D"}));
419   ASSERT_TRUE(config.HasAtLeastOneMatchingPropertiesInSection("A", {"B", "C", "D"}));
420   ASSERT_FALSE(config.HasAtLeastOneMatchingPropertiesInSection("AA:BB:CC:DD:EE:FF", {"BC", "D"}));
421   ASSERT_THAT(config.GetPersistentSections(), ElementsAre());
422 }
423 
TEST(ConfigCacheTest,test_get_section_property_names)424 TEST(ConfigCacheTest, test_get_section_property_names) {
425   ConfigCache config(100, Device::kLinkKeyProperties);
426   config.SetProperty("A", "A", "A");
427   config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "B");
428   config.SetProperty("AA:BB:CC:DD:EE:EF", BTIF_STORAGE_KEY_LINK_KEY, "C");
429 
430   ASSERT_THAT(config.GetPropertyNames("A"), ElementsAre("A"));
431   ASSERT_THAT(config.GetPropertyNames("AA:BB:CC:DD:EE:FF"), ElementsAre("B"));
432   ASSERT_THAT(config.GetPropertyNames("AA:BB:CC:DD:EE:EF"), ElementsAre(BTIF_STORAGE_KEY_LINK_KEY));
433   ASSERT_THAT(config.GetPropertyNames("D"), ElementsAre());
434 }
435 
436 }  // namespace testing
437