Skip to content

Commit

Permalink
fs_helpers: make more filesystem utilities mockable.
Browse files Browse the repository at this point in the history
From `man fmemopen`:
> There  is  no  file  descriptor  associated with the file stream
returned by this function (i.e., fileno(3) will return an error if
called on the returned stream).
  • Loading branch information
darosior committed Dec 29, 2023
1 parent 5974af7 commit f4e07ef
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/util/fs_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,14 @@ std::streampos GetFileSize(const char* path, std::streamsize max)
return file.gcount();
}

std::function<bool(FILE* file)> g_mock_file_commit{nullptr};

bool FileCommit(FILE* file)
{
if (g_mock_file_commit) {
return g_mock_file_commit(file);
}

if (fflush(file) != 0) { // harmless if redundantly called
LogPrintf("fflush failed: %s\n", SysErrorString(errno));
return false;
Expand Down Expand Up @@ -142,8 +148,14 @@ bool FileCommit(FILE* file)
return true;
}

std::function<void(const fs::path&)> g_mock_dir_commit{nullptr};

void DirectoryCommit(const fs::path& dirname)
{
if (g_mock_dir_commit) {
return g_mock_dir_commit(dirname);
}

#ifndef WIN32
FILE* file = fsbridge::fopen(dirname, "r");
if (file) {
Expand All @@ -153,8 +165,14 @@ void DirectoryCommit(const fs::path& dirname)
#endif
}

std::function<bool(FILE*, unsigned int)> g_mock_truncate_file{nullptr};

bool TruncateFile(FILE* file, unsigned int length)
{
if (g_mock_truncate_file) {
return g_mock_truncate_file(file, length);
}

#if defined(WIN32)
return _chsize(_fileno(file), length) == 0;
#else
Expand Down Expand Up @@ -186,12 +204,18 @@ int RaiseFileDescriptorLimit(int nMinFD)
#endif
}

std::function<void(FILE*, unsigned int, unsigned int)> g_mock_allocate_file_range{nullptr};

/**
* this function tries to make a particular range of a file allocated (corresponding to disk space)
* it is advisory, and the range specified in the arguments will never contain live data
*/
void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length)
{
if (g_mock_allocate_file_range) {
return g_mock_allocate_file_range(file, offset, length);
}

#if defined(WIN32)
// Windows-specific version
HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
Expand Down
14 changes: 14 additions & 0 deletions src/util/fs_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,34 @@
#include <iosfwd>
#include <limits>

//! Used to replace the implementation of the FileCommit function.
extern std::function<bool(FILE* file)> g_mock_file_commit;

/**
* Ensure file contents are fully committed to disk, using a platform-specific
* feature analogous to fsync().
*/
bool FileCommit(FILE* file);

//! Used to replace the implementation of the DirectoryCommit function.
extern std::function<void(const fs::path&)> g_mock_dir_commit;

/**
* Sync directory contents. This is required on some environments to ensure that
* newly created files are committed to disk.
*/
void DirectoryCommit(const fs::path& dirname);

//! Used to replace the implementation of the TruncateFile function.
extern std::function<bool(FILE*, unsigned int)> g_mock_truncate_file;

bool TruncateFile(FILE* file, unsigned int length);

int RaiseFileDescriptorLimit(int nMinFD);

//! Used to replace the implementation of the AllocateFileRange function.
extern std::function<void(FILE*, unsigned int, unsigned int)> g_mock_allocate_file_range;

void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length);

/**
Expand Down

0 comments on commit f4e07ef

Please sign in to comment.