package bonsai

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file callback_tests.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
open! Core
open! Async_kernel
open Bonsai_web

let schedule_and_print_response callback =
  Vdom.Effect.Expert.handle_non_dom_event_exn
    (let%bind.Effect r = callback in
     print_s [%message "this is userdata" (r : int)];
     Vdom.Effect.Ignore)
;;

let%expect_test "synchronous callback" =
  let increment = Effect.of_sync_fun (fun a -> a + 1) in
  schedule_and_print_response (increment 1);
  [%expect {| ("this is userdata" (r 2)) |}]
;;

let%expect_test "bind and return" =
  let open Effect.Let_syntax in
  let increment = Effect.of_sync_fun (fun a -> a + 1) in
  let callback =
    let%bind a = increment 1 in
    let%bind b = increment 2 in
    return (a + b)
  in
  schedule_and_print_response callback;
  [%expect {| ("this is userdata" (r 5)) |}]
;;

let%expect_test "of_deferred_fun" =
  (* Note that there is no module that can drive the async_kernel scheduler that is
     compatible with javascript tests. The only way therefore of testing of_deferred_fun
     is to instruct the scheduler ourselves. *)
  let open Async_kernel in
  let state = Int.Table.create () in
  let callback =
    Effect.of_deferred_fun (fun n ->
      Ivar.read (Hashtbl.find_or_add state n ~default:Ivar.create))
  in
  schedule_and_print_response (callback 1);
  schedule_and_print_response (callback 2);
  schedule_and_print_response (callback 3);
  [%expect {||}];
  print_s [%sexp (Hashtbl.keys state : int list)];
  [%expect {| (1 3 2) |}];
  Ivar.fill (Hashtbl.find_and_remove state 1 |> Option.value_exn) 42;
  (* Nothing yet, because the scheduler has not run a cycle *)
  [%expect {||}];
  (* Tell async_kernel to run a cycle manually to see that the effect is responded to *)
  Async_kernel_scheduler.Private.run_cycles_until_no_jobs_remain ();
  [%expect {| ("this is userdata" (r 42)) |}];
  Hashtbl.iteri state ~f:(fun ~key:query ~data:ivar -> Ivar.fill ivar (10 * query));
  Async_kernel_scheduler.Private.run_cycles_until_no_jobs_remain ();
  [%expect {|
    ("this is userdata" (r 20))
    ("this is userdata" (r 30)) |}]
;;

let%expect_test "svar" =
  let in_flight_query_and_response = ref None in
  let callback =
    Effect.For_testing.of_svar_fun (fun query ->
      let svar = Effect.For_testing.Svar.create () in
      in_flight_query_and_response := Some (query, svar);
      svar)
  in
  schedule_and_print_response (callback 1);
  [%expect {||}];
  let query, response = Option.value_exn !in_flight_query_and_response in
  Effect.For_testing.Svar.fill_if_empty response (query + 1);
  [%expect {| ("this is userdata" (r 2)) |}]
;;

let%expect_test "Query_response_tracker" =
  let qrt = Effect.For_testing.Query_response_tracker.create () in
  let callback = Effect.For_testing.of_query_response_tracker qrt in
  schedule_and_print_response (callback 1);
  schedule_and_print_response (callback 2);
  schedule_and_print_response (callback 3);
  [%expect {||}];
  Effect.For_testing.Query_response_tracker.maybe_respond qrt ~f:(fun i ->
    if i % 2 = 0 then Respond (10 * i) else No_response_yet);
  [%expect {| ("this is userdata" (r 20)) |}];
  printf
    !"%{sexp: int list}"
    (Effect.For_testing.Query_response_tracker.queries_pending_response qrt);
  [%expect {| (3 1) |}];
  Effect.For_testing.Query_response_tracker.maybe_respond qrt ~f:(fun i ->
    Respond (20 * i));
  [%expect {|
    ("this is userdata" (r 60))
    ("this is userdata" (r 20)) |}];
  printf
    !"%{sexp: int list}"
    (Effect.For_testing.Query_response_tracker.queries_pending_response qrt);
  [%expect {| () |}]
;;
OCaml

Innovation. Community. Security.