open Functoria open Cmdliner let key_a = Key.create "a" Key.Arg.(flag @@ Arg.info [ "a" ]) let key_b = Key.create "b" Key.Arg.(opt Arg.int 0 @@ Arg.info [ "b" ]) let key_c = Key.create "c" Key.Arg.(required Arg.string @@ Arg.info [ "c" ]) let key_d = Key.create "d" Key.Arg.(opt_all Arg.int @@ Arg.info [ "d" ]) let empty = Context.empty let ( & ) (k, v) c = Key.add_to_context k v c let ( && ) x y = x & y & empty let test_eval () = let context = (key_a, true) & (key_b, 0) && (key_c, Some "foo") in let if_ = Key.if_ Key.(value key_a) "hello" "world" in let r = Key.eval context if_ in Alcotest.(check string) "if" "hello" r; let match_1 = Key.match_ Key.(value key_b) (function 0 -> "hello" | _ -> "world") in let r = Key.eval context match_1 in Alcotest.(check string) "match 1" "hello" r; let match_2 = Key.match_ Key.(value key_c) (function Some "foo" -> "hello" | _ -> "world") in let r = Key.eval context match_2 in Alcotest.(check string) "match 1" "hello" r let keys = Key.Set.of_list Key.[ v key_a; v key_b; v key_c; v key_d ] let keys_no_required = Key.Set.of_list Key.[ v key_a; v key_b; v key_d ] let eval f keys argv = let argv = Array.of_list ("" :: argv) in match Cmdliner.Cmd.eval_value ~argv (Cmdliner.Cmd.v (Cmdliner.Cmd.info "keys") (f keys)) with | Error _ -> Alcotest.fail "Error" | Ok (`Ok x) -> x | Ok `Version -> Alcotest.fail "version" | Ok `Help -> Alcotest.fail "help" exception Error let test_get () = let context = eval Key.context keys [ "-a"; "-c"; "foo" ] in Alcotest.(check bool) "get a" true (Key.get context key_a); Alcotest.(check int) "get b" 0 (Key.get context key_b); Alcotest.(check (option string)) "get c" (Some "foo") (Key.get context key_c); let context = eval Key.context keys_no_required [ "-a" ] in Alcotest.(check (option string)) "get c with_required:false" None (Key.get context key_c); Alcotest.check_raises "get c with_required:true" Error (fun () -> try ignore (eval Key.context keys [ "-a" ]) with _ -> raise Error) let test_find () = let context = eval Key.context keys_no_required [] in Alcotest.(check (option bool)) "find a" None (Key.find context key_a); Alcotest.(check (option int)) "find b" None (Key.find context key_b); Alcotest.(check (option (option string))) "find c" None (Key.find context key_c) let test_merge () = let cache = (key_a, true) && (key_c, Some "foo") in let cli = (key_a, false) && (key_b, 2) in let context = Context.merge ~default:cache cli in Alcotest.(check bool) "merge a" false (Key.get context key_a); Alcotest.(check int) "merge b" 2 (Key.get context key_b); Alcotest.(check (option string)) "merge c" (Some "foo") (Key.get context key_c) let key = Alcotest.testable Key.pp Key.equal let test_equal () = let module A = Arg in let k1 = Key.(v @@ create "foo" Arg.(opt A.int 1 (A.info [ "foo" ]))) in let k2 = Key.(v @@ create "foo" Arg.(opt A.int 2 (A.info [ "foo" ]))) in let k3 = Key.(v @@ create "foo" Arg.(opt A.int 1 (A.info [ "foo" ]))) in Alcotest.(check @@ neg key) "different defaults" k1 k2; Alcotest.(check @@ key) "same defaults" k1 k3 let test_cmdliner () = let module A = Arg in let k1 = Key.(v @@ create "foo" Arg.(opt A.int 1 (A.info [ "foo" ]))) in let k2 = Key.(v @@ create "foo" Arg.(opt A.int 2 (A.info [ "foo" ]))) in let keys = Key.Set.of_list [ k1; k2 ] in let context = Key.context keys in let _ = eval (fun x -> x) context [] in () let test_opt_all () = let context = eval Key.context keys_no_required [ "-d"; "1"; "-d"; "2"; "-d"; "3" ] in Alcotest.(check (list int)) "get d" [ 1; 2; 3 ] (Key.get context key_d); let context = eval Key.context keys_no_required [] in Alcotest.(check (list int)) "get d" [] (Key.get context key_d); match Cmdliner.Cmd.eval_value ~argv:[| ""; "-d" |] Cmdliner.(Cmd.v (Cmd.info "keys") (Key.context keys_no_required)) with | Ok (`Ok _ | `Help | `Version) -> Alcotest.failf "Invalid given command-line, eval must fail." | Error _ -> Alcotest.(check pass) "invalid opt-all argument" () () let suite = List.map (fun (n, f) -> (n, `Quick, f)) [ ("equal", test_equal); ("eval", test_eval); ("get", test_get); ("find", test_find); ("merge", test_merge); ("cmdliner", test_cmdliner); ("opt-all", test_opt_all); ]