File 1892-Test-invalid-patterns-in-property-based-tests-for-th.patch of Package erlang

From dab01006a63edb23274f17c3b72b73f5ba752d46 Mon Sep 17 00:00:00 2001
From: Jan Uhlig <juhlig@hnc-agency.org>
Date: Mon, 4 Sep 2023 17:35:18 +0200
Subject: [PATCH 2/4] Test invalid patterns in property-based tests for the
 binary module

---
 .../test/binary_property_test_SUITE.erl       | 136 ++++++++++++------
 lib/stdlib/test/property_test/binary_prop.erl | 132 ++++++++++++++---
 2 files changed, 206 insertions(+), 62 deletions(-)

diff --git a/lib/stdlib/test/binary_property_test_SUITE.erl b/lib/stdlib/test/binary_property_test_SUITE.erl
index 87740a0dc5..ad713b8e74 100644
--- a/lib/stdlib/test/binary_property_test_SUITE.erl
+++ b/lib/stdlib/test/binary_property_test_SUITE.erl
@@ -22,29 +22,55 @@
 -compile([export_all, nowarn_export_all]).
 
 all() ->
-    [at_case, at_invalid_case,
-     bin_to_list_1_case,
-     bin_to_list_2_3_case, bin_to_list_2_3_invalid_case,
-     compile_pattern_case, compile_pattern_invalid_case,
-     copy_case, copy_2_invalid_case,
-     decode_hex_case, decode_hex_invalid_case,
+    [{group, valid_input}, {group, invalid_input}].
+
+valid_input_tests() ->
+    [at_case,
+     bin_to_list_1_case, bin_to_list_2_3_case,
+     compile_pattern_case,
+     copy_case,
+     decode_hex_case,
      decode_unsigned_case,
      encode_hex_case,
-     encode_unsigned_case, encode_unsigned_invalid_case,
+     encode_unsigned_case,
      first_case,
      last_case,
-     list_to_bin_case, list_to_bin_invalid_case,
+     list_to_bin_case,
      longest_common_prefix_case,
      longest_common_suffix_case,
-     match_2_case,
-     match_3_case, match_3_invalid_case,
-     matches_2_case,
-     matches_3_case, matches_3_invalid_case,
-     part_case, part_invalid_case,
-     replace_3_case,
-     replace_4_case, replace_4_invalid1_case, replace_4_invalid2_case,
-     split_2_case,
-     split_3_case, split_3_invalid_case].
+     match_2_case, match_3_case,
+     matches_2_case, matches_3_case,
+     part_case,
+     replace_3_case, replace_4_case,
+     split_2_case, split_3_case].
+
+out_of_binary_tests() ->
+    [at_invalid_index_case,
+     bin_to_list_2_3_invalid_range_case,
+     match_3_invalid_scope_case,
+     matches_3_invalid_scope_case,
+     part_invalid_range_case,
+     replace_4_invalid_scope_case, replace_4_invalid_insert_replaced_case,
+     split_3_invalid_scope_case].
+
+invalid_pattern_tests() ->
+    [compile_pattern_invalid_pattern_case,
+     match_2_invalid_pattern_case, match_3_invalid_pattern_case,
+     matches_2_invalid_pattern_case, matches_3_invalid_pattern_case,
+     replace_3_invalid_pattern_case, replace_4_invalid_pattern_case,
+     split_2_invalid_pattern_case, split_3_invalid_pattern_case].
+
+misc_invalid_input_tests() ->
+    [copy_2_invalid_n_case,
+     decode_hex_invalid_chars_case,
+     encode_unsigned_invalid_integer_case,
+     list_to_bin_invalid_bytes_case].
+
+groups() ->
+    [{valid_input, [], valid_input_tests()},
+     {invalid_input, [], [{out_of_binary, [], out_of_binary_tests()},
+                          {invalid_patterns, [], invalid_pattern_tests()},
+                          {misc_invalid, [], misc_invalid_input_tests()}]}].
 
 init_per_suite(Config) ->
     ct_property_test:init_per_suite(Config).
@@ -58,8 +84,8 @@ do_proptest(Prop, Config) ->
 at_case(Config) ->
     do_proptest(prop_at, Config).
 
-at_invalid_case(Config) ->
-    do_proptest(prop_at_invalid, Config).
+at_invalid_index_case(Config) ->
+    do_proptest(prop_at_invalid_index, Config).
 
 bin_to_list_1_case(Config) ->
     do_proptest(prop_bin_to_list_1, Config).
@@ -67,26 +93,26 @@ bin_to_list_1_case(Config) ->
 bin_to_list_2_3_case(Config) ->
     do_proptest(prop_bin_to_list_2_3, Config).
 
-bin_to_list_2_3_invalid_case(Config) ->
-    do_proptest(prop_bin_to_list_2_3_invalid, Config).
+bin_to_list_2_3_invalid_range_case(Config) ->
+    do_proptest(prop_bin_to_list_2_3_invalid_range, Config).
 
 compile_pattern_case(Config) ->
     do_proptest(prop_compile_pattern, Config).
 
-compile_pattern_invalid_case(Config) ->
-    do_proptest(prop_compile_pattern_invalid, Config).
+compile_pattern_invalid_pattern_case(Config) ->
+    do_proptest(prop_compile_pattern_invalid_pattern, Config).
 
 copy_case(Config) ->
     do_proptest(prop_copy, Config).
 
-copy_2_invalid_case(Config) ->
-    do_proptest(prop_copy_2_invalid, Config).
+copy_2_invalid_n_case(Config) ->
+    do_proptest(prop_copy_2_invalid_n, Config).
 
 decode_hex_case(Config) ->
     do_proptest(prop_decode_hex, Config).
 
-decode_hex_invalid_case(Config) ->
-    do_proptest(prop_decode_hex_invalid, Config).
+decode_hex_invalid_chars_case(Config) ->
+    do_proptest(prop_decode_hex_invalid_chars, Config).
 
 decode_unsigned_case(Config) ->
     do_proptest(prop_decode_unsigned, Config).
@@ -97,8 +123,8 @@ encode_hex_case(Config) ->
 encode_unsigned_case(Config) ->
     do_proptest(prop_encode_unsigned, Config).
 
-encode_unsigned_invalid_case(Config) ->
-    do_proptest(prop_encode_unsigned_invalid, Config).
+encode_unsigned_invalid_integer_case(Config) ->
+    do_proptest(prop_encode_unsigned_invalid_integer, Config).
 
 first_case(Config) ->
     do_proptest(prop_first, Config).
@@ -109,8 +135,8 @@ last_case(Config) ->
 list_to_bin_case(Config) ->
     do_proptest(prop_list_to_bin, Config).
 
-list_to_bin_invalid_case(Config) ->
-    do_proptest(prop_list_to_bin_invalid, Config).
+list_to_bin_invalid_bytes_case(Config) ->
+    do_proptest(prop_list_to_bin_invalid_bytes, Config).
 
 longest_common_prefix_case(Config) ->
     do_proptest(prop_longest_common_prefix, Config).
@@ -121,45 +147,69 @@ longest_common_suffix_case(Config) ->
 match_2_case(Config) ->
     do_proptest(prop_match_2, Config).
 
+match_2_invalid_pattern_case(Config) ->
+    do_proptest(prop_match_2_invalid_pattern, Config).
+
 match_3_case(Config) ->
     do_proptest(prop_match_3, Config).
 
-match_3_invalid_case(Config) ->
-    do_proptest(prop_match_3_invalid, Config).
+match_3_invalid_scope_case(Config) ->
+    do_proptest(prop_match_3_invalid_scope, Config).
+
+match_3_invalid_pattern_case(Config) ->
+    do_proptest(prop_match_3_invalid_pattern, Config).
 
 matches_2_case(Config) ->
     do_proptest(prop_matches_2, Config).
 
+matches_2_invalid_pattern_case(Config) ->
+    do_proptest(prop_matches_2_invalid_pattern, Config).
+
 matches_3_case(Config) ->
     do_proptest(prop_matches_3, Config).
 
-matches_3_invalid_case(Config) ->
-    do_proptest(prop_matches_3_invalid, Config).
+matches_3_invalid_scope_case(Config) ->
+    do_proptest(prop_matches_3_invalid_scope, Config).
+
+matches_3_invalid_pattern_case(Config) ->
+    do_proptest(prop_matches_3_invalid_pattern, Config).
 
 part_case(Config) ->
     do_proptest(prop_part, Config).
 
-part_invalid_case(Config) ->
-    do_proptest(prop_part_invalid, Config).
+part_invalid_range_case(Config) ->
+    do_proptest(prop_part_invalid_range, Config).
 
 replace_3_case(Config) ->
     do_proptest(prop_replace_3, Config).
 
+replace_3_invalid_pattern_case(Config) ->
+    do_proptest(prop_replace_3_invalid_pattern, Config).
+
 replace_4_case(Config) ->
     do_proptest(prop_replace_4, Config).
 
-replace_4_invalid1_case(Config) ->
-    do_proptest(prop_replace_4_invalid1, Config).
+replace_4_invalid_scope_case(Config) ->
+    do_proptest(prop_replace_4_invalid_scope, Config).
+
+replace_4_invalid_insert_replaced_case(Config) ->
+    do_proptest(prop_replace_4_invalid_insert_replaced, Config).
 
-replace_4_invalid2_case(Config) ->
-    do_proptest(prop_replace_4_invalid2, Config).
+replace_4_invalid_pattern_case(Config) ->
+    do_proptest(prop_replace_4_invalid_pattern, Config).
 
 split_2_case(Config) ->
     do_proptest(prop_split_2, Config).
 
+split_2_invalid_pattern_case(Config) ->
+    do_proptest(prop_split_2_invalid_pattern, Config).
+
 split_3_case(Config) ->
     do_proptest(prop_split_3, Config).
 
-split_3_invalid_case(Config) ->
-    do_proptest(prop_split_3_invalid, Config).
+split_3_invalid_scope_case(Config) ->
+    do_proptest(prop_split_3_invalid_scope, Config).
+
+split_3_invalid_pattern_case(Config) ->
+    do_proptest(prop_split_3_invalid_pattern, Config).
 
diff --git a/lib/stdlib/test/property_test/binary_prop.erl b/lib/stdlib/test/property_test/binary_prop.erl
index b07cf13f43..80235d49e2 100644
--- a/lib/stdlib/test/property_test/binary_prop.erl
+++ b/lib/stdlib/test/property_test/binary_prop.erl
@@ -37,7 +37,7 @@ prop_at() ->
         Byte =:= binary:at(Bin, Pos)
     ).
 
-prop_at_invalid() ->
+prop_at_invalid_index() ->
     ?FORALL(
         {Bin, Pos},
         ?LET(
@@ -73,7 +73,7 @@ prop_bin_to_list_2_3() ->
         List =:= binary:bin_to_list(Bin, Pos, Len)
     ).
 
-prop_bin_to_list_2_3_invalid() ->
+prop_bin_to_list_2_3_invalid_range() ->
     ?FORALL(
         {Bin, {Pos, Len}=PosLen},
         ?LET(
@@ -93,7 +93,7 @@ prop_compile_pattern() ->
         is_tuple(binary:compile_pattern(P))
     ).
 
-prop_compile_pattern_invalid() ->
+prop_compile_pattern_invalid_pattern() ->
     ?FORALL(
         P,
         oneof([
@@ -128,7 +128,7 @@ prop_copy() ->
         end
     ).
 
-prop_copy_2_invalid() ->
+prop_copy_2_invalid_n() ->
     ?FORALL(
         {Bin, N},
         {binary(), neg_integer()},
@@ -161,7 +161,7 @@ prop_decode_hex() ->
         BR =:= binary:decode_hex(BE)
     ).
 
-prop_decode_hex_invalid() ->
+prop_decode_hex_invalid_chars() ->
     ?FORALL(
         Bin,
         ?SUCHTHAT(B, binary(), not is_hex_bin(B)),
@@ -213,7 +213,7 @@ prop_encode_unsigned() ->
         end
     ).
 
-prop_encode_unsigned_invalid() ->
+prop_encode_unsigned_invalid_integer() ->
     ?FORALL(
         I,
         neg_integer(),
@@ -258,7 +258,7 @@ prop_list_to_bin() ->
         Bin =:= binary:list_to_bin(List)
     ).
 
-prop_list_to_bin_invalid() ->
+prop_list_to_bin_invalid_bytes() ->
     ?FORALL(
         List,
         ?SUCHTHAT(
@@ -309,6 +309,13 @@ prop_match_2() ->
         end
     ).
 
+prop_match_2_invalid_pattern() ->
+    ?FORALL(
+        {Bin, Pattern},
+        {binary(), gen_patterns_invalid()},
+        expect_error(fun binary:match/2, [Bin, Pattern])
+    ).
+
 %% --- match/3 --------------------------------------------------------
 prop_match_3() ->
     ?FORALL(
@@ -325,7 +332,7 @@ prop_match_3() ->
         end
     ).
 
-prop_match_3_invalid() ->
+prop_match_3_invalid_scope() ->
     ?FORALL(
         {Bin, Pattern, Opts},
         ?LET(
@@ -337,6 +344,17 @@ prop_match_3_invalid() ->
         expect_error(fun binary:match/3, [Bin, binary:compile_pattern(Pattern), Opts])
     ).
 
+prop_match_3_invalid_pattern() ->
+    ?FORALL(
+        {Bin, Pattern, Opts},
+        ?LET(
+            B,
+            binary(),
+            {B, gen_patterns_invalid(), gen_opts([], [gen_scope_opt(B)])}
+        ),
+        expect_error(fun binary:match/3, [Bin, Pattern, Opts])
+    ).
+
 %% --- matches/2 ------------------------------------------------------
 prop_matches_2() ->
     ?FORALL(
@@ -353,6 +371,13 @@ prop_matches_2() ->
         end
     ).
 
+prop_matches_2_invalid_pattern() ->
+    ?FORALL(
+        {Bin, Pattern},
+        {binary(), gen_patterns_invalid()},
+        expect_error(fun binary:matches/2, [Bin, Pattern])
+    ).
+
 %% --- matches/3 ------------------------------------------------------
 prop_matches_3() ->
     ?FORALL(
@@ -369,7 +394,7 @@ prop_matches_3() ->
         end
     ).
 
-prop_matches_3_invalid() ->
+prop_matches_3_invalid_scope() ->
     ?FORALL(
         {Bin, Pattern, Opts},
         ?LET(
@@ -381,6 +406,17 @@ prop_matches_3_invalid() ->
         expect_error(fun binary:matches/3, [Bin, binary:compile_pattern(Pattern), Opts])
     ).
 
+prop_matches_3_invalid_pattern() ->
+    ?FORALL(
+        {Bin, Pattern, Opts},
+        ?LET(
+            B,
+            binary(),
+            {B, gen_patterns_invalid(), gen_opts([], [gen_scope_opt(B)])}
+        ),
+        expect_error(fun binary:matches/3, [Bin, Pattern, Opts])
+    ).
+
 %% --- part/2,3 -------------------------------------------------------
 prop_part() ->
     ?FORALL(
@@ -399,7 +435,7 @@ prop_part() ->
         end
     ).
 
-prop_part_invalid() ->
+prop_part_invalid_range() ->
     ?FORALL(
         {Bin, {Pos, Len}=PosLen},
         ?LET(
@@ -427,6 +463,13 @@ prop_replace_3() ->
        end
     ).
 
+prop_replace_3_invalid_pattern() ->
+    ?FORALL(
+        {Bin, Pattern, Replacement},
+        {binary(), gen_patterns_invalid(), oneof([binary(), function1(binary())])},
+        expect_error(fun binary:replace/3, [Bin, Pattern, Replacement])
+    ).
+
 %% --- replace/4 ------------------------------------------------------
 prop_replace_4() ->
     ?FORALL(
@@ -443,7 +486,7 @@ prop_replace_4() ->
         end
     ).
 
-prop_replace_4_invalid1() ->
+prop_replace_4_invalid_scope() ->
     ?FORALL(
         {Bin, Pattern, Replacement, Opts},
         ?LET(
@@ -455,7 +498,7 @@ prop_replace_4_invalid1() ->
         expect_error(fun binary:replace/4, [Bin, binary:compile_pattern(Pattern), Replacement, Opts])
     ).
 
-prop_replace_4_invalid2() ->
+prop_replace_4_invalid_insert_replaced() ->
     ?FORALL(
         {Bin, Pattern, Replacement, Opts},
         ?LET(
@@ -467,6 +510,17 @@ prop_replace_4_invalid2() ->
         expect_error(fun binary:replace/4, [Bin, binary:compile_pattern(Pattern), Replacement, Opts])
     ).
 
+prop_replace_4_invalid_pattern() ->
+    ?FORALL(
+        {Bin, Pattern, Replacement, Opts},
+        ?LET(
+            {B, R},
+            {binary(), oneof([binary(), function1(binary())])},
+            {B, gen_patterns_invalid(), R, gen_opts([], [global, gen_scope_opt(B), gen_insert_replaced_opt(R)])}
+        ),
+        expect_error(fun binary:replace/4, [Bin, Pattern, Replacement, Opts])
+    ).
+
 %% --- split/2 --------------------------------------------------------
 prop_split_2() ->
     ?FORALL(
@@ -483,6 +537,13 @@ prop_split_2() ->
         end
     ).
 
+prop_split_2_invalid_pattern() ->
+    ?FORALL(
+        {Bin, Pattern},
+        {binary(), gen_patterns_invalid()},
+        expect_error(fun binary:split/2, [Bin, Pattern])
+    ).
+
 %% --- split/3 --------------------------------------------------------
 prop_split_3() ->
     ?FORALL(
@@ -499,7 +560,7 @@ prop_split_3() ->
         end
     ).
 
-prop_split_3_invalid() ->
+prop_split_3_invalid_scope() ->
     ?FORALL(
         {Bin, Pattern, Opts},
         ?LET(
@@ -511,6 +572,17 @@ prop_split_3_invalid() ->
         expect_error(fun binary:split/3, [Bin, binary:compile_pattern(Pattern), Opts])
     ).
 
+prop_split_3_invalid_pattern() ->
+    ?FORALL(
+        {Bin, Pattern, Opts},
+        ?LET(
+            B,
+            binary(),
+            {B, gen_patterns_invalid(), gen_opts([], [global, trim, trim_all, gen_scope_opt(B)])}
+        ),
+        expect_error(fun binary:split/3, [Bin, Pattern, Opts])
+    ).
+
 
 %%%%%%%%%%%%%%%%%%
 %%% Generators %%%
@@ -607,6 +679,28 @@ gen_pattern(Bin) ->
                 )
             )]).
 
+%% Generator for invalid patterns.
+gen_patterns_invalid() ->
+    ?LET(
+        T,
+        oneof([?SUCHTHAT(T, gen_pattern_invalid(), not is_list(T)), list(oneof([gen_pattern(), gen_pattern_invalid()]))]),
+        case T of
+            [_|_] ->
+                case lists:all(fun(<<_, _/binary>>) -> true; (_) -> false end, T) of
+                    true ->
+                        [gen_pattern_invalid() | T];
+                    false ->
+                        T
+                end;
+            _ ->
+                T
+        end
+    ).
+
+%% Generator for a single invalid pattern.
+gen_pattern_invalid() ->
+    ?SUCHTHAT(T, ct_proper_ext:safe_any(), T =:= <<>> orelse not is_binary(T)).
+
 
 %%%%%%%%%%%%%%%
 %%% Helpers %%%
@@ -640,11 +734,11 @@ opts_to_scope_parts(Bin, Opts) ->
 opts_to_trim(Opts) ->
     case {lists:member(trim_all, Opts), lists:member(trim, Opts)} of
         {true, _} ->
-	    all;
+            all;
         {_, true} ->
-	    rear;
+            rear;
         _ ->
-	    none
+            none
     end.
 
 %% Process a replacement based on the insert_replaced options specified in the given options list
@@ -660,7 +754,7 @@ opts_to_replacement(Replacement, Opts) ->
             split_replacement(Positions, Replacement);
         {insert_replaced, Position} ->
             <<Front:Position/binary, Rear/binary>> = Replacement,
-	    [Front, Rear]
+            [Front, Rear]
     end.
 
 split_replacement(Inserts, Bin) ->
@@ -825,10 +919,10 @@ do_split(Bin, Patterns, Opts) ->
     Splitted2 = lists:droplast(Splitted1) ++ [<<(lists:last(Splitted1))/binary, Rear/binary>>],
     case Trim of
         none ->
-	    Splitted2;
+            Splitted2;
         all ->
             lists:filter(fun(Part) -> Part =/= <<>> end, Splitted2);
-	rear ->
+        rear ->
             lists:reverse(lists:dropwhile(fun(Part) -> Part =:= <<>> end, lists:reverse(Splitted2)))
     end.
 
-- 
2.35.3

openSUSE Build Service is sponsored by