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