在
Format
模块中,pp_print_flush
将输出写入格式化程序,并重置漂亮的打印状态。是否可以刷新但不重置状态?
例如,使用
Format.make_formatter out flush
创建格式化程序,当例如使用out
。我想触发此调用,但不重置漂亮的打印机状态,例如打开盒子。(我认为我的问题是漂亮打印机的行为,而不是我不明白的一些 Lwt 同步)
问题我的系统是一个单元测试框架,我想支持测试的并发执行。但输出应该是这样的:测试的输出与启动的顺序相同,并且最肯定的是不同测试的输出不会交错。
但是我也想尽快输出,所以一旦“Test 1”完成,它的输出就会立即写入,但是如果“Test 3”在“Test 1”和“Test 2”之前完成,则不会写入,直到前两个已完成。
为了验证此行为,我编写了一个测试来控制测试完成的顺序,并在每个任务完成后验证打印输出。
为了帮助测试,我制作了一个附加到
fprintf fmt ...
的格式化程序。但在调用
string ref
之前,不会调用 out 函数。pp_print_flush
:
make_string_ref_formatter
测试:
let make_string_ref_formatter s =
let out b p l =
let current = !s in
let appended = String.sub b p l in
s := current ^ appended
in
Format.make_formatter out (fun _ -> ())
因此,如果测试未刷新,则无法验证输出。但当冲洗关闭漂亮的打印机盒子时,压痕就消失了。
现在,我已经更改了期望以匹配这种不良行为,但我真的希望测试能够描述
实际预期输出。
对于第二个 hackish 选项,需要记住的重要一点是,如果打印队列中没有未知大小的令牌,则
let s = ref "" in
let fmt = make_string_ref_formatter s in
let p1, r1 = Lwt.wait () in
let p2, r2 = Lwt.wait () in
let p3, r3 = Lwt.wait () in
(* Setup test functions for these delayed promises, and run the test runner ... *)
Lwt.wakeup r3 ();
!s |> should (equal_string "");
Lwt.wakeup r1 ();
(* The assertion fails if I don't flush the formatter here *)
Format.pp_print_flush fmt ();
!s |> should (equal_string "• ctx\n ✔ 1\n ");
Lwt.wakeup r2 ();
(* Flush is not necessary in tests, the test runner has completed and flushed *)
(* But the assertion fails because the boxes were reset, so the last item is not indented *)
!s |> should (equal_string "• ctx\n ✔ 1\n ✔ 2\n ✔ 3");
格式化引擎始终直接打印到低级设备。换句话说,如果需要刷新才能看到内容,格式化引擎仍在尝试确定下一个标记的大小。这也意味着强制输出的一种方法是将打印队列的当前大小设置为+无穷大
Format
在
let large_size = 1_000_000 (*ideally Format.pp_infinity when available*) in
Format.fprintf ppf "@<%n>%s" large_size ""
格式化程序上“打印”
""
,就好像其大小为 ppf
。小备注:您的 large_size
是
make_string_ref_formatter
的性能较差的实现。