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/legacy_config_file.h"
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 #include <filesystem>
23
24 #include "os/files.h"
25 #include "storage/config_keys.h"
26 #include "storage/device.h"
27
28 namespace testing {
29
30 using bluetooth::os::ReadSmallFile;
31 using bluetooth::os::WriteToFile;
32 using bluetooth::storage::ConfigCache;
33 using bluetooth::storage::Device;
34 using bluetooth::storage::LegacyConfigFile;
35
TEST(LegacyConfigFileTest,write_and_read_loop_back_test)36 TEST(LegacyConfigFileTest, write_and_read_loop_back_test) {
37 auto temp_dir = std::filesystem::temp_directory_path();
38 auto temp_config = temp_dir / "temp_config.txt";
39
40 ConfigCache config(100, Device::kLinkKeyProperties);
41 config.SetProperty("A", "B", "C");
42 config.SetProperty("AA:BB:CC:DD:EE:FF", "B", "C");
43 config.SetProperty("AA:BB:CC:DD:EE:FF", "C", "D");
44 config.SetProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY, "AABBAABBCCDDEE");
45 EXPECT_TRUE(config.HasProperty("CC:DD:EE:FF:00:11", BTIF_STORAGE_KEY_LINK_KEY));
46 EXPECT_THAT(config.GetPersistentSections(), ElementsAre("CC:DD:EE:FF:00:11"));
47
48 EXPECT_TRUE(LegacyConfigFile::FromPath(temp_config.string()).Write(config));
49 auto config_read = LegacyConfigFile::FromPath(temp_config.string()).Read(100);
50 EXPECT_TRUE(config_read);
51 // Unpaired devices do not exist in persistent config file
52 config.RemoveSection("AA:BB:CC:DD:EE:FF");
53 EXPECT_EQ(config, *config_read);
54 EXPECT_THAT(config_read->GetPersistentSections(), ElementsAre("CC:DD:EE:FF:00:11"));
55 EXPECT_THAT(config_read->GetProperty("A", "B"), Optional(StrEq("C")));
56 EXPECT_THAT(config_read->GetProperty("CC:DD:EE:FF:00:11", "LinkKey"), Optional(StrEq("AABBAABBCCDDEE")));
57
58 EXPECT_TRUE(std::filesystem::remove(temp_config));
59 }
60
61 static const std::string kReadTestConfig =
62 "[Info]\n"
63 "FileSource = Empty\n"
64 "TimeCreated = 2020-05-20 01:20:56\n"
65 "\n"
66 "[Metrics]\n"
67 "Salt256Bit = 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\n"
68 "\n"
69 "[Adapter]\n"
70 "Address = 01:02:03:ab:cd:ef\n"
71 "LE_LOCAL_KEY_IRK = fedcba0987654321fedcba0987654321\n"
72 "LE_LOCAL_KEY_IR = fedcba0987654321fedcba0987654322\n"
73 "LE_LOCAL_KEY_DHK = fedcba0987654321fedcba0987654323\n"
74 "LE_LOCAL_KEY_ER = fedcba0987654321fedcba0987654324\n"
75 "ScanMode = 2\n"
76 "DiscoveryTimeout = 120\n"
77 "\n"
78 "[01:02:03:ab:cd:ea]\n"
79 "name = hello world\n"
80 "LinkKey = fedcba0987654321fedcba0987654328\n";
81
TEST(LegacyConfigFileTest,read_test)82 TEST(LegacyConfigFileTest, read_test) {
83 auto temp_dir = std::filesystem::temp_directory_path();
84 auto temp_config = temp_dir / "temp_config.txt";
85 EXPECT_TRUE(WriteToFile(temp_config.string(), kReadTestConfig));
86
87 auto config_read = LegacyConfigFile::FromPath(temp_config.string()).Read(100);
88 EXPECT_TRUE(config_read);
89 EXPECT_THAT(config_read->GetPersistentSections(), ElementsAre("01:02:03:ab:cd:ea"));
90 EXPECT_THAT(config_read->GetProperty("Info", "FileSource"), Optional(StrEq("Empty")));
91 EXPECT_THAT(config_read->GetProperty("Info", "FileSource"), Optional(StrEq("Empty")));
92 EXPECT_THAT(
93 config_read->GetProperty("01:02:03:ab:cd:ea", "LinkKey"), Optional(StrEq("fedcba0987654321fedcba0987654328")));
94
95 EXPECT_TRUE(std::filesystem::remove(temp_config));
96 }
97
98 static const std::string kWriteTestConfig =
99 "[Info]\n"
100 "FileSource = Empty\n"
101 "TimeCreated = \n"
102 "\n"
103 "[Adapter]\n"
104 "Address = 01:02:03:ab:cd:ef\n"
105 "\n"
106 "[01:02:03:ab:cd:ea]\n"
107 "Name = hello world\n"
108 "LinkKey = fedcba0987654321fedcba0987654328\n"
109 "\n";
110
TEST(LegacyConfigFileTest,write_test)111 TEST(LegacyConfigFileTest, write_test) {
112 auto temp_dir = std::filesystem::temp_directory_path();
113 auto temp_config = temp_dir / "temp_config.txt";
114
115 ConfigCache config(100, Device::kLinkKeyProperties);
116 config.SetProperty("Info", "FileSource", "Empty");
117 config.SetProperty("Info", "TimeCreated", "");
118 config.SetProperty(BTIF_STORAGE_SECTION_ADAPTER, BTIF_STORAGE_KEY_ADDRESS, "01:02:03:ab:cd:ef");
119 config.SetProperty("01:02:03:ab:cd:ea", BTIF_STORAGE_KEY_NAME, "hello world");
120 config.SetProperty(
121 "01:02:03:ab:cd:ea", BTIF_STORAGE_KEY_LINK_KEY, "fedcba0987654321fedcba0987654328");
122 EXPECT_TRUE(LegacyConfigFile::FromPath(temp_config.string()).Write(config));
123
124 EXPECT_THAT(ReadSmallFile(temp_config.string()), Optional(StrEq(kWriteTestConfig)));
125
126 EXPECT_TRUE(std::filesystem::remove(temp_config));
127 }
128
129 static const std::string kConfigWithDuplicateSectionAndKey =
130 " \n\
131 first_key=value \n\
132 \n\
133 # Device ID (DID) configuration \n\
134 [DID] \n\
135 \n\
136 # Record Number: 1, 2 or 3 - maximum of 3 records \n\
137 recordNumber = 1 \n\
138 \n\
139 # Primary Record - true or false (default) \n\
140 # There can be only one primary record \n\
141 primaryRecord = true \n\
142 \n\
143 # Vendor ID '0xFFFF' indicates no Device ID Service Record is present in the device \n\
144 # 0x000F = Broadcom Corporation (default) \n\
145 #vendorId = 0x000F \n\
146 \n\
147 # Vendor ID Source \n\
148 # 0x0001 = Bluetooth SIG assigned Device ID Vendor ID value (default) \n\
149 # 0x0002 = USB Implementer's Forum assigned Device ID Vendor ID value \n\
150 #vendorIdSource = 0x0001 \n\
151 \n\
152 # Product ID & Product Version \n\
153 # Per spec DID v1.3 0xJJMN for version is interpreted as JJ.M.N \n\
154 # JJ: major version number, M: minor version number, N: sub-minor version number \n\
155 # For example: 1200, v14.3.6 \n\
156 productId = 0x1200 \n\
157 version = 0x1111 \n\
158 \n\
159 # Optional attributes \n\
160 #clientExecutableURL = \n\
161 #serviceDescription = \n\
162 #documentationURL = \n\
163 \n\
164 # Additional optional DID records. Bluedroid supports up to 3 records. \n\
165 [DID] \n\
166 [DID] \n\
167 version = 0x1436 \n\
168 \n\
169 HiSyncId = 18446744073709551615 \n\
170 HiSyncId2 = 15001900 \n\
171 ";
172
TEST(LegacyConfigFileTest,duplicate_section_and_key_test)173 TEST(LegacyConfigFileTest, duplicate_section_and_key_test) {
174 auto temp_dir = std::filesystem::temp_directory_path();
175 auto temp_config = temp_dir / "temp_config.txt";
176 ASSERT_TRUE(WriteToFile(temp_config.string(), kConfigWithDuplicateSectionAndKey));
177
178 auto config_read = LegacyConfigFile::FromPath(temp_config.string()).Read(100);
179 ASSERT_TRUE(config_read);
180 EXPECT_THAT(config_read->GetProperty(ConfigCache::kDefaultSectionName, "first_key"), Optional(StrEq("value")));
181 // All sections with the same name merge into the same key-value pair
182 EXPECT_THAT(config_read->GetProperty("DID", "primaryRecord"), Optional(StrEq("true")));
183 // When keys are repeated, the later one wins
184 EXPECT_THAT(config_read->GetProperty("DID", "version"), Optional(StrEq("0x1436")));
185
186 EXPECT_TRUE(std::filesystem::remove(temp_config));
187 }
188
189 } // namespace testing