Skip to content

Commit ab453a6

Browse files
committed
better regression test
1 parent 9e336db commit ab453a6

16 files changed

+693
-383
lines changed

jscomp/bin/all_ounit_tests.i.ml

+248-147
Large diffs are not rendered by default.

jscomp/bin/all_ounit_tests.ml

+166-94
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,8 @@ val find : ?start:int -> sub:string -> string -> int
16761676

16771677
val contain_substring : string -> string -> bool
16781678

1679+
val non_overlap_count : sub:string -> string -> int
1680+
16791681
val rfind : sub:string -> string -> int
16801682

16811683
val tail_from : string -> int -> string
@@ -1905,9 +1907,10 @@ let unsafe_is_sub ~sub i s j ~len =
19051907
exception Local_exit
19061908
let find ?(start=0) ~sub s =
19071909
let n = String.length sub in
1910+
let s_len = String.length s in
19081911
let i = ref start in
19091912
try
1910-
while !i + n <= String.length s do
1913+
while !i + n <= s_len do
19111914
if unsafe_is_sub ~sub 0 s !i ~len:n then
19121915
raise_notrace Local_exit;
19131916
incr i
@@ -1919,6 +1922,18 @@ let find ?(start=0) ~sub s =
19191922
let contain_substring s sub =
19201923
find s ~sub >= 0
19211924

1925+
(** TODO: optimize
1926+
avoid nonterminating when string is empty
1927+
*)
1928+
let non_overlap_count ~sub s =
1929+
let sub_len = String.length sub in
1930+
let rec aux acc off =
1931+
let i = find ~start:off ~sub s in
1932+
if i < 0 then acc
1933+
else aux (acc + 1) (i + sub_len) in
1934+
if String.length sub = 0 then invalid_arg "Ext_string.non_overlap_count"
1935+
else aux 0 0
1936+
19221937

19231938
let rfind ~sub s =
19241939
let n = String.length sub in
@@ -3473,8 +3488,8 @@ let (//) = Filename.concat
34733488

34743489
(** may nonterminate when [cwd] is '.' *)
34753490
let rec unsafe_root_dir_aux cwd =
3476-
if Sys.file_exists (cwd//Literals.bsconfig_json) then cwd
3477-
else unsafe_root_dir_aux (Filename.dirname cwd)
3491+
if Sys.file_exists (cwd//Literals.bsconfig_json) then cwd
3492+
else unsafe_root_dir_aux (Filename.dirname cwd)
34783493

34793494
let project_root = unsafe_root_dir_aux (Sys.getcwd ())
34803495
let jscomp = project_root // "jscomp"
@@ -3487,7 +3502,7 @@ let stdlib_dir = jscomp // "stdlib"
34873502

34883503

34893504
let ((>::),
3490-
(>:::)) = OUnit.((>::),(>:::))
3505+
(>:::)) = OUnit.((>::),(>:::))
34913506

34923507
let (=~) = OUnit.assert_equal
34933508

@@ -3508,111 +3523,162 @@ let safe_close fd =
35083523

35093524

35103525
type output = {
3511-
stderr : string ;
3512-
stdout : string ;
3513-
exit_code : int
3526+
stderr : string ;
3527+
stdout : string ;
3528+
exit_code : int
35143529
}
35153530

35163531
let perform command args =
3517-
let new_fd_in, new_fd_out = Unix.pipe () in
3518-
let err_fd_in, err_fd_out = Unix.pipe () in
3519-
match Unix.fork () with
3520-
| 0 ->
3521-
begin try
3522-
safe_close new_fd_in;
3523-
safe_close err_fd_in;
3524-
Unix.dup2 err_fd_out Unix.stderr ;
3525-
Unix.dup2 new_fd_out Unix.stdout;
3526-
Unix.execv command args
3527-
with _ ->
3528-
exit 127
3529-
end
3530-
| pid ->
3531-
(* when all the descriptors on a pipe's input are closed and the pipe is
3532-
empty, a call to [read] on its output returns zero: end of file.
3533-
when all the descriptiors on a pipe's output are closed, a call to
3534-
[write] on its input kills the writing process (EPIPE).
3535-
*)
3536-
safe_close new_fd_out ;
3537-
safe_close err_fd_out ;
3538-
let in_chan = Unix.in_channel_of_descr new_fd_in in
3539-
let err_in_chan = Unix.in_channel_of_descr err_fd_in in
3540-
let buf = Buffer.create 1024 in
3541-
let err_buf = Buffer.create 1024 in
3542-
(try
3543-
while true do
3544-
Buffer.add_string buf (input_line in_chan );
3545-
Buffer.add_char buf '\n'
3546-
done;
3547-
with
3548-
End_of_file -> ()) ;
3549-
(try
3550-
while true do
3551-
Buffer.add_string err_buf (input_line err_in_chan );
3552-
Buffer.add_char err_buf '\n'
3553-
done;
3554-
with
3555-
End_of_file -> ()) ;
3556-
let exit_code = match snd @@ Unix.waitpid [] pid with
3557-
| Unix.WEXITED exit_code -> exit_code
3558-
| Unix.WSIGNALED _signal_number
3559-
| Unix.WSTOPPED _signal_number -> 127 in
3560-
{
3561-
stdout = Buffer.contents buf ;
3562-
stderr = Buffer.contents err_buf;
3563-
exit_code
3564-
}
3532+
let new_fd_in, new_fd_out = Unix.pipe () in
3533+
let err_fd_in, err_fd_out = Unix.pipe () in
3534+
match Unix.fork () with
3535+
| 0 ->
3536+
begin try
3537+
safe_close new_fd_in;
3538+
safe_close err_fd_in;
3539+
Unix.dup2 err_fd_out Unix.stderr ;
3540+
Unix.dup2 new_fd_out Unix.stdout;
3541+
Unix.execv command args
3542+
with _ ->
3543+
exit 127
3544+
end
3545+
| pid ->
3546+
(* when all the descriptors on a pipe's input are closed and the pipe is
3547+
empty, a call to [read] on its output returns zero: end of file.
3548+
when all the descriptiors on a pipe's output are closed, a call to
3549+
[write] on its input kills the writing process (EPIPE).
3550+
*)
3551+
safe_close new_fd_out ;
3552+
safe_close err_fd_out ;
3553+
let in_chan = Unix.in_channel_of_descr new_fd_in in
3554+
let err_in_chan = Unix.in_channel_of_descr err_fd_in in
3555+
let buf = Buffer.create 1024 in
3556+
let err_buf = Buffer.create 1024 in
3557+
(try
3558+
while true do
3559+
Buffer.add_string buf (input_line in_chan );
3560+
Buffer.add_char buf '\n'
3561+
done;
3562+
with
3563+
End_of_file -> ()) ;
3564+
(try
3565+
while true do
3566+
Buffer.add_string err_buf (input_line err_in_chan );
3567+
Buffer.add_char err_buf '\n'
3568+
done;
3569+
with
3570+
End_of_file -> ()) ;
3571+
let exit_code = match snd @@ Unix.waitpid [] pid with
3572+
| Unix.WEXITED exit_code -> exit_code
3573+
| Unix.WSIGNALED _signal_number
3574+
| Unix.WSTOPPED _signal_number -> 127 in
3575+
{
3576+
stdout = Buffer.contents buf ;
3577+
stderr = Buffer.contents err_buf;
3578+
exit_code
3579+
}
35653580

35663581

35673582
let perform_bsc args =
3568-
perform bsc_exe
3569-
(Array.append
3570-
[|bsc_exe ;
3571-
"-bs-package-name" ; "bs-platform";
3572-
"-bs-no-version-header";
3573-
"-bs-cross-module-opt";
3574-
"-w";
3575-
"-40";
3576-
"-I" ;
3577-
runtime_dir ;
3578-
"-I";
3579-
others_dir ;
3580-
"-I" ;
3581-
stdlib_dir
3582-
|] args)
3583+
perform bsc_exe
3584+
(Array.append
3585+
[|bsc_exe ;
3586+
"-bs-package-name" ; "bs-platform";
3587+
"-bs-no-version-header";
3588+
"-bs-cross-module-opt";
3589+
"-w";
3590+
"-40";
3591+
"-I" ;
3592+
runtime_dir ;
3593+
"-I";
3594+
others_dir ;
3595+
"-I" ;
3596+
stdlib_dir
3597+
|] args)
3598+
3599+
let bsc_eval str =
3600+
perform_bsc [|"-bs-eval"; str|]
3601+
35833602
(* let output_of_exec_command command args =
35843603
let readme, writeme = Unix.pipe () in
35853604
let pid = Unix.create_process command args Unix.stdin writeme Unix.stderr in
35863605
let in_chan = Unix.in_channel_of_descr readme *)
35873606

35883607
let debug_output o =
3589-
Printf.printf "\nexit_code:%d\nstdout:%s\nstderr:%s\n"
3590-
o.exit_code o.stdout o.stderr
3608+
Printf.printf "\nexit_code:%d\nstdout:%s\nstderr:%s\n"
3609+
o.exit_code o.stdout o.stderr
3610+
3611+
let react = {|
3612+
type u
3613+
3614+
external a : u = "react" [@@bs.module]
3615+
3616+
external b : unit -> int = "bool" [@@bs.module "react"]
3617+
3618+
let v = a
3619+
let h = b ()
3620+
3621+
|}
3622+
let foo_react = {|
3623+
type bla
3624+
3625+
3626+
external foo : bla = "foo.react" [@@bs.module]
3627+
3628+
external bar : unit -> bla = "bar" [@@bs.val] [@@bs.module "foo.react"]
3629+
3630+
let c = foo
3631+
3632+
let d = bar ()
3633+
3634+
|}
3635+
35913636

35923637
let suites =
3593-
__FILE__
3594-
>::: [
3595-
__LOC__ >:: begin fun _ ->
3596-
let v_output = perform_bsc [| "-v" |] in
3597-
OUnit.assert_bool __LOC__ ((perform_bsc [| "-h" |]).exit_code <> 0 );
3598-
OUnit.assert_bool __LOC__ (v_output.exit_code = 0);
3599-
(* Printf.printf "\n*>%s" v_output.stdout; *)
3600-
(* Printf.printf "\n*>%s" v_output.stderr ; *)
3601-
end;
3602-
__LOC__ >:: begin fun _ ->
3603-
let simple_quote =
3604-
perform_bsc [| "-bs-eval"; {|let str = "'a'" |}|] in
3605-
OUnit.assert_bool __LOC__ (simple_quote.exit_code = 0)
3606-
end;
3607-
__LOC__ >:: begin fun _ ->
3608-
let should_be_warning =
3609-
perform_bsc [|"-bs-eval"; {|let bla4 foo x y= foo##(method1 x y [@bs]) |}|] in
3610-
(* debug_output should_be_warning; *)
3611-
OUnit.assert_bool __LOC__ (Ext_string.contain_substring
3612-
should_be_warning.stderr Literals.unused_attribute)
3638+
__FILE__
3639+
>::: [
3640+
__LOC__ >:: begin fun _ ->
3641+
let v_output = perform_bsc [| "-v" |] in
3642+
OUnit.assert_bool __LOC__ ((perform_bsc [| "-h" |]).exit_code <> 0 );
3643+
OUnit.assert_bool __LOC__ (v_output.exit_code = 0);
3644+
(* Printf.printf "\n*>%s" v_output.stdout; *)
3645+
(* Printf.printf "\n*>%s" v_output.stderr ; *)
3646+
end;
3647+
__LOC__ >:: begin fun _ ->
3648+
let simple_quote =
3649+
perform_bsc [| "-bs-eval"; {|let str = "'a'" |}|] in
3650+
OUnit.assert_bool __LOC__ (simple_quote.exit_code = 0)
3651+
end;
3652+
__LOC__ >:: begin fun _ ->
3653+
let should_be_warning =
3654+
bsc_eval {|let bla4 foo x y= foo##(method1 x y [@bs]) |} in
3655+
(* debug_output should_be_warning; *)
3656+
OUnit.assert_bool __LOC__ (Ext_string.contain_substring
3657+
should_be_warning.stderr Literals.unused_attribute)
3658+
end;
3659+
__LOC__ >:: begin fun _ ->
3660+
let dedupe_require =
3661+
bsc_eval (react ^ foo_react) in
3662+
OUnit.assert_bool __LOC__ (Ext_string.non_overlap_count
3663+
dedupe_require.stdout ~sub:"require" = 2
3664+
)
3665+
end;
3666+
__LOC__ >:: begin fun _ ->
3667+
let dedupe_require =
3668+
bsc_eval react in
3669+
OUnit.assert_bool __LOC__ (Ext_string.non_overlap_count
3670+
dedupe_require.stdout ~sub:"require" = 1
3671+
)
3672+
end;
3673+
__LOC__ >:: begin fun _ ->
3674+
let dedupe_require =
3675+
bsc_eval foo_react in
3676+
OUnit.assert_bool __LOC__ (Ext_string.non_overlap_count
3677+
dedupe_require.stdout ~sub:"require" = 1
3678+
)
3679+
end
36133680

3614-
end
3615-
]
3681+
]
36163682

36173683

36183684
end
@@ -11377,6 +11443,12 @@ let suites =
1137711443
Ext_string.find ~sub:"hello" "xx hello hello xx" =~ 3 ;
1137811444
Ext_string.rfind ~sub:"hello" "xx hello hello xx" =~ 9 ;
1137911445
end;
11446+
__LOC__ >:: begin fun _ ->
11447+
Ext_string.non_overlap_count ~sub:"0" "1000,000" =~ 6;
11448+
Ext_string.non_overlap_count ~sub:"0" "000000" =~ 6;
11449+
Ext_string.non_overlap_count ~sub:"00" "000000" =~ 3;
11450+
Ext_string.non_overlap_count ~sub:"00" "00000" =~ 2
11451+
end;
1138011452
__LOC__ >:: begin fun _ ->
1138111453
OUnit.assert_bool __LOC__ (Ext_string.contain_substring "abc" "abc");
1138211454
OUnit.assert_bool __LOC__ (Ext_string.contain_substring "abc" "a");

jscomp/bin/bsb.ml

+16-1
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@ val find : ?start:int -> sub:string -> string -> int
462462

463463
val contain_substring : string -> string -> bool
464464

465+
val non_overlap_count : sub:string -> string -> int
466+
465467
val rfind : sub:string -> string -> int
466468

467469
val tail_from : string -> int -> string
@@ -691,9 +693,10 @@ let unsafe_is_sub ~sub i s j ~len =
691693
exception Local_exit
692694
let find ?(start=0) ~sub s =
693695
let n = String.length sub in
696+
let s_len = String.length s in
694697
let i = ref start in
695698
try
696-
while !i + n <= String.length s do
699+
while !i + n <= s_len do
697700
if unsafe_is_sub ~sub 0 s !i ~len:n then
698701
raise_notrace Local_exit;
699702
incr i
@@ -705,6 +708,18 @@ let find ?(start=0) ~sub s =
705708
let contain_substring s sub =
706709
find s ~sub >= 0
707710

711+
(** TODO: optimize
712+
avoid nonterminating when string is empty
713+
*)
714+
let non_overlap_count ~sub s =
715+
let sub_len = String.length sub in
716+
let rec aux acc off =
717+
let i = find ~start:off ~sub s in
718+
if i < 0 then acc
719+
else aux (acc + 1) (i + sub_len) in
720+
if String.length sub = 0 then invalid_arg "Ext_string.non_overlap_count"
721+
else aux 0 0
722+
708723

709724
let rfind ~sub s =
710725
let n = String.length sub in

0 commit comments

Comments
 (0)