aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/test')
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl20
-rw-r--r--lib/stdlib/test/calendar_SUITE.erl16
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl12
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl11
-rw-r--r--lib/stdlib/test/ets_SUITE.erl117
-rw-r--r--lib/stdlib/test/io_SUITE.erl39
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl10
7 files changed, 203 insertions, 22 deletions
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index c5cfea5e9e..9b2033ec4a 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -22,7 +22,8 @@
-export([all/0, suite/0,
interesting/1,scope_return/1,random_ref_comp/1,random_ref_sr_comp/1,
random_ref_fla_comp/1,parts/1, bin_to_list/1, list_to_bin/1,
- copy/1, referenced/1,guard/1,encode_decode/1,badargs/1,longest_common_trap/1]).
+ copy/1, referenced/1,guard/1,encode_decode/1,badargs/1,longest_common_trap/1,
+ check_no_invalid_read_bug/1]).
-export([random_number/1, make_unaligned/1]).
@@ -36,7 +37,7 @@ all() ->
[scope_return,interesting, random_ref_fla_comp, random_ref_sr_comp,
random_ref_comp, parts, bin_to_list, list_to_bin, copy,
referenced, guard, encode_decode, badargs,
- longest_common_trap].
+ longest_common_trap, check_no_invalid_read_bug].
-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
@@ -754,8 +755,9 @@ list_to_bin(Config) when is_list(Config) ->
copy(Config) when is_list(Config) ->
<<1,2,3>> = binary:copy(<<1,2,3>>),
RS = random_string({1,10000}),
- RS = RS2 = binary:copy(RS),
- false = erts_debug:same(RS,RS2),
+ RS2 = binary:copy(RS),
+ true = RS =:= RS2,
+ false = erts_debug:same(RS, RS2),
<<>> = ?MASK_ERROR(binary:copy(<<1,2,3>>,0)),
badarg = ?MASK_ERROR(binary:copy(<<1,2,3:3>>,2)),
badarg = ?MASK_ERROR(binary:copy([],0)),
@@ -1361,3 +1363,13 @@ make_unaligned2(Bin0) when is_binary(Bin0) ->
Bin.
id(I) -> I.
+
+check_no_invalid_read_bug(Config) when is_list(Config) ->
+ check_no_invalid_read_bug(24);
+check_no_invalid_read_bug(60) ->
+ ok;
+check_no_invalid_read_bug(I) ->
+ N = 1 bsl I,
+ binary:encode_unsigned(N+N),
+ binary:encode_unsigned(N+N, little),
+ check_no_invalid_read_bug(I+1).
diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl
index df62c0921d..224c0d5625 100644
--- a/lib/stdlib/test/calendar_SUITE.erl
+++ b/lib/stdlib/test/calendar_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
gregorian_days/1,
+ big_gregorian_days/1,
gregorian_seconds/1,
day_of_the_week/1,
day_of_the_week_calibrate/1,
@@ -36,13 +37,16 @@
-define(START_YEAR, 1947).
-define(END_YEAR, 2012).
+-define(BIG_START_YEAR, 20000000).
+-define(BIG_END_YEAR, 20000020).
+
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[gregorian_days, gregorian_seconds, day_of_the_week,
day_of_the_week_calibrate, leap_years,
last_day_of_the_month, local_time_to_universal_time_dst,
- iso_week_number, system_time, rfc3339].
+ iso_week_number, system_time, rfc3339, big_gregorian_days].
groups() ->
[].
@@ -67,6 +71,14 @@ gregorian_days(Config) when is_list(Config) ->
MaxDays = calendar:date_to_gregorian_days({?END_YEAR, 1, 1}),
check_gregorian_days(Days, MaxDays).
+%% Tests that date_to_gregorian_days and gregorian_days_to_date
+%% are each others inverses from ?BIG_START_YEAR-01-01 up to ?BIG_END_YEAR-01-01.
+%% At the same time valid_date is tested.
+big_gregorian_days(Config) when is_list(Config) ->
+ Days = calendar:date_to_gregorian_days({?BIG_START_YEAR, 1, 1}),
+ MaxDays = calendar:date_to_gregorian_days({?BIG_END_YEAR, 1, 1}),
+ check_gregorian_days(Days, MaxDays).
+
%% Tests that datetime_to_gregorian_seconds and
%% gregorian_seconds_to_date are each others inverses for a sampled
%% number of seconds from ?START_YEAR-01-01 up to ?END_YEAR-01-01: We check
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index f4019d477b..2436c8091c 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1156,7 +1156,17 @@ simple() ->
{A}.
simple1() ->
- erlang:error(simple).
+ %% If the compiler could see that this function would always
+ %% throw an error exception, it would rewrite simple() like this:
+ %%
+ %% simple() -> simple1().
+ %%
+ %% That would change the stacktrace. To prevent the compiler from
+ %% doing that optimization, we must obfuscate the code.
+ case get(a_key_that_is_not_defined) of
+ undefined -> erlang:error(simple);
+ WillNeverHappen -> WillNeverHappen
+ end.
%% Simple cases, just to cover some code.
funs(Config) when is_list(Config) ->
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index dda8d0a12e..f5d80e7e68 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@
otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1,
otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1,
otp_10302/1, otp_10820/1, otp_11100/1, otp_11861/1, pr_1014/1,
- otp_13662/1, otp_14285/1]).
+ otp_13662/1, otp_14285/1, otp_15592/1]).
%% Internal export.
-export([ehook/6]).
@@ -81,7 +81,7 @@ groups() ->
[otp_6321, otp_6911, otp_6914, otp_8150, otp_8238,
otp_8473, otp_8522, otp_8567, otp_8664, otp_9147,
otp_10302, otp_10820, otp_11100, otp_11861, pr_1014, otp_13662,
- otp_14285]}].
+ otp_14285, otp_15592]}].
init_per_suite(Config) ->
Config.
@@ -1167,6 +1167,11 @@ otp_14285(_Config) ->
[{encoding,latin1}])),
ok.
+otp_15592(_Config) ->
+ ok = pp_expr(<<"long12345678901234567890123456789012345678901234"
+ "56789012345678901234:f(<<>>)">>),
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
compile(Config, Tests) ->
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 22c77aa172..8561491d50 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -56,9 +56,11 @@
-export([t_match_spec_run/1]).
-export([t_bucket_disappears/1]).
-export([t_named_select/1]).
+-export([select_fixtab_owner_change/1]).
-export([otp_5340/1]).
-export([otp_6338/1]).
-export([otp_6842_select_1000/1]).
+-export([select_mbuf_trapping/1]).
-export([otp_7665/1]).
-export([meta_wb/1]).
-export([grow_shrink/1, grow_pseudo_deleted/1, shrink_pseudo_deleted/1]).
@@ -129,9 +131,10 @@ all() ->
t_insert_list, t_test_ms, t_select_delete, t_select_replace,
t_select_replace_next_bug,
t_ets_dets, memory, t_select_reverse, t_bucket_disappears,
- t_named_select,
+ t_named_select, select_fixtab_owner_change,
select_fail, t_insert_new, t_repair_continuation,
otp_5340, otp_6338, otp_6842_select_1000, otp_7665,
+ select_mbuf_trapping,
otp_8732, meta_wb, grow_shrink, grow_pseudo_deleted,
shrink_pseudo_deleted, {group, meta_smp}, smp_insert,
smp_fixed_delete, smp_unfix_fix, smp_select_replace,
@@ -247,7 +250,64 @@ t_named_select_do(Opts) ->
verify_etsmem(EtsMem).
+%% Verify select and friends release fixtab as they should
+%% even when owneship is changed between traps.
+select_fixtab_owner_change(_Config) ->
+ T = ets:new(xxx, [protected]),
+ NKeys = 2000,
+ [ets:insert(T,{K,K band 7}) || K <- lists:seq(1,NKeys)],
+ %% Buddy and Papa will ping-pong table ownership between them
+ %% and the aim is to give Buddy the table when he is
+ %% in the middle of a yielding select* call.
+ {Buddy,_} = spawn_opt(fun() -> sfoc_buddy_loop(T, 1, undefined) end,
+ [link,monitor]),
+
+ sfoc_papa_loop(T, Buddy),
+
+ receive {'DOWN', _, process, Buddy, _} -> ok end,
+ ets:delete(T),
+ ok.
+
+sfoc_buddy_loop(T, I, State0) ->
+ receive
+ {'ETS-TRANSFER', T, Papa, _} ->
+ ets:give_away(T, Papa, State0),
+ case State0 of
+ done ->
+ ok;
+ _ ->
+ State1 = sfoc_traverse(T, I, State0),
+ %% Verify no fixation left
+ {I, false} = {I, ets:info(T, safe_fixed_monotonic_time)},
+ sfoc_buddy_loop(T, I+1, State1)
+ end
+ end.
+
+sfoc_papa_loop(T, Buddy) ->
+ ets:give_away(T, Buddy, "Catch!"),
+ receive
+ {'ETS-TRANSFER', T, Buddy, State} ->
+ case State of
+ done ->
+ ok;
+ _ ->
+ sfoc_papa_loop(T, Buddy)
+ end
+ end.
+
+sfoc_traverse(T, 1, S) ->
+ ets:select(T, [{{'$1',7}, [], ['$1']}]), S;
+sfoc_traverse(T, 2, S) ->
+ 0 = ets:select_count(T, [{{'$1',7}, [], [false]}]), S;
+sfoc_traverse(T, 3, _) ->
+ Limit = ets:info(T, size) div 2,
+ {_, Continuation} = ets:select(T, [{{'$1',7}, [], ['$1']}],
+ Limit),
+ Continuation;
+sfoc_traverse(_T, 4, Continuation) ->
+ _ = ets:select(Continuation),
+ done.
%% Check ets:match_spec_run/2.
t_match_spec_run(Config) when is_list(Config) ->
@@ -5292,6 +5352,61 @@ otp_6338(Config) when is_list(Config) ->
end),
ok.
+%% OTP-15660: Verify select not doing excessive trapping
+%% when process have mbuf heap fragments.
+select_mbuf_trapping(Config) when is_list(Config) ->
+ select_mbuf_trapping_do(set),
+ select_mbuf_trapping_do(ordered_set).
+
+select_mbuf_trapping_do(Type) ->
+ T = ets:new(xxx, [Type]),
+ NKeys = 50,
+ [ets:insert(T, {K, value}) || K <- lists:seq(1,NKeys)],
+
+ {priority, Prio} = process_info(self(), priority),
+ Tracee = self(),
+ [SchedTracer]
+ = start_loopers(1, Prio,
+ fun (SC) ->
+ receive
+ {trace, Tracee, out, _} ->
+ SC+1;
+ done ->
+ Tracee ! {schedule_count, SC},
+ exit(normal)
+ end
+ end,
+ 0),
+
+ erlang:garbage_collect(),
+ 1 = erlang:trace(self(), true, [running,{tracer,SchedTracer}]),
+
+ %% Artificially create an mbuf heap fragment
+ MbufTerm = "Frag me up",
+ MbufTerm = erts_debug:set_internal_state(mbuf, MbufTerm),
+
+ Keys = ets:select(T, [{{'$1', value}, [], ['$1']}]),
+ NKeys = length(Keys),
+
+ 1 = erlang:trace(self(), false, [running]),
+ Ref = erlang:trace_delivered(Tracee),
+ receive
+ {trace_delivered, Tracee, Ref} ->
+ SchedTracer ! done
+ end,
+ receive
+ {schedule_count, N} ->
+ io:format("~p context switches: ~p", [Type,N]),
+ if
+ N < 3 -> ok;
+ true -> ct:fail(failed)
+ end
+ end,
+ true = ets:delete(T),
+ ok.
+
+
+
%% Elements could come in the wrong order in a bag if a rehash occurred.
otp_5340(Config) when is_list(Config) ->
repeat_for_opts(fun otp_5340_do/1).
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index f097552e8c..824f5d19f2 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
io_with_huge_message_queue/1, format_string/1,
maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1,
otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1,
- otp_15159/1]).
+ otp_15159/1, otp_15639/1]).
-export([pretty/2, trf/3]).
@@ -64,7 +64,8 @@ all() ->
io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836,
io_lib_width_too_small, io_with_huge_message_queue,
format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175,
- otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159].
+ otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159,
+ otp_15639].
%% Error cases for output.
error_1(Config) when is_list(Config) ->
@@ -2647,3 +2648,35 @@ otp_15076(_Config) ->
{'EXIT', {badarg, _}} = (catch io_lib:build_text(L)),
{'EXIT', {badarg, _}} = (catch io_lib:build_text(L, [])),
ok.
+
+otp_15639(_Config) ->
+ L = lists:duplicate(10, "a"),
+ LOpts = [{encoding, latin1}, {chars_limit, 10}],
+ UOpts = [{encoding, unicode}, {chars_limit, 10}],
+ "[[...]|...]" = pretty(L, LOpts),
+ "[[...]|...]" = pretty(L, UOpts),
+ "[\"a\",[...]|...]" =
+ pretty(L, [{chars_limit, 12}, {encoding, latin1}]),
+ "[\"a\",[...]|...]" =
+ pretty(L, [{chars_limit, 12}, {encoding, unicode}]),
+
+ %% Latin-1
+ "\"12345678\"" = pretty("12345678", LOpts),
+ "\"12345678\"..." = pretty("123456789", LOpts),
+ "\"\\r\\n123456\"..." = pretty("\r\n1234567", LOpts),
+ "\"\\r1234567\"..." = pretty("\r12345678", LOpts),
+ "\"\\r\\n123456\"..." = pretty("\r\n12345678", LOpts),
+ "\"12345678\"..." = pretty("12345678"++[x], LOpts),
+ "[49,50|...]" = pretty("1234567"++[x], LOpts),
+ "[49,x]" = pretty("1"++[x], LOpts),
+ "[[...]|...]" = pretty(["1","2","3","4","5","6","7","8"], LOpts),
+ %% Unicode
+ "\"12345678\"" = pretty("12345678", UOpts),
+ "\"12345678\"..." = pretty("123456789", UOpts),
+ "\"\\r\\n1234567\"" = pretty("\r\n1234567", UOpts),
+ "\"\\r1234567\"..." = pretty("\r12345678", UOpts),
+ "\"\\r\\n1234567\"..." = pretty("\r\n12345678", UOpts),
+ "[49,50|...]" = pretty("12345678"++[x], UOpts),
+ "\"12345678\"..." = pretty("123456789"++[x], UOpts),
+ "[[...]|...]" = pretty(["1","2","3","4","5","6","7","8"], UOpts),
+ ok.
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index d7354438f9..2354a08f78 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -3163,19 +3163,13 @@ lookup2(Config) when is_list(Config) ->
[a] = lookup_keys(Q)
end, [{a},{b},{c}])">>,
- {cres,
- <<"etsc(fun(E) ->
+ <<"etsc(fun(E) ->
Q = qlc:q([X || {X}=Y <- ets:table(E),
element(2, Y) == b,
X =:= 1]),
[] = qlc:e(Q),
false = lookup_keys(Q)
- end, [{1,b},{2,3}])">>,
- %% {warnings,[{2,sys_core_fold,nomatch_guard},
- %% {3,qlc,nomatch_filter},
- %% {3,sys_core_fold,{eval_failure,badarg}}]}},
- {warnings,[{2,sys_core_fold,nomatch_guard},
- {3,sys_core_fold,{eval_failure,badarg}}]}},
+ end, [{1,b},{2,3}])">>,
<<"etsc(fun(E) ->
Q = qlc:q([X || {X} <- ets:table(E), element(1,{X}) =:= 1]),