Skip to content

FileActionLog: needs a fault-injection seam for file I/O failure paths (fwrite/fflush/fsync/fopen/repairTornTail) #97

Description

@Yaraslaut

FileActionLog (include/morph/journal/file_action_log.hpp) has several branch arms that only run when a real filesystem/stdio call fails partway through an otherwise-successful operation:

  • append(): std::fwrite returning a short count (line ~146).
  • flush(): std::fflush failing (~173) or fsync/_commit failing (~182).
  • rotate(): the pre-rotation std::fflush failing (~278) or fsync/_commit failing (~286); and — the bigger gap — std::fopen failing to reopen the active path after the rename to sealedPath has already succeeded (~305-310). That last one is also what makes the destructor's _file != nullptr guard (~113), requireOpen()'s throwing arm (~322), and the "successful vs failed rename" wording in the reopen-failure message (~308) unreachable from a test — they all require _file to end up null, which today only happens via that one reopen failure.
  • repairTornTail(): std::ifstream failing to open a path that std::filesystem::file_size just succeeded on (~345), and std::filesystem::resize_file failing while truncating a torn tail (~363).

None of these are reachable from a portable unit test today: they all need a real OS-level failure (disk full, permission revoked mid-call, fd exhaustion, directory removed between two calls) at an exact point between two library calls, and the codebase has no fault-injection seam for file I/O (checked test_support.hpp and sibling test files — the existing deterministic-race idioms there are executor/scheduling hooks, not I/O hooks).

Requested seam: a way to make FileActionLog's file I/O calls (fwrite, fflush, fsync/_commit, fopen for the reopen, and — for repairTornTail()file_size, opening the ifstream, and resize_file) fail on demand from a test, without changing the class's public behavior for normal callers. Prior art in this repo: SqlLogger-style hooks used for the Lightweight-side pool tracing (see LASTRADA-Software/Lightweight#548) — an analogous "current failure mode" hook, settable only from test code (e.g. an optional injection point threaded through the constructor or a test-only subclass seam), would let each of the branches above be driven directly instead of skipped.

Until this seam exists, these branches are intentionally left uncovered rather than shipping a flaky/hacky test (e.g. filling the disk, revoking permissions mid-test, or racing directory removal). Each site has an in-code comment pointing back to this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions