test.ml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. open Base
  2. open OUnit2
  3. open Helper
  4. module Logging_graphics : Ax.React_loop.GRAPHICS_LAYER = struct
  5. let clear () = log "clear"
  6. let rect aabb color =
  7. logf "rect{%s;%s}"
  8. (Ax.Math.AABB.to_string aabb)
  9. (Ax.Color.to_string color)
  10. end
  11. ;;
  12. run_test_tt_main @@
  13. test_list
  14. [
  15. ts (module Int)
  16. ["math1", 3 + 4, 7;
  17. "math2", 8 * 2, 16];
  18. ts (module IntOption)
  19. ["opt1", Some(3), Some(1 + 2);
  20. "opt2", None, None];
  21. t_log "hello_world" ["hello";"world"]
  22. (fun () -> log "hello"; logf "w%sld" "or");
  23. tfails
  24. [ "fail_world", Failure("ello"),
  25. (fun () -> failwith "hello world")
  26. ; "math3", Division_by_zero,
  27. (fun () -> 3 / (2 - 4 / 2)) ];
  28. ts (module ListUnordered_(Int))
  29. ["uo1", [1;2;3], [3;2;1];
  30. "uo2", [1;3;4;3], [3;3;1;4];
  31. "uo3", [], []];
  32. "Draw_tree">:::begin
  33. let open Ax.Color in
  34. let open Ax.Math in
  35. let open Ax.Draw_tree in
  36. let t_render name (expected : Draw.t list) (tree : tree) =
  37. t name (module List_(Draw))
  38. expected
  39. (Sequence.to_list (render tree))
  40. in
  41. let rects = [ figure (Rect({w=30;h=40}, red))
  42. ; figure (Rect({w=70;h=20}, blue))
  43. ; figure (Rect({w=10;h=50}, black)) ] in
  44. [ t_render "H_rects"
  45. [ Rect({bx=0;by=5;bw=30;bh=40},red)
  46. ; Rect({bx=30;by=15;bw=70;bh=20},blue)
  47. ; Rect({bx=100;by=0;bw=10;bh=50},black) ]
  48. (arm `H rects)
  49. ; t_render "V_rects"
  50. [ Rect({bx=20;by=0;bw=30;bh=40},red)
  51. ; Rect({bx=0;by=40;bw=70;bh=20},blue)
  52. ; Rect({bx=30;by=60;bw=10;bh=50},black) ]
  53. (arm `V rects)
  54. ; t_render "H+V"
  55. [ Rect({bx=0;by=35;bw=20;bh=20},red)
  56. ; Rect({bx=25;by=0;bw=30;bh=40},blue)
  57. ; Rect({bx=20;by=40;bw=40;bh=50},green)
  58. ; Rect({bx=60;by=30;bw=10;bh=10},yellow)
  59. ; Rect({bx=60;by=40;bw=10;bh=20},cyan) ]
  60. (arm `H [ figure (Rect({w=20;h=20}, red))
  61. ; arm `V [ figure (Rect({w=30;h=40}, blue))
  62. ; figure (Rect({w=40;h=50}, green)) ]
  63. ; arm `V [ figure (Rect({w=10;h=10}, yellow))
  64. ; figure (Rect({w=10;h=20}, cyan)) ] ])
  65. ; t_render "ignore_captures"
  66. (Sequence.to_list (render (arm `H rects)))
  67. (capture (Ax.Event.Id.gen ()) (arm `H rects))
  68. ; t_render "ignore_captures'"
  69. (Sequence.to_list (render (arm `H rects)))
  70. (arm `H @@ List.map rects ~f:(fun r -> capture (Ax.Event.Id.gen ()) r))
  71. ]
  72. end;
  73. "Draw_tree.capture_point">:begin
  74. let open Ax.Color in
  75. let open Ax.Math in
  76. let open Ax.Draw_tree in
  77. let r10x10 = figure (Rect({w=10;h=10},red)) in
  78. let id1, id2 = Ax.Event.Id.gen (), Ax.Event.Id.gen () in
  79. let cap x y t = capture_point ~pos:{x;y} t in
  80. ts (module List_(Ax.Event.Id))
  81. [ "empty",
  82. [], cap 5 5 @@ arm `H []
  83. ; "didnt_hit",
  84. [], cap 5 5 @@ arm `H [ r10x10 ; capture id1 r10x10 ]
  85. ; "did_hit",
  86. [id1], cap 15 5 @@ arm `H [ r10x10 ; capture id1 r10x10 ]
  87. ; "hit_nested",
  88. [id1;id2], cap 15 5 @@ capture id1 (arm `H [ r10x10 ; capture id2 r10x10 ])
  89. ; "hit_partial",
  90. [id1], cap 5 5 @@ capture id1 (arm `H [ r10x10 ; capture id2 r10x10 ])
  91. ]
  92. end;
  93. "Generic_tree.Zipper">:begin
  94. let open Ax.Private.Generic_tree in
  95. let module Z = Ax.Private.Generic_tree.Zipper in
  96. let module Tree = struct
  97. type nonrec t = (char, string) t
  98. include Make_show_eq(Char)(String)
  99. end in
  100. let lf_x = Leaf("xx") in let lf_y = Leaf("yy") in let lf_z = Leaf("zz") in
  101. let build mid = Arm('P', [ lf_x ; Arm('Q', [ lf_y ; lf_z ; mid ]) ; lf_z ; lf_y ]) in
  102. let zip = Z.(build lf_x |> of_tree |> down_exn 1 |> down_exn 2) in
  103. ts (module Tree)
  104. [ "get_focus",
  105. lf_x,
  106. Z.get zip
  107. ; "set_focus",
  108. build lf_y,
  109. Z.(zip |> set lf_y |> to_tree)
  110. ; "set_up",
  111. Arm('P', [lf_x;lf_y;lf_z;lf_y]),
  112. Z.(zip |> up_exn |> set lf_y |> to_tree)
  113. ; "side_zero",
  114. build lf_x,
  115. Z.(zip |> side_exn 0 |> to_tree)
  116. ; "side_positive",
  117. Arm('P', [ lf_x ; Arm('Q', [lf_y;lf_z;lf_z]) ; lf_z ; lf_y ]),
  118. Z.(of_tree (build lf_x) |> down_exn 1 |> down_exn 0 |> side_exn 2 |> set lf_z |> to_tree)
  119. ; "side_negative",
  120. Arm('P', [ lf_x ; Arm('Q', [lf_x;lf_z;lf_x]) ; lf_z ; lf_y ]),
  121. Z.(of_tree (build lf_x) |> down_exn 1 |> down_exn 2 |> side_exn ~-2 |> set lf_x |> to_tree)
  122. ]
  123. end;
  124. "Draw_tree.Path">:begin
  125. let open Ax.Draw_tree in
  126. ts (module Bool) @@
  127. List.map ~f:(fun (n,x,y,cmp) -> (n, true, (cmp (Path.compare x y) 0)))
  128. [ "cmp1", [], [], (=)
  129. ; "cmp2", [1], [], (<)
  130. ; "cmp3", [], [1], (>)
  131. ; "cmp4", [2;3], [2;3], (=)
  132. ; "cmp5", [2;3], [2;4], (<)
  133. ; "cmp6", [2;7], [2;4], (>) ]
  134. end;
  135. "Draw_tree.update">:begin
  136. let open Ax.Color in
  137. let open Ax.Draw_tree in
  138. let f1 = Rect({w=1;h=1}, red) in
  139. let f2 = Rect({w=2;h=2}, blue) in
  140. let f3 = Rect({w=3;h=3}, white) in
  141. let f4 = Rect({w=4;h=4}, black) in
  142. let f5 = Rect({w=5;h=5}, red) in
  143. let r1 = figure f1 in let r2 = figure f2 in
  144. let r3 = figure f3 in let r4 = figure f4 in let r5 = figure f5 in
  145. let t0 = arm `H [ r1 ; arm `V [ r2 ; r3 ; arm `H [r4;r5] ] ] in
  146. let t1 = arm `H [ r4 ; arm `V [ r2 ; r3 ; arm `H [r4;r5] ] ] in
  147. let t2 = arm `H [ r1 ; arm `V [ r2 ; r3 ; arm `H [r1;r5] ] ] in
  148. let t3 = arm `H [ r1 ; arm `V [ r2 ; r5 ; arm `H [r1;r5] ] ] in
  149. let t4 = arm `H [ r1 ; arm `V [ r2 ; r3 ; arm `H [r1;r2] ] ] in
  150. ts (module Ax.Draw_tree) @@
  151. List.map ~f:(fun (n,t',ps) -> (n, t', apply_updates_exn (Sequence.of_list ps) t0))
  152. [ "root", r1, [ [], f1 ]
  153. ; "shallow", t1, [ [0], f4 ]
  154. ; "deep", t2, [ [1;2;0], f1 ]
  155. ; "two", t3, [ [1;1], f5 ; [1;2;0], f1 ]
  156. ; "two'", t3, [ [1;2;0], f1 ; [1;1], f5 ]
  157. ; "adjacent", t4, [ [1;2;0], f1 ; [1;2;1], f2 ] ]
  158. end;
  159. "Source">:::begin
  160. let open Ax.Source in
  161. let src1 = create () in
  162. let src2 = create () in
  163. [ tfail "empty_state" (Failure("source unset"))
  164. (fun () -> State.(get_exn src1 empty))
  165. ; t "not_equal" (module Bool)
  166. false
  167. (equal src1 src2)
  168. ; t "set_get" (module Int)
  169. 5
  170. State.(get_exn src1 (set src1 5 empty))
  171. ; t "set_set_get" (module Int)
  172. 8
  173. State.(get_exn src1 (set src1 8 (set src1 5 empty)))
  174. ; t "set_other_get" (module Int)
  175. 5
  176. State.(get_exn src1 (set src2 8 (set src1 5 empty)))
  177. ]
  178. end;
  179. "Component.mount">:::begin
  180. let module T = Ax.Draw_tree in
  181. let module C = Ax.Component in
  182. let module B = Ax.Behavior in
  183. let module S = Ax.Source in
  184. let module E = Ax.Event in
  185. let module Sinks_ = Map_(S)(ListUnordered_(T.Path)) in
  186. let open Ax.Color in
  187. let open Ax.Math in
  188. let r1 = C.rect @@ B.const ({w=1;h=1}, red) in
  189. let r2 = C.rect @@ B.const ({w=2;h=2}, blue) in
  190. let r3 = C.rect @@ B.const ({w=3;h=3}, white) in
  191. let r_dyn b = C.rect @@ B.(b >>| fun t -> {w=t;h=t}, black) in
  192. let state = S.State.of_time 25 in
  193. [ t "static" (module Ax.Draw_tree)
  194. C.(let _, _, t = mount state @@
  195. arm `H [ r1
  196. ; arm `V [ r2
  197. ; r3 ] ]
  198. in t)
  199. T.(arm `H [ figure (Rect({w=1;h=1}, red))
  200. ; arm `V [ figure (Rect({w=2;h=2}, blue))
  201. ; figure (Rect({w=3;h=3}, white)) ] ])
  202. ; "time">:::begin
  203. let _, callbacks, tree =
  204. C.(mount state @@
  205. arm `H
  206. [ arm `V
  207. [ r1
  208. ; r_dyn B.time ]
  209. ; r2
  210. ])
  211. in
  212. [ t "init_tree" (module Ax.Draw_tree)
  213. T.(arm `H [ arm `V [ figure (Rect({w=1;h=1}, red))
  214. ; figure (Rect({w=25;h=25}, black)) ]
  215. ; figure (Rect({w=2;h=2}, blue)) ])
  216. tree
  217. ; t "sinks" (module Sinks_)
  218. (Map.of_alist_exn (module S)
  219. [ S.time, [ [0;1] ] ])
  220. (Map.map callbacks.sinks ~f:(List.map ~f:fst))
  221. ; t "handlers" (module ListUnordered_(E.Id))
  222. []
  223. (Map.keys callbacks.handlers) ]
  224. end
  225. ; "events">:::begin
  226. let src = S.Private.next_id ~diff:0 in
  227. let eid1 = E.Id.Private.next_id ~diff:0 in
  228. let eid2 = E.Id.Private.next_id ~diff:1 in
  229. let init_state, callbacks, tree =
  230. C.(mount state @@
  231. arm `H
  232. [ arm `V
  233. [ r1
  234. ; fold ~init:57 ~f:(fun _ -> Int.succ)
  235. r_dyn ]
  236. ; callback ~f:ignore r3
  237. ])
  238. in
  239. [ t "init_tree" (module Ax.Draw_tree)
  240. T.(arm `H [ arm `V [ figure (Rect({w=1;h=1}, red))
  241. ; capture eid1
  242. (figure (Rect({w=57;h=57}, black))) ]
  243. ; capture eid2
  244. (figure (Rect({w=3;h=3}, white))) ])
  245. tree
  246. ; t "init_state" (module Int)
  247. 57 (S.State.get_exn src init_state)
  248. ; t "sinks" (module Sinks_)
  249. (Map.of_alist_exn (module S)
  250. [ src, [ [0;1;0] ] ])
  251. (Map.map callbacks.sinks ~f:(List.map ~f:fst))
  252. ; t "handlers" (module ListUnordered_(E.Id))
  253. [eid1;eid2]
  254. (Map.keys callbacks.handlers)
  255. ]
  256. end;
  257. ]
  258. end;
  259. "React_loop">:::begin
  260. let open Ax.Color in
  261. let open Ax.Math in
  262. let open Ax.Component in
  263. let module B = Ax.Behavior in
  264. let current_cb = ref ignore in
  265. let current_time = ref 0 in
  266. let tick () = Int.incr current_time ; !current_cb Ax.React_loop.Tick in
  267. let click x y = !current_cb (Ax.React_loop.Click {x;y}) in
  268. let exit () = !current_cb Ax.React_loop.Exit in
  269. let module RL =
  270. Ax.React_loop.Make
  271. (struct
  272. type callback_id = unit
  273. let bind_callback f = current_cb := f
  274. let unregister () = current_cb := ignore ; logf "unreg"
  275. let poll_time_ms () = 1000 * !current_time
  276. end)
  277. (Logging_graphics)
  278. in
  279. [ t_log "no_callbacks"
  280. [ "clear" ; "rect{<0,0 4x4>;#0ff}" ; "unreg" ]
  281. (fun () -> RL.run (rect @@ B.const ({w=4;h=4}, cyan))
  282. ; tick ()
  283. ; tick ()
  284. ; exit ())
  285. ; t_log "simple"
  286. [ "clear" ; "rect{<0,0 25x26>;#0ff}"
  287. ; "clear" ; "rect{<0,0 26x27>;#0ff}"
  288. ; "clear" ; "rect{<0,0 27x28>;#0ff}"
  289. ; "unreg" ]
  290. (fun () -> current_time := 25
  291. ; RL.run (rect B.(time >>| fun t -> {w=t;h=t+1}, cyan))
  292. ; tick ()
  293. ; tick ()
  294. ; exit ())
  295. ; t_log "click"
  296. [ "clear" ; "rect{<0,0 25x30>;#0ff}"
  297. ; "CLICK <5,5>" ; "CLICK <15,5>"
  298. ; "unreg" ]
  299. (fun () ->
  300. let f = function Ax.Event.Click(pos) ->
  301. logf "CLICK %s" (Pos.to_string pos)
  302. in
  303. RL.run (callback ~f (rect (B.const ({w=25;h=30}, cyan))))
  304. ; click 5 5 ; click 28 5 ; click 15 5 ; click 5 37
  305. ; exit ())
  306. ; t_log "click+state"
  307. [ "clear" ; "rect{<0,0 25x30>;#0ff}"
  308. ; "clear" ; "rect{<0,0 26x31>;#0ff}"
  309. ; "clear" ; "rect{<0,0 27x32>;#0ff}"
  310. ; "unreg" ]
  311. (fun () ->
  312. let inc _ n = n + 1 in
  313. let comp n = rect B.(n >>| fun n -> ({w=n;h=n+5}, cyan)) in
  314. RL.run (fold ~init:25 ~f:inc comp)
  315. ; click 5 5 ; click 28 5 ; click 15 5 ; click 5 37
  316. ; exit ())
  317. ]
  318. end;
  319. ]