start host FS impl
This commit is contained in:
parent
3df1161560
commit
aca8b53a59
@ -1,5 +1,6 @@
|
|||||||
add_subdirectory(devicehandlers)
|
add_subdirectory(devicehandlers)
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
|
add_subdirectory(host)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
add_subdirectory(linux)
|
add_subdirectory(linux)
|
||||||
|
@ -1 +1 @@
|
|||||||
|
target_sources(${LIB_FSFW_NAME} PUBLIC HostFilesystem.cpp)
|
||||||
|
99
src/fsfw_hal/host/HostFilesystem.cpp
Normal file
99
src/fsfw_hal/host/HostFilesystem.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "HostFilesystem.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "fsfw/serialize.h"
|
||||||
|
|
||||||
|
using namespace std::filesystem;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
HostFilesystem::HostFilesystem() = default;
|
||||||
|
|
||||||
|
ReturnValue_t HostFilesystem::writeToFile(FileOpParams params, const uint8_t *data) {
|
||||||
|
if (params.path == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
path path(params.path);
|
||||||
|
if (not exists(path)) {
|
||||||
|
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
ofstream file(path, ios::binary | ios::out);
|
||||||
|
if (file.fail()) {
|
||||||
|
return HasFileSystemIF::GENERIC_FILE_ERROR;
|
||||||
|
}
|
||||||
|
file.seekp(static_cast<unsigned int>(params.offset));
|
||||||
|
file.write(reinterpret_cast<const char *>(data), static_cast<unsigned int>(params.size));
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t HostFilesystem::readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize,
|
||||||
|
size_t maxSize) {
|
||||||
|
if (params.path == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
path path(params.path);
|
||||||
|
if (not exists(path)) {
|
||||||
|
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
ifstream file(path);
|
||||||
|
if (file.fail()) {
|
||||||
|
return HasFileSystemIF::GENERIC_FILE_ERROR;
|
||||||
|
}
|
||||||
|
auto readLen = static_cast<unsigned int>(params.offset);
|
||||||
|
file.seekg(readLen);
|
||||||
|
if (readSize + params.size > maxSize) {
|
||||||
|
return SerializeIF::BUFFER_TOO_SHORT;
|
||||||
|
}
|
||||||
|
file.read(reinterpret_cast<char *>(*buffer), readLen);
|
||||||
|
readSize += readLen;
|
||||||
|
*buffer += readLen;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t HostFilesystem::createFile(FilesystemParams params, const uint8_t *data,
|
||||||
|
size_t size) {
|
||||||
|
if (params.path == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
path path(params.path);
|
||||||
|
if (exists(path)) {
|
||||||
|
return HasFileSystemIF::FILE_ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
ofstream file(path);
|
||||||
|
if (file.fail()) {
|
||||||
|
return HasFileSystemIF::GENERIC_FILE_ERROR;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t HostFilesystem::removeFile(const char *path_, FileSystemArgsIF *args) {
|
||||||
|
if (path_ == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
path path(path_);
|
||||||
|
if (not exists(path)) {
|
||||||
|
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
if (remove(path, errorCode)) {
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
return HasFileSystemIF::GENERIC_FILE_ERROR;
|
||||||
|
}
|
||||||
|
ReturnValue_t HostFilesystem::createDirectory(FilesystemParams params, bool createParentDirs) {
|
||||||
|
if (params.path == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
path dirPath(params.path);
|
||||||
|
if (createParentDirs) {
|
||||||
|
create_directories(dirPath, errorCode);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ReturnValue_t HostFilesystem::removeDirectory(FilesystemParams params, bool deleteRecurively) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ReturnValue_t HostFilesystem::renameFile(const char *oldPath, char *newPath,
|
||||||
|
FileSystemArgsIF *args) {
|
||||||
|
return 0;
|
||||||
|
}
|
24
src/fsfw_hal/host/HostFilesystem.h
Normal file
24
src/fsfw_hal/host/HostFilesystem.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef FSFW_HAL_HOSTFILESYSTEM_H
|
||||||
|
#define FSFW_HAL_HOSTFILESYSTEM_H
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
#include "fsfw/filesystem/HasFileSystemIF.h"
|
||||||
|
|
||||||
|
class HostFilesystem : public HasFileSystemIF {
|
||||||
|
public:
|
||||||
|
HostFilesystem();
|
||||||
|
ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override;
|
||||||
|
ReturnValue_t readFromFile(FileOpParams fileOpInfo, uint8_t **buffer, size_t &readSize,
|
||||||
|
size_t maxSize) override;
|
||||||
|
ReturnValue_t createFile(FilesystemParams params, const uint8_t *data, size_t size) override;
|
||||||
|
ReturnValue_t removeFile(const char *path, FileSystemArgsIF *args) override;
|
||||||
|
ReturnValue_t createDirectory(FilesystemParams params, bool createParentDirs) override;
|
||||||
|
ReturnValue_t removeDirectory(FilesystemParams params, bool deleteRecurively) override;
|
||||||
|
ReturnValue_t renameFile(const char *oldPath, char *newPath, FileSystemArgsIF *args) override;
|
||||||
|
|
||||||
|
std::error_code errorCode;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
#endif // FSFW_HAL_HOSTFILESYSTEM_H
|
@ -1 +1,2 @@
|
|||||||
target_sources(${FSFW_TEST_TGT} PRIVATE testCommandExecutor.cpp)
|
target_sources(${FSFW_TEST_TGT} PRIVATE testCommandExecutor.cpp
|
||||||
|
testHostFilesystem.cpp)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
static const char TEST_FILE_NAME[] = "/tmp/fsfw-unittest-test.txt";
|
static const char TEST_FILE_NAME[] = "/tmp/fsfw-unittest-test.txt";
|
||||||
|
|
||||||
TEST_CASE("Command Executor", "[cmd-exec]") {
|
TEST_CASE("Command Executor", "[hal][linux]") {
|
||||||
// Check blocking mode first
|
// Check blocking mode first
|
||||||
CommandExecutor cmdExecutor(1024);
|
CommandExecutor cmdExecutor(1024);
|
||||||
std::string cmd = "echo \"test\" >> " + std::string(TEST_FILE_NAME);
|
std::string cmd = "echo \"test\" >> " + std::string(TEST_FILE_NAME);
|
||||||
|
5
unittests/hal/testHostFilesystem.cpp
Normal file
5
unittests/hal/testHostFilesystem.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include "fsfw_hal/host/HostFilesystem.h"
|
||||||
|
|
||||||
|
TEST_CASE("Host Filesystem", "[hal][host]") { auto hostFs = HostFilesystem(); }
|
@ -1,6 +1,76 @@
|
|||||||
#include "FilesystemMock.h"
|
#include "FilesystemMock.h"
|
||||||
|
|
||||||
|
#include "fsfw/serialize/SerializeIF.h"
|
||||||
|
|
||||||
ReturnValue_t FilesystemMock::writeToFile(FileOpParams params, const uint8_t *data) {
|
ReturnValue_t FilesystemMock::writeToFile(FileOpParams params, const uint8_t *data) {
|
||||||
|
createOrAddToFile(params, data);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FilesystemMock::readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize,
|
||||||
|
size_t maxSize) {
|
||||||
|
std::string filename(params.path);
|
||||||
|
auto iter = fileMap.find(filename);
|
||||||
|
if (iter == fileMap.end()) {
|
||||||
|
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
||||||
|
} else {
|
||||||
|
FileInfo &info = iter->second;
|
||||||
|
size_t readLen = params.size;
|
||||||
|
if (params.offset + params.size > info.fileRaw.size()) {
|
||||||
|
if (params.offset > info.fileRaw.size()) {
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
readLen = info.fileRaw.size() - params.offset;
|
||||||
|
}
|
||||||
|
if (readSize + readLen > maxSize) {
|
||||||
|
return SerializeIF::STREAM_TOO_SHORT;
|
||||||
|
}
|
||||||
|
std::copy(info.fileRaw.data() + params.offset, info.fileRaw.data() + readLen, *buffer);
|
||||||
|
*buffer += readLen;
|
||||||
|
readSize += readLen;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FilesystemMock::createFile(FilesystemParams params, const uint8_t *data,
|
||||||
|
size_t size) {
|
||||||
|
FileOpParams params2(params.path, size);
|
||||||
|
createOrAddToFile(params2, data);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FilesystemMock::removeFile(const char *path, FileSystemArgsIF *args) {
|
||||||
|
std::string filename(path);
|
||||||
|
auto iter = fileMap.find(filename);
|
||||||
|
if (iter == fileMap.end()) {
|
||||||
|
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
||||||
|
} else {
|
||||||
|
fileMap.erase(iter);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FilesystemMock::createDirectory(FilesystemParams params, bool createParentDirs) {
|
||||||
|
std::string dirPath = params.path;
|
||||||
|
dirMap[dirPath].createCallCount++;
|
||||||
|
dirMap[dirPath].wihParentDir.push(createParentDirs);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FilesystemMock::removeDirectory(FilesystemParams params, bool deleteRecurively) {
|
||||||
|
std::string dirPath = params.path;
|
||||||
|
dirMap[dirPath].delCallCount++;
|
||||||
|
dirMap[dirPath].recursiveDeletion.push(deleteRecurively);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FilesystemMock::renameFile(const char *oldPath, char *newPath,
|
||||||
|
FileSystemArgsIF *args) {
|
||||||
|
renameQueue.push(RenameInfo(oldPath, newPath));
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilesystemMock::createOrAddToFile(FileOpParams params, const uint8_t *data) {
|
||||||
std::string filename(params.path);
|
std::string filename(params.path);
|
||||||
auto iter = fileMap.find(filename);
|
auto iter = fileMap.find(filename);
|
||||||
if (iter == fileMap.end()) {
|
if (iter == fileMap.end()) {
|
||||||
@ -8,40 +78,31 @@ ReturnValue_t FilesystemMock::writeToFile(FileOpParams params, const uint8_t *da
|
|||||||
queue.push(FileWriteInfo(filename, params.offset, data, params.size));
|
queue.push(FileWriteInfo(filename, params.offset, data, params.size));
|
||||||
FileInfo info;
|
FileInfo info;
|
||||||
info.fileSegQueue = queue;
|
info.fileSegQueue = queue;
|
||||||
info.fileRaw.insert(info.fileRaw.end(), data, data + params.size);
|
if (data != nullptr) {
|
||||||
|
info.fileRaw.insert(info.fileRaw.end(), data, data + params.size);
|
||||||
|
}
|
||||||
fileMap.emplace(filename, info);
|
fileMap.emplace(filename, info);
|
||||||
} else {
|
} else {
|
||||||
FileInfo& info = iter->second;
|
FileInfo &info = iter->second;
|
||||||
info.fileSegQueue.push(FileWriteInfo(filename, params.offset, data, params.size));
|
info.fileSegQueue.push(FileWriteInfo(filename, params.offset, data, params.size));
|
||||||
|
if (data == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Easiest case: append data to the end
|
// Easiest case: append data to the end
|
||||||
if(params.offset == info.fileRaw.size()) {
|
if (params.offset == info.fileRaw.size()) {
|
||||||
info.fileRaw.insert(info.fileRaw.end(), data, data + params.size);
|
info.fileRaw.insert(info.fileRaw.end(), data, data + params.size);
|
||||||
} else {
|
} else {
|
||||||
size_t totalNewLen = params.offset + params.size;
|
size_t totalNewLen = params.offset + params.size;
|
||||||
if(totalNewLen > info.fileRaw.size()) {
|
if (totalNewLen > info.fileRaw.size()) {
|
||||||
info.fileRaw.resize(params.offset + params.size);
|
info.fileRaw.resize(params.offset + params.size);
|
||||||
}
|
}
|
||||||
std::copy(data, data + params.size, info.fileRaw.begin() + static_cast<unsigned int>(params.offset));
|
std::copy(data, data + params.size,
|
||||||
|
info.fileRaw.begin() + static_cast<unsigned int>(params.offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
ReturnValue_t FilesystemMock::readFromFile(FileOpParams fileOpInfo, uint8_t **buffer,
|
|
||||||
size_t &readSize, size_t maxSize) {
|
void FilesystemMock::reset() {
|
||||||
return 0;
|
fileMap.clear();
|
||||||
}
|
dirMap.clear();
|
||||||
ReturnValue_t FilesystemMock::createFile(FilesystemParams params, const uint8_t *data,
|
|
||||||
size_t size) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ReturnValue_t FilesystemMock::removeFile(const char *path, FileSystemArgsIF *args) { return 0; }
|
|
||||||
ReturnValue_t FilesystemMock::createDirectory(FilesystemParams params, bool createParentDirs) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ReturnValue_t FilesystemMock::removeDirectory(FilesystemParams params, bool deleteRecurively) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ReturnValue_t FilesystemMock::renameFile(const char *oldPath, char *newPath,
|
|
||||||
FileSystemArgsIF *args) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,26 @@
|
|||||||
#ifndef FSFW_MOCKS_FILESYSTEMMOCK_H
|
#ifndef FSFW_MOCKS_FILESYSTEMMOCK_H
|
||||||
#define FSFW_MOCKS_FILESYSTEMMOCK_H
|
#define FSFW_MOCKS_FILESYSTEMMOCK_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "fsfw/filesystem.h"
|
#include "fsfw/filesystem.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This mock models a filesystem in the RAM. It can be used to verify correct behaviour of
|
||||||
|
* a component using a filesystem without relying on an actual OS filesystem implementation.
|
||||||
|
*
|
||||||
|
* Please note that this object does not actually check paths for validity. The file API was
|
||||||
|
* built in a way to allow reading a file back after it was written while also remembering
|
||||||
|
* the specific file segments which were inserted in write calls.
|
||||||
|
*/
|
||||||
class FilesystemMock : public HasFileSystemIF {
|
class FilesystemMock : public HasFileSystemIF {
|
||||||
public:
|
public:
|
||||||
struct FileWriteInfo {
|
struct FileWriteInfo {
|
||||||
FileWriteInfo(std::string filename, size_t offset, const uint8_t* data, size_t len)
|
FileWriteInfo(std::string filename, size_t offset, const uint8_t *data, size_t len)
|
||||||
: filename(std::move(filename)), offset(offset) {
|
: filename(std::move(filename)), offset(offset) {
|
||||||
this->data.insert(this->data.end(), data, data + len);
|
this->data.insert(this->data.end(), data, data + len);
|
||||||
}
|
}
|
||||||
std::string filename;
|
std::string filename;
|
||||||
@ -28,14 +36,36 @@ class FilesystemMock : public HasFileSystemIF {
|
|||||||
|
|
||||||
std::map<std::string, FileInfo> fileMap;
|
std::map<std::string, FileInfo> fileMap;
|
||||||
|
|
||||||
|
struct DirInfo {
|
||||||
|
size_t createCallCount = 0;
|
||||||
|
size_t delCallCount = 0;
|
||||||
|
std::queue<bool> wihParentDir;
|
||||||
|
std::queue<bool> recursiveDeletion;
|
||||||
|
};
|
||||||
|
std::map<std::string, DirInfo> dirMap;
|
||||||
|
|
||||||
|
struct RenameInfo {
|
||||||
|
RenameInfo(std::string oldName, std::string newName)
|
||||||
|
: oldName(std::move(oldName)), newName(std::move(newName)) {}
|
||||||
|
|
||||||
|
std::string oldName;
|
||||||
|
std::string newName;
|
||||||
|
};
|
||||||
|
std::queue<RenameInfo> renameQueue;
|
||||||
|
|
||||||
ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override;
|
ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override;
|
||||||
ReturnValue_t readFromFile(FileOpParams fileOpInfo, uint8_t **buffer, size_t &readSize,
|
ReturnValue_t readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize,
|
||||||
size_t maxSize) override;
|
size_t maxSize) override;
|
||||||
ReturnValue_t createFile(FilesystemParams params, const uint8_t *data, size_t size) override;
|
ReturnValue_t createFile(FilesystemParams params, const uint8_t *data, size_t size) override;
|
||||||
ReturnValue_t removeFile(const char *path, FileSystemArgsIF *args) override;
|
ReturnValue_t removeFile(const char *path, FileSystemArgsIF *args) override;
|
||||||
ReturnValue_t createDirectory(FilesystemParams params, bool createParentDirs) override;
|
ReturnValue_t createDirectory(FilesystemParams params, bool createParentDirs) override;
|
||||||
ReturnValue_t removeDirectory(FilesystemParams params, bool deleteRecurively) override;
|
ReturnValue_t removeDirectory(FilesystemParams params, bool deleteRecurively) override;
|
||||||
ReturnValue_t renameFile(const char *oldPath, char *newPath, FileSystemArgsIF *args) override;
|
ReturnValue_t renameFile(const char *oldPath, char *newPath, FileSystemArgsIF *args) override;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createOrAddToFile(FileOpParams params, const uint8_t *data);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FSFW_MOCKS_FILESYSTEMMOCK_H
|
#endif // FSFW_MOCKS_FILESYSTEMMOCK_H
|
||||||
|
Loading…
Reference in New Issue
Block a user