diff --git a/compiler/tests-jsoo/lib-effects/double-translation/dune b/compiler/tests-jsoo/lib-effects-2/dune similarity index 65% rename from compiler/tests-jsoo/lib-effects/double-translation/dune rename to compiler/tests-jsoo/lib-effects-2/dune index c3e273e341..fa95cec71f 100644 --- a/compiler/tests-jsoo/lib-effects/double-translation/dune +++ b/compiler/tests-jsoo/lib-effects-2/dune @@ -22,7 +22,33 @@ ;; TODO: remove once support in ocaml/dune#11222 is released. (compilation_mode whole_program)))) -(copy_files# ../*.ml) +(copy_files# + (only_sources true) + (files ../lib-effects/*.ml)) + +(library + (name jsoo_testsuite_effect2) + (enabled_if + (>= %{ocaml_version} 5)) + (inline_tests + (modes js wasm best)) + (modules + (:standard + \ + assume_no_perform + assume_no_perform_unhandled + assume_no_perform_nested_handler + deep_state + effects)) + (preprocess + (pps ppx_expect))) + +(tests + (build_if + (>= %{ocaml_version} 5)) + (names effects) + (modules effects) + (modes js wasm)) (tests (build_if @@ -31,6 +57,10 @@ assume_no_perform assume_no_perform_unhandled assume_no_perform_nested_handler) + (modules + assume_no_perform + assume_no_perform_unhandled + assume_no_perform_nested_handler) (libraries js_of_ocaml) (action (ignore-outputs diff --git a/compiler/tests-jsoo/lib-effects/dune b/compiler/tests-jsoo/lib-effects/dune index 66df040883..ba160e259d 100644 --- a/compiler/tests-jsoo/lib-effects/dune +++ b/compiler/tests-jsoo/lib-effects/dune @@ -16,10 +16,18 @@ assume_no_perform assume_no_perform_unhandled assume_no_perform_nested_handler - deep_state)) + deep_state + effects)) (preprocess (pps ppx_expect))) +(tests + (build_if + (>= %{ocaml_version} 5)) + (names effects) + (modules effects) + (modes js wasm)) + (tests (build_if (>= %{ocaml_version} 5)) diff --git a/compiler/tests-ocaml/lib-effects/effects.expected b/compiler/tests-jsoo/lib-effects/effects.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/effects.expected rename to compiler/tests-jsoo/lib-effects/effects.expected diff --git a/compiler/tests-jsoo/lib-effects/effects.ml b/compiler/tests-jsoo/lib-effects/effects.ml new file mode 100644 index 0000000000..116ece6475 --- /dev/null +++ b/compiler/tests-jsoo/lib-effects/effects.ml @@ -0,0 +1,295 @@ +[@@@ocaml.warning "-27-32"] + +open Effect +open Effect.Deep + +type _ Effect.t += Xchg : int -> int t + +let comp1 () = + let a = Xchg 0 in + let x = perform a in + let b = Xchg 1 in + let y = perform b in + x + y + +let comp2 () = + let _ = perform (Xchg 0) in + raise Not_found + +let comp3 () = + let _ = perform (Xchg 0) in + int_of_string "fdjsl" + +let handle comp = + (* try*) + Format.printf "%d@." + @@ match_with + comp + () + { retc = (fun x -> x - 30) + ; exnc = (fun _ -> 42) + ; effc = + (fun (type a) (eff : a t) -> + match eff with + | Xchg n -> Some (fun (k : (a, _) continuation) -> continue k (n + 17)) + | _ -> None) + } +(*with Not_found -> assert false*) + +let () = + handle comp1; + handle comp2; + handle comp3 + +type 'a status = + | Complete of 'a + | Suspended of + { msg : int + ; cont : (int, 'a status) continuation + } + +let step (f : unit -> 'a) () : 'a status = + match_with + f + () + { retc = (fun v -> Complete v) + ; exnc = raise + ; effc = + (fun (type a) (eff : a t) -> + match eff with + | Xchg msg -> Some (fun (cont : (a, _) continuation) -> Suspended { msg; cont }) + | _ -> None) + } + +let rec run_both a b = + match a (), b () with + | Complete va, Complete vb -> va, vb + | Suspended { msg = m1; cont = k1 }, Suspended { msg = m2; cont = k2 } -> + run_both (fun () -> continue k1 m2) (fun () -> continue k2 m1) + | _ -> failwith "Improper synchronization" + +let comp2 () = perform (Xchg 21) * perform (Xchg 21) + +let () = + let x, y = run_both (step comp1) (step comp2) in + Format.printf ">> %d %d@." x y + +type _ Effect.t += Fork : (unit -> unit) -> unit t | Yield : unit t + +let fork f = perform (Fork f) + +let yield () = perform Yield + +let xchg v = perform (Xchg v) + +(* A concurrent round-robin scheduler *) +let run (main : unit -> unit) : unit = + let exchanger = ref None in + (* waiting exchanger *) + let run_q = Queue.create () in + (* scheduler queue *) + let enqueue k v = + let task () = continue k v in + Queue.push task run_q + in + let dequeue () = + if Queue.is_empty run_q + then () (* done *) + else + let task = Queue.pop run_q in + task () + in + let rec spawn (f : unit -> unit) : unit = + match_with + f + () + { retc = dequeue + ; exnc = + (fun e -> + print_endline (Printexc.to_string e); + dequeue ()) + ; effc = + (fun (type a) (eff : a t) -> + match eff with + | Yield -> + Some + (fun (k : (a, unit) continuation) -> + enqueue k (); + dequeue ()) + | Fork f -> + Some + (fun (k : (a, unit) continuation) -> + enqueue k (); + spawn f) + | Xchg n -> + Some + (fun (k : (int, unit) continuation) -> + match !exchanger with + | Some (n', k') -> + exchanger := None; + enqueue k' n; + continue k n' + | None -> + exchanger := Some (n, k); + dequeue ()) + | _ -> None) + } + in + spawn main + +let _ = + run (fun _ -> + fork (fun _ -> + Format.printf "[t1] Sending 0@."; + let v = xchg 0 in + Format.printf "[t1] received %d@." v); + fork (fun _ -> + Format.printf "[t2] Sending 1@."; + let v = xchg 1 in + Format.printf "[t2] received %d@." v)) + +(*****) + +type _ Effect.t += E : string t | F : string t + +let foo () = perform F ^ " " ^ perform E ^ " " ^ perform F + +let bar () = + try_with + foo + () + { effc = + (fun (type a) (eff : a t) -> + match eff with + | E -> Some (fun (k : (a, _) continuation) -> continue k "Coucou!") + | _ -> None) + } + +let baz () = + try_with + bar + () + { effc = + (fun (type a) (eff : a t) -> + match eff with + | F -> Some (fun (k : (a, _) continuation) -> continue k "Hello, world!") + | _ -> None) + } + +let () = Format.printf "%s@." (baz ()) + +(****) + +let () = + Format.printf + "%s@." + (try_with + (fun () -> try perform F with Not_found -> "Discontinued") + () + { effc = (fun (type a) (eff : a t) -> Some (fun k -> discontinue k Not_found)) }) + +let () = + Format.printf + "%s@." + (try_with + (fun () -> try perform F with Unhandled _ -> "Unhandled") + () + { effc = (fun (type a) (eff : a t) -> None) }) + +let () = Format.printf "%s@." (try bar () with Unhandled _ -> "Saw unhandled exception") + +let () = + try + Format.printf "%d@." + @@ try_with + perform + (Xchg 0) + { effc = + (fun (type a) (eff : a t) -> + match eff with + | Xchg n -> + Some (fun (k : (a, _) continuation) -> continue k 21 + continue k 21) + | _ -> None) + } + with Continuation_already_resumed -> Format.printf "One-shot@." + +(****) + +let invert (type a) ~(iter : (a -> unit) -> unit) : a Seq.t = + let module M = struct + type _ Effect.t += Yield : a -> unit t + end in + let yield v = perform (M.Yield v) in + fun () -> + match_with + iter + yield + { retc = (fun _ -> Seq.Nil) + ; exnc = raise + ; effc = + (fun (type b) (eff : b Effect.t) -> + match eff with + | M.Yield v -> + Some (fun (k : (b, _) continuation) -> Seq.Cons (v, continue k)) + | _ -> None) + } + +let s = invert ~iter:(Fun.flip String.iter "OCaml") + +let next = Seq.to_dispenser s + +let rec loop () = + match next () with + | Some c -> + Format.printf "%c" c; + loop () + | None -> Format.printf "@." + +let () = loop () + +(****) + +type _ Effect.t += Send : int -> unit Effect.t | Recv : int Effect.t + +open! Effect.Shallow + +let run (comp : unit -> unit) : unit = + let rec loop_send : type a. (a, unit) continuation -> a -> unit = + fun k v -> + continue_with + k + v + { retc = Fun.id + ; exnc = raise + ; effc = + (fun (type b) (eff : b Effect.t) -> + match eff with + | Send n -> Some (fun (k : (b, _) continuation) -> loop_recv n k ()) + | Recv -> failwith "protocol violation" + | _ -> None) + } + and loop_recv : type a. int -> (a, unit) continuation -> a -> unit = + fun n k v -> + continue_with + k + v + { retc = Fun.id + ; exnc = raise + ; effc = + (fun (type b) (eff : b Effect.t) -> + match eff with + | Recv -> Some (fun (k : (b, _) continuation) -> loop_send k n) + | Send v -> failwith "protocol violation" + | _ -> None) + } + in + loop_send (fiber comp) () + +let () = + run (fun () -> + Format.printf "Send 42@."; + perform (Send 42); + Format.printf "Recv: %d@." (perform Recv); + Format.printf "Send 43@."; + perform (Send 43); + Format.printf "Recv: %d@." (perform Recv)) diff --git a/compiler/tests-ocaml/lib-gc/dune b/compiler/tests-jsoo/lib-gc/dune similarity index 100% rename from compiler/tests-ocaml/lib-gc/dune rename to compiler/tests-jsoo/lib-gc/dune diff --git a/compiler/tests-jsoo/lib-gc/test_gc.ml b/compiler/tests-jsoo/lib-gc/test_gc.ml new file mode 100644 index 0000000000..d3e2d16b6d --- /dev/null +++ b/compiler/tests-jsoo/lib-gc/test_gc.ml @@ -0,0 +1,40 @@ +(* TEST *) + +type stat = + { minor_words : float + ; promoted_words : float + ; major_words : float + ; minor_collections : int + ; major_collections : int + ; heap_words : int + ; heap_chunks : int + ; live_words : int + ; live_blocks : int + ; free_words : int + ; free_blocks : int + ; largest_free : int + ; fragments : int + ; compactions : int + ; top_heap_words : int + ; stack_size : int + ; forced_major_collections : int + } + +type control = + { minor_heap_size : int + ; major_heap_increment : int + ; space_overhead : int + ; verbose : int + ; max_overhead : int + ; stack_limit : int + ; allocation_policy : int + ; window_size : int + ; custom_major_ratio : int + ; custom_minor_ratio : int + ; custom_minor_max_size : int + } + +let () = + assert ((Gc.get ()).custom_minor_max_size = 0); + assert ((Gc.stat ()).forced_major_collections = 0); + assert ((Gc.quick_stat ()).forced_major_collections = 0) diff --git a/compiler/tests-ocaml/REAME.md b/compiler/tests-ocaml/REAME.md new file mode 100644 index 0000000000..209e6ff4c9 --- /dev/null +++ b/compiler/tests-ocaml/REAME.md @@ -0,0 +1,16 @@ +# Testsuite from the OCaml compiler distribution + +This directory contains a subset of the tests available in +https://github.com/ocaml/ocaml under the testsuite/tests/ +directory. + +The tests have been updated to accommodate wasoo and jsoo but we should +aim at keeping diffs as small as possible to simplify (re-)synchronisation. + +- `*.reference` files in the ocaml repo are renamed to `*.expected` here. +- expect test are not suppot yet. + +## Tooling +`tools/sync_testsuite.exe` is a small tool that helps visualizing the diff between the ocaml testsuite and this directory. + +`dune exe tools/sync_testsuite.exe -- /testsuite/tests/ compiler/tests-ocaml/` \ No newline at end of file diff --git a/compiler/tests-ocaml/dune b/compiler/tests-ocaml/dune index cf35e9dbe1..0d65819d8a 100644 --- a/compiler/tests-ocaml/dune +++ b/compiler/tests-ocaml/dune @@ -2,3 +2,8 @@ (_ (flags (:standard -w -27-32-33-35-39-50-60)))) + +(library + (name ocaml_testing) + (modules testing) + (wrapped false)) diff --git a/compiler/tests-ocaml/lib-effects/double-translation/dune b/compiler/tests-ocaml/effects-2/dune similarity index 93% rename from compiler/tests-ocaml/lib-effects/double-translation/dune rename to compiler/tests-ocaml/effects-2/dune index ad46c764c2..5680803fda 100644 --- a/compiler/tests-ocaml/lib-effects/double-translation/dune +++ b/compiler/tests-ocaml/effects-2/dune @@ -22,9 +22,11 @@ ;; TODO: remove once support in ocaml/dune#11222 is released. (compilation_mode whole_program)))) -(copy_files ../*.expected) +(copy_files ../effects/*.expected) -(copy_files# ../*.ml) +(copy_files# + (only_sources true) + (files ../effects/*.ml)) (tests (build_if @@ -32,7 +34,6 @@ (names cmphash marshal - effects evenodd manylive overflow diff --git a/compiler/tests-ocaml/lib-effects/cmphash.expected b/compiler/tests-ocaml/effects/cmphash.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/cmphash.expected rename to compiler/tests-ocaml/effects/cmphash.expected diff --git a/compiler/tests-ocaml/lib-effects/cmphash.ml b/compiler/tests-ocaml/effects/cmphash.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/cmphash.ml rename to compiler/tests-ocaml/effects/cmphash.ml diff --git a/compiler/tests-ocaml/lib-effects/dune b/compiler/tests-ocaml/effects/dune similarity index 98% rename from compiler/tests-ocaml/lib-effects/dune rename to compiler/tests-ocaml/effects/dune index ce1481b47d..c46238219a 100644 --- a/compiler/tests-ocaml/lib-effects/dune +++ b/compiler/tests-ocaml/effects/dune @@ -14,7 +14,6 @@ (names cmphash marshal - effects evenodd manylive overflow diff --git a/compiler/tests-ocaml/lib-effects/evenodd.expected b/compiler/tests-ocaml/effects/evenodd.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/evenodd.expected rename to compiler/tests-ocaml/effects/evenodd.expected diff --git a/compiler/tests-ocaml/lib-effects/evenodd.ml b/compiler/tests-ocaml/effects/evenodd.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/evenodd.ml rename to compiler/tests-ocaml/effects/evenodd.ml diff --git a/compiler/tests-ocaml/lib-effects/manylive.expected b/compiler/tests-ocaml/effects/manylive.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/manylive.expected rename to compiler/tests-ocaml/effects/manylive.expected diff --git a/compiler/tests-ocaml/lib-effects/manylive.ml b/compiler/tests-ocaml/effects/manylive.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/manylive.ml rename to compiler/tests-ocaml/effects/manylive.ml diff --git a/compiler/tests-ocaml/lib-effects/marshal.expected b/compiler/tests-ocaml/effects/marshal.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/marshal.expected rename to compiler/tests-ocaml/effects/marshal.expected diff --git a/compiler/tests-ocaml/lib-effects/marshal.ml b/compiler/tests-ocaml/effects/marshal.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/marshal.ml rename to compiler/tests-ocaml/effects/marshal.ml diff --git a/compiler/tests-ocaml/lib-effects/overflow.expected b/compiler/tests-ocaml/effects/overflow.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/overflow.expected rename to compiler/tests-ocaml/effects/overflow.expected diff --git a/compiler/tests-ocaml/lib-effects/overflow.ml b/compiler/tests-ocaml/effects/overflow.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/overflow.ml rename to compiler/tests-ocaml/effects/overflow.ml diff --git a/compiler/tests-ocaml/lib-effects/partial.expected b/compiler/tests-ocaml/effects/partial.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/partial.expected rename to compiler/tests-ocaml/effects/partial.expected diff --git a/compiler/tests-ocaml/lib-effects/partial.ml b/compiler/tests-ocaml/effects/partial.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/partial.ml rename to compiler/tests-ocaml/effects/partial.ml diff --git a/compiler/tests-ocaml/lib-effects/reperform.expected b/compiler/tests-ocaml/effects/reperform.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/reperform.expected rename to compiler/tests-ocaml/effects/reperform.expected diff --git a/compiler/tests-ocaml/lib-effects/reperform.ml b/compiler/tests-ocaml/effects/reperform.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/reperform.ml rename to compiler/tests-ocaml/effects/reperform.ml diff --git a/compiler/tests-ocaml/lib-effects/sched.expected b/compiler/tests-ocaml/effects/sched.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/sched.expected rename to compiler/tests-ocaml/effects/sched.expected diff --git a/compiler/tests-ocaml/lib-effects/sched.ml b/compiler/tests-ocaml/effects/sched.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/sched.ml rename to compiler/tests-ocaml/effects/sched.ml diff --git a/compiler/tests-ocaml/lib-effects/shallow_state.expected b/compiler/tests-ocaml/effects/shallow_state.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/shallow_state.expected rename to compiler/tests-ocaml/effects/shallow_state.expected diff --git a/compiler/tests-ocaml/lib-effects/shallow_state.ml b/compiler/tests-ocaml/effects/shallow_state.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/shallow_state.ml rename to compiler/tests-ocaml/effects/shallow_state.ml diff --git a/compiler/tests-ocaml/lib-effects/shallow_state_io.expected b/compiler/tests-ocaml/effects/shallow_state_io.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/shallow_state_io.expected rename to compiler/tests-ocaml/effects/shallow_state_io.expected diff --git a/compiler/tests-ocaml/lib-effects/shallow_state_io.ml b/compiler/tests-ocaml/effects/shallow_state_io.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/shallow_state_io.ml rename to compiler/tests-ocaml/effects/shallow_state_io.ml diff --git a/compiler/tests-ocaml/lib-effects/test1.expected b/compiler/tests-ocaml/effects/test1.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test1.expected rename to compiler/tests-ocaml/effects/test1.expected diff --git a/compiler/tests-ocaml/lib-effects/test1.ml b/compiler/tests-ocaml/effects/test1.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test1.ml rename to compiler/tests-ocaml/effects/test1.ml diff --git a/compiler/tests-ocaml/lib-effects/test10.expected b/compiler/tests-ocaml/effects/test10.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test10.expected rename to compiler/tests-ocaml/effects/test10.expected diff --git a/compiler/tests-ocaml/lib-effects/test10.ml b/compiler/tests-ocaml/effects/test10.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test10.ml rename to compiler/tests-ocaml/effects/test10.ml diff --git a/compiler/tests-ocaml/lib-effects/test11.expected b/compiler/tests-ocaml/effects/test11.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test11.expected rename to compiler/tests-ocaml/effects/test11.expected diff --git a/compiler/tests-ocaml/lib-effects/test11.ml b/compiler/tests-ocaml/effects/test11.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test11.ml rename to compiler/tests-ocaml/effects/test11.ml diff --git a/compiler/tests-ocaml/lib-effects/test2.expected b/compiler/tests-ocaml/effects/test2.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test2.expected rename to compiler/tests-ocaml/effects/test2.expected diff --git a/compiler/tests-ocaml/lib-effects/test2.ml b/compiler/tests-ocaml/effects/test2.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test2.ml rename to compiler/tests-ocaml/effects/test2.ml diff --git a/compiler/tests-ocaml/lib-effects/test3.expected b/compiler/tests-ocaml/effects/test3.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test3.expected rename to compiler/tests-ocaml/effects/test3.expected diff --git a/compiler/tests-ocaml/lib-effects/test3.ml b/compiler/tests-ocaml/effects/test3.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test3.ml rename to compiler/tests-ocaml/effects/test3.ml diff --git a/compiler/tests-ocaml/lib-effects/test4.expected b/compiler/tests-ocaml/effects/test4.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test4.expected rename to compiler/tests-ocaml/effects/test4.expected diff --git a/compiler/tests-ocaml/lib-effects/test4.ml b/compiler/tests-ocaml/effects/test4.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test4.ml rename to compiler/tests-ocaml/effects/test4.ml diff --git a/compiler/tests-ocaml/lib-effects/test5.expected b/compiler/tests-ocaml/effects/test5.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test5.expected rename to compiler/tests-ocaml/effects/test5.expected diff --git a/compiler/tests-ocaml/lib-effects/test5.ml b/compiler/tests-ocaml/effects/test5.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test5.ml rename to compiler/tests-ocaml/effects/test5.ml diff --git a/compiler/tests-ocaml/lib-effects/test6.expected b/compiler/tests-ocaml/effects/test6.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test6.expected rename to compiler/tests-ocaml/effects/test6.expected diff --git a/compiler/tests-ocaml/lib-effects/test6.ml b/compiler/tests-ocaml/effects/test6.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test6.ml rename to compiler/tests-ocaml/effects/test6.ml diff --git a/compiler/tests-ocaml/lib-effects/test_lazy.expected b/compiler/tests-ocaml/effects/test_lazy.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/test_lazy.expected rename to compiler/tests-ocaml/effects/test_lazy.expected diff --git a/compiler/tests-ocaml/lib-effects/test_lazy.ml b/compiler/tests-ocaml/effects/test_lazy.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/test_lazy.ml rename to compiler/tests-ocaml/effects/test_lazy.ml diff --git a/compiler/tests-ocaml/lib-effects/unhandled_unlinked.expected b/compiler/tests-ocaml/effects/unhandled_unlinked.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/unhandled_unlinked.expected rename to compiler/tests-ocaml/effects/unhandled_unlinked.expected diff --git a/compiler/tests-ocaml/lib-effects/unhandled_unlinked.ml b/compiler/tests-ocaml/effects/unhandled_unlinked.ml similarity index 73% rename from compiler/tests-ocaml/lib-effects/unhandled_unlinked.ml rename to compiler/tests-ocaml/effects/unhandled_unlinked.ml index bc2badb8e8..d03162e88d 100644 --- a/compiler/tests-ocaml/lib-effects/unhandled_unlinked.ml +++ b/compiler/tests-ocaml/effects/unhandled_unlinked.ml @@ -1,5 +1,5 @@ (* TEST - exit_status= "2" + exit_status= "2"; *) open Effect diff --git a/compiler/tests-ocaml/lib-effects/used_cont.expected b/compiler/tests-ocaml/effects/used_cont.expected similarity index 100% rename from compiler/tests-ocaml/lib-effects/used_cont.expected rename to compiler/tests-ocaml/effects/used_cont.expected diff --git a/compiler/tests-ocaml/lib-effects/used_cont.ml b/compiler/tests-ocaml/effects/used_cont.ml similarity index 100% rename from compiler/tests-ocaml/lib-effects/used_cont.ml rename to compiler/tests-ocaml/effects/used_cont.ml diff --git a/compiler/tests-ocaml/lib-bigarray/fftba.ml b/compiler/tests-ocaml/lib-bigarray/fftba.ml index 671ecbe183..ee35acfcb7 100644 --- a/compiler/tests-ocaml/lib-bigarray/fftba.ml +++ b/compiler/tests-ocaml/lib-bigarray/fftba.ml @@ -1,7 +1,4 @@ -[@@@ocaml.warning "-35"] - -(* TEST -*) +(* TEST *) open Bigarray @@ -149,12 +146,12 @@ let test np = pxi.{i+1} <- y; pxi.{j+1} <- -.y done; -(* +(** print_newline(); for i=0 to 15 do Printf.printf "%d %f %f\n" i pxr.{i+1} pxi.{i+1} done; **) let _ = fft pxr pxi np in -(* +(** for i=0 to 15 do Printf.printf "%d %f %f\n" i pxr.{i+1} pxi.{i+1} done; **) let zr = ref 0.0 in diff --git a/compiler/tests-ocaml/lib-bool/dune b/compiler/tests-ocaml/lib-bool/dune index 16342d6417..a53598eb62 100644 --- a/compiler/tests-ocaml/lib-bool/dune +++ b/compiler/tests-ocaml/lib-bool/dune @@ -1,4 +1,6 @@ (tests (names test) + (build_if + (>= %{ocaml_version} 5.3)) (libraries) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-bool/test.ml b/compiler/tests-ocaml/lib-bool/test.ml index a59fd7c586..6a3c92bd16 100644 --- a/compiler/tests-ocaml/lib-bool/test.ml +++ b/compiler/tests-ocaml/lib-bool/test.ml @@ -1,5 +1,4 @@ -(* TEST -*) +(* TEST *) let test_not () = assert (Bool.not false = true); @@ -69,6 +68,14 @@ let test_to_string () = assert (Bool.to_string true = "true"); () + +let test_hash () = + let f b = + assert (Hashtbl.hash b = Bool.hash b); + assert (Hashtbl.seeded_hash 16 b = Bool.seeded_hash 16 b) + in + f true; f false + let tests () = test_not (); test_and (); @@ -79,6 +86,7 @@ let tests () = test_to_float (); test_of_string (); test_to_string (); + test_hash (); () let () = diff --git a/compiler/tests-ocaml/lib-buffer/dune b/compiler/tests-ocaml/lib-buffer/dune index 16342d6417..be1e14090f 100644 --- a/compiler/tests-ocaml/lib-buffer/dune +++ b/compiler/tests-ocaml/lib-buffer/dune @@ -1,4 +1,6 @@ (tests (names test) + (build_if + (>= %{ocaml_version} 5.2)) (libraries) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-buffer/test.ml b/compiler/tests-ocaml/lib-buffer/test.ml index 7b1ab9a475..fb7fac0fb7 100644 --- a/compiler/tests-ocaml/lib-buffer/test.ml +++ b/compiler/tests-ocaml/lib-buffer/test.ml @@ -256,3 +256,34 @@ let () = assert(Buffer.length b = 800); done ;; + +(* Tests for add_substitute *) +let () = + let b = Buffer.create 64 in + let f x = + match x with + | "foo" -> "FOO" + | "bar" -> "BAR" + | "dollar" -> "$" + | "backslash" -> "\\" + | "#" -> "hash" + | "()" -> "nil" + | _ -> "unknown" + in + (* plain variable *) + Buffer.add_substitute b f " $foo"; + (* parens *) + Buffer.add_substitute b f " ${#}"; + Buffer.add_substitute b f " $(#)"; + (* nested parens *) + Buffer.add_substitute b f " $(())"; + (* escaped dollar *) + Buffer.add_substitute b f {| \$foo|}; + Buffer.add_substitute b f {| \\$foo|}; + Buffer.add_substitute b f {| \\\$foo|}; + (* no variable name *) + Buffer.add_substitute b f " $"; + Buffer.add_substitute b f " $!"; + Buffer.add_substitute b f " $(abc"; + assert (Buffer.contents b + = {| FOO hash hash nil $foo \$foo \\$foo $ $! $(abc|}) diff --git a/compiler/tests-ocaml/lib-bytes/dune b/compiler/tests-ocaml/lib-bytes/dune index 4af2ae612c..ff5a8f2082 100644 --- a/compiler/tests-ocaml/lib-bytes/dune +++ b/compiler/tests-ocaml/lib-bytes/dune @@ -1,4 +1,4 @@ (tests (names test_bytes binary) - (libraries) + (libraries ocaml_testing) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-bytes/test_bytes.ml b/compiler/tests-ocaml/lib-bytes/test_bytes.ml index 1ea7281c7b..56e71c94b8 100644 --- a/compiler/tests-ocaml/lib-bytes/test_bytes.ml +++ b/compiler/tests-ocaml/lib-bytes/test_bytes.ml @@ -1,5 +1,5 @@ (* TEST - include testing + include testing; *) let test_raises_invalid_argument f x = diff --git a/compiler/tests-ocaml/lib-digest/digests.ml b/compiler/tests-ocaml/lib-digest/digests.ml index 2d0f653c26..67d9ed428d 100644 --- a/compiler/tests-ocaml/lib-digest/digests.ml +++ b/compiler/tests-ocaml/lib-digest/digests.ml @@ -4,10 +4,7 @@ module Test(H: Digest.S) = struct let string (msg, hh) = - if not ( (H.(equal (string msg) (of_hex hh)))) - then ( - Printf.printf "Expecting %S\ - \nGot %S\n" hh (H.to_hex (H.string msg)); assert false) + assert (H.(equal (string msg) (of_hex hh))) let file wlen rlen = let data = String.init wlen Char.unsafe_chr in diff --git a/compiler/tests-ocaml/lib-digest/md5.ml b/compiler/tests-ocaml/lib-digest/md5.ml index d66ba52257..fade9baf35 100644 --- a/compiler/tests-ocaml/lib-digest/md5.ml +++ b/compiler/tests-ocaml/lib-digest/md5.ml @@ -1,5 +1,5 @@ (* TEST - flags += " -w -a " + flags += " -w -a "; *) (* Test int32 arithmetic and optimizations using the MD5 algorithm *) diff --git a/compiler/tests-ocaml/lib-dynarray/dune b/compiler/tests-ocaml/lib-dynarray/dune new file mode 100644 index 0000000000..d5bbec1ddf --- /dev/null +++ b/compiler/tests-ocaml/lib-dynarray/dune @@ -0,0 +1,6 @@ +(tests + (build_if + (>= %{ocaml_version} 5.3)) + (names test heap_sort) + (libraries) + (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-dynarray/heap_sort.ml b/compiler/tests-ocaml/lib-dynarray/heap_sort.ml new file mode 100644 index 0000000000..8fb1939b40 --- /dev/null +++ b/compiler/tests-ocaml/lib-dynarray/heap_sort.ml @@ -0,0 +1,98 @@ +(* TEST *) + +(* We present our priority queues as a functor + parametrized on the comparison function. *) +module Heap (Elem : Map.OrderedType) : sig + type t + val create : unit -> t + val add : t -> Elem.t -> unit + val pop_min : t -> Elem.t option +end = struct + + (* Our priority queues are implemented using the standard "min heap" + data structure, a dynamic array representing a binary tree. *) + type t = Elem.t Dynarray.t + let create = Dynarray.create + + (* The node of index [i] has as children the nodes of index [2 * i + 1] + and [2 * i + 2] -- if they are valid indices in the dynarray. *) + let left_child i = 2 * i + 1 + let right_child i = 2 * i + 2 + let parent_node i = (i - 1) / 2 + + (* We use indexing operators for convenient notations. *) + let ( .!() ) = Dynarray.get + let ( .!()<- ) = Dynarray.set + + (* Auxiliary functions to compare and swap two elements + in the dynamic array. *) + let order h i j = + Elem.compare h.!(i) h.!(j) + + let swap h i j = + let v = h.!(i) in + h.!(i) <- h.!(j); + h.!(j) <- v + + (* We say that a heap respects the "heap ordering" if the value of + each node is smaller than the value of its children. The + algorithm manipulates arrays that respect the heap algorithm, + except for one node whose value may be too small or too large. + + The auxiliary functions [heap_up] and [heap_down] take + such a misplaced value, and move it "up" (respectively: "down") + the tree by permuting it with its parent value (respectively: + a children's value) until the heap ordering is restored. *) + + let rec heap_up h i = + if i = 0 then () else + let parent = parent_node i in + if order h i parent < 0 then + (swap h i parent; heap_up h parent) + + and heap_down h ~len i = + let left, right = left_child i, right_child i in + if left >= len then () (* no child, stop *) else + let smallest = + if right >= len then left (* no right child *) else + if order h left right < 0 then left else right + in + if order h i smallest > 0 then + (swap h i smallest; heap_down h ~len smallest) + + let add h s = + let i = Dynarray.length h in + Dynarray.add_last h s; + heap_up h i + + let pop_min h = + if Dynarray.is_empty h then None + else begin + (* Standard trick: swap the 'best' value at index 0 + with the last value of the array. *) + let last = Dynarray.length h - 1 in + swap h 0 last; + (* At this point [pop_last] returns the 'best' value, + and leaves a heap with one misplaced element at position 0. *) + let best = Dynarray.pop_last h in + (* Restore the heap ordering -- does nothing if the heap is empty. *) + heap_down h ~len:last 0; + Some best + end +end + +let heap_sort (type a) cmp li = + let module Heap = Heap(struct type t = a let compare = cmp end) in + let heap = Heap.create () in + List.iter (Heap.add heap) li; + List.map (fun _ -> Heap.pop_min heap |> Option.get) li + +let () = + let rev cmp x y = cmp y x in + assert (heap_sort compare [3; 1; 2; 7; 2; 5] = [1; 2; 2; 3; 5; 7]); + assert (heap_sort (rev compare) [3; 1; 2; 7; 2; 5] = [7; 5; 3; 2; 2; 1]); + for i = 1 to 1_000 do + let li = List.init 10 (fun _ -> Random.int 10) in + assert (heap_sort compare li = List.sort compare li); + assert (heap_sort (rev compare) li = List.sort (rev compare) li); + done diff --git a/compiler/tests-ocaml/lib-dynarray/test.ml b/compiler/tests-ocaml/lib-dynarray/test.ml new file mode 100644 index 0000000000..39e5766c26 --- /dev/null +++ b/compiler/tests-ocaml/lib-dynarray/test.ml @@ -0,0 +1,542 @@ +(* TEST *) + +let list_range start len : _ list = + Seq.ints start |> Seq.take len |> List.of_seq + +module A = Dynarray + +(** {1:dynarrays Dynamic arrays} *) + +(** create, add_last *) + +let () = + let a = A.create() in + A.add_last a 1; + A.add_last a 2; + assert (A.length a = 2); + assert (A.to_list a = [1;2]);; + + +(** make *) + +let () = + let a = A.make 3 5 in + A.add_last a 6; + assert (A.to_list a = [5; 5; 5; 6]);; + + +(** init *) + +let () = + let test_init n f = + assert (A.init n f |> A.to_array = Array.init n f) in + for i = 0 to 1024 do + test_init i Fun.id + done;; + + +(** is_empty *) + +let () = + let a = A.create () in + assert (A.is_empty a); + A.ensure_capacity a 256; + assert (A.is_empty a);; + +(** length is tested below *) + +(** get_last, find_last *) +let () = + let a = A.of_list [1; 2] in + assert (A.get_last a = 2); + assert (A.find_last a = Some 2); + + A.remove_last a; + assert (A.to_list a = [1]); + assert (A.get_last a = 1); + assert (A.find_last a = Some 1); + + A.remove_last a; + assert (A.to_list a = []); + assert (match A.get_last a with exception _ -> true | _ -> false); + assert (A.find_last a = None) + +(** copy, add_last *) + +let () = + assert (A.of_list [1;2;3] |> A.copy |> A.to_list = [1;2;3]);; + +let () = + let a = A.create() in + for i=0 to 20 do A.add_last a i; done; + assert (A.to_list (A.copy a) = list_range 0 21);; + +let () = + assert (A.create() |> A.copy |> A.is_empty);; + +let () = + let a = A.of_list [1; 2; 3] in + let b = A.copy a in + for i = 4 to 1024 do + A.add_last b i + done; + assert (A.fold_left (+) 0 a = (1 + 2 + 3)); + assert (A.fold_left (+) 0 b = (1024 * 1025) / 2);; + +let () = + let a = A.of_list [1; 2; 3] in + assert (A.fold_right List.cons a [] = [1; 2; 3]);; + +(** {1:adding Adding elements} *) + +(** add_last was tested above *) + +(** append *) + +let () = + let a1 = A.init 5 (fun i->i) + and a2 = A.init 5 (fun i->i+5) in + A.append a1 a2; + assert (A.to_list a1 = list_range 0 10);; + +let () = + let empty = A.create () + and a2 = A.init 5 (fun i->i) in + A.append empty a2; + assert (A.to_list empty = list_range 0 5);; + +let () = + let a1 = A.init 5 (fun i->i) and empty = A.create () in + A.append a1 empty; + assert (A.to_list a1 = list_range 0 5);; + +let () = + let a = A.init 3 (fun i->i) in + A.append a (A.copy a); + (** Note: [A.append a a] is unspecified, and in particular it + loops infinitely with the following natural implementation: +{[ + let append a b = + append_iter a iter b + + let iter f a = + let i = ref 0 in + while !i < length a do + f (get a !i); + incr i + done +]} + *) + assert (A.to_list a = [0; 1; 2; 0; 1; 2]);; + +let() = + let empty = A.create () in + A.append empty empty; + assert (A.to_list empty = []);; + + +(** dynarrays with floats *) + +let () = + let a = A.create() in + A.add_last a 0.; A.add_last a 1.; + assert (0. = A.get a 0); + assert (1. = A.get a 1); + assert (1. = A.fold_left (+.) 0. a); + A.clear a; + A.add_last a 0.; A.add_last a 1.; A.add_last a 7.; A.add_last a 10.; A.add_last a 12.; + A.truncate a 2; + assert (1. = A.fold_left (+.) 0. a); + A.clear a; + assert (0 = A.length a); + A.add_last a 0.; A.add_last a 1.; A.add_last a 7.; A.add_last a 10.; A.add_last a 12.; + A.set a 2 8.; + assert (0. +. 1. +. 8. +. 10. +. 12. = A.fold_left (+.) 0. a);; + + +(** blit *) +let () = + let () = + (* normal blit works ok *) + let a = A.of_list [1; 2; 3; 4; 5; 6] in + let b = A.of_list [7; 8; 9; 10; 11] in + A.blit ~src:b ~src_pos:1 ~dst:a ~dst_pos:2 ~len:3; + assert (A.to_list a = [1; 2; 8; 9; 10; 6]) + in + let () = + (* source range overflows source array: error *) + let a = A.of_list [1; 2] in + let b = A.of_list [3; 4] in + assert (match + A.blit ~src:b ~src_pos:2 ~dst:a ~dst_pos:0 ~len:2 + with exception _ -> true | _ -> false) + in + let () = + (* target range overflows target array: extend the array *) + let a = A.of_list [1; 2] in + let b = A.of_list [3; 4; 5] in + A.blit ~src:b ~src_pos:0 ~dst:a ~dst_pos:1 ~len:3; + assert (A.to_list a = [1; 3; 4; 5]); + (* call [fit_capacity] to test the resize logic later on. *) + A.fit_capacity a; + (* this works even at the end *) + A.blit ~src:b ~src_pos:0 ~dst:a ~dst_pos:4 ~len:2; + assert (A.to_list a = [1; 3; 4; 5; 3; 4]); + (* ... but it fails if the extension would leave a gap *) + assert (A.length a = 6); + assert (match + A.blit ~src:b ~src_pos:0 ~dst:a ~dst_pos:7 ~len:2 + with exception _ -> true | _ -> false) + in + let () = + (* self-blitting scenarios *) + (* src_pos > dst_pos *) + let a = A.of_list [1; 2; 3] in + A.blit ~src:a ~src_pos:1 ~dst:a ~dst_pos:0 ~len:2; + assert (A.to_list a = [2; 3; 3]); + A.blit ~src:a ~src_pos:0 ~dst:a ~dst_pos:2 ~len:3; + assert (A.to_list a = [2; 3; 2; 3; 3]); + let b = A.of_list [1; 2; 3; 4] in + (* src_pos = dst_pos *) + A.blit ~src:b ~src_pos:1 ~dst:b ~dst_pos:1 ~len:2; + assert (A.to_list b = [1; 2; 3; 4]); + (* src_pos < dst_pos *) + A.blit ~src:b ~src_pos:0 ~dst:b ~dst_pos:2 ~len:2; + assert (A.to_list b = [1; 2; 1; 2]); + in + () + +(** {1:removing Removing elements} *) + + +(** pop_last_opt, length *) + +let () = + let seq = Seq.(ints 0 |> take 10_000) in + let a = A.of_seq seq in + assert (Some 9999 = A.pop_last_opt a); + assert (Some 9998 = A.pop_last_opt a); + assert (Some 9997 = A.pop_last_opt a); + assert (9997 = A.length a); + ();; + +let () = + let a = A.of_list [1;2] in + assert (Some 2 = A.pop_last_opt a); + assert (Some 1 = A.pop_last_opt a); + assert (None = A.pop_last_opt a); + assert (None = A.pop_last_opt a); + ();; + + +(** truncate *) + +let () = + let a = A.create() in + let max_length = 20_000 in + for i = 0 to max_length - 1 do A.add_last a i; done; + List.iter + (fun size -> + A.truncate a size; + let result_size = min max_length size in + assert (A.to_list a = list_range 0 result_size)) + [ 30_000; 20_000; 19_999; 2000; 100; 50; 4; 4; 3; 2; 1; 0];; + + + +(** {1:iteration Iteration} *) + +(** map *) + +let () = + let a = A.of_list [1;2;3] in + assert (A.to_list @@ A.map string_of_int a = ["1"; "2"; "3"]);; + + +(** mapi *) + +let () = + let a = A.of_list [1;2;3] in + let a = A.mapi (fun i e -> Printf.sprintf "%i %i" i e) a in + assert (A.to_list a = ["0 1"; "1 2"; "2 3"]);; + +(** mem *) +let () = + let a = A.of_list [1;2;3;4;5] in + assert (A.mem 1 a = true); + assert (A.mem 7 a = false) + +(** memq *) +let () = + let five = 5 in + let a = A.of_list [five; 6; 7] in + assert (A.memq five a = true) + +(** find_opt *) +let () = + let a = A.of_list [1;4;9] in + assert (A.find_opt (fun x -> x / 2 = 2) a = Some 4); + assert (A.find_opt (fun x -> x = 5) a = None) + +(** find_index *) +let () = + let a = A.of_list [1;2;3] in + assert (A.find_index (fun x -> x = 1) a = Some 0); + assert (A.find_index (fun x -> x = 5) a = None) + +(** find_map *) +let () = + let a = A.of_list [1;2;3;4;5] in + let b = A.of_list [1;2;3] in + let go x = if x > 3 then Some x else None in + assert (A.find_map go a = Some 4); + assert (A.find_map go b = None) + +(** find_mapi *) +let () = + let a = A.of_list [1;1;3] in + let b = A.of_list [3;2;1] in + let go i x = if i = x then Some (i, x) else None in + assert (A.find_mapi go a = Some (1,1)); + assert (A.find_mapi go b = None) + +(** Iterator invalidation *) + +let raises_invalid_argument f = + match f () with + | exception Invalid_argument _ -> true + | exception _ | _ -> false + +let () = + let a = A.of_list [1; 2; 3] in + assert (raises_invalid_argument (fun () -> + A.append a a + )) + +let () = + let a = A.of_list [1; 2; 3] in + assert (raises_invalid_argument (fun () -> + a |> A.iter (fun i -> + A.add_last a (10 + i) + ) + )) + +let () = + let a = A.of_list [1; 2; 3] in + assert (raises_invalid_argument (fun () -> + a |> A.iter (fun i -> + if i >= 2 then A.remove_last a + ) + )) + +let does_not_raise_invalid_argument f = + not (raises_invalid_argument f) + +(* The spec says that this is a programming error, but currently we accept + the following without an error. *) +let () = + let a = A.of_list [1; 2; 3] in + A.ensure_capacity a 10; + assert (does_not_raise_invalid_argument (fun () -> + a |> A.iter (fun i -> + A.add_last a i; + A.remove_last a + ) + )) + +(* Even with a capacity increase in the middle, + we still accept this although the spec would let us reject. *) +let () = + let a = A.of_list [1; 2; 3] in + A.fit_capacity a; + assert (does_not_raise_invalid_argument (fun () -> + a |> A.iter (fun i -> + A.add_last a i; + A.remove_last a + ) + )) + + +(** {1:comparison Comparison functions} *) + +let () = + let a = A.of_list [1; 2; 3] in + A.ensure_capacity a 1000; + let b = A.of_list [1; 2; 3] in + assert (A.equal (=) a a); + assert (A.compare Int.compare a a = 0); + assert (A.equal (=) a b); + assert (A.compare Int.compare a b = 0); + () + +let () = + let same eq l1 l2 = A.equal eq (A.of_list l1) (A.of_list l2) in + assert (not (same (=) [1; 2; 3] [1; 3; 2])); + assert (not (same (=) [1; 2; 3] [1; 2])); + assert (not (same (=) [1] [1; 2])); + assert (not (same (=) [] [1; 2])); + assert (same (fun _ _ -> true) [1; 2] [3; 4]); + assert (not (same (fun _ _ -> true) [1; 2] [3])); + () + +let () = + let compare cmp l1 l2 = A.compare cmp (A.of_list l1) (A.of_list l2) in + assert (compare Int.compare [] [] = 0); + assert (compare Int.compare [1; 2] [1; 2] = 0); + assert (compare Int.compare [min_int] [max_int] < 0); + assert (compare Int.compare [10] [0; 1] < 0); + assert (compare Int.compare [10] [0] > 0); + assert (compare (Fun.flip Int.compare) [10] [0] < 0); + () + +(** {1:conversions Conversions to other data structures} *) + +(** {of,to}_{list,array,seq{,_rev}{,_rentrant}} *) + +let () = + for i = 0 to 1024 do + let ints = List.init i Fun.id in + assert ((ints |> A.of_list |> A.to_list) = ints); + let arr = Array.of_list ints in + assert ((arr |> A.of_array |> A.to_array) = arr); + let seq = Array.to_seq arr in + [A.to_seq; A.to_seq_reentrant] |> List.iter (fun dynarray_to_seq -> + assert ((seq |> A.of_seq |> dynarray_to_seq) |> Array.of_seq = arr) + ); + [A.to_seq_rev; A.to_seq_rev_reentrant] |> List.iter (fun dynarray_to_seq_rev -> + assert ((seq |> A.of_seq |> dynarray_to_seq_rev) + |> List.of_seq |> List.rev + = ints) + ); + done;; + +(** reentrancy for to_seq{,_rev}_reentrant *) +let () = + let a = A.of_list [1; 2; 3; 4] in + let seq = A.to_seq a in + let srq = A.to_seq_reentrant a in + let elems_a = A.to_seq_reentrant a in + + let (i, seq) = Option.get (Seq.uncons seq) in assert (i = 1); + let (i, srq) = Option.get (Seq.uncons srq) in assert (i = 1); + + (* setting an element in the middle is observed by both versions *) + A.set a 1 12; + assert (List.of_seq elems_a = [1; 12; 3; 4]); + let (i, seq) = Option.get (Seq.uncons seq) in assert (i = 12); + let (i, srq) = Option.get (Seq.uncons srq) in assert (i = 12); + + (* adding or removing elements invalidates [seq] but works with [srq] *) + A.remove_last a; + assert (List.of_seq elems_a = [1; 12; 3]); + assert (match Seq.uncons seq with + | exception (Invalid_argument _) -> true + | _ -> false + ); + let (i, srq) = Option.get (Seq.uncons srq) in assert (i = 3); + + A.add_last a 4; + assert (List.of_seq elems_a = [1; 12; 3; 4]); + let (i, srq) = Option.get (Seq.uncons srq) in assert (i = 4); + assert (Seq.is_empty srq) + +let () = + let a = A.of_list [1; 2; 3; 4; 5] in + let seq = A.to_seq_rev a in + let srq = A.to_seq_rev_reentrant a in + + let (i, seq) = Option.get (Seq.uncons seq) in assert (i = 5); + let (i, srq) = Option.get (Seq.uncons srq) in assert (i = 5); + + (* setting an element in the middle is observed by both versions *) + A.set a 3 14; + assert (A.to_list a = [1; 2; 3; 14; 5]); + let (i, seq) = Option.get (Seq.uncons seq) in assert (i = 14); + let (i, srq) = Option.get (Seq.uncons srq) in assert (i = 14); + + (* adding elements invalidates [seq] but is ignored by [srq] *) + A.add_last a 6; + assert (A.to_list a = [1; 2; 3; 14; 5; 6]); + assert (match Seq.uncons seq with + | exception (Invalid_argument _) -> true + | _ -> false + ); + (* just check the head, no popping *) + let (i, _) = Option.get (Seq.uncons srq) in assert (i = 3); + let (i, _) = Option.get (Seq.uncons srq) in assert (i = 3); + + (* [srq] skips removed elements *) + A.truncate a 1; + assert (A.to_list a = [1]); + let (i, srq) = Option.get (Seq.uncons srq) in assert (i = 1); + assert (Seq.is_empty srq) + + +(** {1:advanced Advanced topics for performance} *) + +(** set_capacity *) + +let () = + let a = A.create() in + let max_length = 20_000 in + for i = 0 to max_length - 1 do A.add_last a i; done; + List.iter + (fun size -> + A.set_capacity a size; + let result_size = min max_length size in + assert (A.to_list a = list_range 0 result_size)) + [ 30_000; 20_000; 19_999; 2000; 100; 50; 4; 4; 3; 2; 1; 0];; + + +(** fit_capacity, capacity *) + +let () = + let a = A.create() in + for i = 0 to 200 do + A.add_last a i; + done; + A.fit_capacity a; + assert (A.length a = 201); + assert (A.length a = A.capacity a);; + + +(** check that comparisons and marshalling-with-sharing work as + expected. *) + +let () = + (** Comparison. + + We expect physically-equal dynarrays to be found equal, + and structurally-distinct dynarrays to be found distinct. + *) + let a = A.of_list [42] in + let b = A.of_list [21] in + assert (Stdlib.compare a a = 0); + assert (Stdlib.compare a b <> 0); + assert (a = a); + assert (a <> b); + + (** On the other hand, we do not specify that comparison is fully + structural, it may find structurally-equal values distinct, and + in fact it does. + + This is not part of our specification, but we document the + current behavior through tests below. *) + let a' = A.create () in + A.ensure_capacity a' 10000; + A.append_list a' [42]; + assert (A.to_list a = A.to_list a'); + assert (a <> a'); + assert (Stdlib.compare a a' <> 0); + ();; + +let () = + (** Marshalling. *) + let a = A.of_list [42] in + let buf = Marshal.to_string a [] in + let c = Marshal.from_string buf 0 in + (* Note: currently the equality of dynarrays is *not* stable by + marshalling-unmarshalling. *) + if false then assert (Stdlib.compare a c <> 0); + if false then assert (a <> c); + ();; diff --git a/compiler/tests-ocaml/lib-effects/effects.ml b/compiler/tests-ocaml/lib-effects/effects.ml deleted file mode 100644 index 4a78648b36..0000000000 --- a/compiler/tests-ocaml/lib-effects/effects.ml +++ /dev/null @@ -1,226 +0,0 @@ - -open Effect -open Effect.Deep - -type _ Effect.t += Xchg: int -> int t - -let comp1 () = let a= Xchg 0 in let x= perform a in let b = Xchg 1 in let y = perform b in x+ y -let comp2 () = let _ = perform (Xchg 0) in raise Not_found - -let comp3 () = let _ = perform (Xchg 0) in int_of_string "fdjsl" - -let handle comp = -(* try*) -Format.printf "%d@." @@ -match_with comp () -{ retc = (fun x -> x - 30); - exnc = (fun _ -> 42); - effc = fun (type a) (eff: a t) -> - match eff with - | Xchg n -> Some (fun (k: (a, _) continuation) -> - continue k (n+17)) - | _ -> None } -(*with Not_found -> assert false*) - -let () = handle comp1; handle comp2; handle comp3 - -type 'a status = - Complete of 'a -| Suspended of {msg: int; cont: (int, 'a status) continuation} - - -let step (f : unit -> 'a) () : 'a status = - match_with f () - { retc = (fun v -> Complete v); - exnc = raise; - effc = fun (type a) (eff: a t) -> - match eff with - | Xchg msg -> Some (fun (cont: (a, _) continuation) -> - Suspended {msg; cont}) - | _ -> None } - - -let rec run_both a b = - match a (), b () with - | Complete va, Complete vb -> (va, vb) - | Suspended {msg = m1; cont = k1}, - Suspended {msg = m2; cont = k2} -> - run_both (fun () -> continue k1 m2) - (fun () -> continue k2 m1) - | _ -> failwith "Improper synchronization" - - -let comp2 () = perform (Xchg 21) * perform (Xchg 21) - -let () = let x, y = run_both (step comp1) (step comp2) in Format.printf ">> %d %d@." x y - - -type _ Effect.t += Fork : (unit -> unit) -> unit t - | Yield : unit t - -let fork f = perform (Fork f) -let yield () = perform Yield -let xchg v = perform (Xchg v) - - -(* A concurrent round-robin scheduler *) -let run (main : unit -> unit) : unit = - let exchanger = ref None in (* waiting exchanger *) - let run_q = Queue.create () in (* scheduler queue *) - let enqueue k v = - let task () = continue k v in - Queue.push task run_q - in - let dequeue () = - if Queue.is_empty run_q then () (* done *) - else begin - let task = Queue.pop run_q in - task () - end - in - let rec spawn (f : unit -> unit) : unit = - match_with f () { - retc = dequeue; - exnc = (fun e -> - print_endline (Printexc.to_string e); - dequeue ()); - effc = fun (type a) (eff : a t) -> - match eff with - | Yield -> Some (fun (k : (a, unit) continuation) -> - enqueue k (); dequeue ()) - | Fork f -> Some (fun (k : (a, unit) continuation) -> - enqueue k (); spawn f) - | Xchg n -> Some (fun (k : (int, unit) continuation) -> - begin match !exchanger with - | Some (n', k') -> - exchanger := None; enqueue k' n; continue k n' - | None -> exchanger := Some (n, k); dequeue () - end) - | _ -> None - } - in - spawn main - -let _ = run (fun _ -> - fork (fun _ -> - Format.printf "[t1] Sending 0@."; - let v = xchg 0 in - Format.printf "[t1] received %d@." v); - fork (fun _ -> - Format.printf "[t2] Sending 1@."; - let v = xchg 1 in - Format.printf "[t2] received %d@." v)) - -(*****) - -type _ Effect.t += E : string t - | F : string t - -let foo () = perform F ^ " " ^ perform E ^ " " ^ perform F - -let bar () = - try_with foo () - { effc = fun (type a) (eff: a t) -> - match eff with - | E -> Some (fun (k: (a,_) continuation) -> - continue k "Coucou!") - | _ -> None } - -let baz () = - try_with bar () - { effc = fun (type a) (eff: a t) -> - match eff with - | F -> Some (fun (k: (a,_) continuation) -> - continue k "Hello, world!") - | _ -> None } - -let () = Format.printf "%s@." (baz()) - -(****) - -let () = - Format.printf "%s@." - (try_with (fun () -> try perform F with Not_found -> "Discontinued") () - { effc = fun (type a) (eff: a t) -> - Some (fun k -> discontinue k Not_found) }) -let () = - Format.printf "%s@." - (try_with (fun () -> try perform F with Unhandled _ -> "Unhandled") () - { effc = fun (type a) (eff: a t) -> None }) - -let () = - Format.printf "%s@." (try bar () with Unhandled _ -> "Saw unhandled exception") - -let () = - try - Format.printf "%d@." @@ - try_with perform (Xchg 0) - { effc = fun (type a) (eff : a t) -> - match eff with - | Xchg n -> Some (fun (k: (a, _) continuation) -> - continue k 21 + continue k 21) - | _ -> None } - with Continuation_already_resumed -> - Format.printf "One-shot@." - -(****) - -let invert (type a) ~(iter : (a -> unit) -> unit) : a Seq.t = - let module M = struct - type _ Effect.t += Yield : a -> unit t - end in - let yield v = perform (M.Yield v) in - fun () -> match_with iter yield - { retc = (fun _ -> Seq.Nil); - exnc = raise; - effc = fun (type b) (eff : b Effect.t) -> - match eff with - | M.Yield v -> Some (fun (k: (b,_) continuation) -> - Seq.Cons (v, continue k)) - | _ -> None } - -let s = invert ~iter:(Fun.flip String.iter "OCaml") -let next = Seq.to_dispenser s;; - -let rec loop () = - match next() with Some c -> Format.printf "%c" c; loop() | None -> Format.printf "@." -let () = loop() - -(****) - -type _ Effect.t += Send : int -> unit Effect.t - | Recv : int Effect.t - -open! Effect.Shallow - -let run (comp: unit -> unit) : unit = - let rec loop_send : type a. (a,unit) continuation -> a -> unit = fun k v -> - continue_with k v - { retc = Fun.id; - exnc = raise; - effc = fun (type b) (eff : b Effect.t) -> - match eff with - | Send n -> Some (fun (k: (b,_) continuation) -> - loop_recv n k ()) - | Recv -> failwith "protocol violation" - | _ -> None } - and loop_recv : type a. int -> (a,unit) continuation -> a -> unit = fun n k v -> - continue_with k v - { retc = Fun.id; - exnc = raise; - effc = fun (type b) (eff : b Effect.t) -> - match eff with - | Recv -> Some (fun (k: (b,_) continuation) -> - loop_send k n) - | Send v -> failwith "protocol violation" - | _ -> None } - in - loop_send (fiber comp) () - -let () = run (fun () -> - Format.printf "Send 42@."; - perform (Send 42); - Format.printf "Recv: %d@." (perform Recv); - Format.printf "Send 43@."; - perform (Send 43); - Format.printf "Recv: %d@." (perform Recv)) diff --git a/compiler/tests-ocaml/lib-floatarray/dune b/compiler/tests-ocaml/lib-floatarray/dune index de31de0d28..a4f9d412da 100644 --- a/compiler/tests-ocaml/lib-floatarray/dune +++ b/compiler/tests-ocaml/lib-floatarray/dune @@ -1,4 +1,6 @@ (tests (names floatarray) (libraries) + (build_if + (>= %{ocaml_version} 5.3)) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-floatarray/floatarray.ml b/compiler/tests-ocaml/lib-floatarray/floatarray.ml index e9d79e7e6a..4b83ee06eb 100644 --- a/compiler/tests-ocaml/lib-floatarray/floatarray.ml +++ b/compiler/tests-ocaml/lib-floatarray/floatarray.ml @@ -12,6 +12,8 @@ module type S = sig val make : int -> float -> t val create : int -> t val init : int -> (int -> float) -> t + val make_matrix : int -> int -> float -> t array + val init_matrix : int -> int -> (int -> int -> float) -> t array val append : t -> t -> t val concat : t list -> t val sub : t -> int -> int -> t @@ -23,7 +25,9 @@ module type S = sig val iter : (float -> unit) -> t -> unit val iteri : (int -> float -> unit) -> t -> unit val map : (float -> float) -> t -> t + val map_inplace : (float -> float) -> t -> unit val mapi : (int -> float -> float) -> t -> t + val mapi_inplace : (int -> float -> float) -> t -> unit val fold_left : ('a -> float -> 'a) -> 'a -> t -> 'a val fold_right : (float -> 'a -> 'a) -> t -> 'a -> 'a val iter2 : (float -> float -> unit) -> t -> t -> unit @@ -32,6 +36,10 @@ module type S = sig val exists : (float -> bool) -> t -> bool val mem : float -> t -> bool val mem_ieee : float -> t -> bool + val find_opt : (float -> bool) -> t -> float option + val find_index : (float-> bool) -> t -> int option + val find_map : (float -> 'a option) -> t -> 'a option + val find_mapi : (int -> float -> 'a option) -> t -> 'a option val sort : (float -> float -> int) -> t -> unit val stable_sort : (float -> float -> int) -> t -> unit val fast_sort : (float -> float -> int) -> t -> unit @@ -120,6 +128,48 @@ module Test (A : S) : sig end = struct check_inval (fun i -> A.init i Float.of_int) (-1); (* check_inval (fun i -> A.init i Float.of_int) (A.max_length + 1); *) + + (* [make_matrix] *) + let check_make_matrix m n = + let a = A.make_matrix m n 42. in + assert (Array.length a = m); + for i = 0 to m-1 do + let row = Array.get a i in + assert (A.length row = n); + for j = 0 to n-1 do + assert (A.get row j = 42.); + A.set row j (Float.of_int (i*n + j)); + done; + done; + (* check absence of sharing: *) + if n > 0 then begin + for i = 0 to m-1 do + assert (A.get (Array.get a i) 0 = Float.of_int (i*n)); + done + end + in + check_make_matrix 0 0; + check_make_matrix 0 3; + check_make_matrix 5 0; + check_make_matrix 5 3; + + (* [init_matrix] *) + let check_init_matrix m n = + let a = A.init_matrix m n (fun i j -> Float.of_int (i*n + j)) in + assert (Array.length a = m); + for i = 0 to m-1 do + let row = Array.get a i in + assert (A.length row = n); + for j = 0 to n-1 do + assert (A.get row j = Float.of_int (i*n + j)); + done; + done; + in + check_init_matrix 0 0; + check_init_matrix 0 3; + check_init_matrix 5 0; + check_init_matrix 5 3; + (* [append] *) let check m n = let a = A.init m Float.of_int in @@ -368,6 +418,61 @@ module Test (A : S) : sig end = struct A.set a 0 nan; assert (not (A.mem_ieee nan a)); + (* [find_opt], test result and order of evaluation *) + let a = A.init 777 Float.of_int in + let r = ref 0.0 in + let f x = + assert (x = !r); + r := x +. 1.0; + false + in + assert (Option.is_none (A.find_opt f a)); + let f x = assert (x = 0.0); true in + assert (Option.is_some (A.find_opt f a)); + + (* [find_index], test result and order of evaluation *) + let a = A.init 777 Float.of_int in + let r = ref 0.0 in + let f x = + assert (x = !r); + r := x +. 1.0; + false + in + assert (Option.is_none (A.find_index f a)); + let f x = assert (x = 0.0); true in + assert (Option.get (A.find_index f a) = 0); + + (* [find_map], test result and order of evaluation *) + let a = A.init 777 Float.of_int in + let r = ref 0.0 in + let f x = + assert (x = !r); + r := x +. 1.0; + None + in + assert (Option.is_none (A.find_map f a)); + let f x = assert (x = 0.0); Some "abc" in + assert (Option.get (A.find_map f a) = "abc"); + + (* [find_mapi], test result and order of evaluation *) + let a = A.init 777 Float.of_int in + let r = ref 0.0 in + let r_i = ref 0 in + let f i x = + assert (i = !r_i); + assert (x = !r); + r_i := !r_i + 1; + r := x +. 1.0; + None + in + assert (Option.is_none (A.find_mapi f a)); + let f i x = + assert (i = 0); + assert (x = 0.0); + Some "abc" + in + assert (Option.get (A.find_mapi f a) = "abc"); + (* [sort] [fast_sort] [stable_sort] *) let check_sort sort cmp a = let rec check_sorted a i = @@ -540,6 +645,20 @@ module Test (A : S) : sig end = struct (* js_of_ocaml doesn't marshal floats *) if false then test_structured_io (A.of_list l); + (* map_inplace *) + let a = A.init 4 (fun i -> Float.of_int (i + 1)) in + A.map_inplace (fun x -> 2. *. x) a; + let got = A.map_to_array Fun.id a in + let expected = [|2.; 4.; 6.; 8.|] in + assert (Array.for_all2 Float.equal got expected); + + (* mapi_inplace *) + let a = A.init 4 (fun i -> Float.of_int (i + 1)) in + A.mapi_inplace (fun i x -> 1. +. (Float.of_int i) +. x) a; + let got = A.map_to_array Fun.id a in + let expected = [|2.; 4.; 6.; 8.|] in + assert (Array.for_all2 Float.equal got expected) + end (* We run the same tests on [Float.Array] and [Array]. *) diff --git a/compiler/tests-ocaml/lib-format/dune b/compiler/tests-ocaml/lib-format/dune index a5860c3846..3c48b53511 100644 --- a/compiler/tests-ocaml/lib-format/dune +++ b/compiler/tests-ocaml/lib-format/dune @@ -1,6 +1,14 @@ (tests - (names pr6824 print_if_newline pp_print_custom_break print_seq tformat) - (libraries) + (names + pr6824 + print_if_newline + pp_print_custom_break + print_seq + tformat + print_array) + (build_if + (>= %{ocaml_version} 5.1)) + (libraries ocaml_testing) (flags (:standard -no-strict-formats \ -strict-formats)) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-format/pr6824.ml b/compiler/tests-ocaml/lib-format/pr6824.ml index 882fba8da4..47c26206f7 100644 --- a/compiler/tests-ocaml/lib-format/pr6824.ml +++ b/compiler/tests-ocaml/lib-format/pr6824.ml @@ -1,5 +1,5 @@ (* TEST - include testing + include testing; *) let f = Format.sprintf "[%i]";; diff --git a/compiler/tests-ocaml/lib-format/print_array.expected b/compiler/tests-ocaml/lib-format/print_array.expected new file mode 100644 index 0000000000..1b34bf6898 --- /dev/null +++ b/compiler/tests-ocaml/lib-format/print_array.expected @@ -0,0 +1,7 @@ +empty + 0 +misc + 1 2 3 +end of tests + +All tests succeeded. diff --git a/compiler/tests-ocaml/lib-format/print_array.ml b/compiler/tests-ocaml/lib-format/print_array.ml new file mode 100644 index 0000000000..5efce52758 --- /dev/null +++ b/compiler/tests-ocaml/lib-format/print_array.ml @@ -0,0 +1,28 @@ +(* TEST + include testing; +*) + +(* + +A test file for the Format module. + +*) + +open Testing;; +open Format;; + +let say s = Printf.printf (s ^^ "\n%!");; + +let pp_print_intarray = pp_print_array ~pp_sep:(fun fmt () -> pp_print_char fmt ' ') pp_print_int;; + +let () = + + say "empty"; + test (asprintf "%a" pp_print_intarray [||] = ""); + + say "\nmisc"; + test (asprintf "%a" pp_print_intarray [| 0 |] = "0"); + test (asprintf "%a" pp_print_intarray [| 0; 1; 2 |] = "0 1 2"); + test (asprintf "%a" pp_print_intarray [| 0; 0 |] = "0 0"); + + say "\nend of tests" diff --git a/compiler/tests-ocaml/lib-format/print_seq.ml b/compiler/tests-ocaml/lib-format/print_seq.ml index 4113ded9ad..d183478ea9 100644 --- a/compiler/tests-ocaml/lib-format/print_seq.ml +++ b/compiler/tests-ocaml/lib-format/print_seq.ml @@ -1,5 +1,5 @@ (* TEST - include testing + include testing; *) (* diff --git a/compiler/tests-ocaml/lib-format/testing.ml b/compiler/tests-ocaml/lib-format/testing.ml deleted file mode 100644 index 4111ca5131..0000000000 --- a/compiler/tests-ocaml/lib-format/testing.ml +++ /dev/null @@ -1,96 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Pierre Weis, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2006 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Testing auxiliaries. *) - -open Scanf;; - -let all_tests_ok = ref true;; - -let finish () = - match !all_tests_ok with - | true -> - print_endline "\nAll tests succeeded." - | _ -> - print_endline "\n\n********* Test suite failed. ***********\n";; - -at_exit finish;; - -let test_num = ref (-1);; - -let print_test_number () = - print_string " "; print_int !test_num; flush stdout;; - -let next_test () = - incr test_num; - print_test_number ();; - -let print_test_fail () = - all_tests_ok := false; - print_string - (Printf.sprintf "\n********* Test number %i failed ***********\n" - !test_num);; - -let print_failure_test_fail () = - all_tests_ok := false; - print_string - (Printf.sprintf - "\n********* Failure Test number %i incorrectly failed ***********\n" - !test_num);; - -let print_failure_test_succeed () = - all_tests_ok := false; - print_string - (Printf.sprintf - "\n********* Failure Test number %i failed to fail ***********\n" - !test_num);; - -let test b = - next_test (); - if not b then print_test_fail ();; - -(* Applies f to x and checks that the evaluation indeed - raises an exception that verifies the predicate [pred]. *) -let test_raises_exc_p pred f x = - next_test (); - try - ignore (f x); - print_failure_test_succeed (); - false - with - | x -> - pred x || (print_failure_test_fail (); false);; - -(* Applies f to x and checks that the evaluation indeed - raises some exception. *) -let test_raises_some_exc f = test_raises_exc_p (fun _ -> true) f;; -let test_raises_this_exc exc = test_raises_exc_p (fun x -> x = exc);; - -(* Applies f to x and checks that the evaluation indeed - raises exception Failure s. *) - -let test_raises_this_failure s f x = - test_raises_exc_p (fun x -> x = Failure s) f x;; - -(* Applies f to x and checks that the evaluation indeed - raises the exception Failure. *) -let test_raises_some_failure f x = - test_raises_exc_p (function Failure _ -> true | _ -> false) f x;; - -let failure_test f x s = test_raises_this_failure s f x;; -let any_failure_test = test_raises_some_failure;; - -let scan_failure_test f x = - test_raises_exc_p (function Scan_failure _ -> true | _ -> false) f x;; diff --git a/compiler/tests-ocaml/lib-format/tformat.ml b/compiler/tests-ocaml/lib-format/tformat.ml index 962ffef339..7b353af78b 100644 --- a/compiler/tests-ocaml/lib-format/tformat.ml +++ b/compiler/tests-ocaml/lib-format/tformat.ml @@ -1,5 +1,6 @@ (* TEST - include testing + include testing; + flags = "-no-strict-formats"; *) (* @@ -56,7 +57,7 @@ try test (sprintf "%u" (-1) = "2147483647"); | 32 -> test (sprintf "%u" (-1) = "4294967295"); - | 62 -> + | 63 -> test (sprintf "%u" (-1) = "9223372036854775807"); | _ -> test false end; diff --git a/compiler/tests-ocaml/lib-gc/test_gc.ml b/compiler/tests-ocaml/lib-gc/test_gc.ml deleted file mode 100644 index eb0572d277..0000000000 --- a/compiler/tests-ocaml/lib-gc/test_gc.ml +++ /dev/null @@ -1,40 +0,0 @@ -(* TEST *) - -type stat = - { minor_words : float; - promoted_words : float; - major_words : float; - minor_collections : int; - major_collections : int; - heap_words : int; - heap_chunks : int; - live_words : int; - live_blocks : int; - free_words : int; - free_blocks : int; - largest_free : int; - fragments : int; - compactions : int; - top_heap_words : int; - stack_size: int; - forced_major_collections: int - } - -type control = - { minor_heap_size : int; - major_heap_increment : int; - space_overhead : int; - verbose : int; - max_overhead : int; - stack_limit : int; - allocation_policy : int; - window_size : int; - custom_major_ratio : int; - custom_minor_ratio : int; - custom_minor_max_size : int; - } - -let () = - assert ((Gc.get ()).custom_minor_max_size = 0); - assert ((Gc.stat ()).forced_major_collections = 0); - assert ((Gc.quick_stat ()).forced_major_collections = 0) diff --git a/compiler/tests-ocaml/lib-hashtbl/htbl.ml b/compiler/tests-ocaml/lib-hashtbl/htbl.ml index e4d6e33555..4af75a9f02 100644 --- a/compiler/tests-ocaml/lib-hashtbl/htbl.ml +++ b/compiler/tests-ocaml/lib-hashtbl/htbl.ml @@ -1,10 +1,7 @@ -(* TEST -*) +(* TEST *) (* Hashtable operations, using maps as a reference *) -[@@@ocaml.warning "-unused-var-strict"] - open Printf module Test(H: Hashtbl.SeededS) (M: Map.S with type key = H.key) = struct diff --git a/compiler/tests-ocaml/lib-int/dune b/compiler/tests-ocaml/lib-int/dune index 16342d6417..a53598eb62 100644 --- a/compiler/tests-ocaml/lib-int/dune +++ b/compiler/tests-ocaml/lib-int/dune @@ -1,4 +1,6 @@ (tests (names test) + (build_if + (>= %{ocaml_version} 5.3)) (libraries) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-int/test.ml b/compiler/tests-ocaml/lib-int/test.ml index dbe3492450..2fdee39520 100644 --- a/compiler/tests-ocaml/lib-int/test.ml +++ b/compiler/tests-ocaml/lib-int/test.ml @@ -1,5 +1,4 @@ -(* TEST -*) +(* TEST *) let test_consts () = assert (Int.zero = 0); @@ -61,6 +60,12 @@ let test_min_max () = assert (Int.max 2 3 = 3); assert (Int.min 2 3 = 2) +let test_hash () = + let f n = + assert (Hashtbl.hash n = Int.hash n); + assert (Hashtbl.seeded_hash 16 n = Int.seeded_hash 16 n) + in + f 0; f 123; f (-456); f 0x3FFFFFFF; f (-0x40000000) let tests () = test_consts (); @@ -71,6 +76,7 @@ let tests () = test_float_conv (); test_string_conv (); test_min_max (); + test_hash (); () let () = diff --git a/compiler/tests-ocaml/lib-list/dune b/compiler/tests-ocaml/lib-list/dune index 16342d6417..1bdcacba13 100644 --- a/compiler/tests-ocaml/lib-list/dune +++ b/compiler/tests-ocaml/lib-list/dune @@ -1,4 +1,6 @@ (tests (names test) (libraries) + (build_if + (>= %{ocaml_version} 5.3)) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-list/test.ml b/compiler/tests-ocaml/lib-list/test.ml index 8f7be225ce..227c454775 100644 --- a/compiler/tests-ocaml/lib-list/test.ml +++ b/compiler/tests-ocaml/lib-list/test.ml @@ -1,5 +1,4 @@ -(* TEST -*) +(* TEST *) let is_even x = (x mod 2 = 0) @@ -62,6 +61,29 @@ let () = assert (List.filteri (fun i _ -> i < 2) (List.rev l) = [9; 8]); + let hello = ['H';'e';'l';'l';'o'] in + let world = ['W';'o';'r';'l';'d';'!'] in + let hello_world = hello @ [' '] @ world in + assert (List.take 5 hello_world = hello); + assert (List.take 3 [1; 2; 3; 4; 5] = [1; 2; 3]); + assert (List.take 3 [1; 2] = [1; 2]); + assert (List.take 3 [] = []); + assert ((try List.take (-1) [1; 2] with Invalid_argument _ -> [999]) = [999]); + assert (List.take 0 [1; 2] = []); + assert (List.drop 6 hello_world = world); + assert (List.drop 3 [1; 2; 3; 4; 5] = [4; 5]); + assert (List.drop 3 [1; 2] = []); + assert (List.drop 3 [] = []); + assert ((try List.drop (-1) [1; 2] with Invalid_argument _ -> [999]) = [999]); + assert (List.drop 0 [1; 2] = [1; 2]); + assert (List.take_while (fun x -> x < 3) [1; 2; 3; 4; 1; 2; 3; 4] + = [1; 2]); + assert (List.take_while (fun x -> x < 9) [1; 2; 3] = [1; 2; 3]); + assert (List.take_while (fun x -> x < 0) [1; 2; 3] = []); + assert (List.drop_while (fun x -> x < 3) [1; 2; 3; 4; 5; 1; 2; 3] + = [3; 4; 5; 1; 2; 3]); + assert (List.drop_while (fun x -> x < 9) [1; 2; 3] = []); + assert (List.drop_while (fun x -> x < 0) [1; 2; 3] = [1; 2; 3]); assert (List.partition is_even [1; 2; 3; 4; 5] = ([2; 4], [1; 3; 5])); assert (List.partition_map string_of_even_or_int [1; 2; 3; 4; 5] @@ -82,6 +104,10 @@ let () = assert (List.compare_length_with [1] 0 > 0); assert (List.compare_length_with ['1'] 1 = 0); assert (List.compare_length_with ['1'] 2 < 0); + + assert (List.is_empty []); + assert (not (List.is_empty [1])); + assert (List.filter_map string_of_even_opt l = ["0";"2";"4";"6";"8"]); assert (List.concat_map (fun i -> [i; i+1]) [1; 5] = [1; 2; 5; 6]); assert ( @@ -92,6 +118,28 @@ let () = assert ( let f a b = a + b, string_of_int b in List.fold_left_map f 0 l = (45, sl)); + + (* [find_index] *) + assert (List.find_index (fun x -> x=1) [] = None); + let xs = [1;2;3;4;5] in + assert (List.find_index (fun x -> x=1) xs = Some 0); + assert (List.find_index (fun x -> x=3) xs = Some 2); + assert (List.find_index (fun x -> x=5) xs = Some 4); + assert (List.find_index (fun x -> x=6) xs = None); + + (* [find_mapi] *) + assert (List.find_mapi + (fun i x -> if x+i=3 then Some(i, x) else None) [] = None); + let xs = [3;3;3;42;42] in + assert (List.find_mapi + (fun i x -> if x+i=3 then Some(i, x) else None) xs = Some (0, 3)); + assert (List.find_mapi + (fun i x -> if x+i=4 then Some(i, x) else None) xs = Some (1, 3)); + assert (List.find_mapi + (fun i x -> if x+i=5 then Some(i, x) else None) xs = Some (2, 3)); + assert (List.find_mapi + (fun i x -> if x+i=7 then Some(i, x) else None) xs = None); + () ;; diff --git a/compiler/tests-ocaml/lib-printf/dune b/compiler/tests-ocaml/lib-printf/dune index 2a15a0ace3..37a54f58ba 100644 --- a/compiler/tests-ocaml/lib-printf/dune +++ b/compiler/tests-ocaml/lib-printf/dune @@ -1,6 +1,6 @@ (tests (names pr6534 pr6938 tprintf) - (libraries) + (libraries ocaml_testing) (flags (:standard -no-strict-formats \ -strict-formats)) (modes diff --git a/compiler/tests-ocaml/lib-printf/pr6534.ml b/compiler/tests-ocaml/lib-printf/pr6534.ml index 42adf39324..9f455a88c7 100644 --- a/compiler/tests-ocaml/lib-printf/pr6534.ml +++ b/compiler/tests-ocaml/lib-printf/pr6534.ml @@ -1,5 +1,6 @@ (* TEST - include testing + include testing; + flags = "-no-strict-formats"; *) (* these are not valid under -strict-formats, but we test them here diff --git a/compiler/tests-ocaml/lib-printf/pr6938.ml b/compiler/tests-ocaml/lib-printf/pr6938.ml index 47efc5eef0..d3a83e4ee1 100644 --- a/compiler/tests-ocaml/lib-printf/pr6938.ml +++ b/compiler/tests-ocaml/lib-printf/pr6938.ml @@ -1,6 +1,7 @@ (* TEST - include testing -*) + include testing; + flags = "-no-strict-formats"; + *) (* these are not valid under -strict-formats, but we test them here for backward-compatibility *) diff --git a/compiler/tests-ocaml/lib-printf/testing.ml b/compiler/tests-ocaml/lib-printf/testing.ml deleted file mode 100644 index 4111ca5131..0000000000 --- a/compiler/tests-ocaml/lib-printf/testing.ml +++ /dev/null @@ -1,96 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Pierre Weis, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2006 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Testing auxiliaries. *) - -open Scanf;; - -let all_tests_ok = ref true;; - -let finish () = - match !all_tests_ok with - | true -> - print_endline "\nAll tests succeeded." - | _ -> - print_endline "\n\n********* Test suite failed. ***********\n";; - -at_exit finish;; - -let test_num = ref (-1);; - -let print_test_number () = - print_string " "; print_int !test_num; flush stdout;; - -let next_test () = - incr test_num; - print_test_number ();; - -let print_test_fail () = - all_tests_ok := false; - print_string - (Printf.sprintf "\n********* Test number %i failed ***********\n" - !test_num);; - -let print_failure_test_fail () = - all_tests_ok := false; - print_string - (Printf.sprintf - "\n********* Failure Test number %i incorrectly failed ***********\n" - !test_num);; - -let print_failure_test_succeed () = - all_tests_ok := false; - print_string - (Printf.sprintf - "\n********* Failure Test number %i failed to fail ***********\n" - !test_num);; - -let test b = - next_test (); - if not b then print_test_fail ();; - -(* Applies f to x and checks that the evaluation indeed - raises an exception that verifies the predicate [pred]. *) -let test_raises_exc_p pred f x = - next_test (); - try - ignore (f x); - print_failure_test_succeed (); - false - with - | x -> - pred x || (print_failure_test_fail (); false);; - -(* Applies f to x and checks that the evaluation indeed - raises some exception. *) -let test_raises_some_exc f = test_raises_exc_p (fun _ -> true) f;; -let test_raises_this_exc exc = test_raises_exc_p (fun x -> x = exc);; - -(* Applies f to x and checks that the evaluation indeed - raises exception Failure s. *) - -let test_raises_this_failure s f x = - test_raises_exc_p (fun x -> x = Failure s) f x;; - -(* Applies f to x and checks that the evaluation indeed - raises the exception Failure. *) -let test_raises_some_failure f x = - test_raises_exc_p (function Failure _ -> true | _ -> false) f x;; - -let failure_test f x s = test_raises_this_failure s f x;; -let any_failure_test = test_raises_some_failure;; - -let scan_failure_test f x = - test_raises_exc_p (function Scan_failure _ -> true | _ -> false) f x;; diff --git a/compiler/tests-ocaml/lib-printf/tprintf.ml b/compiler/tests-ocaml/lib-printf/tprintf.ml index 35290e251b..badf8f3483 100644 --- a/compiler/tests-ocaml/lib-printf/tprintf.ml +++ b/compiler/tests-ocaml/lib-printf/tprintf.ml @@ -1,5 +1,6 @@ (* TEST - include testing + include testing; + flags = "-no-strict-formats"; *) (* @@ -677,5 +678,3 @@ with e -> printf "unexpected exception: %s\n%!" (Printexc.to_string e); test false; ;; - -let () = exit 0 diff --git a/compiler/tests-ocaml/lib-queue/dune b/compiler/tests-ocaml/lib-queue/dune index 16342d6417..1bdcacba13 100644 --- a/compiler/tests-ocaml/lib-queue/dune +++ b/compiler/tests-ocaml/lib-queue/dune @@ -1,4 +1,6 @@ (tests (names test) (libraries) + (build_if + (>= %{ocaml_version} 5.3)) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-queue/test.ml b/compiler/tests-ocaml/lib-queue/test.ml index ac05f4e303..b08306d923 100644 --- a/compiler/tests-ocaml/lib-queue/test.ml +++ b/compiler/tests-ocaml/lib-queue/test.ml @@ -1,5 +1,4 @@ -(* TEST -*) +(* TEST *) module Q = struct include Queue @@ -9,7 +8,7 @@ end let does_raise f q = try - ignore (f q : int); + ignore (f q); false with Q.Empty -> true @@ -138,4 +137,11 @@ let () = assert (Q.length q2 = 8); assert (Q.to_list q2 = [5; 6; 7; 8; 1; 2; 3; 4]); ;; +let () = + let q = Q.create () in + Q.add 1 q; Q.drop q; assert (does_raise Q.drop q); + Q.add 2 q; Q.drop q; assert (does_raise Q.drop q); + assert (Q.length q = 0); +;; + let () = print_endline "OK" diff --git a/compiler/tests-ocaml/lib-random/chi2.ml b/compiler/tests-ocaml/lib-random/chi2.ml index 42d2b1d7cd..52e02d464f 100644 --- a/compiler/tests-ocaml/lib-random/chi2.ml +++ b/compiler/tests-ocaml/lib-random/chi2.ml @@ -1,5 +1,4 @@ -(* TEST -*) +(* TEST *) (* A basic chi-square test to detect simple errors in the Random module. *) @@ -31,27 +30,47 @@ let test name f = if not (chisquare 100_000 f) then Printf.printf "%s: suspicious result\n%!" name +(* Division of [x] by [y] where [x] is interpreted as an unsigned integer. + * This code assumes [y >= 0]. *) +let udiv x y = + if x >= 0 then x / y + else + let x' = x + min_int in + let q = (x' / y) - (min_int / y) + and r = (x' mod y) - (min_int mod y) in + if r < y then q else q + 1 + let _ = + + (* [bits] *) test "Random.bits (bits 0-7)" Random.bits; test "Random.bits (bits 12-19)" (fun () -> Random.bits() lsr 12); test "Random.bits (bits 22-29)" (fun () -> Random.bits() lsr 22); + + (* [int] *) test "Random.int 2^26 (bits 0-7)" (fun () -> Random.int (1 lsl 26)); test "Random.int 2^26 (bits 18-25)" (fun () -> Random.int (1 lsl 26) lsr 18); test "Random.int (256 * p) / p" (fun () -> Random.int (256 * 853187) / 853187); + + (* [float] *) test "Random.float 1.0 (first 8 bits)" (fun () -> int_of_float (Random.float 1.0 *. 256.0)); test "Random.float 1.0 (next 8 bits)" (fun () -> int_of_float (Random.float 1.0 *. 65536.0)); + + (* [bits32] *) test "Random.bits32 (bits 0-7)" (fun () -> Int32.to_int (Random.bits32())); test "Random.bits32 (bits 20-27)" (fun () -> Int32.(to_int (shift_right (Random.bits32()) 20))); + + (* [int32] *) test "Random.int32 2^30 (bits 0-7)" (fun () -> Int32.to_int (Random.int32 0x40000000l)); test "Random.int32 2^30 (bits 20-27)" @@ -59,12 +78,16 @@ let _ = test "Random.int32 (256 * p) / p" (let p = 7048673l in fun () -> Int32.(to_int (div (Random.int32 (mul 256l p)) p))); + + (* [bits64] *) test "Random.bits64 (bits 0-7)" (fun () -> Int64.to_int (Random.bits64())); test "Random.bits64 (bits 30-37)" (fun () -> Int64.(to_int (shift_right (Random.bits64()) 30))); test "Random.bits64 (bits 52-59)" (fun () -> Int64.(to_int (shift_right (Random.bits64()) 52))); + + (* [int64] *) test "Random.int64 2^60 (bits 0-7)" (fun () -> Int64.to_int (Random.int64 0x1000000000000000L)); test "Random.int64 2^60 (bits 30-37)" @@ -76,6 +99,8 @@ let _ = test "Random.int64 (256 * p) / p" (let p = 16430454264262693L in fun () -> Int64.(to_int (div (Random.int64 (mul 256L p)) p))); + + (* [full_int] *) if Sys.int_size >= 32 then begin test "Random.full_int 2^30 (bits 0-7)" (fun () -> Random.full_int (1 lsl 30)); @@ -96,6 +121,178 @@ let _ = (let p = Int64.to_int 17766642568158577L in fun () -> Random.full_int (256 * p) / p) end; + + (* [int_in_range] *) + + let min_ = -214748364 in + let max_ = min_ + 0x1FFF_FFFF in + test "Random.int_in_range, range of length 2^29 (bits 0-7)" + (fun () -> Random.int_in_range ~min:min_ ~max:max_ - min_); + test "Random.int_in_range, range of length 2^29 (bits 21-28)" + (fun () -> (Random.int_in_range ~min:min_ ~max:max_ - min_) lsr 21); + let min_ = -214748364 in + let max_ = min_ + 0x3FFF_FFFF in + test "Random.int_in_range, range of length 2^30 (bits 0-7)" + (fun () -> Random.int_in_range ~min:min_ ~max:max_ - min_); + test "Random.int_in_range, range of length 2^30 (bits 22-29)" + (fun () -> (Random.int_in_range ~min:min_ ~max:max_ - min_) lsr 22); + let min_int31 = -0x4000_0000 in + let max_int31 = 0x3FFF_FFFF in + test "Random.int_in_range, full int31 range (bits 0-7)" + (fun () -> Random.int_in_range ~min:min_int31 ~max:max_int31); + test "Random.int_in_range, full int31 range (bits 23-30)" + (fun () -> (Random.int_in_range ~min:min_int31 ~max:max_int31) lsr 23); + test "Random.int_in_range, range of length 256*p < 2^30 (bits 0-7)" + (let p = 2_097_169 in (* prime < 2^22 *) + let min_ = -214748364 in + let max_ = min_ + (256 * p) - 1 in + fun () -> (Random.int_in_range ~min:min_ ~max:max_ - min_) / p); + test "Random.int_in_range, range of length 2^30 < 256*p < 2^31 (bits 0-7)" + (let p = 6_291_469 in (* prime > 2^22 and < 2^23 *) + let min_ = min_int in + let max_ = min_ + (256 * p) - 1 in + fun () -> udiv (Random.int_in_range ~min:min_ ~max:max_ - min_) p); + if Sys.int_size >= 32 then begin + let min_int32 = Int64.to_int (-0x8000_0000L) in + let max_int32 = Int64.to_int 0x7FFF_FFFFL in + test "Random.int_in_range, full int32 range (bits 0-7)" + (fun () -> Random.int_in_range ~min:min_int32 ~max:max_int32); + test "Random.int_in_range, full int32 range (bits 24-31)" + (fun () -> (Random.int_in_range ~min:min_int32 ~max:max_int32) lsr 24); + test "Random.int_in_range, range of length 2^31 < 256*p < 2^32 (bits 0-7)" + (let p = 12_582_917 in (* prime > 2^23 and < 2^24 *) + let min_ = min_int in + let max_ = min_ + (256 * p) - 1 in + fun () -> udiv (Random.int_in_range ~min:min_ ~max:max_ - min_) p); + end; + if Sys.int_size >= 63 then begin + let min_ = Int64.to_int (-1844674407370955197L) in + let max_ = min_ + Int64.to_int 0x1FFF_FFFF_FFFF_FFFFL in + test "Random.int_in_range, range of length 2^61 (bits 0-7)" + (fun () -> Random.int_in_range ~min:min_ ~max:max_ - min_); + test "Random.int_in_range, range of length 2^61 (bits 30-37)" + (fun () -> (Random.int_in_range ~min:min_ ~max:max_ - min_) lsr 30); + test "Random.int_in_range, range of length 2^61 (bits 53-60)" + (fun () -> (Random.int_in_range ~min:min_ ~max:max_ - min_) lsr 53); + let min_ = Int64.to_int (-1844674407370955197L) in + let max_ = min_ + Int64.to_int 0x3FFF_FFFF_FFFF_FFFFL in + test "Random.int_in_range, range of length 2^62 (bits 0-7)" + (fun () -> Random.int_in_range ~min:min_ ~max:max_ - min_); + test "Random.int_in_range, range of length 2^62 (bits 30-37)" + (fun () -> (Random.int_in_range ~min:min_ ~max:max_ - min_) lsr 30); + test "Random.int_in_range, range of length 2^62 (bits 54-61)" + (fun () -> (Random.int_in_range ~min:min_ ~max:max_ - min_) lsr 54); + test "Random.int_in_range, full int range (bits 0-7)" + (fun () -> Random.int_in_range ~min:min_int ~max:max_int); + test "Random.int_in_range, full int range (bits 30-37)" + (fun () -> (Random.int_in_range ~min:min_int ~max:max_int) lsr 30); + test "Random.int_in_range, full int range (bits 55-62)" + (fun () -> (Random.int_in_range ~min:min_int ~max:max_int) lsr 55); + test "Random.int_in_range, range of length 2^61 < 256*p < 2^62 (bits 0-7)" + (let p = Int64.to_int 13510798882111519L in (*prime > 2^53 and < 2^54 *) + let min_ = min_int in + let max_ = min_ + (256 * p) - 1 in + fun () -> (Random.int_in_range ~min:min_ ~max:max_ - min_) / p); + test "Random.int_in_range, range of length 256*p > 2^62 (bits 0-7)" + (let p = Int64.to_int 27021597764223071L in (*prime > 2^54 and < 2^55 *) + let min_ = min_int in + let max_ = min_ + (256 * p) - 1 in + fun () -> udiv (Random.int_in_range ~min:min_ ~max:max_ - min_) p); + end; + + (* [int32_in_range] *) + let min_ = -429496751l in + let max_ = Int32.add min_ 0x3FFF_FFFFl in + test "Random.int32_in_range, range of length 2^30 (bits 0-7)" + (fun () -> Int32.(to_int + (sub (Random.int32_in_range ~min:min_ ~max:max_) min_))); + test "Random.int32_in_range, range of length 2^30 (bits 22-29)" + (fun () -> Int32.(to_int (shift_right + (sub (Random.int32_in_range ~min:min_ ~max:max_) min_) + 22))); + let min_ = -429496751l in + let max_ = Int32.add min_ 0x7FFF_FFFFl in + test "Random.int32_in_range, range of length 2^31 (bits 0-7)" + (fun () -> Int32.(to_int + (sub (Random.int32_in_range ~min:min_ ~max:max_) min_))); + test "Random.int32_in_range, range of length 2^31 (bits 23-30)" + (fun () -> Int32.(to_int (shift_right + (sub (Random.int32_in_range ~min:min_ ~max:max_) min_) + 23))); + test "Random.int32_in_range, full int32 range (bits 0-7)" + (fun () -> Int32.(to_int + (Random.int32_in_range ~min:min_int ~max:max_int))); + test "Random.int32_in_range, full int32 range (bits 24-31)" + (fun () -> Int32.(to_int (shift_right + (Random.int32_in_range ~min:min_int ~max:max_int) + 24))); + test "Random.int32_in_range, range of length 256*p < 2^31 (bits 0-7)" + (let p = 6_291_469l in (* prime < 2^23 *) + let min_ = -429496751l in + let max_ = Int32.(pred (add min_ (mul 256l p))) in + fun () -> Int32.(to_int + (div (sub (Random.int32_in_range ~min:min_ ~max:max_) min_) p))); + test "Random.int32_in_range, range of length 256*p > 2^31 (bits 0-7)" + (let p = 12_582_917l in (* prime > 2^23 and < 2^24 *) + let min_ = Int32.min_int in + let max_ = Int32.(pred (add min_ (mul 256l p))) in + fun () -> Int32.(to_int + (unsigned_div (sub (Random.int32_in_range ~min:min_ ~max:max_) min_) + p))); + + (* [int64_in_range] *) + let min_ = -1844674407370955197L in + let max_ = Int64.add min_ 0x3FFF_FFFF_FFFF_FFFFL in + test "Random.int64_in_range, range of length 2^62 (bits 0-7)" + (fun () -> Int64.(to_int + (sub (Random.int64_in_range ~min:min_ ~max:max_) min_))); + test "Random.int64_in_range, range of length 2^62 (bits 30-37)" + (fun () -> Int64.(to_int (shift_right + (sub (Random.int64_in_range ~min:min_ ~max:max_) min_) + 30))); + test "Random.int64_in_range, range of length 2^62 (bits 54-61)" + (fun () -> Int64.(to_int (shift_right + (sub (Random.int64_in_range ~min:min_ ~max:max_) min_) + 54))); + let min_ = -1844674407370955197L in + let max_ = Int64.add min_ 0x7FFF_FFFF_FFFF_FFFFL in + test "Random.int64_in_range, range of length 2^63 (bits 0-7)" + (fun () -> Int64.(to_int + (sub (Random.int64_in_range ~min:min_ ~max:max_) min_))); + test "Random.int64_in_range, range of length 2^63 (bits 30-37)" + (fun () -> Int64.(to_int (shift_right + (sub (Random.int64_in_range ~min:min_ ~max:max_) min_) + 30))); + test "Random.int64_in_range, range of length 2^63 (bits 55-62)" + (fun () -> Int64.(to_int (shift_right + (sub (Random.int64_in_range ~min:min_ ~max:max_) min_) + 55))); + test "Random.int64_in_range, full int64 range (bits 0-7)" + (fun () -> Int64.(to_int + (Random.int64_in_range ~min:min_int ~max:max_int))); + test "Random.int64_in_range, full int64 range (bits 30-37)" + (fun () -> Int64.(to_int (shift_right + (Random.int64_in_range ~min:min_int ~max:max_int) + 30))); + test "Random.int64_in_range, full int64 range (bits 56-63)" + (fun () -> Int64.(to_int (shift_right + (Random.int64_in_range ~min:min_int ~max:max_int) + 56))); + test "Random.int64_in_range, range of length 256*p < 2^63 (bits 0-7)" + (let p = 27021597764223071L in (* prime < 2^55 *) + let min_ = -1844674407370955197L in + let max_ = Int64.(pred (add min_ (mul 256L p))) in + fun () -> Int64.(to_int + (div (sub (Random.int64_in_range ~min:min_ ~max:max_) min_) p))); + test "Random.int64_in_range, range of length 256*p > 2^63 (bits 0-7)" + (let p = 54043195528445957L in (* prime > 2^55 and < 2^56 *) + let min_ = Int64.min_int in + let max_ = Int64.(pred (add min_ (mul 256L p))) in + fun () -> Int64.(to_int + (unsigned_div (sub (Random.int64_in_range ~min:min_ ~max:max_) min_) + p))); + + (* [split] *) let r1 = Random.split() in let r2 = Random.split() in let r3 = Random.State.split r1 in diff --git a/compiler/tests-ocaml/lib-random/compat_32_64.expected b/compiler/tests-ocaml/lib-random/compat_32_64.expected new file mode 100644 index 0000000000..32026cd625 --- /dev/null +++ b/compiler/tests-ocaml/lib-random/compat_32_64.expected @@ -0,0 +1,156 @@ +691769754 +1061553262 +344373510 +616584865 +2616996 +582111861 +403737495 +786655037 +234874283 +861395434 +772162098 +917958495 +53725144 +862765034 +568000806 +978003028 +879053180 +588214058 +54672416 +802084138 +884612654 +268599649 +714738946 +899342876 +50068887 +378318794 +495447764 +227504342 +610800572 +328600136 +333963177 +956808855 +916073717 +324922837 +271778746 +12481130 +855825287 +90864420 +508292232 +27636216 +1029983911 +291793467 +689728247 +229322728 +45172927 +107738202 +292122103 +618814194 +711332398 +554972104 + +-1073741530 +-1073740888 +-1073741782 +-1073741019 +-1073740859 +-1073740865 +-1073741534 +-1073741577 +-1073741282 +-1073741163 +-1073741513 +-1073741034 +-1073741500 +-1073741368 +-1073741290 +-1073741244 +-1073741270 +-1073741269 +-1073741439 +-1073741377 +-1073741692 +-1073741341 +-1073741140 +-1073740989 +-1073741504 +-1073741276 +-1073741273 +-1073740998 +-1073741366 +-1073741750 +-1073741279 +-1073741219 +-1073741771 +-1073741731 +-1073741608 +-1073740877 +-1073741738 +-1073741048 +-1073741059 +-1073741346 +-1073741209 +-1073741593 +-1073741116 +-1073741048 +-1073741793 +-1073741416 +-1073741431 +-1073740978 +-1073740848 +-1073741504 + +838038025 +1060073484 +-555975041 +-825987583 +975134752 +831716180 +330110777 +-119695492 +929643271 +52572337 +464726704 +136828399 +-978275585 +-518656455 +723340377 +-551292710 +980383878 +-736276577 +75010286 +-992468772 +-1022581416 +-810312547 +-813307923 +461161247 +-437494086 +-308452031 +856020781 +-90096979 +426279563 +-292766912 +-487493925 +570776330 +-470717058 +-447203604 +70094832 +794730351 +741719169 +-167883286 +70654065 +79129735 +315532303 +746624829 +992716426 +477281232 +558865877 +103841147 +966710857 +-304632204 +-539866915 +-558915649 + +true +true +true diff --git a/compiler/tests-ocaml/lib-random/compat_32_64.ml b/compiler/tests-ocaml/lib-random/compat_32_64.ml new file mode 100644 index 0000000000..cb0d8d6284 --- /dev/null +++ b/compiler/tests-ocaml/lib-random/compat_32_64.ml @@ -0,0 +1,123 @@ +(* TEST *) + +(* Check that [full_int] and [int_in_range] yield the same outputs + * - for 31-bit input on every tested platform; + * - for 32-bit input on every tested platform where [Sys.int_size >= 32]. *) + +let min_int31 = -0x4000_0000 (* = -2^30 *) +let max_int31 = 0x3FFF_FFFF (* = 2^30-1 *) +let min_int32 = -(1 lsl 31) + (* = -0x8000_0000 on platforms where [Sys.int_size >= 32] *) +let max_int32 = (1 lsl 31) - 1 + (* = 0x7FFF_FFFF on platforms where [Sys.int_size >= 32] *) + +let expected__full_int__int32 = + List.map Int64.to_int + [ + 451177519L; 819244110L; 1569039028L; 1898166382L; 382924821L; + 369901015L; 352113804L; 405163262L; 1999817968L; 626859825L; + 1606096148L; 768468192L; 2112068721L; 360408220L; 1086772984L; + 155961157L; 407238554L; 422041964L; 315222802L; 2141327316L; + 927599929L; 307430453L; 1936714909L; 1017363199L; 2125175059L; + 1311994963L; 759137410L; 212550723L; 1706544910L; 810893211L; + 2056429253L; 1079086093L; 1713675986L; 753193678L; 276572642L; + 530348252L; 617726581L; 944299189L; 674895562L; 32787006L; + 1830016271L; 1067904883L; 589173623L; 950337835L; 2078987417L; + 1487106135L; 569957530L; 2015304950L; 885035468L; 234722862L; + ] + +let expected__int_in_range__int32 = + List.map Int64.to_int + [ + -2147483542L; -2147483052L; -2147483634L; -2147483498L; -2147483224L; + -2147482666L; -2147483631L; -2147483278L; -2147483612L; -2147482799L; + -2147483421L; -2147482825L; -2147483593L; -2147483470L; -2147483177L; + -2147482829L; -2147483463L; -2147482933L; -2147483591L; -2147482786L; + -2147483446L; -2147483415L; -2147482710L; -2147482883L; -2147483199L; + -2147482957L; -2147482912L; -2147483195L; -2147483513L; -2147482887L; + -2147483394L; -2147483434L; -2147483251L; -2147483597L; -2147482693L; + -2147483453L; -2147482724L; -2147483596L; -2147482822L; -2147482813L; + -2147483565L; -2147482939L; -2147483428L; -2147483274L; -2147483612L; + -2147483279L; -2147482698L; -2147483617L; -2147483301L; -2147483082L; + ] + +let expected__int_in_range__full_int32_range = + List.map Int64.to_int + [ + 316667342L; -295023111L; 1894765368L; 185794834L; -981816301L; + 740994304L; -680489891L; 278403874L; -2032365355L; -71571733L; + -313777328L; -689756819L; -980386453L; 82099031L; 1573778309L; + -760895485L; 511322260L; 1825182001L; 954732521L; -1492321820L; + 773383493L; -1681170167L; 2067003710L; -1742733312L; 1195851762L; + 1602173427L; -357434044L; -1334661233L; -128246722L; -2094933952L; + -431878364L; 1978816493L; 808773565L; -1454547995L; 364583207L; + 2002713488L; -786979985L; 964103855L; -1430475164L; 1303482935L; + -356009461L; -111417631L; 1106019824L; -1988580373L; 1586895675L; + -1580402270L; 2061313798L; -1676201176L; 975189254L; -361726938L; + ] + +let _ = + + (* Test outputs for 31-bit input: *) + if Sys.int_size >= 31 then begin + + (* [full_int], range that fits in 30 bits: *) + for i = 0 to 49 do + Printf.printf "%i\n" (Random.full_int max_int31) + done; + print_newline (); + + (* [int_in_range], all-negative range whose length fits in 30 bits: *) + for i = 0 to 49 do + Printf.printf "%i\n" + (Random.int_in_range ~min:min_int31 ~max:(min_int31 + 996)) + done; + print_newline (); + + (* [int_in_range], full 31-bit range: *) + for i = 0 to 49 do + Printf.printf "%i\n" + (Random.int_in_range ~min:min_int31 ~max:max_int31) + done; + print_newline (); + + end; + + (* Test outputs for 32-bit input: *) + if Sys.int_size >= 32 then begin + + (* [full_int], range that fits in 31 bits: *) + let ok = ref true in + expected__full_int__int32 |> + List.iter begin fun expected -> + ok := !ok && expected = + (Random.full_int max_int32) + end ; + Printf.printf "%b\n" !ok; + + (* [int_in_range], all-negative range whose length fits in 31 bits: *) + let ok = ref true in + expected__int_in_range__int32 |> + List.iter begin fun expected -> + ok := !ok && expected = + (Random.int_in_range ~min:min_int32 ~max:(min_int32 + 996)) + end ; + Printf.printf "%b\n" !ok; + + (* [int_in_range], full 32-bit range: *) + let ok = ref true in + expected__int_in_range__full_int32_range |> + List.iter begin fun expected -> + ok := !ok && expected = + (Random.int_in_range ~min:min_int32 ~max:max_int32) + end ; + Printf.printf "%b\n" !ok; + + end + else begin + Printf.printf "true\ntrue\ntrue\n" ; + end; + + () + +let _ = exit 0 diff --git a/compiler/tests-ocaml/lib-random/defaultinit.ml b/compiler/tests-ocaml/lib-random/defaultinit.ml index df3550374e..8c5b095bae 100644 --- a/compiler/tests-ocaml/lib-random/defaultinit.ml +++ b/compiler/tests-ocaml/lib-random/defaultinit.ml @@ -1,5 +1,5 @@ (* TEST - include testing + include testing; *) (* Check that the numbers drawn from the default state are the same @@ -17,3 +17,5 @@ let _ = done let _ = exit 0 + +include Testing diff --git a/compiler/tests-ocaml/lib-random/dune b/compiler/tests-ocaml/lib-random/dune index 6c1c5e29e1..fe3acf3113 100644 --- a/compiler/tests-ocaml/lib-random/dune +++ b/compiler/tests-ocaml/lib-random/dune @@ -1,8 +1,8 @@ (tests - (names chi2 selfinit testvectors) + (names chi2 selfinit defaultinit testvectors compat_32_64) (build_if - (>= %{ocaml_version} 5)) - (libraries) + (>= %{ocaml_version} 5.2)) + (libraries ocaml_testing) (modes js wasm diff --git a/compiler/tests-ocaml/lib-random/testvectors.ml b/compiler/tests-ocaml/lib-random/testvectors.ml index c7883e3cd2..b8f09ae058 100644 --- a/compiler/tests-ocaml/lib-random/testvectors.ml +++ b/compiler/tests-ocaml/lib-random/testvectors.ml @@ -11,7 +11,7 @@ let _ = (* Violate abstraction of type Random.State.t to manipulate state directly *) let r = (Obj.magic a : Random.State.t) in for i = 0 to 49 do - Printf.printf "%Ld\n" (Random.State.bits64 r); + Printf.printf "%Ld\n" (Random.State.bits64 r) done let _ = exit 0 diff --git a/compiler/tests-ocaml/lib-seq/dune b/compiler/tests-ocaml/lib-seq/dune index 16342d6417..a53598eb62 100644 --- a/compiler/tests-ocaml/lib-seq/dune +++ b/compiler/tests-ocaml/lib-seq/dune @@ -1,4 +1,6 @@ (tests (names test) + (build_if + (>= %{ocaml_version} 5.3)) (libraries) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-seq/test.ml b/compiler/tests-ocaml/lib-seq/test.ml index bd5e467162..31913dc419 100644 --- a/compiler/tests-ocaml/lib-seq/test.ml +++ b/compiler/tests-ocaml/lib-seq/test.ml @@ -246,6 +246,31 @@ let () = = (List.of_seq s |> List.sort compare)); () +(* [find_index] *) +let () = + assert (Seq.find_index (fun x -> x=1) !?[] = None); + let xs = !?[1;2;3;4;5] in + assert (Seq.find_index (fun x -> x=1) xs = Some 0); + assert (Seq.find_index (fun x -> x=3) xs = Some 2); + assert (Seq.find_index (fun x -> x=5) xs = Some 4); + assert (Seq.find_index (fun x -> x=6) xs = None); + () + +(* [find_mapi] *) +let () = + assert (Seq.find_mapi + (fun i x -> if x+i=3 then Some(i, x) else None) !?[] = None); + let xs = !?[3;3;3;42;42] in + assert (Seq.find_mapi + (fun i x -> if x+i=3 then Some(i, x) else None) xs = Some (0, 3)); + assert (Seq.find_mapi + (fun i x -> if x+i=4 then Some(i, x) else None) xs = Some (1, 3)); + assert (Seq.find_mapi + (fun i x -> if x+i=5 then Some(i, x) else None) xs = Some (2, 3)); + assert (Seq.find_mapi + (fun i x -> if x+i=7 then Some(i, x) else None) xs = None); + () + (* Auxiliary definitions of 2d matrices. *) let square n f = Seq.(init n (fun i -> init n (fun j -> f i j))) diff --git a/compiler/tests-ocaml/lib-stack/dune b/compiler/tests-ocaml/lib-stack/dune index 16342d6417..a53598eb62 100644 --- a/compiler/tests-ocaml/lib-stack/dune +++ b/compiler/tests-ocaml/lib-stack/dune @@ -1,4 +1,6 @@ (tests (names test) + (build_if + (>= %{ocaml_version} 5.3)) (libraries) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-stack/test.ml b/compiler/tests-ocaml/lib-stack/test.ml index 5023b12b2a..16544f3fb6 100644 --- a/compiler/tests-ocaml/lib-stack/test.ml +++ b/compiler/tests-ocaml/lib-stack/test.ml @@ -118,4 +118,24 @@ let () = assert (S.length s2 = 4); assert (S.to_list s2 = [1; 2; 3; 4]); ;; +let () = + let s = S.create () in + S.push 0 s; + S.push 1 s; + S.push 2 s; + assert (S.to_list s = [0; 1; 2]); + S.drop s; + assert (S.to_list s = [0; 1]); + S.drop s; + assert (S.to_list s = [0]); + S.drop s; + assert (S.to_list s = []); + begin + try + S.drop s; + assert false + with S.Empty -> () + end; +;; + let () = print_endline "OK" diff --git a/compiler/tests-ocaml/lib-str/t01.ml b/compiler/tests-ocaml/lib-str/t01.ml index 076172bdcb..ec8590157f 100644 --- a/compiler/tests-ocaml/lib-str/t01.ml +++ b/compiler/tests-ocaml/lib-str/t01.ml @@ -1,8 +1,11 @@ (* TEST -* hasstr -include str -** bytecode -** native + include str; + hasstr; + { + bytecode; + }{ + native; + } *) open Printf diff --git a/compiler/tests-ocaml/lib-string/test_string.expected b/compiler/tests-ocaml/lib-string/test_string.expected index 982fba6640..2a48fe5556 100644 --- a/compiler/tests-ocaml/lib-string/test_string.expected +++ b/compiler/tests-ocaml/lib-string/test_string.expected @@ -1,4 +1,4 @@ -- Hashtbl.hash raw_string: 240a0e56 --- String.unseeded_hash raw_string: 240a0e56 +-- String.hash raw_string: 240a0e56 -- Hashtbl.seeded_hash 16 raw_string: 3210af30 --- String.hash 16 raw_string: 3210af30 +-- String.seeded_hash 16 raw_string: 3210af30 diff --git a/compiler/tests-ocaml/lib-string/test_string.ml b/compiler/tests-ocaml/lib-string/test_string.ml index 1ba9bbdb5d..953da365c4 100644 --- a/compiler/tests-ocaml/lib-string/test_string.ml +++ b/compiler/tests-ocaml/lib-string/test_string.ml @@ -44,15 +44,15 @@ let () = let () = printf "-- Hashtbl.hash raw_string: %x\n%!" (Hashtbl.hash raw_string); - printf "-- String.unseeded_hash raw_string: %x\n%!" (String.hash raw_string); + printf "-- String.hash raw_string: %x\n%!" (String.hash raw_string); printf "-- Hashtbl.seeded_hash 16 raw_string: %x\n%!" (Hashtbl.seeded_hash 16 raw_string); - printf "-- String.hash 16 raw_string: %x\n%!" (String.seeded_hash 16 raw_string); + printf "-- String.seeded_hash 16 raw_string: %x\n%!" (String.seeded_hash 16 raw_string); ;; (* GPR#805/815/833 *) -let () = - if Sys.word_size = 32 then begin -(* +let () = + if Sys.word_size = 32 && Sys.backend_type = Native || Sys.backend_type = Bytecode + then begin let big = String.make Sys.max_string_length 'x' in let push x l = l := x :: !l in let (+=) a b = a := !a + b in @@ -61,7 +61,9 @@ let () = while !sz <= 0 do push big l; sz += Sys.max_string_length done; try ignore (String.concat "" !l); assert false with Invalid_argument _ -> (); -*) + end + +let () = assert(String.starts_with ~prefix:"foob" "foobarbaz"); assert(String.starts_with ~prefix:"" "foobarbaz"); assert(String.starts_with ~prefix:"" ""); @@ -74,4 +76,3 @@ let () = assert(not (String.ends_with ~suffix:"foobar" "bar")); assert(not (String.ends_with ~suffix:"foo" "")); assert(not (String.ends_with ~suffix:"obaz" "foobar")); - end diff --git a/compiler/tests-ocaml/lib-uchar/dune b/compiler/tests-ocaml/lib-uchar/dune index 16342d6417..f153036e8a 100644 --- a/compiler/tests-ocaml/lib-uchar/dune +++ b/compiler/tests-ocaml/lib-uchar/dune @@ -1,4 +1,6 @@ (tests + (build_if + (>= %{ocaml_version} 5.3)) (names test) (libraries) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-uchar/test.ml b/compiler/tests-ocaml/lib-uchar/test.ml index 14e907d230..134fdf0023 100644 --- a/compiler/tests-ocaml/lib-uchar/test.ml +++ b/compiler/tests-ocaml/lib-uchar/test.ml @@ -1,5 +1,4 @@ -(* TEST -*) +(* TEST *) let assert_raise_invalid_argument f v = assert (try ignore (f v); false with Invalid_argument _ -> true) @@ -72,6 +71,14 @@ let test_compare () = assert (Uchar.(compare max min) = 1); () +let test_hash () = + let f u = + assert (Hashtbl.hash u = Uchar.hash u); + assert (Hashtbl.seeded_hash 42 u = Uchar.seeded_hash 42 u) + in + List.iter (Fun.compose f Uchar.of_int) + [0x0000; 0x002D; 0x00E9; 0x062D; 0x2014; 0x1F349] + let test_utf_decode () = let d0 = Uchar.utf_decode 1 Uchar.min in let d1 = Uchar.utf_decode 4 Uchar.max in @@ -110,6 +117,7 @@ let tests () = test_to_char (); test_equal (); test_compare (); + test_hash (); test_utf_decode (); test_utf_x_byte_length (); () diff --git a/compiler/tests-ocaml/prim-revapply/apply.ml b/compiler/tests-ocaml/prim-revapply/apply.ml index 4f947d9771..8b557e152f 100644 --- a/compiler/tests-ocaml/prim-revapply/apply.ml +++ b/compiler/tests-ocaml/prim-revapply/apply.ml @@ -1,4 +1,5 @@ (* TEST + flags = "-w +48"; *) external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply" @@ -37,3 +38,24 @@ let _ = h @@ g @@ f @@ 3; (* 37 *) add 4 @@ g @@ f @@ add 3 @@ add 2 @@ 3; (* 260 *) ] + +(* PR#10081 *) +let bump ?(cap = 100) x = min cap (x + 1) +let _f x = bump @@ x (* no warning 48 *) + +(* Abstract functions *) +let _ = + let module A:sig + type f + type x + val succ: f + val zero:x + external (@@): f -> x -> int = "%apply" + end = struct + type f = int -> int + type x = int + let succ = succ + let zero = 0 + external (@@): f -> x -> int = "%apply" + end in + A.(succ @@ zero) diff --git a/compiler/tests-ocaml/prim-revapply/dune b/compiler/tests-ocaml/prim-revapply/dune index 017e60f37c..7e5c2e25ee 100644 --- a/compiler/tests-ocaml/prim-revapply/dune +++ b/compiler/tests-ocaml/prim-revapply/dune @@ -1,4 +1,6 @@ (tests (names apply revapply) (libraries) + (flags + (:standard -w -34-37)) (modes js wasm)) diff --git a/compiler/tests-ocaml/prim-revapply/revapply.ml b/compiler/tests-ocaml/prim-revapply/revapply.ml index 32435562af..341548c2eb 100644 --- a/compiler/tests-ocaml/prim-revapply/revapply.ml +++ b/compiler/tests-ocaml/prim-revapply/revapply.ml @@ -1,4 +1,5 @@ (* TEST + flags = "-w +48"; *) external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply" @@ -19,3 +20,30 @@ let _ = 3 |> f |> g |> h; (* 37 *) 3 |> add 2 |> add 3 |> f |> g |> add 4; (* 260 *) ] + + +(* PR#10081 *) +let bump ?(cap = 100) x = min cap (x + 1) +let _f x = x |> bump (* no warning 48 *) + +(* PR#10081 *) +type t = A | B +type s = A | B +let _f (x : t) = x |> function A -> 0 | B -> 1 + +(* Abstract functions *) +let _ = + let module A:sig + type f + type x + val succ: f + val zero:x + external (|>): x -> f -> int = "%revapply" + end = struct + type f = int -> int + type x = int + let succ = succ + let zero = 0 + external (|>): x -> f -> int = "%revapply" + end in + A.(zero |> succ) diff --git a/compiler/tests-ocaml/lib-bytes/testing.ml b/compiler/tests-ocaml/testing.ml similarity index 100% rename from compiler/tests-ocaml/lib-bytes/testing.ml rename to compiler/tests-ocaml/testing.ml diff --git a/tools/dune b/tools/dune index f5589b29cc..5953c6bc08 100644 --- a/tools/dune +++ b/tools/dune @@ -7,3 +7,8 @@ (name ci_setup) (modules ci_setup) (libraries opam-format unix)) + +(executable + (name sync_testsuite) + (modules sync_testsuite) + (libraries)) diff --git a/tools/sync_testsuite.ml b/tools/sync_testsuite.ml new file mode 100644 index 0000000000..cf6fbdf8b7 --- /dev/null +++ b/tools/sync_testsuite.ml @@ -0,0 +1,114 @@ +module File = struct + type t = + | Ml of string + | Dir of string + | Expected of string + + let compare a b = compare a b + + let concat a b = + match b with + | Ml x -> Ml (Filename.concat a x) + | Dir x -> Dir (Filename.concat a x) + | Expected x -> Expected (Filename.concat a x) +end + +module FileSet = Set.Make (File) + +let src, dst = + match Sys.argv with + | [| _; src; dst |] -> src, dst + | _ -> failwith (Printf.sprintf "%s OCAMLTESTDIR JSOOTESTDIR" Sys.executable_name) + +let readdir s = + Sys.readdir s + |> Array.to_seq + |> Seq.filter_map (fun f -> + if Sys.is_directory (Filename.concat s f) + then Some (File.Dir f) + else if String.ends_with ~suffix:".ml" f + then Some (File.Ml f) + else if String.ends_with ~suffix:".expected" f + then Some (File.Expected (Filename.chop_suffix f ".expected")) + else if String.ends_with ~suffix:".reference" f + then Some (File.Expected (Filename.chop_suffix f ".reference")) + else None) + |> FileSet.of_seq + +let split a b = FileSet.diff a b, FileSet.inter a b, FileSet.diff b a + +let _ignore_ x = + if String.starts_with ~prefix:"typing-" x + then `Typing + else if String.starts_with ~prefix:"tool-" x + then `Tool + else if String.starts_with ~prefix:"lib-dynlink-" x + then `Dynlink + else + match x with + | "lib-either" -> `Expect + | "lib-array" -> `Expect + | "lib-bigarray-2" -> `Stubs + | "lib-digest/blake2b_self_test.ml" -> `Stubs + | "lib-bigarray-file" -> `Mapfile + | "lib-lazy" -> `Expect + | "lib-internalformat" -> `Expect + | "lib-random/parallel.ml" | "lib-str/parallel.ml" -> `Parallel + | "lib-hashtbl/compatibility.ml" -> `Old + | _ -> `No + +let () = + let rec diff f a b path = + let a0 = Filename.concat a path and b0 = Filename.concat b path in + let ad = readdir a0 and bd = readdir b0 in + let missing, common, extra = split ad bd in + FileSet.iter (fun x -> f (`Missing (File.concat path x))) missing; + FileSet.iter (fun x -> f (`Extra (File.concat path x))) extra; + FileSet.iter + (function + | Dir x -> diff f a b (Filename.concat path x) + | Ml x -> f (`Same (Filename.concat path x)) + | Expected x -> f (`Expected (Filename.concat path x))) + common + in + diff + (function + | `Missing (Dir x | Ml x) -> ( + match _ignore_ x with + | `Tool | `Typing | `Dynlink | `Expect -> () + | `Stubs | `Old -> () + | `Parallel -> () + | `Mapfile -> () + | `No -> Printf.eprintf "missing %s\n" x) + | `Missing (Expected x) -> ( + match _ignore_ (x ^ ".ml") with + | `Tool | `Typing | `Dynlink | `Expect -> () + | `Stubs | `Old -> () + | `Parallel -> () + | `Mapfile -> () + | `No -> Printf.eprintf "missing expected %s\n" x) + | `Extra (Dir "effects-2") -> () + | `Extra (Ml "testing.ml") -> () + | `Extra (Expected x) -> Printf.eprintf "extra expected %s\n" x + | `Extra (Dir x | Ml x) -> Printf.eprintf "extra %s\n" x + | `Same x -> ( + Sys.command + (Printf.sprintf + "patdiff %s %s" + (Filename.concat src x) + (Filename.concat dst x)) + |> function + | 0 -> () + | _ -> Printf.eprintf "differ %s\n" x) + | `Expected x -> ( + Sys.command + (Printf.sprintf + "patdiff %s.reference %s.expected" + (Filename.concat src x) + (Filename.concat dst x)) + |> function + | 0 -> () + | _ -> Printf.eprintf "differ %s\n" x)) + src + dst + ""