diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2024-09-28 00:23:22 -0500 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2024-09-28 00:23:22 -0500 |
commit | 07d30629d78474ed810cad73ead71db96079aff0 (patch) | |
tree | 5f43fd8f6a818a590818e0c474f03a1f05076dba /test/test_directory.cpp | |
parent | 63711877057f1f89b4d1774e24fe20907a3af656 (diff) |
Add directory interface.
Diffstat (limited to 'test/test_directory.cpp')
-rw-r--r-- | test/test_directory.cpp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/test/test_directory.cpp b/test/test_directory.cpp new file mode 100644 index 0000000..9cec80d --- /dev/null +++ b/test/test_directory.cpp @@ -0,0 +1,147 @@ +/* + * 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_array.hpp" +#include "fud_c_file.hpp" +#include "fud_directory.hpp" +#include "fud_memory.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 { + +int unlink_cb(const char* fpath, const struct stat* sb, int typeflag, struct FTW* ftwbuf) +{ + int retValue = remove(fpath); + + EXPECT_EQ(retValue, 0); + if (retValue) { + perror(fpath); + } + + return retValue; +} + +FudStatus removeRecursive(const String& path) +{ + if (!path.utf8Valid()) { + return FudStatus::Utf8Invalid; + } + if (path.length() < 5) { + return FudStatus::InvalidInput; + } + const String prefix{"/tmp/"}; + auto diffResult = compareMem(path.data(), path.length(), prefix.data(), prefix.length()); + if (diffResult.isError()) { + return FudStatus::InvalidInput; + } + auto diff = diffResult.getOkay(); + if (diff != 0) { + return FudStatus::InvalidInput; + } + constexpr int maxOpenFd = 64; + auto status = nftw(path.c_str(), unlink_cb, maxOpenFd, FTW_DEPTH | FTW_PHYS); + if (status == 0) { + return FudStatus::Success; + } + + if (errno == ENOENT) { + return FudStatus::Success; + } + + return FudStatus::Failure; +} + +TEST(FudDirectory, Basic) +{ + const String testDirName{"/tmp/fud_directory_test"}; + ASSERT_TRUE(testDirName.utf8Valid()); + constexpr mode_t pathMode = 0777; + const Array<String, 2> files{ + String{"file1"}, + String{"file2"}, + }; + ASSERT_TRUE(files[0].utf8Valid()); + ASSERT_TRUE(files[1].utf8Valid()); + + 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; + } + + const String testDirNamePrefix = testDirName.catenate("/"); + ASSERT_TRUE(testDirNamePrefix.utf8Valid()); + for (const auto& fnameBase : files) { + const auto fname = testDirNamePrefix.catenate(fnameBase); + ASSERT_TRUE(fname.utf8Valid()); + CBinaryFile file{fname, CFileMode::ReadWriteTruncate}; + ASSERT_EQ(file.open(), FileStatus::Success); + Array<utf8, 5> data{"test"}; + WriteResult expected{data.size(), FileStatus::Success}; + auto writeResult = file.write(data); + ASSERT_EQ(writeResult.bytesWritten, expected.bytesWritten); + ASSERT_EQ(writeResult.status, expected.status); + } + + Directory directory{testDirName}; + ASSERT_EQ(directory.status(), FudStatus::Success); + ASSERT_EQ(directory.errorCode(), 0); + + const Array<DirectoryEntry, 4> expectedFiles{ + DirectoryEntry{String{"."}, 0, 2, 0, DirectoryEntryType::Directory}, + DirectoryEntry{String{".."}, 0, 1, 0, DirectoryEntryType::Directory}, + DirectoryEntry{files[0], files[0].size(), 1, 0, DirectoryEntryType::RegularFile}, + DirectoryEntry{files[1], files[1].size(), 1, 0, DirectoryEntryType::RegularFile}, + }; + ASSERT_TRUE(expectedFiles[0].name.compare(expectedFiles[0].name)); + + for (auto idx = 0; idx < expectedFiles.size(); ++idx) { + auto dirEntryResult = directory.getNextEntry(); + EXPECT_TRUE(dirEntryResult.isOkay()); + const auto dirEntryOpt = dirEntryResult.getOkay(); + if (dirEntryOpt == std::nullopt) { + break; + } + const auto dirEntry = *dirEntryOpt; + const auto expected = std::find_if( + expectedFiles.begin(), + expectedFiles.end(), + [&dirEntry](const DirectoryEntry& entry) { return entry.name.compare(dirEntry.name) && entry.entryType == dirEntry.entryType; }); + EXPECT_NE(expected, nullptr); + EXPECT_NE(expected, expectedFiles.end()); + printf("%s %u\n", dirEntry.name.c_str(), static_cast<uint8_t>(dirEntry.entryType)); + } + + auto finalDirEntryResult = directory.getNextEntry(); + EXPECT_TRUE(finalDirEntryResult.isOkay()); + EXPECT_EQ(finalDirEntryResult.getOkay(), std::nullopt); + + // ASSERT_EQ(removeRecursive(testDirName), FudStatus::Success); +} + +} // namespace fud |