Test Mocks for Eio.Flow and StdEnv to write to a file

Thanks for the extra details @Mohan_Radhakrishnan, that is super helpful. I also put two and two together and realised this is (in part) a continuation of: How do I pass Eio 'env'?.

In light of that I think the question becomes a lot clearer. And yes, if your point of abstraction is an _ Eio.Path.t then at the moment eio.mock does not offer ways to mock the required interfaces (directories and files). This actually gets very complicated very quickly as you end up needing to mock Eio.Fs.Pi.DIR and Eio.File.Pi.RO/RW. The logic between all of your mocks will need to take into account file creation, handlers for calls to stat etc. If you are curious to head down this route, I started mocking Fs.Dir and File.Ro, and I think opening an issue on Eio would be the correct next step. Here is what that might then look like:

module type WalWriter = sig
  type t

  val v : _ Eio.Path.t -> t
  val write : t -> Cstruct.t -> unit
  val read : t -> string
end

let make_stat ~size kind : Eio.File.Stat.t = {
    dev = 0L;
    ino = 0L;
    kind;
    perm = 0;
    nlink = 0L;
    uid = 0L;
    gid = 0L;
    rdev = 0L;
    size = Optint.Int63.of_int size;
    atime = 0.;
    mtime = 0.;
    ctime = 0.;
}

let test1 wal =
  assert (String.length (WalWriter.read wal) = 4)

let test () = 
  let mock_reader = Mock.File.make_ro "wal-reader" in
  Mock.File.on_read mock_reader [ `Return "1234" ];
  let t = Mock.Fs.make "mock-wal" in
  let path : _ Eio.Path.t = ((t :> Eio.Fs.dir_ty r), "/mock.log") in
  Mock.Fs.on_open_in t [ `Return mock_reader ];
  (* For your stat to check if the file exists, not strictly necessary *)
  Mock.Fs.on_stat t [ `Return (make_stat ~size:4 `Regular_file) ];
  (* For the file loading stat *)
  Mock.File.on_stat mock_reader [ `Return (make_stat ~size:4 `Regular_file) ];
  let wal = WalWriter.v path in
  test1 wal 
 
let () =
   Eio_mock.Backend.run @@ fun () ->
   test () 

Pretty gnarly… I think you would be better off using the filesystem directly in your tests instead of trying to mock it. Note as well that I changed your module signature a little to be more conventional. I hope this helps.

1 Like