[unit test] Complete FUSE unit tests #22
This commit is contained in:
@@ -5,6 +5,7 @@ _sh_denyrd
|
|||||||
_sh_denyrw
|
_sh_denyrw
|
||||||
_spawnv
|
_spawnv
|
||||||
aarch64
|
aarch64
|
||||||
|
abcdefgh
|
||||||
advapi32
|
advapi32
|
||||||
armv8
|
armv8
|
||||||
autogen
|
autogen
|
||||||
|
@@ -496,6 +496,56 @@ public:
|
|||||||
|
|
||||||
unlink_file_and_test(file_path);
|
unlink_file_and_test(file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void overwrite_text(const std::string &path, const std::string &data) {
|
||||||
|
int desc = ::open(path.c_str(), O_WRONLY | O_TRUNC);
|
||||||
|
ASSERT_NE(desc, -1);
|
||||||
|
write_all(desc, data);
|
||||||
|
::close(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_all(int desc, const std::string &data) {
|
||||||
|
std::size_t off{0U};
|
||||||
|
while (off < data.size()) {
|
||||||
|
auto written = ::write(desc, &data.at(off), data.length() - off);
|
||||||
|
ASSERT_NE(written, -1);
|
||||||
|
off += static_cast<size_t>(written);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto slurp(const std::string &path) -> std::string {
|
||||||
|
int desc = ::open(path.c_str(), O_RDONLY);
|
||||||
|
if (desc == -1) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::string out;
|
||||||
|
std::array<char, 4096U> buf{};
|
||||||
|
for (;;) {
|
||||||
|
auto bytes_read = ::read(desc, buf.data(), buf.size());
|
||||||
|
if (bytes_read == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (bytes_read == -1) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.append(buf.begin(), std::next(buf.begin(), bytes_read));
|
||||||
|
}
|
||||||
|
|
||||||
|
::close(desc);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static auto stat_size(const std::string &path) -> off_t {
|
||||||
|
struct stat st_unix{};
|
||||||
|
int res = ::stat(path.c_str(), &st_unix);
|
||||||
|
EXPECT_EQ(0, res) << "stat(" << path
|
||||||
|
<< ") failed: " << std::strerror(errno);
|
||||||
|
return st_unix.st_size;
|
||||||
|
}
|
||||||
#endif // !defined(_WIN32)
|
#endif // !defined(_WIN32)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -23,60 +23,13 @@
|
|||||||
|
|
||||||
#include "fixtures/drive_fixture.hpp"
|
#include "fixtures/drive_fixture.hpp"
|
||||||
|
|
||||||
namespace {
|
|
||||||
void overwrite_text(const std::string &path, const std::string &data);
|
|
||||||
void write_all(int desc, const std::string &data);
|
|
||||||
[[nodiscard]] auto slurp(const std::string &path) -> std::string;
|
|
||||||
|
|
||||||
void overwrite_text(const std::string &path, const std::string &data) {
|
|
||||||
int desc = ::open(path.c_str(), O_WRONLY | O_TRUNC);
|
|
||||||
ASSERT_NE(desc, -1);
|
|
||||||
write_all(desc, data);
|
|
||||||
::close(desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_all(int desc, const std::string &data) {
|
|
||||||
std::size_t off{0U};
|
|
||||||
while (off < data.size()) {
|
|
||||||
auto written = ::write(desc, &data.at(off), data.length() - off);
|
|
||||||
ASSERT_NE(written, -1);
|
|
||||||
off += static_cast<size_t>(written);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto slurp(const std::string &path) -> std::string {
|
|
||||||
int desc = ::open(path.c_str(), O_RDONLY);
|
|
||||||
if (desc == -1) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::string out;
|
|
||||||
std::array<char, 4096U> buf{};
|
|
||||||
for (;;) {
|
|
||||||
auto bytes_read = ::read(desc, buf.data(), buf.size());
|
|
||||||
if (bytes_read == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (bytes_read == -1) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out.append(buf.begin(), std::next(buf.begin(), bytes_read));
|
|
||||||
}
|
|
||||||
|
|
||||||
::close(desc);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
TYPED_TEST_SUITE(fuse_test, platform_provider_types);
|
TYPED_TEST_SUITE(fuse_test, platform_provider_types);
|
||||||
|
|
||||||
TYPED_TEST(fuse_test, rename_can_rename_a_file) {
|
TYPED_TEST(fuse_test, rename_can_rename_a_file) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +56,7 @@ TYPED_TEST(fuse_test, rename_can_rename_a_file) {
|
|||||||
TYPED_TEST(fuse_test, rename_can_rename_a_directory) {
|
TYPED_TEST(fuse_test, rename_can_rename_a_directory) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +83,7 @@ TYPED_TEST(fuse_test, rename_can_rename_a_directory) {
|
|||||||
TYPED_TEST(fuse_test, rename_can_overwrite_existing_file) {
|
TYPED_TEST(fuse_test, rename_can_overwrite_existing_file) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +93,8 @@ TYPED_TEST(fuse_test, rename_can_overwrite_existing_file) {
|
|||||||
std::string dst_name{"rename2.txt"};
|
std::string dst_name{"rename2.txt"};
|
||||||
auto dst = this->create_file_and_test(dst_name);
|
auto dst = this->create_file_and_test(dst_name);
|
||||||
|
|
||||||
overwrite_text(src, "SRC");
|
this->overwrite_text(src, "SRC");
|
||||||
overwrite_text(dst, "DST");
|
this->overwrite_text(dst, "DST");
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
ASSERT_EQ(0, ::rename(src.c_str(), dst.c_str()));
|
ASSERT_EQ(0, ::rename(src.c_str(), dst.c_str()));
|
||||||
@@ -148,7 +103,7 @@ TYPED_TEST(fuse_test, rename_can_overwrite_existing_file) {
|
|||||||
EXPECT_EQ(-1, ::access(src.c_str(), F_OK));
|
EXPECT_EQ(-1, ::access(src.c_str(), F_OK));
|
||||||
EXPECT_EQ(ENOENT, errno);
|
EXPECT_EQ(ENOENT, errno);
|
||||||
|
|
||||||
EXPECT_EQ("SRC", slurp(dst));
|
EXPECT_EQ("SRC", this->slurp(dst));
|
||||||
|
|
||||||
this->unlink_file_and_test(dst);
|
this->unlink_file_and_test(dst);
|
||||||
}
|
}
|
||||||
@@ -156,6 +111,7 @@ TYPED_TEST(fuse_test, rename_can_overwrite_existing_file) {
|
|||||||
TYPED_TEST(fuse_test, rename_can_rename_file_into_different_directory) {
|
TYPED_TEST(fuse_test, rename_can_rename_file_into_different_directory) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +125,7 @@ TYPED_TEST(fuse_test, rename_can_rename_file_into_different_directory) {
|
|||||||
auto src = this->create_file_and_test(file_name);
|
auto src = this->create_file_and_test(file_name);
|
||||||
std::string dst = utils::path::combine(dir2, {"moved.txt"});
|
std::string dst = utils::path::combine(dir2, {"moved.txt"});
|
||||||
|
|
||||||
overwrite_text(src, "CMDC");
|
this->overwrite_text(src, "CMDC");
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
ASSERT_EQ(0, ::rename(src.c_str(), dst.c_str()));
|
ASSERT_EQ(0, ::rename(src.c_str(), dst.c_str()));
|
||||||
@@ -177,7 +133,7 @@ TYPED_TEST(fuse_test, rename_can_rename_file_into_different_directory) {
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
EXPECT_EQ(-1, ::access(src.c_str(), F_OK));
|
EXPECT_EQ(-1, ::access(src.c_str(), F_OK));
|
||||||
EXPECT_EQ(ENOENT, errno);
|
EXPECT_EQ(ENOENT, errno);
|
||||||
EXPECT_EQ("CMDC", slurp(dst));
|
EXPECT_EQ("CMDC", this->slurp(dst));
|
||||||
|
|
||||||
this->unlink_file_and_test(dst);
|
this->unlink_file_and_test(dst);
|
||||||
this->rmdir_and_test(dir1);
|
this->rmdir_and_test(dir1);
|
||||||
@@ -187,16 +143,17 @@ TYPED_TEST(fuse_test, rename_can_rename_file_into_different_directory) {
|
|||||||
TYPED_TEST(fuse_test, rename_can_rename_file_to_same_path) {
|
TYPED_TEST(fuse_test, rename_can_rename_file_to_same_path) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string file_name{"rename"};
|
std::string file_name{"rename"};
|
||||||
auto src = this->create_file_and_test(file_name);
|
auto src = this->create_file_and_test(file_name);
|
||||||
overwrite_text(src, "CMDC");
|
this->overwrite_text(src, "CMDC");
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
EXPECT_EQ(0, ::rename(src.c_str(), src.c_str()));
|
EXPECT_EQ(0, ::rename(src.c_str(), src.c_str()));
|
||||||
EXPECT_EQ("CMDC", slurp(src));
|
EXPECT_EQ("CMDC", this->slurp(src));
|
||||||
|
|
||||||
this->unlink_file_and_test(src);
|
this->unlink_file_and_test(src);
|
||||||
}
|
}
|
||||||
@@ -204,6 +161,7 @@ TYPED_TEST(fuse_test, rename_can_rename_file_to_same_path) {
|
|||||||
TYPED_TEST(fuse_test, rename_file_fails_if_source_file_does_not_exist) {
|
TYPED_TEST(fuse_test, rename_file_fails_if_source_file_does_not_exist) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +183,7 @@ TYPED_TEST(fuse_test,
|
|||||||
rename_file_fails_if_destination_directory_does_not_exist) {
|
rename_file_fails_if_destination_directory_does_not_exist) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,6 +205,7 @@ TYPED_TEST(fuse_test,
|
|||||||
TYPED_TEST(fuse_test, rename_file_fails_if_destination_is_directory) {
|
TYPED_TEST(fuse_test, rename_file_fails_if_destination_is_directory) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +228,7 @@ TYPED_TEST(fuse_test, rename_file_fails_if_destination_is_directory) {
|
|||||||
TYPED_TEST(fuse_test, rename_file_fails_if_source_directory_is_read_only) {
|
TYPED_TEST(fuse_test, rename_file_fails_if_source_directory_is_read_only) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,6 +260,7 @@ TYPED_TEST(fuse_test, rename_file_fails_if_source_directory_is_read_only) {
|
|||||||
TYPED_TEST(fuse_test, rename_file_fails_if_destination_directory_is_read_only) {
|
TYPED_TEST(fuse_test, rename_file_fails_if_destination_directory_is_read_only) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,6 +292,7 @@ TYPED_TEST(fuse_test, rename_file_fails_if_destination_directory_is_read_only) {
|
|||||||
TYPED_TEST(fuse_test, rename_file_succeeds_if_destination_file_is_read_only) {
|
TYPED_TEST(fuse_test, rename_file_succeeds_if_destination_file_is_read_only) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,8 +302,8 @@ TYPED_TEST(fuse_test, rename_file_succeeds_if_destination_file_is_read_only) {
|
|||||||
std::string dest_file_name{"rename_test_2"};
|
std::string dest_file_name{"rename_test_2"};
|
||||||
auto dst = this->create_file_and_test(dest_file_name);
|
auto dst = this->create_file_and_test(dest_file_name);
|
||||||
|
|
||||||
overwrite_text(src, "NEW");
|
this->overwrite_text(src, "NEW");
|
||||||
overwrite_text(dst, "OLD");
|
this->overwrite_text(dst, "OLD");
|
||||||
|
|
||||||
ASSERT_EQ(0, ::chmod(dst.c_str(), 0444));
|
ASSERT_EQ(0, ::chmod(dst.c_str(), 0444));
|
||||||
|
|
||||||
@@ -354,7 +317,7 @@ TYPED_TEST(fuse_test, rename_file_succeeds_if_destination_file_is_read_only) {
|
|||||||
}
|
}
|
||||||
ASSERT_EQ(0, res);
|
ASSERT_EQ(0, res);
|
||||||
|
|
||||||
EXPECT_EQ("NEW", slurp(dst));
|
EXPECT_EQ("NEW", this->slurp(dst));
|
||||||
|
|
||||||
ASSERT_EQ(0, ::chmod(dst.c_str(), 0644));
|
ASSERT_EQ(0, ::chmod(dst.c_str(), 0644));
|
||||||
this->unlink_file_and_test(dst);
|
this->unlink_file_and_test(dst);
|
||||||
@@ -363,6 +326,7 @@ TYPED_TEST(fuse_test, rename_file_succeeds_if_destination_file_is_read_only) {
|
|||||||
TYPED_TEST(fuse_test, rename_file_retains_open_file_descriptor) {
|
TYPED_TEST(fuse_test, rename_file_retains_open_file_descriptor) {
|
||||||
if (this->current_provider != provider_type::sia) {
|
if (this->current_provider != provider_type::sia) {
|
||||||
// TODO finish test
|
// TODO finish test
|
||||||
|
GTEST_SKIP();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +336,7 @@ TYPED_TEST(fuse_test, rename_file_retains_open_file_descriptor) {
|
|||||||
std::string dest_file_name{"rename_test_2"};
|
std::string dest_file_name{"rename_test_2"};
|
||||||
auto dst = this->create_file_and_test(dest_file_name);
|
auto dst = this->create_file_and_test(dest_file_name);
|
||||||
|
|
||||||
overwrite_text(src, "HELLO");
|
this->overwrite_text(src, "HELLO");
|
||||||
|
|
||||||
int desc = ::open(src.c_str(), O_RDWR);
|
int desc = ::open(src.c_str(), O_RDWR);
|
||||||
ASSERT_NE(desc, -1);
|
ASSERT_NE(desc, -1);
|
||||||
@@ -385,10 +349,10 @@ TYPED_TEST(fuse_test, rename_file_retains_open_file_descriptor) {
|
|||||||
EXPECT_EQ(ENOENT, errno);
|
EXPECT_EQ(ENOENT, errno);
|
||||||
|
|
||||||
ASSERT_NE(-1, ::lseek(desc, 0, SEEK_END));
|
ASSERT_NE(-1, ::lseek(desc, 0, SEEK_END));
|
||||||
write_all(desc, " WORLD");
|
this->write_all(desc, " WORLD");
|
||||||
::close(desc);
|
::close(desc);
|
||||||
|
|
||||||
EXPECT_EQ("HELLO WORLD", slurp(dst));
|
EXPECT_EQ("HELLO WORLD", this->slurp(dst));
|
||||||
this->unlink_file_and_test(dst);
|
this->unlink_file_and_test(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,28 +1,3 @@
|
|||||||
// static void test_truncate(const std::string &file_path) {
|
|
||||||
// std::cout << __FUNCTION__ << std::endl;
|
|
||||||
// EXPECT_EQ(0, truncate(file_path.c_str(), 10u));
|
|
||||||
//
|
|
||||||
// std::uint64_t file_size{};
|
|
||||||
// EXPECT_TRUE(utils::file::get_file_size(file_path, file_size));
|
|
||||||
//
|
|
||||||
// EXPECT_EQ(std::uint64_t(10u), file_size);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void test_ftruncate(const std::string &file_path) {
|
|
||||||
// std::cout << __FUNCTION__ << std::endl;
|
|
||||||
// auto fd = open(file_path.c_str(), O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP);
|
|
||||||
// EXPECT_LE(1, fd);
|
|
||||||
//
|
|
||||||
// EXPECT_EQ(0, ftruncate(fd, 10u));
|
|
||||||
//
|
|
||||||
// std::uint64_t file_size{};
|
|
||||||
// EXPECT_TRUE(utils::file::get_file_size(file_path, file_size));
|
|
||||||
//
|
|
||||||
// EXPECT_EQ(std::uint64_t(10u), file_size);
|
|
||||||
//
|
|
||||||
// close(fd);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// #if !defined(__APPLE__)
|
// #if !defined(__APPLE__)
|
||||||
// static void test_fallocate(const std::string & /* api_path */,
|
// static void test_fallocate(const std::string & /* api_path */,
|
||||||
// const std::string &file_path) {
|
// const std::string &file_path) {
|
||||||
|
214
repertory/repertory_test/src/fuse_drive_truncate_test.cpp
Normal file
214
repertory/repertory_test/src/fuse_drive_truncate_test.cpp
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
|
||||||
|
#include "fixtures/drive_fixture.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
TYPED_TEST_SUITE(fuse_test, platform_provider_types);
|
||||||
|
|
||||||
|
TYPED_TEST(fuse_test, truncate_can_shrink_file) {
|
||||||
|
std::string file_name{"truncate"};
|
||||||
|
auto src = this->create_file_and_test(file_name);
|
||||||
|
this->overwrite_text(src, "ABCDEFGH");
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
ASSERT_EQ(0, ::truncate(src.c_str(), 3));
|
||||||
|
EXPECT_EQ(3, this->stat_size(src));
|
||||||
|
EXPECT_EQ("ABC", this->slurp(src));
|
||||||
|
|
||||||
|
this->unlink_file_and_test(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(fuse_test, truncate_expand_file_is_zero_filled) {
|
||||||
|
std::string name{"truncate"};
|
||||||
|
auto src = this->create_file_and_test(name);
|
||||||
|
this->overwrite_text(src, "XYZ");
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
ASSERT_EQ(0, ::truncate(src.c_str(), 10));
|
||||||
|
EXPECT_EQ(10, this->stat_size(src));
|
||||||
|
|
||||||
|
auto data = this->slurp(src);
|
||||||
|
ASSERT_EQ(10U, data.size());
|
||||||
|
EXPECT_EQ('X', data.at(0U));
|
||||||
|
EXPECT_EQ('Y', data.at(1U));
|
||||||
|
EXPECT_EQ('Z', data.at(2U));
|
||||||
|
for (std::size_t idx = 3; idx < data.size(); ++idx) {
|
||||||
|
EXPECT_EQ('\0', data[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->unlink_file_and_test(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(fuse_test, truncate_fails_if_source_does_not_exist) {
|
||||||
|
std::string name{"truncate"};
|
||||||
|
auto src = this->create_file_path(name);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
EXPECT_EQ(-1, ::truncate(src.c_str(), 1));
|
||||||
|
EXPECT_EQ(ENOENT, errno);
|
||||||
|
|
||||||
|
EXPECT_FALSE(utils::file::file{src}.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(fuse_test, truncate_fails_if_path_is_directory) {
|
||||||
|
std::string name{"truncate"};
|
||||||
|
auto src = this->create_directory_and_test(name);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
auto res = ::truncate(src.c_str(), 0);
|
||||||
|
EXPECT_EQ(-1, res);
|
||||||
|
EXPECT_TRUE(errno == EISDIR || errno == EPERM || errno == EACCES ||
|
||||||
|
errno == EINVAL);
|
||||||
|
|
||||||
|
this->rmdir_and_test(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TYPED_TEST(fuse_test, truncate_readonly_file_eacces_or_eperm_or_erofs_skip) {
|
||||||
|
if (this->current_provider != provider_type::sia)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string name{"trunc_ro"};
|
||||||
|
std::string p = this->create_file_and_test(name);
|
||||||
|
this->overwrite_text(p, "DATA");
|
||||||
|
|
||||||
|
ASSERT_EQ(0, ::chmod(p.c_str(), 0444)) << std::strerror(errno);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
int res = ::truncate(p.c_str(), 2);
|
||||||
|
if (res == -1 && errno == EROFS) {
|
||||||
|
ASSERT_EQ(0, ::chmod(p.c_str(), 0644));
|
||||||
|
this->unlink_file_and_test(p);
|
||||||
|
GTEST_SKIP() << "read-only mount; truncate returns EROFS";
|
||||||
|
}
|
||||||
|
EXPECT_EQ(-1, res);
|
||||||
|
EXPECT_TRUE(errno == EACCES || errno == EPERM)
|
||||||
|
<< "errno=" << errno << " " << std::strerror(errno);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, ::chmod(p.c_str(), 0644));
|
||||||
|
this->unlink_file_and_test(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ftruncate(2) ==========
|
||||||
|
|
||||||
|
TYPED_TEST(fuse_test, ftruncate_shrink_open_fd) {
|
||||||
|
if (this->current_provider != provider_type::sia)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string name{"ftrunc_shrink"};
|
||||||
|
std::string p = this->create_file_and_test(name);
|
||||||
|
this->overwrite_text(p, "HELLOWORLD"); // 10 bytes
|
||||||
|
|
||||||
|
int fd = ::open(p.c_str(), O_RDWR);
|
||||||
|
ASSERT_NE(fd, -1) << "open failed: " << std::strerror(errno);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
ASSERT_EQ(0, ::ftruncate(fd, 4)) << std::strerror(errno);
|
||||||
|
::close(fd);
|
||||||
|
|
||||||
|
EXPECT_EQ(4, this->stat_size(p));
|
||||||
|
EXPECT_EQ("HELL", this->slurp(p));
|
||||||
|
|
||||||
|
this->unlink_file_and_test(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(fuse_test, ftruncate_expand_open_fd_zero_fills) {
|
||||||
|
if (this->current_provider != provider_type::sia)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string name{"ftrunc_expand"};
|
||||||
|
std::string p = this->create_file_and_test(name);
|
||||||
|
this->overwrite_text(p, "AA"); // 2 bytes
|
||||||
|
|
||||||
|
int fd = ::open(p.c_str(), O_RDWR);
|
||||||
|
ASSERT_NE(fd, -1);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
ASSERT_EQ(0, ::ftruncate(fd, 6)) << std::strerror(errno);
|
||||||
|
::close(fd);
|
||||||
|
|
||||||
|
EXPECT_EQ(6, this->stat_size(p));
|
||||||
|
|
||||||
|
auto s = this->slurp(p);
|
||||||
|
ASSERT_EQ(6u, s.size());
|
||||||
|
EXPECT_EQ('A', s[0]);
|
||||||
|
EXPECT_EQ('A', s[1]);
|
||||||
|
for (size_t i = 2; i < s.size(); ++i) {
|
||||||
|
EXPECT_EQ('\0', s[i]) << "byte " << i << " not zero";
|
||||||
|
}
|
||||||
|
|
||||||
|
this->unlink_file_and_test(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(fuse_test, ftruncate_readonly_fd_ebadf) {
|
||||||
|
if (this->current_provider != provider_type::sia)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string name{"ftrunc_rofd"};
|
||||||
|
std::string p = this->create_file_and_test(name);
|
||||||
|
this->overwrite_text(p, "RW");
|
||||||
|
|
||||||
|
int fd = ::open(p.c_str(), O_RDONLY);
|
||||||
|
ASSERT_NE(fd, -1);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
EXPECT_EQ(-1, ::ftruncate(fd, 1));
|
||||||
|
EXPECT_EQ(EBADF, errno);
|
||||||
|
|
||||||
|
::close(fd);
|
||||||
|
this->unlink_file_and_test(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(fuse_test, ftruncate_on_ro_mount_erofs_or_skip) {
|
||||||
|
if (this->current_provider != provider_type::sia)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string name{"ftrunc_ro_mount"};
|
||||||
|
std::string p = this->create_file_and_test(name);
|
||||||
|
this->overwrite_text(p, "X");
|
||||||
|
|
||||||
|
int fd = ::open(p.c_str(), O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
this->unlink_file_and_test(p);
|
||||||
|
GTEST_SKIP() << "cannot open O_RDWR; probable RO mount";
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
int res = ::ftruncate(fd, 0);
|
||||||
|
if (res == -1 && errno == EROFS) {
|
||||||
|
::close(fd);
|
||||||
|
this->unlink_file_and_test(p);
|
||||||
|
GTEST_SKIP() << "read-only mount; ftruncate returns EROFS";
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EQ(0, res) << std::strerror(errno);
|
||||||
|
::close(fd);
|
||||||
|
|
||||||
|
this->unlink_file_and_test(p);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // !defined(_WIN32)
|
Reference in New Issue
Block a user