mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-05 19:00:31 -05:00
226 lines
5.5 KiB
OCaml
226 lines
5.5 KiB
OCaml
open CCSexp
|
|
module T = (val Containers_testlib.make ~__FILE__ ())
|
|
include T;;
|
|
|
|
t @@ fun () ->
|
|
CCResult.to_opt (parse_string "(abc d/e/f \"hello \\\" () world\" )") <> None
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
CCResult.to_opt (parse_string "(abc ( d e ffff ) \"hello/world\")") <> None
|
|
;;
|
|
|
|
t @@ fun () -> CCResult.to_opt (parse_string "\"\123\bcoucou\"") <> None
|
|
|
|
let eq' =
|
|
eq ~printer:(function
|
|
| Ok x -> to_string x
|
|
| Error e -> "error " ^ e)
|
|
;;
|
|
|
|
eq' (parse_string "(a b)") (Ok (`List [ `Atom "a"; `Atom "b" ]));;
|
|
eq' (parse_string "(a\n ;coucou\n b)") (Ok (`List [ `Atom "a"; `Atom "b" ]));;
|
|
|
|
eq'
|
|
(parse_string "(a #; (foo bar\n (1 2 3)) b)")
|
|
(Ok (`List [ `Atom "a"; `Atom "b" ]))
|
|
;;
|
|
|
|
eq' (parse_string "#; (a b) (c d)") (Ok (`List [ `Atom "c"; `Atom "d" ]));;
|
|
eq' (parse_string "#; (a b) 1") (Ok (`Atom "1"))
|
|
|
|
let eq' =
|
|
eq ~printer:(function
|
|
| Ok x -> String.concat ";" @@ List.map to_string x
|
|
| Error e -> "error " ^ e)
|
|
;;
|
|
|
|
eq'
|
|
(parse_string_list "(a b)(c)")
|
|
(Ok [ `List [ `Atom "a"; `Atom "b" ]; `List [ `Atom "c" ] ])
|
|
;;
|
|
|
|
eq' (parse_string_list " ") (Ok []);;
|
|
|
|
eq'
|
|
(parse_string_list "(a\n ;coucou\n b)")
|
|
(Ok [ `List [ `Atom "a"; `Atom "b" ] ])
|
|
;;
|
|
|
|
eq'
|
|
(parse_string_list "#; (a b) (c d) e ")
|
|
(Ok [ `List [ `Atom "c"; `Atom "d" ]; `Atom "e" ])
|
|
;;
|
|
|
|
eq' (parse_string_list "#; (a b) 1") (Ok [ `Atom "1" ])
|
|
|
|
let sexp_bijective s = to_string s |> parse_string = Ok s;;
|
|
|
|
eq
|
|
~printer:CCFormat.(to_string (Dump.result pp))
|
|
(Ok (`List [ `Atom "" ]))
|
|
(parse_string "(\"\")")
|
|
;;
|
|
|
|
t @@ fun () -> sexp_bijective (`List [ `Atom "" ])
|
|
|
|
let sexp_gen =
|
|
let mkatom a = `Atom a and mklist l = `List l in
|
|
let atom = Q.Gen.(map mkatom (string_size ~gen:printable (1 -- 30))) in
|
|
let gen =
|
|
Q.Gen.(
|
|
sized
|
|
(fix (fun self n st ->
|
|
match n with
|
|
| 0 -> atom st
|
|
| _ ->
|
|
frequency
|
|
[
|
|
1, atom; 2, map mklist (list_size (0 -- 10) (self (n / 10)));
|
|
]
|
|
st)))
|
|
in
|
|
let rec small = function
|
|
| `Atom s -> String.length s
|
|
| `List l -> List.fold_left (fun n x -> n + small x) 0 l
|
|
and print = function
|
|
| `Atom s -> Printf.sprintf "`Atom \"%s\"" s
|
|
| `List l -> "`List " ^ Q.Print.list print l
|
|
and shrink = function
|
|
| `Atom s -> Q.Iter.map mkatom (Q.Shrink.string s)
|
|
| `List l -> Q.Iter.map mklist (Q.Shrink.list ~shrink l)
|
|
in
|
|
Q.make ~print ~small ~shrink gen
|
|
;;
|
|
|
|
q ~count:100 sexp_gen sexp_bijective;;
|
|
|
|
(* regression for #338 *)
|
|
t @@ fun () ->
|
|
Printexc.record_backtrace true;
|
|
let cases =
|
|
[
|
|
"\"\\256\"";
|
|
"\"\\722\02622222\\\\\n\r<\\\\\\\\\"\\222222222\\\\\"\"\2032!2222\\\\\"\"";
|
|
"\"\n\r<\\t\023\n\203\\622222222\\\\\"\"\2032!2222\\\\\"\"";
|
|
"\"\n\
|
|
\r<@t\023\n\
|
|
\203\\2222D2\n\
|
|
\r22222\01622222222222222222222222\203\\292242\222 2\\\\\">K2";
|
|
"\"\n\r<\\t\023\n\203\\272222222\\\\\"\"\2032\0042222\\\\\"\"";
|
|
"\"\023\n\
|
|
\203\\5222\n\
|
|
\r<\\t\023\n\
|
|
\203\\52222222\\\\\"2\\\216\216\216\216\216\\\\\"\216\216\216\216\216\216\216\216\216222222222222222\147";
|
|
"\"\\722\02622222\\\\\n\r<\\\\\\\\\"\\222222222\\\\\"\"\2032!2222\\\\\"\"";
|
|
]
|
|
in
|
|
cases
|
|
|> List.iter (fun s ->
|
|
try ignore (parse_string s)
|
|
with e ->
|
|
let st = Printexc.get_backtrace () in
|
|
print_endline @@ Printexc.to_string e ^ "\n" ^ st;
|
|
assert false);
|
|
true
|
|
|
|
module CS = CCCanonical_sexp
|
|
|
|
module Csexp_arg = struct
|
|
open Csexp
|
|
|
|
type t = Csexp.t
|
|
|
|
let atom s = Atom s
|
|
let list l = List l
|
|
|
|
let match_ s ~atom ~list =
|
|
match s with
|
|
| Atom s -> atom s
|
|
| List l -> list l
|
|
|
|
type loc = unit
|
|
|
|
let make_loc = None
|
|
let atom_with_loc ~loc:() = atom
|
|
let list_with_loc ~loc:() = list
|
|
end
|
|
|
|
module CS0 = CS.Make (Csexp_arg)
|
|
module Sexp0 = CCSexp.Make (Csexp_arg)
|
|
|
|
let gen_csexp (str : string Q.Gen.t) : CS0.t Q.Gen.t =
|
|
let open Q.Gen in
|
|
let open Csexp in
|
|
( fix @@ fun self depth ->
|
|
let mklist n = list_size (0 -- n) (self (depth + 1)) >|= fun l -> List l in
|
|
frequency
|
|
@@ List.flatten
|
|
[
|
|
[ (3, str >|= fun s -> Atom s) ];
|
|
(match depth with
|
|
| 0 -> [ 4, mklist 25 ]
|
|
| 1 -> [ 2, mklist 7 ]
|
|
| 2 -> [ 1, mklist 2 ]
|
|
| _ -> []);
|
|
] )
|
|
0
|
|
|
|
let rec shrink_csexp (s : Csexp.t) : Csexp.t Q.Iter.t =
|
|
let open Csexp in
|
|
let open Q.Iter in
|
|
match s with
|
|
| Atom s -> Q.Shrink.string s >|= fun s -> Atom s
|
|
| List l -> Q.Shrink.list ~shrink:shrink_csexp l >|= fun l -> List l
|
|
|
|
let arb_csexp_pp =
|
|
let genstr = Q.Gen.(string_size ~gen:Q.Gen.printable (0 -- 15)) in
|
|
Q.make ~print:Sexp0.to_string ~shrink:shrink_csexp (gen_csexp genstr)
|
|
|
|
let arb_csexp_arb =
|
|
(* binary-ready *)
|
|
let genchar = Q.Gen.(0 -- 255 >|= Char.chr) in
|
|
let genstr = Q.Gen.(string_size ~gen:genchar (0 -- 15)) in
|
|
Q.make ~print:Sexp0.to_string ~shrink:shrink_csexp (gen_csexp genstr)
|
|
|
|
module Make (X : sig
|
|
val arb : Csexp.t Q.arbitrary
|
|
end)
|
|
() =
|
|
struct
|
|
open X;;
|
|
|
|
q ~count:2_000 arb @@ fun sexp ->
|
|
let s = CS0.to_string sexp in
|
|
match Csexp.parse_string s with
|
|
| Ok sexp' -> sexp = sexp'
|
|
| Error (_, msg) -> Q.Test.fail_report msg
|
|
;;
|
|
|
|
q ~count:2_000 arb @@ fun sexp ->
|
|
let s = Csexp.to_string sexp in
|
|
match CS0.parse_string s with
|
|
| Ok sexp' -> sexp = sexp'
|
|
| Error msg -> Q.Test.fail_report msg
|
|
|
|
let init () = ()
|
|
end
|
|
|
|
let () =
|
|
let module M1 =
|
|
Make
|
|
(struct
|
|
let arb = arb_csexp_pp
|
|
end)
|
|
()
|
|
in
|
|
let module M2 =
|
|
Make
|
|
(struct
|
|
let arb = arb_csexp_arb
|
|
end)
|
|
()
|
|
in
|
|
M1.init ();
|
|
M2.init ();
|
|
()
|