2022-09-15 16:20:52 +02:00
|
|
|
#include <etl/crc32.h>
|
|
|
|
|
2022-08-10 17:03:23 +02:00
|
|
|
#include <catch2/catch_test_macros.hpp>
|
2022-08-11 10:10:05 +02:00
|
|
|
#include <filesystem>
|
2022-08-17 11:39:15 +02:00
|
|
|
#include <fstream>
|
2022-09-15 16:20:52 +02:00
|
|
|
#include <random>
|
2022-08-10 17:03:23 +02:00
|
|
|
|
2022-08-17 16:10:52 +02:00
|
|
|
#include "fsfw/serialize/SerializeIF.h"
|
2022-08-10 17:03:23 +02:00
|
|
|
#include "fsfw_hal/host/HostFilesystem.h"
|
|
|
|
|
2022-08-17 11:39:15 +02:00
|
|
|
using namespace std;
|
|
|
|
|
2022-08-11 09:59:14 +02:00
|
|
|
TEST_CASE("Host Filesystem", "[hal][host]") {
|
2022-08-17 11:39:15 +02:00
|
|
|
namespace fs = filesystem;
|
2022-08-11 09:59:14 +02:00
|
|
|
auto hostFs = HostFilesystem();
|
|
|
|
auto tmpDir = fs::temp_directory_path();
|
2022-08-11 10:10:05 +02:00
|
|
|
fs::path file0 = tmpDir / "hello.txt";
|
2022-08-11 10:19:25 +02:00
|
|
|
fs::path file1 = tmpDir / "hello2.txt";
|
|
|
|
fs::path dir0 = tmpDir / "test_dir";
|
2022-08-17 16:10:52 +02:00
|
|
|
fs::path fileInDir0 = dir0 / "hello.txt";
|
|
|
|
fs::path dirWithParent = dir0 / "test_dir";
|
|
|
|
|
2022-08-11 10:10:05 +02:00
|
|
|
REQUIRE_NOTHROW(fs::remove(file0));
|
|
|
|
REQUIRE_NOTHROW(fs::remove(file1));
|
2022-08-17 16:10:52 +02:00
|
|
|
REQUIRE_NOTHROW(fs::remove_all(dir0));
|
2022-08-11 09:59:14 +02:00
|
|
|
|
|
|
|
SECTION("Create file") {
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createFile(file0.c_str()) == returnvalue::OK);
|
2022-08-11 10:19:25 +02:00
|
|
|
CHECK(fs::is_regular_file(file0));
|
|
|
|
REQUIRE(fs::exists(file0));
|
2022-08-11 09:59:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Remove File") {
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createFile(file0.c_str()) == returnvalue::OK);
|
2022-08-11 10:19:25 +02:00
|
|
|
CHECK(fs::is_regular_file(file0));
|
|
|
|
REQUIRE(fs::exists(file0));
|
2022-08-22 16:35:53 +02:00
|
|
|
REQUIRE(hostFs.removeFile(file0.c_str()) == returnvalue::OK);
|
2022-08-11 10:19:25 +02:00
|
|
|
REQUIRE(not fs::exists(file0));
|
2022-08-11 09:59:14 +02:00
|
|
|
}
|
|
|
|
|
2022-08-11 10:10:05 +02:00
|
|
|
SECTION("Create Directory") {
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createDirectory(dir0.c_str()) == returnvalue::OK);
|
2022-08-11 10:19:25 +02:00
|
|
|
CHECK(fs::is_directory(dir0));
|
|
|
|
REQUIRE(fs::exists(dir0));
|
2022-08-11 10:10:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Remove Directory") {
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createDirectory(dir0.c_str()) == returnvalue::OK);
|
2022-08-11 10:19:25 +02:00
|
|
|
REQUIRE(fs::exists(dir0));
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.removeDirectory(dir0.c_str(), false, nullptr) == returnvalue::OK);
|
2022-08-11 10:19:25 +02:00
|
|
|
REQUIRE(not fs::exists(dir0));
|
2022-08-11 10:10:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Rename File") {
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createFile(file0.c_str()) == returnvalue::OK);
|
2022-08-11 10:19:25 +02:00
|
|
|
CHECK(fs::is_regular_file(file0));
|
|
|
|
REQUIRE(fs::exists(file0));
|
2022-08-22 16:35:53 +02:00
|
|
|
REQUIRE(hostFs.rename(file0.c_str(), file1.c_str()) == returnvalue::OK);
|
2022-08-11 10:10:05 +02:00
|
|
|
}
|
2022-08-11 10:19:25 +02:00
|
|
|
|
|
|
|
SECTION("Write To File") {
|
|
|
|
std::string data = "hello world!";
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createFile(file0.c_str()) == returnvalue::OK);
|
2022-08-11 10:19:25 +02:00
|
|
|
CHECK(fs::is_regular_file(file0));
|
|
|
|
REQUIRE(fs::exists(file0));
|
2024-05-24 14:29:42 +02:00
|
|
|
CHECK(hostFs.writeToFile(file0.c_str(), 0, reinterpret_cast<const uint8_t*>(data.c_str()),
|
|
|
|
data.size()) == returnvalue::OK);
|
2022-08-17 11:39:15 +02:00
|
|
|
CHECK(fs::file_size(file0) == data.size());
|
|
|
|
ifstream ifile(file0);
|
2022-09-15 16:20:52 +02:00
|
|
|
std::array<char, 524> readBuf{};
|
|
|
|
ifile.read(readBuf.data(), sizeof(readBuf));
|
|
|
|
std::string readBackString(readBuf.data());
|
2022-08-17 11:39:15 +02:00
|
|
|
CHECK(data == readBackString);
|
|
|
|
}
|
|
|
|
|
2022-09-15 16:20:52 +02:00
|
|
|
SECTION("Write To File, Check Not Truncated") {
|
|
|
|
std::random_device dev;
|
|
|
|
std::mt19937 rng(dev());
|
|
|
|
std::uniform_int_distribution<std::mt19937::result_type> distU8(1, 255);
|
|
|
|
std::array<uint8_t, 512> randData{};
|
|
|
|
for (uint8_t& byte : randData) {
|
|
|
|
byte = distU8(rng);
|
|
|
|
}
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createFile(file0.c_str()) == returnvalue::OK);
|
2022-09-15 16:20:52 +02:00
|
|
|
CHECK(fs::is_regular_file(file0));
|
|
|
|
REQUIRE(fs::exists(file0));
|
|
|
|
// Write first file chunk
|
2024-05-24 14:29:42 +02:00
|
|
|
CHECK(hostFs.writeToFile(file0.c_str(), 0, randData.cbegin(), randData.size() - 256) ==
|
|
|
|
returnvalue::OK);
|
|
|
|
CHECK(hostFs.writeToFile(file0.c_str(), 256, randData.cbegin() + 256, 256) == returnvalue::OK);
|
2022-09-15 16:20:52 +02:00
|
|
|
std::ifstream rf(file0, ios::binary);
|
|
|
|
std::array<uint8_t, 512> readBack{};
|
|
|
|
REQUIRE(std::filesystem::file_size(file0) == 512);
|
|
|
|
rf.read(reinterpret_cast<char*>(readBack.data()), readBack.size());
|
|
|
|
for (size_t i = 0; i < 512; i++) {
|
|
|
|
CHECK(randData[i] == readBack[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-17 11:39:15 +02:00
|
|
|
SECTION("Read From File") {
|
|
|
|
std::string data = "hello world!";
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createFile(file0.c_str()) == returnvalue::OK);
|
2022-08-17 11:39:15 +02:00
|
|
|
CHECK(fs::is_regular_file(file0));
|
|
|
|
ofstream of(file0);
|
|
|
|
of.write(data.c_str(), static_cast<unsigned int>(data.size()));
|
|
|
|
of.close();
|
|
|
|
CHECK(fs::file_size(file0) == data.size());
|
|
|
|
REQUIRE(fs::exists(file0));
|
|
|
|
std::array<uint8_t, 256> readBuf{};
|
|
|
|
uint8_t* readPtr = readBuf.data();
|
2024-05-24 14:29:42 +02:00
|
|
|
size_t readSize = data.size();
|
|
|
|
size_t actuallyRead = 0;
|
|
|
|
CHECK(hostFs.readFromFile(file0.c_str(), 0, readSize, readPtr, actuallyRead, readBuf.size()) ==
|
|
|
|
returnvalue::OK);
|
2022-08-17 11:39:15 +02:00
|
|
|
std::string readBackString(reinterpret_cast<const char*>(readBuf.data()));
|
|
|
|
CHECK(readSize == data.size());
|
|
|
|
CHECK(data == readBackString);
|
2022-08-17 16:10:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Invalid Input does not crash") {
|
|
|
|
FileOpParams params(nullptr, 10);
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createFile(nullptr) != returnvalue::OK);
|
|
|
|
REQUIRE(hostFs.createDirectory(nullptr) != returnvalue::OK);
|
|
|
|
REQUIRE(hostFs.createFile(nullptr) != returnvalue::OK);
|
|
|
|
REQUIRE(hostFs.removeDirectory(nullptr, false, nullptr) != returnvalue::OK);
|
2022-08-22 16:35:53 +02:00
|
|
|
REQUIRE(hostFs.removeFile(nullptr) != returnvalue::OK);
|
|
|
|
REQUIRE(hostFs.rename(nullptr, nullptr) != returnvalue::OK);
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.writeToFile(nullptr, 0, nullptr, 0) != returnvalue::OK);
|
2022-08-17 16:10:52 +02:00
|
|
|
size_t readLen = 0;
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.readFromFile(nullptr, 0, 0, nullptr, readLen, 20) != returnvalue::OK);
|
2022-08-17 16:10:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Create File but already exists") {
|
|
|
|
FilesystemParams params(file0.c_str());
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createFile(file0.c_str()) == returnvalue::OK);
|
|
|
|
REQUIRE(hostFs.createFile(file0.c_str()) == HasFileSystemIF::FILE_ALREADY_EXISTS);
|
2022-08-17 16:10:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Remove File but does not exist") {
|
|
|
|
REQUIRE(hostFs.removeFile(file0.c_str()) == HasFileSystemIF::FILE_DOES_NOT_EXIST);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Create Directory but already exists") {
|
|
|
|
FileOpParams params(file0.c_str(), 12);
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.createDirectory(file0.c_str()) == returnvalue::OK);
|
|
|
|
REQUIRE(hostFs.createDirectory(file0.c_str()) == HasFileSystemIF::DIRECTORY_ALREADY_EXISTS);
|
2022-08-17 16:10:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Remove Directory but does not exist") {
|
|
|
|
FilesystemParams params(dir0.c_str());
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.removeDirectory(dir0.c_str(), false, nullptr) ==
|
|
|
|
HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST);
|
2022-08-17 16:10:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Remove Directory but is file") {
|
|
|
|
ofstream of(file0);
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.removeDirectory(file0.c_str(), false, nullptr) ==
|
|
|
|
HasFileSystemIF::NOT_A_DIRECTORY);
|
2022-08-17 16:10:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Read from file but does not exist") {
|
|
|
|
std::string data = "hello world!";
|
2024-05-24 14:29:42 +02:00
|
|
|
std::array<uint8_t, 16> readBuf{};
|
2022-08-17 16:10:52 +02:00
|
|
|
uint8_t* readPtr = readBuf.data();
|
|
|
|
size_t readSize = 0;
|
2024-05-24 14:29:42 +02:00
|
|
|
CHECK(hostFs.readFromFile(file0.c_str(), 0, data.size(), readPtr, readSize, readBuf.size()) ==
|
2022-08-17 16:10:52 +02:00
|
|
|
HasFileSystemIF::FILE_DOES_NOT_EXIST);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Write to file but does not exist") {
|
|
|
|
std::string data = "hello world!";
|
2024-05-24 14:29:42 +02:00
|
|
|
CHECK(hostFs.writeToFile(file0.c_str(), 0, reinterpret_cast<const uint8_t*>(data.c_str()),
|
|
|
|
data.size()) == HasFileSystemIF::FILE_DOES_NOT_EXIST);
|
2022-08-17 16:10:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Remove recursively") {
|
|
|
|
fs::create_directory(dir0.c_str());
|
|
|
|
ofstream of(fileInDir0);
|
|
|
|
CHECK(fs::is_directory(dir0));
|
|
|
|
CHECK(fs::is_regular_file(fileInDir0));
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.removeDirectory(dir0.c_str(), true, nullptr) == returnvalue::OK);
|
2022-08-17 16:10:52 +02:00
|
|
|
CHECK(not fs::is_directory(dir0));
|
|
|
|
CHECK(not fs::is_regular_file(fileInDir0));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Non-Recursive Removal Fails") {
|
|
|
|
fs::create_directory(dir0.c_str());
|
|
|
|
ofstream of(fileInDir0);
|
|
|
|
CHECK(fs::is_directory(dir0));
|
|
|
|
CHECK(fs::is_regular_file(fileInDir0));
|
2024-05-24 14:29:42 +02:00
|
|
|
REQUIRE(hostFs.removeDirectory(dir0.c_str(), false, nullptr) ==
|
2022-08-17 16:10:52 +02:00
|
|
|
HasFileSystemIF::DIRECTORY_NOT_EMPTY);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Create directory with parent directory") {
|
2024-05-24 14:29:42 +02:00
|
|
|
CHECK(hostFs.createDirectory(dirWithParent.c_str(), true, nullptr) == returnvalue::OK);
|
2022-08-17 16:10:52 +02:00
|
|
|
CHECK(fs::is_directory(dir0));
|
|
|
|
CHECK(fs::is_directory(dirWithParent));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Read but provided buffer too small") {
|
|
|
|
std::string data = "hello world!";
|
|
|
|
FileOpParams params(file0.c_str(), data.size());
|
|
|
|
ofstream of(file0);
|
|
|
|
of.write(data.c_str(), static_cast<unsigned int>(data.size()));
|
|
|
|
of.close();
|
|
|
|
CHECK(fs::file_size(file0) == data.size());
|
|
|
|
REQUIRE(fs::exists(file0));
|
|
|
|
std::array<uint8_t, 15> readBuf{};
|
|
|
|
uint8_t* readPtr = readBuf.data();
|
|
|
|
size_t readSize = 0;
|
2024-05-24 14:29:42 +02:00
|
|
|
CHECK(hostFs.readFromFile(file0.c_str(), 0, data.size(), readPtr, readSize, 5) ==
|
2022-08-17 16:10:52 +02:00
|
|
|
SerializeIF::BUFFER_TOO_SHORT);
|
2024-05-24 14:29:42 +02:00
|
|
|
;
|
2022-08-11 10:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
REQUIRE_NOTHROW(fs::remove(file0));
|
|
|
|
REQUIRE_NOTHROW(fs::remove(file1));
|
2022-08-17 16:10:52 +02:00
|
|
|
REQUIRE_NOTHROW(fs::remove_all(dir0));
|
2022-08-11 09:59:14 +02:00
|
|
|
}
|