aboutsummaryrefslogtreecommitdiff
path: root/gd/storage/config_cache_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gd/storage/config_cache_test.cc')
-rw-r--r--gd/storage/config_cache_test.cc340
1 files changed, 340 insertions, 0 deletions
diff --git a/gd/storage/config_cache_test.cc b/gd/storage/config_cache_test.cc
new file mode 100644
index 000000000..bec056f70
--- /dev/null
+++ b/gd/storage/config_cache_test.cc
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "storage/config_cache.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <cstdio>
+
+#include "hci/enum_helper.h"
+#include "storage/device.h"
+
+namespace testing {
+
+namespace {
+std::string GetTestAddress(int i) {
+ std::string res = "00:00:00:00:00:00";
+ res.reserve(res.size() + 1);
+ std::snprintf(res.data(), res.capacity(), "AA:BB:CC:DD:EE:%02d", i);
+ return res;
+}
+} // namespace
+
+using bluetooth::storage::ConfigCache;
+using bluetooth::storage::Device;
+using SectionAndPropertyValue = bluetooth::storage::ConfigCache::SectionAndPropertyValue;
+
+TEST(ConfigCacheTest, simple_set_get_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ auto value = config.GetProperty("A", "B");
+ ASSERT_TRUE(value);
+ ASSERT_EQ(*value, "C");
+}
+
+TEST(ConfigCacheTest, empty_values_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ ASSERT_DEATH({ config.SetProperty("", "B", "C"); }, "Empty section name not allowed");
+ ASSERT_DEATH({ config.SetProperty("A", "", "C"); }, "Empty property name not allowed");
+ // empty value is allowed
+ config.SetProperty("A", "B", "");
+ auto value = config.GetProperty("A", "B");
+ ASSERT_TRUE(value);
+ ASSERT_EQ(*value, "");
+}
+
+TEST(ConfigCacheTest, insert_boundary_device_with_linkkey_test) {
+ ConfigCache config(2, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("CC:DD:EE:FF:00:10", "Name", "Hello");
+ config.SetProperty("CC:DD:EE:FF:00:09", "Name", "Hello 2");
+ config.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ ASSERT_TRUE(config.GetProperty("CC:DD:EE:FF:00:10", "Name"));
+}
+
+TEST(ConfigCacheTest, comparison_test) {
+ ConfigCache config_1(2, Device::kLinkKeyProperties);
+ config_1.SetProperty("A", "B", "C");
+ config_1.SetProperty("CC:DD:EE:FF:00:10", "Name", "Hello");
+ config_1.SetProperty("CC:DD:EE:FF:00:09", "Name", "Hello 2");
+ config_1.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ ConfigCache config_2(2, Device::kLinkKeyProperties);
+ config_2.SetProperty("A", "B", "C");
+ config_2.SetProperty("CC:DD:EE:FF:00:10", "Name", "Hello");
+ config_2.SetProperty("CC:DD:EE:FF:00:09", "Name", "Hello 2");
+ config_2.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ ASSERT_EQ(config_1, config_2);
+ // Config with different temp device order should not be equal
+ ASSERT_TRUE(config_2.GetProperty("CC:DD:EE:FF:00:10", "Name"));
+ ASSERT_NE(config_1, config_2);
+ ASSERT_TRUE(config_1.GetProperty("CC:DD:EE:FF:00:10", "Name"));
+ ASSERT_EQ(config_1, config_2);
+ // Config with different persistent device order should not be equal
+ config_1.SetProperty("CC:DD:EE:FF:00:12", "LinkKey", "AABBAABBCCDDEE");
+ config_2.RemoveSection("CC:DD:EE:FF:00:11");
+ config_2.SetProperty("CC:DD:EE:FF:00:12", "LinkKey", "AABBAABBCCDDEE");
+ config_2.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ ASSERT_NE(config_1, config_2);
+ // Config with different capacity should not be equal
+ ConfigCache config_3(3, Device::kLinkKeyProperties);
+ config_3.SetProperty("A", "B", "C");
+ config_3.SetProperty("CC:DD:EE:FF:00:10", "Name", "Hello");
+ config_3.SetProperty("CC:DD:EE:FF:00:09", "Name", "Hello 2");
+ config_3.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ config_3.SetProperty("CC:DD:EE:FF:00:12", "LinkKey", "AABBAABBCCDDEE");
+ ASSERT_NE(config_1, config_3);
+ // Empty config should not be equal to non-empty ones
+ ConfigCache config_4(2, Device::kLinkKeyProperties);
+ ASSERT_NE(config_1, config_4);
+ // Empty configs should be equal
+ ConfigCache config_5(2, Device::kLinkKeyProperties);
+ ASSERT_EQ(config_4, config_5);
+ // Empty configs with different capacity should not be equal
+ ConfigCache config_6(3, Device::kLinkKeyProperties);
+ ASSERT_NE(config_4, config_6);
+}
+
+TEST(ConfigCacheTest, empty_string_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "");
+ auto value = config.GetProperty("A", "B");
+ ASSERT_TRUE(value);
+ ASSERT_EQ(*value, "");
+}
+
+TEST(ConfigCacheTest, mac_address_set_get_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ auto value = config.GetProperty("A", "B");
+ ASSERT_TRUE(value);
+ ASSERT_EQ(*value, "C");
+ value = config.GetProperty("AA:BB:CC:DD:EE:FF", "B");
+ ASSERT_TRUE(value);
+ ASSERT_EQ(*value, "C");
+ ASSERT_FALSE(config.GetProperty("A", "BC"));
+ ASSERT_FALSE(config.GetProperty("ABC", "B"));
+}
+
+TEST(ConfigCacheTest, has_section_and_property_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ ASSERT_TRUE(config.HasSection("A"));
+ ASSERT_TRUE(config.HasSection("AA:BB:CC:DD:EE:FF"));
+ ASSERT_TRUE(config.HasProperty("A", "B"));
+ ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ auto value = config.GetProperty("AA:BB:CC:DD:EE:FF", "C");
+ ASSERT_TRUE(value);
+ ASSERT_EQ(*value, "D");
+ value = config.GetProperty("AA:BB:CC:DD:EE:FF", "B");
+ ASSERT_TRUE(value);
+ ASSERT_EQ(*value, "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "E");
+ value = config.GetProperty("AA:BB:CC:DD:EE:FF", "B");
+ ASSERT_TRUE(value);
+ ASSERT_THAT(value, Optional(StrEq("E")));
+ ASSERT_FALSE(config.HasSection("Ab"));
+ ASSERT_FALSE(config.HasSection("AA:11:CC:DD:EE:FF"));
+ ASSERT_FALSE(config.HasProperty("A", "bB"));
+ ASSERT_FALSE(config.HasProperty("AA:BB:11:DD:EE:FF", "B"));
+}
+
+TEST(ConfigCacheTest, remove_section_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ ASSERT_TRUE(config.HasSection("A"));
+ ASSERT_TRUE(config.HasSection("AA:BB:CC:DD:EE:FF"));
+ ASSERT_TRUE(config.HasProperty("A", "B"));
+ ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
+ ASSERT_TRUE(config.RemoveSection("AA:BB:CC:DD:EE:FF"));
+ ASSERT_TRUE(config.RemoveSection("A"));
+ ASSERT_FALSE(config.HasProperty("A", "B"));
+ ASSERT_FALSE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
+}
+
+TEST(ConfigCacheTest, remove_property_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ ASSERT_TRUE(config.HasSection("A"));
+ ASSERT_TRUE(config.HasSection("AA:BB:CC:DD:EE:FF"));
+ ASSERT_TRUE(config.HasProperty("A", "B"));
+ ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
+ ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "C"));
+ ASSERT_TRUE(config.RemoveProperty("AA:BB:CC:DD:EE:FF", "B"));
+ ASSERT_FALSE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
+ ASSERT_FALSE(config.GetProperty("AA:BB:CC:DD:EE:FF", "B"));
+}
+
+TEST(ConfigCacheTest, remove_all_properties_from_section_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ ASSERT_TRUE(config.HasSection("A"));
+ ASSERT_TRUE(config.HasSection("AA:BB:CC:DD:EE:FF"));
+ ASSERT_TRUE(config.HasProperty("A", "B"));
+ ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
+ ASSERT_TRUE(config.HasProperty("AA:BB:CC:DD:EE:FF", "C"));
+ ASSERT_TRUE(config.RemoveSection("AA:BB:CC:DD:EE:FF"));
+ ASSERT_FALSE(config.HasSection("AA:BB:CC:DD:EE:FF"));
+ ASSERT_FALSE(config.HasProperty("AA:BB:CC:DD:EE:FF", "B"));
+ ASSERT_FALSE(config.GetProperty("AA:BB:CC:DD:EE:FF", "C"));
+}
+
+TEST(ConfigCacheTest, get_persistent_devices_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ config.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ ASSERT_TRUE(config.HasProperty("CC:DD:EE:FF:00:11", "LinkKey"));
+ ASSERT_THAT(config.GetPersistentSections(), ElementsAre("CC:DD:EE:FF:00:11"));
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "LinkKey", "DEERDEERDEER");
+ ASSERT_THAT(config.GetPersistentSections(), ElementsAre("CC:DD:EE:FF:00:11", "AA:BB:CC:DD:EE:FF"));
+ ASSERT_TRUE(config.RemoveProperty("CC:DD:EE:FF:00:11", "LinkKey"));
+ ASSERT_THAT(config.GetPersistentSections(), ElementsAre("AA:BB:CC:DD:EE:FF"));
+}
+
+TEST(ConfigCacheTest, appoaching_temporary_config_limit_test) {
+ ConfigCache config(2, Device::kLinkKeyProperties);
+ for (int i = 0; i < 10; ++i) {
+ config.SetProperty(GetTestAddress(i), "Name", "Hello" + std::to_string(i));
+ if (i % 2 == 0) {
+ config.SetProperty(GetTestAddress(i), "LinkKey", "Key" + std::to_string(i));
+ }
+ }
+ for (int i = 0; i < 10; ++i) {
+ if (i % 2 == 0) {
+ ASSERT_TRUE(config.HasSection(GetTestAddress(i)));
+ ASSERT_TRUE(config.HasProperty(GetTestAddress(i), "LinkKey"));
+ ASSERT_THAT(config.GetProperty(GetTestAddress(i), "Name"), Optional(StrEq("Hello" + std::to_string(i))));
+ } else if (i >= 7) {
+ ASSERT_TRUE(config.HasSection(GetTestAddress(i)));
+ ASSERT_THAT(config.GetProperty(GetTestAddress(i), "Name"), Optional(StrEq("Hello" + std::to_string(i))));
+ } else {
+ ASSERT_FALSE(config.HasSection(GetTestAddress(i)));
+ }
+ }
+ ASSERT_THAT(
+ config.GetPersistentSections(),
+ ElementsAre(GetTestAddress(0), GetTestAddress(2), GetTestAddress(4), GetTestAddress(6), GetTestAddress(8)));
+}
+
+TEST(ConfigCacheTest, remove_section_with_property_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
+ config.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ config.RemoveSectionWithProperty("B");
+ ASSERT_FALSE(config.HasSection("A"));
+ ASSERT_FALSE(config.HasSection("AA:BB:CC:DD:EE:FF"));
+ ASSERT_FALSE(config.HasSection("CC:DD:EE:FF:00:11"));
+}
+
+TEST(ConfigCacheTest, persistent_config_changed_callback_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ int num_change = 0;
+ config.SetPersistentConfigChangedCallback([&num_change] { num_change++; });
+ config.SetProperty("A", "B", "C");
+ ASSERT_EQ(num_change, 1);
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ ASSERT_EQ(num_change, 1);
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ ASSERT_EQ(num_change, 1);
+ config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
+ ASSERT_EQ(num_change, 1);
+ config.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ ASSERT_EQ(num_change, 2);
+ config.RemoveProperty("CC:DD:EE:FF:00:11", "LinkKey");
+ ASSERT_EQ(num_change, 3);
+ config.RemoveSectionWithProperty("B");
+ ASSERT_EQ(num_change, 4);
+}
+
+TEST(ConfigCacheTest, fix_device_type_inconsistency_test) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
+ ASSERT_TRUE(config.FixDeviceTypeInconsistencies());
+ ASSERT_THAT(
+ config.GetProperty("AA:BB:CC:DD:EE:FF", "DevType"),
+ Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::BR_EDR))));
+ config.SetProperty("CC:DD:EE:FF:00:11", "B", "AABBAABBCCDDEE");
+ config.SetProperty("CC:DD:EE:FF:00:11", "DevType", std::to_string(bluetooth::hci::DeviceType::BR_EDR));
+ config.SetProperty("CC:DD:EE:FF:00:11", "LinkKey", "AABBAABBCCDDEE");
+ ASSERT_FALSE(config.FixDeviceTypeInconsistencies());
+ ASSERT_THAT(
+ config.GetProperty("CC:DD:EE:FF:00:11", "DevType"),
+ Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::BR_EDR))));
+ config.SetProperty("CC:DD:EE:FF:00:11", "LE_KEY_PENC", "AABBAABBCCDDEE");
+ ASSERT_TRUE(config.FixDeviceTypeInconsistencies());
+ ASSERT_THAT(
+ config.GetProperty("CC:DD:EE:FF:00:11", "DevType"),
+ Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::DUAL))));
+ config.RemoveProperty("CC:DD:EE:FF:00:11", "LinkKey");
+ ASSERT_TRUE(config.FixDeviceTypeInconsistencies());
+ ASSERT_THAT(
+ config.GetProperty("CC:DD:EE:FF:00:11", "DevType"),
+ Optional(StrEq(std::to_string(bluetooth::hci::DeviceType::LE))));
+}
+
+TEST(ConfigCacheTest, test_get_section_with_property) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:EF", "C", "D");
+ ASSERT_THAT(
+ config.GetSectionNamesWithProperty("B"),
+ ElementsAre(
+ SectionAndPropertyValue{.section = "A", .property = "C"},
+ SectionAndPropertyValue{.section = "AA:BB:CC:DD:EE:FF", .property = "C"}));
+}
+
+TEST(ConfigCacheTest, test_get_sections_matching_at_least_one_property) {
+ ConfigCache config(100, Device::kLinkKeyProperties);
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:EF", "C", "D");
+ ASSERT_TRUE(config.HasAtLeastOneMatchingPropertiesInSection("AA:BB:CC:DD:EE:FF", {"B", "C", "D"}));
+ ASSERT_TRUE(config.HasAtLeastOneMatchingPropertiesInSection("A", {"B", "C", "D"}));
+ ASSERT_FALSE(config.HasAtLeastOneMatchingPropertiesInSection("AA:BB:CC:DD:EE:FF", {"BC", "D"}));
+}
+
+TEST(ConfigCacheTest, test_empty_persistent_properties) {
+ ConfigCache config(100, {});
+ config.SetProperty("A", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
+ config.SetProperty("AA:BB:CC:DD:EE:EF", "C", "D");
+ config.SetProperty("AA:BB:CC:DD:EE:EF", "LinkKey", "D");
+ ASSERT_TRUE(config.HasAtLeastOneMatchingPropertiesInSection("AA:BB:CC:DD:EE:FF", {"B", "C", "D"}));
+ ASSERT_TRUE(config.HasAtLeastOneMatchingPropertiesInSection("A", {"B", "C", "D"}));
+ ASSERT_FALSE(config.HasAtLeastOneMatchingPropertiesInSection("AA:BB:CC:DD:EE:FF", {"BC", "D"}));
+ ASSERT_THAT(config.GetPersistentSections(), ElementsAre());
+}
+
+} // namespace testing \ No newline at end of file