mirror of
https://github.com/c-cube/moonpool.git
synced 2025-12-06 03:05:30 -05:00
try to make test more deterministic
This commit is contained in:
parent
a2ea24551b
commit
62770a87b5
2 changed files with 140 additions and 94 deletions
|
|
@ -1,60 +1,61 @@
|
||||||
============
|
============
|
||||||
start
|
start
|
||||||
wait for subs
|
1: wait for subs
|
||||||
await fiber 0
|
1.0.0: await fiber 0
|
||||||
cur fiber is some: true
|
1.0.1: cur fiber[0] is some: true
|
||||||
cur fiber is some: true
|
1.0.2: cur fiber[0] is some: true
|
||||||
res 0 = 0
|
1.0.3: res 0 = 0
|
||||||
await fiber 1
|
1.1.0: await fiber 1
|
||||||
cur fiber is some: true
|
1.1.1: cur fiber[1] is some: true
|
||||||
cur fiber is some: true
|
1.1.2: cur fiber[1] is some: true
|
||||||
res 1 = 1
|
1.1.3: res 1 = 1
|
||||||
await fiber 2
|
1.2.0: await fiber 2
|
||||||
cur fiber is some: true
|
1.2.1: cur fiber[2] is some: true
|
||||||
cur fiber is some: true
|
1.2.2: cur fiber[2] is some: true
|
||||||
res 2 = 2
|
1.2.3: res 2 = 2
|
||||||
await fiber 3
|
1.3.0: await fiber 3
|
||||||
cur fiber is some: true
|
1.3.1: cur fiber[3] is some: true
|
||||||
cur fiber is some: true
|
1.3.2: cur fiber[3] is some: true
|
||||||
res 3 = 3
|
1.3.3: res 3 = 3
|
||||||
await fiber 4
|
1.4.0: await fiber 4
|
||||||
cur fiber is some: true
|
1.4.1: cur fiber[4] is some: true
|
||||||
cur fiber is some: true
|
1.4.2: cur fiber[4] is some: true
|
||||||
res 4 = 4
|
1.4.3: res 4 = 4
|
||||||
main fiber done
|
2: main fiber done
|
||||||
other fib done
|
3: other fib done
|
||||||
main fiber exited
|
4: main fiber exited
|
||||||
============
|
============
|
||||||
start
|
start
|
||||||
wait for subs
|
1: start fibers
|
||||||
fiber 0 resolved as ok
|
1.7.1: I'm fiber 7 and I'm about to…
|
||||||
await fiber 0
|
1.8.1: sub-fiber 8 was cancelled
|
||||||
res 0 = 0
|
1.9.1: sub-fiber 9 was cancelled
|
||||||
await fiber 1
|
2.0: fiber 0 resolved as ok
|
||||||
fiber 1 resolved as ok
|
2.1: fiber 1 resolved as ok
|
||||||
res 1 = 1
|
2.2: fiber 2 resolved as ok
|
||||||
await fiber 2
|
2.3: fiber 3 resolved as ok
|
||||||
fiber 2 resolved as ok
|
2.4: fiber 4 resolved as ok
|
||||||
res 2 = 2
|
2.5: fiber 5 resolved as ok
|
||||||
await fiber 3
|
2.6: fiber 6 resolved as ok
|
||||||
fiber 3 resolved as ok
|
2.7: fiber 7 resolved as error
|
||||||
res 3 = 3
|
2.8: fiber 8 resolved as error
|
||||||
await fiber 4
|
2.9: fiber 9 resolved as error
|
||||||
fiber 4 resolved as ok
|
3: wait for subs
|
||||||
res 4 = 4
|
4: await fiber 0
|
||||||
await fiber 5
|
5: res 0 = 0
|
||||||
fiber 5 resolved as ok
|
6: await fiber 1
|
||||||
res 5 = 5
|
7: res 1 = 1
|
||||||
await fiber 6
|
8: await fiber 2
|
||||||
fiber 6 resolved as ok
|
9: res 2 = 2
|
||||||
res 6 = 6
|
10: await fiber 3
|
||||||
await fiber 7
|
11: res 3 = 3
|
||||||
I'm fiber 7 and I'm about to…
|
12: await fiber 4
|
||||||
sub-fiber 8 was cancelled
|
13: res 4 = 4
|
||||||
fiber 8 resolved as error
|
14: await fiber 5
|
||||||
sub-fiber 9 was cancelled
|
15: res 5 = 5
|
||||||
fiber 9 resolved as error
|
16: await fiber 6
|
||||||
main fiber result: error Failure("oh no!")
|
17: res 6 = 6
|
||||||
fiber 7 resolved as error
|
18: await fiber 7
|
||||||
main fib failed with "oh no!"
|
19: main fiber result: error Failure("oh no!")
|
||||||
main fiber exited
|
20: main fib failed with "oh no!"
|
||||||
|
21: main fiber exited
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,55 @@
|
||||||
open Moonpool
|
open! Moonpool
|
||||||
|
module A = Atomic
|
||||||
module F = Moonpool_fib.Fiber
|
module F = Moonpool_fib.Fiber
|
||||||
|
|
||||||
let ( let@ ) = ( @@ )
|
let ( let@ ) = ( @@ )
|
||||||
let runner = Ws_pool.create ~num_threads:8 ()
|
let runner = Ws_pool.create ~num_threads:8 ()
|
||||||
let lock = Lock.create ()
|
|
||||||
|
|
||||||
let logf fmt =
|
module TS = struct
|
||||||
Printf.ksprintf
|
type t = int list
|
||||||
(fun s ->
|
|
||||||
let out = stdout in
|
let show (s : t) = String.concat "." @@ List.map string_of_int s
|
||||||
(let@ () = Lock.with_ lock in
|
let init = [ 0 ]
|
||||||
output_string out s);
|
|
||||||
flush out)
|
let next_ = function
|
||||||
fmt
|
| [] -> [ 0 ]
|
||||||
|
| n :: tl -> (n + 1) :: tl
|
||||||
|
|
||||||
|
let tick (t : t ref) = t := next_ !t
|
||||||
|
|
||||||
|
let tick_get t =
|
||||||
|
tick t;
|
||||||
|
!t
|
||||||
|
end
|
||||||
|
|
||||||
|
(* more deterministic logging of events *)
|
||||||
|
module Log_ = struct
|
||||||
|
let events : (TS.t * string) list A.t = A.make []
|
||||||
|
|
||||||
|
let add_event t msg : unit =
|
||||||
|
while
|
||||||
|
let old = A.get events in
|
||||||
|
not (A.compare_and_set events old ((t, msg) :: old))
|
||||||
|
do
|
||||||
|
()
|
||||||
|
done
|
||||||
|
|
||||||
|
let logf t fmt = Printf.ksprintf (add_event t) fmt
|
||||||
|
|
||||||
|
let print_and_clear () =
|
||||||
|
let l =
|
||||||
|
A.exchange events []
|
||||||
|
|> List.map (fun (ts, msg) -> List.rev ts, msg)
|
||||||
|
|> List.sort Stdlib.compare
|
||||||
|
in
|
||||||
|
List.iter (fun (ts, msg) -> Printf.printf "%s: %s\n" (TS.show ts) msg) l
|
||||||
|
end
|
||||||
|
|
||||||
|
let logf = Log_.logf
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
logf "============\nstart\n";
|
Printf.printf "============\nstart\n";
|
||||||
|
let clock = ref TS.init in
|
||||||
let fib =
|
let fib =
|
||||||
F.spawn_top ~on:runner @@ fun () ->
|
F.spawn_top ~on:runner @@ fun () ->
|
||||||
let subs =
|
let subs =
|
||||||
|
|
@ -28,85 +62,96 @@ let () =
|
||||||
ignore
|
ignore
|
||||||
(F.spawn_link ~protect:false @@ fun () ->
|
(F.spawn_link ~protect:false @@ fun () ->
|
||||||
Thread.delay 0.4;
|
Thread.delay 0.4;
|
||||||
logf "other fib done\n%!"
|
TS.tick clock;
|
||||||
|
logf !clock "other fib done"
|
||||||
: _ F.t);
|
: _ F.t);
|
||||||
logf "wait for subs\n%!";
|
|
||||||
|
logf (TS.tick_get clock) "wait for subs";
|
||||||
List.iteri
|
List.iteri
|
||||||
(fun i f ->
|
(fun i f ->
|
||||||
logf "await fiber %d\n%!" i;
|
let clock = ref (0 :: i :: !clock) in
|
||||||
logf "cur fiber is some: %b\n%!"
|
logf !clock "await fiber %d" i;
|
||||||
|
logf (TS.tick_get clock) "cur fiber[%d] is some: %b" i
|
||||||
(Option.is_some @@ F.Private_.get_cur ());
|
(Option.is_some @@ F.Private_.get_cur ());
|
||||||
let res = F.await f in
|
let res = F.await f in
|
||||||
logf "cur fiber is some: %b\n%!"
|
logf (TS.tick_get clock) "cur fiber[%d] is some: %b" i
|
||||||
(Option.is_some @@ F.Private_.get_cur ());
|
(Option.is_some @@ F.Private_.get_cur ());
|
||||||
Thread.delay 0.000_01;
|
|
||||||
F.yield ();
|
F.yield ();
|
||||||
logf "res %d = %d\n%!" i res)
|
logf (TS.tick_get clock) "res %d = %d" i res)
|
||||||
subs;
|
subs;
|
||||||
logf "main fiber done\n%!"
|
logf (TS.tick_get clock) "main fiber done"
|
||||||
in
|
in
|
||||||
|
|
||||||
Fut.wait_block_exn @@ F.res fib;
|
Fut.wait_block_exn @@ F.res fib;
|
||||||
logf "main fiber exited\n%!";
|
logf (TS.tick_get clock) "main fiber exited";
|
||||||
|
Log_.print_and_clear ();
|
||||||
()
|
()
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
(* same but now, cancel *)
|
(* same but now, cancel one of the sub-fibers *)
|
||||||
logf "============\nstart\n";
|
Printf.printf "============\nstart\n";
|
||||||
|
|
||||||
|
let clock = ref TS.init in
|
||||||
let fib =
|
let fib =
|
||||||
F.spawn_top ~on:runner @@ fun () ->
|
F.spawn_top ~on:runner @@ fun () ->
|
||||||
let@ () =
|
let@ () =
|
||||||
F.with_self_cancel_callback (fun ebt ->
|
F.with_self_cancel_callback (fun ebt ->
|
||||||
logf "main fiber cancelled with %s\n%!" @@ Exn_bt.show ebt)
|
logf (TS.tick_get clock) "main fiber cancelled with %s"
|
||||||
|
@@ Exn_bt.show ebt)
|
||||||
in
|
in
|
||||||
|
|
||||||
|
logf (TS.tick_get clock) "start fibers";
|
||||||
let subs =
|
let subs =
|
||||||
List.init 10 (fun i ->
|
List.init 10 (fun i ->
|
||||||
|
let clock = ref (0 :: i :: !clock) in
|
||||||
F.spawn_link ~protect:false @@ fun () ->
|
F.spawn_link ~protect:false @@ fun () ->
|
||||||
let@ () =
|
let@ () =
|
||||||
F.with_self_cancel_callback (fun _ ->
|
F.with_self_cancel_callback (fun _ ->
|
||||||
logf "sub-fiber %d was cancelled\n%!" i)
|
logf (TS.tick_get clock) "sub-fiber %d was cancelled" i)
|
||||||
in
|
in
|
||||||
Thread.delay (float i *. 0.001);
|
Thread.delay (float i *. 0.001);
|
||||||
F.yield ();
|
F.yield ();
|
||||||
if i = 7 then (
|
if i = 7 then (
|
||||||
logf "I'm fiber %d and I'm about to…\n%!" i;
|
logf (TS.tick_get clock) "I'm fiber %d and I'm about to…" i;
|
||||||
failwith "oh no!"
|
failwith "oh no!"
|
||||||
);
|
);
|
||||||
i)
|
i)
|
||||||
in
|
in
|
||||||
|
|
||||||
|
let post = TS.tick_get clock in
|
||||||
List.iteri
|
List.iteri
|
||||||
(fun i fib ->
|
(fun i fib ->
|
||||||
F.on_result fib (function
|
F.on_result fib (function
|
||||||
| Ok _ -> logf "fiber %d resolved as ok\n%!" i
|
| Ok _ -> logf (i :: post) "fiber %d resolved as ok" i
|
||||||
| Error _ -> logf "fiber %d resolved as error\n%!" i))
|
| Error _ -> logf (i :: post) "fiber %d resolved as error" i))
|
||||||
subs;
|
subs;
|
||||||
|
|
||||||
ignore
|
ignore
|
||||||
(F.spawn_link ~protect:false @@ fun () ->
|
(F.spawn_link ~protect:false @@ fun () ->
|
||||||
Thread.delay 0.2;
|
Thread.delay 0.2;
|
||||||
logf "other fib done\n%!"
|
logf (TS.tick_get clock) "other fib done"
|
||||||
: _ F.t);
|
: _ F.t);
|
||||||
|
|
||||||
logf "wait for subs\n%!";
|
logf (TS.tick_get clock) "wait for subs";
|
||||||
List.iteri
|
List.iteri
|
||||||
(fun i f ->
|
(fun i f ->
|
||||||
logf "await fiber %d\n%!" i;
|
logf (TS.tick_get clock) "await fiber %d" i;
|
||||||
let res = F.await f in
|
let res = F.await f in
|
||||||
logf "res %d = %d\n%!" i res)
|
logf (TS.tick_get clock) "res %d = %d" i res)
|
||||||
subs;
|
subs;
|
||||||
logf "yield\n%!";
|
logf (TS.tick_get clock) "yield";
|
||||||
F.yield ();
|
F.yield ();
|
||||||
logf "yielded\n%!";
|
logf (TS.tick_get clock) "yielded";
|
||||||
logf "main fiber done\n%!"
|
logf (TS.tick_get clock) "main fiber done"
|
||||||
in
|
in
|
||||||
|
|
||||||
F.on_result fib (function
|
F.on_result fib (function
|
||||||
| Ok () -> logf "main fiber result: ok\n%!"
|
| Ok () -> logf (TS.tick_get clock) "main fiber result: ok"
|
||||||
| Error ebt -> logf "main fiber result: error %s\n%!" (Exn_bt.show ebt));
|
| Error ebt ->
|
||||||
|
logf (TS.tick_get clock) "main fiber result: error %s" (Exn_bt.show ebt));
|
||||||
|
|
||||||
(try Fut.wait_block_exn @@ F.res fib
|
(try Fut.wait_block_exn @@ F.res fib
|
||||||
with Failure msg -> logf "main fib failed with %S\n%!" msg);
|
with Failure msg -> logf (TS.tick_get clock) "main fib failed with %S" msg);
|
||||||
logf "main fiber exited\n%!";
|
logf (TS.tick_get clock) "main fiber exited";
|
||||||
|
Log_.print_and_clear ();
|
||||||
()
|
()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue