123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771 |
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "hdfspp_mini_dfs.h"
- #include "hdfspp/hdfs_ext.h"
- #include <cstring>
- #include <chrono>
- #include <exception>
- namespace hdfs {
- class HdfsExtTest: public ::testing::Test {
- public:
- MiniCluster cluster;
- };
- // Make sure we can set up a mini-cluster and connect to it
- TEST_F(HdfsExtTest, TestGetBlockLocations) {
- HdfsHandle connection = cluster.connect_c();
- EXPECT_NE(nullptr, connection.handle());
- hdfsBlockLocations * blocks = nullptr;
- // Free a null pointer
- int result = hdfsFreeBlockLocations(blocks);
- EXPECT_EQ(0, result);
- // Test non-extant files
- EXPECT_EQ(-1, hdfsGetBlockLocations(connection, "non_extant_file", &blocks)); // Should be an error
- EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
- // Test an extant file
- std::string filename = connection.newFile(1024);
- result = hdfsGetBlockLocations(connection, filename.c_str(), &blocks);
- EXPECT_EQ(0, result);
- EXPECT_EQ(1024, blocks->fileLength);
- EXPECT_EQ(1, blocks->num_blocks);
- EXPECT_EQ(0, blocks->isUnderConstruction);
- EXPECT_NE(0, blocks->isLastBlockComplete);
- EXPECT_EQ(1024, blocks->blocks->num_bytes);
- EXPECT_EQ(0, blocks->blocks->start_offset);
- EXPECT_EQ(1, blocks->blocks->num_locations);
- EXPECT_NE(nullptr, blocks->blocks->locations->hostname);
- EXPECT_NE(nullptr, blocks->blocks->locations->ip_address);
- EXPECT_NE(nullptr, blocks->blocks->locations->network_location);
- EXPECT_NE(0, blocks->blocks->locations->xfer_port);
- result = hdfsFreeBlockLocations(blocks);
- EXPECT_EQ(0, result);
- }
- // Writing a file to the filesystem and checking the used space
- TEST_F(HdfsExtTest, TestGetUsed) {
- using namespace std::chrono;
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- // File system's used space before writing
- tOffset used_before_write;
- EXPECT_GE(used_before_write = hdfsGetUsed(fs), 0);
- // Write to a file
- tOffset fileSize = 1024;
- std::string filename = connection.newFile(fileSize);
- //Need to run hdfsGetUsed() in a loop until the refreshInterval
- //is passed on the filesystem and the used space is updated
- //Time-out is 3 minutes
- tOffset used_after_write;
- tOffset difference;
- minutes beginTime = duration_cast<minutes>(
- system_clock::now().time_since_epoch());
- minutes currentTime;
- do{
- EXPECT_GE(used_after_write = hdfsGetUsed(fs), 0);
- difference = used_after_write - used_before_write;
- currentTime = duration_cast<minutes>(
- system_clock::now().time_since_epoch());
- } while (difference == 0 && currentTime.count() - beginTime.count() < 3);
- //There should be at least fileSize bytes added to the used space
- EXPECT_GT(difference, fileSize);
- //There could be additional metadata added to the used space,
- //but no more than double the fileSize
- EXPECT_LT(difference, fileSize * 2);
- }
- //Testing allow, disallow, create, and delete snapshot
- TEST_F(HdfsExtTest, TestSnapshotOperations) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //argument 'path' is NULL
- EXPECT_EQ(-1, hdfsAllowSnapshot(fs, nullptr));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- EXPECT_EQ(-1, hdfsCreateSnapshot(fs, nullptr, "Bad"));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- EXPECT_EQ(-1, hdfsDeleteSnapshot(fs, nullptr, "Bad"));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- EXPECT_EQ(-1, hdfsRenameSnapshot(fs, nullptr, "Bad", "Bad"));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- EXPECT_EQ(-1, hdfsDisallowSnapshot(fs, nullptr));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- //argument 'name' is NULL for deletion
- EXPECT_EQ(-1, hdfsDeleteSnapshot(fs, "/dir/", nullptr));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- //Path not found
- std::string path = "/wrong/dir/";
- EXPECT_EQ(-1, hdfsAllowSnapshot(fs, path.c_str()));
- EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
- EXPECT_EQ(-1, hdfsCreateSnapshot(fs, path.c_str(), "Bad"));
- EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
- EXPECT_EQ(-1, hdfsDeleteSnapshot(fs, path.c_str(), "Bad"));
- EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
- EXPECT_EQ(-1, hdfsRenameSnapshot(fs, path.c_str(), "Bad", "Bad"));
- EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
- EXPECT_EQ(-1, hdfsDisallowSnapshot(fs, path.c_str()));
- EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
- //Not a directory
- path = connection.newFile(1024); //1024 byte file
- EXPECT_EQ(-1, hdfsAllowSnapshot(fs, path.c_str()));
- EXPECT_EQ((int) std::errc::not_a_directory, errno);
- EXPECT_EQ(-1, hdfsCreateSnapshot(fs, path.c_str(), "Bad"));
- EXPECT_EQ((int) std::errc::not_a_directory, errno);
- EXPECT_EQ(-1, hdfsDeleteSnapshot(fs, path.c_str(), "Bad"));
- EXPECT_EQ((int) std::errc::not_a_directory, errno);
- EXPECT_EQ(-1, hdfsRenameSnapshot(fs, path.c_str(), "Bad", "Bad"));
- EXPECT_EQ((int) std::errc::not_a_directory, errno);
- EXPECT_EQ(-1, hdfsDisallowSnapshot(fs, path.c_str()));
- EXPECT_EQ((int) std::errc::not_a_directory, errno);
- //Not snapshottable directory
- std::string dirName = connection.newDir();
- EXPECT_EQ(0, hdfsDisallowSnapshot(fs, dirName.c_str()));
- EXPECT_EQ(-1, hdfsCreateSnapshot(fs, dirName.c_str(), "Bad"));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- //Verify snapshot created
- EXPECT_EQ(0, hdfsAllowSnapshot(fs, dirName.c_str()));
- EXPECT_EQ(0, hdfsCreateSnapshot(fs, dirName.c_str(), "Good"));
- std::string snapDir = dirName + ".snapshot/";
- int size;
- hdfsFileInfo *file_infos;
- EXPECT_NE(nullptr, file_infos = hdfsListDirectory(fs, snapDir.c_str(), &size));
- EXPECT_EQ(1, size);
- EXPECT_STREQ("Good", file_infos[0].mName);
- hdfsFreeFileInfo(file_infos, 1);
- //Verify snapshot renamed
- EXPECT_EQ(0, hdfsRenameSnapshot(fs, dirName.c_str(), "Good", "Best"));
- //Verify snapshot deleted
- EXPECT_EQ(0, hdfsDeleteSnapshot(fs, dirName.c_str(), "Best"));
- EXPECT_EQ(nullptr, file_infos = hdfsListDirectory(fs, snapDir.c_str(), &size));
- EXPECT_EQ(0, size);
- hdfsFreeFileInfo(file_infos, 0);
- }
- //Testing creating directories
- TEST_F(HdfsExtTest, TestMkdirs) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Correct operation
- EXPECT_EQ(0, hdfsCreateDirectory(fs, "/myDir123"));
- //TODO Should return error if directory already exists?
- //EXPECT_EQ(-1, hdfsCreateDirectory(fs, "/myDir123"));
- //EXPECT_EQ((int) std::errc::file_exists, errno);
- //Creating directory on a path of the existing file
- std::string path = connection.newFile(1024); //1024 byte file
- EXPECT_EQ(-1, hdfsCreateDirectory(fs, path.c_str()));
- EXPECT_EQ((int) std::errc::file_exists, errno);
- }
- //Testing deleting files and directories
- TEST_F(HdfsExtTest, TestDelete) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Path not found
- EXPECT_EQ(-1, hdfsDelete(fs, "/wrong_path", 1));
- EXPECT_EQ((int) std::errc::no_such_file_or_directory, errno);
- EXPECT_EQ(0, hdfsCreateDirectory(fs, "/myDir"));
- std::string path = connection.newFile("/myDir", 1024); //1024 byte file
- //Non-recursive delete should fail on a non-empty directory
- //error ENOTEMPTY(39) for libhdfspp or 255 for libhdfs
- EXPECT_EQ(-1, hdfsDelete(fs, "/myDir", 0));
- EXPECT_EQ((int) std::errc::directory_not_empty, errno);
- //Correct operation
- EXPECT_EQ(0, hdfsDelete(fs, "/myDir", 1));
- }
- //Testing renaming files and directories
- TEST_F(HdfsExtTest, TestRename) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Creating directory with two files
- EXPECT_EQ(0, hdfsCreateDirectory(fs, "/myDir"));
- std::string file1 = connection.newFile("/myDir", 1024); //1024 byte file
- std::string file2 = connection.newFile("/myDir", 1024); //1024 byte file
- std::string file3 = connection.newFile(1024); //1024 byte file
- //Path not found
- EXPECT_EQ(-1, hdfsRename(fs, "/wrong_path", "/new_name"));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- //No parent directory in new path
- EXPECT_EQ(-1, hdfsRename(fs, file1.c_str(), "/wrong_parent/new_name"));
- EXPECT_EQ((int ) std::errc::invalid_argument, errno);
- //New name already exists in the folder
- EXPECT_EQ(-1, hdfsRename(fs, file1.c_str(), file2.c_str()));
- EXPECT_EQ((int ) std::errc::invalid_argument, errno);
- //Correct operation
- EXPECT_EQ(0, hdfsRename(fs, file1.c_str(), "/myDir/new_awesome_name"));
- EXPECT_EQ(0, hdfsRename(fs, file3.c_str(), "/myDir/another_file"));
- EXPECT_EQ(0, hdfsRename(fs, "/myDir", "/new_awesome_dir"));
- //Verification
- int numEntries;
- hdfsFileInfo * dirList = hdfsListDirectory(fs, "/new_awesome_dir", &numEntries);
- EXPECT_NE(nullptr, dirList);
- EXPECT_EQ(3, numEntries);
- hdfsFreeFileInfo(dirList, 3);
- }
- //Testing Chmod and Chown
- TEST_F(HdfsExtTest, TestChmodChown) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Path not found
- std::string path = "/wrong/dir/";
- EXPECT_EQ(-1, hdfsChmod(fs, path.c_str(), 0777));
- EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
- EXPECT_EQ(-1, hdfsChown(fs, path.c_str(), "foo", "bar"));
- EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
- //Wrong arguments
- path = connection.newFile(1024); //1024 byte file
- EXPECT_EQ(-1, hdfsChmod(fs, nullptr, 0777));
- EXPECT_EQ((int ) std::errc::invalid_argument, errno);
- EXPECT_EQ(-1, hdfsChmod(fs, path.c_str(), 07777));
- EXPECT_EQ((int ) std::errc::invalid_argument, errno);
- EXPECT_EQ(-1, hdfsChmod(fs, path.c_str(), -1));
- EXPECT_EQ((int ) std::errc::invalid_argument, errno);
- EXPECT_EQ(-1, hdfsChown(fs, nullptr, "foo", "bar"));
- EXPECT_EQ((int ) std::errc::invalid_argument, errno);
- //Permission denied
- HdfsHandle connection2 = cluster.connect_c("OtherGuy");
- hdfsFS fs2 = connection2.handle();
- EXPECT_EQ(-1, hdfsChmod(fs2, path.c_str(), 0123));
- EXPECT_EQ((int ) std::errc::permission_denied, errno);
- EXPECT_EQ(-1, hdfsChown(fs2, path.c_str(), "cool", "nice"));
- EXPECT_EQ((int ) std::errc::permission_denied, errno);
- //Verify Chmod and Chown worked
- EXPECT_EQ(0, hdfsChmod(fs, path.c_str(), 0123));
- EXPECT_EQ(0, hdfsChown(fs, path.c_str(), "cool", "nice"));
- hdfsFileInfo *file_info;
- EXPECT_NE(nullptr, file_info = hdfsGetPathInfo(fs, path.c_str()));
- EXPECT_EQ(0123, file_info->mPermissions);
- EXPECT_STREQ("cool", file_info->mOwner);
- EXPECT_STREQ("nice", file_info->mGroup);
- hdfsFreeFileInfo(file_info, 1);
- }
- //Testing EOF
- TEST_F(HdfsExtTest, TestEOF) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Write to a file
- errno = 0;
- int size = 256;
- std::string path = "/eofTest";
- hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
- EXPECT_NE(nullptr, file);
- void * buf = malloc(size);
- memset(buf, ' ', size);
- EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
- free(buf);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- //libhdfs file operations work, but sometimes sets errno ENOENT : 2
- //Test normal reading (no EOF)
- char buffer[300];
- file = hdfsOpenFile(fs, path.c_str(), O_RDONLY, 0, 0, 0);
- EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
- //Read executes correctly, but causes a warning (captured in HDFS-10595)
- //and sets errno to EINPROGRESS 115 : Operation now in progress
- //Test reading at offset past the EOF
- EXPECT_EQ(-1, hdfsPread(fs, file, sizeof(buffer), buffer, sizeof(buffer)));
- EXPECT_EQ(Status::kInvalidOffset, errno);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- }
- //Testing hdfsExists
- TEST_F(HdfsExtTest, TestExists) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Path not found
- EXPECT_EQ(-1, hdfsExists(fs, "/wrong/dir/"));
- EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
- //Correct operation
- std::string pathDir = "/testExistsDir";
- EXPECT_EQ(0, hdfsCreateDirectory(fs, pathDir.c_str()));
- EXPECT_EQ(0, hdfsExists(fs, pathDir.c_str()));
- std::string pathFile = connection.newFile(pathDir.c_str(), 1024);
- EXPECT_EQ(0, hdfsExists(fs, pathFile.c_str()));
- //Permission denied
- EXPECT_EQ(0, hdfsChmod(fs, pathDir.c_str(), 0700));
- HdfsHandle connection2 = cluster.connect_c("OtherGuy");
- hdfsFS fs2 = connection2.handle();
- EXPECT_EQ(-1, hdfsExists(fs2, pathFile.c_str()));
- EXPECT_EQ((int ) std::errc::permission_denied, errno);
- }
- //Testing Replication and Time modifications
- TEST_F(HdfsExtTest, TestReplAndTime) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- std::string path = "/wrong/dir/";
- //Path not found
- EXPECT_EQ(-1, hdfsSetReplication(fs, path.c_str(), 3));
- EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
- EXPECT_EQ(-1, hdfsUtime(fs, path.c_str(), 1000000, 1000000));
- EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
- //Correct operation
- path = connection.newFile(1024);
- EXPECT_EQ(0, hdfsSetReplication(fs, path.c_str(), 7));
- EXPECT_EQ(0, hdfsUtime(fs, path.c_str(), 123456789, 987654321));
- hdfsFileInfo *file_info;
- EXPECT_NE(nullptr, file_info = hdfsGetPathInfo(fs, path.c_str()));
- EXPECT_EQ(7, file_info->mReplication);
- EXPECT_EQ(123456789, file_info->mLastMod);
- EXPECT_EQ(987654321, file_info->mLastAccess);
- hdfsFreeFileInfo(file_info, 1);
- //Wrong arguments
- EXPECT_EQ(-1, hdfsSetReplication(fs, path.c_str(), 0));
- EXPECT_EQ((int ) std::errc::invalid_argument, errno);
- EXPECT_EQ(-1, hdfsSetReplication(fs, path.c_str(), 513));
- EXPECT_EQ((int ) std::errc::invalid_argument, errno);
- //Permission denied
- EXPECT_EQ(0, hdfsChmod(fs, path.c_str(), 0700));
- HdfsHandle connection2 = cluster.connect_c("OtherGuy");
- hdfsFS fs2 = connection2.handle();
- EXPECT_EQ(-1, hdfsSetReplication(fs2, path.c_str(), 3));
- EXPECT_EQ((int ) std::errc::permission_denied, errno);
- EXPECT_EQ(-1, hdfsUtime(fs2, path.c_str(), 111111111, 222222222));
- EXPECT_EQ((int ) std::errc::permission_denied, errno);
- }
- //Testing getting default block size at path
- TEST_F(HdfsExtTest, TestDefaultBlockSize) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Correct operation (existing path)
- std::string path = connection.newFile(1024);
- long block_size = hdfsGetDefaultBlockSizeAtPath(fs, path.c_str());
- EXPECT_GT(block_size, 0);
- hdfsFileInfo *file_info;
- EXPECT_NE(nullptr, file_info = hdfsGetPathInfo(fs, path.c_str()));
- EXPECT_EQ(block_size, file_info->mBlockSize);
- hdfsFreeFileInfo(file_info, 1);
- //Non-existing path
- path = "/wrong/dir/";
- EXPECT_GT(hdfsGetDefaultBlockSizeAtPath(fs, path.c_str()), 0);
- //No path specified
- EXPECT_GT(hdfsGetDefaultBlockSize(fs), 0);
- }
- //Testing getting hosts
- TEST_F(HdfsExtTest, TestHosts) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- char *** hosts = nullptr;
- // Free a null pointer
- hdfsFreeHosts(hosts);
- EXPECT_EQ(0, errno);
- // Test non-existent files
- EXPECT_EQ(nullptr, hdfsGetHosts(fs, "/wrong/file/", 0, std::numeric_limits<int64_t>::max()));
- EXPECT_EQ((int ) std::errc::no_such_file_or_directory, errno);
- // Test an existent file
- std::string filename = connection.newFile(1024);
- EXPECT_NE(nullptr, hosts = hdfsGetHosts(fs, filename.c_str(), 0, std::numeric_limits<int64_t>::max()));
- //Make sure there is at least one host
- EXPECT_NE(nullptr, *hosts);
- EXPECT_NE(nullptr, **hosts);
- hdfsFreeHosts(hosts);
- EXPECT_EQ(0, errno);
- //Test invalid arguments
- EXPECT_EQ(nullptr, hdfsGetHosts(fs, filename.c_str(), 0, std::numeric_limits<int64_t>::max()+1));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- //Test invalid arguments
- EXPECT_EQ(nullptr, hdfsGetHosts(fs, filename.c_str(), std::numeric_limits<int64_t>::max()+1, std::numeric_limits<int64_t>::max()));
- EXPECT_EQ((int) std::errc::invalid_argument, errno);
- }
- //Testing read statistics
- TEST_F(HdfsExtTest, TestReadStats) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- struct hdfsReadStatistics *stats;
- //Write to a file
- int size = 256;
- std::string path = "/readStatTest";
- hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
- EXPECT_NE(nullptr, file);
- void * buf = malloc(size);
- bzero(buf, size);
- EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
- free(buf);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- //test before reading
- file = hdfsOpenFile(fs, path.c_str(), O_RDONLY, 0, 0, 0);
- EXPECT_EQ(0, hdfsFileGetReadStatistics(file, &stats));
- EXPECT_EQ(0, stats->totalBytesRead);
- hdfsFileFreeReadStatistics(stats);
- //test after reading
- char buffer[123];
- //Read executes correctly, but causes a warning (captured in HDFS-10595)
- EXPECT_EQ(sizeof(buffer), hdfsRead(fs, file, buffer, sizeof(buffer)));
- EXPECT_EQ(0, hdfsFileGetReadStatistics(file, &stats));
- EXPECT_EQ(sizeof(buffer), stats->totalBytesRead);
- EXPECT_EQ(sizeof(buffer), stats->totalLocalBytesRead);
- EXPECT_EQ(0, hdfsReadStatisticsGetRemoteBytesRead(stats));
- hdfsFileFreeReadStatistics(stats);
- //test after clearing
- EXPECT_EQ(0, hdfsFileClearReadStatistics(file));
- EXPECT_EQ(0, hdfsFileGetReadStatistics(file, &stats));
- EXPECT_EQ(0, stats->totalBytesRead);
- hdfsFileFreeReadStatistics(stats);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- EXPECT_EQ(0, errno);
- }
- //Testing working directory
- TEST_F(HdfsExtTest, TestWorkingDirectory) {
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Correct operation of setter and getter
- std::string pathDir = "/testWorkDir/";
- EXPECT_EQ(0, hdfsCreateDirectory(fs, pathDir.c_str()));
- std::string pathFile = connection.newFile(pathDir.c_str(), 1024);
- EXPECT_EQ(0, hdfsSetWorkingDirectory(fs, pathDir.c_str()));
- char array[100];
- EXPECT_STREQ(pathDir.c_str(), hdfsGetWorkingDirectory(fs, array, 100));
- //Get relative path
- std::size_t slashPos = pathFile.find_last_of("/");
- std::string fileName = pathFile.substr(slashPos + 1);
- //Testing various functions with relative path:
- //hdfsGetDefaultBlockSizeAtPath
- EXPECT_GT(hdfsGetDefaultBlockSizeAtPath(fs, fileName.c_str()), 0);
- //hdfsSetReplication
- EXPECT_EQ(0, hdfsSetReplication(fs, fileName.c_str(), 7));
- //hdfsUtime
- EXPECT_EQ(0, hdfsUtime(fs, fileName.c_str(), 123456789, 987654321));
- //hdfsExists
- EXPECT_EQ(0, hdfsExists(fs, fileName.c_str()));
- //hdfsGetPathInfo
- hdfsFileInfo *file_info;
- EXPECT_NE(nullptr, file_info = hdfsGetPathInfo(fs, fileName.c_str()));
- hdfsFreeFileInfo(file_info, 1);
- //hdfsOpenFile
- hdfsFile file;
- file = hdfsOpenFile(fs, fileName.c_str(), O_RDONLY, 0, 0, 0);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- //hdfsCreateDirectory
- EXPECT_EQ(0, hdfsCreateDirectory(fs, "newDir"));
- //add another file
- std::string fileName2 = connection.newFile(pathDir + "/newDir", 1024);
- //hdfsListDirectory
- int numEntries;
- hdfsFileInfo * dirList;
- EXPECT_NE(nullptr, dirList = hdfsListDirectory(fs, "newDir", &numEntries));
- EXPECT_EQ(1, numEntries);
- hdfsFreeFileInfo(dirList, 1);
- //hdfsChmod
- EXPECT_EQ(0, hdfsChmod(fs, fileName.c_str(), 0777));
- //hdfsChown
- EXPECT_EQ(0, hdfsChown(fs, fileName.c_str(), "cool", "nice"));
- //hdfsDisallowSnapshot
- EXPECT_EQ(0, hdfsDisallowSnapshot(fs, "newDir"));
- //hdfsAllowSnapshot
- EXPECT_EQ(0, hdfsAllowSnapshot(fs, "newDir"));
- //hdfsCreateSnapshot
- EXPECT_EQ(0, hdfsCreateSnapshot(fs, "newDir", "Some"));
- //hdfsDeleteSnapshot
- EXPECT_EQ(0, hdfsDeleteSnapshot(fs, "newDir", "Some"));
- //hdfsGetBlockLocations
- hdfsBlockLocations * blocks = nullptr;
- EXPECT_EQ(0, hdfsGetBlockLocations(connection, fileName.c_str(), &blocks));
- hdfsFreeBlockLocations(blocks);
- //hdfsGetHosts
- char *** hosts;
- EXPECT_NE(nullptr, hosts = hdfsGetHosts(fs, fileName.c_str(), 0, std::numeric_limits<int64_t>::max()));
- hdfsFreeHosts(hosts);
- //hdfsRename
- EXPECT_EQ(0, hdfsRename(fs, fileName.c_str(), "new_file_name"));
- //hdfsDelete
- EXPECT_EQ(0, hdfsDelete(fs, "new_file_name", 0));
- }
- // Flags used to test event handlers
- static int connect_callback_invoked = 0;
- int basic_fs_callback(const char *event, const char *cluster, int64_t value, int64_t cookie) {
- (void)cluster;
- (void)value;
- if(::strstr(FS_NN_CONNECT_EVENT, event) && cookie == 0xFFF0) {
- connect_callback_invoked = 1;
- }
- return LIBHDFSPP_EVENT_OK;
- }
- // Make sure event handler gets called during connect
- TEST_F(HdfsExtTest, TestConnectEvent) {
- connect_callback_invoked = 0;
- hdfsPreAttachFSMonitor(basic_fs_callback, 0xFFF0);
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- EXPECT_EQ(connect_callback_invoked, 1);
- }
- int throwing_fs_callback(const char *event, const char *cluster, int64_t value, int64_t cookie) {
- (void)cluster;
- (void)value;
- if(::strstr(FS_NN_CONNECT_EVENT, event) && cookie == 0xFFF1) {
- connect_callback_invoked = 1;
- throw std::runtime_error("Throwing in callbacks is a bad thing.");
- }
- return LIBHDFSPP_EVENT_OK;
- }
- // Make sure throwing in the connect event handler doesn't prevent connection
- TEST_F(HdfsExtTest, TestConnectEventThrow) {
- connect_callback_invoked = 0;
- hdfsPreAttachFSMonitor(throwing_fs_callback, 0xFFF1);
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- EXPECT_EQ(connect_callback_invoked, 1);
- }
- int char_throwing_fs_callback(const char *event, const char *cluster, int64_t value, int64_t cookie) {
- (void)cluster;
- (void)value;
- if(::strstr(FS_NN_CONNECT_EVENT, event) && cookie == 0xFFF2) {
- connect_callback_invoked = 1;
- throw "Throwing non std::exceptions in callbacks is even worse.";
- }
- return LIBHDFSPP_EVENT_OK;
- }
- TEST_F(HdfsExtTest, TestConnectEventThrowChar) {
- connect_callback_invoked = 0;
- hdfsPreAttachFSMonitor(char_throwing_fs_callback, 0xFFF2);
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- EXPECT_EQ(connect_callback_invoked, 1);
- }
- // Make sure throwing in the read event handler doesn't prevent reads
- int read_handler_invokation_count = 0;
- int basic_read_event_handler(const char *event, const char *cluster, const char *file,
- int64_t value, int64_t cookie)
- {
- (void)cluster;
- (void)file;
- (void)value;
- if(::strstr(FILE_DN_READ_EVENT, event) && cookie == 0xFFF3) {
- read_handler_invokation_count += 1;
- }
- return LIBHDFSPP_EVENT_OK;
- }
- // Testing that read handler is called.
- // Note: This is counting calls to async_read rather than hdfsPread.
- // Typically a call to hdfs(P)Read that doesn't span blocks/packets
- // invokes async_read 6 times; 4 more than required (improving that
- // in HDFS-11266).
- TEST_F(HdfsExtTest, TestReadEvent) {
- read_handler_invokation_count = 0;
- hdfsPreAttachFileMonitor(basic_read_event_handler, 0xFFF3);
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Write to a file
- errno = 0;
- int size = 256;
- std::string path = "/readEventTest";
- hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
- EXPECT_NE(nullptr, file);
- void * buf = malloc(size);
- memset(buf, ' ', size);
- EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
- free(buf);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- //Test that read counters are getting incremented
- char buffer[300];
- file = hdfsOpenFile(fs, path.c_str(), O_RDONLY, 0, 0, 0);
- EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
- EXPECT_EQ(read_handler_invokation_count, 6);
- EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
- EXPECT_EQ(read_handler_invokation_count, 12);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- }
- int throwing_read_event_handler(const char *event, const char *cluster, const char *file,
- int64_t value, int64_t cookie)
- {
- (void)cluster;
- (void)file;
- (void)value;
- if(::strstr(FILE_DN_READ_EVENT, event) && cookie == 0xFFF4) {
- read_handler_invokation_count += 1;
- throw std::runtime_error("Throwing here is a bad idea, but shouldn't break reads");
- }
- return LIBHDFSPP_EVENT_OK;
- }
- // Testing that reads can be done when event handler throws.
- TEST_F(HdfsExtTest, TestReadEventThrow) {
- read_handler_invokation_count = 0;
- hdfsPreAttachFileMonitor(throwing_read_event_handler, 0xFFF4);
- HdfsHandle connection = cluster.connect_c();
- hdfsFS fs = connection.handle();
- EXPECT_NE(nullptr, fs);
- //Write to a file
- errno = 0;
- int size = 256;
- std::string path = "/readEventTest";
- hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
- EXPECT_NE(nullptr, file);
- void * buf = malloc(size);
- memset(buf, ' ', size);
- EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
- free(buf);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- //Test that read counters are getting incremented
- char buffer[300];
- file = hdfsOpenFile(fs, path.c_str(), O_RDONLY, 0, 0, 0);
- EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
- EXPECT_EQ(read_handler_invokation_count, 6);
- EXPECT_EQ(size, hdfsPread(fs, file, 0, buffer, sizeof(buffer)));
- EXPECT_EQ(read_handler_invokation_count, 12);
- EXPECT_EQ(0, hdfsCloseFile(fs, file));
- }
- } // end namespace hdfs
- int main(int argc, char *argv[]) {
- // The following line must be executed to initialize Google Mock
- // (and Google Test) before running the tests.
- ::testing::InitGoogleMock(&argc, argv);
- int exit_code = RUN_ALL_TESTS();
- google::protobuf::ShutdownProtobufLibrary();
- return exit_code;
- }
|