* add openbsd support Renames fileno() so it doesn't clash with OpenBSD's macro expansion. Makes minor changes to build steps so the test suite compiles and runs on OpenBSD. See https://github.com/skypjack/uvw/issues/201 for full context * drop no-error override * disable sendfile tests on openbsd * forgot to commit the new file
524 lines
16 KiB
C++
524 lines
16 KiB
C++
#include <gtest/gtest.h>
|
|
#include <uvw.hpp>
|
|
#include <chrono>
|
|
|
|
#ifdef _WIN32
|
|
#define _CRT_DECLARE_NONSTDC_NAMES 1
|
|
#include <fcntl.h>
|
|
#endif
|
|
|
|
|
|
TEST(FileReq, OpenAndCloseErr) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/err.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto openReq = loop->resource<uvw::FileReq>();
|
|
auto closeReq = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileOpenErrorEvent = false;
|
|
bool checkFileCloseErrorEvent = false;
|
|
|
|
openReq->on<uvw::ErrorEvent>([&checkFileOpenErrorEvent](const auto &, auto &) {
|
|
ASSERT_FALSE(checkFileOpenErrorEvent);
|
|
checkFileOpenErrorEvent = true;
|
|
});
|
|
|
|
closeReq->on<uvw::ErrorEvent>([&checkFileCloseErrorEvent](const auto &, auto &) {
|
|
ASSERT_FALSE(checkFileCloseErrorEvent);
|
|
checkFileCloseErrorEvent = true;
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::RDONLY>();
|
|
openReq->open(filename, flags, 0644);
|
|
closeReq->close();
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileOpenErrorEvent);
|
|
ASSERT_TRUE(checkFileCloseErrorEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, OpenAndCloseErrSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/err.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_FALSE(request->openSync(filename, O_RDONLY, 0644));
|
|
ASSERT_FALSE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, OpenAndClose) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileOpenEvent = false;
|
|
bool checkFileCloseEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::CLOSE>>([&checkFileCloseEvent](const auto &, auto &) {
|
|
ASSERT_FALSE(checkFileCloseEvent);
|
|
checkFileCloseEvent = true;
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([&checkFileOpenEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileOpenEvent);
|
|
checkFileOpenEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::WRONLY>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileOpenEvent);
|
|
ASSERT_TRUE(checkFileCloseEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, OpenAndCloseSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_WRONLY, 0644));
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, RWChecked) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileWriteEvent = false;
|
|
bool checkFileReadEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::READ>>([&checkFileReadEvent](const auto &event, auto &req) {
|
|
ASSERT_FALSE(checkFileReadEvent);
|
|
ASSERT_EQ(event.data[0], 42);
|
|
checkFileReadEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::WRITE>>([&checkFileWriteEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileWriteEvent);
|
|
checkFileWriteEvent = true;
|
|
req.read(0, 1);
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([](const auto &, auto &req) {
|
|
req.write(std::unique_ptr<char[]>{new char[1]{ 42 }}, 1, 0);
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileWriteEvent);
|
|
ASSERT_TRUE(checkFileReadEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, RWUnchecked) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
std::unique_ptr<char[]> data{new char[1]{ 42 }};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileWriteEvent = false;
|
|
bool checkFileReadEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::READ>>([&checkFileReadEvent](const auto &event, auto &req) {
|
|
ASSERT_FALSE(checkFileReadEvent);
|
|
ASSERT_EQ(event.data[0], 42);
|
|
checkFileReadEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::WRITE>>([&checkFileWriteEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileWriteEvent);
|
|
checkFileWriteEvent = true;
|
|
req.read(0, 1);
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([&data](const auto &, auto &req) {
|
|
req.write(data.get(), 1, 0);
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileWriteEvent);
|
|
ASSERT_TRUE(checkFileReadEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, RWSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
|
|
auto writeR = request->writeSync(std::unique_ptr<char[]>{new char[1]{ 42 }}, 1, 0);
|
|
|
|
ASSERT_TRUE(writeR.first);
|
|
ASSERT_EQ(writeR.second, std::size_t{1});
|
|
|
|
auto readR = request->readSync(0, 1);
|
|
|
|
ASSERT_TRUE(readR.first);
|
|
ASSERT_EQ(readR.second.first[0], 42);
|
|
ASSERT_EQ(readR.second.second, std::size_t{1});
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, Stat) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileStatEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::FSTAT>>([&checkFileStatEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileStatEvent);
|
|
checkFileStatEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([](const auto &, auto &req) {
|
|
req.stat();
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileStatEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, StatSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
|
|
auto statR = request->statSync();
|
|
|
|
ASSERT_TRUE(statR.first);
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, Sync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileSyncEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::FSYNC>>([&checkFileSyncEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileSyncEvent);
|
|
checkFileSyncEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([](const auto &, auto &req) {
|
|
req.sync();
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileSyncEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, SyncSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
ASSERT_TRUE(request->syncSync());
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, Datasync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileDatasyncEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::FDATASYNC>>([&checkFileDatasyncEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileDatasyncEvent);
|
|
checkFileDatasyncEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([](const auto &, auto &req) {
|
|
req.datasync();
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileDatasyncEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, DatasyncSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
ASSERT_TRUE(request->datasyncSync());
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, Truncate) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileTruncateEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::FTRUNCATE>>([&checkFileTruncateEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileTruncateEvent);
|
|
checkFileTruncateEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([](const auto &, auto &req) {
|
|
req.truncate(0);
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileTruncateEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, TruncateSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
ASSERT_TRUE(request->truncateSync(0));
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, Chmod) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileChmodEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::FCHMOD>>([&checkFileChmodEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileChmodEvent);
|
|
checkFileChmodEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([](const auto &, auto &req) {
|
|
req.chmod(0644);
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileChmodEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, ChmodSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
ASSERT_TRUE(request->chmodSync(0644));
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, Futime) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileUtimeEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::FUTIME>>([&checkFileUtimeEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileUtimeEvent);
|
|
checkFileUtimeEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([](const auto &, auto &req) {
|
|
auto now = std::chrono::system_clock::now();
|
|
auto epoch = now.time_since_epoch();
|
|
auto value = std::chrono::duration_cast<std::chrono::seconds>(epoch);
|
|
req.futime(value, value);
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileUtimeEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, FutimeSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
|
|
auto now = std::chrono::system_clock::now();
|
|
auto epoch = now.time_since_epoch();
|
|
auto value = std::chrono::duration_cast<std::chrono::seconds>(epoch);
|
|
|
|
ASSERT_TRUE(request->futimeSync(value, value));
|
|
ASSERT_TRUE(request->truncateSync(0));
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|
|
|
|
|
|
TEST(FileReq, Chown) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
bool checkFileChownEvent = false;
|
|
|
|
request->on<uvw::ErrorEvent>([](const auto &, auto &) { FAIL(); });
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::FCHOWN>>([&checkFileChownEvent](const auto &, auto &req) {
|
|
ASSERT_FALSE(checkFileChownEvent);
|
|
checkFileChownEvent = true;
|
|
req.close();
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::FSTAT>>([](const auto &event, auto &req) {
|
|
auto uid = static_cast<uvw::Uid>(event.stat.st_uid);
|
|
auto gid = static_cast<uvw::Uid>(event.stat.st_gid);
|
|
req.chown(uid, gid);
|
|
});
|
|
|
|
request->on<uvw::FsEvent<uvw::FileReq::Type::OPEN>>([](const auto &, auto &req) {
|
|
req.stat();
|
|
});
|
|
|
|
auto flags = uvw::Flags<uvw::FileReq::FileOpen>::from<uvw::FileReq::FileOpen::CREAT, uvw::FileReq::FileOpen::RDWR, uvw::FileReq::FileOpen::TRUNC>();
|
|
request->open(filename, flags, 0644);
|
|
|
|
loop->run();
|
|
|
|
ASSERT_TRUE(checkFileChownEvent);
|
|
}
|
|
|
|
|
|
TEST(FileReq, ChownSync) {
|
|
const std::string filename = std::string{TARGET_FILE_REQ_DIR} + std::string{"/test.file"};
|
|
|
|
auto loop = uvw::Loop::getDefault();
|
|
auto request = loop->resource<uvw::FileReq>();
|
|
|
|
ASSERT_TRUE(request->openSync(filename, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
|
|
auto statR = request->statSync();
|
|
|
|
ASSERT_TRUE(statR.first);
|
|
auto uid = static_cast<uvw::Uid>(statR.second.st_uid);
|
|
auto gid = static_cast<uvw::Uid>(statR.second.st_gid);
|
|
ASSERT_TRUE(request->chownSync(uid, gid));
|
|
ASSERT_TRUE(request->closeSync());
|
|
|
|
loop->run();
|
|
}
|