mte/unikernel/duniverse/base/test/test_hashtbl.ml
2025-11-11 02:07:51 +01:00

150 lines
4.3 KiB
OCaml

open! Base
open Expect_test_helpers_base
type int_hashtbl = int Hashtbl.M(Int).t [@@deriving sexp]
let%test "Hashtbl.merge succeeds with first-class-module interface" =
let t1 = Hashtbl.create (module Int) in
let t2 = Hashtbl.create (module Int) in
let result =
Hashtbl.merge t1 t2 ~f:(fun ~key:_ -> function
| `Left x -> x
| `Right x -> x
| `Both _ -> assert false)
|> Hashtbl.to_alist
in
List.equal Poly.equal result []
;;
let%test_module _ =
(module Hashtbl_tests.Make (struct
include Hashtbl
let create_poly ?size () = Poly.create ?size ()
let of_alist_poly_exn l = Poly.of_alist_exn l
let of_alist_poly_or_error l = Poly.of_alist_or_error l
end))
;;
let%expect_test "Hashtbl.find_exn" =
let table = Hashtbl.of_alist_exn (module String) [ "one", 1; "two", 2; "three", 3 ] in
let test_success key =
require_does_not_raise [%here] (fun () ->
print_s [%sexp (Hashtbl.find_exn table key : int)])
in
test_success "one";
[%expect {| 1 |}];
test_success "two";
[%expect {| 2 |}];
test_success "three";
[%expect {| 3 |}];
let test_failure key =
require_does_raise [%here] (fun () -> Hashtbl.find_exn table key)
in
test_failure "zero";
[%expect {| (Not_found_s ("Hashtbl.find_exn: not found" zero)) |}];
test_failure "four";
[%expect {| (Not_found_s ("Hashtbl.find_exn: not found" four)) |}]
;;
let%expect_test "[t_of_sexp] error on duplicate" =
let sexp = Sexplib.Sexp.of_string "((0 a)(1 b)(2 c)(1 d))" in
(match [%of_sexp: string Hashtbl.M(String).t] sexp with
| t -> print_cr [%here] [%message "did not raise" (t : string Hashtbl.M(String).t)]
| exception (Sexp.Of_sexp_error _ as exn) -> print_s (sexp_of_exn exn)
| exception exn -> print_cr [%here] [%message "wrong kind of exception" (exn : exn)]);
[%expect {| (Of_sexp_error "Hashtbl.t_of_sexp: duplicate key" (invalid_sexp 1)) |}]
;;
let%expect_test "[choose], [choose_exn], [choose_randomly], [choose_randomly_exn]" =
let test ?size l =
let t = l |> List.map ~f:(fun i -> i, i) |> Hashtbl.of_alist_exn ?size (module Int) in
print_s
[%message
""
~input:(t : int_hashtbl)
~choose:(Hashtbl.choose t : (_ * _) option)
~choose_exn:
(Or_error.try_with (fun () -> Hashtbl.choose_exn t) : (_ * _) Or_error.t)
~choose_randomly:(Hashtbl.choose_randomly t : (_ * _) option)
~choose_randomly_exn:
(Or_error.try_with (fun () -> Hashtbl.choose_randomly_exn t)
: (_ * _) Or_error.t)]
in
test [];
[%expect
{|
((input ())
(choose ())
(choose_exn (Error ("[Hashtbl.choose_exn] of empty hashtbl")))
(choose_randomly ())
(choose_randomly_exn (
Error ("[Hashtbl.choose_randomly_exn] of empty hashtbl"))))
|}];
test [] ~size:100;
[%expect
{|
((input ())
(choose ())
(choose_exn (Error ("[Hashtbl.choose_exn] of empty hashtbl")))
(choose_randomly ())
(choose_randomly_exn (
Error ("[Hashtbl.choose_randomly_exn] of empty hashtbl"))))
|}];
test [ 1 ];
[%expect
{|
((input ((1 1)))
(choose ((_ _)))
(choose_exn (Ok (_ _)))
(choose_randomly ((_ _)))
(choose_randomly_exn (Ok (_ _))))
|}];
test [ 1 ] ~size:100;
[%expect
{|
((input ((1 1)))
(choose ((_ _)))
(choose_exn (Ok (_ _)))
(choose_randomly ((_ _)))
(choose_randomly_exn (Ok (_ _))))
|}];
test [ 1; 2 ];
[%expect
{|
((input (
(1 1)
(2 2)))
(choose ((_ _)))
(choose_exn (Ok (_ _)))
(choose_randomly ((_ _)))
(choose_randomly_exn (Ok (_ _))))
|}];
test [ 1; 2 ] ~size:100;
[%expect
{|
((input (
(1 1)
(2 2)))
(choose ((_ _)))
(choose_exn (Ok (_ _)))
(choose_randomly ((_ _)))
(choose_randomly_exn (Ok (_ _))))
|}]
;;
let%expect_test "update_and_return" =
let t = Hashtbl.create (module String) in
let update_and_return str ~f =
let x = Hashtbl.update_and_return t str ~f in
print_s [%message (t : (string, int) Hashtbl.t) (x : int)]
in
update_and_return "foo" ~f:(function
| None -> 1
| Some _ -> failwith "no");
[%expect {| ((t ((foo 1))) (x 1)) |}];
update_and_return "foo" ~f:(function
| Some 1 -> 2
| _ -> failwith "no");
[%expect {| ((t ((foo 2))) (x 2)) |}]
;;