Skip to content

Commit d158624

Browse files
committed
Extend test for regexp parser.
1 parent e73434b commit d158624

File tree

1 file changed

+56
-5
lines changed

1 file changed

+56
-5
lines changed

tests/test_regexp.ml

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,27 @@ module Regexp = struct
173173
Format.fprintf ppf " => %S" (to_string e);
174174
Format.pp_print_flush ppf ();
175175
Buffer.contents buf
176+
177+
let rec to_re e =
178+
(match e.Loc.txt with
179+
| Code re -> Re.Perl.re re
180+
| Seq es -> Re.seq (List.map to_re es)
181+
| Alt es -> Re.alt (List.map to_re es)
182+
| Opt e -> Re.opt (to_re e)
183+
| Repeat ({Loc.txt = (i, j); _}, e) -> Re.repn (to_re e) i j
184+
| Nongreedy e -> Re.non_greedy (to_re e)
185+
| Capture e -> Re.group (to_re e)
186+
| Capture_as (_, e) -> Re.group (to_re e)
187+
| Call _ -> raise Re.Perl.Not_supported)
188+
189+
let rec has_anon_capture e =
190+
(match e.Loc.txt with
191+
| Code _ | Call _ -> false
192+
| Seq es | Alt es -> List.exists has_anon_capture es
193+
| Opt e | Repeat (_, e) | Capture_as (_, e) | Nongreedy e ->
194+
has_anon_capture e
195+
| Capture _ -> true)
196+
176197
end
177198

178199
let gen_name =
@@ -252,17 +273,47 @@ let shrink_regexp =
252273
let arb_regexp =
253274
Q.make ~print:Regexp.show_debug ~shrink:shrink_regexp gen_regexp
254275

276+
let test_parse s =
277+
let r =
278+
(match Regexp.parse_exn s with
279+
| exception Location.Error err -> Error err
280+
| e ->
281+
Ok (e,
282+
(try Ok (Regexp.to_re e) with
283+
| Re.Perl.Parse_error -> Error `Parse_error
284+
| Re.Perl.Not_supported -> Error `Not_supported)))
285+
in
286+
let r' =
287+
try Ok (Re.Perl.re s) with
288+
| Re.Perl.Parse_error -> Error `Parse_error
289+
| Re.Perl.Not_supported -> Error `Not_supported
290+
in
291+
(match r, r' with
292+
| (Error _ | Ok (_, Error _)), Error _ -> true
293+
| Ok _, Error `Not_supported -> true
294+
| Ok (e, Ok _), Error `Parse_error ->
295+
if Regexp.has_anon_capture e then true else
296+
Q.Test.fail_reportf "Parsed to %a and converted to Re.t, \
297+
but should be invalid" Regexp.pp_debug e
298+
| Error err, Ok _ ->
299+
Q.Test.fail_reportf "Failed to parse valid %s: %a" s
300+
Location.report_error err
301+
| Ok (e, Error _), Ok _ ->
302+
Q.Test.fail_reportf "Parsed to %a but conversion to Re.t failed"
303+
Regexp.pp_debug e
304+
| Ok (_, Ok _), Ok _ ->
305+
(* TODO: Would have been nice to compare the two Re.t here. *)
306+
true)
307+
255308
let tests = [
256-
Q.Test.make ~name:"parse ∘ to_string" arb_regexp
309+
Q.Test.make ~long_factor:100 ~name:"parse ∘ to_string" arb_regexp
257310
(fun e ->
258311
(match Regexp.parse_exn (Regexp.to_string e) with
259312
| exception Location.Error err ->
260313
Q.Test.fail_reportf "%a" Location.report_error err
261314
| e' -> Regexp.equal e' e));
262-
(* TODO:
263-
* - `to_string ∘ parse`: An arbitrary string will not be canonical, but even
264-
* controlled generation should add coverage compared to the above identity.
265-
* - Compare to PCRE. *)
315+
Q.Test.make ~long_factor:100 ~name:"to_string ∘ parse"
316+
(Q.string_gen Q.Gen.printable) test_parse;
266317
]
267318

268319
let () = QCheck_runner.run_tests_main tests

0 commit comments

Comments
 (0)