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 "osi/include/config.h" 18 19 #include <base/files/file_util.h> 20 #include <gtest/gtest.h> 21 22 #include <filesystem> 23 24 #include "AllocationTestHarness.h" 25 26 static const std::filesystem::path kConfigFile = 27 std::filesystem::temp_directory_path() / "config_test.conf"; 28 static const char* CONFIG_FILE = kConfigFile.c_str(); 29 static const char CONFIG_FILE_CONTENT[] = 30 " \n\ 31 first_key=value \n\ 32 \n\ 33 # Device ID (DID) configuration \n\ 34 [DID] \n\ 35 \n\ 36 # Record Number: 1, 2 or 3 - maximum of 3 records \n\ 37 recordNumber = 1 \n\ 38 \n\ 39 # Primary Record - true or false (default) \n\ 40 # There can be only one primary record \n\ 41 primaryRecord = true \n\ 42 \n\ 43 # Vendor ID '0xFFFF' indicates no Device ID Service Record is present in the device \n\ 44 # 0x000F = Broadcom Corporation (default) \n\ 45 #vendorId = 0x000F \n\ 46 \n\ 47 # Vendor ID Source \n\ 48 # 0x0001 = Bluetooth SIG assigned Device ID Vendor ID value (default) \n\ 49 # 0x0002 = USB Implementer's Forum assigned Device ID Vendor ID value \n\ 50 #vendorIdSource = 0x0001 \n\ 51 \n\ 52 # Product ID & Product Version \n\ 53 # Per spec DID v1.3 0xJJMN for version is interpreted as JJ.M.N \n\ 54 # JJ: major version number, M: minor version number, N: sub-minor version number \n\ 55 # For example: 1200, v14.3.6 \n\ 56 productId = 0x1200 \n\ 57 version = 0x1111 \n\ 58 \n\ 59 # Optional attributes \n\ 60 #clientExecutableURL = \n\ 61 #serviceDescription = \n\ 62 #documentationURL = \n\ 63 \n\ 64 # Additional optional DID records. Bluedroid supports up to 3 records. \n\ 65 [DID] \n\ 66 [DID] \n\ 67 version = 0x1436 \n\ 68 \n\ 69 HiSyncId = 18446744073709551615 \n\ 70 HiSyncId2 = 15001900 \n\ 71 "; 72 73 class ConfigTest : public AllocationTestHarness { 74 protected: 75 void SetUp() override { 76 AllocationTestHarness::SetUp(); 77 FILE* fp = fopen(CONFIG_FILE, "wt"); 78 ASSERT_NE(fp, nullptr); 79 ASSERT_EQ(fwrite(CONFIG_FILE_CONTENT, 1, sizeof(CONFIG_FILE_CONTENT), fp), 80 sizeof(CONFIG_FILE_CONTENT)); 81 ASSERT_EQ(fclose(fp), 0); 82 } 83 84 void TearDown() override { 85 EXPECT_TRUE(std::filesystem::remove(kConfigFile)); 86 AllocationTestHarness::TearDown(); 87 } 88 }; 89 90 TEST_F(ConfigTest, config_find) { 91 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 92 ASSERT_NE(config, nullptr); 93 EXPECT_TRUE(config->Has("DID")); 94 auto section_iter = config->Find("DID"); 95 ASSERT_NE(section_iter, config->sections.end()); 96 EXPECT_FALSE(config->Has("random")); 97 EXPECT_EQ(config->Find("random"), config->sections.end()); 98 } 99 100 TEST_F(ConfigTest, section_find) { 101 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 102 ASSERT_NE(config, nullptr); 103 EXPECT_TRUE(config->Has("DID")); 104 auto section_iter = config->Find("DID"); 105 ASSERT_NE(section_iter, config->sections.end()); 106 EXPECT_EQ(section_iter->name, "DID"); 107 EXPECT_TRUE(section_iter->Has("version")); 108 auto entry_iter = section_iter->Find("version"); 109 ASSERT_NE(entry_iter, section_iter->entries.end()); 110 EXPECT_EQ(entry_iter->key, "version"); 111 EXPECT_EQ(entry_iter->value, "0x1436"); 112 EXPECT_EQ(section_iter->Find("random"), section_iter->entries.end()); 113 EXPECT_FALSE(section_iter->Has("random")); 114 } 115 116 TEST_F(ConfigTest, section_set) { 117 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 118 ASSERT_NE(config, nullptr); 119 EXPECT_TRUE(config->Has("DID")); 120 auto section_iter = config->Find("DID"); 121 ASSERT_NE(section_iter, config->sections.end()); 122 EXPECT_EQ(section_iter->name, "DID"); 123 EXPECT_FALSE(section_iter->Has("random")); 124 section_iter->Set("random", "foo"); 125 EXPECT_TRUE(section_iter->Has("random")); 126 auto entry_iter = section_iter->Find("random"); 127 ASSERT_NE(entry_iter, section_iter->entries.end()); 128 EXPECT_EQ(entry_iter->key, "random"); 129 EXPECT_EQ(entry_iter->value, "foo"); 130 section_iter->Set("random", "bar"); 131 EXPECT_EQ(entry_iter->value, "bar"); 132 entry_iter = section_iter->Find("random"); 133 ASSERT_NE(entry_iter, section_iter->entries.end()); 134 EXPECT_EQ(entry_iter->value, "bar"); 135 } 136 137 TEST_F(ConfigTest, config_new_empty) { 138 std::unique_ptr<config_t> config = config_new_empty(); 139 EXPECT_TRUE(config.get() != NULL); 140 } 141 142 TEST_F(ConfigTest, config_new_no_file) { 143 std::unique_ptr<config_t> config = config_new("/meow"); 144 EXPECT_TRUE(config.get() == NULL); 145 } 146 147 TEST_F(ConfigTest, config_new) { 148 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 149 EXPECT_TRUE(config.get() != NULL); 150 } 151 152 TEST_F(ConfigTest, config_new_clone) { 153 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 154 std::unique_ptr<config_t> clone = config_new_clone(*config); 155 156 config_set_string(clone.get(), CONFIG_DEFAULT_SECTION, "first_key", 157 "not_value"); 158 159 std::string one = std::string("one"); 160 EXPECT_STRNE( 161 config_get_string(*config, CONFIG_DEFAULT_SECTION, "first_key", &one) 162 ->c_str(), 163 config_get_string(*clone, CONFIG_DEFAULT_SECTION, "first_key", &one) 164 ->c_str()); 165 } 166 167 TEST_F(ConfigTest, config_has_section) { 168 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 169 EXPECT_TRUE(config_has_section(*config, "DID")); 170 } 171 172 TEST_F(ConfigTest, config_has_key_in_default_section) { 173 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 174 EXPECT_TRUE(config_has_key(*config, CONFIG_DEFAULT_SECTION, "first_key")); 175 EXPECT_STREQ( 176 config_get_string(*config, CONFIG_DEFAULT_SECTION, "first_key", nullptr) 177 ->c_str(), 178 "value"); 179 } 180 181 TEST_F(ConfigTest, config_has_keys) { 182 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 183 EXPECT_TRUE(config_has_key(*config, "DID", "recordNumber")); 184 EXPECT_TRUE(config_has_key(*config, "DID", "primaryRecord")); 185 EXPECT_TRUE(config_has_key(*config, "DID", "productId")); 186 EXPECT_TRUE(config_has_key(*config, "DID", "version")); 187 } 188 189 TEST_F(ConfigTest, config_no_bad_keys) { 190 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 191 EXPECT_FALSE(config_has_key(*config, "DID_BAD", "primaryRecord")); 192 EXPECT_FALSE(config_has_key(*config, "DID", "primaryRecord_BAD")); 193 EXPECT_FALSE( 194 config_has_key(*config, CONFIG_DEFAULT_SECTION, "primaryRecord")); 195 } 196 197 TEST_F(ConfigTest, config_get_int_version) { 198 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 199 EXPECT_EQ(config_get_int(*config, "DID", "version", 0), 0x1436); 200 } 201 202 TEST_F(ConfigTest, config_get_int_default) { 203 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 204 EXPECT_EQ(config_get_int(*config, "DID", "primaryRecord", 123), 123); 205 } 206 207 TEST_F(ConfigTest, config_get_uint64) { 208 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 209 EXPECT_EQ(config_get_uint64(*config, "DID", "HiSyncId", 0), 210 0xFFFFFFFFFFFFFFFF); 211 EXPECT_EQ(config_get_uint64(*config, "DID", "HiSyncId2", 0), 212 uint64_t(15001900)); 213 } 214 215 TEST_F(ConfigTest, config_get_uint64_default) { 216 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 217 EXPECT_EQ(config_get_uint64(*config, "DID", "primaryRecord", 123), 218 uint64_t(123)); 219 } 220 221 TEST_F(ConfigTest, config_remove_section) { 222 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 223 EXPECT_TRUE(config_remove_section(config.get(), "DID")); 224 EXPECT_FALSE(config_has_section(*config, "DID")); 225 EXPECT_FALSE(config_has_key(*config, "DID", "productId")); 226 } 227 228 TEST_F(ConfigTest, config_remove_section_missing) { 229 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 230 EXPECT_FALSE(config_remove_section(config.get(), "not a section")); 231 } 232 233 TEST_F(ConfigTest, config_remove_key) { 234 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 235 EXPECT_EQ(config_get_int(*config, "DID", "productId", 999), 0x1200); 236 EXPECT_TRUE(config_remove_key(config.get(), "DID", "productId")); 237 EXPECT_FALSE(config_has_key(*config, "DID", "productId")); 238 } 239 240 TEST_F(ConfigTest, config_remove_key_missing) { 241 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 242 EXPECT_EQ(config_get_int(*config, "DID", "productId", 999), 0x1200); 243 EXPECT_TRUE(config_remove_key(config.get(), "DID", "productId")); 244 EXPECT_EQ(config_get_int(*config, "DID", "productId", 999), 999); 245 } 246 247 TEST_F(ConfigTest, config_save_basic) { 248 std::unique_ptr<config_t> config = config_new(CONFIG_FILE); 249 EXPECT_TRUE(config_save(*config, CONFIG_FILE)); 250 } 251 252 TEST_F(ConfigTest, checksum_read) { 253 auto tmp_dir = std::filesystem::temp_directory_path(); 254 auto filename = tmp_dir / "test.checksum"; 255 std::string checksum = "0x1234"; 256 base::FilePath file_path(filename.string()); 257 258 EXPECT_EQ(base::WriteFile(file_path, checksum.data(), checksum.size()), 259 (int)checksum.size()); 260 261 EXPECT_EQ(checksum_read(filename.c_str()), checksum.c_str()); 262 263 EXPECT_TRUE(std::filesystem::remove(filename)); 264 } 265 266 TEST_F(ConfigTest, checksum_save) { 267 auto tmp_dir = std::filesystem::temp_directory_path(); 268 auto filename = tmp_dir / "test.checksum"; 269 std::string checksum = "0x1234"; 270 base::FilePath file_path(filename.string()); 271 272 EXPECT_TRUE(checksum_save(checksum, filename)); 273 274 EXPECT_TRUE(base::PathExists(file_path)); 275 276 EXPECT_TRUE(std::filesystem::remove(filename)); 277 } 278