diff options
Diffstat (limited to 'lib/kernel')
-rw-r--r-- | lib/kernel/doc/src/disk_log.xml | 2 | ||||
-rw-r--r-- | lib/kernel/doc/src/inet.xml | 11 | ||||
-rw-r--r-- | lib/kernel/doc/src/notes.xml | 15 | ||||
-rw-r--r-- | lib/kernel/src/error_logger.erl | 6 | ||||
-rw-r--r-- | lib/kernel/src/erts_debug.erl | 35 | ||||
-rw-r--r-- | lib/kernel/src/file_server.erl | 8 | ||||
-rw-r--r-- | lib/kernel/src/global.erl | 16 | ||||
-rw-r--r-- | lib/kernel/src/inet.erl | 3 | ||||
-rw-r--r-- | lib/kernel/src/kernel.app.src | 2 | ||||
-rw-r--r-- | lib/kernel/src/kernel.appup.src | 4 | ||||
-rw-r--r-- | lib/kernel/src/net_kernel.erl | 2 | ||||
-rw-r--r-- | lib/kernel/src/pg2.erl | 4 | ||||
-rw-r--r-- | lib/kernel/src/user_drv.erl | 31 | ||||
-rw-r--r-- | lib/kernel/test/Makefile | 4 | ||||
-rw-r--r-- | lib/kernel/test/code_SUITE.erl | 50 | ||||
-rw-r--r-- | lib/kernel/test/gen_tcp_misc_SUITE.erl | 44 | ||||
-rw-r--r-- | lib/kernel/test/kernel_bench.spec | 1 | ||||
-rw-r--r-- | lib/kernel/test/zlib_SUITE.erl | 799 | ||||
-rw-r--r-- | lib/kernel/vsn.mk | 2 |
19 files changed, 669 insertions, 370 deletions
diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index 1be28adfb8..884cb32c0c 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -972,7 +972,7 @@ <item> <p>Specifies if messages will be sent to <c>error_logger</c> on recoverable errors with - the log files. Defaults to <c>true</c>.</p> + the log files. Defaults to <c>false</c>.</p> </item> </taglist> <p><c>open/1</c> returns <c>{ok, <anno>Log</anno>}</c> if the diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index b71e8a1e5d..169a76463b 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -222,11 +222,18 @@ fe80::204:acff:fe17:bf38 <name name="get_rc" arity="0"/> <fsummary>Return a list of IP configuration parameters.</fsummary> <desc> - <p>Returns the state of the <c>Inet</c> configuration database in + <p> + Returns the state of the <c>Inet</c> configuration database in form of a list of recorded configuration parameters. For more information, see <seealso marker="erts:inet_cfg">ERTS User's Guide: Inet Configuration</seealso>. - Only parameters with other than default values are returned.</p> + </p> + <p> + Only actual parameters with other than default values + are returned, for example not directives that specify + other sources for configuration parameters nor + directives that clear parameters. + </p> </desc> </func> diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index e1cf45109d..9cd03ffcad 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,21 @@ </header> <p>This document describes the changes made to the Kernel application.</p> +<section><title>Kernel 5.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The documentation for the 'quiet' option in + disk_log:open/1 had an incorrect default value.</p> + <p> + Own Id: OTP-14498</p> + </item> + </list> + </section> + +</section> + <section><title>Kernel 5.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index 9bf8547745..585507c545 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -504,7 +504,11 @@ string_p([]) -> string_p(Term) -> string_p1(Term). -string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 -> +string_p1([H|T]) when is_integer(H), H >= $\040, H =< $\176 -> + string_p1(T); +string_p1([H|T]) when is_integer(H), H >= 16#A0, H < 16#D800; + is_integer(H), H > 16#DFFF, H < 16#FFFE; + is_integer(H), H > 16#FFFF, H =< 16#10FFFF -> string_p1(T); string_p1([$\n|T]) -> string_p1(T); string_p1([$\r|T]) -> string_p1(T); diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index ad92aafc2f..480db6814e 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -33,10 +33,10 @@ -export([breakpoint/2, disassemble/1, display/1, dist_ext_to_term/2, dump_monitors/1, dump_links/1, flat_size/1, - get_internal_state/1, instructions/0, lock_counters/1, + get_internal_state/1, instructions/0, map_info/1, same/2, set_internal_state/2, - size_shared/1, copy_shared/1, dirty_cpu/2, dirty_io/2, - dirty/3]). + size_shared/1, copy_shared/1, dirty_cpu/2, dirty_io/2, dirty/3, + lcnt_control/1, lcnt_control/2, lcnt_collect/0, lcnt_clear/0]). -spec breakpoint(MFA, Flag) -> non_neg_integer() when MFA :: {Module :: module(), @@ -142,12 +142,31 @@ ic(F) when is_function(F) -> io:format("Total: ~w~n",[lists:sum([C||{_I,C}<-Is])]), R. --spec lock_counters(info) -> term(); - (clear) -> ok; - ({copy_save, boolean()}) -> boolean(); - ({process_locks, boolean()}) -> boolean(). +-spec lcnt_control + (copy_save, boolean()) -> ok; + (mask, list(atom())) -> ok. -lock_counters(_) -> +lcnt_control(_Option, _Value) -> + erlang:nif_error(undef). + +-spec lcnt_control + (copy_save) -> boolean(); + (mask) -> list(atom()). + +lcnt_control(_Option) -> + erlang:nif_error(undef). + +-type lcnt_lock_info() :: {atom(), term(), atom(), term()}. + +-spec lcnt_collect() -> + list({duration, {non_neg_integer(), non_neg_integer()}} | + {locks, list(lcnt_lock_info())}). + +lcnt_collect() -> + erlang:nif_error(undef). + +-spec lcnt_clear() -> ok. +lcnt_clear() -> erlang:nif_error(undef). -spec same(Term1, Term2) -> boolean() when diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl index 6504174cbc..6e8f64d932 100644 --- a/lib/kernel/src/file_server.erl +++ b/lib/kernel/src/file_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. 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. @@ -207,7 +207,7 @@ handle_call(stop, _From, Handle) -> {stop, normal, stopped, Handle}; handle_call(Request, From, Handle) -> - error_logger:error_msg("handle_call(~p, ~p, _)", [Request, From]), + error_logger:error_msg("handle_call(~tp, ~tp, _)", [Request, From]), {noreply, Handle}. %%---------------------------------------------------------------------- @@ -220,7 +220,7 @@ handle_call(Request, From, Handle) -> -spec handle_cast(term(), state()) -> {'noreply', state()}. handle_cast(Msg, State) -> - error_logger:error_msg("handle_cast(~p, _)", [Msg]), + error_logger:error_msg("handle_cast(~tp, _)", [Msg]), {noreply, State}. %%---------------------------------------------------------------------- @@ -243,7 +243,7 @@ handle_info({'EXIT', Handle, _Reason}, Handle) -> {stop, normal, Handle}; handle_info(Info, State) -> - error_logger:error_msg("handle_Info(~p, _)", [Info]), + error_logger:error_msg("handle_Info(~tp, _)", [Info]), {noreply, State}. %%---------------------------------------------------------------------- diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index a9e92b28b8..a38522eb5c 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -262,7 +262,7 @@ check_dupname(Name, Pid) -> {ok, allow} -> true; _ -> - S = "global: ~w registered under several names: ~w\n", + S = "global: ~w registered under several names: ~tw\n", Names = [Name | [Name1 || {_Pid, Name1} <- PidNames]], error_logger:error_msg(S, [Pid, Names]), false @@ -659,7 +659,7 @@ handle_call(stop, _From, S) -> handle_call(Request, From, S) -> error_logger:warning_msg("The global_name_server " "received an unexpected message:\n" - "handle_call(~p, ~p, _)\n", + "handle_call(~tp, ~tp, _)\n", [Request, From]), {noreply, S}. @@ -828,7 +828,7 @@ handle_cast({async_del_lock, _ResourceId, _Pid}, S) -> handle_cast(Request, S) -> error_logger:warning_msg("The global_name_server " "received an unexpected message:\n" - "handle_cast(~p, _)\n", [Request]), + "handle_cast(~tp, _)\n", [Request]), {noreply, S}. %%======================================================================== @@ -955,7 +955,7 @@ handle_info({'DOWN', MonitorRef, process, _Pid, _Info}, S0) -> handle_info(Message, S) -> error_logger:warning_msg("The global_name_server " "received an unexpected message:\n" - "handle_info(~p, _)\n", [Message]), + "handle_info(~tp, _)\n", [Message]), {noreply, S}. @@ -1949,13 +1949,13 @@ exchange_names([{Name, Pid, Method} | Tail], Node, Ops, Res) -> exchange_names(Tail, Node, [Op | Ops], [Op | Res]); {badrpc, Badrpc} -> error_logger:info_msg("global: badrpc ~w received when " - "conflicting name ~w was found\n", + "conflicting name ~tw was found\n", [Badrpc, Name]), Op = {insert, {Name, Pid, Method}}, exchange_names(Tail, Node, [Op | Ops], Res); Else -> error_logger:info_msg("global: Resolve method ~w for " - "conflicting name ~w returned ~w\n", + "conflicting name ~tw returned ~tw\n", [Method, Name, Else]), Op = {delete, Name}, exchange_names(Tail, Node, [Op | Ops], [Op | Res]) @@ -1984,7 +1984,7 @@ minmax(P1,P2) -> Pid2 :: pid(). random_exit_name(Name, Pid, Pid2) -> {Min, Max} = minmax(Pid, Pid2), - error_logger:info_msg("global: Name conflict terminating ~w\n", + error_logger:info_msg("global: Name conflict terminating ~tw\n", [{Name, Max}]), exit(Max, kill), Min. @@ -2200,7 +2200,7 @@ unexpected_message({'EXIT', _Pid, _Reason}, _What) -> ok; unexpected_message(Message, What) -> error_logger:warning_msg("The global_name_server ~w process " - "received an unexpected message:\n~p\n", + "received an unexpected message:\n~tp\n", [What, Message]). %%% Utilities diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 6aef5476f1..dc20c21c77 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -151,7 +151,8 @@ %%% --------------------------------- --spec get_rc() -> [{Par :: any(), Val :: any()}]. +-spec get_rc() -> [{Par :: atom(), Val :: any()} | + {Par :: atom(), Val1 :: any(), Val2 :: any()}]. get_rc() -> inet_db:get_rc(). diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index e150938487..2a11b04310 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -120,6 +120,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-9.0", "stdlib-3.0", "sasl-3.0"]} + {runtime_dependencies, ["erts-9.1", "stdlib-3.0", "sasl-3.0"]} ] }. diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 77085b2064..f1ef70a373 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,7 +18,7 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"5\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.* + [{<<"5\\.[0-3](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.*, OTP-20.0 %% Down to - max one major revision back - [{<<"5\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.* + [{<<"5\\.[0-3](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.*, OTP-20.0 }. diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl index ddda396713..7da89dd7cb 100644 --- a/lib/kernel/src/net_kernel.erl +++ b/lib/kernel/src/net_kernel.erl @@ -778,7 +778,7 @@ handle_info(transition_period_end, {noreply,State#state{tick = #tick{ticker = Tckr, time = T}}}; handle_info(X, State) -> - error_msg("Net kernel got ~w~n",[X]), + error_msg("Net kernel got ~tw~n",[X]), {noreply,State}. %% ----------------------------------------------------------- diff --git a/lib/kernel/src/pg2.erl b/lib/kernel/src/pg2.erl index edf4aedde2..c4732f37ee 100644 --- a/lib/kernel/src/pg2.erl +++ b/lib/kernel/src/pg2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. 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. @@ -199,7 +199,7 @@ handle_call({delete, Name}, _From, S) -> {reply, ok, S}; handle_call(Request, From, S) -> error_logger:warning_msg("The pg2 server received an unexpected message:\n" - "handle_call(~p, ~p, _)\n", + "handle_call(~tp, ~tp, _)\n", [Request, From]), {noreply, S}. diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl index b794d4f45e..99ea4210bd 100644 --- a/lib/kernel/src/user_drv.erl +++ b/lib/kernel/src/user_drv.erl @@ -175,6 +175,18 @@ server_loop(Iport, Oport, Curr, User, Gr, {Resp, IOQ} = IOQueue) -> {Iport,eof} -> Curr ! {self(),eof}, server_loop(Iport, Oport, Curr, User, Gr, IOQueue); + + %% We always handle geometry and unicode requests + {Requester,tty_geometry} -> + Requester ! {self(),tty_geometry,get_tty_geometry(Iport)}, + server_loop(Iport, Oport, Curr, User, Gr, IOQueue); + {Requester,get_unicode_state} -> + Requester ! {self(),get_unicode_state,get_unicode_state(Iport)}, + server_loop(Iport, Oport, Curr, User, Gr, IOQueue); + {Requester,set_unicode_state, Bool} -> + Requester ! {self(),set_unicode_state,set_unicode_state(Iport,Bool)}, + server_loop(Iport, Oport, Curr, User, Gr, IOQueue); + Req when element(1,Req) =:= User orelse element(1,Req) =:= Curr, tuple_size(Req) =:= 2 orelse tuple_size(Req) =:= 3 -> %% We match {User|Curr,_}|{User|Curr,_,_} @@ -224,21 +236,16 @@ server_loop(Iport, Oport, Curr, User, Gr, {Resp, IOQ} = IOQueue) -> _ -> % not current, just remove it server_loop(Iport, Oport, Curr, User, gr_del_pid(Gr, Pid), IOQueue) end; + {Requester, {put_chars_sync, _, _, Reply}} -> + %% We need to ack the Req otherwise originating process will hang forever + %% Do discard the output to non visible shells (as was done previously) + Requester ! {reply, Reply}, + server_loop(Iport, Oport, Curr, User, Gr, IOQueue); _X -> - %% Ignore unknown messages. - server_loop(Iport, Oport, Curr, User, Gr, IOQueue) + %% Ignore unknown messages. + server_loop(Iport, Oport, Curr, User, Gr, IOQueue) end. -%% We always handle geometry and unicode requests -handle_req({Curr,tty_geometry},Iport,_Oport,IOQueue) -> - Curr ! {self(),tty_geometry,get_tty_geometry(Iport)}, - IOQueue; -handle_req({Curr,get_unicode_state},Iport,_Oport,IOQueue) -> - Curr ! {self(),get_unicode_state,get_unicode_state(Iport)}, - IOQueue; -handle_req({Curr,set_unicode_state, Bool},Iport,_Oport,IOQueue) -> - Curr ! {self(),set_unicode_state,set_unicode_state(Iport,Bool)}, - IOQueue; handle_req(next,Iport,Oport,{false,IOQ}=IOQueue) -> case queue:out(IOQ) of {empty,_} -> diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index b9942e899f..efe3a68531 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -148,8 +148,8 @@ release_tests_spec: make_emakefile $(INSTALL_DIR) "$(RELSYSDIR)" $(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)" $(INSTALL_DATA) $(APP_FILES) "$(RELSYSDIR)" - $(INSTALL_DATA) kernel.spec kernel_smoke.spec $(EMAKEFILE)\ - $(COVERFILE) "$(RELSYSDIR)" + $(INSTALL_DATA) kernel.spec kernel_smoke.spec kernel_bench.spec \ + $(EMAKEFILE) $(COVERFILE) "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 6f8e949aac..612f77149d 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -35,6 +35,7 @@ purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, on_load_embedded/1, on_load_errors/1, on_load_update/1, + on_load_trace_on_load/1, on_load_purge/1, on_load_self_call/1, on_load_pending/1, on_load_deleted/1, big_boot_embedded/1, @@ -66,14 +67,16 @@ all() -> ext_mod_dep, clash, where_is_file, purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, - on_load_binary, on_load_embedded, on_load_errors, on_load_update, + on_load_binary, on_load_embedded, on_load_errors, + {group, sequence}, on_load_purge, on_load_self_call, on_load_pending, on_load_deleted, module_status, big_boot_embedded, native_early_modules, get_mode, normalized_paths]. -groups() -> - []. +%% These need to run in order +groups() -> [{sequence, [sequence], [on_load_update, + on_load_trace_on_load]}]. init_per_group(_GroupName, Config) -> Config. @@ -1493,7 +1496,7 @@ do_on_load_error(ReturnValue) -> {undef,[{on_load_error,main,[],_}|_]} = Exit end. -on_load_update(_Config) -> +on_load_update(Config) -> {Mod,Code1} = on_load_update_code(1), {module,Mod} = code:load_binary(Mod, "", Code1), 42 = Mod:a(), @@ -1503,7 +1506,7 @@ on_load_update(_Config) -> {Mod,Code2} = on_load_update_code(2), {error,on_load_failure} = code:load_binary(Mod, "", Code2), 42 = Mod:a(), - 100 = Mod:b(99), + 78 = Mod:b(77), {'EXIT',{undef,_}} = (catch Mod:never()), 4 = erlang:trace_pattern({Mod,'_','_'}, false), @@ -1514,6 +1517,9 @@ on_load_update(_Config) -> {'EXIT',{undef,_}} = (catch Mod:b(10)), {'EXIT',{undef,_}} = (catch Mod:never()), + code:purge(Mod), + code:delete(Mod), + code:purge(Mod), ok. on_load_update_code(Version) -> @@ -1545,6 +1551,40 @@ on_load_update_code_1(3, Mod) -> "f() -> ok.\n", "c() -> 100.\n"]). +%% Test -on_load while trace feature 'on_load' is enabled (OTP-14612) +on_load_trace_on_load(Config) -> + Papa = self(), + Tracer = spawn_link(fun F() -> receive M -> Papa ! M end, F() end), + {tracer,[]} = erlang:trace_info(self(),tracer), + erlang:trace(self(), true, [call, {tracer, Tracer}]), + erlang:trace_pattern(on_load, true, []), + on_load_update(Config), + erlang:trace_pattern(on_load, false, []), + erlang:trace(self(), false, [call]), + + %% WE GET TRACES FOR CALLS TO UNDEFINED FUNCTIONS ??? + %% Remove filter when that is fixed. + Ms = lists:filter(fun({trace,Papa,call, + {error_handler,undefined_function, + [on_load_update_code,_,_]}}) + -> false; + (_) -> true + end, + flush()), + + [{trace, Papa, call, {on_load_update_code, a, []}}, + {trace, Papa, call, {on_load_update_code, b, [99]}}, + {trace, Papa, call, {on_load_update_code, c, []}}] = Ms, + + exit(Tracer, normal), + ok. + +flush() -> + receive M -> [M | flush()] + after 100 -> [] + end. + + on_load_purge(_Config) -> Mod = ?FUNCTION_NAME, register(Mod, self()), diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 929f66d400..331864b5de 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -50,9 +50,8 @@ killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1, several_accepts_in_one_go/1, accept_system_limit/1, active_once_closed/1, send_timeout/1, send_timeout_active/1, - otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, - wrapping_oct/0, wrapping_oct/1, - otp_9389/1]). + otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, + wrapping_oct/0, wrapping_oct/1, otp_9389/1, otp_13939/1]). %% Internal exports. -export([sender/3, not_owner/1, passive_sockets_server/2, priority_server/1, @@ -3014,3 +3013,42 @@ ok({ok,V}) -> V. get_hostname(Name) -> "@"++Host = lists:dropwhile(fun(C) -> C =/= $@ end, atom_to_list(Name)), Host. + +otp_13939(doc) -> + ["Check that writing to a remotely closed socket doesn't block forever " + "when exit_on_close is false."]; +otp_13939(suite) -> + []; +otp_13939(Config) when is_list(Config) -> + {Pid, Ref} = spawn_opt( + fun() -> + {ok, Listener} = gen_tcp:listen(0, [{exit_on_close, false}]), + {ok, Port} = inet:port(Listener), + + spawn_link( + fun() -> + {ok, Client} = gen_tcp:connect("localhost", Port, + [{active, false}]), + ok = gen_tcp:close(Client) + end), + + {ok, Accepted} = gen_tcp:accept(Listener), + + ok = gen_tcp:send(Accepted, <<0:(10*1024*1024*8)>>), + + %% The bug surfaces when there's a delay between the send + %% operations; inet:getstat is a red herring. + timer:sleep(100), + + {error, Code} = gen_tcp:send(Accepted, <<0:(10*1024*1024*8)>>), + ct:pal("gen_tcp:send returned ~p~n", [Code]) + end, [link, monitor]), + + receive + {'DOWN', Ref, process, Pid, normal} -> + ok + after 1000 -> + demonitor(Ref, [flush]), + exit(Pid, normal), + ct:fail("Server process blocked on send.") + end. diff --git a/lib/kernel/test/kernel_bench.spec b/lib/kernel/test/kernel_bench.spec new file mode 100644 index 0000000000..8de60dae31 --- /dev/null +++ b/lib/kernel/test/kernel_bench.spec @@ -0,0 +1 @@ +{groups,"../kernel_test",zlib_SUITE,[bench]}. diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index 4b67fce9a8..e246276262 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -21,60 +21,56 @@ -module(zlib_SUITE). -include_lib("common_test/include/ct.hrl"). - --compile(export_all). - --define(error(Format,Args), - put(test_server_loc,{?MODULE,?LINE}), - error(Format,Args,?MODULE,?LINE)). - -%% Learn erts team how to really write tests ;-) --define(m(ExpectedRes,Expr), - fun() -> - ACtual1 = (catch (Expr)), - try case ACtual1 of - ExpectedRes -> ACtual1 - end - catch - error:{case_clause,ACtuAl} -> - ?error("Not Matching Actual result was:~n ~p ~n", - [ACtuAl]), - ACtuAl - end - end()). - --define(BARG, {'EXIT',{badarg,[{zlib,_,_,_}|_]}}). --define(DATA_ERROR, {'EXIT',{data_error,[{zlib,_,_,_}|_]}}). - -init_per_testcase(_Func, Config) -> - Config. - -end_per_testcase(_Func, _Config) -> - ok. - -error(Format, Args, File, Line) -> - io:format("~p:~p: ERROR: " ++ Format, [File,Line|Args]), - group_leader() ! {failed, File, Line}. - -%% Hopefully I don't need this to get it to work with the testserver.. -%% Fail = #'REASON'{file = filename:basename(File), -%% line = Line, -%% desc = Args}, -%% case global:whereis_name(mnesia_test_case_sup) of -%% undefined -> -%% ignore; -%% Pid -> -%% Pid ! Fail -%% %% global:send(mnesia_test_case_sup, Fail), -%% end, -%% log("<>ERROR<>~n" ++ Format, Args, File, Line). +-include_lib("common_test/include/ct_event.hrl"). + +-export([suite/0, all/0, groups/0]). + +%% API group +-export([api_open_close/1]). +-export([api_deflateInit/1, api_deflateSetDictionary/1, api_deflateReset/1, + api_deflateParams/1, api_deflate/1, api_deflateEnd/1]). +-export([api_inflateInit/1, api_inflateReset/1, api_inflate2/1, api_inflate3/1, + api_inflateChunk/1, api_safeInflate/1, api_inflateEnd/1]). +-export([api_inflateSetDictionary/1, api_inflateGetDictionary/1]). +-export([api_crc32/1, api_adler32/1]). +-export([api_un_compress/1, api_un_zip/1, api_g_un_zip/1]). + +%% Examples group +-export([intro/1]). + +%% Usage group +-export([zip_usage/1, gz_usage/1, gz_usage2/1, compress_usage/1, + dictionary_usage/1, large_deflate/1, crc/1, adler/1, + only_allow_owner/1, sub_heap_binaries/1]). + +%% Bench group +-export([inflate_bench_zeroed/1, inflate_bench_rand/1, + deflate_bench_zeroed/1, deflate_bench_rand/1, + chunk_bench_zeroed/1, chunk_bench_rand/1]). + +%% Others +-export([smp/1, otp_9981/1, otp_7359/1]). + +-define(m(Guard, Expression), + fun() -> + Actual = (catch (Expression)), + case Actual of + Guard -> Actual; + _Other -> + ct:fail("Failed to match ~p, actual result was ~p", + [??Guard, Actual]) + end + end()). + +-define(EXIT(Reason), {'EXIT',{Reason,[{_,_,_,_}|_]}}). suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap,{minutes,1}}]. all() -> - [{group, api}, {group, examples}, {group, func}, smp, + [{group, api}, {group, examples}, {group, func}, + {group, bench}, smp, otp_9981, otp_7359]. @@ -84,28 +80,19 @@ groups() -> api_deflateSetDictionary, api_deflateReset, api_deflateParams, api_deflate, api_deflateEnd, api_inflateInit, api_inflateSetDictionary, api_inflateGetDictionary, - api_inflateSync, api_inflateReset, api_inflate, api_inflateChunk, - api_inflateEnd, api_setBufsz, api_getBufsz, api_crc32, - api_adler32, api_getQSize, api_un_compress, api_un_zip, + api_inflateReset, api_inflate2, api_inflate3, api_inflateChunk, + api_safeInflate, api_inflateEnd, api_crc32, + api_adler32, api_un_compress, api_un_zip, api_g_un_zip]}, {examples, [], [intro]}, {func, [], [zip_usage, gz_usage, gz_usage2, compress_usage, - dictionary_usage, large_deflate, crc, adler]}]. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - + dictionary_usage, large_deflate, crc, adler, + only_allow_owner, sub_heap_binaries]}, + {bench, + [inflate_bench_zeroed, inflate_bench_rand, + deflate_bench_zeroed, deflate_bench_rand, + chunk_bench_zeroed, chunk_bench_rand]}]. %% Test open/0 and close/1. api_open_close(Config) when is_list(Config) -> @@ -113,7 +100,7 @@ api_open_close(Config) when is_list(Config) -> Fd2 = zlib:open(), ?m(false,Fd1 == Fd2), ?m(ok,zlib:close(Fd1)), - ?m(?BARG, zlib:close(Fd1)), + ?m(?EXIT(not_initialized), zlib:close(Fd1)), ?m(ok,zlib:close(Fd2)), %% Make sure that we don't get any EXIT messages if trap_exit is enabled. @@ -128,9 +115,11 @@ api_open_close(Config) when is_list(Config) -> %% Test deflateInit/2 and /6. api_deflateInit(Config) when is_list(Config) -> Z1 = zlib:open(), - ?m(?BARG, zlib:deflateInit(gurka, none)), - ?m(?BARG, zlib:deflateInit(gurka, gurka)), - ?m(?BARG, zlib:deflateInit(Z1, gurka)), + + ?m(?EXIT(badarg), zlib:deflateInit(gurka, none)), + + ?m(?EXIT(bad_compression_level), zlib:deflateInit(gurka, gurka)), + ?m(?EXIT(bad_compression_level), zlib:deflateInit(Z1, gurka)), Levels = [none, default, best_speed, best_compression] ++ lists:seq(0,9), lists:foreach(fun(Level) -> Z = zlib:open(), @@ -138,20 +127,30 @@ api_deflateInit(Config) when is_list(Config) -> ?m(ok,zlib:close(Z)) end, Levels), %% /6 - ?m(?BARG, zlib:deflateInit(Z1,gurka,deflated,-15,8,default)), - - ?m(?BARG, zlib:deflateInit(Z1,default,undefined,-15,8,default)), - - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,48,8,default)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-20,8,default)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-7,8,default)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,7,8,default)), - - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,0,default)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,10,default)), - - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,8,0)), - ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,8,undefined)), + ?m(?EXIT(bad_compression_level), + zlib:deflateInit(Z1,gurka,deflated,-15,8,default)), + + ?m(?EXIT(bad_compression_method), + zlib:deflateInit(Z1,default,undefined,-15,8,default)), + + ?m(?EXIT(bad_compression_strategy), + zlib:deflateInit(Z1,default,deflated,-15,8,0)), + ?m(?EXIT(bad_compression_strategy), + zlib:deflateInit(Z1,default,deflated,-15,8,undefined)), + + ?m(?EXIT(bad_windowbits), + zlib:deflateInit(Z1,default,deflated,48,8,default)), + ?m(?EXIT(bad_windowbits), + zlib:deflateInit(Z1,default,deflated,-20,8,default)), + ?m(?EXIT(bad_windowbits), + zlib:deflateInit(Z1,default,deflated,-7,8,default)), + ?m(?EXIT(bad_windowbits), + zlib:deflateInit(Z1,default,deflated,7,8,default)), + + ?m(?EXIT(bad_memlevel), + zlib:deflateInit(Z1,default,deflated,-15,0,default)), + ?m(?EXIT(bad_memlevel), + zlib:deflateInit(Z1,default,deflated,-15,10,default)), lists:foreach(fun(Level) -> Z = zlib:open(), @@ -183,7 +182,11 @@ api_deflateInit(Config) when is_list(Config) -> ?m(ok,zlib:close(Z)) end, Strategies), ?m(ok, zlib:deflateInit(Z1,default,deflated,-15,8,default)), - ?m({'EXIT',_}, zlib:deflateInit(Z1,none,deflated,-15,8,default)), %% ?? + + %% Let it crash for any reason; we don't care about the order in which the + %% parameters are checked. + ?m(?EXIT(_), zlib:deflateInit(Z1,none,deflated,-15,8,default)), + ?m(ok, zlib:close(Z1)). %% Test deflateSetDictionary. @@ -192,17 +195,17 @@ api_deflateSetDictionary(Config) when is_list(Config) -> ?m(ok, zlib:deflateInit(Z1, default)), ?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, <<1,1,2,3,4,5,1>>)), ?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, [1,1,2,3,4,5,1])), - ?m(?BARG, zlib:deflateSetDictionary(Z1, gurka)), - ?m(?BARG, zlib:deflateSetDictionary(Z1, 128)), - ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), - ?m({'EXIT',{stream_error,_}},zlib:deflateSetDictionary(Z1,<<1,1,2,3,4,5,1>>)), + ?m(?EXIT(badarg), zlib:deflateSetDictionary(Z1, gurka)), + ?m(?EXIT(badarg), zlib:deflateSetDictionary(Z1, 128)), + ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), + ?m(?EXIT(stream_error), zlib:deflateSetDictionary(Z1,<<1,1,2,3,4,5,1>>)), ?m(ok, zlib:close(Z1)). %% Test deflateReset. api_deflateReset(Config) when is_list(Config) -> Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1, default)), - ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), + ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), ?m(ok, zlib:deflateReset(Z1)), ?m(ok, zlib:deflateReset(Z1)), %% FIXME how do I make this go wrong?? @@ -212,9 +215,9 @@ api_deflateReset(Config) when is_list(Config) -> api_deflateParams(Config) when is_list(Config) -> Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1, default)), - ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), + ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), ?m(ok, zlib:deflateParams(Z1, best_compression, huffman_only)), - ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, sync)), + ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, sync)), ?m(ok, zlib:close(Z1)). %% Test deflate. @@ -231,11 +234,13 @@ api_deflate(Config) when is_list(Config) -> ?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, full)), ?m(B when is_list(B), zlib:deflate(Z1, <<>>, finish)), - ?m(?BARG, zlib:deflate(gurka, <<1,1,1,1,1,1,1,1,1>>, full)), - ?m(?BARG, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, asdj)), - ?m(?BARG, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, 198)), + ?m(?EXIT(badarg), zlib:deflate(gurka, <<1,1,1,1,1,1,1,1,1>>, full)), + + ?m(?EXIT(bad_flush_mode), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, asdj)), + ?m(?EXIT(bad_flush_mode), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, 198)), + %% Causes problems ERROR REPORT - ?m(?BARG, zlib:deflate(Z1, [asdj,asd], none)), + ?m(?EXIT(badarg), zlib:deflate(Z1, [asdj,asd], none)), ?m(ok, zlib:close(Z1)). @@ -244,11 +249,11 @@ api_deflateEnd(Config) when is_list(Config) -> Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1, default)), ?m(ok, zlib:deflateEnd(Z1)), - ?m({'EXIT', {einval,_}}, zlib:deflateEnd(Z1)), %% ?? - ?m(?BARG, zlib:deflateEnd(gurka)), + ?m(?EXIT(not_initialized), zlib:deflateEnd(Z1)), + ?m(?EXIT(badarg), zlib:deflateEnd(gurka)), ?m(ok, zlib:deflateInit(Z1, default)), ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)), - ?m({'EXIT', {data_error,_}}, zlib:deflateEnd(Z1)), + ?m(?EXIT(data_error), zlib:deflateEnd(Z1)), ?m(ok, zlib:deflateInit(Z1, default)), ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)), ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>, finish)), @@ -259,9 +264,9 @@ api_deflateEnd(Config) when is_list(Config) -> %% Test inflateInit /1 and /2. api_inflateInit(Config) when is_list(Config) -> Z1 = zlib:open(), - ?m(?BARG, zlib:inflateInit(gurka)), + ?m(?EXIT(badarg), zlib:inflateInit(gurka)), ?m(ok, zlib:inflateInit(Z1)), - ?m({'EXIT',{einval,_}}, zlib:inflateInit(Z1, 15)), %% ?? + ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, 15)), lists:foreach(fun(Wbits) -> Z11 = zlib:open(), ?m(ok, zlib:inflateInit(Z11,Wbits)), @@ -270,33 +275,34 @@ api_inflateInit(Config) when is_list(Config) -> ?m(ok,zlib:close(Z11)), ?m(ok,zlib:close(Z12)) end, lists:seq(8,15)), - ?m(?BARG, zlib:inflateInit(gurka, -15)), - ?m(?BARG, zlib:inflateInit(Z1, 7)), - ?m(?BARG, zlib:inflateInit(Z1, -7)), - ?m(?BARG, zlib:inflateInit(Z1, 48)), - ?m(?BARG, zlib:inflateInit(Z1, -16)), + ?m(?EXIT(badarg), zlib:inflateInit(gurka, -15)), + ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, 7)), + ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, -7)), + ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, 48)), + ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, -16)), ?m(ok, zlib:close(Z1)). %% Test inflateSetDictionary. api_inflateSetDictionary(Config) when is_list(Config) -> Z1 = zlib:open(), ?m(ok, zlib:inflateInit(Z1)), - ?m(?BARG, zlib:inflateSetDictionary(gurka,<<1,1,1,1,1>>)), - ?m(?BARG, zlib:inflateSetDictionary(Z1,102)), - ?m(?BARG, zlib:inflateSetDictionary(Z1,gurka)), + ?m(?EXIT(badarg), zlib:inflateSetDictionary(gurka,<<1,1,1,1,1>>)), + ?m(?EXIT(badarg), zlib:inflateSetDictionary(Z1,102)), + ?m(?EXIT(badarg), zlib:inflateSetDictionary(Z1,gurka)), Dict = <<1,1,1,1,1>>, - ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z1,Dict)), + ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z1,Dict)), ?m(ok, zlib:close(Z1)). %% Test inflateGetDictionary. api_inflateGetDictionary(Config) when is_list(Config) -> Z1 = zlib:open(), + zlib:inflateInit(Z1), IsOperationSupported = case catch zlib:inflateGetDictionary(Z1) of - {'EXIT',{einval,_}} -> true; - {'EXIT',{enotsup,_}} -> false + ?EXIT(not_supported) -> false; + _ -> true end, - _ = zlib:close(Z1), + zlib:close(Z1), api_inflateGetDictionary_if_supported(IsOperationSupported). api_inflateGetDictionary_if_supported(false) -> @@ -306,64 +312,53 @@ api_inflateGetDictionary_if_supported(true) -> Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1)), Dict = <<"foobar barfoo foo bar far boo">>, - ?m(_, zlib:deflateSetDictionary(Z1, Dict)), + Checksum = zlib:deflateSetDictionary(Z1, Dict), Payload = <<"foobarbarbar">>, Compressed = zlib:deflate(Z1, Payload, finish), ?m(ok, zlib:close(Z1)), - % Decompress and test dictionary extraction + % Decompress and test dictionary extraction with inflate/2 Z2 = zlib:open(), ?m(ok, zlib:inflateInit(Z2)), ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z2))), - ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z2, Dict)), - ?m({'EXIT',{{need_dictionary,_},_}}, zlib:inflate(Z2, Compressed)), + ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z2, Dict)), + ?m(?EXIT({need_dictionary,Checksum}), zlib:inflate(Z2, Compressed)), ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z2))), - ?m(Payload, iolist_to_binary(zlib:inflate(Z2, Compressed))), + Payload = iolist_to_binary(zlib:inflate(Z2, [])), ?m(ok, zlib:close(Z2)), - ?m(?BARG, zlib:inflateSetDictionary(Z2, Dict)), - ok. + ?m(?EXIT(not_initialized), zlib:inflateSetDictionary(Z2, Dict)), -%% Test inflateSync. -api_inflateSync(Config) when is_list(Config) -> - {skip,"inflateSync/1 sucks"}. -%% Z1 = zlib:open(), -%% ?m(ok, zlib:deflateInit(Z1)), -%% B1list0 = zlib:deflate(Z1, "gurkan gurra ger galna tunnor", full), -%% B2 = zlib:deflate(Z1, "grodan boll", finish), -%% io:format("~p\n", [B1list0]), -%% io:format("~p\n", [B2]), -%% ?m(ok, zlib:deflateEnd(Z1)), -%% B1 = clobber(14, list_to_binary(B1list0)), -%% Compressed = list_to_binary([B1,B2]), -%% io:format("~p\n", [Compressed]), - -%% ?m(ok, zlib:inflateInit(Z1)), -%% ?m(?BARG, zlib:inflateSync(gurka)), -%% ?m({'EXIT',{data_error,_}}, zlib:inflate(Z1, Compressed)), -%% ?m(ok, zlib:inflateSync(Z1)), -%% Ubs = zlib:inflate(Z1, []), -%% <<"grodan boll">> = list_to_binary(Ubs), -%% ?m(ok, zlib:close(Z1)). - -clobber(N, Bin) when is_binary(Bin) -> - T = list_to_tuple(binary_to_list(Bin)), - Byte = case element(N, T) of - 255 -> 254; - B -> B+1 - end, - list_to_binary(tuple_to_list(setelement(N, T, Byte))). + %% ... And do the same for inflate/3 + Z3 = zlib:open(), + ?m(ok, zlib:inflateInit(Z3)), + ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z3))), + ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z3, Dict)), + + {need_dictionary, Checksum, _Output = []} = + zlib:inflate(Z3, Compressed, [{exception_on_need_dict, false}]), + + ?m(ok, zlib:inflateSetDictionary(Z3, Dict)), + ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z3))), + + Payload = iolist_to_binary( + zlib:inflate(Z3, [], [{exception_on_need_dict, false}])), + + ?m(ok, zlib:close(Z3)), + ?m(?EXIT(not_initialized), zlib:inflateSetDictionary(Z3, Dict)), + + ok. %% Test inflateReset. api_inflateReset(Config) when is_list(Config) -> Z1 = zlib:open(), ?m(ok, zlib:inflateInit(Z1)), - ?m(?BARG, zlib:inflateReset(gurka)), + ?m(?EXIT(badarg), zlib:inflateReset(gurka)), ?m(ok, zlib:inflateReset(Z1)), ?m(ok, zlib:close(Z1)). -%% Test inflate. -api_inflate(Config) when is_list(Config) -> +%% Test inflate/2 +api_inflate2(Config) when is_list(Config) -> Data = [<<1,2,2,3,3,3,4,4,4,4>>], Compressed = zlib:compress(Data), Z1 = zlib:open(), @@ -373,12 +368,32 @@ api_inflate(Config) when is_list(Config) -> ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:inflateInit(Z1)), ?m(Data, zlib:inflate(Z1, Compressed)), - ?m(?BARG, zlib:inflate(gurka, Compressed)), - ?m(?BARG, zlib:inflate(Z1, 4384)), - ?m(?BARG, zlib:inflate(Z1, [atom_list])), + ?m(?EXIT(badarg), zlib:inflate(gurka, Compressed)), + ?m(?EXIT(badarg), zlib:inflate(Z1, 4384)), + ?m(?EXIT(badarg), zlib:inflate(Z1, [atom_list])), ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:inflateInit(Z1)), - ?m({'EXIT',{data_error,_}}, zlib:inflate(Z1, <<2,1,2,1,2>>)), + ?m(?EXIT(data_error), zlib:inflate(Z1, <<2,1,2,1,2>>)), + ?m(ok, zlib:close(Z1)). + +%% Test inflate/3; same as inflate/2 but with the default options inverted. +api_inflate3(Config) when is_list(Config) -> + Data = [<<1,2,2,3,3,3,4,4,4,4>>], + Options = [{exception_on_need_dict, false}], + Compressed = zlib:compress(Data), + Z1 = zlib:open(), + ?m(ok, zlib:inflateInit(Z1)), + ?m([], zlib:inflate(Z1, <<>>, Options)), + ?m(Data, zlib:inflate(Z1, Compressed)), + ?m(ok, zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), + ?m(Data, zlib:inflate(Z1, Compressed, Options)), + ?m(?EXIT(badarg), zlib:inflate(gurka, Compressed, Options)), + ?m(?EXIT(badarg), zlib:inflate(Z1, 4384, Options)), + ?m(?EXIT(badarg), zlib:inflate(Z1, [atom_list], Options)), + ?m(ok, zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), + ?m(?EXIT(data_error), zlib:inflate(Z1, <<2,1,2,1,2>>, Options)), ?m(ok, zlib:close(Z1)). %% Test inflateChunk. @@ -388,69 +403,105 @@ api_inflateChunk(Config) when is_list(Config) -> Part1 = binary:part(Data, 0, ChunkSize), Part2 = binary:part(Data, ChunkSize, ChunkSize), Part3 = binary:part(Data, ChunkSize * 2, ChunkSize), + Compressed = zlib:compress(Data), Z1 = zlib:open(), + zlib:setBufSize(Z1, ChunkSize), + ?m(ok, zlib:inflateInit(Z1)), - ?m([], zlib:inflateChunk(Z1, <<>>)), - ?m({more, Part1}, zlib:inflateChunk(Z1, Compressed)), - ?m({more, Part2}, zlib:inflateChunk(Z1)), - ?m(Part3, zlib:inflateChunk(Z1)), - ?m(ok, zlib:inflateEnd(Z1)), + 0 = iolist_size(zlib:inflateChunk(Z1, <<>>)), + + {more, Part1AsIOList} = zlib:inflateChunk(Z1, Compressed), + {more, Part2AsIOList} = zlib:inflateChunk(Z1), + {more, Part3AsIOList} = zlib:inflateChunk(Z1), + [] = zlib:inflateChunk(Z1), + + ?m(Part1, iolist_to_binary(Part1AsIOList)), + ?m(Part2, iolist_to_binary(Part2AsIOList)), + ?m(Part3, iolist_to_binary(Part3AsIOList)), + + ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:inflateInit(Z1)), - ?m({more, Part1}, zlib:inflateChunk(Z1, Compressed)), + + ?m({more, Part1AsIOList}, zlib:inflateChunk(Z1, Compressed)), ?m(ok, zlib:inflateReset(Z1)), - zlib:setBufSize(Z1, size(Data)), - ?m(Data, zlib:inflateChunk(Z1, Compressed)), - ?m(ok, zlib:inflateEnd(Z1)), + zlib:setBufSize(Z1, byte_size(Data) + 1), + + DataAsIOList = zlib:inflateChunk(Z1, Compressed), + ?m(Data, iolist_to_binary(DataAsIOList)), + ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:inflateInit(Z1)), - ?m(?BARG, zlib:inflateChunk(gurka, Compressed)), - ?m(?BARG, zlib:inflateChunk(Z1, 4384)), - ?m({'EXIT',{data_error,_}}, zlib:inflateEnd(Z1)), + + ?m(?EXIT(badarg), zlib:inflateChunk(gurka, Compressed)), + ?m(?EXIT(badarg), zlib:inflateChunk(Z1, 4384)), + + ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), + ?m(ok, zlib:close(Z1)). -%% Test inflateEnd. -api_inflateEnd(Config) when is_list(Config) -> +%% Test safeInflate as a mirror of inflateChunk, but ignore the stuff about +%% exact chunk sizes. +api_safeInflate(Config) when is_list(Config) -> + Data = << <<(I rem 150)>> || I <- lists:seq(1, 20 bsl 10) >>, + Compressed = zlib:compress(Data), Z1 = zlib:open(), - ?m({'EXIT',{einval,_}}, zlib:inflateEnd(Z1)), - ?m(ok, zlib:inflateInit(Z1)), - ?m(?BARG, zlib:inflateEnd(gurka)), - ?m({'EXIT',{data_error,_}}, zlib:inflateEnd(Z1)), - ?m({'EXIT',{einval,_}}, zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), - ?m(B when is_list(B), zlib:inflate(Z1, zlib:compress("abc"))), + + SafeInflateLoop = + fun + Loop({continue, Chunk}, Output) -> + Loop(zlib:safeInflate(Z1, []), [Output, Chunk]); + Loop({finished, Chunk}, Output) -> + [Output, Chunk] + end, + + Decompressed = SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []), + Data = iolist_to_binary(Decompressed), + ?m(ok, zlib:inflateEnd(Z1)), - ?m(ok, zlib:close(Z1)). + ?m(ok, zlib:inflateInit(Z1)), -%% Test getBufsz. -api_getBufsz(Config) when is_list(Config) -> - Z1 = zlib:open(), - ?m(Val when is_integer(Val), zlib:getBufSize(Z1)), - ?m(?BARG, zlib:getBufSize(gurka)), - ?m(ok, zlib:close(Z1)). + {continue, Partial} = zlib:safeInflate(Z1, Compressed), + PBin = iolist_to_binary(Partial), + PSize = byte_size(PBin), + <<PBin:PSize/binary, Rest/binary>> = Data, -%% Test setBufsz. -api_setBufsz(Config) when is_list(Config) -> - Z1 = zlib:open(), - ?m(?BARG, zlib:setBufSize(Z1, gurka)), - ?m(?BARG, zlib:setBufSize(gurka, 1232330)), - Sz = ?m( Val when is_integer(Val), zlib:getBufSize(Z1)), - ?m(ok, zlib:setBufSize(Z1, Sz*2)), - DSz = Sz*2, - ?m(DSz, zlib:getBufSize(Z1)), + ?m(ok, zlib:inflateReset(Z1)), + + {continue, Partial} = zlib:safeInflate(Z1, Compressed), + PBin = iolist_to_binary(Partial), + PSize = byte_size(PBin), + <<PBin:PSize/binary, Rest/binary>> = Data, + + ?m(ok, zlib:inflateReset(Z1)), + + SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []), + + ?m(?EXIT(data_error), zlib:safeInflate(Z1, Compressed)), + + ?m(ok, zlib:inflateReset(Z1)), + ?m(?EXIT(badarg), zlib:safeInflate(gurka, Compressed)), + ?m(?EXIT(badarg), zlib:safeInflate(Z1, 4384)), + ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), ?m(ok, zlib:close(Z1)). -%%% Debug function ?? -%% Test getQSize. -api_getQSize(Config) when is_list(Config) -> +%% Test inflateEnd. +api_inflateEnd(Config) when is_list(Config) -> Z1 = zlib:open(), - Q = ?m(Val when is_integer(Val), zlib:getQSize(Z1)), - io:format("QSize ~p ~n", [Q]), - ?m(?BARG, zlib:getQSize(gurka)), + ?m(?EXIT(not_initialized), zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), + ?m(?EXIT(badarg), zlib:inflateEnd(gurka)), + ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), + ?m(?EXIT(not_initialized), zlib:inflateEnd(Z1)), + ?m(ok, zlib:inflateInit(Z1)), + ?m(B when is_list(B), zlib:inflate(Z1, zlib:compress("abc"))), + ?m(ok, zlib:inflateEnd(Z1)), ?m(ok, zlib:close(Z1)). %% Test crc32. @@ -458,8 +509,8 @@ api_crc32(Config) when is_list(Config) -> Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)), Bin = <<1,1,1,1,1,1,1,1,1>>, - Compressed1 = ?m(_, zlib:deflate(Z1, Bin, none)), - Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)), + Compressed1 = ?m(L when is_list(L), zlib:deflate(Z1, Bin, none)), + Compressed2 = ?m(L when is_list(L), zlib:deflate(Z1, <<>>, finish)), Compressed = list_to_binary(Compressed1 ++ Compressed2), CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)), ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,Bin)), @@ -467,15 +518,15 @@ api_crc32(Config) when is_list(Config) -> ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,Compressed)), CRC2 = ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,0,Compressed)), ?m(CRC3 when CRC2 /= CRC3, zlib:crc32(Z1,234,Compressed)), - ?m(?BARG, zlib:crc32(gurka)), - ?m(?BARG, zlib:crc32(Z1, not_a_binary)), - ?m(?BARG, zlib:crc32(gurka, <<1,1,2,4,4>>)), - ?m(?BARG, zlib:crc32(Z1, 2298929, not_a_binary)), - ?m(?BARG, zlib:crc32(Z1, not_an_int, <<123,123,123,35,231>>)), - ?m(?BARG, zlib:crc32_combine(Z1, not_an_int, 123123, 123)), - ?m(?BARG, zlib:crc32_combine(Z1, noint, 123123, 123)), - ?m(?BARG, zlib:crc32_combine(Z1, 123123, noint, 123)), - ?m(?BARG, zlib:crc32_combine(Z1, 123123, 123, noint)), + ?m(?EXIT(badarg), zlib:crc32(gurka)), + ?m(?EXIT(badarg), zlib:crc32(Z1, not_a_binary)), + ?m(?EXIT(badarg), zlib:crc32(gurka, <<1,1,2,4,4>>)), + ?m(?EXIT(badarg), zlib:crc32(Z1, 2298929, not_a_binary)), + ?m(?EXIT(badarg), zlib:crc32(Z1, not_an_int, <<123,123,123,35,231>>)), + ?m(?EXIT(badarg), zlib:crc32_combine(Z1, not_an_int, 123123, 123)), + ?m(?EXIT(badarg), zlib:crc32_combine(Z1, noint, 123123, 123)), + ?m(?EXIT(badarg), zlib:crc32_combine(Z1, 123123, noint, 123)), + ?m(?EXIT(badarg), zlib:crc32_combine(Z1, 123123, 123, noint)), ?m(ok, zlib:deflateEnd(Z1)), ?m(ok, zlib:close(Z1)). @@ -484,74 +535,115 @@ api_adler32(Config) when is_list(Config) -> Z1 = zlib:open(), ?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)), Bin = <<1,1,1,1,1,1,1,1,1>>, - Compressed1 = ?m(_, zlib:deflate(Z1, Bin, none)), - Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)), + Compressed1 = ?m(L when is_list(L), zlib:deflate(Z1, Bin, none)), + Compressed2 = ?m(L when is_list(L), zlib:deflate(Z1, <<>>, finish)), Compressed = list_to_binary(Compressed1 ++ Compressed2), ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,Bin)), ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,binary_to_list(Bin))), ADLER2 = ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,Compressed)), ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,1,Compressed)), ?m(ADLER3 when ADLER2 /= ADLER3, zlib:adler32(Z1,234,Compressed)), - ?m(?BARG, zlib:adler32(Z1, not_a_binary)), - ?m(?BARG, zlib:adler32(gurka, <<1,1,2,4,4>>)), - ?m(?BARG, zlib:adler32(Z1, 2298929, not_a_binary)), - ?m(?BARG, zlib:adler32(Z1, not_an_int, <<123,123,123,35,231>>)), - ?m(?BARG, zlib:adler32_combine(Z1, noint, 123123, 123)), - ?m(?BARG, zlib:adler32_combine(Z1, 123123, noint, 123)), - ?m(?BARG, zlib:adler32_combine(Z1, 123123, 123, noint)), + ?m(?EXIT(badarg), zlib:adler32(Z1, not_a_binary)), + ?m(?EXIT(badarg), zlib:adler32(gurka, <<1,1,2,4,4>>)), + ?m(?EXIT(badarg), zlib:adler32(Z1, 2298929, not_a_binary)), + ?m(?EXIT(badarg), zlib:adler32(Z1, not_an_int, <<123,123,123,35,231>>)), + ?m(?EXIT(badarg), zlib:adler32_combine(Z1, noint, 123123, 123)), + ?m(?EXIT(badarg), zlib:adler32_combine(Z1, 123123, noint, 123)), + ?m(?EXIT(badarg), zlib:adler32_combine(Z1, 123123, 123, noint)), ?m(ok, zlib:deflateEnd(Z1)), ?m(ok, zlib:close(Z1)). %% Test compress. api_un_compress(Config) when is_list(Config) -> - ?m(?BARG,zlib:compress(not_a_binary)), + ?m(?EXIT(badarg),zlib:compress(not_a_binary)), Bin = <<1,11,1,23,45>>, Comp = zlib:compress(Bin), - ?m(?BARG,zlib:uncompress(not_a_binary)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<171,171,171,171,171>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3,0>>)), - ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<0,156,3,0,0,0,0,1>>)), + ?m(?EXIT(badarg),zlib:uncompress(not_a_binary)), + ?m(?EXIT(data_error), zlib:uncompress(<<171,171,171,171,171>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<120>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<120,156>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<120,156,3>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<120,156,3,0>>)), + ?m(?EXIT(data_error), zlib:uncompress(<<0,156,3,0,0,0,0,1>>)), ?m(Bin, zlib:uncompress(binary_to_list(Comp))), ?m(Bin, zlib:uncompress(Comp)). %% Test zip. api_un_zip(Config) when is_list(Config) -> - ?m(?BARG,zlib:zip(not_a_binary)), + ?m(?EXIT(badarg),zlib:zip(not_a_binary)), Bin = <<1,11,1,23,45>>, Comp = zlib:zip(Bin), ?m(Comp, zlib:zip(binary_to_list(Bin))), - ?m(?BARG,zlib:unzip(not_a_binary)), - ?m({'EXIT',{data_error,_}}, zlib:unzip(<<171,171,171,171,171>>)), - ?m({'EXIT',{data_error,_}}, zlib:unzip(<<>>)), + ?m(?EXIT(badarg),zlib:unzip(not_a_binary)), + ?m(?EXIT(data_error), zlib:unzip(<<171,171,171,171,171>>)), + ?m(?EXIT(data_error), zlib:unzip(<<>>)), ?m(Bin, zlib:unzip(Comp)), ?m(Bin, zlib:unzip(binary_to_list(Comp))), %% OTP-6396 - B = <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97,1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2,10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97,116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101,104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112,114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101,100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100,101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181,107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57,57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4,10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125,248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203,251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0,200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94,13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0,108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,106>>, + B = + <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97, + 1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2, + 10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97, + 116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113, + 107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197, + 31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73, + 64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10 + ,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97, + 112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4, + 103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101, + 104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112, + 114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101, + 100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100, + 100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101, + 102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100, + 101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100, + 100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100, + 101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181, + 107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100, + 0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102, + 105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97, + 16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11, + 97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97, + 11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7, + 214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57, + 57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4, + 10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105, + 110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125, + 248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203, + 251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0, + 200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94, + 13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120, + 5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198, + 118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0, + 108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104, + 12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64, + 104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0, + 33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101, + 114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99, + 50,52,48,4,103,112,114,115,8,0,106>>, + Z = zlib:zip(B), ?m(B, zlib:unzip(Z)). %% Test gunzip. api_g_un_zip(Config) when is_list(Config) -> - ?m(?BARG,zlib:gzip(not_a_binary)), + ?m(?EXIT(badarg),zlib:gzip(not_a_binary)), Bin = <<1,11,1,23,45>>, Comp = zlib:gzip(Bin), ?m(Comp, zlib:gzip(binary_to_list(Bin))), - ?m(?BARG, zlib:gunzip(not_a_binary)), - ?m(?DATA_ERROR, zlib:gunzip(<<171,171,171,171,171>>)), - ?m(?DATA_ERROR, zlib:gunzip(<<>>)), + ?m(?EXIT(badarg), zlib:gunzip(not_a_binary)), + ?m(?EXIT(data_error), zlib:gunzip(<<171,171,171,171,171>>)), + ?m(?EXIT(data_error), zlib:gunzip(<<>>)), ?m(Bin, zlib:gunzip(Comp)), ?m(Bin, zlib:gunzip(binary_to_list(Comp))), %% Bad CRC; bad length. BadCrc = bad_crc_data(), - ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadCrc))), + ?m(?EXIT(data_error),(catch zlib:gunzip(BadCrc))), BadLen = bad_len_data(), - ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadLen))), + ?m(?EXIT(data_error),(catch zlib:gunzip(BadLen))), ok. bad_crc_data() -> @@ -594,30 +686,15 @@ intro(Config) when is_list(Config) -> large_deflate(Config) when is_list(Config) -> large_deflate_do(). large_deflate_do() -> - Z = zlib:open(), - Plain = rand_bytes(zlib:getBufSize(Z)*5), - ok = zlib:deflateInit(Z), - _ZlibHeader = zlib:deflate(Z, [], full), - Deflated = zlib:deflate(Z, Plain, full), - ?m(ok, zlib:close(Z)), - ?m(Plain, zlib:unzip(list_to_binary([Deflated, 3, 0]))). - -rand_bytes(Sz) -> - L = <<8,2,3,6,1,2,3,2,3,4,8,7,3,7,2,3,4,7,5,8,9,3>>, - rand_bytes(erlang:md5(L),Sz). - -rand_bytes(Bin, Sz) when byte_size(Bin) >= Sz -> - <<Res:Sz/binary, _/binary>> = Bin, - Res; -rand_bytes(Bin, Sz) -> - rand_bytes(<<(erlang:md5(Bin))/binary, Bin/binary>>, Sz). - + Plain = gen_determ_rand_bytes(64 bsl 10), + Deflated = zlib:zip(Plain), + ?m(Plain, zlib:unzip(Deflated)). %% Test a standard compressed zip file. zip_usage(Config) when is_list(Config) -> zip_usage(zip_usage({get_arg,Config})); zip_usage({get_arg,Config}) -> - Out = conf(data_dir,Config), + Out = get_data_dir(Config), {ok,ZIP} = file:read_file(filename:join(Out,"zipdoc.zip")), {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), {run,ZIP,ORIG}; @@ -688,7 +765,7 @@ zip_usage({run,ZIP,ORIG}) -> gz_usage(Config) when is_list(Config) -> gz_usage(gz_usage({get_arg,Config})); gz_usage({get_arg,Config}) -> - Out = conf(data_dir,Config), + Out = get_data_dir(Config), {ok,GZIP} = file:read_file(filename:join(Out,"zipdoc.1.gz")), {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), {ok,GZIP2} = file:read_file(filename:join(Out,"zipdoc.txt.gz")), @@ -709,7 +786,7 @@ gz_usage2(Config) -> case os:find_executable("gzip") of Name when is_list(Name) -> Z = zlib:open(), - Out = conf(data_dir,Config), + Out = get_data_dir(Config), {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), Compressed = zlib:gzip(ORIG), GzOutFile = filename:join(Out,"out.gz"), @@ -737,7 +814,7 @@ gz_usage2(Config) -> compress_usage(Config) when is_list(Config) -> compress_usage(compress_usage({get_arg,Config})); compress_usage({get_arg,Config}) -> - Out = conf(data_dir,Config), + Out = get_data_dir(Config), {ok,C1} = file:read_file(filename:join(Out,"png-compressed.zlib")), {run,C1}; compress_usage({run,C1}) -> @@ -792,7 +869,7 @@ compress_usage({run,C1}) -> crc(Config) when is_list(Config) -> crc(crc({get_arg,Config})); crc({get_arg,Config}) -> - Out = conf(data_dir,Config), + Out = get_data_dir(Config), {ok,C1} = file:read_file(filename:join(Out,"zipdoc")), {run,C1}; crc({run,C1}) -> @@ -821,7 +898,7 @@ crc({run,C1}) -> adler(Config) when is_list(Config) -> adler(adler({get_arg,Config})); adler({get_arg,Config}) -> - Out = conf(data_dir,Config), + Out = get_data_dir(Config), File1 = filename:join(Out,"zipdoc"), {ok,C1} = file:read_file(File1), {run,C1}; @@ -869,10 +946,14 @@ dictionary_usage({run}) -> %% Now uncompress. Z2 = zlib:open(), ?m(ok, zlib:inflateInit(Z2)), - {'EXIT',{{need_dictionary,DictID},_}} = (catch zlib:inflate(Z2, Compressed)), + + ?m(?EXIT({need_dictionary, DictID}), zlib:inflate(Z2, Compressed)), + ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), ?m(ok, zlib:inflateSetDictionary(Z2, binary_to_list(Dict))), + Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])), + ?m(ok, zlib:inflateEnd(Z2)), ?m(ok, zlib:close(Z2)), ?m(Data, list_to_binary(Uncompressed)). @@ -882,33 +963,64 @@ split_bin(<<Part:1997/binary,Rest/binary>>, Acc) -> split_bin(Last,Acc) -> lists:reverse([Last|Acc]). +only_allow_owner(Config) when is_list(Config) -> + Z = zlib:open(), -%% Check concurrent access to zlib driver. -smp(Config) -> - case erlang:system_info(smp_support) of - true -> - NumOfProcs = lists:min([8,erlang:system_info(schedulers)]), - io:format("smp starting ~p workers\n",[NumOfProcs]), + ?m(ok, zlib:inflateInit(Z)), + ?m(ok, zlib:inflateReset(Z)), - %% Tests to run in parallel. - Funcs = [zip_usage, gz_usage, compress_usage, dictionary_usage, - crc, adler], + {Pid, Ref} = spawn_monitor( + fun() -> + ?m(?EXIT(not_on_controlling_process), zlib:inflateReset(Z)) + end), - %% We get all function arguments here to avoid repeated parallel - %% file read access. - FnAList = lists:map(fun(F) -> {F,?MODULE:F({get_arg,Config})} - end, Funcs), + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ok + after 200 -> + ct:fail("Spawned worker timed out.") + end, - Pids = [spawn_link(?MODULE, worker, [rand:uniform(9999), - list_to_tuple(FnAList), - self()]) - || _ <- lists:seq(1,NumOfProcs)], - wait_pids(Pids); + ?m(ok, zlib:inflateReset(Z)). - false -> - {skipped,"No smp support"} - end. +sub_heap_binaries(Config) when is_list(Config) -> + Compressed = zlib:compress(<<"gurka">>), + ConfLen = erlang:length(Config), + + HeapBin = <<ConfLen:8/integer, Compressed/binary>>, + <<_:8/integer, SubHeapBin/binary>> = HeapBin, + + ?m(<<"gurka">>, zlib:uncompress(SubHeapBin)), + ok. +%% Check concurrent access to zlib driver. +smp(Config) -> + case erlang:system_info(smp_support) of + true -> + NumOfProcs = lists:min([8,erlang:system_info(schedulers)]), + io:format("smp starting ~p workers\n",[NumOfProcs]), + + %% Tests to run in parallel. + Funcs = + [zip_usage, gz_usage, compress_usage, dictionary_usage, + crc, adler], + + %% We get all function arguments here to avoid repeated parallel + %% file read access. + UsageArgs = + list_to_tuple([{F, ?MODULE:F({get_arg,Config})} || F <- Funcs]), + Parent = self(), + + WorkerFun = + fun() -> + worker(rand:uniform(9999), UsageArgs, Parent) + end, + + Pids = [spawn_link(WorkerFun) || _ <- lists:seq(1, NumOfProcs)], + wait_pids(Pids); + false -> + {skipped,"No smp support"} + end. worker(Seed, FnATpl, Parent) -> io:format("smp worker ~p, seed=~p~n",[self(),Seed]), @@ -999,43 +1111,98 @@ otp_9981(Config) when is_list(Config) -> Ports = lists:sort(erlang:ports()), ok. +-define(BENCH_SIZE, (16 bsl 20)). + +-define(DECOMPRESS_BENCH(Name, What, Data), + Name(Config) when is_list(Config) -> + Uncompressed = Data, + Compressed = zlib:compress(Uncompressed), + What(Compressed, byte_size(Uncompressed))). + +-define(COMPRESS_BENCH(Name, What, Data), + Name(Config) when is_list(Config) -> + Compressed = Data, + What(Compressed, byte_size(Compressed))). + +?DECOMPRESS_BENCH(inflate_bench_zeroed, throughput_bench_inflate, + <<0:(8 * ?BENCH_SIZE)>>). +?DECOMPRESS_BENCH(inflate_bench_rand, throughput_bench_inflate, + gen_determ_rand_bytes(?BENCH_SIZE)). + +?DECOMPRESS_BENCH(chunk_bench_zeroed, throughput_bench_chunk, + <<0:(8 * ?BENCH_SIZE)>>). +?DECOMPRESS_BENCH(chunk_bench_rand, throughput_bench_chunk, + gen_determ_rand_bytes(?BENCH_SIZE)). +?COMPRESS_BENCH(deflate_bench_zeroed, throughput_bench_deflate, + <<0:(8 * ?BENCH_SIZE)>>). +?COMPRESS_BENCH(deflate_bench_rand, throughput_bench_deflate, + gen_determ_rand_bytes(?BENCH_SIZE)). + +throughput_bench_inflate(Compressed, Size) -> + Z = zlib:open(), + zlib:inflateInit(Z), + + submit_throughput_results(Size, + fun() -> + zlib:inflate(Z, Compressed) + end). + +throughput_bench_deflate(Uncompressed, Size) -> + Z = zlib:open(), + zlib:deflateInit(Z), + + submit_throughput_results(Size, + fun() -> + zlib:deflate(Z, Uncompressed, finish) + end). + +throughput_bench_chunk(Compressed, Size) -> + Z = zlib:open(), + zlib:inflateInit(Z), + + ChunkLoop = + fun + Loop({more, _}) -> Loop(zlib:inflateChunk(Z)); + Loop(_) -> ok + end, + + submit_throughput_results(Size, + fun() -> + ChunkLoop(zlib:inflateChunk(Z, Compressed)) + end). + +submit_throughput_results(Size, Fun) -> + TimeTaken = measure_perf_counter(Fun, millisecond), + + KBPS = trunc((Size bsr 10) / (TimeTaken / 1000)), + ct_event:notify(#event{ name = benchmark_data, data = [{value,KBPS}] }), + {comment, io_lib:format("~p ms, ~p KBPS", [TimeTaken, KBPS])}. + +measure_perf_counter(Fun, Unit) -> + Start = os:perf_counter(Unit), + Fun(), + os:perf_counter(Unit) - Start. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Helps with testing directly %%%%%%%%%%%%% -conf(What,Config) -> - try proplists:get_value(What,Config) of - undefined -> - "./zlib_SUITE_data"; - Dir -> - Dir +get_data_dir(Config) -> + try proplists:get_value(data_dir,Config) of + undefined -> + "./zlib_SUITE_data"; + Dir -> + Dir catch - _:_ -> "./zlib_SUITE_data" + _:_ -> "./zlib_SUITE_data" end. -t() -> t([all]). - -t(What) when not is_list(What) -> - t([What]); -t(What) -> - lists:foreach(fun(T) -> - try ?MODULE:T([]) - catch _E:_R -> - Line = get(test_server_loc), - io:format("Failed ~p:~p ~p ~p ~p~n", - [T,Line,_E,_R, erlang:get_stacktrace()]) - end - end, expand(What)). - -expand(All) -> - lists:reverse(expand(All,[])). -expand([H|T], Acc) -> - case ?MODULE:H(suite) of - [] -> expand(T,[H|Acc]); - Cs -> - R = expand(Cs, Acc), - expand(T, R) - end; -expand([], Acc) -> Acc. - +%% Generates a bunch of statistically random bytes using the size as seed. +gen_determ_rand_bytes(Size) -> + gen_determ_rand_bytes(Size, erlang:md5_init(), <<>>). +gen_determ_rand_bytes(Size, _Context, Acc) when Size =< 0 -> + Acc; +gen_determ_rand_bytes(Size, Context0, Acc) when Size > 0 -> + Context = erlang:md5_update(Context0, <<Size/integer>>), + Checksum = erlang:md5_final(Context), + gen_determ_rand_bytes(Size - 16, Context, <<Acc/binary, Checksum/binary>>). diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 4edecd8969..c9463241d1 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.3 +KERNEL_VSN = 5.3.1 |