hdfs_ext_test.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  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 "hdfspp_mini_dfs.h"
  19. #include "hdfspp/hdfs_ext.h"
  20. #include "x-platform/syscall.h"
  21. #include <cstring>
  22. #include <chrono>
  23. #include <exception>
  24. namespace hdfs {
  25. class HdfsExtTest: public ::testing::Test {
  26. public:
  27. MiniCluster cluster;
  28. };
  29. // Make sure we can set up a mini-cluster and connect to it
  30. TEST_F(HdfsExtTest, TestGetBlockLocations) {
  31. HdfsHandle connection = cluster.connect_c();
  32. EXPECT_NE(nullptr, connection.handle());
  33. hdfsBlockLocations * blocks = nullptr;
  34. // Free a null pointer
  35. int result = hdfsFreeBlockLocations(blocks);
  36. EXPECT_EQ(0, result);
  37. // Test non-extant files
  38. EXPECT_EQ(-1, hdfsGetBlockLocations(connection, "non_extant_file", &blocks)); // Should be an error
  39. EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
  40. // Test an extant file
  41. std::string filename = connection.newFile(1024);
  42. result = hdfsGetBlockLocations(connection, filename.c_str(), &blocks);
  43. EXPECT_EQ(0, result);
  44. EXPECT_EQ(1024, blocks->fileLength);
  45. EXPECT_EQ(1, blocks->num_blocks);
  46. EXPECT_EQ(0, blocks->isUnderConstruction);
  47. EXPECT_NE(0, blocks->isLastBlockComplete);
  48. EXPECT_EQ(1024, blocks->blocks->num_bytes);
  49. EXPECT_EQ(0, blocks->blocks->start_offset);
  50. EXPECT_EQ(1, blocks->blocks->num_locations);
  51. EXPECT_NE(nullptr, blocks->blocks->locations->hostname);
  52. EXPECT_NE(nullptr, blocks->blocks->locations->ip_address);
  53. EXPECT_NE(nullptr, blocks->blocks->locations->network_location);
  54. EXPECT_NE(0, blocks->blocks->locations->xfer_port);
  55. result = hdfsFreeBlockLocations(blocks);
  56. EXPECT_EQ(0, result);
  57. }
  58. // Writing a file to the filesystem and checking the used space
  59. TEST_F(HdfsExtTest, TestGetUsed) {
  60. using namespace std::chrono;
  61. HdfsHandle connection = cluster.connect_c();
  62. hdfsFS fs = connection.handle();
  63. EXPECT_NE(nullptr, fs);
  64. // File system's used space before writing
  65. tOffset used_before_write;
  66. EXPECT_GE(used_before_write = hdfsGetUsed(fs), 0);
  67. // Write to a file
  68. tOffset fileSize = 1024;
  69. std::string filename = connection.newFile(fileSize);
  70. //Need to run hdfsGetUsed() in a loop until the refreshInterval
  71. //is passed on the filesystem and the used space is updated
  72. //Time-out is 3 minutes
  73. tOffset used_after_write;
  74. tOffset difference;
  75. minutes beginTime = duration_cast<minutes>(
  76. system_clock::now().time_since_epoch());
  77. minutes currentTime;
  78. do{
  79. EXPECT_GE(used_after_write = hdfsGetUsed(fs), 0);
  80. difference = used_after_write - used_before_write;
  81. currentTime = duration_cast<minutes>(
  82. system_clock::now().time_since_epoch());
  83. } while (difference == 0 && currentTime.count() - beginTime.count() < 3);
  84. //There should be at least fileSize bytes added to the used space
  85. EXPECT_GT(difference, fileSize);
  86. //There could be additional metadata added to the used space,
  87. //but no more than double the fileSize
  88. EXPECT_LT(difference, fileSize * 2);
  89. }
  90. //Testing allow, disallow, create, and delete snapshot
  91. TEST_F(HdfsExtTest, TestSnapshotOperations) {
  92. HdfsHandle connection = cluster.connect_c();
  93. hdfsFS fs = connection.handle();
  94. EXPECT_NE(nullptr, fs);
  95. //argument 'path' is NULL
  96. EXPECT_EQ(-1, hdfsAllowSnapshot(fs, nullptr));
  97. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  98. EXPECT_EQ(-1, hdfsCreateSnapshot(fs, nullptr, "Bad"));
  99. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  100. EXPECT_EQ(-1, hdfsDeleteSnapshot(fs, nullptr, "Bad"));
  101. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  102. EXPECT_EQ(-1, hdfsRenameSnapshot(fs, nullptr, "Bad", "Bad"));
  103. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  104. EXPECT_EQ(-1, hdfsDisallowSnapshot(fs, nullptr));
  105. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  106. //argument 'name' is NULL for deletion
  107. EXPECT_EQ(-1, hdfsDeleteSnapshot(fs, "/dir/", nullptr));
  108. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  109. //Path not found
  110. std::string path = "/wrong/dir/";
  111. EXPECT_EQ(-1, hdfsAllowSnapshot(fs, path.c_str()));
  112. EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
  113. EXPECT_EQ(-1, hdfsCreateSnapshot(fs, path.c_str(), "Bad"));
  114. EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
  115. EXPECT_EQ(-1, hdfsDeleteSnapshot(fs, path.c_str(), "Bad"));
  116. EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
  117. EXPECT_EQ(-1, hdfsRenameSnapshot(fs, path.c_str(), "Bad", "Bad"));
  118. EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
  119. EXPECT_EQ(-1, hdfsDisallowSnapshot(fs, path.c_str()));
  120. EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
  121. //Not a directory
  122. path = connection.newFile(1024); //1024 byte file
  123. EXPECT_EQ(-1, hdfsAllowSnapshot(fs, path.c_str()));
  124. EXPECT_EQ((int) std::errc::not_a_directory, errno);
  125. EXPECT_EQ(-1, hdfsCreateSnapshot(fs, path.c_str(), "Bad"));
  126. EXPECT_EQ((int) std::errc::not_a_directory, errno);
  127. EXPECT_EQ(-1, hdfsDeleteSnapshot(fs, path.c_str(), "Bad"));
  128. EXPECT_EQ((int) std::errc::not_a_directory, errno);
  129. EXPECT_EQ(-1, hdfsRenameSnapshot(fs, path.c_str(), "Bad", "Bad"));
  130. EXPECT_EQ((int) std::errc::not_a_directory, errno);
  131. EXPECT_EQ(-1, hdfsDisallowSnapshot(fs, path.c_str()));
  132. EXPECT_EQ((int) std::errc::not_a_directory, errno);
  133. //Not snapshottable directory
  134. std::string dirName = connection.newDir();
  135. EXPECT_EQ(0, hdfsDisallowSnapshot(fs, dirName.c_str()));
  136. EXPECT_EQ(-1, hdfsCreateSnapshot(fs, dirName.c_str(), "Bad"));
  137. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  138. //Verify snapshot created
  139. EXPECT_EQ(0, hdfsAllowSnapshot(fs, dirName.c_str()));
  140. EXPECT_EQ(0, hdfsCreateSnapshot(fs, dirName.c_str(), "Good"));
  141. std::string snapDir = dirName + ".snapshot/";
  142. int size;
  143. hdfsFileInfo *file_infos;
  144. EXPECT_NE(nullptr, file_infos = hdfsListDirectory(fs, snapDir.c_str(), &size));
  145. EXPECT_EQ(1, size);
  146. EXPECT_STREQ("Good", file_infos[0].mName);
  147. hdfsFreeFileInfo(file_infos, 1);
  148. //Verify snapshot renamed
  149. EXPECT_EQ(0, hdfsRenameSnapshot(fs, dirName.c_str(), "Good", "Best"));
  150. //Verify snapshot deleted
  151. EXPECT_EQ(0, hdfsDeleteSnapshot(fs, dirName.c_str(), "Best"));
  152. EXPECT_EQ(nullptr, file_infos = hdfsListDirectory(fs, snapDir.c_str(), &size));
  153. EXPECT_EQ(0, size);
  154. hdfsFreeFileInfo(file_infos, 0);
  155. }
  156. //Testing creating directories
  157. TEST_F(HdfsExtTest, TestMkdirs) {
  158. HdfsHandle connection = cluster.connect_c();
  159. hdfsFS fs = connection.handle();
  160. EXPECT_NE(nullptr, fs);
  161. //Correct operation
  162. EXPECT_EQ(0, hdfsCreateDirectory(fs, "/myDir123"));
  163. //TODO Should return error if directory already exists?
  164. //EXPECT_EQ(-1, hdfsCreateDirectory(fs, "/myDir123"));
  165. //EXPECT_EQ((int) std::errc::file_exists, errno);
  166. //Creating directory on a path of the existing file
  167. std::string path = connection.newFile(1024); //1024 byte file
  168. EXPECT_EQ(-1, hdfsCreateDirectory(fs, path.c_str()));
  169. EXPECT_EQ((int) std::errc::file_exists, errno);
  170. }
  171. //Testing deleting files and directories
  172. TEST_F(HdfsExtTest, TestDelete) {
  173. HdfsHandle connection = cluster.connect_c();
  174. hdfsFS fs = connection.handle();
  175. EXPECT_NE(nullptr, fs);
  176. //Path not found
  177. EXPECT_EQ(-1, hdfsDelete(fs, "/wrong_path", 1));
  178. EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
  179. EXPECT_EQ(0, hdfsCreateDirectory(fs, "/myDir"));
  180. std::string path = connection.newFile("/myDir", 1024); //1024 byte file
  181. //Non-recursive delete should fail on a non-empty directory
  182. //error ENOTEMPTY(39) for libhdfspp or 255 for libhdfs
  183. EXPECT_EQ(-1, hdfsDelete(fs, "/myDir", 0));
  184. EXPECT_EQ((int) std::errc::directory_not_empty, errno);
  185. //Correct operation
  186. EXPECT_EQ(0, hdfsDelete(fs, "/myDir", 1));
  187. }
  188. //Testing renaming files and directories
  189. TEST_F(HdfsExtTest, TestRename) {
  190. HdfsHandle connection = cluster.connect_c();
  191. hdfsFS fs = connection.handle();
  192. EXPECT_NE(nullptr, fs);
  193. //Creating directory with two files
  194. EXPECT_EQ(0, hdfsCreateDirectory(fs, "/myDir"));
  195. std::string file1 = connection.newFile("/myDir", 1024); //1024 byte file
  196. std::string file2 = connection.newFile("/myDir", 1024); //1024 byte file
  197. std::string file3 = connection.newFile(1024); //1024 byte file
  198. //Path not found
  199. EXPECT_EQ(-1, hdfsRename(fs, "/wrong_path", "/new_name"));
  200. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  201. //No parent directory in new path
  202. EXPECT_EQ(-1, hdfsRename(fs, file1.c_str(), "/wrong_parent/new_name"));
  203. EXPECT_EQ((int ) std::errc::invalid_argument, errno);
  204. //New name already exists in the folder
  205. EXPECT_EQ(-1, hdfsRename(fs, file1.c_str(), file2.c_str()));
  206. EXPECT_EQ((int ) std::errc::invalid_argument, errno);
  207. //Correct operation
  208. EXPECT_EQ(0, hdfsRename(fs, file1.c_str(), "/myDir/new_awesome_name"));
  209. EXPECT_EQ(0, hdfsRename(fs, file3.c_str(), "/myDir/another_file"));
  210. EXPECT_EQ(0, hdfsRename(fs, "/myDir", "/new_awesome_dir"));
  211. //Verification
  212. int numEntries;
  213. hdfsFileInfo * dirList = hdfsListDirectory(fs, "/new_awesome_dir", &numEntries);
  214. EXPECT_NE(nullptr, dirList);
  215. EXPECT_EQ(3, numEntries);
  216. hdfsFreeFileInfo(dirList, 3);
  217. }
  218. //Testing Chmod and Chown
  219. TEST_F(HdfsExtTest, TestChmodChown) {
  220. HdfsHandle connection = cluster.connect_c();
  221. hdfsFS fs = connection.handle();
  222. EXPECT_NE(nullptr, fs);
  223. //Path not found
  224. std::string path = "/wrong/dir/";
  225. EXPECT_EQ(-1, hdfsChmod(fs, path.c_str(), 0777));
  226. EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
  227. EXPECT_EQ(-1, hdfsChown(fs, path.c_str(), "foo", "bar"));
  228. EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
  229. //Wrong arguments
  230. path = connection.newFile(1024); //1024 byte file
  231. EXPECT_EQ(-1, hdfsChmod(fs, nullptr, 0777));
  232. EXPECT_EQ((int ) std::errc::invalid_argument, errno);
  233. EXPECT_EQ(-1, hdfsChmod(fs, path.c_str(), 07777));
  234. EXPECT_EQ((int ) std::errc::invalid_argument, errno);
  235. EXPECT_EQ(-1, hdfsChmod(fs, path.c_str(), -1));
  236. EXPECT_EQ((int ) std::errc::invalid_argument, errno);
  237. EXPECT_EQ(-1, hdfsChown(fs, nullptr, "foo", "bar"));
  238. EXPECT_EQ((int ) std::errc::invalid_argument, errno);
  239. //Permission denied
  240. HdfsHandle connection2 = cluster.connect_c("OtherGuy");
  241. hdfsFS fs2 = connection2.handle();
  242. EXPECT_EQ(-1, hdfsChmod(fs2, path.c_str(), 0123));
  243. EXPECT_EQ((int ) std::errc::permission_denied, errno);
  244. EXPECT_EQ(-1, hdfsChown(fs2, path.c_str(), "cool", "nice"));
  245. EXPECT_EQ((int ) std::errc::permission_denied, errno);
  246. //Verify Chmod and Chown worked
  247. EXPECT_EQ(0, hdfsChmod(fs, path.c_str(), 0123));
  248. EXPECT_EQ(0, hdfsChown(fs, path.c_str(), "cool", "nice"));
  249. hdfsFileInfo *file_info;
  250. EXPECT_NE(nullptr, file_info = hdfsGetPathInfo(fs, path.c_str()));
  251. EXPECT_EQ(0123, file_info->mPermissions);
  252. EXPECT_STREQ("cool", file_info->mOwner);
  253. EXPECT_STREQ("nice", file_info->mGroup);
  254. hdfsFreeFileInfo(file_info, 1);
  255. }
  256. //Testing EOF
  257. TEST_F(HdfsExtTest, TestEOF) {
  258. HdfsHandle connection = cluster.connect_c();
  259. hdfsFS fs = connection.handle();
  260. EXPECT_NE(nullptr, fs);
  261. //Write to a file
  262. errno = 0;
  263. int size = 256;
  264. std::string path = "/eofTest";
  265. hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
  266. EXPECT_NE(nullptr, file);
  267. void * buf = malloc(size);
  268. memset(buf, ' ', size);
  269. EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
  270. free(buf);
  271. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  272. //libhdfs file operations work, but sometimes sets errno ENOENT : 2
  273. //Test normal reading (no EOF)
  274. char buffer[300];
  275. file = hdfsOpenFile(fs, path.c_str(), O_RDONLY, 0, 0, 0);
  276. EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
  277. //Read executes correctly, but causes a warning (captured in HDFS-10595)
  278. //and sets errno to EINPROGRESS 115 : Operation now in progress
  279. //Test reading at offset past the EOF
  280. EXPECT_EQ(-1, hdfsPread(fs, file, sizeof(buffer), buffer, sizeof(buffer)));
  281. EXPECT_EQ(Status::kInvalidOffset, errno);
  282. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  283. }
  284. //Testing hdfsExists
  285. TEST_F(HdfsExtTest, TestExists) {
  286. HdfsHandle connection = cluster.connect_c();
  287. hdfsFS fs = connection.handle();
  288. EXPECT_NE(nullptr, fs);
  289. //Path not found
  290. EXPECT_EQ(-1, hdfsExists(fs, "/wrong/dir/"));
  291. EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
  292. //Correct operation
  293. std::string pathDir = "/testExistsDir";
  294. EXPECT_EQ(0, hdfsCreateDirectory(fs, pathDir.c_str()));
  295. EXPECT_EQ(0, hdfsExists(fs, pathDir.c_str()));
  296. std::string pathFile = connection.newFile(pathDir.c_str(), 1024);
  297. EXPECT_EQ(0, hdfsExists(fs, pathFile.c_str()));
  298. //Permission denied
  299. EXPECT_EQ(0, hdfsChmod(fs, pathDir.c_str(), 0700));
  300. HdfsHandle connection2 = cluster.connect_c("OtherGuy");
  301. hdfsFS fs2 = connection2.handle();
  302. EXPECT_EQ(-1, hdfsExists(fs2, pathFile.c_str()));
  303. EXPECT_EQ((int ) std::errc::permission_denied, errno);
  304. }
  305. //Testing Replication and Time modifications
  306. TEST_F(HdfsExtTest, TestReplAndTime) {
  307. HdfsHandle connection = cluster.connect_c();
  308. hdfsFS fs = connection.handle();
  309. EXPECT_NE(nullptr, fs);
  310. std::string path = "/wrong/dir/";
  311. //Path not found
  312. EXPECT_EQ(-1, hdfsSetReplication(fs, path.c_str(), 3));
  313. EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
  314. EXPECT_EQ(-1, hdfsUtime(fs, path.c_str(), 1000000, 1000000));
  315. EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
  316. //Correct operation
  317. path = connection.newFile(1024);
  318. EXPECT_EQ(0, hdfsSetReplication(fs, path.c_str(), 7));
  319. EXPECT_EQ(0, hdfsUtime(fs, path.c_str(), 123456789, 987654321));
  320. hdfsFileInfo *file_info;
  321. EXPECT_NE(nullptr, file_info = hdfsGetPathInfo(fs, path.c_str()));
  322. EXPECT_EQ(7, file_info->mReplication);
  323. EXPECT_EQ(123456789, file_info->mLastMod);
  324. EXPECT_EQ(987654321, file_info->mLastAccess);
  325. hdfsFreeFileInfo(file_info, 1);
  326. //Wrong arguments
  327. EXPECT_EQ(-1, hdfsSetReplication(fs, path.c_str(), 0));
  328. EXPECT_EQ((int ) std::errc::invalid_argument, errno);
  329. EXPECT_EQ(-1, hdfsSetReplication(fs, path.c_str(), 513));
  330. EXPECT_EQ((int ) std::errc::invalid_argument, errno);
  331. //Permission denied
  332. EXPECT_EQ(0, hdfsChmod(fs, path.c_str(), 0700));
  333. HdfsHandle connection2 = cluster.connect_c("OtherGuy");
  334. hdfsFS fs2 = connection2.handle();
  335. EXPECT_EQ(-1, hdfsSetReplication(fs2, path.c_str(), 3));
  336. EXPECT_EQ((int ) std::errc::permission_denied, errno);
  337. EXPECT_EQ(-1, hdfsUtime(fs2, path.c_str(), 111111111, 222222222));
  338. EXPECT_EQ((int ) std::errc::permission_denied, errno);
  339. }
  340. //Testing getting default block size at path
  341. TEST_F(HdfsExtTest, TestDefaultBlockSize) {
  342. HdfsHandle connection = cluster.connect_c();
  343. hdfsFS fs = connection.handle();
  344. EXPECT_NE(nullptr, fs);
  345. //Correct operation (existing path)
  346. std::string path = connection.newFile(1024);
  347. long block_size = hdfsGetDefaultBlockSizeAtPath(fs, path.c_str());
  348. EXPECT_GT(block_size, 0);
  349. hdfsFileInfo *file_info;
  350. EXPECT_NE(nullptr, file_info = hdfsGetPathInfo(fs, path.c_str()));
  351. EXPECT_EQ(block_size, file_info->mBlockSize);
  352. hdfsFreeFileInfo(file_info, 1);
  353. //Non-existing path
  354. path = "/wrong/dir/";
  355. EXPECT_GT(hdfsGetDefaultBlockSizeAtPath(fs, path.c_str()), 0);
  356. //No path specified
  357. EXPECT_GT(hdfsGetDefaultBlockSize(fs), 0);
  358. }
  359. //Testing getting hosts
  360. TEST_F(HdfsExtTest, TestHosts) {
  361. HdfsHandle connection = cluster.connect_c();
  362. hdfsFS fs = connection.handle();
  363. EXPECT_NE(nullptr, fs);
  364. char *** hosts = nullptr;
  365. // Free a null pointer
  366. hdfsFreeHosts(hosts);
  367. EXPECT_EQ(0, errno);
  368. // Test non-existent files
  369. EXPECT_EQ(nullptr, hdfsGetHosts(fs, "/wrong/file/", 0, std::numeric_limits<int64_t>::max()));
  370. EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
  371. // Test an existent file
  372. std::string filename = connection.newFile(1024);
  373. EXPECT_NE(nullptr, hosts = hdfsGetHosts(fs, filename.c_str(), 0, std::numeric_limits<int64_t>::max()));
  374. //Make sure there is at least one host
  375. EXPECT_NE(nullptr, *hosts);
  376. EXPECT_NE(nullptr, **hosts);
  377. hdfsFreeHosts(hosts);
  378. EXPECT_EQ(0, errno);
  379. //Test invalid arguments
  380. EXPECT_EQ(nullptr, hdfsGetHosts(fs, filename.c_str(), 0, std::numeric_limits<int64_t>::min()));
  381. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  382. //Test invalid arguments
  383. EXPECT_EQ(nullptr, hdfsGetHosts(fs, filename.c_str(), std::numeric_limits<int64_t>::min(), std::numeric_limits<int64_t>::max()));
  384. EXPECT_EQ((int) std::errc::invalid_argument, errno);
  385. }
  386. //Testing read statistics
  387. TEST_F(HdfsExtTest, TestReadStats) {
  388. HdfsHandle connection = cluster.connect_c();
  389. hdfsFS fs = connection.handle();
  390. EXPECT_NE(nullptr, fs);
  391. struct hdfsReadStatistics *stats;
  392. //Write to a file
  393. int size = 256;
  394. std::string path = "/readStatTest";
  395. hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
  396. EXPECT_NE(nullptr, file);
  397. void * buf = malloc(size);
  398. XPlatform::Syscall::ClearBufferSafely(buf, size);
  399. EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
  400. free(buf);
  401. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  402. //test before reading
  403. file = hdfsOpenFile(fs, path.c_str(), O_RDONLY, 0, 0, 0);
  404. EXPECT_EQ(0, hdfsFileGetReadStatistics(file, &stats));
  405. EXPECT_EQ(0, stats->totalBytesRead);
  406. hdfsFileFreeReadStatistics(stats);
  407. //test after reading
  408. char buffer[123];
  409. //Read executes correctly, but causes a warning (captured in HDFS-10595)
  410. EXPECT_EQ(sizeof(buffer), hdfsRead(fs, file, buffer, sizeof(buffer)));
  411. EXPECT_EQ(0, hdfsFileGetReadStatistics(file, &stats));
  412. EXPECT_EQ(sizeof(buffer), stats->totalBytesRead);
  413. EXPECT_EQ(sizeof(buffer), stats->totalLocalBytesRead);
  414. EXPECT_EQ(0, hdfsReadStatisticsGetRemoteBytesRead(stats));
  415. hdfsFileFreeReadStatistics(stats);
  416. //test after clearing
  417. EXPECT_EQ(0, hdfsFileClearReadStatistics(file));
  418. EXPECT_EQ(0, hdfsFileGetReadStatistics(file, &stats));
  419. EXPECT_EQ(0, stats->totalBytesRead);
  420. hdfsFileFreeReadStatistics(stats);
  421. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  422. // Since libhdfs is not guaranteed to set errno to 0 on successful
  423. // operations, we disable this check for now, see HDFS-14325 for a
  424. // long term solution to this problem
  425. // EXPECT_EQ(0, errno);
  426. }
  427. //Testing working directory
  428. TEST_F(HdfsExtTest, TestWorkingDirectory) {
  429. HdfsHandle connection = cluster.connect_c();
  430. hdfsFS fs = connection.handle();
  431. EXPECT_NE(nullptr, fs);
  432. //Correct operation of setter and getter
  433. std::string pathDir = "/testWorkDir/";
  434. EXPECT_EQ(0, hdfsCreateDirectory(fs, pathDir.c_str()));
  435. std::string pathFile = connection.newFile(pathDir.c_str(), 1024);
  436. EXPECT_EQ(0, hdfsSetWorkingDirectory(fs, pathDir.c_str()));
  437. char array[100];
  438. EXPECT_STREQ(pathDir.c_str(), hdfsGetWorkingDirectory(fs, array, 100));
  439. //Get relative path
  440. std::size_t slashPos = pathFile.find_last_of("/");
  441. std::string fileName = pathFile.substr(slashPos + 1);
  442. //Testing various functions with relative path:
  443. //hdfsGetDefaultBlockSizeAtPath
  444. EXPECT_GT(hdfsGetDefaultBlockSizeAtPath(fs, fileName.c_str()), 0);
  445. //hdfsSetReplication
  446. EXPECT_EQ(0, hdfsSetReplication(fs, fileName.c_str(), 7));
  447. //hdfsUtime
  448. EXPECT_EQ(0, hdfsUtime(fs, fileName.c_str(), 123456789, 987654321));
  449. //hdfsExists
  450. EXPECT_EQ(0, hdfsExists(fs, fileName.c_str()));
  451. //hdfsGetPathInfo
  452. hdfsFileInfo *file_info;
  453. EXPECT_NE(nullptr, file_info = hdfsGetPathInfo(fs, fileName.c_str()));
  454. hdfsFreeFileInfo(file_info, 1);
  455. //hdfsOpenFile
  456. hdfsFile file;
  457. file = hdfsOpenFile(fs, fileName.c_str(), O_RDONLY, 0, 0, 0);
  458. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  459. //hdfsCreateDirectory
  460. EXPECT_EQ(0, hdfsCreateDirectory(fs, "newDir"));
  461. //add another file
  462. std::string fileName2 = connection.newFile(pathDir + "/newDir", 1024);
  463. //hdfsListDirectory
  464. int numEntries;
  465. hdfsFileInfo * dirList;
  466. EXPECT_NE(nullptr, dirList = hdfsListDirectory(fs, "newDir", &numEntries));
  467. EXPECT_EQ(1, numEntries);
  468. hdfsFreeFileInfo(dirList, 1);
  469. //hdfsChmod
  470. EXPECT_EQ(0, hdfsChmod(fs, fileName.c_str(), 0777));
  471. //hdfsChown
  472. EXPECT_EQ(0, hdfsChown(fs, fileName.c_str(), "cool", "nice"));
  473. //hdfsDisallowSnapshot
  474. EXPECT_EQ(0, hdfsDisallowSnapshot(fs, "newDir"));
  475. //hdfsAllowSnapshot
  476. EXPECT_EQ(0, hdfsAllowSnapshot(fs, "newDir"));
  477. //hdfsCreateSnapshot
  478. EXPECT_EQ(0, hdfsCreateSnapshot(fs, "newDir", "Some"));
  479. //hdfsDeleteSnapshot
  480. EXPECT_EQ(0, hdfsDeleteSnapshot(fs, "newDir", "Some"));
  481. //hdfsGetBlockLocations
  482. hdfsBlockLocations * blocks = nullptr;
  483. EXPECT_EQ(0, hdfsGetBlockLocations(connection, fileName.c_str(), &blocks));
  484. hdfsFreeBlockLocations(blocks);
  485. //hdfsGetHosts
  486. char *** hosts;
  487. EXPECT_NE(nullptr, hosts = hdfsGetHosts(fs, fileName.c_str(), 0, std::numeric_limits<int64_t>::max()));
  488. hdfsFreeHosts(hosts);
  489. //hdfsRename
  490. EXPECT_EQ(0, hdfsRename(fs, fileName.c_str(), "new_file_name"));
  491. //hdfsDelete
  492. EXPECT_EQ(0, hdfsDelete(fs, "new_file_name", 0));
  493. }
  494. // Flags used to test event handlers
  495. static int connect_callback_invoked = 0;
  496. int basic_fs_callback(const char *event, const char *cluster, int64_t value, int64_t cookie) {
  497. (void)cluster;
  498. (void)value;
  499. if(::strstr(FS_NN_CONNECT_EVENT, event) && cookie == 0xFFF0) {
  500. connect_callback_invoked = 1;
  501. }
  502. return LIBHDFSPP_EVENT_OK;
  503. }
  504. // Make sure event handler gets called during connect
  505. TEST_F(HdfsExtTest, TestConnectEvent) {
  506. connect_callback_invoked = 0;
  507. hdfsPreAttachFSMonitor(basic_fs_callback, 0xFFF0);
  508. HdfsHandle connection = cluster.connect_c();
  509. hdfsFS fs = connection.handle();
  510. EXPECT_NE(nullptr, fs);
  511. EXPECT_EQ(connect_callback_invoked, 1);
  512. }
  513. int throwing_fs_callback(const char *event, const char *cluster, int64_t value, int64_t cookie) {
  514. (void)cluster;
  515. (void)value;
  516. if(::strstr(FS_NN_CONNECT_EVENT, event) && cookie == 0xFFF1) {
  517. connect_callback_invoked = 1;
  518. throw std::runtime_error("Throwing in callbacks is a bad thing.");
  519. }
  520. return LIBHDFSPP_EVENT_OK;
  521. }
  522. // Make sure throwing in the connect event handler doesn't prevent connection
  523. TEST_F(HdfsExtTest, TestConnectEventThrow) {
  524. connect_callback_invoked = 0;
  525. hdfsPreAttachFSMonitor(throwing_fs_callback, 0xFFF1);
  526. HdfsHandle connection = cluster.connect_c();
  527. hdfsFS fs = connection.handle();
  528. EXPECT_NE(nullptr, fs);
  529. EXPECT_EQ(connect_callback_invoked, 1);
  530. }
  531. int char_throwing_fs_callback(const char *event, const char *cluster, int64_t value, int64_t cookie) {
  532. (void)cluster;
  533. (void)value;
  534. if(::strstr(FS_NN_CONNECT_EVENT, event) && cookie == 0xFFF2) {
  535. connect_callback_invoked = 1;
  536. throw "Throwing non std::exceptions in callbacks is even worse.";
  537. }
  538. return LIBHDFSPP_EVENT_OK;
  539. }
  540. TEST_F(HdfsExtTest, TestConnectEventThrowChar) {
  541. connect_callback_invoked = 0;
  542. hdfsPreAttachFSMonitor(char_throwing_fs_callback, 0xFFF2);
  543. HdfsHandle connection = cluster.connect_c();
  544. hdfsFS fs = connection.handle();
  545. EXPECT_NE(nullptr, fs);
  546. EXPECT_EQ(connect_callback_invoked, 1);
  547. }
  548. // Make sure throwing in the read event handler doesn't prevent reads
  549. int read_handler_invokation_count = 0;
  550. int basic_read_event_handler(const char *event, const char *cluster, const char *file,
  551. int64_t value, int64_t cookie)
  552. {
  553. (void)cluster;
  554. (void)file;
  555. (void)value;
  556. if(::strstr(FILE_DN_READ_EVENT, event) && cookie == 0xFFF3) {
  557. read_handler_invokation_count += 1;
  558. }
  559. return LIBHDFSPP_EVENT_OK;
  560. }
  561. // Testing that read handler is called.
  562. // Note: This is counting calls to async_read rather than hdfsPread.
  563. // Typically a call to hdfs(P)Read that doesn't span blocks/packets
  564. // invokes async_read 6 times; 4 more than required (improving that
  565. // in HDFS-11266).
  566. TEST_F(HdfsExtTest, TestReadEvent) {
  567. read_handler_invokation_count = 0;
  568. hdfsPreAttachFileMonitor(basic_read_event_handler, 0xFFF3);
  569. HdfsHandle connection = cluster.connect_c();
  570. hdfsFS fs = connection.handle();
  571. EXPECT_NE(nullptr, fs);
  572. //Write to a file
  573. errno = 0;
  574. int size = 256;
  575. std::string path = "/readEventTest";
  576. hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
  577. EXPECT_NE(nullptr, file);
  578. void * buf = malloc(size);
  579. memset(buf, ' ', size);
  580. EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
  581. free(buf);
  582. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  583. //Test that read counters are getting incremented
  584. char buffer[300];
  585. file = hdfsOpenFile(fs, path.c_str(), O_RDONLY, 0, 0, 0);
  586. EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
  587. EXPECT_EQ(read_handler_invokation_count, 6);
  588. EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
  589. EXPECT_EQ(read_handler_invokation_count, 12);
  590. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  591. }
  592. int throwing_read_event_handler(const char *event, const char *cluster, const char *file,
  593. int64_t value, int64_t cookie)
  594. {
  595. (void)cluster;
  596. (void)file;
  597. (void)value;
  598. if(::strstr(FILE_DN_READ_EVENT, event) && cookie == 0xFFF4) {
  599. read_handler_invokation_count += 1;
  600. throw std::runtime_error("Throwing here is a bad idea, but shouldn't break reads");
  601. }
  602. return LIBHDFSPP_EVENT_OK;
  603. }
  604. // Testing that reads can be done when event handler throws.
  605. TEST_F(HdfsExtTest, TestReadEventThrow) {
  606. read_handler_invokation_count = 0;
  607. hdfsPreAttachFileMonitor(throwing_read_event_handler, 0xFFF4);
  608. HdfsHandle connection = cluster.connect_c();
  609. hdfsFS fs = connection.handle();
  610. EXPECT_NE(nullptr, fs);
  611. //Write to a file
  612. errno = 0;
  613. int size = 256;
  614. std::string path = "/readEventTest";
  615. hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
  616. EXPECT_NE(nullptr, file);
  617. void * buf = malloc(size);
  618. memset(buf, ' ', size);
  619. EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
  620. free(buf);
  621. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  622. //Test that read counters are getting incremented
  623. char buffer[300];
  624. file = hdfsOpenFile(fs, path.c_str(), O_RDONLY, 0, 0, 0);
  625. EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
  626. EXPECT_EQ(read_handler_invokation_count, 6);
  627. EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
  628. EXPECT_EQ(read_handler_invokation_count, 12);
  629. EXPECT_EQ(0, hdfsCloseFile(fs, file));
  630. }
  631. } // end namespace hdfs
  632. int main(int argc, char *argv[]) {
  633. // The following line must be executed to initialize Google Mock
  634. // (and Google Test) before running the tests.
  635. ::testing::InitGoogleMock(&argc, argv);
  636. int exit_code = RUN_ALL_TESTS();
  637. google::protobuf::ShutdownProtobufLibrary();
  638. return exit_code;
  639. }