Hi @Mohan_Radhakrishnan,
I think we need a few more bits of information here about what you are trying to achieve and what is not working for you. I also think a little more specificity in your title would make this much more searchable later (e.g. “How to use Eio’s mock flows to write data”).
I’m not sure what “like this” is referring to here?
The idea with mock flows is that anywhere that accepts a flow will also accept a mock flow that you can instrument in some way to test. Your actual code remains agnostic to whatever flow it accepts. Consider the following self-contained example:
type t = { name : string; age : int }
let to_json t = Fmt.str {|{ "name": "%s", "age": %i }|} t.name t.age
(* Read CSV from stdin *)
let parse_from_stdin stdin =
let buf = Eio.Buf_read.of_flow ~max_size:max_int stdin in
let rec loop acc =
try
let line = Eio.Buf_read.line buf in
match String.split_on_char ',' line with
| [ name; age ] -> loop ({ name; age = int_of_string age } :: acc)
| _ -> invalid_arg line
with End_of_file -> List.rev acc
in loop []
(* Copy to stdout *)
let dump_to_stdout stdout ts =
Eio.Buf_write.with_flow stdout @@ fun bw ->
Eio.Buf_write.string bw "[";
let rec loop = function
| [] -> ()
| [ t ] -> Eio.Buf_write.string bw (to_json t)
| t :: rest ->
Eio.Buf_write.string bw (to_json t);
Eio.Buf_write.string bw ",\n";
loop rest
in
loop ts;
Eio.Buf_write.string bw "]"
It is a rather simple parser of a CSV-like list of people’s names and ages. We might read those from command line and print them as JSON to stdout (I’ve used buffered readers and writers here only to show this works when you are doing more with your flows).
let main stdin stdout =
parse_from_stdin stdin |> dump_to_stdout stdout
let () =
Eio_main.run @@ fun env ->
main env#stdin env#stdout
If we wanted to test our parse_from_stdin we could instead instrument a mock flow to do so.
let test1 () =
let mock = Eio_mock.Flow.make "mock-stdin" in
Eio_mock.Flow.on_read mock [
`Return "alice,42";
`Raise End_of_file
];
let people = parse_from_stdin mock in
assert (people = [{ name = "alice"; age = 42 }])
We no longer need all of the OS resources that something like Eio_main provides us. We could just run this as let () = test1 (), but to future-proof the code (in case Fibers are involved) we can wrap it in the provided mock backend.
let () =
Eio_mock.Backend.run @@ fun () ->
test1 ()
To achieve what you want for a “mock” writer, we can use Eio.Flow.buffer_sink.
let test2 () =
let people = [ { name = "alice"; age = 42 } ] in
let buffer = Buffer.create 16 in
dump_to_stdout (Eio.Flow.buffer_sink buffer) people;
assert (Buffer.contents buffer = {|[{ "name": "alice", "age": 42 }]|})
Hopefully that helps a little? Please do add more information if this does not answer your question.