configuration_test.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include "configuration_test.h"
  19. #include "common/configuration.h"
  20. #include "common/configuration_loader.h"
  21. #include <gmock/gmock.h>
  22. #include <cstdio>
  23. #include <fstream>
  24. using ::testing::_;
  25. using namespace hdfs;
  26. namespace hdfs {
  27. TEST(ConfigurationTest, TestDegenerateInputs) {
  28. /* Completely empty stream */
  29. {
  30. std::stringstream stream;
  31. optional<Configuration> config = ConfigurationLoader().Load<Configuration>("");
  32. EXPECT_FALSE(config && "Empty stream");
  33. }
  34. /* No values */
  35. {
  36. std::string data = "<configuration></configuration>";
  37. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(data);
  38. EXPECT_TRUE(config && "Blank config");
  39. }
  40. /* Extraneous values */
  41. {
  42. std::string data = "<configuration><spam></spam></configuration>";
  43. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(data);
  44. EXPECT_TRUE(config && "Extraneous values");
  45. }
  46. }
  47. TEST(ConfigurationTest, TestBasicOperations) {
  48. /* Single value */
  49. {
  50. std::stringstream stream;
  51. simpleConfigStream(stream, "key1", "value1");
  52. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  53. EXPECT_TRUE(config && "Parse single value");
  54. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  55. }
  56. /* Multiple values */
  57. {
  58. optional<Configuration> config =
  59. simpleConfig("key1", "value1", "key2", "value2");
  60. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  61. EXPECT_EQ("value2", config->GetWithDefault("key2", ""));
  62. }
  63. /* Case-insensitive */
  64. {
  65. std::stringstream stream;
  66. simpleConfigStream(stream, "key1", "value1");
  67. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  68. EXPECT_TRUE(config && "Parse single value");
  69. EXPECT_EQ("value1", config->GetWithDefault("KEY1", ""));
  70. }
  71. /* No defaults */
  72. {
  73. std::stringstream stream;
  74. simpleConfigStream(stream, "key1", "value1");
  75. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  76. EXPECT_TRUE(config && "Parse single value");
  77. optional<std::string> value = config->Get("key1");
  78. EXPECT_TRUE((bool)value);
  79. EXPECT_EQ("value1", *value);
  80. EXPECT_FALSE(config->Get("key2"));
  81. }
  82. }
  83. TEST(ConfigurationTest, TestCompactValues) {
  84. {
  85. std::stringstream stream;
  86. stream << "<configuration><property name=\"key1\" "
  87. "value=\"value1\"/></configuration>";
  88. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  89. EXPECT_TRUE(config && "Compact value parse");
  90. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  91. }
  92. }
  93. TEST(ConfigurationTest, TestMultipleResources) {
  94. /* Single value */
  95. {
  96. std::stringstream stream;
  97. simpleConfigStream(stream, "key1", "value1");
  98. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  99. EXPECT_TRUE(config && "Parse first stream");
  100. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  101. std::stringstream stream2;
  102. simpleConfigStream(stream2, "key2", "value2");
  103. optional<Configuration> config2 =
  104. ConfigurationLoader().OverlayResourceString(config.value(), stream2.str());
  105. EXPECT_TRUE(config2 && "Parse second stream");
  106. EXPECT_EQ("value1", config2->GetWithDefault("key1", ""));
  107. EXPECT_EQ("value2", config2->GetWithDefault("key2", ""));
  108. }
  109. }
  110. TEST(ConfigurationTest, TestStringResource) {
  111. /* Single value */
  112. {
  113. std::stringstream stream;
  114. simpleConfigStream(stream, "key1", "value1");
  115. std::string str = stream.str();
  116. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  117. EXPECT_TRUE(config && "Parse single value");
  118. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  119. }
  120. }
  121. TEST(ConfigurationTest, TestValueOverlay) {
  122. /* Incremental updates */
  123. {
  124. ConfigurationLoader loader;
  125. std::stringstream stream;
  126. stream << "<configuration>"
  127. "<property><name>key1</name><value>value1</value><final>false</final></property>"
  128. "<property><name>final2</name><value>value2</value><final>true</final></property>"
  129. "</configuration>";
  130. optional<Configuration> config = loader.Load<Configuration>(stream.str());
  131. EXPECT_TRUE(config && "Parse single value");
  132. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  133. EXPECT_EQ("value2", config->GetWithDefault("final2", ""));
  134. config = loader.OverlayValue(config.value(), "key3", "value3");
  135. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  136. EXPECT_EQ("value2", config->GetWithDefault("final2", ""));
  137. EXPECT_EQ("value3", config->GetWithDefault("key3", ""));
  138. config = loader.OverlayValue(config.value(), "final2", "value4");
  139. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  140. EXPECT_EQ("value2", config->GetWithDefault("final2", ""));
  141. EXPECT_EQ("value3", config->GetWithDefault("key3", ""));
  142. // Case insensitive overlay
  143. config = loader.OverlayValue(config.value(), "KEY3", "value3a");
  144. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  145. EXPECT_EQ("value2", config->GetWithDefault("final2", ""));
  146. EXPECT_EQ("value3a", config->GetWithDefault("key3", ""));
  147. }
  148. }
  149. TEST(ConfigurationTest, TestFinal) {
  150. {
  151. /* Explicitly non-final non-compact value */
  152. std::stringstream stream;
  153. stream << "<configuration><property><name>key1</name><value>value1</"
  154. "value><final>false</final></property></configuration>";
  155. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  156. EXPECT_TRUE(config && "Parse first stream");
  157. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  158. std::stringstream stream2;
  159. simpleConfigStream(stream2, "key1", "value2");
  160. optional<Configuration> config2 =
  161. ConfigurationLoader().OverlayResourceString(config.value(), stream2.str());
  162. EXPECT_TRUE(config2 && "Parse second stream");
  163. EXPECT_EQ("value2", config2->GetWithDefault("key1", ""));
  164. }
  165. {
  166. /* Explicitly final non-compact value */
  167. std::stringstream stream;
  168. stream << "<configuration><property><name>key1</name><value>value1</"
  169. "value><final>true</final></property></configuration>";
  170. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  171. EXPECT_TRUE(config && "Parse first stream");
  172. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  173. std::stringstream stream2;
  174. simpleConfigStream(stream2, "key1", "value2");
  175. optional<Configuration> config2 =
  176. ConfigurationLoader().OverlayResourceString(config.value(), stream2.str());
  177. EXPECT_TRUE(config2 && "Parse second stream");
  178. EXPECT_EQ("value1", config2->GetWithDefault("key1", ""));
  179. }
  180. {
  181. /* Explicitly non-final compact value */
  182. std::stringstream stream;
  183. stream << "<configuration><property name=\"key1\" value=\"value1\" "
  184. "final=\"false\"/></configuration>";
  185. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  186. EXPECT_TRUE(config && "Parse first stream");
  187. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  188. std::stringstream stream2;
  189. simpleConfigStream(stream2, "key1", "value2");
  190. optional<Configuration> config2 =
  191. ConfigurationLoader().OverlayResourceString(config.value(), stream2.str());
  192. EXPECT_TRUE(config2 && "Parse second stream");
  193. EXPECT_EQ("value2", config2->GetWithDefault("key1", ""));
  194. }
  195. {
  196. /* Explicitly final compact value */
  197. std::stringstream stream;
  198. stream << "<configuration><property name=\"key1\" value=\"value1\" "
  199. "final=\"true\"/></configuration>";
  200. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  201. EXPECT_TRUE(config && "Parse first stream");
  202. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  203. std::stringstream stream2;
  204. simpleConfigStream(stream2, "key1", "value2");
  205. optional<Configuration> config2 =
  206. ConfigurationLoader().OverlayResourceString(config.value(), stream2.str());
  207. EXPECT_TRUE(config2 && "Parse second stream");
  208. EXPECT_EQ("value1", config2->GetWithDefault("key1", ""));
  209. }
  210. {
  211. /* Bogus final value */
  212. std::stringstream stream;
  213. stream << "<configuration><property><name>key1</name><value>value1</"
  214. "value><final>spam</final></property></configuration>";
  215. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  216. EXPECT_TRUE(config && "Parse first stream");
  217. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  218. std::stringstream stream2;
  219. simpleConfigStream(stream2, "key1", "value2");
  220. optional<Configuration> config2 =
  221. ConfigurationLoader().OverlayResourceString(config.value(), stream2.str());
  222. EXPECT_TRUE(config2 && "Parse second stream");
  223. EXPECT_EQ("value2", config2->GetWithDefault("key1", ""));
  224. }
  225. {
  226. /* Blank final value */
  227. std::stringstream stream;
  228. stream << "<configuration><property><name>key1</name><value>value1</"
  229. "value><final></final></property></configuration>";
  230. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  231. EXPECT_TRUE(config && "Parse first stream");
  232. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  233. std::stringstream stream2;
  234. simpleConfigStream(stream2, "key1", "value2");
  235. optional<Configuration> config2 =
  236. ConfigurationLoader().OverlayResourceString(config.value(), stream2.str());
  237. EXPECT_TRUE(config2 && "Parse second stream");
  238. EXPECT_EQ("value2", config2->GetWithDefault("key1", ""));
  239. }
  240. }
  241. TEST(ConfigurationTest, TestFileReads)
  242. {
  243. // Single stream
  244. {
  245. TempFile tempFile;
  246. writeSimpleConfig(tempFile.filename, "key1", "value1");
  247. optional<Configuration> config = ConfigurationLoader().LoadFromFile<Configuration>(tempFile.filename);
  248. EXPECT_TRUE(config && "Parse first stream");
  249. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  250. }
  251. // Multiple files
  252. {
  253. TempFile tempFile;
  254. writeSimpleConfig(tempFile.filename, "key1", "value1");
  255. ConfigurationLoader loader;
  256. optional<Configuration> config = loader.LoadFromFile<Configuration>(tempFile.filename);
  257. ASSERT_TRUE(config && "Parse first stream");
  258. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  259. TempFile tempFile2;
  260. writeSimpleConfig(tempFile2.filename, "key2", "value2");
  261. optional<Configuration> config2 = loader.OverlayResourceFile(*config, tempFile2.filename);
  262. ASSERT_TRUE(config2 && "Parse second stream");
  263. EXPECT_EQ("value1", config2->GetWithDefault("key1", ""));
  264. EXPECT_EQ("value2", config2->GetWithDefault("key2", ""));
  265. }
  266. // Try to add a directory
  267. {
  268. TempDir tempDir;
  269. optional<Configuration> config = ConfigurationLoader().LoadFromFile<Configuration>(tempDir.path);
  270. EXPECT_FALSE(config && "Add directory as file resource");
  271. }
  272. // Search path splitting
  273. {
  274. ConfigurationLoader loader;
  275. loader.SetSearchPath("foo:/bar:baz/:/fioux/:/bar/bar/bong");
  276. // Paths will have / appended to them if not already present
  277. EXPECT_EQ("foo/:/bar/:baz/:/fioux/:/bar/bar/bong/", loader.GetSearchPath());
  278. }
  279. // Search path
  280. {
  281. TempDir tempDir1;
  282. TempFile tempFile1(tempDir1.path + "/file1.xml");
  283. writeSimpleConfig(tempFile1.filename, "key1", "value1");
  284. TempDir tempDir2;
  285. TempFile tempFile2(tempDir2.path + "/file2.xml");
  286. writeSimpleConfig(tempFile2.filename, "key2", "value2");
  287. TempDir tempDir3;
  288. TempFile tempFile3(tempDir3.path + "/file3.xml");
  289. writeSimpleConfig(tempFile3.filename, "key3", "value3");
  290. ConfigurationLoader loader;
  291. loader.SetSearchPath(tempDir1.path + ":" + tempDir2.path + ":" + tempDir3.path);
  292. optional<Configuration> config1 = loader.LoadFromFile<Configuration>("file1.xml");
  293. EXPECT_TRUE(config1 && "Parse first stream");
  294. optional<Configuration> config2 = loader.OverlayResourceFile(*config1, "file2.xml");
  295. EXPECT_TRUE(config2 && "Parse second stream");
  296. optional<Configuration> config3 = loader.OverlayResourceFile(*config2, "file3.xml");
  297. EXPECT_TRUE(config3 && "Parse third stream");
  298. EXPECT_EQ("value1", config3->GetWithDefault("key1", ""));
  299. EXPECT_EQ("value2", config3->GetWithDefault("key2", ""));
  300. EXPECT_EQ("value3", config3->GetWithDefault("key3", ""));
  301. }
  302. }
  303. TEST(ConfigurationTest, TestDefaultConfigs) {
  304. // Search path
  305. {
  306. TempDir tempDir;
  307. TempFile coreSite(tempDir.path + "/core-site.xml");
  308. writeSimpleConfig(coreSite.filename, "key1", "value1");
  309. ConfigurationLoader loader;
  310. loader.SetSearchPath(tempDir.path);
  311. optional<Configuration> config = loader.LoadDefaultResources<Configuration>();
  312. EXPECT_TRUE(config && "Parse streams");
  313. EXPECT_EQ("value1", config->GetWithDefault("key1", ""));
  314. }
  315. }
  316. TEST(ConfigurationTest, TestIntConversions) {
  317. /* No defaults */
  318. {
  319. std::stringstream stream;
  320. simpleConfigStream(stream, "key1", "1");
  321. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  322. EXPECT_TRUE(config && "Parse single value");
  323. optional<int64_t> value = config->GetInt("key1");
  324. EXPECT_TRUE((bool)value);
  325. EXPECT_EQ(1, *value);
  326. EXPECT_FALSE(config->GetInt("key2"));
  327. }
  328. {
  329. optional<Configuration> config = simpleConfig("key1", "1");
  330. EXPECT_EQ(1, config->GetIntWithDefault("key1", -1));
  331. }
  332. {
  333. optional<Configuration> config = simpleConfig("key1", "-100");
  334. EXPECT_EQ(-100, config->GetIntWithDefault("key1", -1));
  335. }
  336. {
  337. optional<Configuration> config = simpleConfig("key1", " 1 ");
  338. EXPECT_EQ(1, config->GetIntWithDefault("key1", -1));
  339. }
  340. {
  341. optional<Configuration> config = simpleConfig("key1", "");
  342. EXPECT_EQ(-1, config->GetIntWithDefault("key1", -1));
  343. }
  344. {
  345. optional<Configuration> config = simpleConfig("key1", "spam");
  346. EXPECT_EQ(-1, config->GetIntWithDefault("key1", -1));
  347. }
  348. {
  349. optional<Configuration> config = simpleConfig("key2", "");
  350. EXPECT_EQ(-1, config->GetIntWithDefault("key1", -1));
  351. }
  352. }
  353. TEST(ConfigurationTest, TestDoubleConversions) {
  354. /* No defaults */
  355. {
  356. std::stringstream stream;
  357. simpleConfigStream(stream, "key1", "1");
  358. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  359. EXPECT_TRUE(config && "Parse single value");
  360. optional<double> value = config->GetDouble("key1");
  361. EXPECT_TRUE((bool)value);
  362. EXPECT_EQ(1, *value);
  363. EXPECT_FALSE(config->GetDouble("key2"));
  364. }
  365. {
  366. optional<Configuration> config = simpleConfig("key1", "1");
  367. EXPECT_EQ(1, config->GetDoubleWithDefault("key1", -1));
  368. }
  369. {
  370. optional<Configuration> config = simpleConfig("key1", "-100");
  371. EXPECT_EQ(-100, config->GetDoubleWithDefault("key1", -1));
  372. }
  373. {
  374. optional<Configuration> config = simpleConfig("key1", " 1 ");
  375. EXPECT_EQ(1, config->GetDoubleWithDefault("key1", -1));
  376. }
  377. {
  378. optional<Configuration> config = simpleConfig("key1", "");
  379. EXPECT_EQ(-1, config->GetDoubleWithDefault("key1", -1));
  380. }
  381. {
  382. optional<Configuration> config = simpleConfig("key1", "spam");
  383. EXPECT_EQ(-1, config->GetDoubleWithDefault("key1", -1));
  384. }
  385. {
  386. optional<Configuration> config = simpleConfig("key2", "");
  387. EXPECT_EQ(-1, config->GetDoubleWithDefault("key1", -1));
  388. }
  389. { /* Out of range */
  390. optional<Configuration> config = simpleConfig("key2", "1e9999");
  391. EXPECT_EQ(-1, config->GetDoubleWithDefault("key1", -1));
  392. }
  393. }
  394. TEST(ConfigurationTest, TestBoolConversions) {
  395. /* No defaults */
  396. {
  397. std::stringstream stream;
  398. simpleConfigStream(stream, "key1", "true");
  399. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  400. EXPECT_TRUE(config && "Parse single value");
  401. optional<bool> value = config->GetBool("key1");
  402. EXPECT_TRUE((bool)value);
  403. EXPECT_EQ(true, *value);
  404. EXPECT_FALSE(config->GetBool("key2"));
  405. }
  406. {
  407. optional<Configuration> config = simpleConfig("key1", "true");
  408. EXPECT_EQ(true, config->GetBoolWithDefault("key1", false));
  409. }
  410. {
  411. optional<Configuration> config = simpleConfig("key1", "tRuE");
  412. EXPECT_EQ(true, config->GetBoolWithDefault("key1", false));
  413. }
  414. {
  415. optional<Configuration> config = simpleConfig("key1", "false");
  416. EXPECT_FALSE(config->GetBoolWithDefault("key1", true));
  417. }
  418. {
  419. optional<Configuration> config = simpleConfig("key1", "FaLsE");
  420. EXPECT_FALSE(config->GetBoolWithDefault("key1", true));
  421. }
  422. {
  423. optional<Configuration> config = simpleConfig("key1", " FaLsE ");
  424. EXPECT_FALSE(config->GetBoolWithDefault("key1", true));
  425. }
  426. {
  427. optional<Configuration> config = simpleConfig("key1", "");
  428. EXPECT_EQ(true, config->GetBoolWithDefault("key1", true));
  429. }
  430. {
  431. optional<Configuration> config = simpleConfig("key1", "spam");
  432. EXPECT_EQ(true, config->GetBoolWithDefault("key1", true));
  433. }
  434. {
  435. optional<Configuration> config = simpleConfig("key1", "");
  436. EXPECT_EQ(true, config->GetBoolWithDefault("key2", true));
  437. }
  438. }
  439. TEST(ConfigurationTest, TestUriConversions) {
  440. /* No defaults */
  441. {
  442. std::stringstream stream;
  443. simpleConfigStream(stream, "key1", "hdfs:///");
  444. optional<Configuration> config = ConfigurationLoader().Load<Configuration>(stream.str());
  445. EXPECT_TRUE(config && "Parse single value");
  446. optional<URI> value = config->GetUri("key1");
  447. EXPECT_TRUE((bool)value);
  448. EXPECT_EQ("hdfs:///", value->str());
  449. EXPECT_FALSE(config->GetUri("key2"));
  450. }
  451. {
  452. optional<Configuration> config = simpleConfig("key1", "hdfs:///");
  453. EXPECT_EQ("hdfs:///", config->GetUriWithDefault("key1", "http:///").str());
  454. }
  455. {
  456. optional<Configuration> config = simpleConfig("key1", " hdfs:/// ");
  457. EXPECT_EQ("hdfs:///", config->GetUriWithDefault("key1", "http:///").str());
  458. }
  459. {
  460. optional<Configuration> config = simpleConfig("key1", "");
  461. EXPECT_EQ("", config->GetUriWithDefault("key1", "http:///").str());
  462. }
  463. {
  464. optional<Configuration> config = simpleConfig("key1", "%%"); // invalid URI
  465. EXPECT_EQ("http:///", config->GetUriWithDefault("key1", "http:///").str());
  466. }
  467. {
  468. optional<Configuration> config = simpleConfig("key2", "hdfs:///");
  469. EXPECT_EQ("http:///", config->GetUriWithDefault("key1", "http:///").str());
  470. }
  471. }
  472. int main(int argc, char *argv[]) {
  473. /*
  474. * The following line must be executed to initialize Google Mock
  475. * (and Google Test) before running the tests.
  476. */
  477. ::testing::InitGoogleMock(&argc, argv);
  478. return RUN_ALL_TESTS();
  479. }
  480. }