summaryrefslogtreecommitdiff
path: root/test/test_file.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_file.cpp')
-rw-r--r--test/test_file.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/test/test_file.cpp b/test/test_file.cpp
new file mode 100644
index 0000000..06e6bcc
--- /dev/null
+++ b/test/test_file.cpp
@@ -0,0 +1,97 @@
+/*
+ * libfud
+ * Copyright 2024 Dominick Allen
+ *
+ * Licensed 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 "fud_file.hpp"
+#include "fud_string.hpp"
+#include "test_common.hpp"
+
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <cerrno>
+#include <fcntl.h>
+#include <ftw.h>
+#include <ranges>
+
+namespace fud {
+
+TEST(FudFile, Basic)
+{
+ constexpr const char* testDirCName = "/tmp/fud_directory_test";
+ const auto testDirName{String::makeFromCString(testDirCName).takeOkay()};
+ ASSERT_TRUE(testDirName.utf8Valid());
+ constexpr mode_t pathMode = 0777;
+
+ ASSERT_EQ(removeRecursive(testDirName), FudStatus::Success);
+
+ auto mkdirResult = mkdir(testDirName.c_str(), pathMode);
+ EXPECT_EQ(mkdirResult, 0);
+ if (mkdirResult != 0) {
+ ASSERT_EQ(removeRecursive(testDirName), FudStatus::Success);
+ return;
+ }
+
+ String testName1{String::makeFromCStrings(testDirCName, "/", "test1").takeOkay()};
+ String testName2{String::makeFromCStrings(testDirCName, "/", "test2").takeOkay()};
+
+ auto rmFile = [](const auto& filename) -> int {
+ auto result = unlink(filename.c_str());
+ if (result == -1) {
+ if (errno == ENOENT) {
+ return 0;
+ }
+ }
+ return result;
+ };
+ ASSERT_EQ(rmFile(testName1), 0);
+ ASSERT_EQ(rmFile(testName2), 0);
+
+ auto fileResult{RegularFile::open(testName1.asView(), FileAccessMode::Read, OpenFlags{}, NullOpt)};
+ EXPECT_EQ(fileResult.takeErrorOr(FudStatus::Success), FudStatus::NotFound);
+
+ /* The irony of the ability for TOCTOU bugs to be present in the test does
+ * not escape me. */
+
+ auto createFile = [](const auto& filename) -> int {
+ constexpr int allPerms = 0777;
+ auto handleResult = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, allPerms);
+ if (handleResult >= 0) {
+ close(handleResult);
+ }
+ return handleResult;
+ };
+ ASSERT_GE(createFile(testName1), 0);
+
+ fileResult = RegularFile::open(testName1.asView(), FileAccessMode::Read, OpenFlags{}, NullOpt);
+ ASSERT_TRUE(fileResult.isOkay());
+ auto file{fileResult.takeOkay()};
+ ASSERT_EQ(file.close(), FudStatus::Success);
+
+ ASSERT_EQ(rmFile(testName1), 0);
+ ASSERT_GE(createFile(testName2), 0);
+ ASSERT_EQ(symlink(testName2.c_str(), testName1.c_str()), 0);
+
+ fileResult = RegularFile::open(testName2.asView(), FileAccessMode::Read, OpenFlags{}, NullOpt);
+ ASSERT_TRUE(fileResult.isOkay());
+ file = fileResult.takeOkay();
+ ASSERT_EQ(file.close(), FudStatus::Success);
+
+ fileResult = RegularFile::open(testName1.asView(), FileAccessMode::Read, OpenFlags{}, NullOpt);
+ ASSERT_TRUE(fileResult.isError());
+ EXPECT_EQ(fileResult.getError(), FudStatus::Failure);
+}
+
+} // namespace fud